示例#1
0
def surf2mesh(S, P=(0, 0, 0), D=(0, 0, 0), wire=False):

    color = "#ffff00"

    points, polylist = S.polylist()

    #Conversion para quethreejs la entienda

    polylist = list(polylist)

    lpoly = []
    lpoints = []

    for l in points:
        lpoints.append(list(l))

    for l in polylist:
        lpoly.append(list(map(int, l)))

    vertices = lpoints

    faces = lpoly

    # Map the vertex colors into the 'color' slot of the faces
    # Map the normals
    nfaces = []
    for f in faces:
        p0 = points[f[0]]
        p1 = points[f[1]]
        p2 = points[f[2]]
        v0 = array(p1) - array(p0)
        v1 = array(p2) - array(p0)
        v3 = cross(v0, v1)
        v3 = tuple(v3 / sqrt(v3[0]**2 + v3[1]**2 + v3[2]**2))

        nfaces.append(f + [v3, color, None])

    # Create the geometry:

    surfaceGeometry = py3js.Geometry(
        vertices=vertices,
        faces=nfaces,
        #colors=vertexcolors
    )

    #surfaceGeometry = py3js.SphereGeometry(radius=300, widthSegments=32, heightSegments=24)

    if wire:
        surfaceGeometry = py3js.WireframeGeometry(surfaceGeometry)

    # Calculate normals per face, for nice crisp edges:
    surfaceGeometry.exec_three_obj_method('computeFaceNormals')

    surfaceMaterial = py3js.MeshPhongMaterial(color=color,
                                              ambient="#050505",
                                              specular="#ffffff",
                                              shininess=15,
                                              emissive="#000000",
                                              side='DoubleSide',
                                              transparent=True,
                                              opacity=.8)
    #surfaceMaterial = py3js.MeshLambertMaterial(color='red',side='DoubleSide')

    # Create a mesh. Note that the material need to be told to use the vertex colors.
    surfaceMesh = py3js.Mesh(
        geometry=surfaceGeometry,
        material=surfaceMaterial,
    )

    surfaceMesh.rotation = *D, "ZYX"
    surfaceMesh.position = tuple(P)
    return surfaceMesh
