def csg_to_mesh(csg_primitive): vertices, triangles = to_mesh(csg_primitive.primitive_a) mesh_a = Mesh(vertices, triangles) vertices, triangles = to_mesh(csg_primitive.primitive_b) mesh_b = Mesh(vertices, triangles) if csg_primitive.__class__ == Intersect: operator = IntersectOperator() elif csg_primitive.__class__ == Union: operator = UnionOperator() elif csg_primitive.__class__ == Subtract: operator = SubtractOperator() else: raise ValueError("Unidentified CSG primitive '{}'.".format(csg_primitive.__class__)) mesh = perform_mesh_csg(mesh_a, mesh_b, operator=operator) vertices = mesh.data.vertices.copy() triangles = mesh.data.triangles.copy() if csg_primitive.parent: to_world = csg_primitive.to_root() else: to_world = csg_primitive.transform # Convert vertices to positions in world coordinates for i in range(vertices.shape[0]): p = Point3D(vertices[i, 0], vertices[i, 1], vertices[i, 2]).transform(to_world) vertices[i, 0] = p.x vertices[i, 1] = p.y vertices[i, 2] = p.z return vertices, triangles
def generate_annulus_mesh_segments(lower_corner, upper_corner, number_segments, world, material=None): """ Generates an annulus from many smaller mesh segments. Used for calculating sensitivity matrices for poloidal inversion grids. :param Point2D lower_corner: the lower corner of the poloidal 2D cell. :param Point2D upper_corner: the upper corner of the poloidal 2D cell. :param int number_segments: The number of angular mesh segments used to build the annulus. :param World world: The scene-graph to which the annulus will be attached. :return: Node holding all the annulus segment primitives. :rtype: Node """ material = material or UnityVolumeEmitter() annulus_node = Node(parent=world) theta_adjusted = 360 / number_segments # Set of points in x-z plane p1a = Point3D(lower_corner.x, 0, lower_corner.y) # corresponds to lower corner is x-z plane p2a = Point3D(lower_corner.x, 0, upper_corner.y) p3a = Point3D(upper_corner.x, 0, upper_corner.y) # corresponds to upper corner in x-z plane p4a = Point3D(upper_corner.x, 0, lower_corner.y) # Set of points rotated away from x-z plane p1b = p1a.transform(rotate_z(theta_adjusted)) p2b = p2a.transform(rotate_z(theta_adjusted)) p3b = p3a.transform(rotate_z(theta_adjusted)) p4b = p4a.transform(rotate_z(theta_adjusted)) vertices = [[p1a.x, p1a.y, p1a.z], [p2a.x, p2a.y, p2a.z], [p3a.x, p3a.y, p3a.z], [p4a.x, p4a.y, p4a.z], [p1b.x, p1b.y, p1b.z], [p2b.x, p2b.y, p2b.z], [p3b.x, p3b.y, p3b.z], [p4b.x, p4b.y, p4b.z]] triangles = [[1, 0, 3], [1, 3, 2], # front face (x-z) [7, 4, 5], [7, 5, 6], # rear face (rotated out of x-z plane) [5, 1, 2], [5, 2, 6], # top face (x-y plane) [3, 0, 4], [3, 4, 7], # bottom face (x-y plane) [4, 0, 5], [1, 5, 0], # inner face (y-z plane) [2, 3, 7], [2, 7, 6]] # outer face (y-z plane) base_segment = Mesh(vertices=vertices, triangles=triangles, smoothing=False) # Construct annulus by duplicating and rotating base segment. for i in range(number_segments): theta_rotation = theta_adjusted * i segment = Mesh(instance=base_segment, transform=rotate_z(theta_rotation), material=material, parent=annulus_node) return annulus_node
def _mayavi_source_from_raysect_object(self): lower = self._raysect_object.lower upper = self._raysect_object.upper # more negative face in x-z plane p1a = lower # lower corner in x-z plane p2a = Point3D(lower.x, lower.y, upper.z) p3a = Point3D(upper.x, lower.y, upper.z) # upper corner in x-z plane p4a = Point3D(upper.x, lower.y, lower.z) # more positive face in x-z plane p1b = Point3D(lower.x, upper.y, lower.z) p2b = Point3D(lower.x, upper.y, upper.z) p3b = upper p4b = Point3D(upper.x, upper.y, lower.z) vertices = [[p1a.x, p1a.y, p1a.z], [p2a.x, p2a.y, p2a.z], [p3a.x, p3a.y, p3a.z], [p4a.x, p4a.y, p4a.z], [p1b.x, p1b.y, p1b.z], [p2b.x, p2b.y, p2b.z], [p3b.x, p3b.y, p3b.z], [p4b.x, p4b.y, p4b.z]] triangles = [[1, 0, 3], [1, 3, 2], # front face (x-z) [7, 4, 5], [7, 5, 6], # rear face (x-z) [5, 1, 2], [5, 2, 6], # top face (x-y) [3, 0, 4], [3, 4, 7], # bottom face (x-y) [4, 0, 5], [1, 5, 0], # left face (y-z) [2, 3, 7], [2, 7, 6]] # right face (y-z) mesh = Mesh(vertices, triangles) self._raysect_mesh = subdivide(mesh)
def import_jet_mesh(world, material=None): for mesh_item in JET_MESH: mesh_path, default_material = mesh_item if not material: material = default_material print("importing {} ...".format(os.path.split(mesh_path)[1])) directory, filename = os.path.split(mesh_path) mesh_name, ext = filename.split('.') Mesh.from_file(mesh_path, parent=world, material=material, name=mesh_name)
def _mayavi_source_from_raysect_object(self): # generate mesh parts if needed if self._back_triangles is None or self._back_vertices is None: self._generate_back_surface_mesh() if self._barrel_triangles is None or self._barrel_vertices is None: self._generate_barrel_surface_mesh() if self._front_triangles is None or self._front_vertices is None: self._generate_front_surface_mesh() #combine vertices of the 3 surfaces vertices = np.concatenate( (self._back_vertices, self._barrel_vertices, self._front_vertices)) # recalculate and combine triangle ids for merged vertices n_back = self._back_vertices.shape[0] n_barrel = self._barrel_vertices.shape[0] barrel_triangles = self._barrel_triangles.copy() barrel_triangles += n_back front_triangles = self._front_triangles.copy() front_triangles += n_back + n_barrel triangles = np.concatenate( (self._back_triangles, barrel_triangles, front_triangles)) # create raysect mesh and weld duplicit vertices mesh = Mesh(vertices=vertices, triangles=triangles) self._raysect_mesh = weld_vertices(mesh)
def load_vessel_world(mesh_parts, shift_p5=False): """Load the world containing the vessel mesh parts. <mesh_parts> is a list of filenames containing mesh files in either RSM or OBJ format, which are to be loaded into the world. If shift_p5 is True, the mesh files representing the P5 coils will have a downward shift applied to them to account for the UEP sag. This is described in CD/MU/04783. Returns world, the root of the scenegraph. """ world = World() for path, _ in mesh_parts: print("importing {} ...".format(os.path.split(path)[1])) filename = os.path.split(path)[-1] name, ext = filename.split('.') if 'P5_' in path and shift_p5: p5_zshift = -0.00485 # From CD/MU/04783 transform = translate(0, 0, p5_zshift) else: transform = None if ext.lower() == 'rsm': Mesh.from_file(path, parent=world, material=AbsorbingSurface(), transform=transform, name=name) elif ext.lower() == 'obj': import_obj(path, parent=world, material=AbsorbingSurface(), name=name) else: raise ValueError("Only RSM and OBJ meshes are supported.") # Add a solid cylinder at R=0 to prevent rays finding their way through the # gaps in the centre column armour. This is only necessary for the MAST # meshes, but it does no harm to add it to MAST-U meshes too height = 6 radius = 0.1 Cylinder(radius=radius, height=height, parent=world, transform=translate(0, 0, -height / 2), material=AbsorbingSurface(), name='Blocking Cylinder') return world
def import_aug_mesh(world, material=RoughTungsten(0.29)): """Imports the full AUG first wall mesh with default materials. :param str material: flag for material setting to us. 'ABSORBING' indicates the mesh should be loaded with a perfectly absorbing surface. """ material = material or AbsorbingSurface() for mesh_path in AUG_FULL_MESH: print("importing {} ...".format(os.path.split(mesh_path)[1])) directory, filename = os.path.split(mesh_path) mesh_name, ext = filename.split('.') if ext == 'rsm': Mesh.from_file(mesh_path, parent=world, material=material, name=mesh_name) else: import_stl(mesh_path, parent=world, material=material, name=mesh_name, scaling=0.001)
def import_mastu_mesh(world, override_material=None, metal_material=None, lambert_material=None): for mesh_item in MASTU_FULL_MESH: mesh_path, default_material = mesh_item if override_material: material = override_material elif metal_material and isinstance(default_material, RoughTungsten): material = metal_material elif lambert_material and isinstance(default_material, Lambert): material = lambert_material else: material = default_material print("importing {} ...".format(os.path.split(mesh_path)[1])) directory, filename = os.path.split(mesh_path) mesh_name, ext = filename.split('.') Mesh.from_file(mesh_path, parent=world, material=material, name=mesh_name)
def _mayavi_source_from_raysect_object(self): primitive_a = self._raysect_object.primitive_a primitive_b = self._raysect_object.primitive_b mesh_a = to_mesh(primitive_a) mesh_a_transformed = Mesh(mesh_a._vertices_transform(primitive_a.transform), mesh_a.triangles) mesh_b = to_mesh(primitive_b) mesh_b_transformed = Mesh(mesh_b._vertices_transform(primitive_b.transform), mesh_b.triangles) if self._raysect_object.__class__ == Intersect: self._csg_operator = IntersectOperator() elif self._raysect_object.__class__ == Union: self._csg_operator = UnionOperator() elif self._raysect_object.__class__ == Subtract: self._csg_operator = SubtractOperator() else: raise ValueError("Unidentified CSG primitive '{}'.".format(csg_primitive.__class__)) self._raysect_mesh = perform_mesh_csg(mesh_a_transformed, mesh_b_transformed, operator=self._csg_operator)
def box_to_mesh(box): if not isinstance(box, Box): raise TypeError("The _box_to_mesh() function takes a Raysect Box primitive as an argument, " "wrong type '{}' given.".format(type(box))) lower = box.lower upper = box.upper # more negative face in x-z plane p1a = lower # lower corner in x-z plane p2a = Point3D(lower.x, lower.y, upper.z) p3a = Point3D(upper.x, lower.y, upper.z) # upper corner in x-z plane p4a = Point3D(upper.x, lower.y, lower.z) # more positive face in x-z plane p1b = Point3D(lower.x, upper.y, lower.z) p2b = Point3D(lower.x, upper.y, upper.z) p3b = upper p4b = Point3D(upper.x, upper.y, lower.z) vertices = [[p1a.x, p1a.y, p1a.z], [p2a.x, p2a.y, p2a.z], [p3a.x, p3a.y, p3a.z], [p4a.x, p4a.y, p4a.z], [p1b.x, p1b.y, p1b.z], [p2b.x, p2b.y, p2b.z], [p3b.x, p3b.y, p3b.z], [p4b.x, p4b.y, p4b.z]] triangles = [[1, 0, 3], [1, 3, 2], # front face (x-z) [7, 4, 5], [7, 5, 6], # rear face (x-z) [5, 1, 2], [5, 2, 6], # top face (x-y) [3, 0, 4], [3, 4, 7], # bottom face (x-y) [4, 0, 5], [1, 5, 0], # left face (y-z) [2, 3, 7], [2, 7, 6]] # right face (y-z) mesh = Mesh(vertices, triangles) mesh = subdivide(mesh) vertices = np.array(mesh.data.vertices) triangles = np.array(mesh.data.triangles) if box.parent: to_world = box.to_root() else: to_world = box.transform # Convert vertices to positions in world coordinates for i in range(vertices.shape[0]): p = Point3D(vertices[i, 0], vertices[i, 1], vertices[i, 2]).transform(to_world) vertices[i, 0] = p.x vertices[i, 1] = p.y vertices[i, 2] = p.z return vertices, triangles
def generate_annulus_mesh_segments(lower_corner, upper_corner, theta_width, theta_offset, world): material = UnityVolumeEmitter() # Set of points in x-z plane p1a = Point3D(lower_corner.x, 0, lower_corner.y) # corresponds to lower corner is x-z plane p2a = Point3D(lower_corner.x, 0, upper_corner.y) p3a = Point3D(upper_corner.x, 0, upper_corner.y) # corresponds to upper corner in x-z plane p4a = Point3D(upper_corner.x, 0, lower_corner.y) # Set of points rotated away from x-z plane p1b = p1a.transform(rotate_z(theta_width)) p2b = p2a.transform(rotate_z(theta_width)) p3b = p3a.transform(rotate_z(theta_width)) p4b = p4a.transform(rotate_z(theta_width)) vertices = [[p1a.x, p1a.y, p1a.z], [p2a.x, p2a.y, p2a.z], [p3a.x, p3a.y, p3a.z], [p4a.x, p4a.y, p4a.z], [p1b.x, p1b.y, p1b.z], [p2b.x, p2b.y, p2b.z], [p3b.x, p3b.y, p3b.z], [p4b.x, p4b.y, p4b.z]] triangles = [ [1, 0, 3], [1, 3, 2], # front face (x-z) [7, 4, 5], [7, 5, 6], # rear face (rotated out of x-z plane) [5, 1, 2], [5, 2, 6], # top face (x-y plane) [3, 0, 4], [3, 4, 7], # bottom face (x-y plane) [4, 0, 5], [1, 5, 0], # inner face (y-z plane) [2, 3, 7], [2, 7, 6] ] # outer face (y-z plane) return Mesh(vertices=vertices, triangles=triangles, smoothing=False, transform=rotate_z(theta_offset), material=material, parent=world)
def weld_vertices(mesh, tolerance=1E-6): vertices = mesh.data.vertices num_vertices = len(vertices) triangles = mesh.data.triangles num_triangles = len(triangles) # construct KD-Tree of original vertex set kdtree = KDTree(vertices) # cycle through old vertices and only add them if greater than tolerance new_vertices = [] unique_ids = [] for i in range(num_vertices): unique_id = kdtree.query_ball_point(vertices[i], tolerance)[0] if not unique_id in unique_ids: new_vertices.append(vertices[unique_id].tolist()) new_kdtree = KDTree(new_vertices) new_triangles = [] for i in range(num_triangles): v1, v2, v3 = triangles[i] dist, new_v1 = new_kdtree.query(vertices[v1]) if dist > tolerance: raise RuntimeError('An error has occurred') dist, new_v2 = new_kdtree.query(vertices[v2]) if dist > tolerance: raise RuntimeError('An error has occurred') dist, new_v3 = new_kdtree.query(vertices[v3]) if dist > tolerance: raise RuntimeError('An error has occurred') new_triangles.append([new_v1, new_v2, new_v3]) return Mesh(new_vertices, new_triangles, smoothing=mesh.data.smoothing, closed=mesh.data.closed, parent=mesh.parent, transform=mesh.transform, material=mesh.material, name=mesh.name)
def box_to_mesh(box): if not isinstance(box, Box): raise TypeError( "The _box_to_mesh() function takes a Raysect Box primitive as an argument, " "wrong type '{}' given.".format(type(box))) lower = box.lower upper = box.upper # more negative face in x-z plane p1a = lower # lower corner in x-z plane p2a = Point3D(lower.x, lower.y, upper.z) p3a = Point3D(upper.x, lower.y, upper.z) # upper corner in x-z plane p4a = Point3D(upper.x, lower.y, lower.z) # more positive face in x-z plane p1b = Point3D(lower.x, upper.y, lower.z) p2b = Point3D(lower.x, upper.y, upper.z) p3b = upper p4b = Point3D(upper.x, upper.y, lower.z) vertices = [[p1a.x, p1a.y, p1a.z], [p2a.x, p2a.y, p2a.z], [p3a.x, p3a.y, p3a.z], [p4a.x, p4a.y, p4a.z], [p1b.x, p1b.y, p1b.z], [p2b.x, p2b.y, p2b.z], [p3b.x, p3b.y, p3b.z], [p4b.x, p4b.y, p4b.z]] triangles = [ [1, 0, 3], [1, 3, 2], # front face (x-z) [7, 4, 5], [7, 5, 6], # rear face (x-z) [5, 1, 2], [5, 2, 6], # top face (x-y) [3, 0, 4], [3, 4, 7], # bottom face (x-y) [4, 0, 5], [1, 5, 0], # left face (y-z) [2, 3, 7], [2, 7, 6] ] # right face (y-z) return Mesh(vertices=vertices, triangles=triangles, smoothing=False, transform=box.transform, material=box.material, name=box.name)
def _mayavi_source_from_raysect_object(self): if self._cap_vertices is None or self._cap_triangles is None: self._generate_cap_surface() if self._cone_vertices is None or self._cone_triangles is None: self._generate_conic_surface() #combine vertices of the 2 surfaces vertices = np.concatenate((self._cap_vertices, self._cone_vertices)) # recalculate and combine triangle ids for merged vertices n_cap = self._cap_vertices.shape[0] parabola_triangles = self._cone_triangles.copy() parabola_triangles += n_cap triangles = np.concatenate((self._cap_triangles, parabola_triangles)) mesh = Mesh(vertices=vertices, triangles=triangles) self._raysect_mesh = weld_vertices(mesh)
from raysect.core import translate, Point3D from raysect.optical import World from raysect.primitive import Sphere, Mesh from raysect_mayavi.primitives import to_mesh from raysect_mayavi.primitives.triangle import triangle3d_intersects_triangle3d world = World() # s1 = Sphere(0.5, transform=translate(-0.25, 0, 0), name='s1') s1 = Sphere(0.5, transform=translate(-0.6, 0, 0), name='s1') # s2 = Sphere(0.5, transform=translate(0.25, 0, 0), name='s2') s2 = Sphere(0.5, transform=translate(0.6, 0, 0), name='s2') s1_vertices, s1_triangles = to_mesh(s1) n_s1_vertices = s1_vertices.shape[0] n_s1_triangles = s1_triangles.shape[0] s1_mesh = Mesh(vertices=s1_vertices, triangles=s1_triangles, smoothing=False) s2_vertices, s2_triangles = to_mesh(s2) n_s2_vertices = s2_vertices.shape[0] n_s2_triangles = s2_triangles.shape[0] s2_mesh = Mesh(vertices=s2_vertices, triangles=s2_triangles, smoothing=False) combined_vertices = np.zeros((n_s1_vertices + n_s2_vertices, 3)) combined_vertices[0:n_s1_vertices] = s1_vertices[:] combined_vertices[n_s1_vertices:] = s2_vertices[:] combined_triangles = np.zeros((n_s1_triangles + n_s2_triangles, 3)) combined_triangles[0:n_s1_triangles] = s1_triangles[:] combined_triangles[n_s1_triangles:] = s2_triangles[:] + n_s1_vertices combined_mesh = Mesh(vertices=combined_vertices,
def _mayavi_source_from_raysect_object(self): # Calculate vertices and faces using the icosohedren method # We compute a regular icosohedren with 12 vertices and 20 faces. # Vertices given by all perturbations of: # (0, ±1, ±ϕ), (±1, ±ϕ, 0), (±ϕ, 0, ±1), where ϕ = golden ratio golden_ratio = 1.61803398875 radius = self._raysect_object.radius v1 = Vector3D(-1.0, golden_ratio, 0.0).normalise() * radius v2 = Vector3D(1.0, golden_ratio, 0.0).normalise() * radius v3 = Vector3D(-1.0, -golden_ratio, 0.0).normalise() * radius v4 = Vector3D(1.0, -golden_ratio, 0.0).normalise() * radius v5 = Vector3D(0.0, -1.0, golden_ratio).normalise() * radius v6 = Vector3D(0.0, 1.0, golden_ratio).normalise() * radius v7 = Vector3D(0.0, -1.0, -golden_ratio).normalise() * radius v8 = Vector3D(0.0, 1.0, -golden_ratio).normalise() * radius v9 = Vector3D(golden_ratio, 0.0, -1.0).normalise() * radius v10 = Vector3D(golden_ratio, 0.0, 1.0).normalise() * radius v11 = Vector3D(-golden_ratio, 0.0, -1.0).normalise() * radius v12 = Vector3D(-golden_ratio, 0.0, 1.0).normalise() * radius vertices = [ [v1.x, v1.y, v1.z], [v2.x, v2.y, v2.z], [v3.x, v3.y, v3.z], [v4.x, v4.y, v4.z], [v5.x, v5.y, v5.z], [v6.x, v6.y, v6.z], [v7.x, v7.y, v7.z], [v8.x, v8.y, v8.z], [v9.x, v9.y, v9.z], [v10.x, v10.y, v10.z], [v11.x, v11.y, v11.z], [v12.x, v12.y, v12.z], ] triangles = [[0, 11, 5], [0, 5, 1], [0, 1, 7], [0, 7, 10], [0, 10, 11], [1, 5, 9], [5, 11, 4], [11, 10, 2], [10, 7, 6], [7, 1, 8], [3, 9, 4], [3, 4, 2], [3, 2, 6], [3, 6, 8], [3, 8, 9], [4, 9, 5], [2, 4, 11], [6, 2, 10], [8, 6, 7], [9, 8, 1]] # Optional - subdivision of icosohedren to increase resolution num_vertices = 12 num_triangles = 20 for i in range(self._subdivision_count): for j in range(num_triangles): triangle = triangles[j] # extract current triangle vertices v0_id = triangle[0] v1_id = triangle[1] v2_id = triangle[2] v0 = Vector3D(vertices[v0_id][0], vertices[v0_id][1], vertices[v0_id][2]) v1 = Vector3D(vertices[v1_id][0], vertices[v1_id][1], vertices[v1_id][2]) v2 = Vector3D(vertices[v2_id][0], vertices[v2_id][1], vertices[v2_id][2]) # subdivide with three new vertices v3 = (v0 + v1).normalise() * radius v3_id = num_vertices v4 = (v1 + v2).normalise() * radius v4_id = num_vertices + 1 v5 = (v2 + v0).normalise() * radius v5_id = num_vertices + 2 vertices.append([v3.x, v3.y, v3.z]) vertices.append([v4.x, v4.y, v4.z]) vertices.append([v5.x, v5.y, v5.z]) # ... and three new faces triangles[j] = [v0_id, v3_id, v5_id] # replace the first face triangles.append([v3_id, v1_id, v4_id]) triangles.append([v4_id, v2_id, v5_id]) triangles.append([v3_id, v4_id, v5_id]) num_vertices += 3 num_triangles += 3 vertices = np.array(vertices) triangles = np.array(triangles) self._raysect_mesh = Mesh(vertices, triangles)
# OPERATION = 'UNION' # OPERATION = 'INTERSECTION' OPERATION = 'DIFFERENCE' world = World() s1 = Sphere(0.5, transform=translate(-0.25, 0, 0), name='s1') s2 = Sphere(0.5, transform=translate(0.25, 0, 0), name='s2') s1_vertices, s1_triangles = to_mesh(s1) n_s1_vertices = s1_vertices.shape[0] n_s1_triangles = s1_triangles.shape[0] s1_mesh = Mesh(vertices=s1_vertices, triangles=s1_triangles, smoothing=False) print() print('n_s1_triangles', n_s1_triangles) s2_vertices, s2_triangles = to_mesh(s2) n_s2_vertices = s2_vertices.shape[0] n_s2_triangles = s2_triangles.shape[0] s2_mesh = Mesh(vertices=s2_vertices, triangles=s2_triangles, smoothing=False) print('n_s2_triangles', n_s2_triangles) s1_intersects = np.zeros(n_s1_triangles) s1s2_distance = np.empty(n_s1_triangles) s1s2_distance[:] = 1E999 s1_from_s2_signed_distance = np.empty(n_s1_triangles) s1_from_s2_signed_distance[:] = 1E999
def sphere_to_mesh(sphere, subdivision_count=2): if not isinstance(sphere, Sphere): raise TypeError( "The _sphere_to_mesh() function takes a Raysect Box primitive as an argument, " "wrong type '{}' given.".format(type(sphere))) # Calculate vertices and faces using the icosohedren method # We compute a regular icosohedren with 12 vertices and 20 faces. # Vertices given by all perturbations of: # (0, ±1, ±ϕ), (±1, ±ϕ, 0), (±ϕ, 0, ±1), where ϕ = golden ratio golden_ratio = 1.61803398875 radius = sphere.radius v1 = Vector3D(-1.0, golden_ratio, 0.0).normalise() * radius v2 = Vector3D(1.0, golden_ratio, 0.0).normalise() * radius v3 = Vector3D(-1.0, -golden_ratio, 0.0).normalise() * radius v4 = Vector3D(1.0, -golden_ratio, 0.0).normalise() * radius v5 = Vector3D(0.0, -1.0, golden_ratio).normalise() * radius v6 = Vector3D(0.0, 1.0, golden_ratio).normalise() * radius v7 = Vector3D(0.0, -1.0, -golden_ratio).normalise() * radius v8 = Vector3D(0.0, 1.0, -golden_ratio).normalise() * radius v9 = Vector3D(golden_ratio, 0.0, -1.0).normalise() * radius v10 = Vector3D(golden_ratio, 0.0, 1.0).normalise() * radius v11 = Vector3D(-golden_ratio, 0.0, -1.0).normalise() * radius v12 = Vector3D(-golden_ratio, 0.0, 1.0).normalise() * radius vertices = [ [v1.x, v1.y, v1.z], [v2.x, v2.y, v2.z], [v3.x, v3.y, v3.z], [v4.x, v4.y, v4.z], [v5.x, v5.y, v5.z], [v6.x, v6.y, v6.z], [v7.x, v7.y, v7.z], [v8.x, v8.y, v8.z], [v9.x, v9.y, v9.z], [v10.x, v10.y, v10.z], [v11.x, v11.y, v11.z], [v12.x, v12.y, v12.z], ] triangles = [[0, 11, 5], [0, 5, 1], [0, 1, 7], [0, 7, 10], [0, 10, 11], [1, 5, 9], [5, 11, 4], [11, 10, 2], [10, 7, 6], [7, 1, 8], [3, 9, 4], [3, 4, 2], [3, 2, 6], [3, 6, 8], [3, 8, 9], [4, 9, 5], [2, 4, 11], [6, 2, 10], [8, 6, 7], [9, 8, 1]] # Optional - subdivision of icosohedren to increase resolution num_vertices = 12 num_triangles = 20 for i in range(subdivision_count): for j in range(num_triangles): triangle = triangles[j] # extract current triangle vertices v0_id = triangle[0] v1_id = triangle[1] v2_id = triangle[2] v0 = Vector3D(vertices[v0_id][0], vertices[v0_id][1], vertices[v0_id][2]) v1 = Vector3D(vertices[v1_id][0], vertices[v1_id][1], vertices[v1_id][2]) v2 = Vector3D(vertices[v2_id][0], vertices[v2_id][1], vertices[v2_id][2]) # subdivide with three new vertices v3 = (v0 + v1).normalise() * radius v3_id = num_vertices v4 = (v1 + v2).normalise() * radius v4_id = num_vertices + 1 v5 = (v2 + v0).normalise() * radius v5_id = num_vertices + 2 vertices.append([v3.x, v3.y, v3.z]) vertices.append([v4.x, v4.y, v4.z]) vertices.append([v5.x, v5.y, v5.z]) # ... and three new faces triangles[j] = [v0_id, v3_id, v5_id] # replace the first face triangles.append([v3_id, v1_id, v4_id]) triangles.append([v4_id, v2_id, v5_id]) triangles.append([v3_id, v4_id, v5_id]) num_vertices += 3 num_triangles += 3 return Mesh(vertices=vertices, triangles=triangles, smoothing=False, transform=sphere.transform, material=sphere.material, name=sphere.name)
def cone_to_mesh(cone, vertical_divisions=10, cylindrical_divisions=36, base_radial_divisions=5): if not isinstance(cone, Cone): raise TypeError( "The _cone_to_mesh() function takes a Raysect Cone primitive as an argument, " "wrong type '{}' given.".format(type(cone))) radius = cone.radius height = cone.height # first make the cone body working_cylindrical_divisions = cylindrical_divisions cone_body_vertices = [] for i in range(vertical_divisions): working_radius = radius * (1 - (i / vertical_divisions)) working_height = height * (i / vertical_divisions) theta_step = 360 / working_cylindrical_divisions for j in range(working_cylindrical_divisions): theta_rad = np.deg2rad(j * theta_step) cone_body_vertices.append([ working_radius * np.cos(theta_rad), working_radius * np.sin(theta_rad), working_height ]) working_cylindrical_divisions -= int(cylindrical_divisions / (vertical_divisions + 1)) if working_cylindrical_divisions < 5: working_cylindrical_divisions = 5 # Finally, add centre point cone_body_vertices.append([0, 0, height]) # Triangulate the vertices vertices_2d = np.array(cone_body_vertices)[:, 0:2] cone_body_triangles = Delaunay(vertices_2d).simplices.tolist() # Now make the cone base working_cylindrical_divisions = cylindrical_divisions cone_base_vertices = [] for i in range(base_radial_divisions): working_radius = radius * (1 - (i / base_radial_divisions)) theta_step = 360 / working_cylindrical_divisions for j in range(working_cylindrical_divisions): theta_rad = np.deg2rad(j * theta_step) cone_base_vertices.append([ working_radius * np.cos(theta_rad), working_radius * np.sin(theta_rad), 0 ]) working_cylindrical_divisions -= int(cylindrical_divisions / (base_radial_divisions + 1)) if working_cylindrical_divisions < 5: working_cylindrical_divisions = 5 # Finally, add centre point cone_base_vertices.append([0, 0, 0]) # Triangulate the vertices vertices_2d = np.array(cone_base_vertices)[:, 0:2] cone_base_triangles = np.flip( Delaunay(vertices_2d).simplices + len(cone_body_vertices), 1).tolist() # Combine the resulting triangles together vertices = cone_body_vertices + cone_base_vertices triangles = cone_body_triangles + cone_base_triangles return Mesh(vertices=vertices, triangles=triangles, smoothing=False, transform=cone.transform, material=cone.material, name=cone.name)
def import_mastu_mesh(world, override_material=None, metal_material=None, lambert_material=None): LOWER_ELM_COILS = [ (os.path.join(CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_10_LOWER.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_11_12_LOWER.rsm'), METAL), (os.path.join(CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_1_LOWER.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_2_3_LOWER.rsm'), METAL), (os.path.join(CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_4_LOWER.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_5_6_LOWER.rsm'), METAL), (os.path.join(CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_7_LOWER.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_8_9_LOWER.rsm'), METAL), ] UPPER_ELM_COILS = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_11_12_UPPER.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_2_3_UPPER.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_5_6_UPPER.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/magnets/elm_coils/SECTOR_8_9_UPPER.rsm'), METAL), ] ELM_COILS = LOWER_ELM_COILS + UPPER_ELM_COILS PF_COILS = [ (os.path.join(CADMESH_PATH, 'mast/mastu-full/magnets/pf_coils/P4_LOWER.rsm'), METAL), (os.path.join(CADMESH_PATH, 'mast/mastu-full/magnets/pf_coils/P4_UPPER.rsm'), METAL), (os.path.join(CADMESH_PATH, 'mast/mastu-full/magnets/pf_coils/P5_LOWER.rsm'), METAL), (os.path.join(CADMESH_PATH, 'mast/mastu-full/magnets/pf_coils/P5_UPPER.rsm'), METAL), (os.path.join(CADMESH_PATH, 'mast/mastu-full/magnets/pf_coils/P6_LOWER.rsm'), METAL), (os.path.join(CADMESH_PATH, 'mast/mastu-full/magnets/pf_coils/P6_UPPER.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET1_lower.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET1_upper.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET2_lower.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET2_upper.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET3_lower.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET3_upper.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET4_lower.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET4_upper.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET5_lower.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET5_upper.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET6_lower.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_BRACKET6_upper.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/P4_P5_SUPPORT_BRACKETS.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/coil_armour/P5_LOWER_ARMOUR.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/coil_armour/P5_UPPER_ARMOUR.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/coil_armour/P6_LOWER_ARMOUR.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/coil_armour/P6_UPPER_ARMOUR.rsm'), METAL), ] VACUUM_VESSEL = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/OUTER_CYLINDER_VACUUM_VESSEL.rsm'), METAL), (os.path.join(CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/BOTTOM_ENDPLATE.rsm'), METAL), (os.path.join(CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/TOP_ENDPLATE.rsm'), METAL), ] BEAM_DUMPS = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/beam_dumps/BEAM_DUMP_6M.rsm'), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/beam_dumps/BEAM_DUMP_8U.rsm'), CARBON), ] C1_TILE = [(os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/centre_column_armour/C1.rsm'), CARBON)] C2_TILES = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/centre_column_armour/C2_lower.rsm'), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/centre_column_armour/C2_upper.rsm'), CARBON), ] C3_TILES = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/centre_column_armour/C3_lower.rsm'), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/centre_column_armour/C3_upper.rsm'), CARBON), ] C4_TILES = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/centre_column_armour/C4_lower.rsm'), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/centre_column_armour/C4_upper.rsm'), CARBON), ] C5_TILES = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/centre_column_armour/C5_lower.rsm'), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/centre_column_armour/C5_upper.rsm'), CARBON), ] C6_TILES = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/centre_column_armour/C6_lower.rsm'), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/centre_column_armour/C6_upper.rsm'), CARBON), ] CENTRE_COLUMN = C1_TILE + C2_TILES + C3_TILES + C4_TILES + C5_TILES + C6_TILES T1_LOWER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T1_L_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T1_L_13_24.rsm' ), CARBON), ] T2_LOWER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T2_L_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T2_L_13_24.rsm' ), CARBON), ] T3_LOWER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T3_L_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T3_L_13_24.rsm' ), CARBON), ] T4_LOWER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T4_L_01_08.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T4_L_09_16.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T4_L_17_24.rsm' ), CARBON), ] T5_LOWER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T5_L_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T5_L_13_24.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T5_L_25_36.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/lower/T5_L_37_48.rsm' ), CARBON), ] LOWER_DIVERTOR_ARMOUR = T1_LOWER + T2_LOWER + T3_LOWER + T4_LOWER + T5_LOWER B1_LOWER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B1_L_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B1_L_13_24.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B1_L_25_36.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B1_L_37_48.rsm' ), CARBON), ] B2_LOWER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B2_L_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B2_L_13_24.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B2_L_25_36.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B2_L_37_48.rsm' ), CARBON), ] B3_LOWER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B3_L_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B3_L_13_24.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B3_L_25_36.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B3_L_37_48.rsm' ), CARBON), ] B4_LOWER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B4_L_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B4_L_13_24.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B4_L_25_36.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/B4_L_37_48.rsm' ), CARBON), ] N1_LOWER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/N1_L_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/N1_L_13_24.rsm' ), CARBON), ] N2_LOWER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/N2_L_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/lower/N2_L_13_24.rsm' ), CARBON), ] LOWER_DIVERTOR_NOSE = B1_LOWER + B2_LOWER + B3_LOWER + B4_LOWER + N1_LOWER + N2_LOWER LOWER_GAS_BAFFLE = [ (os.path.join(CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/GAS_BAFFLE_LOWER.rsm'), METAL) ] LOWER_DIVERTOR = LOWER_DIVERTOR_ARMOUR + LOWER_DIVERTOR_NOSE + LOWER_GAS_BAFFLE T1_UPPER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T1_U_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T1_U_13_24.rsm' ), CARBON), ] T2_UPPER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T2_U_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T2_U_13_24.rsm' ), CARBON), ] T3_UPPER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T3_U_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T3_U_13_24.rsm' ), CARBON), ] T4_UPPER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T4_U_01_08.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T4_U_09_16.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T4_U_17_24.rsm' ), CARBON), ] T5_UPPER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T5_U_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T5_U_13_24.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T5_U_25_36.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/divertor_armour/upper/T5_U_37_48.rsm' ), CARBON), ] UPPER_DIVERTOR_ARMOUR = T1_UPPER + T2_UPPER + T3_UPPER + T4_UPPER + T5_UPPER B1_UPPER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B1_U_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B1_U_13_24.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B1_U_25_36.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B1_U_37_48.rsm' ), CARBON), ] B2_UPPER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B2_U_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B2_U_13_24.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B2_U_25_36.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B2_U_37_48.rsm' ), CARBON), ] B3_UPPER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B3_U_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B3_U_13_24.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B3_U_25_36.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B3_U_37_48.rsm' ), CARBON), ] B4_UPPER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B4_U_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B4_U_13_24.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B4_U_25_36.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/B4_U_37_48.rsm' ), CARBON), ] N1_UPPER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/N1_U_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/N1_U_13_24.rsm' ), CARBON), ] N2_UPPER = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/N2_U_01_12.rsm' ), CARBON), (os.path.join( CADMESH_PATH, 'mast/mastu-full/vessel_armour/throat_armour/upper/N2_U_13_24.rsm' ), CARBON), ] UPPER_DIVERTOR_NOSE = B1_UPPER + B2_UPPER + B3_UPPER + B4_UPPER + N1_UPPER + N2_UPPER UPPER_GAS_BAFFLE = [ (os.path.join(CADMESH_PATH, 'mast/mastu-full/vacuum_vessel/GAS_BAFFLE_UPPER.rsm'), METAL) ] UPPER_DIVERTOR = UPPER_DIVERTOR_ARMOUR + UPPER_DIVERTOR_NOSE + UPPER_GAS_BAFFLE MASTU_FULL_MESH = ELM_COILS + PF_COILS + VACUUM_VESSEL + BEAM_DUMPS + CENTRE_COLUMN + LOWER_DIVERTOR + UPPER_DIVERTOR SXD_BOLOMETERS = [ (os.path.join( CADMESH_PATH, 'mast/mastu-full/diagnostics/DIVERTOR_horizontal_bolometer.rsm'), METAL), (os.path.join( CADMESH_PATH, 'mast/mastu-full/diagnostics/DIVERTOR_verticall_bolometer.rsm'), METAL), ] for mesh_item in MASTU_FULL_MESH: mesh_path, default_material = mesh_item if override_material: material = override_material elif metal_material and isinstance(default_material, RoughTungsten): material = metal_material elif lambert_material and isinstance(default_material, Lambert): material = lambert_material else: material = default_material print("importing {} ...".format(os.path.split(mesh_path)[1])) directory, filename = os.path.split(mesh_path) mesh_name, ext = filename.split('.') Mesh.from_file(mesh_path, parent=world, material=material, name=mesh_name) return world
def cylinder_to_mesh(cylinder, vertical_divisions=10, cylindrical_divisions=36, radial_divisions=5): if not isinstance(cylinder, Cylinder): raise TypeError( "The _cylinder_to_mesh() function takes a Raysect Cylinder primitive as an argument, " "wrong type '{}' given.".format(type(cylinder))) radius = cylinder.radius height = cylinder.height # first make the main cylinder theta_step = 360 / cylindrical_divisions vertices = [] for i in range(vertical_divisions): z = (i / (vertical_divisions - 1)) * height for j in range(cylindrical_divisions): theta_rad = np.deg2rad(j * theta_step) vertices.append( [radius * np.cos(theta_rad), radius * np.sin(theta_rad), z]) triangles = [] for i in range(vertical_divisions - 1): row_start = cylindrical_divisions * i next_row_start = cylindrical_divisions * (i + 1) for j in range(cylindrical_divisions): v1 = row_start + j if j != cylindrical_divisions - 1: v2 = row_start + j + 1 v3 = next_row_start + j + 1 else: v2 = row_start v3 = next_row_start v4 = next_row_start + j triangles.append([v1, v2, v3]) triangles.append([v3, v4, v1]) def _make_cap_triangles(n_cylindrical_segments, n_radial_segments, radius, z_height): working_cylindrical_segments = n_cylindrical_segments cap_vertices = [] for i in range(n_radial_segments): working_radius = radius * (1 - (i / n_radial_segments)) theta_step = 360 / working_cylindrical_segments for j in range(working_cylindrical_segments): theta_rad = np.deg2rad(j * theta_step) cap_vertices.append([ working_radius * np.cos(theta_rad), working_radius * np.sin(theta_rad), z_height ]) working_cylindrical_segments -= int(n_cylindrical_segments / (n_radial_segments + 1)) if working_cylindrical_segments < 5: working_cylindrical_segments = 5 # Finally, add centre point cap_vertices.append([0, 0, z_height]) vertices_2d = np.array(cap_vertices)[:, 0:2] triangles = Delaunay(vertices_2d).simplices return cap_vertices, triangles # Make the upper and lower end caps lower_cap_vertices, lower_cap_triangles = _make_cap_triangles( cylindrical_divisions, radial_divisions, radius, 0) lower_cap_triangles = np.flip(lower_cap_triangles, 1) lower_cap_triangles += len(vertices) lower_cap_triangles = lower_cap_triangles.tolist() vertices += lower_cap_vertices triangles += lower_cap_triangles upper_cap_vertices, upper_cap_triangles = _make_cap_triangles( cylindrical_divisions, radial_divisions, radius, height) upper_cap_triangles += len(vertices) upper_cap_triangles = upper_cap_triangles.tolist() vertices += upper_cap_vertices triangles += upper_cap_triangles return Mesh(vertices=vertices, triangles=triangles, smoothing=False, transform=cylinder.transform, material=cylinder.material, name=cylinder.name)