示例#1
0
    def draw(self):
        """Draw the box associated with the artist.

        Returns
        -------
        list
            The GUIDs of the objects created in Rhino.
        """
        vertices = [list(vertex) for vertex in self.shape.vertices]
        faces = self.shape.faces
        edges = self.shape.edges
        points = [{'pos': point, 'color': self.color} for point in vertices]
        lines = [{
            'start': vertices[i],
            'end': vertices[j],
            'color': self.color
        } for i, j in edges]
        polygons = [{
            'points': [vertices[index] for index in face],
            'color': self.color
        } for face in faces]
        guids = compas_rhino.draw_points(points,
                                         layer=self.layer,
                                         clear=False,
                                         redraw=False)
        guids += compas_rhino.draw_lines(lines,
                                         layer=self.layer,
                                         clear=False,
                                         redraw=False)
        guids += compas_rhino.draw_faces(polygons,
                                         layer=self.layer,
                                         clear=False,
                                         redraw=False)
        self._guids = guids
        return guids
示例#2
0
    def draw(self, u=10):
        """Draw the cone associated with the artist.

        Parameters
        ----------
        u : int, optional
            Number of faces in the "u" direction.
            Default is ``10``.

        Returns
        -------
        list
            The GUIDs of the objects created in Rhino.
        """
        vertices, faces = self.shape.to_vertices_and_faces(u=u)
        vertices = [list(vertex) for vertex in vertices]
        points = [{'pos': point, 'color': self.color} for point in vertices]
        polygons = [{
            'points': [vertices[index] for index in face],
            'color': self.color
        } for face in faces]
        guids = compas_rhino.draw_points(points,
                                         layer=self.layer,
                                         clear=False,
                                         redraw=False)
        guids += compas_rhino.draw_faces(polygons,
                                         layer=self.layer,
                                         clear=False,
                                         redraw=False)
        self._guids = guids
        return guids
示例#3
0
    def draw_faces(self, keys=None, color=None, join_faces=False):
        """Draw a selection of faces.

        Parameters
        ----------
        fkeys : list
            A list of face keys identifying which faces to draw.
            The default is ``None``, in which case all faces are drawn.
        color : str, tuple, dict
            The color specififcation for the faces.
            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 face color.

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

        """
        keys = keys or list(self.datastructure.faces())

        colordict = color_to_colordict(color,
                                       keys,
                                       default=self.defaults.get('color.face'),
                                       colorformat='rgb',
                                       normalize=False)
        faces = []
        for fkey in keys:
            faces.append({
                'points':
                self.datastructure.face_coordinates(fkey),
                'name':
                self.datastructure.face_name(fkey),
                'color':
                colordict[fkey],
                'layer':
                self.datastructure.face_attribute(fkey, 'layer', None)
            })

        guids = compas_rhino.draw_faces(faces,
                                        layer=self.layer,
                                        clear=False,
                                        redraw=False)
        if not join_faces:
            return guids
        guid = rs.JoinMeshes(guids, delete_input=True)
        rs.ObjectLayer(guid, self.layer)
        rs.ObjectName(guid, '{}.mesh'.format(self.datastructure.name))
        if color:
            rs.ObjectColor(guid, color)
        return guid
    def draw_interfaces(self, keys=None, color=None):
        """Draw the interfaces between the blocks.

        Parameters
        ----------
        keys : list
            A list of interface identifiers (i.e. assembly edge (u, v) tuples).
            Default is ``None``, in which case all interfaces are drawn.
        color : str, tuple, dict
            The color specififcation for the interfaces.
            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 interfaces, provide a single color
            specification. Individual colors can be assigned using a dictionary
            of key-color pairs. Missing keys will be assigned the default interface
            color (``self.settings['color.interface']``).
            The default is ``None``, in which case all interfaces are assigned the
            default interface color.

        Notes
        -----
        * Interfaces are drawn as mesh faces.
        * Interfaces are drawn on a sub-layer *Interfaces* of the base layer, if a base layer was provided.
        * Interface names have the following pattern: ``"{assembly_name}.interface.{from block_id}-{to block_id}"``
        * Interfaces have a direction, as suggested by the naming convention.
        """
        layer = "{}::Interfaces".format(self.layer) if self.layer else None
        faces = []
        keys = keys or list(self.assembly.edges())
        colordict = color_to_colordict(
            color,
            keys,
            default=self.settings.get('color.interface'),
            colorformat='rgb',
            normalize=False)
        for (u, v), attr in self.assembly.edges(True):
            faces.append({
                'points':
                attr['interface_points'],
                'name':
                "{}.interface.{}-{}".format(self.assembly.name, u, v),
                'color':
                colordict[(u, v)]
            })
        compas_rhino.draw_faces(faces, layer=layer, clear=False, redraw=False)