示例#2
0
def to_surf_mesh(actor, surf, mapper, prop, add_attr={}):
    """Convert a pyvista surface to a buffer geometry.

    General Notes
    -------------

    * THREE.BufferGeometry expects position and index attributes
      representing a triangulated mesh points and face indices or just
      a position array representing individual faces of a mesh.
    * The normals attribute is needed for physically based rendering,
      but not for the other mesh types.
    * Colors must be a RGB array with one value per point.

    Shading Notes
    -------------
    To match VTK, the following materials are used to match VTK's shading:

    * MeshPhysicalMaterial when physically based rendering is enabled
    * MeshPhongMaterial when physically based rendering is disabled,
      but lighting is enabled.
    * MeshBasicMaterial when lighting is disabled.

    """
    # convert to an all-triangular surface
    if surf.is_all_triangles():
        trimesh = surf
    else:
        trimesh = surf.triangulate()

    position = array_to_float_buffer(trimesh.points)

    # convert to minimum index type
    face_ind = trimesh.faces.reshape(-1, 4)[:, 1:]
    index = cast_to_min_size(face_ind, trimesh.n_points)
    attr = {
        'position': position,
        'index': index,
    }

    if prop.GetInterpolation():  # something other than flat shading
        attr['normal'] = buffer_normals(trimesh)

    # extract point/cell scalars for coloring
    colors = None
    scalar_mode = mapper.GetScalarModeAsString()
    if scalar_mode == 'UsePointData':
        colors = map_scalars(mapper, trimesh.point_data.active_scalars)
    elif scalar_mode == 'UseCellData':
        # special handling for RGBA
        if mapper.GetColorMode() == 2:
            scalars = trimesh.cell_data.active_scalars.repeat(3, axis=0)
            scalars = scalars.astype(np.float32, copy=False)
            colors = scalars[:, :3] / 255  # ignore alpha
        else:
            # must repeat for each triangle
            scalars = trimesh.cell_data.active_scalars.repeat(3)
            colors = map_scalars(mapper, scalars)

        position = array_to_float_buffer(trimesh.points[face_ind])
        attr = {'position': position}

    # add colors to the buffer geometry attributes
    if colors is not None:
        attr['color'] = array_to_float_buffer(colors)

    # texture coordinates
    t_coords = trimesh.active_t_coords
    if t_coords is not None:
        attr['uv'] = array_to_float_buffer(t_coords)

    # TODO: Convert PBR textures
    # base_color_texture = prop.GetTexture("albedoTex")
    # orm_texture = prop.GetTexture("materialTex")
    # anisotropy_texture = prop.GetTexture("anisotropyTex")
    # normal_texture = prop.GetTexture("normalTex")
    # emissive_texture = prop.GetTexture("emissiveTex")
    # coatnormal_texture = prop.GetTexture("coatNormalTex")
    if prop.GetNumberOfTextures():  # pragma: no cover
        warnings.warn(
            'pythreejs converter does not support PBR textures (yet).')

    # create base buffer geometry
    surf_geo = tjs.BufferGeometry(attributes=attr)

    # add texture to the surface buffer if available
    texture = actor.GetTexture()
    tjs_texture = None
    if texture is not None:
        wrapped_tex = pv.wrap(texture.GetInput())
        data = wrapped_tex.active_scalars
        dim = (wrapped_tex.dimensions[0], wrapped_tex.dimensions[1],
               data.shape[1])
        data = data.reshape(dim)
        fmt = "RGBFormat" if data.shape[1] == 3 else "RGBAFormat"

        # Create data texture and catch invalid warning
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore",
                                    message="Given trait value dtype")
            tjs_texture = tjs.DataTexture(data=data,
                                          format="RGBFormat",
                                          type="UnsignedByteType")

    # these attributes are always used regardless of the material
    shared_attr = {
        'vertexColors': get_coloring(mapper, trimesh),
        'wireframe': prop.GetRepresentation() == 1,
        'opacity': prop.GetOpacity(),
        'wireframeLinewidth': prop.GetLineWidth(),
        # 'side': 'DoubleSide'  # enabling seems to mess with textures
    }

    if colors is None:
        shared_attr['color'] = color_to_hex(prop.GetColor())

    if tjs_texture is not None:
        shared_attr['map'] = tjs_texture
    else:
        shared_attr['side'] = 'DoubleSide'

    if prop.GetOpacity() < 1.0:
        shared_attr['transparent'] = True

    if prop.GetInterpolation() == 3:  # using physically based rendering
        material = tjs.MeshPhysicalMaterial(flatShading=False,
                                            roughness=prop.GetRoughness(),
                                            metalness=prop.GetMetallic(),
                                            reflectivity=0,
                                            **shared_attr,
                                            **add_attr)
    elif prop.GetLighting():
        # specular disabled to fix lighting issues
        material = tjs.MeshPhongMaterial(
            shininess=0,
            flatShading=prop.GetInterpolation() == 0,
            specular=color_to_hex((0, 0, 0)),
            reflectivity=0,
            **shared_attr,
            **add_attr)
    else:  # no lighting
        material = tjs.MeshBasicMaterial(**shared_attr, **add_attr)

    return tjs.Mesh(geometry=surf_geo, material=material)
