コード例 #1
0
    def read_mesh_from_filename(self, filename, meshcls):
        if not os.path.isfile(filename):
            raise FileNotFoundError("No such file: '%s'" % filename)
        extension = filename[(filename.rfind(".") + 1):]
        if extension == "dae": # no dae support yet
            #mesh = Mesh.from_dae(filename)
            obj_filename = filename.replace(".dae", ".obj")
            if os.path.isfile(obj_filename):
                mesh = Mesh.from_obj(obj_filename)
                # former DAE files have yaxis and zaxis swapped
                # TODO: already fix in conversion to obj
                frame = Frame([0,0,0], [1,0,0], [0,0,1])
                T = Transformation.from_frame(frame)
                mesh_transform(mesh, T)
            else:
                raise FileNotFoundError("Please convert '%s' into an OBJ file, \
                                         since DAE is currently not supported \
                                         yet." % filename)
        elif extension == "obj":
            mesh = Mesh.from_obj(filename)
        elif extension == "stl":
            mesh = Mesh.from_stl(filename)
        else:
            raise ValueError("%s file types not yet supported" %
                extension.upper())

        return meshcls(mesh)
コード例 #2
0
    def transform(self, transformation):
        """Transforms the element.

        Parameters
        ----------
        transformation : :class:`Transformation`

        Returns
        -------
        None

        Examples
        --------
        >>> from compas.geometry import Box
        >>> from compas.geometry import Translation
        >>> element = Element.from_box(Box(Frame.worldXY(), 1, 1, 1))
        >>> element.transform(Translation([1, 0, 0]))
        """
        self.frame.transform(transformation)
        if self._gripping_frame:
            self.gripping_frame.transform(transformation)
        if self._source:
            if type(self._source) == Mesh:
                mesh_transform(
                    self._source, transformation
                )  # it would be really good to have Mesh.transform()
            else:
                self._source.transform(transformation)
コード例 #3
0
ファイル: transformations.py プロジェクト: yijiangh/compas
def mesh_transformed(mesh, transformation):
    """Transform a copy of ``mesh``.

    Parameters
    ----------
    mesh : Mesh
        The mesh.
    transformation : Transformation
        The transformation.

    Returns
    -------
    Mesh
        A transformed independent copy of ``mesh``.

    Notes
    -----
    The original mesh is not modified.
    Instead a transformed independent copy is returned.

    Examples
    --------
    >>> mesh = Mesh.from_obj(compas.get('cube.obj'))
    >>> T = matrix_from_axis_and_angle([0, 0, 1], pi / 4)
    >>> tmesh = mesh_transformed(mesh, T)
    >>> viewer.mesh = tmesh  # this should be a list of meshes
    >>> viewer.show()

    """
    mesh_copy = mesh.copy()
    mesh_transform(mesh_copy, transformation)
    return mesh_copy
コード例 #4
0
    def scale(self, transformation):
        """Scales the collision mesh.

        Parameters
        ----------
        transformation : compas.geometry.Scale
        """
        mesh_transform(self.mesh, transformation)
コード例 #5
0
def _mesh_import(url, filename):
    """Internal function to load meshes using the correct loader.

    Name and file might be the same but not always, e.g. temp files."""
    file_extension = _get_file_format(url)

    if file_extension not in SUPPORTED_FORMATS:
        raise NotImplementedError(
            'Mesh type not supported: {}'.format(file_extension))
    
    print(filename)
    
    if file_extension == "dae": # no dae support yet
        #mesh = Mesh.from_dae(filename)
        obj_filename = filename.replace(".dae", ".obj")
        if os.path.isfile(obj_filename):
            mesh = Mesh.from_obj(obj_filename)
            # former DAE files have yaxis and zaxis swapped
            # TODO: already fix in conversion to obj
            frame = Frame([0,0,0], [1,0,0], [0,0,1])
            T = Transformation.from_frame(frame)
            mesh_transform(mesh, T)
            return mesh
        else:
            raise FileNotFoundError("Please convert '%s' into an OBJ file, \
                                        since DAE is currently not supported \
                                        yet." % filename)

    if file_extension == 'obj':
        return Mesh.from_obj(filename)
    elif file_extension == 'stl':
        return Mesh.from_stl(filename)
    elif file_extension == 'ply':
        return Mesh.from_ply(filename)

    raise Exception