示例#5
0
    def draw_faces(self, keys=None, color=None, join_faces=False):
        """Draw a selection of faces.

        Parameters
        ----------
        fkeys : list
            A list of face keys identifying which faces to draw.
            The default is ``None``, in which case all faces are drawn.
        color : str, tuple, dict
            The color specififcation for the faces.
            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.settings['color.faces']``).
            The default is ``None``, in which case all faces are assigned the default face color.
        join_faces : bool, optional
            Join the faces into 1 mesh.
            Default is ``False``, in which case the faces are drawn as individual meshes.

        Returns
        -------
        list
            The GUIDs of the created Rhino objects.

        """
        faces = keys or list(self.mesh.faces())
        face_color = color_to_colordict(color,
                                        faces,
                                        default=self.settings['color.faces'],
                                        colorformat='rgb',
                                        normalize=False)
        facets = []
        for face in faces:
            facets.append({
                'points': self.mesh.face_coordinates(face),
                'name': "{}.face.{}".format(self.mesh.name, face),
                'color': face_color[face]
            })

        guids = compas_rhino.draw_faces(facets,
                                        layer=self.layer,
                                        clear=False,
                                        redraw=False)
        if not join_faces:
            self.guid_face = zip(guids, faces)
            return guids

        guid = compas_rhino.rs.JoinMeshes(guids, delete_input=True)
        compas_rhino.rs.ObjectLayer(guid, self.layer)
        compas_rhino.rs.ObjectName(guid, '{}.mesh'.format(self.mesh.name))
        if color:
            compas_rhino.rs.ObjectColor(guid, color)

        self.guids += [guid]
        return [guid]
示例#6
0
    def draw(self, show_points=False, show_edges=False, show_face=True):
        """Draw the polygon.

        Parameters
        ----------
        show_points : bool, optional
            If True, draw the corner points of the polygon.
        show_edges : bool, optional
            If True, draw the boundary edges of the polygon.
        show_face : bool, optional
            If True, draw the face of the polygon.

        Returns
        -------
        list[System.Guid]
            The GUIDs of the created Rhino objects.

        """
        _points = map(list, self.primitive.points)
        guids = []
        if show_points:
            points = [{
                'pos': point,
                'color': self.color,
                'name': self.primitive.name
            } for point in _points]
            guids += compas_rhino.draw_points(points,
                                              layer=self.layer,
                                              clear=False,
                                              redraw=False)
        if show_edges:
            lines = [{
                'start': list(a),
                'end': list(b),
                'color': self.color,
                'name': self.primitive.name
            } for a, b in self.primitive.lines]
            guids += compas_rhino.draw_lines(lines,
                                             layer=self.layer,
                                             clear=False,
                                             redraw=False)
        if show_face:
            polygons = [{
                'points': _points,
                'color': self.color,
                'name': self.primitive.name
            }]
            guids += compas_rhino.draw_faces(polygons,
                                             layer=self.layer,
                                             clear=False,
                                             redraw=False)
        return guids
