Form-finding 1
Vaults, minimal surfaces and mesh relaxation
Last updated
Vaults, minimal surfaces and mesh relaxation
Last updated
In this session we introduce the concept of “form-finding” []; a process of deriving geometry via experiments involving materials and physics. Classic examples include experiments for composite vault designs [] using rope and weight physical models []; dome designs [] derived from soap bubble experiments []; and tensile canopy structures [] produced by stretching membranes and thin films [].
The appeal of those design forms is in that they integrate certain mechanical material properties and also because they cannot be designed with conventional constructive geometry methods using pen and paper or CAD. Today we use physics simulation to perform form-finding as it is easier to setup and execute, compared with quite labor intensive preparation of physical experimental prototypes.
In previous examples we kept relationships ie. the way forces associate with particles, implicit: In the projectile case we established none, in the multibody case we defined all possible combinations, and in the chain case we implied that adjacent particles in a list are connected in a rope-like sense. Controlling connectivity between particles explicitly requires describing relationships in a more well-structured manner. How should this structure look like and what kind of data shall we store?
The common pattern among operations performed during the application of forces to particles was some form of “smart” indexing for selecting the positions of particle pairs, defining force vectors, applying physics laws and accumulating force sums. This indexing logic is what we need to express with data. For every particle we shall retain a list of all other connected particles. This structure is also known as an edge table.
In the figure above, the particle at index “0” is connected with particles “1”, “3” and “4”; particle “2” is connected with “1” and “5”; particle “4” is pretty much connected to every other particle except “6” and “2”. The entire edge table is encoded below such that for every particle [0, 8] we have captured all of its connected neighbours.
The topology cluster constructs the edge table by examining the mesh’s face indices. We employ a python component, because it is faster and less verbose, but it is also possible to use simple “expression” components or even basic comparisons instead.
The key insight for associating how vertices, edges and faces are related to one another is observing that given a mesh’s face “[A, B, C]”, where “A”, “B” and “C” are the three vertex indices of a triangle, we can tell that vertex “A” is forward linked to “B” via an edge and backward to “C” via another edge. Thus all we need to do is to accumulate linkage information for every vertex. It is easier to explain the mechanics of this process if we work out an example with specific values instead of symbols.
The first operation performed by the topology construction cluster is to decompose a mesh into its vertex and face lists; nine vertices and eight faces seen below. We may express the edges of each triangle as pairs of indices of the face list. For example the triangle “[0, 1, 4]”, contains the three edges “[0, 1]”, “[1, 4]” and looping back to the first we have also “[4, 0]”.
Next we push the face list data to the python component as well as a regular series with as many items as the number of vertices i.e. in this example nine in “[0, 8]”. The python expression for triangles, in ternary “if” form, can be written as seen below.
The cascading “if” construct detects whether a vertex at index “I”, in the mesh vertex list, matches either face index “A”, “B”, or “C”. Specifically for “U”, if it matches “A” it returns “B”; if it matches “B” it returns “C”; if it matches “C” it returns “A”; otherwise it signals failure to match using “-1”. The “V” value performs the same query but in the opposite direction i.e. instead of “A→B→C” it matches “A←B←C”.
In plain English this query translates to: is a given vertex present in any edge of a given triangle face? If so, report with which other vertex it is connected, otherwise mark it as not connected.
The expected result given that we use “graft” ie. the Cartesian product between the mesh vertices and faces, is two of tables of nine rows by eight columns, respectively. The presence of “-1” values makes it difficult to discern the contents of the tables.
We need to perform some data reshaping and clean up. First we will merge the two tables into one, as seen below. We need to transpose and merge to keep the same sense of rows and columns.
Finally we perform a “set difference” between the above table and a set containing only one element, namely “-1”. This is to get rid of the pesky “not found” value. We thus end up with exactly what we were looking for: a table that for each vertex, in the mesh’s vertex list, it tells us which are other vertices are connected to it in the sense of edge linkages. You may verify the result by comparing with figure below.
Developing the edge table using only visual programming components was a bit of a challenge. It is much simpler, more intuitive and faster to write the whole process with few lines of python code. Nevertheless, this proves that all forms of computation are sort of equivalent with various degrees of mental gymnastics required by each.
The actual python for edge table extraction in the graph provided in at the end of the section uses the regular form of “if” statements instead of cascading “if” expressions. This is for legibility given that it aims to works for both triangular, quadrilateral and mixed-faced meshes.
Then we use the “create set” component which removes duplicate entries from a list. A set is like a list but a value can appear in this type of container only once. As a side note, we also do not care about the order of a set’s elements []. This results to the following jagged table. As you may be able to see now we are almost there.