コード例 #6
0
def _dae_mesh_importer(filename, precision):
    """This is a very simple implementation of a DAE/Collada parser.

    Collada specification: https://www.khronos.org/files/collada_spec_1_5.pdf
    """
    dae = XML.from_file(filename)
    meshes = []
    visual_scenes = dae.root.find('library_visual_scenes')
    materials = dae.root.find('library_materials')
    effects = dae.root.find('library_effects')

    for geometry in dae.root.findall('library_geometries/geometry'):
        mesh_xml = geometry.find('mesh')
        mesh_id = geometry.attrib['id']
        matrix_node = visual_scenes.find('visual_scene/node/instance_geometry[@url="#{}"]/../matrix'.format(mesh_id))
        transform = None

        if matrix_node is not None:
            M = [float(i) for i in matrix_node.text.split()]

            # If it's the identity matrix, then ignore, we don't need to transform it
            if M != [1., 0., 0., 0.,
                     0., 1., 0., 0.,
                     0., 0., 1., 0.,
                     0., 0., 0., 1.]:
                M = M[0:4], M[4:8], M[8:12], M[12:16]
                transform = Transformation.from_matrix(M)

        # primitive elements can be any combination of:
        # lines, linestrips, polygons, polylist, triangles, trifans, tristrips
        # The current implementation only supports triangles and polylist of triangular meshes
        primitive_element_sets = []
        primitive_element_sets.extend(mesh_xml.findall('triangles'))
        primitive_element_sets.extend(mesh_xml.findall('polylist'))

        if len(primitive_element_sets) == 0:
            raise Exception('No primitive elements found (currently only triangles and polylist are supported)')

        for primitive_element_set in primitive_element_sets:
            primitive_tag = primitive_element_set.tag
            primitive_set_data = primitive_element_set.find('p').text.split()

            # Try to retrieve mesh colors
            mesh_colors = {}

            if materials is not None and effects is not None:
                try:
                    instance_effect = None
                    material_id = primitive_element_set.attrib.get('material')
                    primitive_count = int(primitive_element_set.attrib['count'])

                    if material_id is not None:
                        instance_effect = materials.find('material[@id="{}"]/instance_effect'.format(material_id))

                    if instance_effect is not None:
                        instance_effect_id = instance_effect.attrib['url'][1:]
                        colors = effects.findall('effect[@id="{}"]/profile_COMMON/technique/phong/*/color'.format(instance_effect_id))
                        for color_node in colors:
                            rgba = [float(i) for i in color_node.text.split()]
                            mesh_colors['mesh_color.{}'.format(color_node.attrib['sid'])] = rgba
                except Exception:
                    LOGGER.exception('Exception while loading materials, all materials of mesh file %s will be ignored ', filename)

            # Parse vertices
            all_offsets = sorted([int(i.attrib['offset']) for i in primitive_element_set.findall('input[@offset]')])
            if not all_offsets:
                raise Exception('Primitive element node does not contain offset information! Primitive tag={}'.format(primitive_tag))

            vertices_input = primitive_element_set.find('input[@semantic="VERTEX"]')
            vertices_id = vertices_input.attrib['source'][1:]
            vertices_link = mesh_xml.find('vertices[@id="{}"]/input'.format(vertices_id))
            positions = mesh_xml.find('source[@id="{}"]/float_array'.format(vertices_link.attrib['source'][1:]))
            positions = positions.text.split()

            vertices = [[float(p) for p in positions[i:i + 3]] for i in range(0, len(positions), 3)]

            # Parse faces
            # Every nth element is a vertex key, we ignore the rest based on the offsets defined
            # Usually, every second item is the normal, but there can be other items offset in there (vertex tangents, etc)
            skip_step = 1 + all_offsets[-1]

            if primitive_tag == 'triangles':
                vcount = [3] * primitive_count
            elif primitive_tag == 'polylist':
                vcount = [int(v) for v in primitive_element_set.find('vcount').text.split()]

            if len(vcount) != primitive_count:
                raise Exception('Primitive count does not match vertex per face count, vertex input id={}'.format(vertices_id))

            fkeys = [int(f) for f in primitive_set_data[::skip_step]]
            faces = []
            for i in range(primitive_count):
                a = i * vcount[i]
                b = a + vcount[i]
                faces.append(fkeys[a:b])

            # Rebuild vertices and faces using the same logic that other importers
            # use remapping everything based on a selected precision
            index_key = OrderedDict()
            vertex = OrderedDict()

            for i, xyz in enumerate(vertices):
                key = geometric_key(xyz, precision)
                index_key[i] = key
                vertex[key] = xyz

            key_index = {key: index for index, key in enumerate(vertex)}
            index_index = {index: key_index[key] for index, key in iter(index_key.items())}
            vertices = [xyz for xyz in iter(vertex.values())]
            faces = [[index_index[index] for index in face] for face in faces]

            mesh = Mesh.from_vertices_and_faces(vertices, faces)

            if mesh_colors:
                mesh.attributes.update(mesh_colors)

            if transform:
                mesh_transform(mesh, transform)

            meshes.append(mesh)

    return meshes