示例#7
0
    def draw(self, u=10, v=10, show_vertices=False, show_edges=False, show_faces=True, join_faces=True):
        """Draw the sphere associated with the artist.

        Parameters
        ----------
        u : int, optional
            Number of faces in the "u" direction.
            Default is ``10``.
        v : int, optional
            Number of faces in the "v" direction.
            Default is ``10``.
        show_vertices : bool, optional
            Default is ``False``.
        show_edges : bool, optional
            Default is ``False``.
        show_faces : bool, optional
            Default is ``True``.
        join_faces : bool, optional
            Default is ``True``.

        Returns
        -------
        list
            The GUIDs of the objects created in Rhino.
        """
        vertices, faces = self.shape.to_vertices_and_faces(u=u, v=v)
        vertices = [list(vertex) for vertex in vertices]
        guids = []
        if show_vertices:
            points = [{'pos': point, 'color': self.color} for point in vertices]
            guids += compas_rhino.draw_points(points, layer=self.layer, clear=False, redraw=False)
        if show_edges:
            lines = []
            seen = set()
            for face in faces:
                for u, v in pairwise(face + face[:1]):
                    if (u, v) not in seen:
                        seen.add((u, v))
                        seen.add((v, u))
                        lines.append({'start': vertices[u], 'end': vertices[v], 'color': self.color})
            guids += compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
        if show_faces:
            if join_faces:
                guid = compas_rhino.draw_mesh(vertices, faces, layer=self.layer, name=self.name, color=self.color, disjoint=True)
                guids.append(guid)
            else:
                polygons = [{'points': [vertices[index] for index in face], 'color': self.color} for face in faces]
                guids += compas_rhino.draw_faces(polygons, layer=self.layer, clear=False, redraw=False)
        self._guids = guids
        return guids
示例#8
0
    def draw_cells(self, cells=None, color=None):
        """Draw a selection of cells.

        Parameters
        ----------
        cells : list[int], optional
            A list of cells to draw.
            The default is None, in which case all cells are drawn.
        color : tuple[int, int, int] or dict[int, tuple[int, int, int]], optional
            The color of the cells.
            The default color is :attr:`VolMeshArtist.default_cellcolor`.

        Returns
        -------
        list[System.Guid]
            The GUIDs of the created Rhino objects.
            Every cell is drawn as an individual mesh.

        """
        self.cell_color = color
        cells = cells or list(self.volmesh.cells())
        vertex_xyz = self.vertex_xyz
        meshes = []
        for cell in cells:
            cell_faces = []
            for fkey in self.volmesh.cell_faces(cell):
                cell_faces.append({
                    'points': [
                        vertex_xyz[vertex]
                        for vertex in self.volmesh.face_vertices(fkey)
                    ],
                    'name':
                    "{}.cell.{}.face.{}".format(self.volmesh.name, cell, fkey),
                    'color':
                    self.cell_color.get(cell, self.default_cellcolor)
                })
            guids = compas_rhino.draw_faces(cell_faces,
                                            layer=self.layer,
                                            clear=False,
                                            redraw=False)
            guid = compas_rhino.rs.JoinMeshes(guids, delete_input=True)
            compas_rhino.rs.ObjectLayer(guid, self.layer)
            compas_rhino.rs.ObjectName(
                guid, '{}.cell.{}'.format(self.volmesh.name, cell))
            compas_rhino.rs.ObjectColor(
                guid, self.cell_color.get(cell, self.default_cellcolor))
            meshes.append(guid)
        return meshes
