Ejemplo n.º 1
0
def display_mesh_face_normals(mesh,
                              display=True,
                              layer=None,
                              scale=1.0,
                              color=(0, 0, 255)):

    guids = compas_rhino.get_objects(
        name='{0}.face.normal.*'.format(mesh.attributes['name']))
    compas_rhino.delete_objects(guids)

    if not display:
        return

    lines = []

    for fkey in mesh.faces():
        normal = mesh.face_normal(fkey)
        start = mesh.face_center(fkey)
        end = [start[axis] + normal[axis] for axis in range(3)]
        name = '{0}.face.normal.{1}'.format(mesh.attributes['name'], fkey)

        lines.append({
            'start': start,
            'end': end,
            'name': name,
            'color': color,
            'arrow': 'end',
        })

    compas_rhino.xdraw_lines(lines, layer=layer, clear=False, redraw=True)
Ejemplo n.º 2
0
    def draw_selfweight(self, scale=None, eps=None):
        """Draw vectors indicating the magnitude of the selfweight of the blocks.

        Parameters
        ----------
        scale : float, optional
            The scale at which the selfweight vectors should be drawn.
            Default is `0.1`.
        eps : float, optional
            A tolerance for drawing small vectors.
            Selfweight vectors with a scaled length smaller than this tolerance are not drawn.
            Default is `1e-3`.

        Notes
        -----
        * Selfweight vectors are drawn as Rhino lines with arrow heads.
        * The default color is *green*: `'#00ff00'` or `(0, 255, 0)`.
        * Selfweight vectors are drawn in a sub-layer *Selfweight* of the base layer, if a base layer was specified.
        * Selfweight vectors are named according to the following pattern: `"{assembly name}.selfweight.{block id}"`.

        """
        layer = "{}::Selfweight".format(self.layer) if self.layer else None
        scale = scale or self.defaults['scale.selfweight']
        eps = eps or self.defaults['eps.selfweight']
        color = self.defaults['color.selfweight']

        lines = []

        for key, attr in self.assembly.vertices(True):
            block = self.assembly.blocks[key]
            volume = block.volume()

            if volume * scale < eps:
                continue

            vector = [0.0, 0.0, -1.0 * volume * scale]

            sp = block.centroid()
            ep = sp[:]
            ep[2] += vector[2]

            lines.append({
                'start':
                sp,
                'end':
                ep,
                'name':
                "{}.selfweight.{}".format(self.assembly.name, key),
                'color':
                color,
                'arrow':
                'end'
            })

        compas_rhino.xdraw_lines(lines, layer=layer, clear=False, redraw=False)
Ejemplo n.º 3
0
    def draw_lines(self, lines, layer=None, clear_layer=False, redraw=False):
        """Draw a collection of lines.

        Parameters
        ----------
        lines : list of dict
            The lines to draw.
        layer : str, optional
            The layer to draw the points in.
            Default is ``None``.
        clear_layer : bool, optional
            Clear the specified layer.
            Default is ``False``.
        redraw : bool, optional
            Redraw the Rhino view.
            Default is ``False``.

        Returns
        -------
        list of guid
            The GUIDs of the points.

        """
        layer = layer or self.layer
        return compas_rhino.xdraw_lines(lines,
                                        layer=layer,
                                        clear=clear_layer,
                                        redraw=redraw)
Ejemplo n.º 4
0
def network_draw_loads(network, scale=1.0, layer=None, clear_layer=False):
    lines = []
    for key, attr in network.vertices(True):
        if not attr['is_fixed']:
            force = attr['px'], attr['py'], attr['pz']
            start = network.vertex_coordinates(key)
            end = [start[axis] + scale * force[axis] for axis in (0, 1, 2)]
            lines.append({
                'start': start,
                'end'  : end,
                'name' : '{}.load.{}'.format(network.name, key),
                'color': (0, 255, 255),
                'arrow': 'end',
            })
    guids = compas_rhino.get_objects(name='{}.load.*'.format(network.name))
    compas_rhino.delete_objects(guids)
    compas_rhino.xdraw_lines(lines, layer=layer, clear=clear_layer)
