Clustering 131 Facade Fins by Curvature to Cut Fabrication Molds
A unitized facade with 131 uniquely curved fins means 131 fabrication molds, unless you can prove some of those curves are close enough to share one. Here is the workflow we used to find out.
On a recent facade rationalization job, the design called for around 131 strip and fin elements, each following its own gentle curve across the building's surface. Left as is, that's 131 unique fabrication molds, and every unique mold costs real money and real lead time. The brief was simple to state and hard to do: find which of those 131 curves are close enough to each other that they can share a mold, without visibly changing the design intent.
Why this can't be done by eye
At 10 or 20 elements, you could plausibly eyeball which curves look similar. At 131, that breaks down in both directions. You miss genuine matches because two curves that are numerically close don't always look identical side by side. And you force bad matches because visual similarity is a poor proxy for the actual manufacturing tolerance a mold needs to hold. The problem needed a number to sort by, not an eye to judge by.
Picking a cheap, honest measure of curvature
Comparing full curve geometry pairwise across 131 elements is expensive, and for this class of shallow arcs, overkill. What actually matters for a mold is how much a curve bows away from a straight line between its endpoints. That's exactly what sagitta measures: the height of the arc above its chord. It's a single number per curve, cheap to compute, and directly tied to the real question, which is whether a curve can pass through a mold built for a slightly different curve and still be within tolerance.
Reducing every curve to one scalar value turns a geometry comparison problem into a sorting problem. Sorting problems are just a lot easier to solve well.
A greedy clustering pass
With sagitta values in hand, the clustering itself is a straightforward greedy pass. Sort all 131 curves by their sagitta value, then walk the sorted list start to end. If a curve's sagitta is within the tolerance band of the cluster currently being built, it joins that cluster and the mold gets built to fit the group's spread. If it falls outside tolerance, it starts a new cluster.
sort curves by sagitta ascending
clusters = []
current = new cluster with curves[0]
for curve in curves[1:]:
if abs(curve.sagitta - current.representative_sagitta) <= tolerance:
current.add(curve)
else:
clusters.append(current)
current = new cluster with curve
clusters.append(current)Simple, but the tolerance band is where the real judgment lives. Set it too tight and you barely reduce the mold count. Set it too loose and you're bending the design intent just to make fabrication easier. That number came from running the clustering at a few different tolerances and checking the resulting groups against what was actually acceptable to the design.
Making 40 plus clusters visually distinguishable
Once curves are grouped, the next problem is purely practical. How do you QA dozens of clusters in the Rhino viewport without the colors blurring together? Stepping hue evenly around the color wheel doesn't work well when you don't know the cluster count ahead of time. You either run out of well separated hues or waste most of the wheel on the first few clusters.
The fix was to step each new cluster's hue by the golden angle, about 137.5 degrees, instead of dividing the wheel evenly. It's the same idea behind sunflower seed spirals. Golden angle stepping stays well distributed no matter how many steps you take, so cluster 3 and cluster 40 both end up easy to tell apart from their neighbors, without deciding the total cluster count up front.
What this generalizes to
None of this is specific to fins. The same shape, reduce a fabrication constrained rationalization problem to one honest scalar, sort it, cluster greedily within a tolerance, color it for QA, applies just as well to mullions, transoms, or any other run of unitized curved elements where the real cost driver is the number of distinct molds or dies, not the number of parts.
The hard part was never the clustering algorithm. It was picking a measurement cheap enough to run 131 times and honest enough to trust.