示例#9
0
    def draw_faces(self, faces=None, color=None, join_faces=False):
        """Draw a selection of faces.

        Parameters
        ----------
        faces : list, optional
            A selection of faces to draw.
            The default is ``None``, in which case all faces are drawn.
        color : tuple or dict of tuple, optional
            The color specififcation for the faces.
            The default color is black ``(0, 0, 0)``.
        join_faces : bool, optional
            Join the faces into 1 mesh.
            Default is ``False``, in which case the faces are drawn as individual meshes.

        Returns
        -------
        list
            The GUIDs of the created Rhino objects.

        """
        faces = faces or list(self.mesh.faces())
        vertex_xyz = self.vertex_xyz
        face_color = colordict(color, faces, default=self.color_faces)
        facets = []
        for face in faces:
            facets.append({
                'points': [
                    vertex_xyz[vertex]
                    for vertex in self.mesh.face_vertices(face)
                ],
                'name':
                "{}.face.{}".format(self.mesh.name, face),
                'color':
                face_color[face]
            })
        guids = compas_rhino.draw_faces(facets,
                                        layer=self.layer,
                                        clear=False,
                                        redraw=False)
        if not join_faces:
            return guids
        guid = compas_rhino.rs.JoinMeshes(guids, delete_input=True)
        compas_rhino.rs.ObjectLayer(guid, self.layer)
        compas_rhino.rs.ObjectName(guid, '{}'.format(self.mesh.name))
        if color:
            compas_rhino.rs.ObjectColor(guid, color)
        return [guid]
示例#10
0
    def draw_cells(self, cells=None, color=None):
        """Draw a selection of cells.

        Parameters
        ----------
        cells : list
            A list of cells to draw.
            The default is ``None``, in which case all cells are drawn.
        color : str, tuple, dict
            The color specififcation for the cells.
            The default color is ``(255, 0, 0)``.

        Returns
        -------
        list
            The GUIDs of the created Rhino objects.
            Every cell is drawn as an individual mesh.

        """
        cells = cells or list(self.volmesh.cells())
        vertex_xyz = self.vertex_xyz
        cell_color = colordict(color, cells, default=self.color_cells)
        meshes = []
        for cell in cells:
            cell_faces = []
            for fkey in self.volmesh.cell_faces(cell):
                cell_faces.append({
                    'points': [
                        vertex_xyz[vertex]
                        for vertex in self.volmesh.face_vertices(fkey)
                    ],
                    'name':
                    "{}.cell.{}.face.{}".format(self.volmesh.name, cell, fkey),
                    'color':
                    cell_color[cell]
                })
            guids = compas_rhino.draw_faces(cell_faces,
                                            layer=self.layer,
                                            clear=False,
                                            redraw=False)
            guid = compas_rhino.rs.JoinMeshes(guids, delete_input=True)
            compas_rhino.rs.ObjectLayer(guid, self.layer)
            compas_rhino.rs.ObjectName(
                guid, '{}.cell.{}'.format(self.volmesh.name, cell))
            compas_rhino.rs.ObjectColor(guid, cell_color[cell])
            meshes.append(guid)
        return meshes
示例#11
0
    def draw_faces(self, faces=None, color=None, join_faces=False):
        """Draw a selection of faces.

        Parameters
        ----------
        faces : list[int], optional
            A selection of faces to draw.
            The default is None, in which case all faces are drawn.
        color : tuple[int, int, int] or dict[int, tuple[int, int, int]], optional
            The color of the faces.
            The default color is the value of :attr:`MeshArtist.default_facecolor`.
        join_faces : bool, optional
            If True, join the faces into a single mesh.

        Returns
        -------
        list[System.Guid]
            The GUIDs of the created Rhino objects.

        """
        self.face_color = color
        faces = faces or self.faces
        vertex_xyz = self.vertex_xyz
        facets = []
        for face in faces:
            facets.append({
                'points': [
                    vertex_xyz[vertex]
                    for vertex in self.mesh.face_vertices(face)
                ],
                'name':
                "{}.face.{}".format(self.mesh.name, face),
                'color':
                self.face_color.get(face, self.default_facecolor)
            })
        guids = compas_rhino.draw_faces(facets,
                                        layer=self.layer,
                                        clear=False,
                                        redraw=False)
        if join_faces:
            guid = compas_rhino.rs.JoinMeshes(guids, delete_input=True)
            compas_rhino.rs.ObjectLayer(guid, self.layer)
            compas_rhino.rs.ObjectName(guid, '{}.mesh'.format(self.mesh.name))
            compas_rhino.rs.ObjectColor(guid, color)
            guids = [guid]
        return guids
