def __call__(self, outerROI, triangle): #Create an Octree from inner surface minx = min([v.x for v in self.inner_mesh.vertices]) - 0.01 maxx = max([v.x for v in self.inner_mesh.vertices]) + 0.01 miny = min([v.y for v in self.inner_mesh.vertices]) - 0.01 maxy = max([v.y for v in self.inner_mesh.vertices]) + 0.01 minz = min([v.z for v in self.inner_mesh.vertices]) - 0.01 maxz = max([v.z for v in self.inner_mesh.vertices]) + 0.01 points = Octree(((minx, maxx), (miny, maxy), (minz, maxz))) for v in self.inner_mesh.vertices: points.insert((v.x, v.y, v.z), v) #Copy extend to inner surface inner_avoid_edges = [] outer_avoid_edges = [] join_strip = [] for roi in outerROI.rois: for start_outer, end_outer in zip(roi.points, roi.points[1:] + [roi.points[0]]): start_outer_vertex = outerROI.mesh.faces[start_outer[3]].nearest_vertex(*start_outer[:3]) end_outer_vertex = outerROI.mesh.faces[end_outer[3]].nearest_vertex(*end_outer[:3]) start_distance, start_coords, start_inner = points.by_distance_from_point((start_outer_vertex.x, start_outer_vertex.y, start_outer_vertex.z)).next() end_distance, end_coords, end_inner = points.by_distance_from_point((end_outer_vertex.x, end_outer_vertex.y, end_outer_vertex.z)).next() inner_strip = [x.edge for x in self.inner_mesh.get_vertex_path(start_inner, end_inner)] outer_strip = [x.edge for x in self.outer_mesh.get_vertex_path(start_outer_vertex,end_outer_vertex)] inner_avoid_edges = inner_avoid_edges + inner_strip outer_avoid_edges = outer_avoid_edges + outer_strip join_strip = join_strip + [(start_inner, inner_strip, start_outer_vertex, outer_strip)] triangle_distance, triangle_coords, triangle_vertex_inner = points.by_distance_from_point(triangle.vertices[0]).next() start_triangle = triangle_vertex_inner.faces[0] innerMesh = self.inner_mesh.cloneSubVol(start_triangle, inner_avoid_edges) print outer_avoid_edges outerMesh = self.outer_mesh.cloneSubVol(triangle, outer_avoid_edges) newMesh = mesh.Mesh() newMesh.add_mesh(outerMesh) newMesh.add_mesh(innerMesh, invert = True) for current_inner, inner_strip, current_outer, outer_strip in join_strip: inner_list = list_vertices(newMesh, current_inner, inner_strip) outer_list = list_vertices(newMesh, current_outer, outer_strip) while len(inner_list) > 1 or len(outer_list) > 1: if len(outer_list) == 1 or (len(inner_list) > 1 and (inner_list[0] - outer_list[1]).magnitude() > (inner_list[1] - outer_list[0]).magnitude()): newMesh.add_face(inner_list[0], inner_list[1], outer_list[0]) inner_list = inner_list[1:] else: newMesh.add_face(inner_list[0], outer_list[1], outer_list[0]) outer_list = outer_list[1:] for edge in newMesh.edges.values(): if edge.lface is None or edge.rface is None: print edge print newMesh.closed() stlwriter = mesh.fileio.StlWriter(mesh.fileio.STL_FORMAT_BINARY) stlwriter.write(newMesh, "Mould", self.base_file + "mould.stl")
def expand(points, distance): expanded = Octree(expand_bounds(points.bounds, distance)) points_list = list(points) d_angle = 0.2 max_angle = 0.600000001 all_norm_offsets = [(0, 0, 1)] distance_slightly_reduced = 0.9999 * distance for theta in [d_angle * (i + 1) for i in range(int(max_angle / d_angle))]: sin_theta = sin(theta) cos_theta = cos(theta) num_phis = int(round(2 * pi * sin_theta / d_angle)) for phi in [2 * pi * j / num_phis for j in range(num_phis)]: all_norm_offsets.append( (sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta))) num_points = len(points_list) hits = 0 for i, (point, normal) in enumerate(points_list): if i % 100 == 0: print "%0.2f%% complete of %i hits from %i starting points" % ( (100.0 * i) / num_points, hits, i) n = Vector(*normal) nn = n.normalise() a, b = nn.get_orthogonal_vectors() for oa, ob, on in all_norm_offsets: new_point = [ pc + on * nc * distance + oa * ac * distance + ob * bc * distance for pc, nc, ac, bc in zip(point, n, a, b) ] try: points.by_distance_from_point( new_point, distance_slightly_reduced).next() except StopIteration: expanded.insert(new_point, normal) hits += 1 return expanded
def copy_point_cloud_excluding(points, excluding_points, distance): clean_skin = Octree(points.bounds) points_list = points.by_distance_from_point( (0, 0, 0) ) #Points do not actually need to be ordered, perhaps they can be found more efficiently for ignore, point, normal in points_list: try: excluding_points.by_distance_from_point(point, distance).next() except StopIteration: clean_skin.insert(point, normal) return clean_skin
def __call__(self, roiGUI, triangle): avoid_edges = [] for roi in roiGUI.rois: avoid = [] for paths in roi.paths: start = None previous_vertex = None for path in paths: for point in path.points(): if start != point:#if first point != last point vertex = point.splitmesh(self.mesh) if previous_vertex is not None: avoid.append(self.mesh.edges[(vertex, previous_vertex)])#Need an edge not a vertex!! previous_vertex = vertex if start is None: start = point avoid_edges.append(avoid) #avoid_edges = roiGUI.get_avoidance_edges() #Save the cut out mesh to a file roughcut = self.mesh.cloneSubVol(triangle, avoid_edges) print "Saving" mesh.fileio.write_ply(roughcut, self.base_file + "rough.ply") #Expand cut out mesh and save that to a file called external minx = min([v.x for v in roughcut.vertices]) - 0.01 maxx = max([v.x for v in roughcut.vertices]) + 0.01 miny = min([v.y for v in roughcut.vertices]) - 0.01 maxy = max([v.y for v in roughcut.vertices]) + 0.01 minz = min([v.z for v in roughcut.vertices]) - 0.01 maxz = max([v.z for v in roughcut.vertices]) + 0.01 points = Octree(((minx, maxx), (miny, maxy), (minz, maxz))) for v in roughcut.vertices: n = v.normal() points.insert((v.x, v.y, v.z), (n.x, n.y, n.z)) external = expand(points, MOULD_THICKNESS) make_ply(external, self.base_file + "external", poisson_depth = POISSON_DEPTH) make_ply(points, self.base_file + "external_base", poisson_depth = POISSON_DEPTH)
def onSelect(self, triangle, m, rois): # XXX: self.base_file = "blahblah" avoid_edges = self.get_avoidance_edges(rois) #Save the cut out mesh to a file roughcut = m.cloneSubVol(triangle, avoid_edges) self.controller.addMesh(roughcut, "Rough") self.controller.parent.meshPanel.addMesh("Rough") self.controller.parent.meshPanel.hideMesh("Skin") return print "Saving" mesh.fileio.write_ply(roughcut, self.base_file + "rough.ply") #Expand cut out mesh and save that to a file called external minx = min([v.x for v in roughcut.vertices]) - 0.01 maxx = max([v.x for v in roughcut.vertices]) + 0.01 miny = min([v.y for v in roughcut.vertices]) - 0.01 maxy = max([v.y for v in roughcut.vertices]) + 0.01 minz = min([v.z for v in roughcut.vertices]) - 0.01 maxz = max([v.z for v in roughcut.vertices]) + 0.01 points = Octree(((minx, maxx), (miny, maxy), (minz, maxz))) for v in roughcut.vertices: n = v.normal() points.insert((v.x, v.y, v.z), (n.x, n.y, n.z)) external = expand(points, MOULD_THICKNESS) make_ply(external, self.base_file + "external", poisson_depth = POISSON_DEPTH) make_ply(points, self.base_file + "external_base", poisson_depth = POISSON_DEPTH) print "Done"
class BasicTests(TestCase): def setUp(self): self.o = Octree(((0.0, 1.0), (0.0, 1.0), (0.0, 1.0))) self.o.insert((0.33, 0.66, 0.99), "Point one") self.o.insert((0.12, 0.34, 0.56), "Point two") self.o.insert((0.98, 0.76, 0.54), "Point three") def test_size(self): self.assertEqual(len(self.o), 3) def test_thinking_outside_box(self): with self.assertRaises(KeyError): self.o.insert((2.35, 0.87, 0.56), "> maxx") with self.assertRaises(KeyError): self.o.insert((-0.43, 0.87, 0.56), "< minx") with self.assertRaises(KeyError): self.o.insert((0.35, 1.94, 0.56), "> maxy") with self.assertRaises(KeyError): self.o.insert((0.35, -0.51, 0.56), "< miny") with self.assertRaises(KeyError): self.o.insert((0.35, 0.87, 1.04), "> maxz") with self.assertRaises(KeyError): self.o.insert((0.35, 0.87, -0.35), "< minz") def test_update_insert(self): with self.assertRaises(KeyError): self.o.insert((0.33, 0.66, 0.99), "Point one, renewed") self.o.update((0.33, 0.66, 0.99), "Point one, renewed") self.assertEqual(len(self.o), 3) self.o.insert((0.98, 0.23, 0.15), "Point four") self.assertEqual(len(self.o), 4)
def __call__(self, outerROI, triangle): #Create an Octree from inner surface minx = min([v.x for v in self.inner_mesh.vertices]) - 0.01 maxx = max([v.x for v in self.inner_mesh.vertices]) + 0.01 miny = min([v.y for v in self.inner_mesh.vertices]) - 0.01 maxy = max([v.y for v in self.inner_mesh.vertices]) + 0.01 minz = min([v.z for v in self.inner_mesh.vertices]) - 0.01 maxz = max([v.z for v in self.inner_mesh.vertices]) + 0.01 points = Octree(((minx, maxx), (miny, maxy), (minz, maxz))) for v in self.inner_mesh.vertices: points.insert((v.x, v.y, v.z), v) #Copy extend to inner surface inner_avoid_edges = [] outer_avoid_edges = [] join_strip = [] for roi in outerROI.rois: for start_outer, end_outer in zip(roi.points, roi.points[1:] + [roi.points[0]]): start_outer_vertex = outerROI.mesh.faces[ start_outer[3]].nearest_vertex(*start_outer[:3]) end_outer_vertex = outerROI.mesh.faces[ end_outer[3]].nearest_vertex(*end_outer[:3]) start_distance, start_coords, start_inner = points.by_distance_from_point( (start_outer_vertex.x, start_outer_vertex.y, start_outer_vertex.z)).next() end_distance, end_coords, end_inner = points.by_distance_from_point( (end_outer_vertex.x, end_outer_vertex.y, end_outer_vertex.z)).next() inner_strip = [ x.edge for x in self.inner_mesh.get_vertex_path( start_inner, end_inner) ] outer_strip = [ x.edge for x in self.outer_mesh.get_vertex_path( start_outer_vertex, end_outer_vertex) ] inner_avoid_edges = inner_avoid_edges + inner_strip outer_avoid_edges = outer_avoid_edges + outer_strip join_strip = join_strip + [ (start_inner, inner_strip, start_outer_vertex, outer_strip) ] triangle_distance, triangle_coords, triangle_vertex_inner = points.by_distance_from_point( triangle.vertices[0]).next() start_triangle = triangle_vertex_inner.faces[0] innerMesh = self.inner_mesh.cloneSubVol(start_triangle, inner_avoid_edges) print outer_avoid_edges outerMesh = self.outer_mesh.cloneSubVol(triangle, outer_avoid_edges) newMesh = mesh.Mesh() newMesh.add_mesh(outerMesh) newMesh.add_mesh(innerMesh, invert=True) for current_inner, inner_strip, current_outer, outer_strip in join_strip: inner_list = list_vertices(newMesh, current_inner, inner_strip) outer_list = list_vertices(newMesh, current_outer, outer_strip) while len(inner_list) > 1 or len(outer_list) > 1: if len(outer_list) == 1 or ( len(inner_list) > 1 and (inner_list[0] - outer_list[1]).magnitude() > (inner_list[1] - outer_list[0]).magnitude()): newMesh.add_face(inner_list[0], inner_list[1], outer_list[0]) inner_list = inner_list[1:] else: newMesh.add_face(inner_list[0], outer_list[1], outer_list[0]) outer_list = outer_list[1:] for edge in newMesh.edges.values(): if edge.lface is None or edge.rface is None: print edge print newMesh.closed() stlwriter = mesh.fileio.StlWriter(mesh.fileio.STL_FORMAT_BINARY) stlwriter.write(newMesh, "Mould", self.base_file + "mould.stl")
def makepoints(t, zpositions, posX, posY, spacingX, spacingY, level): t = t.astype(numpy.int16) mean = (t[1:, 1:, 1:] + t[1:, 1:, :-1] + t[1:, :-1, 1:] + t[1:, :-1, :-1] + t[:-1, 1:, 1:] + t[:-1, 1:, :-1] + t[:-1, :-1, 1:] + t[:-1, :-1, :-1]) / 8 gz = (t[1:, 1:, 1:] + t[1:, 1:, :-1] + t[1:, :-1, 1:] + t[1:,:-1,:-1] \ - t[:-1, 1:, 1:] - t[:-1, 1:, :-1] - t[:-1, :-1, 1:] - t[:-1,:-1,:-1]) / 4 #print "gz", gz gy = (t[1:, 1:, 1:] + t[1:, 1:, :-1] - t[1:, :-1, 1:] - t[1:,:-1,:-1] \ + t[:-1, 1:, 1:] + t[:-1, 1:, :-1] - t[:-1, :-1, 1:] - t[:-1,:-1,:-1]) / 4 gx = (t[1:, 1:, 1:] - t[1:, 1:, :-1] + t[1:, :-1, 1:] - t[1:,:-1,:-1] \ + t[:-1, 1:, 1:] - t[:-1, 1:, :-1] + t[:-1, :-1, 1:] - t[:-1,:-1,:-1]) / 4 #print t[:2, :2, :2] #print mean[:1, :1, :1] #print "gx", gx[:1, :1, :1] #print "gy", gy[:1, :1, :1] #print "gz", gz.dtype #print ((posX, posX + (t.shape[0] + 1) * spacingX),(posY, posY + (t.shape[1] + 1) * spacingY),(min(zpositions),max(zpositions))) results = Octree( ((posX, posX + (t.shape[2] + 1) * spacingX), (posY, posY + (t.shape[1] + 1) * spacingY), (min(zpositions), max(zpositions)))) #del t gn = (gx**2 + gy**2 + gz**2)**0.5 nx = gx / gn #print nx.dtype #print gx.dtype del gx ny = gy / gn del gy nz = gz / gn del gz dist = (mean - level) / gn del gn dx = dist * nx dy = dist * ny dz = dist * nz print dz.dtype del dist hit = numpy.logical_and(numpy.logical_and(abs(dx) < 0.5, abs(dy) < 0.5), abs(dz) < 0.5) for i, j, k in zip(*hit.nonzero()): rx = nx[i, j, k] / spacingX ry = ny[i, j, k] / spacingY rz = nz[i, j, k] / float(zpositions[i + 1] - zpositions[i]) rn = (rx**2 + ry**2 + rz**2)**0.5 rx = -rx / rn ry = -ry / rn rz = -rz / rn #print k, dx[i, j, k], posX, spacingX, t.shape #print posX, posX + (k + 0.5 - dx[i, j, k] / 2) * spacingX, posX + (t.shape[0] + 1) * spacingX results.insert( (posX + (k + 0.5 - dx[i, j, k]) * spacingX, posY + (j + 0.5 - dy[i, j, k]) * spacingY, float(zpositions[i]) * (0.5 + dz[i, j, k]) + float(zpositions[i + 1]) * (0.5 - dz[i, j, k])), (rx, ry, rz)) del dx del dy del dz del nx del ny del nz return results