# Planarisation

At any point during the design process, the faces of polyhedral cells or multi-cell polyhedrons may become non-planar. Before any further design explorations can be made, the non-planar faces need to be planarised. Planarisation of non-planar faces can be formulated as an iterative projection method, which is a tried-and-tested methodology in computational geometry (1, 2 and 3).

Figure 1 shows an example application of the planarisation algorithm, implemented using the iterative projection method. At each time step, each face is projected onto either: the plane defined by its initial normal and the current centroid; a plane defined by a target normal; or a best-fit plane computed from its current vertex coordinates. Because faces are projected independently from one another, there will be multiple coordinates for a single vertex at the end of each time step. The average or the barycenter of the coordinates of a vertex is its new location for that time step. The procedure continues until a desired tolerance has been reached.

If there are no constraints enforced, each face projects itself to the plane defined by its current centroid and normal (Figure 1-b). In some 3D graphic statics applications, specified faces may need to stay fixed in their orientations. For example, some of the boundary faces of a multicell polyhedron corresponds to externally applied loads, which typically do not change in their magnitudes or locations during the design process. In addition, it may sometimes be desired to fix the orientations of certain members in the form diagram.

The orientation constraint can be enforced by updating the `fix_normal`

attribute of the specified faces.
Individual vertex constraints can also be set by updating the `x_fix`

, `y_fix`

, `z_fix`

attributes for the specified vertices.
Figure 1-c shows the planarisation, but this time with faces 2, 1 and 5 constrained to be perpendicular to the x, y and z axes, respectively.

## Example

In this example, three random vertices are chosen to remain fixed during the planarisation.

```
from __future__ import absolute_import
from __future__ import print_function
from __future__ import division
import compas
from compas_rhino.helpers import volmesh_from_polysurfaces
from compas_rhino.selectors import VertexSelector
from compas.utilities import i_to_red
from compas_3gs.diagrams import ForceVolMesh
from compas_3gs.algorithms import volmesh_planarise
from compas_3gs.rhino import VolmeshConduit
from compas_3gs.utilities import compare_initial_current
from compas_3gs.utilities import volmesh_face_flatness
from compas_3gs.rhino import bake_cells_as_polysurfaces
try:
import rhinoscriptsyntax as rs
except ImportError:
compas.raise_if_ironpython()
__author__ = 'Juney Lee'
__copyright__ = 'Copyright 2019, BLOCK Research Group - ETH Zurich'
__license__ = 'MIT License'
__email__ = 'juney.lee@arch.ethz.ch'
# ------------------------------------------------------------------------------
# 1. make vomesh from rhino polysurfaces
# ------------------------------------------------------------------------------
layer = 'force_volmesh'
guids = rs.GetObjects("select polysurfaces", filter=rs.filter.polysurface)
rs.HideObjects(guids)
forcediagram = ForceVolMesh()
forcediagram = volmesh_from_polysurfaces(forcediagram,
guids)
forcediagram.layer = layer
forcediagram.attributes['name'] = layer
forcediagram.draw(layer=layer)
# ------------------------------------------------------------------------------
# 2. pick vertices to fix
# ------------------------------------------------------------------------------
vkeys = VertexSelector.select_vertices(forcediagram,
message='Select vertices to fix:')
# ------------------------------------------------------------------------------
# 3. planarise
# ------------------------------------------------------------------------------
forcediagram.clear()
initial_flatness = volmesh_face_flatness(forcediagram)
# conduit
conduit = VolmeshConduit(forcediagram)
def callback(forcediagram, k, args):
if k % 5:
current_flatness = volmesh_face_flatness(forcediagram)
face_colordict = compare_initial_current(current_flatness,
initial_flatness,
color_scheme=i_to_red)
conduit.face_colordict = face_colordict
conduit.redraw()
# planarise
with conduit.enabled():
volmesh_planarise(forcediagram,
kmax=2000,
fix_vkeys=vkeys,
fix_boundary_normals=False,
tolerance_flat=0.01,
callback=callback,
print_result_info=True)
# update / redraw
# forcediagram.draw()
bake_cells_as_polysurfaces(forcediagram)
```

## References

- 1
Liu, Y., H. Pottmann, J. Wallner, Y.-L. Yang, and W. Wang (2006, July). Geometric modeling with conical meshes and developable surfaces.

**ACM Trans. Graph.**25(3), 681–689.- 2
Bouaziz, S., M. Deuss, Y. Schwartzburg, T. Weise, and M. Pauly (2012). Shape-up: Shaping discrete geometry with projections.

**Comput. Graph. Forum**31(5), 1657–1667.- 3
Deuss, M., A. H. Deleuran, S. Bouaziz, B. Deng, D. Piker, and M. Pauly (2015). Shapeop—a robust and extensible geometric modelling paradigm. In R. M. Thomsen, M. Tamke, C. Gengnagel, B. Faircloth, and F. Scheurer (Eds.),

**Modelling Behaviour: Design Modelling Symposium 2015**, pp. 505–515. Cham: Springer International Publishing.