示例#12
0
    def draw_faces(self, faces=None, color=None, join_faces=False):
        """Draw a selection of faces.

        Parameters
        ----------
        faces : list, optional
            A selection of faces to draw.
            The default is ``None``, in which case all faces are drawn.
        color : tuple or dict of tuple, optional
            The color specification for the faces.
            The default color is the value of ``~MeshArtist.default_facecolor``.
        join_faces : bool, optional
            Join the faces into 1 mesh.
            Default is ``False``, in which case the faces are drawn as individual meshes.

        Returns
        -------
        list
            The GUIDs of the created Rhino objects.

        """
        self.face_color = color
        faces = faces or self.faces
        vertex_xyz = self.vertex_xyz
        facets = []
        for face in faces:
            facets.append({
                'points': [vertex_xyz[vertex] for vertex in self.mesh.face_vertices(face)],
                'name': "{}.face.{}".format(self.mesh.name, face),
                'color': self.face_color.get(face, self.default_facecolor)
            })
        guids = compas_rhino.draw_faces(facets, layer=self.layer, clear=False, redraw=False)
        if join_faces:
            guid = compas_rhino.rs.JoinMeshes(guids, delete_input=True)
            compas_rhino.rs.ObjectLayer(guid, self.layer)
            compas_rhino.rs.ObjectName(guid, '{}.mesh'.format(self.mesh.name))
            compas_rhino.rs.ObjectColor(guid, color)
            guids = [guid]
        return guids
示例#13
0
    def draw(self, show_vertices=False, show_edges=False, show_faces=True, join_faces=True):
        """Draw the polyhedron associated with the artist.

        Parameters
        ----------
        show_vertices : bool, optional
            Default is ``False``.
        show_edges : bool, optional
            Default is ``False``.
        show_faces : bool, optional
            Default is ``True``.
        join_faces : bool, optional
            Default is ``True``.

        Returns
        -------
        list
            The GUIDs of the objects created in Rhino.
        """
        vertices = [list(vertex) for vertex in self.shape.vertices]
        guids = []
        if show_vertices:
            points = [{'pos': point, 'color': self.color, 'name': str(index)} for index, point in enumerate(vertices)]
            guids += compas_rhino.draw_points(points, layer=self.layer, clear=False, redraw=False)
        if show_edges:
            edges = self.shape.edges
            lines = [{'start': vertices[i], 'end': vertices[j], 'color': self.color} for i, j in edges]
            guids += compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
        if show_faces:
            faces = self.shape.faces
            if join_faces:
                guid = compas_rhino.draw_mesh(vertices, faces, layer=self.layer, name=self.name, color=self.color, disjoint=True)
                guids.append(guid)
            else:
                polygons = [{'points': [vertices[index] for index in face], 'color': self.color} for face in faces]
                guids += compas_rhino.draw_faces(polygons, layer=self.layer, clear=False, redraw=False)
        self._guids = guids
        return guids
示例#14
0
    def draw_faces(self, faces=None, color=None):
        """Draw a selection of faces.

        Parameters
        ----------
        faces : list
            A list of faces to draw.
            The default is ``None``, in which case all faces are drawn.
        color : str, tuple, dict
            The color specififcation for the faces.
            The default color is ``(210, 210, 210)``.

        Returns
        -------
        list
            The GUIDs of the created Rhino objects.

        """
        faces = faces or list(self.volmesh.faces())
        vertex_xyz = self.vertex_xyz
        face_color = colordict(color, faces, default=self.color_faces)
        facets = []
        for face in faces:
            facets.append({
                'points': [
                    vertex_xyz[vertex]
                    for vertex in self.volmesh.halfface_vertices(face)
                ],
                'name':
                "{}.face.{}".format(self.volmesh.name, face),
                'color':
                face_color[face]
            })
        return compas_rhino.draw_faces(facets,
                                       layer=self.layer,
                                       clear=False,
                                       redraw=False)
