Source code for compas_rhino.objects.networkobject


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import compas_rhino
from compas.geometry import Point
from compas.geometry import Scale
from compas.geometry import Translation
from compas.geometry import Rotation
from compas_rhino.objects._object import BaseObject
from compas_rhino.objects.modify import network_update_attributes
from compas_rhino.objects.modify import network_update_node_attributes
from compas_rhino.objects.modify import network_update_edge_attributes
from compas_rhino.objects.modify import network_move_node


__all__ = ['NetworkObject']


[docs]class NetworkObject(BaseObject): """Class for representing COMPAS networkes in Rhino. Parameters ---------- network : :class:`compas.datastructures.Network` A network data structure. scene : :class:`compas.scenes.Scene`, optional A scene object. name : str, optional The name of the object. layer : str, optional The layer for drawing. visible : bool, optional Toggle for the visibility of the object. settings : dict, optional A dictionary of settings. """ SETTINGS = { 'color.nodes': (255, 255, 255), 'color.edges': (0, 0, 0), 'show.nodes': True, 'show.edges': True, 'show.nodelabels': False, 'show.edgelabels': False, } modify = network_update_attributes modify_nodes = network_update_node_attributes modify_edges = network_update_edge_attributes def __init__(self, network, scene=None, name=None, layer=None, visible=True, settings=None): super(NetworkObject, self).__init__(network, scene, name, layer, visible) self._guid_node = {} self._guid_edge = {} self._guid_nodelabel = {} self._guid_edgelabel = {} self._anchor = None self._location = None self._scale = None self._rotation = None self.settings.update(NetworkObject.SETTINGS) if settings: self.settings.update(settings) @property def network(self): return self.item @network.setter def network(self, network): self.item = network self._guids = [] self._guid_node = {} self._guid_edge = {} self._guid_nodelabel = {} self._guid_edgelabel = {} # def __getstate__(self): # pass # def __setstate__(self, state): # pass @property def anchor(self): """The node of the network that is anchored to the location of the object.""" return self._anchor @anchor.setter def anchor(self, node): if self.network.has_node(node): self._anchor = node @property def location(self): """:class:`compas.geometry.Point`: The location of the object. Default is the origin of the world coordinate system. The object transformation is applied relative to this location. Setting this location will make a copy of the provided point object. Moving the original point will thus not affect the object's location. """ if not self._location: self._location = Point(0, 0, 0) return self._location @location.setter def location(self, location): self._location = Point(*location) @property def scale(self): """float: A uniform scaling factor for the object in the scene. The scale is applied relative to the location of the object in the scene. """ if not self._scale: self._scale = 1.0 return self._scale @scale.setter def scale(self, scale): self._scale = scale @property def rotation(self): """list of float: The rotation angles around the 3 axis of the coordinate system with the origin placed at the location of the object in the scene. """ if not self._rotation: self._rotation = [0, 0, 0] return self._rotation @rotation.setter def rotation(self, rotation): self._rotation = rotation @property def node_xyz(self): """dict : The view coordinates of the mesh object.""" origin = Point(0, 0, 0) if self.anchor is not None: xyz = self.network.node_attributes(self.anchor, 'xyz') point = Point(* xyz) T1 = Translation.from_vector(origin - point) S = Scale.from_factors([self.scale] * 3) R = Rotation.from_euler_angles(self.rotation) T2 = Translation.from_vector(self.location) X = T2 * R * S * T1 else: S = Scale.from_factors([self.scale] * 3) R = Rotation.from_euler_angles(self.rotation) T = Translation.from_vector(self.location) X = T * R * S network = self.network.transformed(X) node_xyz = {network: network.node_attributes(node, 'xyz') for node in network.nodes()} return node_xyz @property def guid_node(self): """dict: Map between Rhino object GUIDs and network node identifiers.""" if not self._guid_node: self._guid_node = {} return self._guid_node @guid_node.setter def guid_node(self, values): self._guid_node = dict(values) @property def guid_edge(self): """dict: Map between Rhino object GUIDs and network edge identifiers.""" if not self._guid_edge: self._guid_edge = {} return self._guid_edge @guid_edge.setter def guid_edge(self, values): self._guid_edge = dict(values) @property def guid_nodelabel(self): """dict: Map between Rhino object GUIDs and network nodelabel identifiers.""" return self._guid_vertexlabel @guid_nodelabel.setter def guid_nodelabel(self, values): self._guid_vertexlabel = dict(values) @property def guid_edgelabel(self): """dict: Map between Rhino object GUIDs and network edgelabel identifiers.""" return self._guid_edgelabel @guid_edgelabel.setter def guid_edgelabel(self, values): self._guid_edgelabel = dict(values) @property def guids(self): guids = [] guids += list(self.guid_node) guids += list(self.guid_edge) return guids
[docs] def clear(self): compas_rhino.delete_objects(self.guids, purge=True) self._guid_node = {} self._guid_edge = {}
[docs] def draw(self): """Draw the object representing the network. """ self.clear() if not self.visible: return self.artist.node_xyz = self.node_xyz if self.settings['show.nodes']: nodes = list(self.network.nodes()) guids = self.artist.draw_nodes(nodes=nodes, color=self.settings['color.nodes']) self.guid_node = zip(guids, nodes) if self.settings['show.nodelabels']: text = {node: str(node) for node in nodes} guids = self.artist.draw_nodelabels(text=text, color=self.settings['color.nodes']) self.guid_nodelabel = zip(guids, nodes) if self.settings['show.edges']: edges = list(self.network.edges()) guids = self.artist.draw_edges(edges=edges, color=self.settings['color.edges']) self.guid_edge = zip(guids, edges) if self.settings['show.edgelabels']: text = {edge: "{}-{}".format(*edge) for edge in edges} guids = self.artist.draw_edgelabels(text=text, color=self.settings['color.edges']) self.guid_edgelabel = zip(guids, edges) self.redraw()
def select(self): # there is currently no "general" selection method # for the entire mesh object raise NotImplementedError
[docs] def select_nodes(self): """Select nodes of the network. Returns ------- list A list of node identifiers. """ guids = compas_rhino.select_points() nodes = [self.guid_node[guid] for guid in guids if guid in self.guid_node] return nodes
[docs] def select_edges(self): """Select edges of the network. Returns ------- list A list of edge identifiers. """ guids = compas_rhino.select_lines() edges = [self.guid_edge[guid] for guid in guids if guid in self.guid_edge] return edges
def move(self): """Move the entire mesh object to a different location.""" raise NotImplementedError def move_node(self, node): """Move a single node of the network object and update the data structure accordingly. Parameters ---------- node : int The identifier of the node. Returns ------- bool True if the operation was successful. False otherwise. """ return network_move_node(self.network, node)
# ============================================================================ # Main # ============================================================================ if __name__ == "__main__": pass