Ejemplo n.º 5
0
def display_network_residual_forces(network,
                                    display=True,
                                    layer=None,
                                    clear_layer=False,
                                    scale=1.0,
                                    color=(0, 255, 255),
                                    attr_name='is_anchor'):

    tol = compas_rhino.get_tolerance()
    guids = compas_rhino.get_objects(name='{0}.force:residual.*'.format(network.attributes['name']))
    compas_rhino.delete_objects(guids)

    if not display:
        return

    lines = []

    for key, attr in network.vertices(True):

        if attr[attr_name]:
            continue

        force  = attr['rx'], attr['ry'], attr['rz']
        start  = network.vertex_coordinates(key)
        end    = [start[i] + scale * force[i] for i in range(3)]
        length = distance_point_point(start, end)
        arrow  = 'end'
        name   = '{0}.force:residual.{1}'.format(network.attributes['name'], key)

        if length < tol:
            continue

        lines.append({
            'start' : start,
            'end'   : end,
            'name'  : name,
            'color' : color,
            'arrow' : arrow,
        })

    compas_rhino.xdraw_lines(lines, layer=layer, clear=clear_layer)
Ejemplo n.º 6
0
    def draw_edges(self, keys=None, color=None):
        """Draw a selection of edges of the network.

        Parameters
        ----------
        keys : list
            A list of edge keys (as uv pairs) identifying which edges to draw.
            The default is ``None``, in which case all edges are drawn.
        color : str, tuple, dict
            The color specififcation for the edges.
            Colors should be specified in the form of a string (hex colors) or
            as a tuple of RGB components.
            To apply the same color to all faces, provide a single color
            specification. Individual colors can be assigned using a dictionary
            of key-color pairs. Missing keys will be assigned the default face
            color (``self.defaults['face.color']``).
            The default is ``None``, in which case all faces are assigned the
            default edge color.

        Notes
        -----
        All edges are named using the following template:
        ``"{}.edge.{}-{}".fromat(self.datastructure.name, u, v)``.
        This name is used afterwards to identify edges of the network in the Rhino model.

        Examples
        --------
        >>> artist.draw_edges()
        >>> artist.draw_edges(color='#ff0000')
        >>> artist.draw_edges(color=(255, 0, 0))
        >>> artist.draw_edges(keys=self.datastructure.edges_xxx())
        >>> artist.draw_edges(color={(u, v): '#00ff00' for u, v in self.datastructure.edges_xxx()})

        """
        keys = keys or list(self.datastructure.edges())
        colordict = color_to_colordict(color,
                                       keys,
                                       default=self.defaults['color.edge'],
                                       colorformat='rgb',
                                       normalize=False)
        lines = []
        for u, v in keys:
            lines.append({
                'start': self.datastructure.vertex_coordinates(u),
                'end': self.datastructure.vertex_coordinates(v),
                'color': colordict[(u, v)],
                'name': self.datastructure.edge_name(u, v)
            })
        return compas_rhino.xdraw_lines(lines,
                                        layer=self.layer,
                                        clear=False,
                                        redraw=False)
Ejemplo n.º 7
0
    def draw_selfweight(self, scale=None, color=None):
        self.clear_selfweight()

        lines = []
        color = color or self.form.attributes['color.selfweight']
        scale = scale or self.form.attributes['scale.selfweight']
        tol = self.form.attributes['tol.selfweight']
        tol2 = tol**2

        for key, attr in self.form.vertices_where(
            {
                'is_anchor': False,
                'is_external': False
            }, True):
            t = attr['t']
            a = self.form.vertex_area(key)
            sp = self.form.vertex_coordinates(key)

            dz = scale * t * a

            if dz**2 < tol2:
                continue

            ep = sp[0], sp[1], sp[2] - dz

            lines.append({
                'start': sp,
                'end': ep,
                'color': color,
                'arrow': 'end',
                'name': "{}.selfweight.{}".format(self.form.name, key)
            })

        compas_rhino.xdraw_lines(lines,
                                 layer=self.layer,
                                 clear=False,
                                 redraw=False)