示例#15
0
    def draw_faces(self, faces=None, color=None):
        """Draw a selection of faces.

        Parameters
        ----------
        faces : list[int], optional
            A list of faces to draw.
            The default is None, in which case all faces are drawn.
        color : tuple[int, int, int] or dict[int, tuple[int, int, int]], optional
            The color of the faces.
            The default color is :attr:`VolMeshArtist.default_facecolor`.

        Returns
        -------
        list[System.Guid]
            The GUIDs of the created Rhino objects.

        """
        self.face_color = color
        faces = faces or list(self.volmesh.faces())
        vertex_xyz = self.vertex_xyz
        facets = []
        for face in faces:
            facets.append({
                'points': [
                    vertex_xyz[vertex]
                    for vertex in self.volmesh.halfface_vertices(face)
                ],
                'name':
                "{}.face.{}".format(self.volmesh.name, face),
                'color':
                self.face_color.get(face, self.default_facecolor)
            })
        return compas_rhino.draw_faces(facets,
                                       layer=self.layer,
                                       clear=False,
                                       redraw=False)
示例#16
0
    f1 = mesh.halfedge_face(vertex, nbr)
    c1 = mesh.face_centroid(f1)
    v1 = subtract_vectors(c1, a)

    f2 = mesh.halfedge_face(nbr, vertex)
    c2 = mesh.face_centroid(f2)
    v2 = subtract_vectors(c2, a)

    a1 = 0.25 * length_vector(cross_vectors(v0, v1))
    a2 = 0.25 * length_vector(cross_vectors(v0, v2))

    lines.append({'start': a, 'end': b, 'arrow': 'end', 'color': (0, 0, 255)})
    lines.append({'start': a, 'end': c1, 'arrow': 'end', 'color': (255, 0, 0)})

    polygons.append({'points': [a, b, add_vectors(b, v1), c1], 'color': (255, 0, 0)})
    polygons.append({'points': [a, b, add_vectors(b, v2), c2], 'color': (0, 0, 255)})


# visualize

artist = CablenetArtist(mesh, layer="ITA20::L5::FormFinding")
artist.clear_layer()

artist.draw_vertices(color={vertex: (255, 0, 0) for vertex in mesh.vertices_where({'is_anchor': True})})
artist.draw_edges()
artist.draw_faces()

