A1. Form and Force Diagram

Ex 1. Basic Form Finding using TNA

Step 1: Create a FormDiagram

FormDiagram is the 2D projection of the thrust network. It can be represented by a mesh datastructure.

# ==============================================================================
# Import
# ==============================================================================
import os
from compas.datastructures import Mesh
from compas_rhino.artists import MeshArtist

# ==============================================================================
# Unserialization
# ==============================================================================
HERE = os.path.dirname(__file__)
FILE = os.path.join(HERE, 'data', 'form.json')
form = Mesh.from_json(FILE)

# ==============================================================================
#  Visualization
# ==============================================================================
artist = MeshArtist(form, layer="CSD2::form")
artist.clear_layer()
artist.draw()

Step 2: Define Boundaries

Corners with two neighboring support vertices are removed. Edges between two support vertices are removed.

# ===============================================================================
# Define Supports
# ===============================================================================
# update default attributes
form.update_default_vertex_attributes({'is_anchor': False})

# anchor the points on the boundary
anchors = []
for vkey in form.vertices_on_boundary():
    form.vertex_attribute(vkey, 'is_anchor', True)
    anchors.append(vkey)

# ==============================================================================
#  Visualization
# ==============================================================================
# highlight anchor vertices
facecolor = {vkey: (200, 200, 200) for vkey in form.vertices()}
for vkey in form.vertices_where({'is_anchor': True}):
    facecolor[vkey] = (255, 0, 0)

# only show inner edges
# hightlight leaf edges
edgecolor = {}
for vkey in anchors:
    nbrs = form.vertex_neighbors(vkey)
    for nbr in nbrs:
        if nbr in anchors:
            edgecolor[(vkey, nbr)] = (250, 250, 250)
            edgecolor[(nbr, vkey)] = (250, 250, 250)
        else:
            edgecolor[(vkey, nbr)] = (0, 255, 0)
            edgecolor[(nbr, vkey)] = (0, 255, 0)

formartist.clear_layer()
formartist.draw_vertices(color=facecolor)
formartist.draw_edges(color=edgecolor)

Step 3: Create Force Diagram

The Force Diagram is the dual of the Form Diagram, in the sense that both diagrams have the same number of edges and that vertices in one diagram correspond to faces in the other, and vice versa.

# ===============================================================================
# Dual Force Diagram
# ===============================================================================
force = form.dual()
forceartist = MeshArtist(force, layer="CSD2::force")
forceartist.clear_layer()
forceartist.draw()
forceartist.draw_edges(color=(0, 0, 255))

Translate the ForceDiagram for visualization.

bbox_form = form.bounding_box_xy()
bbox_force = force.bounding_box_xy()
xmin_form, xmax_form = bbox_form[0][0], bbox_form[1][0]
xmin_force, _ = bbox_force[0][0], bbox_force[1][0]
ymin_form, ymax_form = bbox_form[0][1], bbox_form[3][1]
ymin_force, ymax_force = bbox_force[0][1], bbox_force[3][1]
y_form = ymin_form + 0.5 * (ymax_form - ymin_form)
y_force = ymin_force + 0.5 * (ymax_force - ymin_force)
dx = 1.3 * (xmax_form - xmin_form) + (xmin_form - xmin_force)
dy = y_form - y_force
force.transform(Translation.from_vector([dx, dy, 0]))

Step 4: solve the horizontal and vertical equilibirum of the structure.

update the force diagram so that the corresponding edges are perpendicular to each other.

TNA offers the force diagram which is not just the visualization of horizontal equilibrium of the shell structure, but also a means through which the designer can explicitly modify the internal forces, thereby enabling a careful and controlled transformation of the geometry of the shell structure.

from compas.rpc import Proxy
proxy = Proxy()
proxy.package = 'compas_tna.equilibrium'

formdata, forcedata = proxy.horizontal_numpy_proxy(form.to_data(), force.to_data(), alpha=100)
form = FormDiagram.from_data(formdata)
force = ForceDiagram.from_data(forcedata)

formdata, scale = proxy.vertical_from_zmax_proxy(form.to_data(), zmax=1000)
form = FormDiagram.from_data(formdata)

Ex2. Modify the ForceDiagram

# ==============================================================================
# Modify Force Diagram
# ==============================================================================
for vkey in force.vertices():
    x = force.vertex_attribute(vkey, 'x')
    if x > 7000:
        force.vertex_attribute(vkey, 'x', x + 2500)

forceartist.clear_layer()
forceartist.draw()
forceartist.draw_edges(color=(0, 0, 255))

====================================================================================

(A more complex pattern? )

Last updated