コード例 #7
0
# empty assembly

assembly = Assembly()

# add bricks in a staggered pattern

for i in range(number_of_courses):
    dy = i * height

    if i % 2 == 0:
        # in the even rows
        # add (number_of_even_bricks) full bricks

        for j in range(number_of_even_bricks):
            block = brick.copy()
            mesh_transform(block, Translation([j * (width + gap), 0, dy]))
            assembly.add_block(block)
    else:
        # in the uneven rows
        # add a half brick
        # add (number_of_even_bricks - 1) full bricks
        # add a half brick

        block = halfbrick.copy()
        mesh_transform(block, Translation([0, 0, dy]))
        assembly.add_block(block)

        for j in range(number_of_even_bricks - 1):
            block = brick.copy()
            mesh_transform(block,
                           Translation([(0.5 + j) * (width + gap), 0, dy]))
コード例 #8
0
assembly = Assembly()

# default block

box = Box.from_width_height_depth(W, H, D)
block = Block.from_vertices_and_faces(box.vertices, box.faces)

# make all blocks
# place each block on top of previous
# shift block randomly in XY plane

for i in range(N):
    b = block.copy()

    factor = choice([0.01, -0.01, 0.05, -0.05, 0.1, -0.1])
    axis = choice([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
    vector = scale_vector(axis, factor)

    T = Translation([vector[0], vector[1], i * H])
    mesh_transform(b, T)

    assembly.add_block(b, is_support=(i == 0))

# identify_interfaces

assembly_interfaces_numpy(assembly)

# compute interface forces

compute_interface_forces_cvx(assembly, solver='CPLEX', verbose=True)
コード例 #9
0
loop = trimesh_subdivide_loop
frames = mesh_subdivide_frames

box = Box.from_corner_corner_height((0.0, 0.0, 0.0), (1.0, 1.0, 0.0), 1.0)
mesh = Mesh.from_shape(box)

trimesh = mesh.copy()
mesh_quads_to_triangles(trimesh)

tri_mesh = tri(mesh, k=3)
quad_mesh = quad(mesh, k=3)
ck_mesh = ck(mesh, k=3)
corner_mesh = corner(mesh, k=3)
doosabin_mesh = doosabin(mesh, k=3)
loop_mesh = loop(trimesh, k=3)
frames_mesh = frames(mesh, 0.1)

mesh_transform(quad_mesh, Translation([1.2, 0.0, 0.0]))
mesh_transform(corner_mesh, Translation([1.2 * 2, 0.0, 0.0]))
mesh_transform(frames_mesh, Translation([1.2 * 3, 0.0, 0.0]))
mesh_transform(ck_mesh, Translation([1.2 * 4, 0.0, 0.0]))
mesh_transform(doosabin_mesh, Translation([1.2 * 5, 0.0, 0.0]))
mesh_transform(loop_mesh, Translation([1.2 * 6, 0.0, 0.0]))

viewer = MultiMeshViewer()
viewer.meshes = [
    tri_mesh, quad_mesh, corner_mesh, frames_mesh, ck_mesh, doosabin_mesh,
    loop_mesh
]
viewer.show()
コード例 #10
0
key_color = vertex_coloring(dual.adjacency)
c = len(set(key_color.values()))
colors = Colormap(list(range(c)), 'rgb')
facecolor = {key: colors(key_color[key]) for key in dual.vertices()}

# the artist for drawing various versions of the mesh
artist = MeshArtist(mesh)

# mesh
mesh.name = "Mesh"
artist.clear()
artist.draw_mesh()

# edges
mesh.name = "Edges"
mesh_transform(mesh, X)
artist.clear()
artist.draw_edges()

# vertices
mesh.name = "Vertices"
mesh_transform(mesh, X)
artist.clear()
artist.draw_vertices(color=vertexcolor)
artist.draw_edges(color=(255, 255, 255))

# faces
mesh.name = "Faces"
mesh_transform(mesh, X)
artist.clear()
artist.draw_faces(color=facecolor)
コード例 #11
0
ANGLES = [radians(1), radians(-1), radians(2), radians(-2)]

# load an assembly

assembly = Assembly.from_json(compas_assembly.get('stack.json'))

# shift and rotate in random directions
# use small increments ("imperfections")

for key in assembly.vertices():
    block = assembly.blocks[key]

    R = Rotation.from_axis_and_angle(choice(XYZ), choice(ANGLES), block.centroid())
    T = Translation(scale_vector(choice(XYZ), choice([0.01, -0.01])))

    mesh_transform(block, T.concatenate(R))

# serialise

assembly.to_json(compas_assembly.get('assembly.json'))

# visualise

R = Rotation.from_axis_and_angle([1.0, 0, 0], -pi / 2)
assembly_transform(assembly, R)

plotter = AssemblyPlotter(assembly, tight=True)

plotter.draw_vertices(text={key: str(key) for key, attr in assembly.vertices(True)})
plotter.draw_blocks(
    facecolor={key: '#ff0000' for key in assembly.vertices_where({'is_support': True})}
コード例 #12
0
from compas.geometry import Translation
from compas.geometry import Scale
from compas.geometry import length_vector
from compas_viewers.multimeshviewer import MultiMeshViewer

tetra = Mesh.from_polyhedron(4)
hexa = Mesh.from_polyhedron(6)
octa = Mesh.from_polyhedron(8)
dodeca = Mesh.from_polyhedron(12)
icosa = Mesh.from_polyhedron(20)

meshes = [tetra, hexa, octa, dodeca, icosa]
for i, mesh in enumerate(meshes):
    radius = length_vector(mesh.vertex_attributes(mesh.get_any_vertex(),
                                                  'xyz'))
    scale = 1 / radius
    T = Translation([2.2 * i, 0.0, 0.0])
    S = Scale([scale, scale, scale])
    X = T * S
    mesh_transform(mesh, X)

duals = []
for mesh in meshes:
    dual = mesh_dual(mesh)
    duals.append(dual)
    mesh_transform(dual, Translation([0.0, 2.2, 0.0]))

viewer = MultiMeshViewer()
viewer.meshes = meshes + duals
viewer.show()
コード例 #13
0
box = Box.from_width_height_depth(W, H, D)
brick = Block.from_vertices_and_faces(box.vertices, box.faces)

# make all blocks
# place each block on top of previous
# shift block randomly in XY plane

for i in range(N):
    block = brick.copy()

    factor = choice([+0.01, -0.01, +0.05, -0.05, +0.1, -0.1])
    axis = choice([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
    vector = add_vectors(scale_vector(axis, factor), [0.0, 0.0, i * H])

    mesh_transform(block, Translation(vector))

    if i == 0:
        assembly.add_block(block, is_support=True)
    else:
        assembly.add_block(block)

# export to json

assembly.to_json(compas_assembly.get('stack.json'))

# visualise

R = Rotation.from_axis_and_angle([1.0, 0, 0], -pi / 2)
assembly_transform(assembly, R)
コード例 #14
0
from compas_rbe.equilibrium import compute_interface_forces_cvx

assembly = Assembly()

b1 = Block.from_polyhedron(6)
b2 = Block.from_polyhedron(6)

u, v = list(b1.edges())[0]

l = b1.edge_length(u, v)

T1 = Translation([0, 0, -0.5 * l])
T2 = Translation([0, 0, +0.5 * l])

mesh_transform(b1, T1)
mesh_transform(b2, T2)

assembly.add_block(b1, is_support=True)
assembly.add_block(b2)

# identify block interfaces and update block_model

assembly_interfaces(
    assembly,
    nmax=10,
    tmax=0.05,
    amin=0.01,
    lmin=0.01,
)
コード例 #15
0
from math import pi

from compas.utilities import print_profile
from compas.geometry import Box
from compas.geometry import matrix_from_translation
from compas.geometry import Translation
from compas.geometry import Rotation
from compas.datastructures import Mesh
from compas.datastructures import mesh_transform

mesh_transform = print_profile(mesh_transform)

box = Box.from_corner_corner_height([0.0, 0.0, 0.0], [1.0, 1.0, 0.0], 1.0)
mesh = Mesh.from_vertices_and_faces(box.vertices, box.faces)

T = matrix_from_translation([-2.0, 0.0, 3.0])
T = Translation([-2.0, 0.0, 3.0])
R = Rotation.from_axis_and_angle([0.0, 0.0, 1.0], pi / 2)

mesh_transform(mesh, R)

print(mesh.get_vertices_attribute('x'))
コード例 #16
0
bbox = bounding_box_xy(points)

# make a support block of the same size as the bounding box

support = Block.from_vertices_and_faces(bbox, [[0, 1, 2, 3]])

# scale the support

lx = length_vector(subtract_vectors(bbox[1], bbox[0]))
ly = length_vector(subtract_vectors(bbox[2], bbox[1]))
sx = (0.0 + lx) / lx
sy = (0.0 + ly) / ly

S = Scale([sx, sy, 1.0])
mesh_transform(support, S)

# align the centroid of the support with the centroid of the bounding box

b = centroid_points(bbox)
a = support.centroid()

mesh_transform(support, Translation(subtract_vectors(b, a)))

# add the support to the assembly

assembly.add_block(support, is_support=True, is_placed=True)

# serialise

assembly.to_json(compas_assembly.get('wall_supported.json'))