compas_rhino.draw_lines(lines, layer=artist.layer)
compas_rhino.draw_faces(polygons, layer=artist.layer)
示例#17
0
from __future__ import absolute_import
示例#18
0
    def draw(self):
        """Draw the objects representing the thrust diagram.
        """
        layer = self.settings['layer']
        self.artist.layer = layer
        self.artist.clear_layer()
        self.clear()
        if not self.visible:
            return
        self.artist.vertex_xyz = self.vertex_xyz

        # ======================================================================
        # Groups
        # ------
        # Create groups for vertices, edges, and faces.
        # These groups will be turned on/off based on the visibility settings of the diagram.
        # Separate groups are created for free and anchored vertices.
        # ======================================================================

        group_free = "{}::vertices_free".format(layer)
        group_anchor = "{}::vertices_anchor".format(layer)

        group_edges = "{}::edges".format(layer)
        group_faces = "{}::faces".format(layer)

        if not compas_rhino.rs.IsGroup(group_free):
            compas_rhino.rs.AddGroup(group_free)

        if not compas_rhino.rs.IsGroup(group_anchor):
            compas_rhino.rs.AddGroup(group_anchor)

        if not compas_rhino.rs.IsGroup(group_edges):
            compas_rhino.rs.AddGroup(group_edges)

        if not compas_rhino.rs.IsGroup(group_faces):
            compas_rhino.rs.AddGroup(group_faces)

        # ======================================================================
        # Vertices
        # --------
        # Draw the vertices and add them to the vertex group.
        # Free vertices and anchored vertices are drawn separately.
        # ======================================================================

        free = list(self.mesh.vertices_where({'is_anchor': False}))
        anchors = list(self.mesh.vertices_where({'is_anchor': True}))
        color_free = self.settings['color.vertices'] if self.settings['_is.valid'] else self.settings['color.invalid']
        color_anchor = self.settings['color.vertices:is_anchor']
        color = {vertex: color_free for vertex in free}
        color.update({vertex: color_anchor for vertex in anchors})
        guids_free = self.artist.draw_vertices(free, color)
        guids_anchor = self.artist.draw_vertices(anchors, color)
        self.guid_free = zip(guids_free, free)
        self.guid_anchor = zip(guids_anchor, anchors)
        compas_rhino.rs.AddObjectsToGroup(guids_free, group_free)
        compas_rhino.rs.AddObjectsToGroup(guids_anchor, group_anchor)

        if self.settings['show.vertices']:
            compas_rhino.rs.HideGroup(group_free)
            compas_rhino.rs.ShowGroup(group_anchor)
        else:
            compas_rhino.rs.HideGroup(group_free)
            compas_rhino.rs.HideGroup(group_anchor)

        # ======================================================================
        # Edges
        # -----
        # Draw the edges and add them to the edge group.
        # ======================================================================

        edges = list(self.mesh.edges_where({'_is_edge': True}))
        color = {edge: self.settings['color.edges'] if self.settings['_is.valid'] else self.settings['color.invalid'] for edge in edges}

        # color analysis
        if self.scene and self.scene.settings['RV2']['show.forces']:
            if self.mesh.dual:
                _edges = list(self.mesh.dual.edges())
                lengths = [self.mesh.dual.edge_length(*edge) for edge in _edges]
                edges = [self.mesh.dual.primal_edge(edge) for edge in _edges]
                lmin = min(lengths)
                lmax = max(lengths)
                for edge, length in zip(edges, lengths):
                    if lmin != lmax:
                        color[edge] = i_to_rgb((length - lmin) / (lmax - lmin))
        guids = self.artist.draw_edges(edges, color)
        self.guid_edge = zip(guids, edges)
        compas_rhino.rs.AddObjectsToGroup(guids, group_edges)

        if self.settings['show.edges']:
            compas_rhino.rs.ShowGroup(group_edges)
        else:
            compas_rhino.rs.HideGroup(group_edges)

        # ======================================================================
        # Faces
        # -----
        # Draw the faces and add them to the face group.
        # ======================================================================

        if self.settings['show.faces']:

            faces = list(self.mesh.faces_where({'_is_loaded': True}))

            color = {face: self.settings['color.faces'] if self.settings['_is.valid'] else self.settings['color.invalid'] for face in faces}

            if self.settings['show.stresses'] and self.settings['_is.valid']:

                vertices = list(self.mesh.vertices())
                vertex_colors = {vertex: self.settings['color.vertices'] if self.settings['_is.valid'] else self.settings['color.invalid'] for vertex in vertices}

                stresses = [self.mesh.vertex_lumped_stress(vertex) for vertex in vertices]
                smin = min(stresses)
                smax = max(stresses)

                for vertex, stress in zip(vertices, stresses):
                    if smin != smax:
                        vertex_colors[vertex] = i_to_rgb((stress - smin) / (smax - smin))

                facets = []
                for face in faces:
                    facets.append({
                        'points': self.mesh.face_coordinates(face),
                        'name': "{}.face.{}".format(self.mesh.name, face),
                        'vertexcolors': [vertex_colors[vertex] for vertex in self.mesh.face_vertices(face)]})

                guids = compas_rhino.draw_faces(facets, layer=self.layer, clear=False, redraw=False)

            else:
                guids = self.artist.draw_faces(faces, color)

            self.guid_face = zip(guids, faces)
            compas_rhino.rs.AddObjectsToGroup(guids, group_faces)
            compas_rhino.rs.ShowGroup(group_faces)

        else:
            compas_rhino.rs.HideGroup(group_faces)

        # ======================================================================
        # Overlays
        # --------
        # Color overlays for various display modes.
        # ======================================================================

        if self.settings['_is.valid'] and self.settings['show.selfweight']:
            tol = self.settings['tol.selfweight']
            vertices = list(self.mesh.vertices())
            color = self.settings['color.selfweight']
            scale = self.settings['scale.selfweight']
            guids = self.artist.draw_selfweight(vertices, color, scale, tol)
            self.guid_selfweight = zip(guids, vertices)

        if self.settings['_is.valid'] and self.settings['show.loads']:
            tol = self.settings['tol.externalforces']
            vertices = list(self.mesh.vertices())
            color = self.settings['color.loads']
            scale = self.settings['scale.externalforces']
            guids = self.artist.draw_loads(vertices, color, scale, tol)
            self.guid_load = zip(guids, vertices)

        if self.settings['_is.valid'] and self.settings['show.residuals']:
            tol = self.settings['tol.residuals']
            vertices = list(self.mesh.vertices_where({'is_anchor': False}))
            color = self.settings['color.residuals']
            scale = self.settings['scale.residuals']
            guids = self.artist.draw_residuals(vertices, color, scale, tol)
            self.guid_residual = zip(guids, vertices)

        if self.settings['_is.valid'] and self.settings['show.reactions']:
            tol = self.settings['tol.externalforces']
            anchors = list(self.mesh.vertices_where({'is_anchor': True}))
            color = self.settings['color.reactions']
            scale = self.settings['scale.externalforces']
            guids = self.artist.draw_reactions(anchors, color, scale, tol)
            self.guid_reaction = zip(guids, anchors)

        if self.settings['_is.valid'] and self.settings['show.pipes']:
            tol = self.settings['tol.pipes']
            edges = list(self.mesh.edges_where({'_is_edge': True}))
            color = {edge: self.settings['color.pipes'] for edge in edges}

            # color analysis
            if self.scene and self.scene.settings['RV2']['show.forces']:
                if self.mesh.dual:
                    _edges = list(self.mesh.dual.edges())
                    lengths = [self.mesh.dual.edge_length(*edge) for edge in _edges]
                    edges = [self.mesh.dual.primal_edge(edge) for edge in _edges]
                    lmin = min(lengths)
                    lmax = max(lengths)
                    for edge, length in zip(edges, lengths):
                        if lmin != lmax:
                            color[edge] = i_to_rgb((length - lmin) / (lmax - lmin))

            scale = self.settings['scale.pipes']
            guids = self.artist.draw_pipes(edges, color, scale, tol)
            self.guid_pipe = zip(guids, edges)
