Exemplo n.º 1
0
def test_astar_shortest_path():
    n = Network()
    a = n.add_node(x=1, y=2, z=0)
    b = n.add_node(x=3, y=1, z=0)
    n.add_edge(a, b)
    path = astar_shortest_path(n, a, b)
    assert path == [a, b]
Exemplo n.º 2
0
def test_astar_shortest_path_disconnected():
    n = Network()
    a = n.add_node(x=1, y=0, z=0)
    b = n.add_node(x=2, y=0, z=0)
    c = n.add_node(x=3, y=0, z=0)
    n.add_edge(a, b)
    path = astar_shortest_path(n, a, c)
    assert path is None
Exemplo n.º 3
0
def test_json_network():
    before = Network()
    a = before.add_node()
    b = before.add_node()
    before.add_edge(a, b)
    after = compas.json_loads(compas.json_dumps(before))
    assert before.dtype == after.dtype
    assert before.attributes == after.attributes
    assert all(before.has_node(node) for node in after.nodes())
    assert all(after.has_node(node) for node in before.nodes())
    assert all(before.has_edge(*edge) for edge in after.edges())
    assert all(after.has_edge(*edge) for edge in before.edges())
Exemplo n.º 4
0
def meshes_to_network(meshes):
    network = Network()

    network.update_default_node_attributes(mesh=None, vkey=None, fkey=None)
    network.update_default_edge_attributes(mesh=None, fkey=None)

    for i, mesh in enumerate(meshes):
        for vkey in mesh.vertices():
            x, y, z = mesh.vertex_coordinates(vkey)
            network.add_node(x=x, y=y, z=z, mesh=i, vkey=vkey)
        for u, v in mesh.edges():
            u1 = next(network.nodes_where({"vkey": u, "mesh": i}))
            v1 = next(network.nodes_where({"vkey": v, "mesh": i}))
            network.add_edge(u1, v1, mesh=i)

    return network
Exemplo n.º 5
0
def test_astar_shortest_path_cycle():
    n = Network()
    a = n.add_node(x=1, y=0, z=0)
    b = n.add_node(x=2, y=0, z=0)
    c = n.add_node(x=3, y=0, z=0)
    d = n.add_node(x=4, y=0, z=0)
    e = n.add_node(x=3.5, y=5, z=0)
    n.add_edge(a, b)
    n.add_edge(a, e)
    n.add_edge(b, c)
    n.add_edge(c, d)
    n.add_edge(e, d)
    path = astar_shortest_path(n, a, d)
    assert path == [a, b, c, d]
Exemplo n.º 6
0
import random

from compas_rhino.artists import NetworkArtist
from compas.datastructures import Network

network = Network()

