Esempio n. 1
0
def shift(mesh, shift):
    #input shift as a vector
    vertices = mesh.vertices
    triangles = mesh.triangles
    n = np.shape(vertices)[0]
    newvertices = vertices + np.tile(shift, (n, 1))
    return Mesh(newvertices, triangles, remove_duplicate_vertices=True)
Esempio n. 2
0
def mesh_from_binary_stl(filename):
    "Return a mesh from a binary stl file."
    if filename.endswith('.bz2'):
        f = bz2.BZ2File(filename)
    else:
        f = open(filename)

    vertices = []
    triangles = []
    vertex_map = {}

    f.read(80)
    ntriangles = struct.unpack('<I', f.read(4))[0]

    for i in range(ntriangles):
        normal = tuple(struct.unpack('<fff', f.read(12)))

        triangle = [None] * 3
        for j in range(3):
            vertex = tuple(struct.unpack('<fff', f.read(12)))

            if vertex not in vertex_map:
                vertices.append(vertex)
                vertex_map[vertex] = len(vertices) - 1

            triangle[j] = vertex_map[vertex]

        triangles.append(triangle)

        f.read(2)

    f.close()

    return Mesh(np.array(vertices), np.array(triangles, dtype=np.uint32))
Esempio n. 3
0
def rotate_extrude(x, y, nsteps=64):
    """
    Return the solid mesh formed by extruding the profile defined by the x and
    y points `x` and `y` around the y axis.

    .. note::
        The path traced by the points `x` and `y` should go counter-clockwise,
        otherwise the mesh will be inside out.

    Example:
        >>> # create a bipyramid
        >>> m = rotate_extrude([0,1,0], [-1,0,1], nsteps=4)
    """
    if len(x) != len(y):
        raise Exception('`x` and `y` arrays must have the same length.')

    points = np.array([x, y, np.zeros(len(x))]).transpose()

    steps = np.linspace(0, 2 * np.pi, nsteps, endpoint=False)
    vertices = np.vstack(
        [rotate(points, angle, (0, -1, 0)) for angle in steps])
    triangles = mesh_grid(
        np.arange(len(vertices)).reshape(
            (len(steps), len(points))).transpose()[::-1])

    return Mesh(vertices, triangles, remove_duplicate_vertices=True)
Esempio n. 4
0
 def render_photon_track(self,geometry,photon_track,sz=1.0,color='wavelength'):
     origin = photon_track.pos[:-1]
     extent = photon_track.pos[1:]-photon_track.pos[:-1]
     perp1 = np.cross(origin,extent)
     perp1 = np.inner(sz/2.0/np.linalg.norm(perp1,axis=1),perp1.T).T
     perp2 = np.cross(perp1,extent)
     perp2 = np.inner(sz/2.0/np.linalg.norm(perp2,axis=1),perp2.T).T
     verts = [perp1+perp2,-perp1+perp2,perp1-perp2,-perp1-perp2]
     bot = [vert+origin for vert in verts]
     top = [vert+origin+extent for vert in verts]
     vertices = [origin,origin+extent,bot[0],top[0],bot[1],top[1],bot[2],top[2],bot[3],top[3]]
     vertices = np.transpose(np.asarray(vertices,np.float32),(1,0,2))
     triangles = np.asarray([[1, 3, 5], [1, 5, 7], [1, 7, 9], [1, 9, 3], [3, 2, 4], [5, 4, 6], [7, 6, 8], [9, 8, 2], [2, 0, 0], [4, 0, 0], [6, 0, 0], [8, 0, 0],
                             [1, 5, 1], [1, 7, 1], [1, 9, 1], [1, 3, 1], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 2, 3], [2, 0, 4], [4, 0, 6], [6, 0, 8], [8, 0, 2]],
                             dtype=np.int32)
     if color == 'wavelength':
         r = np.asarray(np.interp(photon_track.wavelengths[:-1],[300,550,800],[0,0,255]),dtype=np.uint32)
         g = np.asarray(np.interp(photon_track.wavelengths[:-1],[300,550,800],[0,255,0]),dtype=np.uint32)
         b = np.asarray(np.interp(photon_track.wavelengths[:-1],[300,550,800],[255,0,0]),dtype=np.uint32)
         colors = np.bitwise_or(b,np.bitwise_or(np.left_shift(g,8),np.left_shift(r,16)))
     else:
         r,g,b = color
         colors = np.full_like(photon_track.wavelengths[:-1],((r<<16)|(g<<8)|b),dtype=np.uint32)
     markers = [Solid(Mesh(v,triangles), vacuum, vacuum, color=c) for v,c in zip(vertices,colors)]
     [geometry.add_solid(marker) for marker in markers]
