D. Cablenet and Connectivity

Now you have learned the compas geometries and how to draw them in the plotter. In this session, we will use what we have learned to visualize a simple flat cable-net.

1. Ex 1: Visualize Cablenet

Question:

You want to visualize your 2D cablenet with plotter. It's a 6 by 6 grid, and the orthogonal distance between each node is 10. All cables are represented by lines, and nodes are by points.

Answer:

1.a. draw nodes

Firstly, use Point objects to visualize all the nodes.

# ==============================================================================
# Import
# ==============================================================================
from compas.geometry import Point
from compas_plotters import GeometryPlotter

# ==============================================================================
# Parameters
# ==============================================================================
row = 5
col = 5
unit_len = 10

# ==============================================================================
# Generating the grid nodes and Visualization
# ==============================================================================
# initiate the plotter
plotter = GeometryPlotter(show_axes=True)

# use a nested for loop to generate the grid
for i in range(row + 1):
    for j in range(col + 1):
        my_point = Point(i * unit_len, j * unit_len, 0)
        plotter.add(my_point)

# show in plotter
plotter.zoom_extents()
plotter.show()

1.b. draw cables

Then draw Line objects.

# create a 5 by 5 grid
# distance between points in x and y directions are both 10

# ==============================================================================
# Import
# ==============================================================================
from compas.geometry import Line
from compas_plotters import GeometryPlotter

# ==============================================================================
# Parameters
# ==============================================================================
row = 5
col = 5
unit_len = 10

# ==============================================================================
# Generating the grid lines and Visualization
# ==============================================================================
# initiate the plotter
plotter = GeometryPlotter(show_axes=True)

# use a nested for loop to generate the grid
for i in range(row + 1):
    for j in range(col + 1):
        # draw horizontal lines
        if i != row:
            start_x = i * unit_len
            start_y = j * unit_len
            end_x = (i + 1) * unit_len
            end_y = j * unit_len

            line_horizontal = Line([start_x, start_y, 0], [end_x, end_y, 0])
            plotter.add(line_horizontal, draw_points=False, draw_as_segment=True, color=(1, 0, 0))

        # draw vertical lines
        if j != col:
            start_x = i * unit_len
            start_y = j * unit_len
            end_x = i * unit_len
            end_y = (j + 1) * unit_len
            line_vertical = Line([start_x, start_y, 0], [end_x, end_y, 0])
            plotter.add(line_vertical, draw_points=False, draw_as_segment=True, color=(0, 1, 0))

# show in plotter
plotter.zoom_extents()
plotter.show()

1.c: draw nodes and lines

Now draw both nodes and cables.

2. Connectivity

In the last part drawing the cable-net, all lines use two points composed of xyz values as input. Thus, when a line is created, two points are created at the same time. How many times a point is created depends on how many lines connect this point. This is in-efficient and hard to organize the information when the cable-net becomes bigger and more complex.

A simple improvement is to use the index of the point when creating lines to avoid repetition. Every time a line is created, an index pair of the start-point and end-point would be used to find the corresponding xyz coordinates of the points.

The index pair is called the connectivity. Here points are called nodes, and lines are called edges. In the following example, node 2 and node 4 are connected, node 4 and node 3 are disconnected.

nodes

xyz coordinates

0

[1, 0, 0]

1

[0, 1, 0]

2

[1, 1, 0]

3

[2, 1, 0]

4

[1, 2, 0]

edges

xyz coordinates

edge connectivity

0

[1, 0, 0], [1, 1, 0]

(0, 2)

1

[0, 1, 0], [1, 1, 0]

(1, 2)

2

[2, 1, 0], [1, 1, 0]

(3, 2)

3

[1, 2, 0], [1, 1, 0]

(4, 2)

The connectivity represents the abstract topology of the cable-net. One significant advantage of the connectivity is that when the xyz coordinate of a node is updated, There's no need to find the lines that contain this point and update the line.

Now, try modifying the cable-net using the connectivity data-structure. List nodes contains all the xyz coordinates of the nodes. List edges contains the connectivity index pairs of the edges.

2.a: Connectivity and Cable-net

# ==============================================================================
# Import
# ==============================================================================
from compas.geometry import Point, Line
from compas_plotters import GeometryPlotter

# ==============================================================================
# Parameters
# ==============================================================================
row = 5
col = 5
unit_len = 10

nodes = []  # list containing the xyz coordinates of the nodes
edges = []  # list containing connectivity of the edges

# ==============================================================================
# Generating the grid
# ==============================================================================
# use a nested for loop to generate the grid
for i in range(row + 1):
    for j in range(col + 1):
        # add the xyz coordinates to nodes
        nodes.append([i * unit_len, j * unit_len, 0])
        # index of the node
        index = i * (row + 1) + j
        # add horizontal edges
        if i != row:
            edges.append([index, index + row + 1])
        # add vertical edges
        if j != col:
            edges.append([index, index + 1])

# ==============================================================================
# Visualize Plottor
# ==============================================================================
plotter = GeometryPlotter(show_axes=True)

for node in nodes:
    plotter.add(Point(*node))

for u, v in edges:
    line = Line(nodes[u], nodes[v])
    plotter.add(line, draw_points=False, draw_as_segment=True)

# show in plotter
plotter.zoom_extents()
plotter.show()

2.b: Update the Cable-net

Question:

Move node 20 along positive x-axis 1 unit and along positive y-axis 2 unit. Update the cable-net.

Answer:

nodes[20][0] += 1
nodes[20][1] += 2

3. Ex 2: Assemble your Cable-net

Question:

You have received all your cables cut correctly in length and nodes. (You could use the cable-net created in the last session) Now you pick one node, node 20, and try to find the nodes connected to it and the cables that connect two nodes. How would you do it?

Answer:

Edges contain all the index pairs of two nodes that are connected. If one of the nodes is node 20, then the other node is the one connected with node 20.

my_node_index = 20
neighbors = []

for u, v in edges:
    if u == my_node_index:
        neighbors.append(v)
    elif v == my_node_index:
        neighbors.append(u)

print("The nodes connect node", my_node_index, "are nodes:", *neighbors)

The nodes connect node 12 are nodes: 14 19 26 21

my_node = nodes[my_node_index]
for nbr_index in neighbors:
    neighbor_node = nodes[nbr_index]
    distance = distance_point_point(my_node, neighbor_node)
    print("distance to node", nbr_index, "is", round(distance, 2))

distance to node 14 is 11.18 distance to node 19 is 12.04 distance to node 26 is 9.22 distance to node 21 is 8.06

Question: What if you want to keep searching more nodes?

Answer:

A simple solution is to change the last part to a function. But this function always loop through all the edges to find the correct index, which is not efficient. Another solution could be creating an index pair dictionary to store the connectivity information, where the key is the index of the node and the item is a list that contains all the neighbor index of the node.

node_neighbors = {i: [] for i in range(len(nodes))}

for u, v in edges:
    node_neighbors[u].append(v)
    node_neighbors[v].append(u)

print(node_neighbors[20])

The number of neighbors of a node isis called the degree or valence of a node.

Last updated