uv_c_dict = get_force_colors_uv(forcediagram, formdiagram, gradient=True)
# uv_c_dict = get_index_colordict(list(formdiagram.edges()))
hf_c_dict = get_force_colors_hf(forcediagram, formdiagram, uv_c_dict=uv_c_dict)

# 2. compute unified diagram geometries ----------------------------------------
halffaces, prism_faces = volmesh_ud(forcediagram, formdiagram, scale=alpha)

# 3. halffaces and prisms ------------------------------------------------------
faces = []
for hfkey in hfkeys:
    vkeys = forcediagram.halfface[hfkey]
    hf_xyz = [halffaces[hfkey][i] for i in vkeys]
    name = '{}.face.ud.{}'.format(forcediagram.name, hfkey)
    faces.append({'points': hf_xyz, 'name': name, 'color': hf_color})

forces = get_force_mags(forcediagram, formdiagram)

for uv in prism_faces:
    name = '{}.face.ud.prism.{}'.format(forcediagram.name, uv)

    for face in prism_faces[uv]:
        faces.append({'points': face, 'name': name, 'color': uv_c_dict[uv]})

# 4. draw ----------------------------------------------------------------------
formdiagram.draw_edges(color=uv_c_dict)

compas_rhino.draw_faces(faces,
                        layer=forcediagram.layer,
                        clear=False,
                        redraw=False)