示例#3
0
    def __initialize_mesh(self):
        drawable_geometry = self.__get_drawable_from_boundary()

        #No color under textures or materials
        if len(self.geometry.material) != 0 or self.geometry.texture is not None:
            vertexEnum = 'NoColors'
        else:
            vertexEnum = 'FaceColors'
        materials = []

        #LambertMaterial is a material for non-shiny surfaces, without specular highlights.
        if len(self.geometry.material) == 0: #No material or texture

            material_geometry = three.MeshLambertMaterial(
                                           map = self.getTexture(self.texture),
                                           polygonOffset=True,
                                           polygonOffsetFactor=1,
                                           polygonOffsetUnits=1,
                                           flatShading = True,
                                           opacity = 1.,
                                           transparent = False,
                                           side = 'DoubleSide',
                                           wireframe=False,
                                           vertexColors = vertexEnum)
            materials = material_geometry


        else:

            for m in self.geometry.material:
                if self.geometry.smoothness:
                    material_geometry = three.MeshLambertMaterial(
                        map=self.getTexture(self.geometry.material[m]["map_kd"]),
                        color=self.color(self.geometry.material[m]["kd"]),
                        emissiveIntensity=self.geometry.material[m]["ke"],
                        specular=self.color(self.geometry.material[m]["ks"]),
                        shininess=self.geometry.material[m]["ns"],
                        transparence=self.geometry.material[m]["transparence"],
                        opacity=self.geometry.material[m]["opacity"],
                        emissiveMap=self.getTexture(self.geometry.material[m]["map_ke"]),
                        alphaMap=self.getTexture(self.geometry.material[m]["map_d"]),
                        specularMap=self.getTexture(self.geometry.material[m]["map_ks"]),
                        bumpMap=self.getTexture(self.geometry.material[m]["bump"]),
                        normalMap=self.getTexture(self.geometry.material[m]["norm"]),
                        refractionRatio=self.geometry.material[m]["ni"]
                    )
                else:
                    material_geometry = three.MeshPhongMaterial(
                        map = self.getTexture(self.geometry.material[m]["map_kd"]),
                        color = self.color(self.geometry.material[m]["kd"]),
                        emissiveIntensity = self.geometry.material[m]["ke"],
                        specular = self.color(self.geometry.material[m]["ks"]),
                        shininess  =self.geometry.material[m]["ns"],
                        transparence = self.geometry.material[m]["transparence"],
                        opacity = self.geometry.material[m]["opacity"],
                        emissiveMap = self.getTexture(self.geometry.material[m]["map_ke"]),
                        alphaMap = self.getTexture(self.geometry.material[m]["map_d"]),
                        specularMap = self.getTexture(self.geometry.material[m]["map_ks"]),
                        bumpMap = self.getTexture(self.geometry.material[m]["bump"]),
                        normalMap = self.getTexture(self.geometry.material[m]["norm"]),
                        refractionRatio = self.geometry.material[m]["ni"]
                    )

                materials.append(material_geometry)

        mesh1 = three.Mesh(
                geometry=drawable_geometry,
                material=materials,
                position=[0, 0, 0]
            )

        return mesh1