Esempio n. 5
0
def rotate(mesh, rotation_matrix):
    vertices = mesh.vertices
    triangles = mesh.triangles
    n = np.shape(vertices)[0]
    newvertices = np.empty((n, 3))
    for i in range(n):
        newvertices[i] = np.dot(rotation_matrix, vertices[i])
    return Mesh(newvertices, triangles, remove_duplicate_vertices=True)
Esempio n. 6
0
def linear_extrude(x1,
                   y1,
                   height,
                   x2=None,
                   y2=None,
                   center=None,
                   endcaps=True):
    """
    Return the solid mesh formed by linearly extruding the polygon formed by
    the x and y points `x1` and `y1` by a distance `height`. If `x2` and `y2`
    are given extrude by connecting the points `x1` and `y1` to `x2` and `y2`;
    this allows the creation of tapered solids.  If `endcaps` is False, then
    the triangles on the endcaps will be left off, and the mesh will not be
    closed.

    .. note::
        The path traced by the points `x` and `y` should go counter-clockwise,
        otherwise the mesh will be inside out.

    Example:
        >>> # create a hexagon prism
        >>> angles = np.linspace(0, 2*np.pi, 6, endpoint=False)
        >>> m = linear_extrude(np.cos(angles), np.sin(angles), 2.0)
    """
    if len(x1) != len(y1):
        raise Exception('`x` and `y` arrays must have the same length.')

    if x2 is None:
        x2 = x1

    if y2 is None:
        y2 = y1

    if len(x2) != len(y2) or len(x2) != len(x1):
        raise Exception('`x` and `y` arrays must have the same length.')

    n = len(x1)

    vertex_iterators = [
        izip(x1, y1, repeat(-height / 2.0, n)),
        izip(x2, y2, repeat(height / 2.0, n))
    ]
    if endcaps:
        vertex_iterators = [izip(repeat(0,n),repeat(0,n),repeat(-height/2.0,n))] \
            + vertex_iterators \
            + [izip(repeat(0,n),repeat(0,n),repeat(height/2.0,n))]

    vertices = np.fromiter(flatten(roundrobin(*vertex_iterators)), float)
    vertices = vertices.reshape((len(vertices) // 3, 3))

    if center is not None:
        vertices += center

    triangles = mesh_grid(
        np.arange(len(vertices)).reshape(
            (len(x1), len(vertices) // len(x1))).transpose()[::-1])

    return Mesh(vertices, triangles, remove_duplicate_vertices=True)
Esempio n. 7
0
def convex_polygon(x, y):
    """
    Return a polygon mesh in the x-y plane. `x` and `y` are the x and
    y coordinates for the points in the polygon.  The simple triangulation
    method used here requires that the polygon be convex and the points
    are specified in order.
    """
    vertices = np.column_stack((x, y, np.zeros_like(x)))
    # Every triangle includes
    triangles = np.empty(shape=(len(vertices) - 2, 3), dtype=np.int32)
    triangles[:, 0] = 0  # Every triangle includes vertex zero
    triangles[:, 1] = np.arange(1, len(vertices) - 1)
    triangles[:, 2] = np.arange(2, len(vertices))

    return Mesh(vertices=vertices, triangles=triangles)
Esempio n. 8
0
 def build_detector(self, detector=None, volume_classifier=_default_volume_classifier):
     '''
     Add the meshes defined by this GDML to the detector. If detector is not
     specified, a new detector will be created.
     
     The volume_classifier should be a function that returns a classification
     of the volume ('pmt','solid','omit') and kwargs passed to the Solid
     constructor for that volume: material1, material2, color, surface
     
     The different classifications have different behaviors:
     'pmt' should specify channel_type in the kwargs to identify the channel, calls add_pmt
     'solid' will add a normal solid to the Chroma geometry, calls add_solid
     'omit' will not add the Solid to the Chroma geometry
     '''
     if detector is None:
         detector = Detector(vacuum)
     q = deque()
     q.append([self.world, np.zeros(3), np.identity(3), None])
     while len(q):
         v, pos, rot, parent_material_ref = q.pop()
         for child, c_pos, c_rot in zip(v.children, v.child_pos, v.child_rot):
             c_pos = self.get_vals(c_pos) if c_pos is not None else np.zeros(3)
             c_rot = self.get_vals(c_rot) if c_rot is not None else np.identity(3)
             c_pos = np.matmul(c_pos,rot)+pos
             x_rot = make_rotation_matrix(c_rot[0], [1, 0, 0])
             y_rot = make_rotation_matrix(c_rot[1], [0, 1, 0])
             z_rot = make_rotation_matrix(c_rot[2], [0, 0, 1])
             c_rot = np.matmul(rot, np.matmul(x_rot, np.matmul(y_rot, z_rot))) #FIXME verify this order
             q.append([child, c_pos, c_rot, v.material_ref])
         m = self.get_mesh(v.solid_ref)
         mesh = Mesh(m.vertices, m.faces) # convert PyMesh mesh to Chroma mesh
         classification, kwargs = volume_classifier(v.name, v.material_ref, parent_material_ref)
         if classification == 'pmt':
             channel_type = kwargs.pop('channel_type',None)
             solid = Solid(mesh, **kwargs)
             detector.add_pmt(solid, displacement=pos, rotation=rot, channel_type=channel_type)   
         elif classification == 'solid':
             solid = Solid(mesh, **kwargs)
             detector.add_solid(solid, displacement=pos, rotation=rot)   
         elif classification == 'omit':
             pass
         else:
             raise Exception('Unknown volume classification: '+classification)
     return detector
Esempio n. 9
0
def mesh_from_ascii_stl(filename):
    "Return a mesh from an ascii stl file."
    if filename.endswith('.bz2'):
        f = bz2.BZ2File(filename)
    else:
        f = open(filename)

    vertices = []
    triangles = []
    vertex_map = {}

    while True:
        line = f.readline()

        if line == '':
            break

        if not line.strip().startswith('vertex'):
            continue

        triangle = [None] * 3
        for i in range(3):
            vertex = tuple([float(s) for s in line.strip().split()[1:]])

            if vertex not in vertex_map:
                vertices.append(vertex)
                vertex_map[vertex] = len(vertices) - 1

            triangle[i] = vertex_map[vertex]

            if i < 3:
                line = f.readline()

        triangles.append(triangle)

    f.close()

    return Mesh(np.array(vertices), np.array(triangles, dtype=np.uint32))
Esempio n. 10
0
    def visit(self, node, debug=False):
        """
        :param node: DAENode instance

        DAENode instances and their pycollada underpinnings meet chroma here

        Chroma needs sensitive detectors to have an associated surface 
        with detect property ...
        """
        #assert node.__class__.__name__ == 'DAENode'
        self.vcount += 1
        if self.vcount < 10:
            log.debug("visit : vcount %s node.index %s node.id %s " %
                      (self.vcount, node.index, node.id))

        bps = list(node.boundgeom.primitives())

        bpl = bps[0]

        assert len(bps) == 1 and bpl.__class__.__name__ == 'BoundPolylist'

        tris = bpl.triangleset()

        vertices = tris._vertex

        triangles = tris._vertex_index

        mesh = Mesh(vertices, triangles, remove_duplicate_vertices=False)

        material2, material1 = self.find_outer_inner_materials(node)

        surface = self.find_surface(
            node)  # lookup Chroma surface corresponding to the node
        if surface == None:
            surfacename = "NOT SPECIFIED"
        else:
            surfacename = surface.name
        if self.dump_node_info:
            print "[NODE %05d:%s]" % (
                node.index, node.lv.id
            ), " NTriangles=%d OuterMat=%s InnerMat=%s Surface=%s" % (len(
                mesh.triangles), material2.name, material1.name, surfacename)

        color = 0x33ffffff

        solid = Solid(mesh, material1, material2, surface, color)
        solid.node = node

        #
        # hmm a PMT is comprised of several volumes all of which
        # have the same associated channel_id
        #
        channel_id = getattr(node, 'channel_id', None)
        if not channel_id is None and channel_id > 0:
            self.channel_count += 1  # nodes with associated non zero channel_id
            self.channel_ids.add(channel_id)
            self.chroma_geometry.add_pmt(solid, channel_id=channel_id)
        else:
            self.chroma_geometry.add_solid(solid)
        pass

        if debug and self.vcount % 1000 == 0:
            print node.id
            print self.vcount, bpl, tris, tris.material
            print mesh
            #print mesh.assemble()
            bounds = mesh.get_bounds()
            extent = bounds[1] - bounds[0]
            print extent
Esempio n. 11
0
def build_checkerboard_scene(checkers_per_side=10, squares_per_checker=50):
    x = np.linspace(-5000.0, 5000.0,
                    checkers_per_side * squares_per_checker + 1)
    y = np.linspace(-5000.0, 5000.0,
                    checkers_per_side * squares_per_checker + 1)

    vertices = np.array(tuple(product(x, y, [0])))

    triangles = []
    for j in range(y.size - 1):
        for i in range(x.size - 1):
            triangles.append([
                j * len(x) + i, (j + 1) * len(x) + i, (j + 1) * len(x) + i + 1
            ])
            triangles.append(
                [j * len(x) + i, j * len(x) + i + 1, (j + 1) * len(x) + i + 1])

    checkerboard_mesh = Mesh(vertices,
                             triangles,
                             remove_duplicate_vertices=True)

    checkerboard_color_line1 = take(
        checkers_per_side * squares_per_checker * 2,
        cycle([0] * 2 * squares_per_checker +
              [0xffffff] * 2 * squares_per_checker)) * squares_per_checker
    checkerboard_color_line2 = take(
        checkers_per_side * squares_per_checker * 2,
        cycle([0xffffff] * 2 * squares_per_checker +
              [0] * 2 * squares_per_checker)) * squares_per_checker
    checkerboard_color = take(
        len(checkerboard_mesh.triangles),
        cycle(checkerboard_color_line1 + checkerboard_color_line2))

    checkerboard_surface_line1 = take(
        checkers_per_side * squares_per_checker * 2,
        cycle([black_surface] * 2 * squares_per_checker +
              [lambertian_surface] * 2 *
              squares_per_checker)) * squares_per_checker
    checkerboard_surface_line2 = take(
        checkers_per_side * squares_per_checker * 2,
        cycle([lambertian_surface] * 2 * squares_per_checker +
              [black_surface] * 2 * squares_per_checker)) * squares_per_checker
    checkerboard_surface = take(
        len(checkerboard_mesh.triangles),
        cycle(checkerboard_surface_line1 + checkerboard_surface_line2))

    checkerboard = Solid(checkerboard_mesh,
                         vacuum,
                         vacuum,
                         surface=checkerboard_surface,
                         color=checkerboard_color)

    sphere1 = Solid(sphere(1000.0, nsteps=512), water, vacuum)
    sphere2 = Solid(sphere(1000.0, nsteps=512),
                    vacuum,
                    vacuum,
                    surface=shiny_surface)
    sphere3 = Solid(sphere(1000.0, nsteps=512),
                    vacuum,
                    vacuum,
                    surface=lambertian_surface)

    checkerboard_scene = Geometry()
    checkerboard_scene.add_solid(checkerboard, displacement=(0, 0, -1500.0))
    checkerboard_scene.add_solid(sphere1, displacement=(2000.0, -2000.0, 0))
    checkerboard_scene.add_solid(sphere2, displacement=(-2000.0, -2000.0, 0))
    checkerboard_scene.add_solid(sphere3, displacement=(0.0, 2000.0, 0))

    return checkerboard_scene