diff options
Diffstat (limited to 'geometry.py')
-rw-r--r-- | geometry.py | 126 |
1 files changed, 40 insertions, 86 deletions
diff --git a/geometry.py b/geometry.py index f50fe89..d1bec2a 100644 --- a/geometry.py +++ b/geometry.py @@ -48,103 +48,57 @@ def morton_order(mesh, bits): return interleave(mean_positions, bits) -class Solid(object): - """ - Object which stores a closed triangle mesh associated with a physically - distinct object. - - Args: - - mesh, array - A closed triangle mesh. - - material1, Material - The material inside within the mesh. - - material2, Material - The material outside the mesh. - - surface1, Surface, - The surface on the inside of the mesh. - - surface2, Surface, - The surface on the outside of the mesh. - - .. warning:: - It is possible to define logically inconsistent geometries unless - you are careful. For example, solid A may define its inside material - as water but contain solid B which defines its outside material as air. - In this case, a photon traveling out of solid B will reflect/refract - assuming it's going into air, but upon reaching solid A's boundary will - calculate attenuation factors assuming it just traveled through water. - """ - def __init__(self, mesh, material1, material2, \ - surface1=None, surface2=None): - if len(mesh.shape) != 3 or mesh.shape[1] != 3 or mesh.shape[2] != 3: - raise Exception('shape mismatch; mesh must be a triangle mesh') +class Geometry(object): + def __init__(self, solids=[]): + self.solids = solids - self.mesh = mesh - self.material1 = material1 - self.material2 = material2 - self.surface1 = surface1 - self.surface2 = surface2 + def add_solid(self, solid): + self.solids.append(solid) - def __len__(self): - return self.mesh.shape[0] + def build(self, bits=8): + self.mesh = np.concatenate([solid.build() for solid in self.solids]) -class Geometry(object): - """Object which stores the global mesh for a geometry.""" + zvalues_mesh = morton_order(self.mesh, bits) + reorder = np.argsort(zvalues_mesh) + zvalues_mesh = zvalues_mesh[reorder] - def __init__(self): - self.solids = [] - self.materials = [] - self.surfaces = [] + if (np.diff(zvalues_mesh) < 0).any(): + raise Exception('zvalues_mesh out of order.') - def add_solid(self, solid): - """Add a solid to the geometry.""" - self.solids.append(solid) + self.mesh = self.mesh[reorder] - if solid.material1 not in self.materials: - self.materials.append(solid.material1) + material1 = np.concatenate([solid.material1 for solid in self.solids]) + material2 = np.concatenate([solid.material2 for solid in self.solids]) + + self.materials = \ + list(np.unique(np.concatenate([material1, material2]))) - if solid.material2 not in self.materials: - self.materials.append(solid.material2) + self.material1_index = np.empty(len(self.mesh), dtype=np.uint32) + self.material2_index = np.empty(len(self.mesh), dtype=np.uint32) - if solid.surface1 not in self.surfaces: - self.surfaces.append(solid.surface1) + for i, material in enumerate(material1[reorder]): + self.material1_index[i] = self.materials.index(material) - if solid.surface2 not in self.surfaces: - self.surfaces.append(solid.surface1) + for i, material in enumerate(material2[reorder]): + self.material2_index[i] = self.materials.index(material) - def build(self, bits=8): - """Build the bounding volume hierarchy of the geometry.""" - mesh = np.concatenate([solid.mesh for solid in self.solids]) - - # lookup solid/material/surface index from triangle index - solid_index = \ - np.concatenate([np.tile(self.solids.index(solid), \ - len(solid)) for solid in self.solids]) - material1_index = \ - np.concatenate([np.tile(self.materials.index(solid.material1), \ - len(solid)) for solid in self.solids]) - material2_index = \ - np.concatenate([np.tile(self.materials.index(solid.material2), \ - len(solid)) for solid in self.solids]) - surface1_index = \ - np.concatenate([np.tile(self.surfaces.index(solid.surface1), \ - len(solid)) for solid in self.solids]) - surface2_index = \ - np.concatenate([np.tile(self.surfaces.index(solid.surface2), \ - len(solid)) for solid in self.solids]) - - zvalues_mesh = morton_order(mesh, bits) - reorder = np.argsort(zvalues_mesh) - zvalues_mesh = zvalues_mesh[reorder] + surface1 = np.concatenate([solid.surface1 for solid in self.solids]) + surface2 = np.concatenate([solid.surface2 for solid in self.solids]) - if (np.diff(zvalues_mesh) < 0).any(): - raise Exception('zvalues_mesh out of order') - - self.mesh = mesh[reorder] - self.solid_index = solid_index[reorder] - self.material1_index = material1_index[reorder] - self.material2_index = material2_index[reorder] - self.surface1_index = surface1_index[reorder] - self.surface2_index = surface2_index[reorder] + self.surfaces = list(np.unique(np.concatenate([surface1, surface2]))) + + self.surface1_index = np.empty(len(self.mesh), dtype=np.uint32) + self.surface2_index = np.empty(len(self.mesh), dtype=np.uint32) + + for i, surface in enumerate(surface1[reorder]): + self.surface1_index[i] = self.surfaces.index(surface) + + for i, surface in enumerate(surface2[reorder]): + self.surface2_index[i] = self.surfaces.index(surface) + + self.solid_index = \ + np.concatenate([np.tile(i, len(solid.mesh)) \ + for i in range(len(self.solids))])[reorder] unique_zvalues = np.unique(zvalues_mesh) zvalues = np.empty(unique_zvalues.size, dtype=np.uint64) |