Ejemplo n.º 8
0
    def draw_reactions(self, scale=1.0, color=None):
        compas_rhino.delete_objects(
            compas_rhino.get_objects(
                name="{}.reaction.*".format(self.mesh.name)))

        color = color or (0, 255, 0)
        lines = []
        for key, attr in self.mesh.vertices(True):
            if not attr['is_anchor']:
                continue

            r = [attr['rx'], attr['ry'], attr['rz']]
            sp = [attr['x'], attr['y'], attr['z']]
            ep = add_vectors(sp, scale_vector(r, -scale))

            lines.append({
                'start': sp,
                'end': ep,
                'color': color,
                'name': "{}.reaction.{}".format(self.mesh.name, key),
                'arrow': 'end'
            })

        compas_rhino.xdraw_lines(lines, layer=self.layer, redraw=True)
Ejemplo n.º 9
0
    def draw_loads(self, scale=None, color=None):
        self.clear_loads()

        lines = []
        color = color or self.form.attributes['color.load']
        scale = scale or self.form.attributes['scale.load']
        tol = self.form.attributes['tol.load']
        tol2 = tol**2

        for key, attr in self.form.vertices_where(
            {
                'is_anchor': False,
                'is_external': False
            }, True):
            px = scale * attr['px']
            py = scale * attr['py']
            pz = scale * attr['pz']

            if px**2 + py**2 + pz**2 < tol2:
                continue

            sp = self.form.vertex_coordinates(key)
            ep = sp[0] + px, sp[1] + py, sp[2] + pz

            lines.append({
                'start': sp,
                'end': ep,
                'color': color,
                'arrow': 'end',
                'name': "{}.load.{}".format(self.form.name, key)
            })

        compas_rhino.xdraw_lines(lines,
                                 layer=self.layer,
                                 clear=False,
                                 redraw=False)
Ejemplo n.º 10
0
    def draw_residuals(self, scale=None, color=None):
        self.clear_residuals()

        lines = []
        color = color or self.form.attributes['color.residual']
        scale = scale or self.form.attributes['scale.residual']
        tol = self.form.attributes['tol.residual']
        tol2 = tol**2

        for key, attr in self.form.vertices_where(
            {
                'is_anchor': False,
                'is_external': False
            }, True):
            rx = scale * attr['rx']
            ry = scale * attr['ry']
            rz = scale * attr['rz']

            if rx**2 + ry**2 + rz**2 < tol2:
                continue

            sp = self.form.vertex_coordinates(key)
            ep = sp[0] + rx, sp[1] + ry, sp[2] + rz

            lines.append({
                'start': sp,
                'end': ep,
                'color': color,
                'arrow': 'start',
                'name': "{}.residual.{}".format(self.form.name, key)
            })

        compas_rhino.xdraw_lines(lines,
                                 layer=self.layer,
                                 clear=False,
                                 redraw=False)
Ejemplo n.º 11
0
def display_network_applied_loads(network,
                                  display=True,
                                  layer=None,
                                  clear_layer=False,
                                  scale=1.0,
                                  color=(0, 0, 255)):

    tol = compas_rhino.get_tolerance()
    guids = compas_rhino.get_objects(name='{0}.force:load.*'.format(network.attributes['name']))
    compas_rhino.delete_objects(guids)

    if not display:
        return

    lines = []

    for key, attr in network.vertices(True):
        load   = attr['px'], attr['py'], attr['pz']
        end    = network.vertex_coordinates(key)
        start  = [end[i] - scale * load[i] for i in range(3)]
        length = distance_point_point(start, end)
        arrow  = 'end'
        name   = '{0}.force:load.{1}'.format(network.attributes['name'], key)

        if length < tol:
            continue

        lines.append({
            'start': start,
            'end'  : end,
            'name' : name,
            'color': color,
            'arrow': arrow,
        })

    compas_rhino.xdraw_lines(lines, layer=layer, clear=clear_layer)
