def __init__(self): # 1 mm is probably about right. # TODO: force this to be recalculated when the StlReader updates self.WidgetSize = 1 self.SurfaceMapper = vtkPolyDataMapper() self.SurfaceActor = vtkActor() self.SurfaceActor.SetMapper(self.SurfaceMapper) # self.seeder = SeedPlacer(self, self.stlActor) self.Locator = vtkModifiedBSPTree() self.SurfacePlacer = vtkPolygonalSurfacePointPlacer() self.SurfacePlacer.AddProp(self.SurfaceActor) self.Renderer = vtkRenderer() self.Renderer.AddActor(self.SurfaceActor) self.CreateMarker() self.PlacedSeed = PlacedSeed(self) self.PlacedSeed.AddObserver('Enabled', self.HandlePlacedItemEnabledChange) self.PlacedIolets = PlacedIoletList() self.PlacedIolets.SetItemEnabledChangeHandler(self.HandlePlacedItemEnabledChange) return
def create_bstree(self, polydata=None): tree = vtk.vtkModifiedBSPTree() tree.SetDataSet(polydata) tree.BuildLocator() # print('vtkModifiedBSPTree = \n', tree) return tree
def __init__(self): # 1 mm is probably about right. # TODO: force this to be recalculated when the StlReader updates self.WidgetSize = 1 self.SurfaceMapper = vtkPolyDataMapper() self.SurfaceActor = vtkActor() self.SurfaceActor.SetMapper(self.SurfaceMapper) # self.seeder = SeedPlacer(self, self.stlActor) self.Locator = vtkModifiedBSPTree() self.SurfacePlacer = vtkPolygonalSurfacePointPlacer() self.SurfacePlacer.AddProp(self.SurfaceActor) self.Renderer = vtkRenderer() self.Renderer.AddActor(self.SurfaceActor) self.CreateMarker() self.PlacedSeed = PlacedSeed(self) self.PlacedSeed.AddObserver('Enabled', self.HandlePlacedItemEnabledChange) self.AddObserver('WidgetSize', self.PlacedSeed.HandleWidgetSizeChange) self.PlacedIolets = PlacedIoletList() self.PlacedIolets.SetItemEnabledChangeHandler( self.HandlePlacedItemEnabledChange) return
def __init__(self, pd, val, alpha=0): self.loc = vtk.vtkCellLocator() self.loc = vtk.vtkModifiedBSPTree() arr_crd_2d = pd.GetPointData().GetArray('2Dcrds') pts = vtk.vtkPoints() for kp in range(pd.GetNumberOfPoints()): p = pd.GetPoint(kp) crd_2D = arr_crd_2d.GetTuple(kp) pts.InsertNextPoint(crd_2D[0], crd_2D[1], 0) pd.SetPoints(pts) del2d = vtk.vtkDelaunay2D() del2d.SetInputData(pd) del2d.SetTolerance(0) if alpha > 0: del2d.SetAlpha(alpha) del2d.Update() self.pd2 = del2d.GetOutput() ## w = vtk.vtkXMLPolyDataWriter() ## w.SetFileName('del.vtp') ## w.SetInputData(self.pd2) ## w.Write() ## sys.exit(0) self.loc.SetDataSet(self.pd2) self.loc.BuildLocator() self.values = val
def createCellLocator(a_FileName, a_LocatorType=None, a_Legacy='vtp'): if a_FileName.endswith('vtu'): reader = vtk.vtkXMLUnstructuredGridReader() elif a_FileName.endswith('vtp'): reader = vtk.vtkXMLPolyDataReader() elif a_FileName.endswith('.vtk'): if a_Legacy == 'none': print("Need To Specify Data Type For Legacy Files") sys.exit() elif a_Legacy == 'vtu': reader = vtk.vtkUnstructuredGridReader() elif a_Legacy == 'vtp': reader = vtk.vtkPolyDataReader() else: print("Unsupported File Extension") sys.exit() reader.SetFileName(a_FileName) reader.Update() if a_LocatorType is None: locator = vtk.vtkCellTreeLocator() else: if a_LocatorType == 'oct': locator = vtk.vtkCellLocator() elif a_LocatorType == 'tre': locator = vtk.vtkCellTreeLocator() elif a_LocatorType == 'bsp': locator = vtk.vtkModifiedBSPTree() locator.SetDataSet(reader.GetOutput()) locator.BuildLocator() return locator
def vtk_raycasting_bsptree(): """Testing out raycasting inside of VTK using vtkModifiedBSPTree """ radius = 0.01 # read and turn OBJ to polydata polydata = wavefront.read_obj_to_polydata('./data/shape_model/ITOKAWA/itokawa_high.obj') renderer = vtk.vtkRenderer() pSource = np.array([1, 0, 0]) pTarget = np.array([0.00372, -0.0609, -0.0609]) # oriented bounding box for the polydata bspTree = vtk.vtkModifiedBSPTree() bspTree.SetDataSet(polydata) bspTree.BuildLocator() pointsVTKintersection = vtk.vtkPoints() code = bspTree.IntersectWithLine(pSource, pTarget, 1e-9, pointsVTKintersection, None) if code: points_int = numpy_support.vtk_to_numpy(pointsVTKintersection.GetData()) for p in points_int: graphics.vtk_addPoint(renderer, p , color=[0, 0, 1], radius=radius) print('{} intersections'.format(points_int.shape[0])) graphics.vtk_addPoly(renderer, polydata) graphics.vtk_addPoint(renderer, pSource, color=[0, 1.0, 0], radius=radius) graphics.vtk_addPoint(renderer, pTarget, color=[1.0, 0, 0], radius=radius) graphics.vtk_addLine(renderer, pSource, pTarget) graphics.vtk_show(renderer)
def __initCaster(self): """Initialize a raycaster Internal method that just creates a vtkOBBTree object and setup """ if self.flag == 'bsp': self.caster = vtk.vtkModifiedBSPTree() elif self.flag == 'obb': self.caster = vtk.vtkOBBTree() # set the object polydata as the dataset self.caster.SetDataSet(self.polydata) self.caster.BuildLocator()
def __init__(self, pd, val, loc_syst, orig): self.loc = vtk.vtkCellLocator() self.loc = vtk.vtkModifiedBSPTree() self.pd2 = vtk.vtkPolyData() self.pd2.DeepCopy(pd) pts = vtk.vtkPoints() for kp in range(pd.GetNumberOfPoints()): p = pd.GetPoint(kp) crd_2D = project_on_plane(loc_syst, orig, p) pts.InsertNextPoint(crd_2D[0], crd_2D[1], 0) self.pd2.SetPoints(pts) self.loc.SetDataSet(self.pd2) self.loc.BuildLocator() self.values = val
def SetAnatomy( self, role, node ): if ( role == "Target" and node.GetPolyData() != None ): self.targetNode = node self.bspTree = vtk.vtkModifiedBSPTree() self.bspTree.SetDataSet( self.targetNode.GetPolyData() ) self.bspTree.BuildLocator() return True if ( role == "Image" ): imageData = node.GetImageData() if ( imageData is None ): return False imageDimensions = [ 0, 0, 0 ] imageData.GetDimensions( imageDimensions ) self.imageMaxX = imageDimensions[ 0 ] self.imageMaxY = imageDimensions[ 1 ] return True return False
def create_vtk_locator(self, use_only_active=True, scaling=False, **kwargs): """Creates locator and mapping dictionary. Returns ------- grid : `pyvista.core.pointset.UnstructuredGrid` object """ _ = kwargs grid_params = {'use_only_active': use_only_active, 'cell_size': None, 'scaling': scaling} if self._vtk_grid is None or self._vtk_grid_params != grid_params: self.create_vtk_grid(**grid_params) geo_filter = vtk.vtkGeometryFilter() geo_filter.SetInputData(self._vtk_grid) geo_filter.Update() polydata = geo_filter.GetOutput() locator = vtk.vtkModifiedBSPTree() locator.LazyEvaluationOff() locator.SetDataSet(polydata) locator.AutomaticOn() locator.BuildLocator() self._vtk_locator = locator
def camera_view(pd, height, resolution, trueLength, isPlotted, plantType="basil"): # Simulate the nadir camera view and retrieve the coordinates of the viewed points. # Based on plot_plant (the plotting part is removed and the ray tracing part is added) nods = np.array([np.array(s) for s in pd.getNodes()]) leafLines = pd.getPolylines(4) if plantType == "arabidopsis": rosetteLines = pd.getPolylines( 3 ) # If the arabidopsis is generated, we need the stem lines because one subType # of stem is a trick to create more leaves organs = pd.getOrgans( 3 ) # Create a list of organs of the same size of rosetteLines, used to retrieve subType if isinstance(pd, pb.RootSystem): pd = segs_to_polydata(pd, 1.) if isinstance(pd, pb.SegmentAnalyser): pd = segs_to_polydata(pd, 1.) if isinstance(pd, pb.Plant): pd = segs_to_polydata(pd, 1.) pd.GetPointData().SetActiveScalars("radius") # for the the filter tubeFilter = vtk.vtkTubeFilter() tubeFilter.SetInputData(pd) tubeFilter.SetNumberOfSides(9) tubeFilter.SetVaryRadiusToVaryRadiusByAbsoluteScalar() tubeFilter.SetCapping(True) tubeFilter.Update() stemModel = tubeFilter.GetOutput() # leaves = create_leaf(leafLines) leaves = create_leaves(leafLines) appendFilter = vtk.vtkAppendPolyData( ) # So we can merge the roots, the stems and the leaves together appendFilter.AddInputData(leaves) appendFilter.AddInputData(stemModel) if plantType == "arabidopsis": rosette = create_rosette(rosetteLines, organs) appendFilter.AddInputData(rosette) appendFilter.Update() plantWithLeaves = appendFilter.GetOutput() bsp = vtk.vtkModifiedBSPTree() bsp.SetDataSet(plantWithLeaves) bsp.BuildLocator() rays = get_rays(resolution[0], resolution[1], height, trueLength) position = [] for i in range(len(rays)): if i % 100 == 0: print(str(i)) bestID, bestT, bestX, ok = intersection(bsp, [[0, 0, height], rays[i]]) if ok == True: position.append(bestX) rays = np.array(rays) position.append([0, 0, height]) position = np.array(position) nods = np.append(nods, np.zeros((len(nods), 1)), axis=1) position = np.append(position, np.ones((len(position), 1)), axis=1) final = np.append(position, nods, axis=0) # Just a part of the code used for checking result (probably useless now) if isPlotted: x = position[:, 0] y = position[:, 1] z = position[:, 2] subfig = go.Scatter3d( x=final[:, 0], y=final[:, 1], z=final[:, 2], # x=position[:200000, 0], # y=position[:200000, 1], # z=position[:200000, 2], mode='markers', marker=dict( size=2, color= final[:, 3], # nodes_cor.T[1] is organ type, nodes_cor.T[2] is the connection number of a node colorscale='Viridis', opacity=0.8)) fig = make_subplots(rows=1, cols=1, specs=[[{'type': 'surface'}]]) fig.add_trace(subfig) fig.update_layout(scene_aspectmode='data', ) fig.show() return position[:, :-1]
def __init__(self, mesh, tolerance=.001): self.bspTree = vtk.vtkModifiedBSPTree() self.bspTree.SetDataSet(mesh) self.bspTree.BuildLocator() self.tolerance = tolerance
def ray_cast_color_thickness(polydata, hit_point_list, ray_direction, dimensions, update_status, gradient_scale_factor=10.0): # configure ray direction castIndex = BoneThicknessMappingLogic.determine_cast_direction_index( ray_direction) update_status(text="Building intersection object tree...", progress=81) bspTree = vtk.vtkModifiedBSPTree() bspTree.SetDataSet(polydata) bspTree.BuildLocator() total = len(hit_point_list) update_status(text="Calculating thickness (may take long)...", progress=82) startTime = time.time() skullThicknessScalarArray = vtk.vtkUnsignedCharArray() skullThicknessScalarArray.SetName(BoneThicknessMappingType.THICKNESS) airCellScalarArray = vtk.vtkUnsignedCharArray() airCellScalarArray.SetName(BoneThicknessMappingType.AIR_CELL) def calculate_distance(point1, point2): d = numpy.linalg.norm( numpy.array((point1[0], point1[1], point1[2])) - numpy.array((point2[0], point2[1], point2[2]))) d = d * gradient_scale_factor return d def interpret_points(points_of_intersection, mode): if mode is BoneThicknessMappingType.THICKNESS: return calculate_distance( points_of_intersection.GetPoint(0), points_of_intersection.GetPoint( points_of_intersection.GetNumberOfPoints() - 1)) elif mode is BoneThicknessMappingType.AIR_CELL: return calculate_distance(points_of_intersection.GetPoint(0), points_of_intersection.GetPoint(1)) pointsOfIntersection, cellsOfIntersection = vtk.vtkPoints( ), vtk.vtkIdList() for i, hitPoint in enumerate(hit_point_list): stretchFactor = dimensions[castIndex] start = [ hitPoint.point[0] + hitPoint.normal[0] * stretchFactor, hitPoint.point[1] + hitPoint.normal[1] * stretchFactor, hitPoint.point[2] + hitPoint.normal[2] * stretchFactor ] end = [ hitPoint.point[0] - hitPoint.normal[0] * stretchFactor, hitPoint.point[1] - hitPoint.normal[1] * stretchFactor, hitPoint.point[2] - hitPoint.normal[2] * stretchFactor ] bspTree.IntersectWithLine(start, end, 0, pointsOfIntersection, cellsOfIntersection) if pointsOfIntersection.GetNumberOfPoints() < 2: continue skullThicknessScalarArray.InsertTuple1( hitPoint.pid, interpret_points(pointsOfIntersection, BoneThicknessMappingType.THICKNESS)) airCellScalarArray.InsertTuple1( hitPoint.pid, interpret_points(pointsOfIntersection, BoneThicknessMappingType.AIR_CELL)) # update rays casted status if i % 500 == 0: update_status( text="Calculating thickness (~" + str(i) + ' rays)', progress=82 + int(round((i * 1.0 / total * 1.0) * 18.0))) update_status(text="Finished thickness calculation in " + str("%.1f" % (time.time() - startTime)) + "s...", progress=100) return skullThicknessScalarArray, airCellScalarArray
def rainfall_quad_cast(polydata, dimensions, ray_direction, precision, region_of_interest, update_status): # configure ray direction dimensions = dimensions[::-1] negated = 1 if ray_direction in [ RayDirection.R, RayDirection.A, RayDirection.S ] else -1 castIndex = None if ray_direction is RayDirection.R or ray_direction is RayDirection.L: castIndex = 0 elif ray_direction is RayDirection.A or ray_direction is RayDirection.P: castIndex = 1 elif ray_direction is RayDirection.S or ray_direction is RayDirection.I: castIndex = 2 castVector = [0.0, 0.0, 0.0] castVector[castIndex] = 1.0 * negated castPlaneIndices = [0, 1, 2] castPlaneIndices.remove(castIndex) preciseHorizontalBounds, preciseVerticalBounds = int( float(dimensions[castPlaneIndices[0]]) / float(precision)), int( float(dimensions[castPlaneIndices[1]]) / float(precision)) def build_ray(i, j): start = [None, None, None] start[castIndex] = dimensions[castIndex] * negated start[castPlaneIndices[ 0]] = -dimensions[castPlaneIndices[0]] / 2.0 + i * precision start[castPlaneIndices[ 1]] = -dimensions[castPlaneIndices[1]] / 2.0 + j * precision end = start[:] end[castIndex] = end[castIndex] * -1.0 return start, end # build search tree update_status(text="Building intersection object tree...", progress=41) bspTree = vtk.vtkModifiedBSPTree() bspTree.SetDataSet(polydata) bspTree.BuildLocator() # cast rays update_status(text="Casting " + str(preciseHorizontalBounds * preciseVerticalBounds) + " rays downward...", progress=42) startTime = time.time() points, temporaryHitPoint = vtk.vtkPoints(), [0.0, 0.0, 0.0] hitPointMatrix = [[None for i in xrange(preciseHorizontalBounds)] for j in reversed(xrange(preciseVerticalBounds))] for i in reversed(xrange(preciseVerticalBounds)): for j in xrange(preciseHorizontalBounds): start, end = build_ray(i, j) res = bspTree.IntersectWithLine(start, end, 0, vtk.reference(0), temporaryHitPoint, [0.0, 0.0, 0.0], vtk.reference(0), vtk.reference(0)) if res != 0 and region_of_interest[0] <= temporaryHitPoint[ castIndex] < region_of_interest[1]: temporaryHitPoint[ castIndex] += 0.3 * negated # raised to improve visibility hitPointMatrix[i][j] = HitPoint( points.InsertNextPoint(temporaryHitPoint), temporaryHitPoint[:]) # form cells update_status(text="Forming top layer polygons", progress=64) cells = vtk.vtkCellArray() for i in xrange(len(hitPointMatrix) - 1): for j in xrange(len(hitPointMatrix[i]) - 1): hitPoints = [ hitPointMatrix[i][j], hitPointMatrix[i + 1][j], hitPointMatrix[i + 1][j + 1], hitPointMatrix[i][j + 1] ] if None in hitPoints: continue rawNormal = numpy.linalg.solve( numpy.array([ hitPoints[0].point, hitPoints[1].point, hitPoints[2].point ]), [1, 1, 1]) hitPointMatrix[i][j].normal = rawNormal / numpy.sqrt( numpy.sum(rawNormal**2)) v1, v2 = numpy.array( hitPointMatrix[i][j].normal), numpy.array(castVector) degrees = numpy.degrees( numpy.math.atan2(len(numpy.cross(v1, v2)), numpy.dot(v1, v2))) if degrees < 80: cells.InsertNextCell(4, [p.pid for p in hitPoints]) update_status(text="Finished ray-casting in " + str("%.1f" % (time.time() - startTime)) + "s, found " + str(cells.GetNumberOfCells()) + " cells...", progress=80) # build polydata topLayerPolyData = vtk.vtkPolyData() topLayerPolyData.SetPoints(points) topLayerPolyData.SetPolys(cells) topLayerPolyData.Modified() return topLayerPolyData, [ p for d0 in hitPointMatrix for p in d0 if p is not None ]
output = pl3d.GetOutput().GetBlock(0) ps = vtk.vtkPlaneSource() ps.SetXResolution(4) ps.SetYResolution(4) ps.SetOrigin(2, -2, 26) ps.SetPoint1(2, 2, 26) ps.SetPoint2(2, -2, 32) psMapper = vtk.vtkPolyDataMapper() psMapper.SetInputConnection(ps.GetOutputPort()) psActor = vtk.vtkActor() psActor.SetMapper(psMapper) psActor.GetProperty().SetRepresentationToWireframe() # Use the vtkModifiedBSPTree rk4 = vtk.vtkRungeKutta4() bspLoc = vtk.vtkModifiedBSPTree() ivp = vtk.vtkCellLocatorInterpolatedVelocityField() ivp.SetCellLocatorPrototype(bspLoc) streamer = vtk.vtkStreamTracer() streamer.SetInputData(output) streamer.SetSourceData(ps.GetOutput()) streamer.SetMaximumPropagation(100) streamer.SetInitialIntegrationStep(.2) streamer.SetIntegrationDirectionToForward() streamer.SetComputeVorticity(1) streamer.SetIntegrator(rk4) streamer.SetInterpolatorPrototype(ivp) rf = vtk.vtkRibbonFilter() rf.SetInputConnection(streamer.GetOutputPort()) rf.SetInputArrayToProcess(1, 0, 0, vtk.vtkDataObject.FIELD_ASSOCIATION_POINTS,
def rainfall_quad_cast(poly_data, seg_bounds, cast_axis, precision, region_of_interest, update_status): update_status(text="Building intersection object tree...", progress=41) bspTree = vtk.vtkModifiedBSPTree() bspTree.SetDataSet(poly_data) bspTree.BuildLocator() update_status(text="Calculating segmentation dimensions...", progress=42) negated = 1 if cast_axis in [ ctk.ctkAxesWidget.Right, ctk.ctkAxesWidget.Anterior, ctk.ctkAxesWidget.Superior ] else -1 castIndex = BoneThicknessMappingLogic.determine_cast_axis_index( cast_axis) castVector = [0.0, 0.0, 0.0] castVector[castIndex] = 1.0 * negated castPlaneIndices = [0, 1, 2] castPlaneIndices.remove(castIndex) update_status(text="Calculating segmentation cast-plane...", progress=43) depthIncrements = [seg_bounds[castIndex], seg_bounds[castIndex + 1]] if cast_axis in [ ctk.ctkAxesWidget.Right, ctk.ctkAxesWidget.Posterior, ctk.ctkAxesWidget.Superior ]: depthIncrements.reverse() horizontalIncrements = [ seg_bounds[castPlaneIndices[0] * 2], seg_bounds[castPlaneIndices[0] * 2 + 1] ] verticalIncrements = [ seg_bounds[castPlaneIndices[1] * 2], seg_bounds[castPlaneIndices[1] * 2 + 1] ] castPlaneIncrements = [ int( abs(horizontalIncrements[0] - horizontalIncrements[1]) / precision), int( abs(verticalIncrements[0] - verticalIncrements[1]) / precision), ] def build_ray(i, j): start = [None, None, None] start[castIndex] = depthIncrements[0] + negated * 100 start[ castPlaneIndices[0]] = horizontalIncrements[0] + i * precision start[castPlaneIndices[1]] = verticalIncrements[0] + j * precision end = start[:] end[castIndex] = depthIncrements[1] - negated * 100 return start, end # cast rays update_status( text="Casting " + str(int(castPlaneIncrements[0] * castPlaneIncrements[1])) + " rays...", progress=44) startTime = time.time() points, temporaryHitPoint = vtk.vtkPoints(), [0.0, 0.0, 0.0] hitPointMatrix = [[None for j in range(castPlaneIncrements[1])] for i in range(castPlaneIncrements[0])] for i in range(len(hitPointMatrix)): for j in range(len(hitPointMatrix[i])): start, end = build_ray(i, j) res = bspTree.IntersectWithLine(start, end, 0, vtk.reference(0), temporaryHitPoint, [0.0, 0.0, 0.0], vtk.reference(0), vtk.reference(0)) # if hit is found, and the top hitpoint is within ROI bounds if res != 0 and region_of_interest[0] <= temporaryHitPoint[ castIndex] < region_of_interest[1]: temporaryHitPoint[ castIndex] += 0.3 * negated # raised to improve visibility hitPointMatrix[i][j] = HitPoint( points.InsertNextPoint(temporaryHitPoint), temporaryHitPoint[:]) # form quads/cells update_status(text="Forming top layer polygons", progress=64) cells = vtk.vtkCellArray() for i in range(len(hitPointMatrix) - 1): # -1 as the end row/col will be taken into account for j in range(len(hitPointMatrix[i]) - 1): hitPoints = [ hitPointMatrix[i][j], hitPointMatrix[i + 1][j], hitPointMatrix[i + 1][j + 1], hitPointMatrix[i][j + 1] ] # check if full quad if None in hitPoints: continue # check if area is not extremely large d1 = numpy.linalg.norm( numpy.array(hitPoints[0].point) - numpy.array(hitPoints[1].point)) d2 = numpy.linalg.norm( numpy.array(hitPoints[0].point) - numpy.array(hitPoints[2].point)) d3 = numpy.linalg.norm( numpy.array(hitPoints[0].point) - numpy.array(hitPoints[3].point)) m = precision * 6 if d1 > m or d2 > m or d3 > m: continue # calculate normals rawNormal = numpy.linalg.solve( numpy.array([ hitPoints[0].point, hitPoints[1].point, hitPoints[2].point ]), [1, 1, 1]) hitPointMatrix[i][j].normal = rawNormal / numpy.sqrt( numpy.sum(rawNormal**2)) # # check if quad is acceptable by normal vs. cast vector # v1, v2 = numpy.array(hitPointMatrix[i][j].normal), numpy.array(castVector) # degrees = numpy.degrees(numpy.math.atan2(numpy.cross(v1, v2).shape[0], numpy.dot(v1, v2))) cells.InsertNextCell(4, [p.pid for p in hitPoints]) update_status(text="Finished ray-casting in " + str("%.1f" % (time.time() - startTime)) + "s, found " + str(cells.GetNumberOfCells()) + " cells...", progress=80) # build poly data topLayerPolyData = vtk.vtkPolyData() topLayerPolyData.SetPoints(points) topLayerPolyData.SetPolys(cells) topLayerPolyData.Modified() return topLayerPolyData, [ p for d0 in hitPointMatrix for p in d0 if p is not None ]
opTime = timer.GetElapsedTime() print(" Find cell probing: {0}".format(opTime)) # Time the deletion of the locator. The incremental locator is quite slow due # to fragmented memory. timer.StartTimer() del locator1 timer.StopTimer() time2 = timer.GetElapsedTime() print(" Delete Cell Tree Locator: {0}".format(time2)) print(" Cell Tree Locator (Total): {0}".format(time+opTime+time2)) print("\n") ############################################################# # Time the creation and building of the bsp tree locator3 = vtk.vtkModifiedBSPTree() locator3.LazyEvaluationOff() locator3.SetDataSet(output) locator3.AutomaticOn() timer.StartTimer() locator3.BuildLocator() timer.StopTimer() time = timer.GetElapsedTime() print("Build BSP Tree Locator: {0}".format(time)) # Probe the dataset with FindClosestPoint() and time it timer.StartTimer() for i in range (0,numProbes): bspClosest.SetId(i, locator3.FindCell(ProbeCells.GetPoint(i),0.001,genCell,pc,weights)) timer.StopTimer()
opTime = timer.GetElapsedTime() print(" Find cell probing: {0}".format(opTime)) # Time the deletion of the locator. The incremental locator is quite slow due # to fragmented memory. timer.StartTimer() del locator1 timer.StopTimer() time2 = timer.GetElapsedTime() print(" Delete Cell Tree Locator: {0}".format(time2)) print(" Cell Tree Locator (Total): {0}".format(time + opTime + time2)) print("\n") ############################################################# # Time the creation and building of the bsp tree locator3 = vtk.vtkModifiedBSPTree() locator3.LazyEvaluationOff() locator3.SetDataSet(output) locator3.AutomaticOn() timer.StartTimer() locator3.BuildLocator() timer.StopTimer() time = timer.GetElapsedTime() print("Build BSP Tree Locator: {0}".format(time)) # Probe the dataset with FindClosestPoint() and time it timer.StartTimer() for i in range(0, numProbes): bspClosest.SetId( i,
def Execute(args): print("evaluate centerlines") reader_ctr = vmtkscripts.vmtkSurfaceReader() reader_ctr.InputFileName = args.centerlines reader_ctr.Execute() print(args.clean_ctr) if(args.clean_ctr): cleaner = vtk.vtkCleanPolyData() cleaner.PointMergingOn() cleaner.SetInputData(reader_ctr.Surface) cleaner.Update() centerlines = cleaner.GetOutput() else: centerlines = reader_ctr.Surface centerlines.BuildLinks() centerlines.BuildCells() # calculate length for each segment # seems to be some error in prevous calculation for i in range(centerlines.GetNumberOfCells()): cell = centerlines.GetCell(i) length_ = 0.0 prevPoint = cell.GetPoints().GetPoint(0) for j in range(cell.GetNumberOfPoints()): point = cell.GetPoints().GetPoint(j) length_ += vtk.vtkMath.Distance2BetweenPoints(prevPoint,point)**0.5 prevPoint = point centerlines.GetCellData().GetArray("length").SetTuple(i, [length_]) #writer2 = vmtkscripts.vmtkSurfaceWriter() #writer2.OutputFileName = "centerlines_test.vtp" #writer2.Input = centerlines #writer2.Execute() reader_br = vmtkscripts.vmtkSurfaceReader() reader_br.InputFileName = args.surface reader_br.Execute() #if (reader_br.Surface.GetPointData().GetNormals() == None): #normalsFilter = vmtkscripts.vmtkSurfaceNormals() #normalsFilter.ComputeCellNormals = 1 #normalsFilter.Surface = reader_br.Surface #normalsFilter.NormalsArrayName = 'Normals' #normalsFilter.Execute() #surface_reference = normalsFilter.Surface #else: surface_reference = reader_br.Surface locator_surf = vtk.vtkPointLocator() locator_surf.SetDataSet(surface_reference) locator_surf.BuildLocator() locator_cell = vtk.vtkCellLocator() locator_cell.SetDataSet(surface_reference) locator_cell.BuildLocator() cell_Ids = vtk.vtkIdList() outputLines = vtk.vtkCellArray() output = vtk.vtkPolyData() triangles = vtk.vtkCellArray() triangle_pd = vtk.vtkPolyData() triangle_pts = vtk.vtkPoints() lengthArray = vtk.vtkDoubleArray() lengthArray.SetName("length") lengthArray.SetNumberOfComponents(1) pts_ids = vtk.vtkIdList() factor = 1.0 factor2 = 2.0 pd_count = 0 size_range = [0.0, 0.0] mid_points = vtk.vtkPoints() vertex = vtk.vtkCellArray() bifurcation_info = {} for i in range(centerlines.GetNumberOfCells()): bifurcation_info[i] = {"clip_id": [], "cell_pt_id": [], "mid_pt": [], "step":[], "less_length": 0.0} cell = centerlines.GetCell(i) if cell.GetCellType() not in (vtk.VTK_POLY_LINE, vtk.VTK_LINE): continue n_cell_pts = cell.GetNumberOfPoints() start_end_pt = [0, n_cell_pts-1] cell_length_half = centerlines.GetCellData().GetArray("length").GetTuple(i)[0]/2.0 for j in start_end_pt: pt_id_pd = cell.GetPointIds().GetId(j) centerlines.GetPointCells(pt_id_pd, cell_Ids) if (cell_Ids.GetNumberOfIds() > 1): radius = centerlines.GetPointData().GetArray("MaximumInscribedSphereRadius").GetTuple(pt_id_pd)[0] length = 0.0 radius2 = 0.0 prev_point = centerlines.GetPoint(pt_id_pd) if( j == start_end_pt[0]): step = 1 stop = start_end_pt[-1] else: step = -1 stop = -1 for k in range(j, stop, step): point = centerlines.GetPoint(cell.GetPointIds().GetId(k)) length += vtk.vtkMath.Distance2BetweenPoints(prev_point,point)**0.5 prev_point = point if (length > (factor*radius + factor2*radius2)): #print(length) pl_vec = centerlines.GetPointData().GetArray("FrenetTangent").GetTuple(cell.GetPointIds().GetId(k)) pl = vtk.vtkPlane() pl.SetOrigin(point) pl.SetNormal(pl_vec) cut = vtk.vtkCutter() cut.SetInputData(surface_reference) cut.SetCutFunction(pl) cut.Update() ex = vtk.vtkPolyDataConnectivityFilter() ex.SetInputConnection(cut.GetOutputPort()) #ex.SetExtractionModeToAllRegions() ex.SetExtractionModeToClosestPointRegion() ex.SetClosestPoint(point) ex.Update() lp = ex.GetOutput() close_cell(lp) cutStrips = vtk.vtkStripper() # Forms loops (closed polylines) from cutter cutStrips.SetInputData(lp) cutStrips.Update() cutPoly = vtk.vtkPolyData() # This trick defines polygons as polyline loop cutPoly.SetPoints((cutStrips.GetOutput()).GetPoints()) cutPoly.SetPolys((cutStrips.GetOutput()).GetLines()) area_test = ComputePolygonArea(cutPoly) size_ratio = area_test/(np.pi*radius**2) #print(area_test, radius, size_ratio) #writerline = vmtkscripts.vmtkSurfaceWriter() #writerline.OutputFileName = "test_loop_{0}.vtp".format(pd_count) #writerline.Input = cutPoly #ex.GetOutput() #writerline.Execute() #pd_count += 1 if (length < cell_length_half): if(size_ratio > 2.0 ): continue cv, offset, shape = ComputeBranchSectionShape(cutPoly, point) if(cv > 0.2): # standard deviation / mean continue if(offset > 0.10): # centroid of slice vs centerline point continue #if(shape > 0.8): # continue #writerline = vmtkscripts.vmtkSurfaceWriter() #writerline.OutputFileName = "test_loop_{0}.vtp".format(pd_count) #writerline.Input = cutPoly #ex.GetOutput() #writerline.Execute() #pd_count += 1 #print(length) clip_id = cell.GetPointIds().GetId(k) bifurcation_info[i]["clip_id"].append(clip_id) bifurcation_info[i]["cell_pt_id"].append(k) bifurcation_info[i]["step"].append(step) bifurcation_info[i]["less_length"] += length tmp_idx = k break midway_length = 0.0 prev_point = centerlines.GetPoint(pt_id_pd) print("hello") for k in range(tmp_idx, stop, step): if k == 1198: print(k) point = centerlines.GetPoint(cell.GetPointIds().GetId(k)) midway_length += vtk.vtkMath.Distance2BetweenPoints(prev_point, point)**0.5 prev_point = point if (midway_length >= cell_length_half): bifurcation_info[i]["mid_pt"].append(point) pt_id = mid_points.InsertNextPoint(point) vertex.InsertNextCell(1, [pt_id]) mid_idx = k break mid_point_pd = vtk.vtkPolyData() mid_point_pd.SetPoints(mid_points) mid_point_pd.SetVerts(vertex) writerline = vmtkscripts.vmtkSurfaceWriter() writerline.OutputFileName = "test_vertex_{0}.vtp".format(0) writerline.Input = mid_point_pd writerline.Execute() #return tree = vtk.vtkModifiedBSPTree() tree.SetDataSet(surface_reference) tree.BuildLocator() #t = [ 1 for i in bifurcation_info.keys() if len(bifurcation_info[i]) == 2] two_bif = False pd_count = 0 avg_x_area = vtk.vtkDoubleArray() avg_x_area.SetName("avg_crosssection") avg_x_area.SetNumberOfComponents(1) avg_x_area.SetNumberOfTuples(centerlines.GetNumberOfCells()) avg_x_area.Fill(-1.0) aspect_ratio = vtk.vtkDoubleArray() aspect_ratio.SetName("aspect_ratio") aspect_ratio.SetNumberOfComponents(1) aspect_ratio.SetNumberOfTuples(centerlines.GetNumberOfCells()) aspect_ratio.Fill(-1.0) vol_array = vtk.vtkDoubleArray() vol_array.SetName("volume") vol_array.SetNumberOfComponents(1) vol_array.SetNumberOfTuples(centerlines.GetNumberOfCells()) vol_array.Fill(-1.0) len_array = vtk.vtkDoubleArray() len_array.SetName("length_wo_bifurcation") len_array.SetNumberOfComponents(1) len_array.SetNumberOfTuples(centerlines.GetNumberOfCells()) len_array.Fill(-1.0) append = vtk.vtkAppendPolyData() for cell_id in bifurcation_info: id_sorted = sorted(bifurcation_info[cell_id]["cell_pt_id"]) step_direction = [x for _,x in sorted(zip(bifurcation_info[cell_id]["cell_pt_id"], bifurcation_info[cell_id]["step"]))] #print(step_direction) if (len(bifurcation_info[cell_id]["cell_pt_id"]) < 2): two_bif = False else: two_bif = True diff = bifurcation_info[cell_id]["cell_pt_id"][0] - bifurcation_info[cell_id]["cell_pt_id"][1] if(abs(diff) < 2): # there is a problem if there less than two points print("houston we got a problem") if (not two_bif): clip_id = centerlines.GetCell(cell_id).GetPointIds().GetId(id_sorted[0]) clip_id_m1 = centerlines.GetCell(cell_id).GetPointIds().GetId(id_sorted[0]+step_direction[0]) start_pt = centerlines.GetPoint(clip_id) surface_pt_id = locator_surf.FindClosestPoint(start_pt) # vector from pt(start_pt+1) - pt(start_pt) v_start = [ x - y for x,y in zip(centerlines.GetPoint(clip_id_m1), start_pt)] v_ctr_start = centerlines.GetPointData().GetArray("FrenetTangent").GetTuple(clip_id) v_normal_start = centerlines.GetPointData().GetArray("FrenetNormal").GetTuple(clip_id) # want inward facing normals if (vtk.vtkMath.Dot(v_start, v_ctr_start) < 0.0): v_ctr_start = [-1.0*x for x in v_ctr_start] #print(clip_tangent) plane1 = vtk.vtkPlane() plane1.SetOrigin(start_pt) plane1.SetNormal(v_ctr_start) seamFilter = vtkvmtk.vtkvmtkTopologicalSeamFilter() seamFilter.SetInputData(surface_reference) seamFilter.SetClosestPoint(surface_reference.GetPoint(surface_pt_id)) seamFilter.SetSeamScalarsArrayName("SeamScalars") seamFilter.SetSeamFunction(plane1) clipper = vtk.vtkClipPolyData() clipper.SetInputConnection(seamFilter.GetOutputPort()) clipper.GenerateClipScalarsOff() clipper.GenerateClippedOutputOn() connectivity = vtk.vtkPolyDataConnectivityFilter() connectivity.SetInputConnection(clipper.GetOutputPort()) connectivity.SetExtractionModeToClosestPointRegion() surface_mid_pt = locator_surf.FindClosestPoint(bifurcation_info[cell_id]["mid_pt"][0]) connectivity.SetClosestPoint(surface_reference.GetPoint(surface_mid_pt)) surfaceCleaner = vtk.vtkCleanPolyData() surfaceCleaner.SetInputConnection(connectivity.GetOutputPort()) surfaceCleaner.Update() surfaceTriangulator = vtk.vtkTriangleFilter() surfaceTriangulator.SetInputConnection(surfaceCleaner.GetOutputPort()) surfaceTriangulator.PassLinesOff() surfaceTriangulator.PassVertsOff() surfaceTriangulator.Update() capper = vmtkscripts.vmtkSurfaceCapper() capper.Surface = surfaceTriangulator.GetOutput() capper.Method = "simple" capper.Interactive = 0 capper.Execute() get_prop = vtk.vtkMassProperties() get_prop.SetInputData(capper.Surface) get_prop.Update() volume = get_prop.GetVolume() new_length = centerlines.GetCellData().GetArray("length").GetTuple(cell_id)[0] - bifurcation_info[cell_id]["less_length"] average_area = volume/new_length avg_x_area.SetTuple(cell_id, [average_area]) aspect_ratio.SetTuple(cell_id, [average_area/new_length]) vol_array.SetTuple(cell_id, [volume]) len_array.SetTuple(cell_id, [new_length]) append.AddInputData(capper.Surface) append.Update() #print(new_length, centerlines.GetCellData().GetArray("length").GetTuple(cell_id)[0], bifurcation_info[cell_id]["less_length"]) #pd_count += 1 writerline = vmtkscripts.vmtkSurfaceWriter() writerline.OutputFileName = args.out_file writerline.Input = append.GetOutput() writerline.Execute() #print( bifurcation_info) centerlines.GetCellData().AddArray(avg_x_area) centerlines.GetCellData().AddArray(aspect_ratio) centerlines.GetCellData().AddArray(vol_array) centerlines.GetCellData().AddArray(len_array) writer = vmtkscripts.vmtkSurfaceWriter() writer.OutputFileName = args.out_segments writer.Input = centerlines writer.Execute()
def CheckIntersections(self, inputModelHierarchyNode, inputFiducialNode): """ Look for intersections between the path (inputFiducialNode) and the models under the hierarchy node. Return (objectIDs, objectNames, normalVectors, entryAngles, curvatures, radiusVectors, totalLengthInObject), where the elements are the arrays of object IDs, names, normal vectors at the entry points, angles between the path and the normal vectors, curvatures at the entry points, normal vectors to the center, and the total length of the path in the object. """ if inputModelHierarchyNode == None: return None if inputFiducialNode == None: return None nOfModels = inputModelHierarchyNode.GetNumberOfChildrenNodes() objectIDs = [] objectNames = [] entryAngles = [] normalVectors = [] totalLengthInObject = [] curvaturesAtEntry = [] radiusNormalsAtEntry = [] for i in range(nOfModels): chnode = inputModelHierarchyNode.GetNthChildNode(i) if chnode == None: continue mnode = chnode.GetAssociatedNode() if mnode == None: continue name = mnode.GetName() objectPoly = mnode.GetPolyData() if objectPoly == None: continue triangle = vtk.vtkTriangleFilter() triangle.SetInputData(objectPoly) triangle.Update() objectTrianglePoly = triangle.GetOutput() # print "Processing object: %s" % name trajectoryPoints = vtk.vtkPoints() idList = vtk.vtkIdList() pos0 = [0.0] * 3 pos1 = [0.0] * 3 pos2 = [0.0] * 3 nFiducials = inputFiducialNode.GetNumberOfFiducials() posStart = None posEnd = None # Look for points inside the object for j in range(nFiducials): inputFiducialNode.GetNthFiducialPosition(j, pos0) trajectoryPoints.InsertNextPoint(pos0) trajectoryPoly = vtk.vtkPolyData() trajectoryPoly.SetPoints(trajectoryPoints) enclosed = vtk.vtkSelectEnclosedPoints() enclosed.SetInputData(trajectoryPoly) enclosed.SetSurfaceData(objectTrianglePoly) enclosed.SetTolerance( 0.0001) # Very important to get consistent result. enclosed.Update() lengthInObject = 0.0 isInside = False angles = [] normals = [] curvatures = [] radiusNormals = [] surfaceNormals = vtk.vtkPolyDataNormals() surfaceNormals.SetInputData(objectTrianglePoly) surfaceNormals.ComputeCellNormalsOn() surfaceNormals.Update() surfaceNormalsOutput = surfaceNormals.GetOutput() # extract the cell data surfaceNormalsCellData = surfaceNormalsOutput.GetCellData() sNormals = surfaceNormalsCellData.GetNormals() for j in range(nFiducials - 1): inputFiducialNode.GetNthFiducialPosition(j, pos0) inputFiducialNode.GetNthFiducialPosition(j + 1, pos1) isInside0 = enclosed.IsInside(j) isInside1 = enclosed.IsInside(j + 1) ## For debug #print "Point %d: from (%f, %f, %f) (%d) to (%f, %f, %f) (%d)" % (j, pos0[0], pos0[1], pos0[2], isInside0, pos1[0], pos1[1], pos1[2], isInside1) # A vector that represents the trajectory between pos0 and pos1 # The orientation will be adjusted later to direct to the outside of the object. trajVec = np.array(pos1) - np.array(pos0) if isInside0 and isInside1: ## Both in the object lSegment = np.linalg.norm(trajVec) lengthInObject = lengthInObject + lSegment isInside = True intersectingPoint = [0.0] * 3 if isInside0 != isInside1: ## Potential intersection bspTree = vtk.vtkModifiedBSPTree() bspTree.SetDataSet(objectTrianglePoly) bspTree.BuildLocator() tolerance = 0.0001 pCoord = [0.0] * 3 t = vtk.mutable(0) subID = vtk.mutable(0) cellID = vtk.mutable(0) fIntersect = bspTree.IntersectWithLine( pos0, pos1, tolerance, t, intersectingPoint, pCoord, subID, cellID) # idList = vtk.vtkIdList() # intersectingPoints = vtk.vtkPoints() # fIntersect = bspTree.IntersectWithLine(pos0, pos1, tolerance, intersectingPoints, idList) if fIntersect == 0: ## If this happens, consider smaller tolerance continue isInside = True # Get intersecting point and measure the length inside the boject # intersectingPoints.GetPoint(0, intersectingPoint) if isInside0: segmentInObject = np.array( intersectingPoint) - np.array(pos0) lengthInObject = lengthInObject + np.linalg.norm( segmentInObject) elif isInside1: segmentInObject = np.array( intersectingPoint) - np.array(pos1) lengthInObject = lengthInObject + np.linalg.norm( segmentInObject) trajVec = -trajVec # cellID = idList.GetId(0) cell = objectTrianglePoly.GetCell(cellID) if cell == None: continue cellNormal = [0.0] * 3 sNormals.GetTuple(cellID, cellNormal) # Check cell type? # if cell.GetCellType() == vtk.VTK_TRIANGLE: # subID = 0 # elif cell.GetCellType() == vtk.VTK_TRIANGLE_STRIP: # print "Triangle Strip" # # Get subID -- no need since the cells have already converted to triangles # cell.IntersectWithLine(pos0, pos1, tolerance, t, intersectingPoint, pCoord, subID) points = cell.GetPoints() if points == None: print "continue 4" continue p0 = [0.0] * 3 p1 = [0.0] * 3 p2 = [0.0] * 3 # Get point (when subID is used) # points.GetPoint(subID + 0, p0) # points.GetPoint(subID + 1, p1) # points.GetPoint(subID + 2, p2) points.GetPoint(0, p0) points.GetPoint(1, p1) points.GetPoint(2, p2) # print (intersectingPoint, p0, p1, p2) # npap0 = np.array(p0) # npap1 = np.array(p1) # npap2 = np.array(p2) # v0 = npap1-npap0 # v1 = npap2-npap0 # v = np.cross(v0, v1) # norm = np.linalg.norm(v,ord=1) # normVec = v / norm # print "Normal = (%f, %f, %f) / (%f, %f, %f)" % (normVec[0], normVec[1], normVec[2], cellNormal[0], cellNormal[1], cellNormal[2]) # Compute average normal #clippedModel = clip.GetOutput() # cellsNormal = clippedModel.GetCell(cellID).GetPointData().GetNormals() # # averageNormal = [0.0, 0.0, 0.0] # nOfNormals = 0; # # for cellIndex in range(0, cellsNormal.GetNumberOfTuples()): # cellNormal = [0.0, 0.0, 0.0] # cellsNormal.GetTuple(cellIndex, cellNormal) # # if not(math.isnan(cellNormal[0]) or math.isnan(cellNormal[1]) or math.isnan(cellNormal[2])): # averageNormal[0] = averageNormal[0] + cellNormal[0] # averageNormal[1] = averageNormal[1] + cellNormal[1] # averageNormal[2] = averageNormal[2] + cellNormal[2] # nOfNormals = nOfNormals + 1 # Calculate the entry angle. Entry angle is zero, when the trajectory is perpendicular # to the surface. # angle = vtk.vtkMath.AngleBetweenVectors(normVec, trajVec) * 180.0 / math.pi angle = vtk.vtkMath.AngleBetweenVectors( cellNormal, trajVec) * 180.0 / math.pi angles.append(angle) normals.append(cellNormal) trajNorm = np.linalg.norm(trajVec, ord=1) nTrajVec = trajVec if trajNorm > 0.0: nTrajVec = trajVec / trajNorm # # Caluclate the entry vector defined by: <v_e> = <n_t> - <n> # # where <n_t> and <n> are the trajectory vector and the normal. # entryVec = nTrajVec - normVec #print " -- Intersecting at (%f, %f, %f) with angle %f and normal vector (%f, %f, %f)" % (p[0], p[1], p[2], angle, normVec[0], normVec[1], normVec[2]) if j > 0: inputFiducialNode.GetNthFiducialPosition(j - 1, pos2) # inputFiducialNode.GetNthFiducialPosition(j, pos0) # inputFiducialNode.GetNthFiducialPosition(j+1, pos1) (kappa, vc) = self.ComputeCurvature(np.array(pos2), np.array(pos0), np.array(pos1)) curvatures.append(kappa) radiusNormals.append(vc) else: inputFiducialNode.GetNthFiducialPosition(j + 2, pos2) (kappa, vc) = self.ComputeCurvature(np.array(pos0), np.array(pos1), np.array(pos2)) curvatures.append(kappa) radiusNormals.append(vc) if isInside: objectIDs.append(i) objectNames.append(name) normalVectors.append(normals) entryAngles.append(angles) totalLengthInObject.append(lengthInObject) curvaturesAtEntry.append(curvatures) radiusNormalsAtEntry.append(radiusNormals) return (objectIDs, objectNames, normalVectors, entryAngles, totalLengthInObject, curvaturesAtEntry, radiusNormalsAtEntry)