summaryrefslogtreecommitdiff
path: root/geometry.py
diff options
context:
space:
mode:
Diffstat (limited to 'geometry.py')
-rw-r--r--geometry.py126
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)