Ejemplo n.º 12
0
    def draw_facenormals(self, color=None):
        """Draw the normals of the faces.

        Parameters
        ----------
        color : str (HEX) or tuple (RGB), optional
            The color specification of the normal vectors.
            String values are interpreted as hex colors (e.g. ``'#ff0000'`` for red).
            Tuples are interpreted as RGB component specifications (e.g. ``(255, 0, 0) for red``.
            The default value is ``None``, in which case the labels are assigned
            the default normal vector color (``self.defaults['color.normal']``).

        Notes
        -----
        The face normals are named using the following template:
        ``"{}.face.normal.{}".format(self.datastructure.name, key)``.
        This name is used afterwards to identify the normals in the Rhino model.

        """
        color = color or self.defaults.get('color.normal')

        lines = []
        for fkey, attr in self.datastructure.faces(True):
            n = self.datastructure.face_normal(fkey)
            sp = self.datastructure.face_centroid(fkey)
            ep = add_vectors(sp, n)
            lines.append({
                'start':
                sp,
                'end':
                ep,
                'name':
                "{}.face.normal.{}".format(self.datastructure.name, fkey),
                'color':
                color,
                'arrow':
                'end'
            })
        return compas_rhino.xdraw_lines(lines,
                                        layer=self.layer,
                                        clear=False,
                                        redraw=False)
Ejemplo n.º 13
0
 def _draw_lines(self, lines):
     compas_rhino.xdraw_lines(lines,
                              layer=self.cablenet.layer,
                              clear=False,
                              redraw=True)
Ejemplo n.º 14
0
    def draw_reactions(self, scale=None, color=None):
        self.clear_reactions()

        lines = []
        color = color or self.form.attributes['color.reaction']
        scale = scale or self.form.attributes['scale.reaction']
        tol = self.form.attributes['tol.reaction']
        tol2 = tol**2

        for key, attr in self.form.vertices_where({'is_anchor': True}, True):
            rx = attr['rx']
            ry = attr['ry']
            rz = attr['rz']

            for nbr in self.form.vertex_neighbors(key):
                is_external = self.form.get_edge_attribute(
                    (key, nbr), 'is_external', False)

                if is_external:
                    f = self.form.get_edge_attribute((key, nbr), 'f', 0.0)
                    u = self.form.edge_direction(key, nbr)
                    u[2] = 0
                    v = scale_vector(u, f)

                    rx += v[0]
                    ry += v[1]

            rx = scale * rx
            ry = scale * ry
            rz = scale * rz

            sp = self.form.vertex_coordinates(key)

            if rx**2 + ry**2 > tol2:
                e1 = sp[0] + rx, sp[1] + ry, sp[2]
                lines.append({
                    'start':
                    sp,
                    'end':
                    e1,
                    'color':
                    color,
                    'arrow':
                    'start',
                    'name':
                    "{}.reaction.{}".format(self.form.name, key)
                })

            if rz**2 > tol2:
                e2 = sp[0], sp[1], sp[2] + rz
                lines.append({
                    'start':
                    sp,
                    'end':
                    e2,
                    'color':
                    color,
                    'arrow':
                    'start',
                    'name':
                    "{}.reaction.{}".format(self.form.name, key)
                })

        compas_rhino.xdraw_lines(lines,
                                 layer=self.layer,
                                 clear=False,
                                 redraw=False)
