def test_zyx_ordering(self): m = mesh.Mesh((3, 1, 1), cellsize=(1, 1, 1)) indices = [r for r in m.iter_coords_int()] expected = [[0, 0, 0], [1, 0, 0], [2, 0, 0]] assert np.array_equal(m.mesh_size, [3, 1, 1]) assert m.array_order == mesh.Mesh.ZYX assert np.array_equal(expected, indices) m = mesh.Mesh((2, 2, 2), cellsize=(1, 1, 1)) indices = [r for r in m.iter_coords_int()] expected = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]] assert np.array_equal(m.mesh_size, [2, 2, 2]) assert m.array_order == mesh.Mesh.ZYX assert np.array_equal(expected, indices)
def parse_2_object(self, obj): a, name, winged, mode = obj self.check_atom(a, "object") # if mode is invisible, skip this a, raw_edges, raw_faces, raw_verts, raw_edge_htable = winged self.check_atom(a, "winged") print "reading object '%s' (%d faces, %d edges, %d vertices)" % (name, len(raw_faces), len(raw_edges), len(raw_verts)) # raw_edge_htable lists hard edges # (edges are soft by default, so this table may be empty, thus None) if raw_edge_htable == None: raw_edge_htable = [] if type(raw_edge_htable) == types.StringType: raw_edge_htable = map(ord, raw_edge_htable) #print raw_edge_htable wobj = mesh.Mesh() wobj.materials = self.materials wobj.name = name self.parse_2_edges(wobj, raw_edges, raw_edge_htable) self.parse_2_faces(wobj, raw_faces) self.parse_2_verts(wobj, raw_verts) return wobj
def load_mesh(self, filename): self.mesh = mesh.Mesh(filename) # TODO: Change bpoints. self.mesh.translate(np.float32([20, 20, 0])) position = self.mesh.bpoint1 # Rename to position size = self.mesh.bpoint2 - self.mesh.bpoint1 # Change by size print np.vstack(self.mesh.triangles)
def convert_binary_image_to_mesh(self, binary_img, extrusion = 1000, min_dim = 5): ''' Converts a binary image in file "filename" to a mesh Params: binary_img: (2d numpy arry) binary image for silhouette (255 = occupied, 0 = not occupied) Returns: mesh object with specified depth bool, whether or not triangulation was successful (since it doesn't work for certain topologies) ''' # get occupied indices from binary image binary_map = np.array(binary_img) occ_ind = np.where(binary_map > self.occupied_thresh_) occ_coords = zip(occ_ind[0], occ_ind[1]) # todo: duplicate at multiple depths front_verts, front_tris, front_ind_map = self.create_mesh_face(occ_coords, extrusion / 2, binary_map.shape, cw = True) back_verts, back_tris, back_ind_map = self.create_mesh_face(occ_coords, -extrusion / 2, binary_map.shape, cw = False) verts, tris = self.join_vert_tri_lists(front_verts, front_tris, back_verts, back_tris) num_verts = len(front_verts) back_ind_map = back_ind_map + num_verts # todo: connect boundaries boundary_img = self.find_boundary(binary_img) success = self.add_boundary_tris(boundary_img, verts, tris, front_ind_map, back_ind_map) # convert to mesh and return m = mesh.Mesh(verts, tris) unreffed_success = m.remove_unreferenced_vertices() succcess = success and unreffed_success coord_conversion = m.image_to_3d_coords() success = success and coord_conversion # m.normalize_vertices() # m.rescale_vertices(min_dim) return m, success
def test_cylinder_volumes(self): for (r, h, n) in [(10, 100, 100), (10, 100, 250)]: m = mesh.Mesh() mesh.primitives.add_cylinder(m, r, h, n) self.assertAlmostEqual(m.volume(), self.expected_cylinder_volume(r, h, n), places=-2)
def test_render_small_square(self): small_square = (' \n' ' \n' ' \n' ' WW \n' ' WW \n' ' \n' ' \n' ' \n' ' \n' ' ') terminal_width, terminal_height = 10, 10 vertex_tuples = [ (0, 0, 5), (2, 0, 5), (2, 2, 5), (0, 2, 5), ] face = mesh.Face.covering_tuples(*vertex_tuples) test_mesh = mesh.Mesh( [mesh.Point3D.from_tuple(p) for p in vertex_tuples], [face]) self.maxDiff = None # These strings are large; we want to see the whole diff if the test fails. self.assertEqual( small_square, test_utils.render_to_string(test_mesh, terminal_width, terminal_height))
def test_something_not_closed(self): m = mesh.Mesh() v1 = m.add_vertex(0, 0, 0) v2 = m.add_vertex(10, 0, 0) v3 = m.add_vertex(0, 10, 0) m.add_face(v1, v2, v3) self.assertFalse(m.closed())
def test_cylinder2_area(self): m = mesh.Mesh() r, h, n = 10, 100, 100 mesh.primitives.add_cylinder(m, r, h, n) self.assertAlmostEqual(m.surface_area(), self.expected_cylinder_area(r, h, n), places=4)
def mesh_from_obj_file(file) -> mesh.Mesh: """ Parse a .obj file (https://en.wikipedia.org/wiki/Wavefront_.obj_file) into a Mesh. """ vertices: List[mesh.Point3D] = [] faces: List[mesh.Face] = [] for line in file: line = line.strip() if line.startswith(VERTEX_PREFIX): if faces: raise Exception( f'''A properly formatted .obj file declares all vertices before faces, but faces had length {len(faces)} as we read in line {line}.''') # Eat the 'v' token since we now know this is a vertex. vertex = _parse_vertex(line.replace(VERTEX_PREFIX, '')) vertices.append(vertex) if line.startswith(FACE_PREFIX): # Eat the 'f' token since we now know this is a face. face = _parse_face(vertices, line.replace(FACE_PREFIX, '')) faces.append(face) return mesh.Mesh(vertices, faces)
def test_cylinder_centroids(self): for (r, h, n) in [(10, 100, 50)]: m = mesh.Mesh() mesh.primitives.add_cylinder(m, r, h, n) v = mesh.Vector(0, 0, h / 2) self.assertAlmostEqualVector(m.solid_centroid(), v) self.assertAlmostEqualVector(m.surface_centroid(), v)
def test_sphere_volume(self): r = 0.8 for model in ["icosa", "octa"]: m = mesh.Mesh() mesh.primitives.add_sphere(m, r, model=model, detail_level=25) self.assertAlmostEqual(m.volume(), self.expected_sphere_volume(r), places=1)
def test_cube_centroids(self): m = mesh.Mesh() mesh.primitives.add_cube(m, 100) centroid0 = mesh.Vector(50.0, 50.0, 50.0) centroid1 = m.solid_centroid() centroid2 = m.surface_centroid() self.assertAlmostEqualVector(centroid1, centroid0) self.assertAlmostEqualVector(centroid2, centroid0)
def test_mesh_comm(): namelist_dict = {} test_mesh = mesh.Mesh(namelist_dict) assert test_mesh.comm.rank == 0 assert test_mesh.comm.size == 1 return
def render_view(self, savepath, xy_centre=None, ground_height=None, keep_obj=False, actually_render=True, flip=False): ''' render a single view of a voxel grid, using blender... ground height is in meters ''' temp = self.copy() # put in a ground plane... if ground_height: height_voxels = float(ground_height) / float(temp.vox_size) temp.V[:, :, :height_voxels] = -10 temp_slice = temp.V[:, :, height_voxels] temp_slice[np.isnan(temp_slice)] = 10 temp.V[:, :, height_voxels] = temp_slice #pickle.dump(self, open('/tmp/temp_voxel_grid.pkl', 'w'), protocol=pickle.HIGHEST_PROTOCOL) print "Generating mesh...", sys.stdout.flush() ms = mesh.Mesh() ms.from_volume(temp, 0) #pickle.dump(ms, open('/tmp/temp_mesh.pkl', 'w'), protocol=pickle.HIGHEST_PROTOCOL) ms.remove_nan_vertices() if xy_centre: cen = temp.origin + (np.array(temp.V.shape) * temp.vox_size) / 2.0 ms.vertices[:, :2] -= cen[:2] ms.vertices[:, 2] -= 0.05 if flip: ms.vertices[:, 0] *= -1 print "Writing to obj...", sys.stdout.flush() ms.write_to_obj(savepath + '.obj') print "Rendering...", if actually_render: sys.stdout.flush() blend_path = os.path.expanduser('~/projects/shape_sharing/src/rendered_scenes/spinaround/spin.blend') blend_py_path = os.path.expanduser('~/projects/shape_sharing/src/rendered_scenes/spinaround/blender_spinaround_frame.py') subenv = os.environ.copy() subenv['BLENDERSAVEFILE'] = savepath sp.call(['blender', blend_path, "-b", "-P", blend_py_path], env=subenv, stdout=open(os.devnull, 'w'), close_fds=True) print "Done rendering...", sys.stdout.flush() if not keep_obj: os.remove(savepath + '.obj')
def import_files(): j = 0 reader = mesh.fileio.PlyReader() for name, filename in ply_files.items(): m = mesh.Mesh() for i in reader.read_part(m, filename): yield int((i + j*10)/len(ply_files)) m.ensure_fresh_octrees() self.meshController.addMesh(m, name, clear=(j==0), reset=True) # clear when adding first mesh j += 1
def test_sphere_centroids(self): m = mesh.Mesh() v = mesh.Vector(23, 45, 67) mesh.primitives.add_sphere(m, 2.0, origin=v, model="octa", detail_level=3) self.assertAlmostEqualVector(m.solid_centroid(), v) self.assertAlmostEqualVector(m.surface_centroid(), v)
def read(self): ''' Read in the vertex, normal, and face lists to form a mesh. Technically this should also read in a texture but right now we don't support it ''' numVerts = 0 verts = [] norms = None faces = [] tex_coords = [] face_norms = [] f = open(self.filepath_, 'r') for line in f: # break up the line by whitespace vals = line.split() if len(vals) > 0: # look for obj tags (see http://en.wikipedia.org/wiki/Wavefront_.obj_file) if vals[0] == 'v': # add vertex v = map(float, vals[1:4]) verts.append(v) if vals[0] == 'vn': # add normal if norms is None: norms = [] n = map(float, vals[1:4]) norms.append(n) if vals[0] == 'f': # add faces (includes vertex indices, texture coordinates, and normals) vi = [] vti = [] nti = [] if vals[1].find('/') == -1: vi = map(int, vals[1:]) vi = [i - 1 for i in vi] else: for j in range(1, len(vals)): # break up like by / to read vert inds, tex coords, and normal inds val = vals[j] tokens = val.split('/') for i in range(len(tokens)): if i == 0: vi.append(int(tokens[i]) - 1) # adjust for python 0 - indexing elif i == 1: if tokens[i] != '': vti.append(int(tokens[i])) elif i == 2: nti.append(int(tokens[i])) faces.append(vi) # below two lists are currently not in use tex_coords.append(vti) face_norms.append(nti) return mesh.Mesh(verts, faces, norms)
def test_mesh_cuts_sticking_around(self): remove_objects() jMesh = mesh.make_cube_mesh() selection0 = meshLoad.MeshGetter().getRandMesh() #only one mesh to get self.assertTrue(selection0.UserDictionary.ContainsKey(jMesh.cut_key)) jMesh = mesh.Mesh(selection0) correct_cuts = [1, 2, 3] jMesh.set_cuts(correct_cuts) second_mesh = meshLoad.MeshGetter().getRandMesh() item = list(second_mesh.UserDictionary[jMesh.cut_key]) self.assertEqual(correct_cuts, item)
def main(): length = 1.0 nb_element = 5 geometry = mesh.Mesh(length, nb_element) x = geometry.mesh["coordinates"][:, 0] linear_shape_function(x) x2 = lambda x: x print(integrate.quad(x2, 0, 1)) print(misc.derivative(x2, 0))
def mesh_from_small_tuples( vertex_tuples: List[Tuple[int, int, int]]) -> mesh.Mesh: """ Constructs a mesh containing with the provided tuples as vertices and a single face which includes all its vertices """ scale_factor = 1_000_000 scaled_vertices = [(t[0] * scale_factor, t[1] * scale_factor, t[2] * scale_factor) for t in vertex_tuples] face = mesh.Face.covering_tuples(*scaled_vertices) return mesh.Mesh([mesh.Point3D.from_tuple(p) for p in scaled_vertices], [face])
def parse_2(self): scene = mesh.Mesh() scene.name = "wings_object" self.materials = scene.materials self.mat_images = {} for raw_mat in self.raw_materials: wmat = self.parse_2_material(raw_mat) scene.materials.append(wmat) self.parse_2_images() for raw_obj in self.raw_objects: wobj = self.parse_2_object(raw_obj) scene.merge(wobj) self.postprocess(scene) return scene
def __init__(self, render, raw_mesh): self.mesh = mesh.Mesh(raw_mesh['obj_path']) if 'texture_path' in raw_mesh: self.texture = render.LoadMeshTexture(raw_mesh['texture_path']) else: self.texture = render.white_texture self.center = tuple(map(float, raw_mesh['center'])) if 'scale' in raw_mesh: self.scale = tuple(map(float, raw_mesh['scale'])) else: self.scale = (1, 1, 1) if 'angle' in raw_mesh: self.angle = float(raw_mesh['angle']) else: self.angle = 0
def mesh_cap(self, offset=0, dir=1, ignore_wind=False): points = join_points_3D(*self.paths) if ignore_wind: triangles = filter( lambda t: abs(self.winding_number(points[t].mean(0))) > offset, spatial.Delaunay(points[:, :2]).vertices) else: triangles = filter( lambda t: self.winding_number(points[t].mean(0)) > offset, spatial.Delaunay(points[:, :2]).vertices) m = mesh.Mesh(points, triangles) m.force_z_normal(dir) return m
def parse_f(self, args): if (len(self.tex_coords) > 1) and (len(self.normals) == 1): # does the spec allow for texture coordinates without normals? # if we allow this condition, the user will get a black screen # which is really confusing raise PywavefrontException( 'Found texture coordinates, but no normals') if self.mesh is None: self.mesh = mesh.Mesh() self.wavefront.add_mesh(self.mesh) if self.material is None: self.material = material.Material() self.mesh.add_material(self.material) # For fan triangulation, remember first and latest vertices v1 = None vlast = None points = [] for i, v in enumerate(args[0:]): if type(v) is bytes: v = v.decode() v_index, t_index, n_index = \ (list(map(int, [j or 0 for j in v.split('/')])) + [0, 0])[:3] if v_index < 0: v_index += len(self.vertices) - 1 if t_index < 0: t_index += len(self.tex_coords) - 1 if n_index < 0: n_index += len(self.normals) - 1 vertex = list(self.tex_coords[t_index]) + \ list(self.normals[n_index]) + \ list(self.vertices[v_index]) if i >= 3: # Triangulate self.material.vertices += v1 + vlast self.material.vertices += vertex if i == 0: v1 = vertex vlast = vertex
def testStationaryBin(self): '''Create a simple test grid that shows how a stationary point (reversal bin) should be added to a mesh.''' f = open('teststat.mesh', 'w') f.write('xxx\n') # first line doesn't matter any more f.write('1e-3\n') # some made up resolution f.write('-3. -3. -2.5 -1. 1. 2.5 3. 3. \n') f.write(' 0. 1. 2. 3. 3. 2. 1. 0. \n') f.write('-2. -2. -1.5 -1. 1. 1.5 2. 2.\n') f.write(' 0. 1. 2. 2. 2. 2. 1. 0.\n') f.close() m = mesh.Mesh('teststat.mesh') # this is a mesh where a stationary cell is entered q = mesh.Quadrilateral([-1., -1., 1., 1.], [0., 0.5, 0.5, 0.]) m.insert_stationary(q) # it is legal to enter more than one stationary cell q2 = mesh.Quadrilateral([-1., -1., 1., 1.], [0.5, 1.0, 1.0, 0.5]) m.insert_stationary(q2) mesh.display_mesh(m, m.dimensions(), label=True)
def testBlockedGrid(self): '''Test a grid that is built of two group of cells that are not necessarily related. The two block are split by a single line containing the string 'closed\n'. ''' f = open('blocktest.mesh', 'w') f.write('xxx\n') # first line doesn't matter any more f.write('1e-3\n') # some made up resolution f.write(' 0. 1. 2. \n') f.write(' 0. 0. 0. \n') f.write(' 0. 1. 2. 3.\n') f.write(' 1. 1. 1. 1.\n') f.write(' 0. 1. 2. 3.\n') f.write(' 2. 2. 2. 2.\n') f.write('closed\n') f.write(' 0. 1.\n') f.write(' 3. 3.\n') f.write(' 0. 1.\n') f.write(' 4. 4.\n') f.close() m = mesh.Mesh('blocktest.mesh') mesh.display_mesh(m, m.dimensions(), True)
def parseModel(filename): model = model.Model() mesh_cnt = 0 file = open(filename,"r") lines = file.readlines() index = [] vertex = [] normal = [] texture = [] finalizing = False for line in lines: line_split = line.rstrip("\n").split(" ") if (len(line_split) > 0): if (line_split[0] == 'o'): # New Mesh mesh_cnt += 1 elif (line_split[0] == 'v'): vertex.append([float(line_split[1])/200,float(line_split[2])/200,float(line_split[3])/200]) elif (line_split[0] == 'vn'): normal.append([float(line_split[1]),float(line_split[2]),float(line_split[3])]) elif (line_split[0] == 'vt'): texture.append([float(line_split[1]),float(line_split[2])]) elif (line_split[0] == 'f'): finalizing = True index.append([line_split[1],line_split[2],line_split[3]]) elif(finalizing): buffer, index_buffer = processArray(index,vertex,normal,texture) index = [] vertex = [] normal = [] texture = [] finalizing = False new_mesh = mesh.Mesh(buffer, index_buffer) model.addMesh(new_mesh) return model
import mesh import numpy as np import scipy.sparse from scipy.sparse.linalg import lsmr m = mesh.Mesh("input-face.obj") # load mesh A = scipy.sparse.lil_matrix( (2 * m.ntriangles + 4, 2 * m.nverts)) # the variables are packed as u0,v0,u1,v1, ... lock1, lock2 = 10324 % m.nverts, 35492 % m.nverts # select two arbitrary vertices to pin for (t, [i, j, k]) in enumerate(m.T): # for each triangle ijk [eij, ejk, eki] = mesh.project_triangle( m.V[i], m.V[j], m.V[k]) # project the triangle to a local 2d basis A[t * 2 + 0, i * 2] = ejk[0] # (grad u)[0] = (grad v)[1] A[t * 2 + 0, j * 2] = eki[0] A[t * 2 + 0, k * 2] = eij[0] A[t * 2 + 0, i * 2 + 1] = ejk[1] A[t * 2 + 0, j * 2 + 1] = eki[1] A[t * 2 + 0, k * 2 + 1] = eij[1] A[t * 2 + 1, i * 2] = ejk[1] # (grad u)[1] = -(grad v)[0] A[t * 2 + 1, j * 2] = eki[1] A[t * 2 + 1, k * 2] = eij[1] A[t * 2 + 1, i * 2 + 1] = -ejk[0] A[t * 2 + 1, j * 2 + 1] = -eki[0] A[t * 2 + 1, k * 2 + 1] = -eij[0] A[-1, lock2 * 2 + 1] = A[-2, lock2 * 2 + 0] = A[-3, lock1 * 2 + 1] = A[-4, lock1 * 2 + 0] = 10 # quadratic penalty A = A.tocsr( ) # convert to compressed sparse row format for faster matrix-vector muliplications
files = problem['materials'], tr_scatt = problem['tr_scatt']) except KeyError: MAT_LIB = material.mat_lib(n_grps = problem['groups'], files = problem['materials']) # Build Material Mapping MAT_MAP = material.mat_map(lib = MAT_LIB, layout = problem['layout'], layout_dict = problem['layout_dict'], x_max=problem['domain_upper'], n=problem['mesh_cells']) # Build Mesh MESH = mesh.Mesh(problem['mesh_cells'], problem['domain_upper'], MAT_MAP) def run(): # do we do NDA do_nda = problem['do_nda'] # Eigen class construction eigen_cls = Eigen() # construct HO solver ho_cls = SAAF(mat_cls=MAT_LIB, mesh_cls=MESH, prob_dict=problem) if not do_nda: # eigen solving eigen_cls.do_iterations(ho_cls=ho_cls, nda_cls=None) else: # construct NDA solver nda_cls = NDA(mat_cls=MAT_LIB, mesh_cls=MESH, prob_dict=problem) # eigen solving
import igl import solver import constraint import transform import open3d as o3d import mesh as m cons = constraint.Constraint() cons.add_constraint(0, [0, 0, 0]) # slvr = solver.Sovler() if __name__ == "__main__": V, F = igl.read_triangle_mesh("cube.obj") mesh = m.Mesh(V, F) slvr = solver.Sovler(mesh, cons) slvr.precompute() V, F = slvr.solve() igl.write_obj("cube_remake", V, F)