last_node = None
for i in range(12):
    node = network.add_node(x=i // 3, y=i % 3, z=0)
    network.node_attribute(node, 'weight', random.choice(range(20)))

    if last_node:
        network.add_edge(node, i - 1)
    last_node = node

print(network.summary())
print(network.to_data())

text = {
    node: network.node_attribute(node, 'weight')
    for node in network.nodes()
}

artist = NetworkArtist(network, layer='network')
artist.clear_layer()
artist.draw_nodelabels(text)
artist.draw()
artist.redraw()
Exemplo n.º 7
0
# with 5 nodes and 4 edges

network = Network()

network.update_dna(is_anchor=False)
network.update_dna(rx=0, ry=0, rz=0)
network.update_dea(f=1)

a = network.add_node(x=0, y=0, z=0, is_anchor=True)
b = network.add_node(x=10, y=0, z=10, is_anchor=True)
c = network.add_node(x=10, y=10, z=0, is_anchor=True)
d = network.add_node(x=0, y=10, z=10, is_anchor=True)

e = network.add_node(x=5, y=5, z=0)

network.add_edge(a, e)
network.add_edge(b, e)
network.add_edge(c, e)
network.add_edge(d, e)

# compute all residuals in the current geometry

for node in network.nodes():
    r = compute_residual(network, node)
    network.node_attributes(node, ['rx', 'ry', 'rz'], r)

# move free nodes in direction of residual

for node in network.nodes():
    if network.node_attribute(node, 'is_anchor'):
        continue
Exemplo n.º 8
0
from compas.geometry import Pointcloud, KDTree
from compas.datastructures import Network

cloud = Pointcloud.from_bounds(10, 5, 3, 200)
tree = KDTree(cloud)

network = Network()

for point in cloud:
    network.add_node(x=point[0], y=point[1], z=point[2])

for node in network.nodes():
    point = network.node_coordinates(node)
    for nbr in tree.nearest_neighbors(point, 4, distance_sort=True):
        if nbr[2] < 1e-6:
            continue
        if not network.has_edge(node, nbr[1], directed=False):
            network.add_edge(node, nbr[1])

start = network.get_any_node()
goal = network.get_any_node()
path = network.shortest_path(start, goal)
Exemplo n.º 9
0
def k5_network():
    network = Network()
    network.add_edge('a', 'b')
    network.add_edge('a', 'c')
    network.add_edge('a', 'd')
    network.add_edge('a', 'e')

    network.add_edge('b', 'c')
    network.add_edge('b', 'd')
    network.add_edge('b', 'e')

    network.add_edge('c', 'd')
    network.add_edge('c', 'e')

    network.add_edge('d', 'e')

    return network
class Assembly(FromToData, FromToJson):
    """A data structure for discrete element assemblies.

    An assembly is essentially a network of assembly elements.
    Each element is represented by a node of the network.
    Each interface or connection between elements is represented by an edge of the network.

    Attributes
    ----------
    network : :class:`compas.Network`, optional
    elements : list of :class:`Element`, optional
        A list of assembly elements.
    attributes : dict, optional
        User-defined attributes of the assembly.
        Built-in attributes are:
        * name (str) : ``'Assembly'``
    default_element_attribute : dict, optional
        User-defined default attributes of the elements of the assembly.
        The built-in attributes are:
        * is_planned (bool) : ``False``
        * is_placed (bool) : ``False``
    default_connection_attributes : dict, optional
        User-defined default attributes of the connections of the assembly.

    Examples
    --------
    >>> assembly = Assembly()
    >>> for i in range(2):
    >>>     element = Element.from_box(Box(Frame.worldXY(), 10, 5, 2))
    >>>     assembly.add_element(element)
    """
    def __init__(self,
                 elements=None,
                 attributes=None,
                 default_element_attributes=None,
                 default_connection_attributes=None):

        self.network = Network()
        self.network.attributes.update({'name': 'Assembly'})

        if attributes is not None:
            self.network.attributes.update(attributes)

        self.network.default_node_attributes.update({
            'is_planned': False,
            'is_placed': False
        })

        if default_element_attributes is not None:
            self.network.default_node_attributes.update(
                default_element_attributes)

        if default_connection_attributes is not None:
            self.network.default_edge_attributes.update(
                default_connection_attributes)

        if elements:
            for element in elements:
                self.add_element(element)

    @property
    def name(self):
        """str : The name of the assembly."""
        return self.network.attributes.get('name', None)

    @name.setter
    def name(self, value):
        self.network.attributes['name'] = value

    def number_of_elements(self):
        """Compute the number of elements of the assembly.

        Returns
        -------
        int
            The number of elements.

        """
        return self.network.number_of_nodes()

    def number_of_connections(self):
        """Compute the number of connections of the assembly.

        Returns
        -------
        int
            the number of connections.

        """
        return self.network.number_of_edges()

    @property
    def data(self):
        """Return a data dictionary of the assembly.
        """
        # Network data does not recursively serialize to data...
        d = self.network.data
        # so we need to trigger that for elements stored in nodes
        node = {}
        for vkey, vdata in d['data']['node'].items():
            node[vkey] = {
                key: vdata[key]
                for key in vdata.keys() if key != 'element'
            }
            node[vkey]['element'] = vdata['element'].to_data()
        d['data']['node'] = node
        return d

    @data.setter
    def data(self, data):
        # Deserialize elements from node dictionary
        for _vkey, vdata in data['data']['node'].items():
            vdata['element'] = Element.from_data(vdata['element'])

        self.network = Network.from_data(data)

    def clear(self):
        """Clear all the assembly data."""
        self.network.clear()

    def add_element(self, element, key=None, attr_dict={}, **kwattr):
        """Add an element to the assembly.

        Parameters
        ----------
        element : Element
            The element to add.
        attr_dict : dict, optional
            A dictionary of element attributes. Default is ``None``.

        Returns
        -------
        hashable
            The identifier of the element.
        """
        attr_dict.update(kwattr)
        x, y, z = element.frame.point
        key = self.network.add_node(key=key,
                                    attr_dict=attr_dict,
                                    x=x,
                                    y=y,
                                    z=z,
                                    element=element)
        return key

    def add_connection(self, u, v, attr_dict=None, **kwattr):
        """Add a connection between two elements and specify its attributes.

        Parameters
        ----------
        u : hashable
            The identifier of the first element of the connection.
        v : hashable
            The identifier of the second element of the connection.
        attr_dict : dict, optional
            A dictionary of connection attributes.
        kwattr
            Other connection attributes as additional keyword arguments.

        Returns
        -------
        tuple
            The identifiers of the elements.
        """
        return self.network.add_edge(u, v, attr_dict, **kwattr)

    def transform(self, transformation):
        """Transforms this assembly.

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

        Returns
        -------
        None
        """
        for _k, element in self.elements(data=False):
            element.transform(transformation)

    def transformed(self, transformation):
        """Returns a transformed copy of this assembly.

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

        Returns
        -------
        Assembly
        """
        assembly = self.copy()
        assembly.transform(transformation)
        return assembly

    def copy(self):
        """Returns a copy of this assembly.
        """
        raise NotImplementedError

    def element(self, key, data=False):
        """Get an element by its key."""
        if data:
            return self.network.node[key]['element'], self.network.node[key]
        else:
            return self.network.node[key]['element']

    def elements(self, data=False):
        """Iterate over the elements of the assembly.

        Parameters
        ----------
        data : bool, optional
            If ``True``, yield both the identifier and the attributes.

        Yields
        ------
        2-tuple
            The next element as a (key, element) tuple, if ``data`` is ``False``.
        3-tuple
            The next element as a (key, element, attr) tuple, if ``data`` is ``True``.

        """
        if data:
            for vkey, vattr in self.network.nodes(True):
                yield vkey, vattr['element'], vattr
        else:
            for vkey in self.network.nodes(data):
                yield vkey, self.network.node[vkey]['element']

    def connections(self, data=False):
        """Iterate over the connections of the network.

        Parameters
        ----------
        data : bool, optional
            If ``True``, yield both the identifier and the attributes.

        Yields
        ------
        2-tuple
            The next connection identifier (u, v), if ``data`` is ``False``.
        3-tuple
            The next connection as a (u, v, attr) tuple, if ``data`` is ``True``.

        """
        return self.network.edges(data)
Exemplo n.º 11
0
class AMModel(FromToData, FromToJson):
    """A data structure for non-discrete element fabrication.

    A model is essentially a network of nodes.
    Each geometrical node is represented by a layer in fabrication.
    The sequence of layers in fabrication is represented by an edge of the network.

    Attributes
    ----------
    network : :class:`compas.Network`, optional
    layers : list of :class:`Layer`, optional
        A list of model layers.
    attributes : dict, optional
        User-defined attributes of the model.
        Built-in attributes are:
        * name (str) : ``'AMModel'``
    default_layer_attribute : dict, optional
        User-defined default attributes of the layers of the model.
        The built-in attributes are:
        * is_planned (bool) : ``False``
        * is_placed (bool) : ``False``

    Examples
    --------

    """
    def __init__(self,
                 layers=None,
                 attributes=None,
                 default_layer_attribute=None,
                 default_connection_attributes=None):

        self.network = Network()
        self.network.attributes.update({'name': 'AMModel'})

        if attributes is not None:
            self.network.attributes.update(attributes)

        self.network.default_node_attributes.update({
            'is_planned': False,
            'is_placed': False
        })

        if default_layer_attribute is not None:
            self.network.default_node_attributes.update(
                default_layer_attribute)

        if default_connection_attributes is not None:
            self.network.default_edge_attributes.update(
                default_connection_attributes)

        if layers:
            for layer in layers:
                self.add_layer(layer)

    @property
    def name(self):
        """str : The name of the model."""
        return self.network.attributes.get('name', None)

    @name.setter
    def name(self, value):
        self.network.attributes['name'] = value

    def number_of_layers(self):
        """Compute the number of layers of the model.

        Returns
        -------
        int
            The number of nodes.

        """
        return self.network.number_of_nodes()

    def number_of_connections(self):
        """Compute the number of connections of the model.

        Returns
        -------
        int
            the number of connections.

        """
        return self.network.number_of_edges()

    @property
    def data(self):
        """Return a data dictionary of the model.
        """
        # Network data does not recursively serialize to data...
        d = self.network.data
        #print(d.keys())
        # so we need to trigger that for layers stored in nodes
        node = {}
        for vkey, vdata in d['data']['node'].items():
            node[vkey] = {
                key: vdata[key]
                for key in vdata.keys() if key != 'layer'
            }
            node[vkey]['layer'] = vdata['layer'].to_data()

        d['data']['node'] = node
        return d

    @data.setter
    def data(self, data):
        # Deserialize elements from node dictionary
        for _vkey, vdata in data['data']['node'].items():
            vdata['layer'] = Layer.from_data(vdata['layer'])

        self.network = Network.from_data(data)

    def clear(self):
        """Clear all the model data."""
        self.network.clear()

    def add_layer(self, layer, key=None, attr_dict={}, **kwattr):
        """Add an element to the model.

        Parameters
        ----------
        layer : Layer
            The layer to add.
        attr_dict : dict, optional
            A dictionary of layer attributes. Default is ``None``.

        Returns
        -------
        hashable
            The identifier of the element.
        """
        attr_dict.update(kwattr)
        key = self.network.add_node(key=key, attr_dict=attr_dict, layer=layer)
        return key

    def add_edge(self, u, v, attr_dict=None, **kwattr):
        """Add a connection between two elements and specify its attributes.

        Parameters
        ----------
        u : hashable
            The identifier of the first element of the connection.
        v : hashable
            The identifier of the second element of the connection.
        attr_dict : dict, optional
            A dictionary of connection attributes.
        kwattr
            Other connection attributes as additional keyword arguments.

        Returns
        -------
        tuple
            The identifiers of the elements.
        """
        return self.network.add_edge(u, v, attr_dict, **kwattr)

    def transform(self, transformation):
        """Transforms this model.

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

        Returns
        -------
        None
        """
        for _k, layer in self.layers(data=False):
            layer.transform(transformation)

    def transformed(self, transformation):
        """Returns a transformed copy of this model.

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

        Returns
        -------
        Assembly
        """
        model = self.copy()
        model.transform(transformation)
        return model

    def copy(self):
        """Returns a copy of this model.
        """
        layers = []
        for key, layer in self.layers():
            layers.append(layer.copy())
        return AMModel(layers, self.network.attributes)

    def layer(self, key, data=False):
        """Get an layer by its key."""
        if data:
            return self.network.node[key]['layer'], self.network.node[key]
        else:
            return self.network.node[key]['layer']

    def layers(self, data=False):
        """Iterate over the elements of the model.

        Parameters
        ----------
        data : bool, optional
            If ``True``, yield both the identifier and the attributes.

        Yields
        ------
        2-tuple
            The next element as a (key, element) tuple, if ``data`` is ``False``.
        3-tuple
            The next element as a (key, element, attr) tuple, if ``data`` is ``True``.

        """
        if data:
            for vkey, vattr in self.network.nodes(True):
                yield vkey, vattr['layer'], vattr
        else:
            for vkey in self.network.nodes(data):
                yield vkey, self.network.node[vkey]['layer']

    def connections(self, data=False):
        """Iterate over the connections of the network.

        Parameters
        ----------
        data : bool, optional
            If ``True``, yield both the identifier and the attributes.

        Yields
        ------
        2-tuple
            The next connection identifier (u, v), if ``data`` is ``False``.
        3-tuple
            The next connection as a (u, v, attr) tuple, if ``data`` is ``True``.

        """
        return self.network.edges(data)
Exemplo n.º 12
0
import random

from compas_rhino.artists import NetworkArtist
from compas.datastructures import Network

network = Network()

network.add_edge(1, 2)
network.add_edge(2, 3)
network.add_edge(1, 4)
network.add_edge(4, 5)
network.add_edge(4, 6)

for node in network.nodes():
    x = random.choice(range(5))
    y = random.choice(range(5))
    z = random.choice(range(5))
    network.node_attributes(node, 'xyz', [x, y, z])

print(network.summary())

text = {node: str(node) for node in network.nodes()}

artist = NetworkArtist(network, layer='network')
artist.clear_layer()
artist.draw_nodelabels(text)
artist.draw()
artist.redraw()
Exemplo n.º 13
0
    network.add_vertex(key=fkey, attr_dict=attr_dict)

for fkey in mesh.faces():
    nbrs = mesh.face_neighbors(fkey)
    for nbr in nbrs:
        if fkey == nbr:
            continue

        angle_diff = math.fabs(angles[fkey] - angles[nbr])

        try:
            ad = network.get_edge_attribute((fkey, nbr), 'angle_diff')
            if ad:
                continue
        except:
            network.add_edge(fkey, nbr, attr_dict={'angle_diff': angle_diff})

# # ==========================================================================
# # color up
# # ==========================================================================

anglemax = max(network.get_edges_attribute('angle_diff'))
print('angle diff max', anglemax)

colors = {}
for u, v, attr in network.edges(True):
    angle_diff = attr['angle_diff']
    color = i_to_rgb(angle_diff / anglemax)
    colors[(u, v)] = color

# # ==========================================================================
Exemplo n.º 14
0
def egi_from_vectors(vectordict, origin, tol=0.001):
    """Construct an egi from a set of vectors.

    Parameters
    ----------
    vectordict : dict
        A dectionary of key-vector pairs.
    origin : list
        The coordinates of the centroid.
    tol : float, optional
        Tolerance for evaluating antipodal.

    Returns
    -------
    egi : mesh
        A mesh object representing the egi.

    Raises
    ------
    Exception
        If there are less than four vectors.

    Notes
    -----
    This algorithm is dependent on Rhinoceros objects; the adjacency arcs are implemented using Rhino.Geometry.Arc, and the cross-adjacencies (arc-arc intersections) are computed using Rhino.Geometry.Intersect.Intersection.CurveCurve.

    Warning
    -------
    - This algorithm does not address scenarios where multiple parallel (collinear) vectors are present.

    References
    ----------
    - Horn, B.K.P. (1984). *Extended Gaussian images*.
    - Moni, S. (1990, June). *A closed-form solution for the reconstruction
    of a convex polyhedron from its extended gaussian image.*
    - Lee, J., T. Van Mele, and P. Block (2018). *Disjointed force polyhedra.*

    """
    if len(vectordict) < 4:
        raise Exception('Four or more vectors are needed for the construction of egi.')

    egi = Network()

    # --------------------------------------------------------------------------
    #   1. add vertices from vectors
    # --------------------------------------------------------------------------
    vertex_geokeys = {}

    for vkey in vectordict:
        normal     = normalize_vector(vectordict[vkey])
        vertex_xyz = add_vectors(normal, origin)
        vertex_geokeys[geometric_key(normal)] = vkey
        egi.add_vertex(x=vertex_xyz[0],
                       y=vertex_xyz[1],
                       z=vertex_xyz[2],
                       key=vkey,
                       attr_dict={'type'  : 'face',
                                  'normal': normal,
                                  'nbrs'  : []})

    # --------------------------------------------------------------------------
    #   2.  Identify main adjacencies
    # --------------------------------------------------------------------------
    vkey_pairs = set()

    for vkey in egi.vertex:
        v_crs_dict = {}

        for nbr_vkey in egi.vertex:

            if nbr_vkey is not vkey:

                n1 = egi.vertex[vkey]['normal']
                n2 = egi.vertex[nbr_vkey]['normal']

                # This checks if the normals are opposite ----------------------
                dot = dot_vectors(n1, n2)

                if dot > 1 - tol:
                    raise Exception("Coincident vectors detected.")

                elif dot > -1 + tol:

                    this_crs = cross_vectors(n1, n2)
                    unit_crs = normalize_vector(this_crs)

                    crs_gkey = geometric_key(unit_crs)

                    # Check to see if any other normals are coplanar
                    if crs_gkey not in v_crs_dict:
                        v_crs_dict[crs_gkey] = nbr_vkey

                    # If multiple arcs are coplanar, choose the closer one
                    elif crs_gkey in v_crs_dict:
                        this_dist = distance(egi.vertex_coordinates(vkey),
                                             egi.vertex_coordinates(nbr_vkey))
                        test_dist = distance(egi.vertex_coordinates(vkey),
                                             egi.vertex_coordinates(v_crs_dict[crs_gkey]))
                        if this_dist < test_dist:
                            del v_crs_dict[crs_gkey]
                            v_crs_dict[crs_gkey] = nbr_vkey

        # Add to overall connectivity dict -------------------------------------
        for crs_gkey in v_crs_dict:
            nbr_vkey = v_crs_dict[crs_gkey]
            pair     = frozenset([vkey, nbr_vkey])
            vkey_pairs.add(pair)

    # --------------------------------------------------------------------------
    #   3.  Main adjacency arcs
    # --------------------------------------------------------------------------
    arcs = {}

    for pair in vkey_pairs:
        u, v = list(pair)
        arc  = _draw_arc(egi.vertex[u]['normal'],
                         egi.vertex[v]['normal'],
                         origin)

        if len(arcs) == 0:
            arc_key = 0
        else:
            arc_key = max(int(x) for x in arcs.keys()) + 1
        arcs[arc_key] = {'arc'      : arc,
                         'vkeys'    : [u, v],
                         'end_vkeys': [u, v],
                         'int_vkeys': {}, }

    # --------------------------------------------------------------------------
    #   3.  arc intersections --> cross adjacencies
    # --------------------------------------------------------------------------
    arc_pairs_seen = set()
    for arckey_1 in arcs:
        for arckey_2 in arcs:
            if arckey_1 != arckey_2:
                arc_pair = frozenset([arckey_1, arckey_2])
                if arc_pair not in arc_pairs_seen:
                    arc_1 = arcs[arckey_1]['arc']
                    arc_2 = arcs[arckey_2]['arc']
                    intersection = _curve_curve_intx(arc_1, arc_2)
                    if intersection:
                        new_vkey   = max(int(vkey) for vkey in egi.vertex.keys()) + 1
                        new_normal = subtract_vectors(intersection, origin)
                        new_normal = normalize_vector(new_normal)
                        new_vertex_geokey = geometric_key(new_normal, precision='3f')

                        # if intersection is not an endpoint -------------------
                        if new_vertex_geokey not in vertex_geokeys.keys():
                            vertex_geokeys[new_vertex_geokey] = new_vkey
                            egi.add_vertex(x=intersection[0],
                                           y=intersection[1],
                                           z=intersection[2],
                                           key=new_vkey,
                                           attr_dict={'type'      : 'zero',
                                                      'normal'    : new_normal,
                                                      'magnitude' : 0,
                                                      'nbrs'      : []})
                            arcs[arckey_1]['vkeys'].append(new_vkey)
                            arcs[arckey_2]['vkeys'].append(new_vkey)
                            arcs[arckey_1]['int_vkeys'][new_vkey] = arckey_2
                            arcs[arckey_2]['int_vkeys'][new_vkey] = arckey_1

                        # if intersection already exists -----------------------
                        elif new_vertex_geokey in vertex_geokeys.keys():
                            vkey = vertex_geokeys[new_vertex_geokey]
                            if vkey not in arcs[arckey_1]['vkeys']:
                                arcs[arckey_1]['vkeys'].append(vkey)
                                arcs[arckey_1]['int_vkeys'][vkey] = arckey_2
                            if vkey not in arcs[arckey_2]['vkeys']:
                                arcs[arckey_2]['vkeys'].append(vkey)
                                arcs[arckey_2]['int_vkeys'][vkey] = arckey_1
                        arc_pairs_seen.add(arc_pair)

    # --------------------------------------------------------------------------
    #   5.  Reorder vertices along each arc and add edges to EGI network
    # --------------------------------------------------------------------------
    for arckey in arcs:
        vkeys = arcs[arckey]['vkeys']
        if len(vkeys) > 2:
            pt_list = [egi.vertex_coordinates(key) for key in vkeys]
            arcs[arckey]['vkeys'] = _reorder_pts_on_arc(pt_list,
                                                        arcs[arckey]['vkeys'],
                                                        arcs[arckey]['arc'])[1]
            edge_type = 'cross'
        else:
            edge_type = 'main'
        for i in range(len(arcs[arckey]['vkeys']) - 1):
            vkey_1 = arcs[arckey]['vkeys'][i]
            vkey_2 = arcs[arckey]['vkeys'][i + 1]
            egi.vertex[vkey_1]['nbrs'] += [vkey_2]
            egi.vertex[vkey_2]['nbrs'] += [vkey_1]
            egi.add_edge(vkey_1, vkey_2)

    # --------------------------------------------------------------------------
    #   6.  For each vertex, sort nbrs in ccw order
    # --------------------------------------------------------------------------
    _egi_sort_v_nbrs(egi)

    # --------------------------------------------------------------------------
    #   7.  Add EGI Network faces
    # --------------------------------------------------------------------------
    egi_mesh = EGI()
    for vkey in egi.vertex:
        egi_mesh.vertex[vkey] = egi.vertex[vkey]

    egi_mesh.attributes['name'] = 'egi'
    egi_mesh.attributes['origin'] = list(origin)

    _egi_find_faces(egi, egi_mesh)

    return egi_mesh
Exemplo n.º 15
0
from compas.datastructures import Network


HERE = os.path.dirname(__file__)
FILE = os.path.join(HERE, 'clusters.json')

network = Network()
network.update_default_node_attributes({'cluster': None, 'base': False})

cloud = Pointcloud.from_bounds(10, 5, 3, 100)
kmeans = KMeans(n_clusters=10, n_init=500, max_iter=100).fit(array(cloud, dtype=float))

clusters = {}
for i, point in zip(kmeans.labels_, cloud):
    print(i)
    if i not in clusters:
        clusters[i] = []
    clusters[i].append(point)

for index in clusters:
    nodes = []
    for point in clusters[index]:
        node = network.add_node(x=point[0], y=point[1], z=point[2], cluster=index)
        nodes.append(node)
    x, y, z = centroid_points(clusters[index])
    base = network.add_node(x=x, y=y, z=z, cluster=index, base=True)
    for node in nodes:
        network.add_edge(base, node)

network.to_json(FILE)
Exemplo n.º 16
0
# create a network

network = Network()

network.update_dna(is_anchor=False)
network.update_dna(rx=0, ry=0, rz=0)
network.update_dea(f=1)

a = network.add_node(x=0, y=0, z=0, is_anchor=True)
b = network.add_node(x=10, y=0, z=10, is_anchor=True)
c = network.add_node(x=10, y=10, z=0, is_anchor=True)
d = network.add_node(x=0, y=10, z=10, is_anchor=True)

e = network.add_node(x=5, y=5, z=0)

network.add_edge(a, e, f=2)
network.add_edge(b, e)
network.add_edge(c, e)
network.add_edge(d, e)

# visualize dynamic process

layer = "ITA20::L5::FormFinding"

artist = NetworkArtist(network, layer=layer)

kmax = 100
tol = 0.01

update_residuals(network)
Exemplo n.º 17
0
network = Network()

network.update_dna(is_anchor=False)
network.update_dna(rx=0, ry=0, rz=0)
network.update_dna(px=0, py=0, pz=0)
network.update_dea(f=0, q=1)

a = network.add_node(x=0, y=0, z=0, is_anchor=True)
b = network.add_node(x=10, y=0, z=10, is_anchor=True)
c = network.add_node(x=10, y=10, z=0, is_anchor=True)
d = network.add_node(x=0, y=10, z=10, is_anchor=True)

e = network.add_node(x=5, y=5, z=0)

network.add_edge(a, e, q=random.randint(1, 10))
network.add_edge(b, e, q=random.randint(1, 10))
network.add_edge(c, e, q=random.randint(1, 10))
network.add_edge(d, e, q=random.randint(1, 10))

# numerical data

n = network.number_of_nodes()

node_index = {node: index for index, node in enumerate(network.nodes())}

fixed = list(network.nodes_where({'is_anchor': True}))
free = list(network.nodes_where({'is_anchor': False}))

fixed[:] = [node_index[node] for node in fixed]
free[:] = [node_index[node] for node in free]
Exemplo n.º 18
0
network = Network()

network.update_dna(is_anchor=False)
network.update_dna(rx=0, ry=0, rz=0)
network.update_dna(px=0, py=0, pz=0)
network.update_dea(q=1)

a = network.add_node(x=0, y=0, z=0, is_anchor=True)
b = network.add_node(x=10, y=0, z=10, is_anchor=True)
c = network.add_node(x=10, y=10, z=0, is_anchor=True)
d = network.add_node(x=0, y=10, z=10, is_anchor=True)

e = network.add_node(x=5, y=5, z=0)

network.add_edge(a, e, q=2)
network.add_edge(b, e, q=5)
network.add_edge(c, e, q=3)
network.add_edge(d, e)

# numerical data

n = network.number_of_nodes()
e = network.number_of_edges()

node_index = {node: index for index, node in enumerate(network.nodes())}

fixed = list(network.nodes_where({'is_anchor': True}))
free = list(network.nodes_where({'is_anchor': False}))

fixed[:] = [node_index[node] for node in fixed]
Exemplo n.º 19
0
from itertools import combinations

from compas.datastructures import Network
from compas.utilities import linspace, meshgrid
from compas_rhino.artists import NetworkArtist

X, Y = meshgrid(linspace(0, 10, 10), linspace(0, 5, 5))

points = []
for z in linspace(0, 3, 3):
    for xs, ys in zip(X, Y):
        for x, y in zip(xs, ys):
            points.append([x, y, z])

network = Network()

for point in points:
    network.add_node(x=point[0], y=point[1], z=point[2])

for a, b in combinations(network.nodes(), 2):
    if network.node_attribute(a, 'z') != network.node_attribute(b, 'z'):
        network.add_edge(a, b)

artist = NetworkArtist(network, layer="ITA20::Network")
artist.clear_layer()
artist.draw_nodes()
artist.draw_edges()
Exemplo n.º 20
0
class Layer:
    """Data structure representing a discrete set of nodes of an model.

    Attributes
    ----------
    network : :class:`compas.Network`, optional
    nodes : :list:class:`Node`, optional
        Nodes discribing the layer geometry
    attributes : dict, optional
        User-defined attributes of the model.
        Built-in attributes are:
        * name (str) : ``'Layer'``
    trajectory : :class:`compas_fab.robots.JointTrajectory`
        The robot trajectory in joint space
    path : :list: :class:`compas.geometry.Frame`
        The robot tool path in cartesian space

    Examples
    --------

    """

    def __init__(self, nodes=None, attributes=None, edges=None):
        self.network = Network()
        self.network.attributes.update({'name': 'Layer',
                                        'is_constructed': False})
        self.is_constructed = False

        if attributes is not None:
            self.network.attributes.update(attributes)
        
        if nodes:
            for node in nodes:
                self.add_node(node)

        self.trajectory = None

    @classmethod
    def from_nodes(cls, nodes):
        """Class method for constructing a layer from a Node objects.

        Parameters
        ----------
        nodes :list: :class:`Node`
            List of Node objects.
        """
        return cls(nodes)

    @property
    def name(self):
        """str : The name of the layer."""
        return self.network.attributes.get('name', None)

    @name.setter
    def name(self, value):
        self.network.attributes['name'] = value
    
    def number_of_nodes(self):
        return self.network.number_of_nodes()
    
    def number_of_edges(self):
        return self.network.number_of_edges()

    def node(self, key, data=False):
        if data:
            return self.network.node[key]['node'], self.network.node[key]
        else:
            return self.network.node[key]['node']

    def nodes(self, data=False):
        if data:
            for vkey, vattr in self.network.nodes(True):
                yield vkey, vattr['node'], vattr
        else:
            for vkey in self.network.nodes(data):
                yield vkey, self.network.node[vkey]['node']

    def edges(self, data=False):
        return self.network.edges(data)

    @property
    def path(self):
        return [node.frame for key, node in self.nodes(False)]

    @path.setter
    def path(self, p):
        self.__path = p

    @classmethod
    def from_data(cls, data):
        """Construct an layer from its data representation.

        Parameters
        ----------
        data : :obj:`dict`
            The data dictionary.

        Returns
        -------
        Layer
            The constructed layer.
        """
        layer = cls()
        layer.data = data
        return layer

    def to_data(self):
        """
        docstring
        """
        return self.data

    @property
    def data(self):
        """Returns the data dictionary that represents the layer.

        Returns
        -------
        dict
            The layer data.

        Examples
        --------
        >>> layer = Layer()
        >>> print(layer.data)
        """
        d = self.network.data
        
        node = {}
        for vkey, vdata in d['data']['node'].items():
            node[vkey] = {key: vdata[key] for key in vdata.keys() if key != 'node'}
            node[vkey]['node'] = vdata['node'].to_data()

        d['data']['node'] = node
        d['data']['is_constructed'] = self.is_constructed
        if self.trajectory:
            d['data']['attributes']['trajectory'] = [f.to_data() for f in self.trajectory]
        if self.path:
            d['data']['attributes']['path'] = [f.to_data() for f in self.path]

        return d

    @data.setter
    def data(self, data):
        for _vkey, vdata in data['data']['node'].items():
            vdata['node'] = Node.from_data(vdata['node'])
        
        if 'is_constructed' in data:
            self.is_constructed = _deserialize_from_data(data['data']['attributes']['is_constructed'])
        if 'trajectory' in data:
            self.trajectory = _deserialize_from_data(data['data']['attributes']['trajectory'])
        if 'path' in data:
            self.path = [Frame.from_data(d) for d in data['data']['attributes']['path']]
        
        self.network = Network.from_data(data)

    def add_node(self, node, key=None, attr_dict={}, **kwattr):
        attr_dict.update(kwattr)
        key = self.network.add_node(key=key, attr_dict=attr_dict, node=node)
        return key
    
    def add_edge(self, u, v, attr_dict=None, **kwattr):
        return self.network.add_edge(u, v, attr_dict, **kwattr)

    def transform(self, transformation):
        for key, node in self.nodes(data=False):
            node.transform(transformation)

    def transformed(self, transformation):
        layer = self.copy()
        layer.transform(transformation)
        return layer

    def copy(self):
        """Returns a copy of this layer.

        Returns
        -------
        Layer
        """
        nodes = []
        for key, node in self.nodes():
            nodes.append(node.copy())
        return Layer(nodes, self.network.attributes)