def trimesh2vtk(inputobj, alphaPerCell=False): """Convert trimesh object to ``Actor(vtkActor)`` object.""" from vtkplotter import Actor #colors.printc('trimesh2vtk inputobj', type(inputobj), c=3) inputobj_type = str(type(inputobj)) if "Trimesh" in inputobj_type or "primitives" in inputobj_type: faces = inputobj.faces poly = buildPolyData(inputobj.vertices, faces) tact = Actor(poly) if inputobj.visual.kind == 'face': trim_c = inputobj.visual.face_colors else: trim_c = inputobj.visual.vertex_colors if isSequence(trim_c): if isSequence(trim_c[0]): trim_cc = trim_c[:, [0, 1, 2]] / 255 trim_al = trim_c[:, 3] / 255 if inputobj.visual.kind == 'face': tact.colorCellsByArray(trim_cc, trim_al, alphaPerCell) else: tact.colorVerticesByArray(trim_cc, trim_al) else: print('trim_c not sequence?', trim_c) return tact elif "PointCloud" in inputobj_type: from vtkplotter.shapes import Points trim_cc, trim_al = 'black', 1 if hasattr(inputobj, 'vertices_color'): trim_c = inputobj.vertices_color if len(trim_c): trim_cc = trim_c[:, [0, 1, 2]] / 255 trim_al = trim_c[:, 3] / 255 trim_al = np.sum(trim_al) / len(trim_al) # just the average return Points(inputobj.vertices, r=8, c=trim_cc, alpha=trim_al) elif "path" in inputobj_type: from vtkplotter.shapes import Line from vtkplotter.actors import Assembly lines = [] for e in inputobj.entities: #print('trimesh entity', e.to_dict()) l = Line(inputobj.vertices[e.points], c='k', lw=2) lines.append(l) return Assembly(lines) return None
def add_optic_cannula(self, target_region=None, pos=None, x_offset=0, y_offset=0, z_offset=-500, use_line=False, **kwargs): """ Adds a cylindrical vtk actor to scene to render optic cannulas. By default this is a semi-transparent blue cylinder centered on the center of mass of a specified target region and oriented vertically. :param target_region: str, acronym of target region to extract coordinates of implanted fiber. By defualt the fiber will be centered on the center of mass of the target region but the offset arguments can be used to fine tune the position. Alternative pass a 'pos' argument with XYZ coords. :param pos: list or tuple or np.array with X,Y,Z coordinates. Must have length = 3. :param x_offset, y_offset, z_offset: int, used to fine tune the coordinates of the implanted cannula. :param **kwargs: used to specify which hemisphere the cannula is and parameters of the rendered cylinder: color, alpha, rotation axis... """ # Set some default kwargs hemisphere = kwargs.pop('hemisphere', 'right') color = kwargs.pop('color', 'powderblue') radius = kwargs.pop('radius', 350) alpha = kwargs.pop('alpha', .5) # Get coordinates of brain-side face of optic cannula if target_region is not None: pos = self.get_region_CenterOfMass(target_region, unilateral=True, hemisphere=hemisphere) elif pos is None: print("No 'pos' or 'target_region' arguments were \ passed to 'add_optic_cannula', nothing to render") return else: if not len(pos) == 3: raise ValueError(f"Invalid target coordinates argument, pos: {pos}") # Offset position pos[0] += y_offset pos[1] += z_offset pos[2] += x_offset # Get coordinates of upper face bounds = self.root.bounds() top = pos.copy() top[1] = bounds[2] - 500 if not use_line: cylinder = self.add_vtkactor(Cylinder(pos=[top, pos], c=color, r=radius, alpha=alpha, **kwargs)) else: cylinder = self.add_vtkactor(Line(top, pos, c=color, alpha=alpha, lw=radius)) return cylinder
def add_line_at_point(self, point, replace_coord, bounds, **kwargs): """ Adds a line oriented on a given axis at a point :param point:list or 1d np array with coordinates of point where crosshair is centered :param replace_coord: index of the coordinate to replace (i.e. along which axis is the line oriented) :param bounds: list of two floats with lower and upper bound for line, determins the extent of the line :param kwargs: dictionary with arguments to specify how lines should look like """ # Get line coords p0, p1 = point.copy(), point.copy() p0[replace_coord] = bounds[0] p1[replace_coord] = bounds[1] # Get some default params color = kwargs.pop('c', 'blackboard') color = kwargs.pop('color', color) lw = kwargs.pop('lw', 3) # Create line actor act = self.add_vtkactor(Line(p0, p1, c=color, lw=lw, **kwargs)) return act
def trimesh2vtk(inputobj, alphaPerCell=False): """ Convert ``Trimesh`` object to ``Actor(vtkActor)`` or ``Assembly`` object. """ if isSequence(inputobj): vms = [] for ob in inputobj: vms.append(trimesh2vtk(ob)) return vms # print('trimesh2vtk inputobj', type(inputobj)) inputobj_type = str(type(inputobj)) if "Trimesh" in inputobj_type or "primitives" in inputobj_type: from vtkplotter import Actor faces = inputobj.faces poly = buildPolyData(inputobj.vertices, faces) tact = Actor(poly) if inputobj.visual.kind == "face": trim_c = inputobj.visual.face_colors else: trim_c = inputobj.visual.vertex_colors if isSequence(trim_c): if isSequence(trim_c[0]): sameColor = len(np.unique( trim_c, axis=0)) < 2 # all vtxs have same color trim_c = trim_c / 255 if sameColor: tact.c(trim_c[0, [0, 1, 2]]).alpha(trim_c[0, 3]) else: if inputobj.visual.kind == "face": tact.cellColors(trim_c[:, [0, 1, 2]], mode='colors', alpha=trim_c[:, 3], alphaPerCell=alphaPerCell) else: tact.pointColors(trim_c[:, [0, 1, 2]], mode='colors', alpha=trim_c[3]) return tact elif "PointCloud" in inputobj_type: from vtkplotter.shapes import Points trim_cc, trim_al = "black", 1 if hasattr(inputobj, "vertices_color"): trim_c = inputobj.vertices_color if len(trim_c): trim_cc = trim_c[:, [0, 1, 2]] / 255 trim_al = trim_c[:, 3] / 255 trim_al = np.sum(trim_al) / len(trim_al) # just the average return Points(inputobj.vertices, r=8, c=trim_cc, alpha=trim_al) elif "path" in inputobj_type: from vtkplotter.shapes import Line from vtkplotter.actors import Assembly lines = [] for e in inputobj.entities: # print('trimesh entity', e.to_dict()) l = Line(inputobj.vertices[e.points], c="k", lw=2) lines.append(l) return Assembly(lines) return None