Ejemplo n.º 15
0
    def draw_forces(self, scale=None, eps=None, mode=0):
        """Draw the contact forces at the interfaces.

        Parameters
        ----------
        scale : float, optional
            The scale at which the forces should be drawn.
            Default is `0.1`.
        eps : float, optional
            A tolerance for drawing small force vectors.
            Force vectors with a scaled length smaller than this tolerance are not drawn.
            Default is `1e-3`.
        mode : int, optional
            Display mode: 0 normal, 1 resultant forces
            Default is 0

        Notes
        -----
        * Forces are drawn as lines with arrow heads.
        * Forces are drawn on a sub-layer *Forces* of the base layer, if a base layer was specified.
        * At every interface point there can be a *compression* force (blue) and a *tension* force (red).
        * Forces are named according to the following pattern:
          ``"{assembly_name}.force.{from block}-{to block}.{interface point}"``

        """
        layer = "{}::Forces".format(self.layer) if self.layer else None
        scale = scale or self.defaults['scale.force']
        eps = eps or self.defaults['eps.force']
        color_compression = self.defaults['color.force:compression']
        color_tension = self.defaults['color.force:tension']

        lines = []
        # resultant_lines = []

        for a, b, attr in self.assembly.edges(True):
            if attr['interface_forces'] is None:
                continue

            w = attr['interface_uvw'][2]

            # forces = []

            for i in range(len(attr['interface_points'])):
                sp = attr['interface_points'][i]
                c = attr['interface_forces'][i]['c_np']
                t = attr['interface_forces'][i]['c_nn']

                f = c - t

                if f > 0.0:
                    if scale * f < eps:
                        continue
                    color = color_compression
                elif f < 0.0:
                    if -scale * f < eps:
                        continue
                    color = color_tension
                else:
                    continue

                lines.append({
                    'start':
                    sp,
                    'end':
                    [sp[axis] + scale * f * w[axis] for axis in range(3)],
                    'color':
                    color,
                    'name':
                    "{0}.force.{1}-{2}.{3}".format(self.assembly.name, a, b,
                                                   i),
                    'arrow':
                    'end'
                })

                # if mode == 1:
                #     forces.append([scale * f * w[axis] for axis in range(3)])

            # if mode == 0:
            #     continue

            # resultant_force = sum_vectors(forces)

            # if len(forces) == 0:
            #     continue

            # resultant_pt = sum_vectors([
            #     scale_vector(attr['interface_points'][i], (length_vector(forces[i]) / length_vector(resultant_force)))
            #     for i in range(len(attr['interface_points']))
            # ])

            # resultant_lines.append({
            #     'start' : resultant_pt,
            #     'end'   : [resultant_pt[axis] + resultant_force[axis] for axis in range(3)],
            #     'color' : color,
            #     'name'  : "{0}.resultant-friction.{1}-{2}.{3}".format(self.assembly.name, a, b, i),
            #     'arrow' : 'end'
            # })

        # if mode == 0:
        compas_rhino.xdraw_lines(lines, layer=layer, clear=False, redraw=False)
Ejemplo n.º 16
0
    def draw_frictions(self, scale=None, eps=None, mode=0):
        """Draw the contact frictions at the interfaces.

        Parameters
        ----------
        scale : float, optional
            The scale at which the forces should be drawn.
            Default is `0.1`.
        eps : float, optional
            A tolerance for drawing small force vectors.
            Force vectors with a scaled length smaller than this tolerance are not drawn.
            Default is `1e-3`.
        mode : int, optional
            Display mode: 0 normal, 1 resultant forces
            Default is 0

        Notes
        -----
        * Forces are drawn as lines with arrow heads.
        * Forces are drawn on a sub-layer *Frictions* of the base layer, if a base layer was specified.
        * Forces are named according to the following pattern:
          ``"{assembly_name}.friction.{from block}-{to block}.{interface point}"``

        """
        layer = "{}::Frictions".format(self.layer) if self.layer else None
        scale = scale or self.defaults['scale.friction']
        eps = eps or self.defaults['eps.friction']
        color_friction = self.defaults['color.force:friction']

        lines = []
        resultant_lines = []

        for a, b, attr in self.assembly.edges(True):
            if attr['interface_forces'] is None:
                continue

            u, v = attr['interface_uvw'][0], attr['interface_uvw'][1]

            forces = []

            for i in range(len(attr['interface_points'])):
                sp = attr['interface_points'][i]
                fr_u_unit = attr['interface_forces'][i]['c_u']
                fr_v_unit = attr['interface_forces'][i]['c_v']

                fr_u = scale_vector(u, fr_u_unit)
                fr_v = scale_vector(v, fr_v_unit)
                f = add_vectors(fr_u, fr_v)
                f_l = length_vector(f)

                if f_l > 0.0:
                    if scale * f_l < eps:
                        continue
                    color = color_friction
                else:
                    continue

                f = scale_vector(f, scale)

                lines.append({
                    'start':
                    sp,
                    'end': [sp[axis] + f[axis] for axis in range(3)],
                    'color':
                    color,
                    'name':
                    "{0}.friction.{1}-{2}.{3}".format(self.assembly.name, a, b,
                                                      i),
                    'arrow':
                    'end'
                })

                if mode == 1:
                    forces.append(f)

            if mode == 0:
                continue

            resultant_force = sum_vectors(forces)

            if len(forces) == 0:
                continue

            resultant_pt = sum_vectors([
                scale_vector(attr['interface_points'][i],
                             (length_vector(forces[i]) /
                              length_vector(resultant_force)))
                for i in range(len(attr['interface_points']))
            ])

            resultant_lines.append({
                'start':
                resultant_pt,
                'end': [
                    resultant_pt[axis] + resultant_force[axis]
                    for axis in range(3)
                ],
                'color':
                color,
                'name':
                "{0}.resultant-friction.{1}-{2}.{3}".format(
                    self.assembly.name, a, b, i),
                'arrow':
                'end'
            })

        if mode == 0:
            compas_rhino.xdraw_lines(lines,
                                     layer=layer,
                                     clear=False,
                                     redraw=False)
        else:
            compas_rhino.xdraw_lines(resultant_lines,
                                     layer=layer,
                                     clear=False,
                                     redraw=False)
