def csgTSpin(rad, len, tolerance, scaling, detail): """ Generates a T-spin joint using the constructive solid geometry (csg) library pycsg. ---- ---- Top disk | | Top tube (Height is 'topheight') --- --- Mid disk | | Bottom tube (Height is 'botheight') ------- Bottom disk Horizontal axes are scaled with the joint width scaling factor (relative to r). Vertical axes are not (relative to rad). """ r = rad * scaling botheight, topheight = 0.4 * rad, 0.3 * rad #Need these two quantities to place visualization later. height = botheight + topheight bottom = -(height / 2) bottomdisk = CSG.cylinder(radius=0.8 * r + tolerance / 2, start=[0, bottom - tolerance / 2, 0], end=[0, bottom + tolerance / 2, 0], slices=detail) bottomtube = CSG.cylinder(radius = 0.8*r+tolerance/2, start = [0,bottom,0], end = [0,botheight,0], slices = detail) \ - CSG.cylinder(radius = 0.8*r-tolerance/2, start = [0,bottom,0], end = [0,botheight,0], slices = detail) middisk = CSG.cylinder(radius = 0.8*r+tolerance/2, start = [0,botheight-tolerance/2,0], end = [0,botheight+tolerance/2,0], slices = detail) \ - CSG.cylinder(radius = 0.6*r - tolerance/2, start = [0,botheight-tolerance/2,0], end = [0,botheight+tolerance/2,0], slices = detail) toptube = CSG.cylinder(radius = 0.6*r+tolerance/2, start = [0,botheight,0], end = [0,height,0], slices = detail) \ - CSG.cylinder(radius = 0.6*r-tolerance/2, start = [0,botheight,0], end = [0,height,0], slices = detail) topdisk = CSG.cylinder(radius = r+tolerance/2, start = [0,height-tolerance/2,0], end = [0,height+tolerance/2,0], slices = detail) \ - CSG.cylinder(radius = 0.6*r-tolerance/2, start = [0,height-tolerance/2,0], end = [0,height+tolerance/2,0], slices = detail) bond = CSG.cylinder(radius=r, start=[0, -(len / 2), 0], end=[0, len / 2, 0], slices=detail) minusjoint = bottomdisk + bottomtube + middisk + toptube + topdisk joint = bond - minusjoint return (csgtovtk(joint), botheight, topheight)
def test_bolt(self): shaft = CSG.cylinder(start=[0., 0., 0.], end=[1., 0., 0.], radius=0.1, slices=32) head = CSG.cone(start=[-0.12, 0., 0.], end=[0.10, 0., 0.], radius=0.25) notch1 = CSG.cube(center=[-0.10, 0., 0.], radius=[0.02, 0.20, 0.02]) notch2 = CSG.cube(center=[-0.10, 0., 0.], radius=[0.02, 0.02, 0.20]) bolt = shaft + head - notch1 - notch2 bolt.saveVTK('test_bolt.vtk')
def test_toPolygons(self): a = CSG.cube([0.5, 0.5, 0.0]) aPolys = a.toPolygons() b = CSG.sphere() bPolys = b.toPolygons() c = CSG.cylinder() cPolys = c.toPolygons()
def test_toPolygons(self): a = CSG.cube([0.5, 0.5, 0.0]) aPolys = a.toPolygons() b = CSG.sphere() bPolys = b.toPolygons() c = CSG.cylinder() cPolys = c.toPolygons()
def test_bolt(self): shaft = CSG.cylinder(start=[0., 0., 0.], end=[1., 0., 0.], radius=0.1, slices=32) head = CSG.cone(start=[-0.12, 0., 0.], end=[0.10, 0., 0.], radius=0.25) notch1 = CSG.cube(center=[-0.10, 0., 0.], radius=[0.02, 0.20, 0.02]) notch2 = CSG.cube(center=[-0.10, 0., 0.], radius=[0.02, 0.02, 0.20]) bolt = shaft + head - notch1 - notch2 bolt.saveVTK('test_bolt.vtk')
def test_sphere_cylinder_subtract(self): a = CSG.sphere(center=[0.5, 0.5, 0.5], radius=0.5, slices=8, stacks=4) b = CSG.cylinder(start=[0., 0., 0.], end=[1., 0., 0.], radius=0.3, slices=16) a.subtract(b).saveVTK('test_sphere_cylinder_subtract.vtk')
def check_cylinder_intersections(filename): """Check if cylinder-cylinder intersections occur with CSG tools (BSP trees) Keyword arguments: filename -- the name of the file which should be checked for intersections """ edges = read_swc_to_edge_list(filename) numIntersections = 0 for combination in combinations(range(0, len(edges) - 2, 2), 2): p1 = edges[combination[0] + 0][0] p2 = edges[combination[0] + 1][1] d1 = edges[combination[0] + 0][2] d2 = edges[combination[0] + 1][2] p3 = edges[combination[1] + 0][0] p4 = edges[combination[1] + 1][1] d3 = edges[combination[1] + 0][2] d4 = edges[combination[1] + 1][2] t1 = edges[combination[0] + 0][3] t2 = edges[combination[0] + 1][3] t3 = edges[combination[1] + 0][3] t4 = edges[combination[1] + 1][3] # ignore soma cylinders (as they are error-prone) if (t1 == 1 or t2 == 1 or t3 == 1 or t4 == 1): continue # ignore self-loops (should actually never happen) if (p1 == p2 or p3 == p4): continue # ignore adjacent cylinders if (p1 == p3 or p1 == p4 or p2 == p3 or p2 == p4): continue # check for intersections a = CSG.cylinder(radius=0.5 * (d1 + d2), start=p1, end=p2, slices=4) b = CSG.cylinder(radius=0.5 * (d3 + d4), start=p3, end=p4, slices=4) polys = a.intersect(b) if polys.toPolygons(): print(polys.toPolygons()) print("Cylinders intersect in neuron with name %s" % filename) print("Cylinders: A (%f;%s;%s) and B(%f;%s;%s)" % (0.5 * (d1 + d2), p1, p2, 0.5 * (d3 + d4), p3, p4)) numIntersections = numIntersections + 1 return numIntersections > 0 and True or False
def cylinder_csg(inst): r, h, n = inst[1:4] key = "%f,%f%dcylidner" % (r, h, n) obj = cache_find(key) if obj is not None: mesh_push(obj, key) return obj = CSG.cylinder(start=[0, 0, 0], end=[0, 0, h], slices=n, radius=r) cache_put(key, obj) mesh_push(obj, key)
def __init__(self, operation): self.faces = [] self.normals = [] self.vertices = [] self.colors = [] self.vnormals = [] self.list = -1 a = CSG.cube() b = CSG.cylinder(radius=0.5, start=[0., -2., 0.], end=[0., 2., 0.]) for p in a.polygons: p.shared = [1.0, 0.0, 0.0, 1.0] for p in b.polygons: p.shared = [0.0, 1.0, 0.0, 1.0] recursionlimit = sys.getrecursionlimit() sys.setrecursionlimit(10000) try: if operation == 'subtract': polygons = a.subtract(b).toPolygons() elif operation == 'union': polygons = a.union(b).toPolygons() elif operation == 'intersect': polygons = a.intersect(b).toPolygons() else: raise Exception('Unknown operation: \'%s\'' % operation) except RuntimeError as e: raise RuntimeError(e) sys.setrecursionlimit(recursionlimit) for polygon in polygons: n = polygon.plane.normal indices = [] for v in polygon.vertices: pos = [v.pos.x, v.pos.y, v.pos.z] if not pos in self.vertices: self.vertices.append(pos) self.vnormals.append([]) index = self.vertices.index(pos) indices.append(index) self.vnormals[index].append(v.normal) self.faces.append(indices) self.normals.append([n.x, n.y, n.z]) self.colors.append(polygon.shared) # setup vertex-normals ns = [] for vns in self.vnormals: n = Vector(0.0, 0.0, 0.0) for vn in vns: n = n.plus(vn) n = n.dividedBy(len(vns)) ns.append([a for a in n]) self.vnormals = ns
def __init__(self, operation): self.faces = [] self.normals = [] self.vertices = [] self.colors = [] self.vnormals = [] self.list = -1 a = CSG.cube() b = CSG.cylinder(radius=0.5, start=[0., -2., 0.], end=[0., 2., 0.]) for p in a.polygons: p.shared = [1.0, 0.0, 0.0, 1.0] for p in b.polygons: p.shared = [0.0, 1.0, 0.0, 1.0] recursionlimit = sys.getrecursionlimit() sys.setrecursionlimit(10000) try: if operation == 'subtract': polygons = a.subtract(b).toPolygons() elif operation == 'union': polygons = a.union(b).toPolygons() elif operation == 'intersect': polygons = a.intersect(b).toPolygons() else: raise Exception('Unknown operation: \'%s\'' % operation) except RuntimeError as e: raise RuntimeError(e) sys.setrecursionlimit(recursionlimit) for polygon in polygons: n = polygon.plane.normal indices = [] for v in polygon.vertices: pos = [v.pos.x, v.pos.y, v.pos.z] if not pos in self.vertices: self.vertices.append(pos) self.vnormals.append([]) index = self.vertices.index(pos) indices.append(index) self.vnormals[index].append(v.normal) self.faces.append(indices) self.normals.append([n.x, n.y, n.z]) self.colors.append(polygon.shared) # setup vertex-normals ns = [] for vns in self.vnormals: n = Vector(0.0, 0.0, 0.0) for vn in vns: n = n.plus(vn) n = n.dividedBy(len(vns)) ns.append([a for a in n]) self.vnormals = ns
def Cylinder(radius, origin, lengths, n_theta=16): """ Create cylinder @param radius radius @param origin center of low end disk @param lengths lengths of the cylinder along each axis @param n_theta number of theta cells """ ori = Vector(origin[0], origin[1], origin[2]) end = Vector(origin[0] + lengths[0], origin[1] + lengths[1], origin[2] + lengths[2]) return CSG.cylinder(start=ori, end=end, radius=radius, slices=n_theta)
def test_cylinder(self): a = CSG.cylinder(start=[0., 0., 0.], end=[1., 2., 3.], radius=1.0, slices=8) a.saveVTK('test_cylinder.vtk')
def test_sphere_cylinder_subtract(self): a = CSG.sphere(center=[0.5, 0.5, 0.5], radius=0.5, slices=8, stacks=4) b = CSG.cylinder(start=[0.,0.,0.], end=[1.,0.,0.], radius=0.3, slices=16) a.subtract(b).saveVTK('test_sphere_cylinder_subtract.vtk')
def test_translate_cylinder(self): b = CSG.cylinder() b.saveVTK('b.vtk') b.translate(disp=[0.1, 0.2, 0.3]) b.saveVTK('bTranslated.vtk')
def test_rotate_cylinder(self): b = CSG.cylinder() b.saveVTK('b.vtk') b.rotate(axis=[0.1, 0.2, 0.3], angleDeg=20.0) b.saveVTK('bRotated.vtk')
def test_translate_cylinder(self): b = CSG.cylinder() b.saveVTK('b.vtk') b.translate(disp=[0.1, 0.2, 0.3]) b.saveVTK('bTranslated.vtk')
def test_rotate_cylinder(self): b = CSG.cylinder() b.saveVTK('b.vtk') b.rotate(axis=[0.1, 0.2, 0.3], angleDeg=20.0) b.saveVTK('bRotated.vtk')
def test_cylinder(self): a = CSG.cylinder(start=[0., 0., 0.], end=[1., 2., 3.], radius=1.0, slices=8) a.saveVTK('test_cylinder.vtk')