示例#4
0
def visualise(mesh,
              geometric_field,
              number_of_dimensions,
              xi_interpolation,
              dependent_field=None,
              variable=None,
              mechanics_animation=False,
              colour_map_dependent_component_number=None,
              cmap='gist_rainbow',
              resolution=1,
              node_labels=False):

    if number_of_dimensions != 3:
        print(
            'Warning: Only visualisation of 3D meshes is currently supported.')
        return

    if xi_interpolation != [1, 1, 1]:
        print(
            'Warning: Only visualisation of 3D elements with linear Lagrange \
            interpolation along all coordinate directions is currently \
            supported.')
        return

    view_width = 600
    view_height = 600

    debug = False
    if debug:
        vertices = [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0],
                    [1, 0, 1], [1, 1, 0], [1, 1, 1]]

        faces = [[0, 1, 3], [0, 3, 2], [0, 2, 4], [2, 6, 4], [0, 4, 1],
                 [1, 4, 5], [2, 3, 6], [3, 7, 6], [1, 5, 3], [3, 5, 7],
                 [4, 6, 5], [5, 6, 7]]

        vertexcolors = [
            '#000000', '#0000ff', '#00ff00', '#ff0000', '#00ffff', '#ff00ff',
            '#ffff00', '#ffffff'
        ]
    else:
        # Get mesh topology information.
        num_nodes = mesh_tools.num_nodes_get(mesh, mesh_component=1)
        node_nums = list(range(1, num_nodes + 1))
        num_elements, element_nums = mesh_tools.num_element_get(
            mesh, mesh_component=1)

        # Convert geometric field to a morphic mesh and export to json
        mesh = mesh_tools.OpenCMISS_to_morphic(mesh,
                                               geometric_field,
                                               element_nums,
                                               node_nums,
                                               dimension=3,
                                               interpolation='linear')
        vertices, faces, _, xi_element_nums, xis = get_faces(
            mesh, res=resolution, exterior_only=True, include_xi=True)

        vertices = vertices.tolist()
        faces = faces.tolist()

    centroid = np.mean(vertices, axis=0)
    max_positions = np.max(vertices, axis=0)
    min_positions = np.min(vertices, axis=0)
    range_positions = max_positions - min_positions

    if (dependent_field is not None) and (colour_map_dependent_component_number
                                          is not None):

        solution = np.zeros(xis.shape[0])
        for idx, (xi, xi_element_num) in enumerate(zip(xis, xi_element_nums)):
            solution[idx] = mesh_tools.interpolate_opencmiss_field_xi(
                dependent_field,
                xi,
                element_ids=[xi_element_num],
                dimension=3,
                deriv=1)[colour_map_dependent_component_number - 1]

        minima = min(solution)
        maxima = max(solution)

        import matplotlib
        norm = matplotlib.colors.Normalize(vmin=minima, vmax=maxima, clip=True)
        mapper = cm.ScalarMappable(norm=norm, cmap=cm.get_cmap(name=cmap))

        vertex_colors = np.zeros((len(vertices), 3), dtype='float32')
        for idx, v in enumerate(solution):
            vertex_colors[idx, :] = mapper.to_rgba(v, alpha=None)[:3]
        # else:
        #     raise ValueError('Visualisation not supported.')
    else:
        vertex_colors = np.tile(np.array([0.5, 0.5, 0.5], dtype='float32'),
                                (len(vertices), 1))

    geometry = pjs.BufferGeometry(attributes=dict(
        position=pjs.BufferAttribute(vertices, normalized=False),
        index=pjs.BufferAttribute(
            np.array(faces).astype(dtype='uint16').ravel(), normalized=False),
        color=pjs.BufferAttribute(vertex_colors),
    ))

    if mechanics_animation:
        deformed_vertices = np.zeros((xis.shape[0], 3), dtype='float32')
        for idx, (xi, xi_element_num) in enumerate(zip(xis, xi_element_nums)):
            deformed_vertices[idx, :] = \
            mesh_tools.interpolate_opencmiss_field_xi(
                dependent_field, xi, element_ids=[xi_element_num],
                dimension=3,
                deriv=1)[0][:3]
        geometry.morphAttributes = {
            'position': [
                pjs.BufferAttribute(deformed_vertices),
            ]
        }

        geometry.exec_three_obj_method('computeFaceNormals')
        geometry.exec_three_obj_method('computeVertexNormals')

        surf1 = pjs.Mesh(geometry,
                         pjs.MeshPhongMaterial(color='#ff3333',
                                               shininess=150,
                                               morphTargets=True,
                                               side='FrontSide'),
                         name='A')
        surf2 = pjs.Mesh(geometry,
                         pjs.MeshPhongMaterial(color='#ff3333',
                                               shininess=150,
                                               morphTargets=True,
                                               side='BackSide'),
                         name='B')
        surf = pjs.Group(children=[surf1, surf2])

        # camera = pjs.PerspectiveCamera(
        #     fov=20, position=[range_positions[0] * 10,
        #                       range_positions[1] * 10,
        #                       range_positions[2] * 10],
        #     width=view_width,
        #     height=view_height, near=1,
        #     far=max(range_positions) * 10)

        camera = pjs.PerspectiveCamera(position=[
            range_positions[0] * 3, range_positions[1] * 3,
            range_positions[2] * 3
        ],
                                       aspect=view_width / view_height)
        camera.up = [0, 0, 1]
        camera.lookAt(centroid.tolist())

        scene3 = pjs.Scene(children=[
            surf1, surf2, camera,
            pjs.DirectionalLight(position=[3, 5, 1], intensity=0.6),
            pjs.AmbientLight(intensity=0.5)
        ])
        axes = pjs.AxesHelper(size=range_positions[0] * 2)
        scene3.add(axes)

        A_track = pjs.NumberKeyframeTrack(
            name='scene/A.morphTargetInfluences[0]',
            times=[0, 3],
            values=[0, 1])
        B_track = pjs.NumberKeyframeTrack(
            name='scene/B.morphTargetInfluences[0]',
            times=[0, 3],
            values=[0, 1])
        pill_clip = pjs.AnimationClip(tracks=[A_track, B_track])
        pill_action = pjs.AnimationAction(pjs.AnimationMixer(scene3),
                                          pill_clip, scene3)

        renderer3 = pjs.Renderer(
            camera=camera,
            scene=scene3,
            controls=[pjs.OrbitControls(controlling=camera)],
            width=view_width,
            height=view_height)

        display(renderer3, pill_action)

    else:
        geometry.exec_three_obj_method('computeFaceNormals')
        geometry.exec_three_obj_method('computeVertexNormals')

        surf1 = pjs.Mesh(geometry=geometry,
                         material=pjs.MeshLambertMaterial(
                             vertexColors='VertexColors',
                             side='FrontSide'))  # Center the cube.
        surf2 = pjs.Mesh(geometry=geometry,
                         material=pjs.MeshLambertMaterial(
                             vertexColors='VertexColors',
                             side='BackSide'))  # Center the cube.
        surf = pjs.Group(children=[surf1, surf2])

        camera = pjs.PerspectiveCamera(position=[
            range_positions[0] * 3, range_positions[1] * 3,
            range_positions[2] * 3
        ],
                                       aspect=view_width / view_height)

        camera.up = [0, 0, 1]
        camera.lookAt(centroid.tolist())

        # if perspective:
        #     camera.mode = 'perspective'
        # else:
        #     camera.mode = 'orthographic'

        lights = [
            pjs.DirectionalLight(position=[
                range_positions[0] * 16, range_positions[1] * 12,
                range_positions[2] * 17
            ],
                                 intensity=0.5),
            pjs.AmbientLight(intensity=0.8),
        ]
        orbit = pjs.OrbitControls(controlling=camera,
                                  screenSpacePanning=True,
                                  target=centroid.tolist())

        scene = pjs.Scene()
        axes = pjs.AxesHelper(size=max(range_positions) * 2)
        scene.add(axes)
        scene.add(surf1)
        scene.add(surf2)
        scene.add(lights)

        if node_labels:
            # Add text labels for each mesh node.
            v, ids = mesh.get_node_ids(group='_default')
            for idx, v in enumerate(v):
                text = make_text(str(ids[idx]), position=(v[0], v[1], v[2]))
                scene.add(text)

        # Add text for axes labels.
        x_axis_label = make_text('x',
                                 position=(max(range_positions) * 2, 0, 0))
        y_axis_label = make_text('y',
                                 position=(0, max(range_positions) * 2, 0))
        z_axis_label = make_text('z',
                                 position=(0, 0, max(range_positions) * 2))
        scene.add(x_axis_label)
        scene.add(y_axis_label)
        scene.add(z_axis_label)

        renderer = pjs.Renderer(scene=scene,
                                camera=camera,
                                controls=[orbit],
                                width=view_width,
                                height=view_height)
        camera.zoom = 1
        display(renderer)

    return vertices, faces