Ejemplo n.º 17
0
def draw_network(network,
                 layer=None,
                 clear_layer=False,
                 vertexcolor=None,
                 edgecolor=None,
                 edgelabel=None):
    """Draw a network data structure in Rhino.

    Parameters:
        network (compas.datastructures.network.Network): The network object.
        layer (str): Optional. The layer to draw in. Default is ``None``. If
            ``None``, the currenlt layer is used.
        clear_layer (bool): Optional. Clear the layer if ``True``. Default is ``False``.
        vertexcolor (list, tuple, str, dict): Optional. The color specification
            for the vertices. Default is ``None``.

                * list, tuple: rgb color, with color specs between 0 and 255 (e.g. ``(255, 0, 0)``).
                * str: hex color (e.g. ``'#ff0000'``).
                * dict: dictionary of hex or rgb colors.

        edgecolor (list, tuple, str, dict): Optional. The color specification
            for the edges. Default is ``None``.

                * list, tuple: rgb color, with color specs between 0 and 255 (e.g. ``(255, 0, 0)``).
                * str: hex color (e.g. ``'#ff0000'``).
                * dict: dictionary of hex or rgb color.

    Note:
        * Any network objects with the same name that are already present in the
          model will be deleted by this function.
        * To also clear the entire layer the network will be drawn on, for
          example, if you have a dedicated network layer, use the ``clear_layer`` flag as well.

    See Also:
        * :class:`compas.datastructures.network.Network`
        * :func:`compas_compas_rhino.utilities.drawing.xdraw_lines`
        * :func:`compas_compas_rhino.utilities.drawing.xdraw_points`

    Example:

        .. code-block:: python
            :emphasize-lines: 7

            import compas
            from compas.datastructures.network import Network
            import compas_rhino as compas_rhino

            network = Network.from_obj(compas.get_data('lines.obj'))

            compas_compas_rhino.draw_network(network)

    """
    vertexcolor = color_to_colordict(vertexcolor,
                                     network.vertices(),
                                     default=network.attributes['color.vertex'],
                                     colorformat='rgb',
                                     normalize=False)

    edgecolor = color_to_colordict(edgecolor,
                                   network.edges(),
                                   default=network.attributes['color.edge'],
                                   colorformat='rgb',
                                   normalize=False)

    edgelabel = edgelabel or {}

    points = []
    for key, attr in network.vertices(True):
        points.append({
            'pos'  : network.vertex_coordinates(key),
            'name' : '{0}.vertex.{1}'.format(network.attributes['name'], repr(key)),
            'color': vertexcolor[key]
        })

    lines = []
    for u, v, attr in network.edges(True):
        lines.append({
            'start': network.vertex_coordinates(u),
            'end'  : network.vertex_coordinates(v),
            'name' : '{0}.edge.{1}-{2}'.format(network.attributes['name'], repr(u), repr(v)),
            'color': edgecolor[(u, v)]
        })

    labels = []
    for (u, v), text in edgelabel.items():
        labels.append({
            'pos'  : network.edge_midpoint(u, v),
            'text' : str(text),
            'name' : '{0}.edge.label.{1}-{2}'.format(network.attributes['name'], repr(u), repr(v)),
            'color': edgecolor[(u, v)],
        })

    guids = compas_rhino.get_objects(name='{0}.*'.format(network.attributes['name']))
    compas_rhino.delete_objects(guids)

    compas_rhino.xdraw_points(
        points,
        layer=layer,
        clear=clear_layer,
        redraw=False
    )
    compas_rhino.xdraw_lines(
        lines,
        layer=layer,
        clear=False,
        redraw=False
    )
    compas_rhino.xdraw_labels(
        labels,
        layer=layer,
        clear=False,
        redraw=True
    )
