def draw_residuals(self, scale=None, color=None): self.clear_residuals() lines = [] color = color or self.settings['color.residual'] scale = scale or self.settings['scale.residual'] tol = self.settings['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.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
def draw_selfweight(self, scale=None, color=None): self.clear_selfweight() lines = [] color = color or self.settings['color.selfweight'] scale = scale or self.settings['scale.selfweight'] tol = self.settings['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.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
def draw_orthonormal_vectors(vectors, layer): """Visualize the three orthonormal output vectors in Rhino in rgb colors. Parameters ---------- vectors : Tuple Three orthonormal vectors. layer: string Name of Layer inside Rhino. """ origin = (0, 0, 0) lines = [{ 'start': origin, 'end': tuple(vectors[0]), 'color': (255, 0, 0), 'arrow': 'end' }, { 'start': origin, 'end': tuple(vectors[1]), 'color': (0, 255, 0), 'arrow': 'end' }, { 'start': origin, 'end': tuple(vectors[2]), 'color': (0, 0, 255), 'arrow': 'end' }] compas_rhino.draw_lines(lines, layer=layer, clear=False)
def draw_loads(self, scale=None, color=None): self.clear_loads() lines = [] color = color or self.settings['color.load'] scale = scale or self.settings['scale.load'] tol = self.settings['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.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
def draw_input_vectors(u, v, layer): """Visualize the two input vectors in Rhino in grey colors. Parameters ---------- u : vector Vector defining the x direction. v : vector Second vector for defining the xy plane. layer: string Name of Layer inside Rhino. """ origin = (0, 0, 0) lines = [ { 'start': origin, 'end': tuple(u), 'color': (100, 100, 100), 'arrow': 'end' }, { 'start': origin, 'end': tuple(v), 'color': (150, 150, 150), 'arrow': 'end' }, ] compas_rhino.draw_lines(lines, layer=layer, clear=False)
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.settings['scale.force'] eps = eps or self.settings['eps.force'] color_compression = self.settings['color.force:compression'] color_tension = self.settings['color.force:tension'] lines = [] for (a, b), attr in self.assembly.edges(True): if attr['interface_forces'] is None: continue w = attr['interface_uvw'][2] 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' }) compas_rhino.draw_lines(lines, layer=layer, clear=False, redraw=False)
def draw_box(bbox, color, layer): lines = [] for a, b in pairwise(bbox[:4] + bbox[:1]): lines.append({'start': a, 'end': b, 'color': color}) for a, b in pairwise(bbox[4:] + bbox[4:5]): lines.append({'start': a, 'end': b, 'color': color}) for a, b in zip(bbox[:4], bbox[4:]): lines.append({'start': a, 'end': b, 'color': color}) compas_rhino.draw_lines(lines, layer=layer, clear=False)
def draw_cloud(cloud, bbox, color, layer): points = [{'pos': xyz, 'color': color} for xyz in cloud] lines = [] for a, b in pairwise(bbox[:4] + bbox[:1]): lines.append({'start': a, 'end': b, 'color': color}) for a, b in pairwise(bbox[4:] + bbox[4:5]): lines.append({'start': a, 'end': b, 'color': color}) for a, b in zip(bbox[:4], bbox[4:]): lines.append({'start': a, 'end': b, 'color': color}) compas_rhino.draw_points(points, layer=layer, clear=True) compas_rhino.draw_lines(lines, layer=layer, clear=False)
def draw_reactions(self, scale=None, color=None): self.clear_reactions() lines = [] color = color or self.settings['color.reaction'] scale = scale or self.settings['scale.reaction'] tol = self.settings['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.edge_attribute((key, nbr), 'is_external') if is_external: f = self.form.edge_attribute((key, nbr), 'f') 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.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
def draw_frame(frame, layer): origin = list(frame.point) xaxis = list(frame.point + frame.xaxis) yaxis = list(frame.point + frame.yaxis) zaxis = list(frame.point + frame.zaxis) points = [{'pos': origin, 'color': (255, 255, 0)}] lines = [ {'start': origin, 'end': xaxis, 'color': (255, 0, 0), 'arrow': 'end'}, {'start': origin, 'end': yaxis, 'color': (0, 255, 0), 'arrow': 'end'}, {'start': origin, 'end': zaxis, 'color': (0, 0, 255), 'arrow': 'end'}] compas_rhino.draw_points(points, layer=layer, clear=True) compas_rhino.draw_lines(lines, layer=layer, clear=False)
def draw_loads(self, color=(0, 255, 0), scale=0.1): lines = [] for vertex in self.mesh.vertices_where({'is_anchor': False}): start = self.mesh.vertex_attributes(vertex, 'xyz') load = self.mesh.vertex_attributes(vertex, ['px', 'py', 'pz']) end = add_vectors(start, scale_vector(load, scale)) lines.append({ 'start': start, 'end': end, 'arrow': 'end', 'color': color }) compas_rhino.draw_lines(lines, layer=self.layer)
def draw_reactions(self, color=(0, 255, 0)): lines = [] for node in self.network.nodes_where({'is_anchor': True}): start = self.network.node_attributes(node, 'xyz') residual = self.network.node_attributes(node, ['rx', 'ry', 'rz']) end = subtract_vectors(start, residual) lines.append({ 'start': start, 'end': end, 'arrow': 'end', 'color': color }) compas_rhino.draw_lines(lines, layer=self.layer)
def draw_polygon(polygon, layer): """Visualize the polygon in Rhino in black. Parameters ---------- polygon: compas.geometry.Polygon An ordered list of points of a convex polygon layer: string Name of Layer inside Rhino. """ lines = [] for a, b in pairwise(list(polygon) + list(polygon[:1])): lines.append({'start': tuple(a), 'end': tuple(b), 'color': (0, 0, 0)}) compas_rhino.draw_lines(lines, layer=layer, clear=False)
def draw_reactions(self, color=(0, 255, 0), scale=0.1): lines = [] for vertex in self.mesh.vertices(): if not self.mesh.vertex_attribute(vertex, 'is_anchor'): continue start = self.mesh.vertex_attributes(vertex, 'xyz') residual = self.mesh.vertex_attributes(vertex, ['rx', 'ry', 'rz']) end = add_vectors(start, scale_vector(residual, -scale)) lines.append({ 'start': start, 'end': end, 'arrow': 'end', 'color': color }) compas_rhino.draw_lines(lines, layer=self.layer)
def draw_residuals(self, color=(0, 255, 255), tol=0.01): lines = [] for node in self.network.nodes_where({'is_anchor': False}): start = self.network.node_attributes(node, 'xyz') residual = self.network.node_attributes(node, ['rx', 'ry', 'rz']) if length_vector(residual) < tol: continue end = add_vectors(start, residual) lines.append({ 'start': start, 'end': end, 'arrow': 'end', 'color': color }) compas_rhino.draw_lines(lines, layer=self.layer)
def draw_reactions(self, scale=1.0, layer="Mesh::Reactions"): reactions = [] for key, attr in self.datastructure.vertices_where({'is_fixed': True}, True): reaction = [attr['rx'], attr['ry'], attr['rz']] vector = scale_vector(reaction, -scale) start = self.datastructure.vertex_coordinates(key) end = add_vectors(start, vector) reactions.append({ 'start': start, 'end': end, 'arrow': 'end', 'color': (0, 255, 0) }) compas_rhino.draw_lines(reactions, layer=layer, clear=True)
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.settings['scale.selfweight'] eps = eps or self.settings['eps.selfweight'] color = self.settings['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.draw_lines(lines, layer=layer, clear=False, redraw=False)
def draw(self, show_point=False, show_normal=False): """Draw the circle. Parameters ---------- show_point : bool, optional Default is ``False``. show_normal : bool, optional Default is ``False``. Returns ------- list The GUIDs of the created Rhino objects. """ point = list(self.primitive.plane.point) normal = list(self.primitive.plane.normal) plane = point, normal radius = self.primitive.radius guids = [] if show_point: points = [{'pos': point, 'color': self.color, 'name': self.primitive.name}] guids += compas_rhino.draw_points(points, layer=self.layer, clear=False, redraw=False) if show_normal: lines = [{'start': point, 'end': add_vectors(point, normal), 'arrow': 'end', 'color': self.color, 'name': self.primitive.name}] guids += compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False) circles = [{'plane': plane, 'radius': radius, 'color': self.color, 'name': self.primitive.name}] guids += compas_rhino.draw_circles(circles, layer=self.layer, clear=False, redraw=False) return guids
def draw_edges(self, edges=None, color=None): """Draw a selection of edges. Parameters ---------- edges : list, optional A selection of edges to draw. The default is ``None``, in which case all edges are drawn. color : tuple or dict of tuple, optional The color specification for the edges. The default color is the value of ``~MeshArtist.default_edgecolor``. Returns ------- list The GUIDs of the created Rhino objects. """ self.edge_color = color edges = edges or self.edges vertex_xyz = self.vertex_xyz lines = [] for edge in edges: lines.append({ 'start': vertex_xyz[edge[0]], 'end': vertex_xyz[edge[1]], 'color': self.edge_color.get(edge, self.default_edgecolor), 'name': "{}.edge.{}-{}".format(self.mesh.name, *edge) }) guids = compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False) return guids
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 line objects. """ layer = layer or self.layer return compas_rhino.draw_lines(lines, layer=layer, clear=clear_layer, redraw=redraw)
def draw_vertexnormals(self, vertices=None, color=(0, 255, 0), scale=1.0): """Draw the normals at the vertices of the mesh. Parameters ---------- vertices : list, optional A selection of vertex normals to draw. Default is to draw all vertex normals. color : tuple, optional The color specification of the normal vectors. The default color is green, ``(0, 255, 0)``. scale : float, optional Scale factor for the vertex normals. Default is ``1.0``. Returns ------- list The GUIDs of the created Rhino objects. """ vertex_xyz = self.vertex_xyz vertices = vertices or list(self.mesh.vertices()) lines = [] for vertex in vertices: a = vertex_xyz[vertex] n = self.mesh.vertex_normal(vertex) b = add_vectors(a, scale_vector(n, scale)) lines.append({ 'start': a, 'end': b, 'color': color, 'name': "{}.vertexnormal.{}".format(self.mesh.name, vertex), 'arrow': 'end'}) return compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
def draw(self, show_points=False): """Draw the line. Parameters ---------- show_points : bool, optional Show the start and end point. Default is ``False``. Returns ------- list The GUIDs of the created Rhino objects. """ start = list(self.primitive.start) end = list(self.primitive.end) guids = [] if show_points: points = [ {'pos': start, 'color': self.color, 'name': self.primitive.name}, {'pos': end, 'color': self.color, 'name': self.primitive.name} ] guids += compas_rhino.draw_points(points, layer=self.layer, clear=False, redraw=False) lines = [{'start': start, 'end': end, 'color': self.color, 'name': self.primitive.name}] guids += compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False) return guids
def draw_vertexnormals(self, keys=None, color=None, scale=None): keys = keys or list(self.mesh.vertices()) scale = scale or self.settings.get('scale.normal:vertex') color = color or self.settings.get('color.normal:vertex') lines = [] for key in keys: a = self.mesh.vertex_coordinates(key) n = self.mesh.vertex_normal(key) b = add_vectors(a, scale_vector(n, scale)) lines.append({ 'start': a, 'end': b, 'color': color, 'name': "{}.vertex.normal.{}".format(self.mesh.name, key), 'arrow': 'end' }) return compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
def draw(self, show_points=False, show_edges=False, show_face=True): """Draw the polygon. Parameters ---------- show_points : bool, optional Default is ``False``. show_edges : bool, optional Default is ``False``. show_face : bool, optional Default is ``True``. Returns ------- list 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.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.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.name}] guids += compas_rhino.draw_faces(polygons, layer=self.layer, clear=False, redraw=False) self._guids = guids return guids
def draw(self, point=None, show_point=False): """Draw the vector. Parameters ---------- point : [float, float, float] or :class:`compas.geometry.Point`, optional Point of application of the vector. Default is ``Point(0, 0, 0)``. show_point : bool, optional If True, draw the base point of the vector. Returns ------- list[System.Guid] The GUIDs of the created Rhino objects. """ if not point: point = [0, 0, 0] start = Point(*point) end = start + self.primitive start = list(start) end = list(end) guids = [] if show_point: points = [{'pos': start, 'color': self.color, 'name': self.primitive.name}] guids += compas_rhino.draw_points(points, layer=self.layer, clear=False, redraw=False) lines = [{'start': start, 'end': end, 'arrow': 'end', 'color': self.color, 'name': self.primitive.name}] guids += compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False) return guids
def draw_facenormals(self, faces=None, color=(0, 255, 255), scale=1.0): """Draw the normals of the faces. Parameters ---------- faces : list, optional A selection of face normals to draw. Default is to draw all face normals. color : tuple, optional The color specification of the normal vectors. The default color is cyan, ``(0, 255, 255)``. scale : float, optional Scale factor for the face normals. Default is ``1.0``. Returns ------- list The GUIDs of the created Rhino objects. """ vertex_xyz = self.vertex_xyz faces = faces or list(self.mesh.faces()) lines = [] for face in faces: a = centroid_points([vertex_xyz[vertex] for vertex in self.mesh.face_vertices(face)]) n = self.mesh.face_normal(face) b = add_vectors(a, scale_vector(n, scale)) lines.append({ 'start': a, 'end': b, 'name': "{}.facenormal.{}".format(self.mesh.name, face), 'color': color, 'arrow': 'end'}) return compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
def draw(self): """Draw the polyhedron 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
def draw_edges(self, edges=None, color=None): """Draw a selection of edges. Parameters ---------- edges : list, optional A selection of edges to draw. The default is ``None``, in which case all edges are drawn. color : tuple or dict of tuple, optional The color specififcation for the edges. The default color is black, ``(0, 0, 0)``. Returns ------- list The GUIDs of the created Rhino objects. """ edges = edges or list(self.mesh.edges()) vertex_xyz = self.vertex_xyz edge_color = colordict(color, edges, default=self.color_edges) lines = [] for edge in edges: lines.append({ 'start': vertex_xyz[edge[0]], 'end': vertex_xyz[edge[1]], 'color': edge_color[edge], 'name': "{}.edge.{}-{}".format(self.mesh.name, *edge) }) return compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
def draw_facenormals(self, color=None, scale=1.0): """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, scale_vector(n, scale)) lines.append({ 'start': sp, 'end': ep, 'name': "{}.face.normal.{}".format(self.datastructure.name, fkey), 'color': color, 'arrow': 'end' }) return compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
def draw_collection(collection, names=None, colors=None, layer=None, clear=False, add_to_group=False, group_name=None): """Draw a collection of lines. Parameters ---------- collection: list of compas.geometry.Line A collection of ``Line`` objects. names : list of str, optional Individual names for the lines. colors : color or list of color, optional A color specification for the lines as a single color or a list of individual colors. layer : str, optional A layer path. clear : bool, optional Clear the layer before drawing. add_to_group : bool, optional Add the frames to a group. group_name : str, optional Name of the group. Returns ------- guids: list A list of GUIDs if the collection is not grouped. groupname: str The name of the group if the collection objects are grouped. """ lines = [{ 'start': list(line[0]), 'end': list(line[1]) } for line in collection] if colors: if isinstance(colors[0], (int, float)): colors = iterable_like(collection, [colors], colors) else: colors = iterable_like(collection, colors, colors[0]) for line, rgb in zip(lines, colors): line['color'] = rgb if names: if isinstance(names, basestring): names = iterable_like(collection, [names], names) else: names = iterable_like(collection, names, names[0]) for line, name in zip(lines, names): line['name'] = name guids = compas_rhino.draw_lines(lines, layer=layer, clear=clear) if not add_to_group: return guids group = compas_rhino.rs.AddGroup(group_name) if group: compas_rhino.rs.AddObjectsToGroup(guids, group) return group