class SuperSeashell: def __init__(self, parameters): self.parameters = parameters self.u_res = parameters['cross_section_resolution'] self.v_res = parameters['coil_resolution'] self.topology = parameters['topology'] self.rows = empty_grid(self.v_res + 1, self.u_res) self.start_cap = None self.end_cap = None self.mesh = Mesh() def generate_mesh(self): self.generate_vertices() self.generate_faces() return self.mesh def generate_vertices(self): if self.topology == 'torus': self.generate_torus_vertices() elif self.topology == 'cone': self.generate_cone_vertices() elif self.topology == 'reverse_cone': self.generate_reverse_cone_vertices() elif self.topology == 'cylinder': self.generate_cylinder_vertices() else: raise RuntimeError(f'Not a valid topology: {self.topology}') def generate_torus_vertices(self): for j in range(self.v_res): v = float(j) / (self.v_res) for i in range(self.u_res): u = float(i) / (self.u_res) vertex = self(u, v) idx = self.mesh.add_vertex(vertex) self.rows[j][i] = idx def generate_cone_vertices(self): start_cap = self.coil(0.0) self.start_cap = self.mesh.add_vertex(start_cap) for i in range(self.v_res): v = float(i) / (self.v_res) for j in range(self.u_res): u = float(j) / (self.u_res) vertex = self(u, v) idx = self.mesh.add_vertex(vertex) self.rows[i][j] = idx end_point = self(0.0, 1.0) end_idx = self.mesh.add_vertex(end_point) self.rows[-1][0] = end_idx def generate_reverse_cone_vertices(self): start_point = self(0.0, 0.0) start_idx = self.mesh.add_vertex(start_point) self.rows[0][0] = start_idx for i in range(1, self.v_res + 1): v = float(i) / (self.v_res) for j in range(self.u_res): u = float(j) / (self.u_res) vertex = self(u, v) idx = self.mesh.add_vertex(vertex) self.rows[i][j] = idx end_cap = self.coil(1.0) self.end_cap = self.mesh.add_vertex(end_cap) def generate_cylinder_vertices(self): start_cap = self.coil(0.0) self.start_cap = self.mesh.add_vertex(start_cap) for i in range(self.v_res + 1): v = float(i) / (self.v_res) for j in range(self.u_res): u = float(j) / (self.u_res) vertex = self(u, v) idx = self.mesh.add_vertex(vertex) self.rows[i][j] = idx end_cap = self.coil(1.0) self.end_cap = self.mesh.add_vertex(end_cap) def generate_faces(self): if self.topology == 'torus': self.generate_torus_faces() elif self.topology == 'cone': self.generate_cone_faces() elif self.topology == 'reverse_cone': self.generate_reverse_cone_faces() elif self.topology == 'cylinder': self.generate_cylinder_faces() else: raise RuntimeError(f'Not a valid topology: {self.topology}') def generate_torus_faces(self): for i in range(self.v_res - 1): for j in range(self.u_res - 1): v1 = self.rows[i][j] v2 = self.rows[i][j + 1] v3 = self.rows[i + 1][j + 1] v4 = self.rows[i + 1][j] # This is intentionally clockwise to ensure normals are # pointing outwards self.mesh.add_face([v1, v4, v3]) self.mesh.add_face([v1, v3, v2]) # Fill the seam for i in range(self.v_res - 1): v1 = self.rows[i][-1] v2 = self.rows[i][0] v3 = self.rows[i + 1][0] v4 = self.rows[i + 1][-1] # This is intentionally clockwise to ensure normals are # pointing outwards self.mesh.add_face([v1, v4, v3]) self.mesh.add_face([v1, v3, v2]) # loop the end back to the start for j in range(self.u_res - 1): v1 = self.rows[-2][j] v2 = self.rows[-2][j + 1] v3 = self.rows[0][j + 1] v4 = self.rows[0][j] # This is intentionally clockwise to ensure normals are # pointing outwards self.mesh.add_face([v1, v4, v3]) self.mesh.add_face([v1, v3, v2]) # Add the last quad where the seam meets the loop row v1 = self.rows[-2][-1] v2 = self.rows[-2][0] v3 = self.rows[0][0] v4 = self.rows[0][-1] # This is intentionally clockwise to ensure normals are # pointing outwards self.mesh.add_face([v1, v4, v3]) self.mesh.add_face([v1, v3, v2]) def generate_cone_faces(self): for i in range(self.v_res - 1): for j in range(self.u_res - 1): v1 = self.rows[i][j] v2 = self.rows[i][j + 1] v3 = self.rows[i + 1][j + 1] v4 = self.rows[i + 1][j] # This is intentionally clockwise to ensure normals are # pointing outwards self.mesh.add_face([v1, v4, v3]) self.mesh.add_face([v1, v3, v2]) # Fill the seam for i in range(self.v_res - 1): v1 = self.rows[i][-1] v2 = self.rows[i][0] v3 = self.rows[i + 1][0] v4 = self.rows[i + 1][-1] # This is intentionally clockwise to ensure normals are # pointing outwards self.mesh.add_face([v1, v4, v3]) self.mesh.add_face([v1, v3, v2]) # Add cap at the start end for j in range(self.u_res - 1): v1 = self.rows[0][j] v2 = self.rows[0][j + 1] self.mesh.add_face([self.start_cap, v1, v2]) # start cap seam v1 = self.rows[0][-1] v2 = self.rows[0][0] self.mesh.add_face([self.start_cap, v1, v2]) # End comes to a point for j in range(self.u_res - 1): point = self.rows[-1][0] v1 = self.rows[-2][j] v2 = self.rows[-2][j + 1] self.mesh.add_face([point, v2, v1]) # point seam point = self.rows[-1][0] v1 = self.rows[-2][-1] v2 = self.rows[-2][0] self.mesh.add_face([point, v2, v1]) def generate_reverse_cone_faces(self): for i in range(1, self.v_res): for j in range(self.u_res - 1): v1 = self.rows[i][j] v2 = self.rows[i][j + 1] v3 = self.rows[i + 1][j + 1] v4 = self.rows[i + 1][j] # This is intentionally clockwise to ensure normals are # pointing outwards self.mesh.add_face([v1, v4, v3]) self.mesh.add_face([v1, v3, v2]) # Fill the seam for i in range(1, self.v_res): v1 = self.rows[i][-1] v2 = self.rows[i][0] v3 = self.rows[i + 1][0] v4 = self.rows[i + 1][-1] # This is intentionally clockwise to ensure normals are # pointing outwards self.mesh.add_face([v1, v4, v3]) self.mesh.add_face([v1, v3, v2]) # Add cap at the end for j in range(self.u_res - 1): v1 = self.rows[-1][j] v2 = self.rows[-1][j + 1] self.mesh.add_face([self.end_cap, v2, v1]) # end cap seam v1 = self.rows[-1][-1] v2 = self.rows[-1][0] self.mesh.add_face([self.end_cap, v2, v1]) # start comes to a point for j in range(self.u_res - 1): point = self.rows[0][0] v1 = self.rows[1][j] v2 = self.rows[1][j + 1] self.mesh.add_face([point, v1, v2]) # point seam point = self.rows[0][0] v1 = self.rows[1][-1] v2 = self.rows[1][0] self.mesh.add_face([point, v1, v2]) def generate_cylinder_faces(self): for i in range(self.v_res): for j in range(self.u_res - 1): v1 = self.rows[i][j] v2 = self.rows[i][j + 1] v3 = self.rows[i + 1][j + 1] v4 = self.rows[i + 1][j] # This is intentionally clockwise to ensure normals are # pointing outwards self.mesh.add_face([v1, v4, v3]) self.mesh.add_face([v1, v3, v2]) # Fill the seam for i in range(self.v_res): v1 = self.rows[i][-1] v2 = self.rows[i][0] v3 = self.rows[i + 1][0] v4 = self.rows[i + 1][-1] # This is intentionally clockwise to ensure normals are # pointing outwards self.mesh.add_face([v1, v4, v3]) self.mesh.add_face([v1, v3, v2]) # Add cap at the start end for j in range(self.u_res - 1): v1 = self.rows[0][j] v2 = self.rows[0][j + 1] self.mesh.add_face([self.start_cap, v1, v2]) # start cap seam v1 = self.rows[0][-1] v2 = self.rows[0][0] self.mesh.add_face([self.start_cap, v1, v2]) # end cap for j in range(self.u_res - 1): v1 = self.rows[-1][j] v2 = self.rows[-1][j + 1] self.mesh.add_face([self.end_cap, v2, v1]) # end cap seam v1 = self.rows[-1][-1] v2 = self.rows[-1][0] self.mesh.add_face([self.end_cap, v2, v1]) def __call__(self, u, v): return add_vecs(self.coil(v), self.cross_section(u, v)) def lerp_params(self, param_name, t): [a, b] = self.parameters[param_name] return lerp(a, b, t) def loglerp_params(self, param_name, t): [a, b] = self.parameters[param_name] return loglerp(a, b, t) def coil_shape(self, v): phi = self.lerp_params('coil_angle', v) * 2.0 * math.pi p = self.loglerp_params('coil_p', v) q = self.loglerp_params('coil_q', v) return superellipse(phi, p, q) def coil(self, v): z = self.lerp_params('coil_z', v) b = self.loglerp_params('coil_logarithm', v) R = self.lerp_params('coil_radius', v) radius = R * math.exp(b * v) (shape_x, shape_y) = self.coil_shape(v) return (radius * shape_x, radius * shape_y, z) def cross_section(self, u, v): (shape_x, shape_y) = self.coil_shape(v) (twist_s, twist_z) = self.twisted(u, v) return (twist_s * shape_x, twist_s * shape_y, twist_z) def twisted(self, u, v): m = self.loglerp_params('cross_section_m', v) n = self.loglerp_params('cross_section_n', v) delta = self.lerp_params('cross_section_twist', v) * 2.0 * math.pi r = self.lerp_params('cross_section_radius', v) theta = 2.0 * math.pi * u shape = superellipse(theta, m, n) return scale(rotate(shape, delta), r)
def combine(mesh1, inverted1, mesh2, inverted2, tolerance = 0.000001): class FaceRemoveException(Exception): pass possible_overlaps = list(mesh1.possible_face_collisions(mesh2)) replaced_faces1 = {} replaced_faces2 = {} print "Mesh1", mesh1.vertices print "Mesh2", mesh2.vertices print len(possible_overlaps) n=40 m=300 while possible_overlaps: face1, face2 = possible_overlaps.pop() assert n > 0 assert m > 0 try: if replaced_faces1.has_key(face1): for new_face1 in replaced_faces1[face1]: possible_overlaps.append((new_face1, face2)) raise FaceRemoveException if replaced_faces2.has_key(face2): for new_face in replaced_faces2[face2]: possible_overlaps.append((face1, new_face)) raise FaceRemoveException if face1.normal.cross(face2.normal).magnitude() < tolerance and abs(face1.normal.dot(face1.vertices[0]) - face1.normal.dot(face2.vertices[0])) < tolerance: for vertex1 in face1.vertices: if point_in_face(vertex1, face2, tolerance) and vertex1 not in mesh2.vertices: vertex2 = mesh2.add_vertex(vertex1.x, vertex1.y, vertex1.z) possible_overlaps.append((face1, face2)) #There may be more than one face intersection for this pair of points replaced_faces2[face2] = mesh2.split_face(vertex2, face2) raise FaceRemoveException for vertex2 in face2.vertices: if point_in_face(vertex2, face1, tolerance) and vertex2 not in mesh1.vertices: vertex1 = mesh1.add_vertex(vertex2.x, vertex2.y, vertex2.z) possible_overlaps.append((face1, face2)) #There may be more than one face intersection for this pair of points replaced_faces1[face1] = mesh1.split_face(vertex1, face1) raise FaceRemoveException except FaceRemoveException: m = m - 1 possible_overlaps = list(mesh1.possible_face_collisions(mesh2)) replaced_faces1 = {} replaced_faces2 = {} print "Mesh1", mesh1.vertices print "Mesh2", mesh2.vertices print len(possible_overlaps) fileio.write_ply(mesh1, "/home/martin/m1.ply") fileio.write_ply(mesh2, "/home/martin/m2.ply") n=40 m=300 while possible_overlaps: face1, face2 = possible_overlaps.pop() fileio.write_ply(mesh1, "/home/martin/m1.ply") fileio.write_ply(mesh2, "/home/martin/m2.ply") assert n > 0 assert m > 0 try: if replaced_faces1.has_key(face1): for new_face1 in replaced_faces1[face1]: if replaced_faces2.has_key(face2): for new_face2 in replaced_faces2[face2]: possible_overlaps.append((new_face1, new_face2)) else: possible_overlaps.append((new_face1, face2)) raise FaceRemoveException if replaced_faces2.has_key(face2): for new_face in replaced_faces2[face2]: possible_overlaps.append((face1, new_face)) raise FaceRemoveException if face1.normal.cross(face2.normal).magnitude() < tolerance and abs(face1.normal.dot(face1.vertices[0]) - face1.normal.dot(face2.vertices[0])) < tolerance: for edge1 in face1.edges: for edge2 in face2.edges: try: ip, s1, s2 = line_intersection_and_proportion((edge1.v1, edge1.v2), (edge2.v1, edge2.v2)) #print "Lines Cross?", edge1.v1, edge1.v2, edge2.v1, edge2.v2, ip, s1, s2 if s1 > tolerance and 1-s1 > tolerance and s2 > tolerance and 1- s2 > tolerance: n = n -1 #print "Crossed", edge1, edge2, s1, s2, ip faces1_to_be_replaced = edge1.faces() new_vertex1 = mesh1.add_vertex(ip) new_faces1 = mesh1.split_edge(new_vertex1, edge1) for face1_to_be_replaced in faces1_to_be_replaced: replaced_faces1[face1_to_be_replaced] = new_faces1 faces2_to_be_replaced = edge2.faces() new_vertex2 = mesh2.add_vertex(ip) origvol = mesh2.volume() new_faces2 = mesh2.split_edge(new_vertex2, edge2) if abs(origvol - mesh2.volume()) > tolerance: #print ip, s1, s2 assert False for face2_to_be_replaced in faces2_to_be_replaced: replaced_faces2[face2_to_be_replaced] = new_faces2 print "EDGE SPLIT" raise FaceRemoveException except (ParallelLinesException, LinesDoNotCrossException): pass except FaceRemoveException: m = m - 1 # possible_overlaps = list(mesh1.possible_face_collisions(mesh2)) # replaced_faces1 = {} # replaced_faces2 = {} # while possible_overlaps: # face1, face2 = possible_overlaps.pop() # try: # if replaced_faces1.has_key(face1): # for new_face in replaced_faces1[face1]: # possible_overlaps.append((new_face, face2)) # raise FaceRemoveException # if replaced_faces2.has_key(face2): # for new_face in replaced_faces2[face2]: # possible_overlaps.append((face1, new_face)) # raise FaceRemoveException # for edge1 in face1.edges: # for edge2 in face2.edges: # try: # ip, s1, s2 = line_intersection_and_proportion((edge1.v1, edge1.v2), (edge2.v1, edge2.v2)) # if s1 > tolerance and 1-s1 > tolerance and s2 > tolerance and 1-s2 > tolerance: # print edge1, edge2, s1, s2 # faces1_to_be_replaced = edge1.faces() # new_vertex1 = mesh1.add_vertex(ip) # new_faces1 = mesh1.split_edge(new_vertex1, edge1) # for face1_to_be_replaced in faces1_to_be_replaced: # replaced_faces1[face1_to_be_replaced] = new_faces1 # faces2_to_be_replaced = edge2.faces() # new_vertex2 = mesh2.add_vertex(ip) # new_faces2 = mesh2.split_edge(new_vertex2, edge2) # for face2_to_be_replaced in faces2_to_be_replaced: # replaced_faces2[face2_to_be_replaced] = new_faces2 # raise FaceRemoveException # except ValueError: # pass # except FaceRemoveException: # pass #fileio.write_stl(mesh1, "/home/martin/m1.ply") #fileio.write_stl(mesh2, "/home/martin/m2.ply") print "M1V", mesh1.vertices print "M1V", mesh1.vertices print "M1F", len(mesh1.faces) print "M2F", len(mesh2.faces) print "M1Vol", mesh1.volume()#Check mesh is closed print "M2Vol", mesh2.volume()#Check mesh is closed m = Mesh() vertex1_map = {} for v in mesh1.vertices: new_vertex = m.get_vertex(v) if new_vertex is None: #Vertex does not exist new_vertex = m.add_vertex(v.x, v.y, v.z) vertex1_map[v] = new_vertex for face in mesh1.faces: vertices = [vertex1_map[vertex] for vertex in face.vertices] if mesh2.contains_point(face.centroid() + face.normal * tolerance * {True: -1, False: 1}[inverted1]) != (not inverted2): if inverted1: m.add_triangle_face(vertices[0], vertices[2], vertices[1]) else: m.add_triangle_face(vertices[0], vertices[1], vertices[2]) vertex2_map = {} for v in mesh2.vertices: new_vertex = m.get_vertex(v) #print "?", m.get_vertex(v), m.get_vertex(v.x, v.y, v.z), v.x, v.y, v.z if new_vertex is None: #Vertex does not exist #print "Adding" new_vertex = m.add_vertex(v.x, v.y, v.z) #print "added" vertex2_map[v] = new_vertex edge_splits = {} for face in mesh2.faces: vertices = [vertex2_map[vertex] for vertex in face.vertices] if mesh1.contains_point(face.centroid() + face.normal * tolerance * {True: -1, False: 1}[inverted2]) != (not inverted1): if inverted2: add_splits_and_face(m, vertices[0], vertices[2], vertices[1], edge_splits) else: add_splits_and_face(m, vertices[0], vertices[1], vertices[2], edge_splits) #clean up verticies m.clean() fileio.write_ply(m, "/home/martin/m3.ply") return m
def combine(mesh1, inverted1, mesh2, inverted2, tolerance=0.000001): class FaceRemoveException(Exception): pass possible_overlaps = list(mesh1.possible_face_collisions(mesh2)) replaced_faces1 = {} replaced_faces2 = {} print "Mesh1", mesh1.vertices print "Mesh2", mesh2.vertices print len(possible_overlaps) n = 40 m = 300 while possible_overlaps: face1, face2 = possible_overlaps.pop() assert n > 0 assert m > 0 try: if replaced_faces1.has_key(face1): for new_face1 in replaced_faces1[face1]: possible_overlaps.append((new_face1, face2)) raise FaceRemoveException if replaced_faces2.has_key(face2): for new_face in replaced_faces2[face2]: possible_overlaps.append((face1, new_face)) raise FaceRemoveException if face1.normal.cross( face2.normal).magnitude() < tolerance and abs( face1.normal.dot(face1.vertices[0]) - face1.normal.dot(face2.vertices[0])) < tolerance: for vertex1 in face1.vertices: if point_in_face( vertex1, face2, tolerance) and vertex1 not in mesh2.vertices: vertex2 = mesh2.add_vertex(vertex1.x, vertex1.y, vertex1.z) possible_overlaps.append( (face1, face2) ) #There may be more than one face intersection for this pair of points replaced_faces2[face2] = mesh2.split_face( vertex2, face2) raise FaceRemoveException for vertex2 in face2.vertices: if point_in_face( vertex2, face1, tolerance) and vertex2 not in mesh1.vertices: vertex1 = mesh1.add_vertex(vertex2.x, vertex2.y, vertex2.z) possible_overlaps.append( (face1, face2) ) #There may be more than one face intersection for this pair of points replaced_faces1[face1] = mesh1.split_face( vertex1, face1) raise FaceRemoveException except FaceRemoveException: m = m - 1 possible_overlaps = list(mesh1.possible_face_collisions(mesh2)) replaced_faces1 = {} replaced_faces2 = {} print "Mesh1", mesh1.vertices print "Mesh2", mesh2.vertices print len(possible_overlaps) fileio.write_ply(mesh1, "/home/martin/m1.ply") fileio.write_ply(mesh2, "/home/martin/m2.ply") n = 40 m = 300 while possible_overlaps: face1, face2 = possible_overlaps.pop() fileio.write_ply(mesh1, "/home/martin/m1.ply") fileio.write_ply(mesh2, "/home/martin/m2.ply") assert n > 0 assert m > 0 try: if replaced_faces1.has_key(face1): for new_face1 in replaced_faces1[face1]: if replaced_faces2.has_key(face2): for new_face2 in replaced_faces2[face2]: possible_overlaps.append((new_face1, new_face2)) else: possible_overlaps.append((new_face1, face2)) raise FaceRemoveException if replaced_faces2.has_key(face2): for new_face in replaced_faces2[face2]: possible_overlaps.append((face1, new_face)) raise FaceRemoveException if face1.normal.cross( face2.normal).magnitude() < tolerance and abs( face1.normal.dot(face1.vertices[0]) - face1.normal.dot(face2.vertices[0])) < tolerance: for edge1 in face1.edges: for edge2 in face2.edges: try: ip, s1, s2 = line_intersection_and_proportion( (edge1.v1, edge1.v2), (edge2.v1, edge2.v2)) #print "Lines Cross?", edge1.v1, edge1.v2, edge2.v1, edge2.v2, ip, s1, s2 if s1 > tolerance and 1 - s1 > tolerance and s2 > tolerance and 1 - s2 > tolerance: n = n - 1 #print "Crossed", edge1, edge2, s1, s2, ip faces1_to_be_replaced = edge1.faces() new_vertex1 = mesh1.add_vertex(ip) new_faces1 = mesh1.split_edge( new_vertex1, edge1) for face1_to_be_replaced in faces1_to_be_replaced: replaced_faces1[ face1_to_be_replaced] = new_faces1 faces2_to_be_replaced = edge2.faces() new_vertex2 = mesh2.add_vertex(ip) origvol = mesh2.volume() new_faces2 = mesh2.split_edge( new_vertex2, edge2) if abs(origvol - mesh2.volume()) > tolerance: #print ip, s1, s2 assert False for face2_to_be_replaced in faces2_to_be_replaced: replaced_faces2[ face2_to_be_replaced] = new_faces2 print "EDGE SPLIT" raise FaceRemoveException except (ParallelLinesException, LinesDoNotCrossException): pass except FaceRemoveException: m = m - 1 # possible_overlaps = list(mesh1.possible_face_collisions(mesh2)) # replaced_faces1 = {} # replaced_faces2 = {} # while possible_overlaps: # face1, face2 = possible_overlaps.pop() # try: # if replaced_faces1.has_key(face1): # for new_face in replaced_faces1[face1]: # possible_overlaps.append((new_face, face2)) # raise FaceRemoveException # if replaced_faces2.has_key(face2): # for new_face in replaced_faces2[face2]: # possible_overlaps.append((face1, new_face)) # raise FaceRemoveException # for edge1 in face1.edges: # for edge2 in face2.edges: # try: # ip, s1, s2 = line_intersection_and_proportion((edge1.v1, edge1.v2), (edge2.v1, edge2.v2)) # if s1 > tolerance and 1-s1 > tolerance and s2 > tolerance and 1-s2 > tolerance: # print edge1, edge2, s1, s2 # faces1_to_be_replaced = edge1.faces() # new_vertex1 = mesh1.add_vertex(ip) # new_faces1 = mesh1.split_edge(new_vertex1, edge1) # for face1_to_be_replaced in faces1_to_be_replaced: # replaced_faces1[face1_to_be_replaced] = new_faces1 # faces2_to_be_replaced = edge2.faces() # new_vertex2 = mesh2.add_vertex(ip) # new_faces2 = mesh2.split_edge(new_vertex2, edge2) # for face2_to_be_replaced in faces2_to_be_replaced: # replaced_faces2[face2_to_be_replaced] = new_faces2 # raise FaceRemoveException # except ValueError: # pass # except FaceRemoveException: # pass #fileio.write_stl(mesh1, "/home/martin/m1.ply") #fileio.write_stl(mesh2, "/home/martin/m2.ply") print "M1V", mesh1.vertices print "M1V", mesh1.vertices print "M1F", len(mesh1.faces) print "M2F", len(mesh2.faces) print "M1Vol", mesh1.volume() #Check mesh is closed print "M2Vol", mesh2.volume() #Check mesh is closed m = Mesh() vertex1_map = {} for v in mesh1.vertices: new_vertex = m.get_vertex(v) if new_vertex is None: #Vertex does not exist new_vertex = m.add_vertex(v.x, v.y, v.z) vertex1_map[v] = new_vertex for face in mesh1.faces: vertices = [vertex1_map[vertex] for vertex in face.vertices] if mesh2.contains_point(face.centroid() + face.normal * tolerance * { True: -1, False: 1 }[inverted1]) != (not inverted2): if inverted1: m.add_triangle_face(vertices[0], vertices[2], vertices[1]) else: m.add_triangle_face(vertices[0], vertices[1], vertices[2]) vertex2_map = {} for v in mesh2.vertices: new_vertex = m.get_vertex(v) #print "?", m.get_vertex(v), m.get_vertex(v.x, v.y, v.z), v.x, v.y, v.z if new_vertex is None: #Vertex does not exist #print "Adding" new_vertex = m.add_vertex(v.x, v.y, v.z) #print "added" vertex2_map[v] = new_vertex edge_splits = {} for face in mesh2.faces: vertices = [vertex2_map[vertex] for vertex in face.vertices] if mesh1.contains_point(face.centroid() + face.normal * tolerance * { True: -1, False: 1 }[inverted2]) != (not inverted1): if inverted2: add_splits_and_face(m, vertices[0], vertices[2], vertices[1], edge_splits) else: add_splits_and_face(m, vertices[0], vertices[1], vertices[2], edge_splits) #clean up verticies m.clean() fileio.write_ply(m, "/home/martin/m3.ply") return m