Ejemplo n.º 18
0
def draw_volmesh(volmesh,
                 name=None,
                 layer=None,
                 clear=True,
                 redraw=True,
                 show_faces=True,
                 show_vertices=True,
                 show_edges=True,
                 vertex_color=None,
                 edge_color=None,
                 face_color=None):
    """"""
    # set default options
    if not isinstance(vertex_color, dict):
        vertex_color = {}
    if not isinstance(edge_color, dict):
        edge_color = {}
    if not isinstance(face_color, dict):
        face_color = {}
    if name:
        volmesh.attributes['name'] = name
    name = volmesh.setdefault('name', name)
    if layer:
        volmesh.attributes['layer'] = layer
    layer = volmesh.setdefault('layer', layer)
    # delete all relevant objects by name
    objects = compas_rhino.get_objects(name='{0}.mesh'.format(name))
    objects += compas_rhino.get_objects(name='{0}.vertex.*'.format(name))
    objects += compas_rhino.get_objects(name='{0}.edge.*'.format(name))
    compas_rhino.delete_objects(objects)
    # clear the layer if requested
    if clear:
        compas_rhino.clear_layers([layer])
    # draw the requested components
    if show_faces:
        faces = []
        color = volmesh.attributes['color.face']
        for vertices in volmesh.faces():
            points = [
                volmesh.vertex_coordinates(vkey)
                for vkey in vertices + [vertices[0]]
            ]
            faces.append({
                'points': points,
                'name': '',
                'color': color,
            })
        compas_rhino.xdraw_faces(faces, layer=layer, clear=False, redraw=False)
    if show_edges:
        lines = []
        color = volmesh.attributes['color.edge']
        for u, v in volmesh.edges_iter():
            lines.append({
                'start': volmesh.vertex_coordinates(u),
                'end': volmesh.vertex_coordinates(v),
                'name': '{0}.edge.{1}-{2}'.format(name, u, v),
                'color': edge_color.get((u, v), color),
            })
        compas_rhino.xdraw_lines(lines, layer=layer, clear=False, redraw=False)
    if show_vertices:
        points = []
        color = volmesh.attributes['color.vertex']
        for key in volmesh.vertices_iter():
            points.append({
                'pos': volmesh.vertex_coordinates(key),
                'name': '{0}.vertex.{1}'.format(name, key),
                'color': vertex_color.get(key, color),
            })
        compas_rhino.xdraw_points(points,
                                  layer=layer,
                                  clear=False,
                                  redraw=False)
    # redraw if requested
    if redraw:
        rs.Redraw()
Ejemplo n.º 19
0
def draw_mesh(
    mesh,
    layer=None,
    clear_layer=False,
    show_faces=True,
    show_vertices=False,
    show_edges=False,
    show_wireframe=False,
    vertexcolor=None,
    edgecolor=None,
    wireframecolor=None,
    facecolor=None,
):
    """
    Draw a mesh object in Rhino.

    Parameters:
        mesh (compas.datastructures.mesh.Mesh): The mesh object.
        layer (str): Optional. The layer to draw in. Default is ``None``.
        clear_layer (bool): Optional. Clear the drawing layer. Default is ``True``.
        show_faces (bool): Optional. Show the faces. Default is ``True``.
        show_vertices (bool): Optional. Show the vertices. Default is ``True``.
        show_edges (bool): Optional. Show the edges. Default is ``True``.
        vertexcolor (str, tuple, list, dict): Optional. The vertex color specification. Default is ``None``.
        edgecolor (str, tuple, list, dict): Optional. The edge color specification. Default is ``None``.
        facecolor (str, tuple, list, dict): Optional. The face color specification. Default is ``None``.
        redraw (bool): Optional. Redraw instructions. Default is ``True``.

    Note:
        Colors can be specifiedin different ways:

        * str: A hexadecimal color that will be applied to all elements subject to the specification.
        * tuple, list: RGB color that will be applied to all elements subject to the specification.
        * dict: RGB or hex color dict with a specification for some or all of the related elements.

    Important:
        RGB colors should specify color values between 0 and 255.

    """

    vertexcolor = color_to_colordict(vertexcolor,
                                     mesh.vertices(),
                                     default=mesh.attributes['color.vertex'],
                                     colorformat='rgb',
                                     normalize=False)

    edgecolor = color_to_colordict(edgecolor,
                                   mesh.edges(),
                                   default=mesh.attributes['color.edge'],
                                   colorformat='rgb',
                                   normalize=False)

    # facecolor = color_to_colordict(facecolor,
    #                                mesh.faces(),
    #                                default=mesh.attributes['color.face'],
    #                                colorformat='rgb',
    #                                normalize=False)

    guids = compas_rhino.get_objects(
        name='{0}.*'.format(mesh.attributes['name']))
    compas_rhino.delete_objects(guids)

    if clear_layer:
        if not layer:
            compas_rhino.clear_current_layer()
        else:
            compas_rhino.clear_layer(layer)

    if show_faces:
        key_index = {key: index for index, key in enumerate(mesh.vertices())}
        xyz = [mesh.vertex_coordinates(key) for key in mesh.vertices()]
        faces = []
        color = mesh.attributes['color.face']

        for fkey in mesh.face:
            face = mesh.face_vertices(fkey, ordered=True)
            v = len(face)

            if v < 3:
                print('Degenerate face: {0} => {1}'.format(fkey, face))
            elif v == 3:
                faces.append([key_index[k] for k in face + [face[-1]]])
            elif v == 4:
                faces.append([key_index[k] for k in face])
            else:
                c = len(xyz)
                xyz.append(mesh.face_center(fkey))
                for i in range(-1, len(face) - 1):
                    key = face[i]
                    nbr = face[i + 1]
                    vertices = [
                        c, key_index[key], key_index[nbr], key_index[nbr]
                    ]
                    faces.append(vertices)

        compas_rhino.xdraw_mesh(xyz,
                                faces,
                                color,
                                '{0}.mesh'.format(mesh.attributes['name']),
                                layer=layer,
                                clear=False,
                                redraw=False)

    if show_edges:
        lines = []
        color = mesh.attributes['color.edge']
        for u, v in mesh.edges():
            lines.append({
                'start':
                mesh.vertex_coordinates(u),
                'end':
                mesh.vertex_coordinates(v),
                'name':
                '{0}.edge.{1}-{2}'.format(mesh.attributes['name'], repr(u),
                                          repr(v)),
                'color':
                edgecolor.get((u, v), color),
            })
        compas_rhino.xdraw_lines(lines, layer=layer, clear=False, redraw=False)

    if show_wireframe:
        lines = []
        color = mesh.attributes['color.edge']
        for u, v in mesh.wireframe():
            lines.append({
                'start':
                mesh.vertex_coordinates(u),
                'end':
                mesh.vertex_coordinates(v),
                'name':
                '{0}.edge.{1}-{2}'.format(mesh.attributes['name'], repr(u),
                                          repr(v)),
                'color':
                edgecolor.get((u, v), color),
            })
        compas_rhino.xdraw_lines(lines, layer=layer, clear=False, redraw=False)

    if show_vertices:
        points = []
        color = mesh.attributes['color.vertex']
        for key in mesh.vertices():
            points.append({
                'pos':
                mesh.vertex_coordinates(key),
                'name':
                '{0}.vertex.{1}'.format(mesh.attributes['name'], repr(key)),
                'color':
                vertexcolor.get(key, color),
            })
        compas_rhino.xdraw_points(points,
                                  layer=layer,
                                  clear=False,
                                  redraw=False)

    rs.EnableRedraw()
    rs.Redraw()