# Bending active Structure

**URL:** <https://discourse.mcneel.com/t/bending-active-structure/189450>\
**Category:** Kangaroo\
**Tags:** windows\
**Created:** [August 13, 2024, 11:35am UTC](https://discourse.mcneel.com/t/bending-active-structure/189450 "2024-08-13T11:35:31Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![VRUN](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/vrun/32/560391_2.png) [@VRUN](https://discourse.mcneel.com/u/VRUN)\
**Post date:** [August 13, 2024, 11:35am UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/1 "2024-08-13T11:35:31Z")

</div>

hello,  
I have made physical model of one prototype with 2 canes with concept of bending active system. Now I am trying to convert it into digital medium. I have gone through the videos of related to this. But I am not able to get the desired solution with kangaroo solver.

help me to figure it out.  
Thank you for your valuable time and consideration.

 ![WhatsApp Image 2024-08-13 at 5.00.15 PM (1)](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/5/4/b/54ba2113e0ce54f72adb21fa3a315873b8bc91a3.jpeg)  
 ![WhatsApp Image 2024-08-13 at 5.00.15 PM](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/2/9/c/29c0b459d7dec738c90419a77769d93b140c427e.jpeg)

---

<div class="post-metadata">

**Author:** ![Pete\_Wenger](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/pete_wenger/32/754444_2.png) [@Pete\_Wenger](https://discourse.mcneel.com/u/Pete_Wenger)\
**Post date:** [September 6, 2024, 6:18pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/2 "2024-09-06T18:18:11Z")

</div>

I’m not an expert in Kangaroo, far from it, but I see something in your model that I also need help with and think is a problem — the tie points. These are what I would call reciprocal constraints on the bending. That is, the tie points influence how and in what direction bending can occur, but the bending also changes the constraint’s location in absolute space. I think this introduces a degree of recursion that, if it is possible, is very very tricky.

My project, for example, is also based on a physical maquette. It uses multiple creases and cuts in a sheet material. As the creases are amplified, they bend the material and are therefore also moved by the material in absolute space. Also, after the creases are made, you can move them around in a way that is constrained by the material and this has a significant impact on the bending caused. The whole system is an interdependent loop. Even faking some of these constraints, I so far have failed to achieve a complete simulation.

---

<div class="post-metadata">

**Author:** ![AndersDeleuran](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/andersdeleuran/32/476683_2.png) [@AndersDeleuran](https://discourse.mcneel.com/u/AndersDeleuran)\
**Post date:** [September 6, 2024, 6:33pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/3 "2024-09-06T18:33:37Z")

</div>

These old project videos might inspire some ideas, or at least demonstrate how to model the input polylines:

> **[The Tower - Bending Active Tensile Membrane - Form Finding 02](https://www.grasshopper3d.com/video/the-tower-bending-active-tensile-membrane-form-finding-02)**
>
> Form finding modelling for a bending active (glass fibre rods) tensile membrane (bespoke knit) tower structure. Developed by Anders Holden Deleuran (CITA) in R…

> **[The Tower: Modelling Pipeline Quick Demo](https://www.grasshopper3d.com/video/the-tower-modelling-pipeline-quick-demo)**

> **[Interactive Modelling of a Form-Active Structure](https://www.grasshopper3d.com/video/interactive-modelling-of-a-form-active-structure)**
>
> First proof of concept Grasshopper definition for interactive modelling (changing the topology and properties) of a form-active structural assembly (of bending…

> **[Calibrated Modelling of Form-Active Hybrid Structures - Smart Geometry 2016 -...](https://www.grasshopper3d.com/video/calibrated-modelling-of-form-active-hybrid-structures-smart)**
>
> Was a fun week :)
> 
> Updated Vimeo description:
> 
> Developed by Anders Holden Deleuran (CITA) in Rhino/Grasshopper (McNeel/David Rutten) using Kangaroo2 (Daniel Pi…

I can link to some papers we wrote when I’m on my laptop again. Some fond bendy memories 🙃

---

<div class="post-metadata">

**Author:** ![Felix\_Berger](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/felix_berger/32/738691_2.png) [@Felix\_Berger](https://discourse.mcneel.com/u/Felix_Berger)\
**Post date:** [December 10, 2025, 10:25pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/5 "2025-12-10T22:25:20Z")

</div>

I’ve come along my way but I didn’t figured out yet how the linear constraint stops the rod from converging into a circle in your first little box example. I’ve been using constantTension and Length for that with trying out to use the intersection points as anchors..

---

<div class="post-metadata">

**Author:** ![AndersDeleuran](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/andersdeleuran/32/476683_2.png) [@AndersDeleuran](https://discourse.mcneel.com/u/AndersDeleuran)\
**Post date:** [December 11, 2025, 7:41am UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/6 "2025-12-11T07:41:17Z")

</div>

I posted some of the source code back here, might help:

> [@Using kangaroo2 or Galapagos in GhPython](https://discourse.mcneel.com/t/using-kangaroo2-or-galapagos-in-ghpython/129932/19):
>
> No worries. I don’t think there is much documentation outside of the C# source code itself, which is pretty accessible through GHPython intellisense and the print() , type() , help() , dir() functions. Also, I just uploaded [some additional examples](https://github.com/AndersDeleuran/KangarooGHPython/tree/master/src) from our Smart Geometry 2016 and Advances in Architectural Geometry 2016 workshops. These were updated to work natively in Rhino 7 for a workshop at CITA in 2020 and are exported from this larger GHPython pipeline:

> [@Felix\_Berger](#):
>
> … how the linear constraint stops the rod from converging into a circle in your first little box example …

Maybe you can add a screenshot? It’s been a loooong time 👴

**Edit:** Here’s a super stripped down version of the Smart Geometry 2016 pipeline (i.e. just the shaping):

 ![2025-12-11 08_53_20-Greenshot](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/1/5/5/1555053a44bf6a4ce4a5646c028c0a2e6e16acb5.png)  
[201210\_FAHS\_InteractiveModellingPipeline\_Minimal\_00.gh](https://discourse.mcneel.com/uploads/short-url/3j1VrEa61iltMF0MmiFftcEpGBz.gh) (45.7 KB)

The code here was updated in 2020 to run in Rhino 6/7. But haven’t tested with 8. Also it’s ten year old code so there are surely many things I’d do differently today. Notably regarding [drawing and dynamic/event-based stuff](https://discourse.mcneel.com/t/ghpython-content-from-aectech-barcelona-workshop/180533).

**Edit II:** Just tried running the definition in Rhino 8 and I’m getting a goal casting error. It does ring a bell, but afraid I can’t recall how to solve it. Thought it might be that I’m referencing the wrong Kangaroo2 assembly, but that doesn’t seem to be it. @DanielPiker might know why it broke?

 ![2025-12-11 09_05_12-Greenshot](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/b/c/2/bc2f02a8e17a581e3bdf0ea3904e015a9fad86a1.png)

---

<div class="post-metadata">

**Author:** ![AndersDeleuran](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/andersdeleuran/32/476683_2.png) [@AndersDeleuran](https://discourse.mcneel.com/u/AndersDeleuran)\
**Post date:** [December 11, 2025, 8:24am UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/7 "2025-12-11T08:24:35Z")

</div>

And here are the primary publications on the projects above. That present quite explicitly how Kangaroo2 and K2 Engineering was implemented:

[Deleuran et al\_2015\_The Tower Modelling , Analysis and Construction of Bending Active Tensile Membrane Hybrid Structures.pdf](https://discourse.mcneel.com/uploads/short-url/2qZucdTFbqks9Af9sLThNnLkNpd.pdf) (2.1 MB)  
[Deleuran et al\_2016\_Exploratory Topology Modelling of Form-Active Hybrid Structures.pdf](https://discourse.mcneel.com/uploads/short-url/jM5UBYxkG7Y3XxSV4MSZO7KgTvR.pdf) (1.8 MB)  
[Quinn et al\_2016\_Calibrated and Interactive Modelling of Form-Active Hybrid Structures.pdf](https://discourse.mcneel.com/uploads/short-url/15dJJEOTIQoFVYB75rqC47HfIAD.pdf) (3.0 MB)  
[Tamke et al.\_2017\_Lace Wall - Extending design intuition through Machine Learning.pdf](https://discourse.mcneel.com/uploads/short-url/dVKBJlK5I8ReIBzCjLoRUDt86aZ.pdf) (960.2 KB)

---

<div class="post-metadata">

**Author:** ![AndersDeleuran](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/andersdeleuran/32/476683_2.png) [@AndersDeleuran](https://discourse.mcneel.com/u/AndersDeleuran)\
**Post date:** [December 11, 2025, 10:32am UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/8 "2025-12-11T10:32:02Z")

</div>

> [@AndersDeleuran](#):
>
> … Thought it might be that I’m referencing the wrong Kangaroo2 assembly, but that doesn’t seem to be it. @DanielPiker might know why it broke?

Just tried using this non-explicit method to reference the `KangarooSolver` dll instead. I’m not really which assembly is being loaded now, but it appears to solve the IGoal error:

 ![2025-12-11 11_27_29-Greenshot](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/3/6/a/36ae0a90564f7017323017a6e9bdfc267a41ec02.png)  
[201210\_FAHS\_InteractiveModellingPipeline\_Minimal\_Rhino8\_00.gh](https://discourse.mcneel.com/uploads/short-url/rMvqUsrqArBuWbQ2Xit5vwekfHX.gh) (47.5 KB)

Also, none of the downstream drawing works in Rhino 8. Likely because the custom display class is deprecated and there’s been a lot of updates to the drawing pipeline in general.

---

<div class="post-metadata">

**Author:** ![Felix\_Berger](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/felix_berger/32/738691_2.png) [@Felix\_Berger](https://discourse.mcneel.com/u/Felix_Berger)\
**Post date:** [December 11, 2025, 10:39am UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/9 "2025-12-11T10:39:58Z")

</div>

Oh man, thank you for putting in that time! I was already browsing up and down why I dont have nor find nor be able to reference my .dll although using Rhino7.. Maybe it’s because of the new macOS versions but this file works!! Natively

---

<div class="post-metadata">

**Author:** ![AndersDeleuran](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/andersdeleuran/32/476683_2.png) [@AndersDeleuran](https://discourse.mcneel.com/u/AndersDeleuran)\
**Post date:** [December 11, 2025, 10:57am UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/10 "2025-12-11T10:57:27Z")

</div>

Yeah I’m not really sure what’s going on (ping @DanielPiker). From what I can tell the `clr.AddReferenceByName("KangarooSolver")` method gets the exact same assembly as using the by file and path reference method. Could be some .NET/core stuff that broke things maybe:

 ![2025-12-11 11_53_06-Grasshopper - K2VersionsRhino8_](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/3/7/1/371bc581b56567ef0ac05d913cfd1fc790fe6a3a.png)  
[K2VersionsRhino8.gh](https://discourse.mcneel.com/uploads/short-url/311NmRr8JJ939QiMZ1IOWA0bZL3.gh) (5.1 KB)

But hey, if it works 🤷‍♂️

---

<div class="post-metadata">

**Author:** ![Felix\_Berger](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/felix_berger/32/738691_2.png) [@Felix\_Berger](https://discourse.mcneel.com/u/Felix_Berger)\
**Post date:** [December 11, 2025, 2:20pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/11 "2025-12-11T14:20:42Z")

</div>

Yea it does haha. A very last question towards this topic: In the last script, the bending analysis, it is missing your very own module adh to visualize the bending stress, any chance to obtain that? 🫣

Appreciate your very much insightful help already!

---

<div class="post-metadata">

**Author:** ![AndersDeleuran](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/andersdeleuran/32/476683_2.png) [@AndersDeleuran](https://discourse.mcneel.com/u/AndersDeleuran)\
**Post date:** [December 11, 2025, 3:11pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/12 "2025-12-11T15:11:41Z")

</div>

> [@Felix\_Berger](#):
>
> … it is missing your very own module adh to visualize the bending stress, any chance to obtain that?

Ah yeah, sorry. Here’s the version from the latest workshop:

```python
"""
Utility functions for writing GHPython scripts
Author: Anders Holden Deleuran
Version: 200811
"""

import time
import math
from scriptcontext import sticky as st
import Rhino as rc
import Grasshopper as gh
import GhPython
import datetime
import rhinoscriptsyntax as rs
from System.Drawing import Color
import scriptcontext as sc

class Timer(object):
    
    """ A simple profiler """
    
    def start(self):

        # Start the timer
        self.startTime = time.time()
        
    def stop(self):
        
        # Print an return elapsed time
        elapsedSeconds = time.time() - self.startTime
        elapsedMilliseconds = elapsedSeconds*1000
        print str(round(elapsedMilliseconds,3)) + " ms"
        return elapsedMilliseconds

def listToTree(nestedList):
    
    """ Convert a nested python iterable to a datatree """
    
    dt = gh.DataTree[object]()
    for i,l in enumerate(nestedList):
        dt.AddRange(l,gh.Kernel.Data.GH_Path(i))
        
    return dt

def customDisplay(toggle,component):
    
    """ Make a custom display which is unique to the component and lives in sticky """
    
    # Make unique name and custom display
    displayGuid = "customDisplay_" + str(component.InstanceGuid)
    if displayGuid not in st:
        st[displayGuid] = rc.Display.CustomDisplay(True)
        
    # Clear display each time component runs
    st[displayGuid].Clear()
    
    # Return the display or get rid of it
    if toggle:
        return st[displayGuid]
    else:
        st[displayGuid].Dispose()
        del st[displayGuid]
        return None

def killCustomDisplays():
    
    """ Clear any custom displays living in the Python sticky dictionary """
    
    for k,v in st.items():
        if type(v) is rc.Display.CustomDisplay:
            v.Dispose()
            del st[k]

def remapValues(values,targetMin,targetMax,srcMin,srcMax):
    
    """ Remaps a list of values to the new domain targetMin-targetMax """
    
    #srcMin = min(values)
    #srcMax = max(values)
    
    if srcMax-srcMin > 0:
        remappedValues = []
        for v in values:
            rv = ((v-srcMin)/(srcMax-srcMin))*(targetMax-targetMin)+targetMin
            remappedValues.append(rv)
    else:
        meanVal = (targetMin+targetMax)/2
        remappedValues = [meanVal for i in range(len(values))]
        
    return remappedValues

def valuesToColors(values):
    
    """ Make a list of HSL colors, meaning that 0.0: red and 0.6: blue """
    
    colors = []
    for v in values:
        rcColor = rc.Display.ColorHSL(v,1.0,0.5)
        colors.append(rcColor)
        
    return colors

def sampleColorSpectrum(colors,t,smooth):
    
    """ Interpolate along multiple colors by 0.00-1.00 parameter t """
    
    if t <= 0.0:
        return colors[0]
    elif t >= 1.0:
        return colors[-1]
    else:
        
        # Compute spectrum t, starting color, and local t
        tSpectrum = t * (len(colors)-1)
        colorID = int(math.floor(tSpectrum))
        tLocal = tSpectrum-colorID
        
        # Use cosine interpolation (see paulbourke.net/miscellaneous/interpolation)
        if smooth:
            tLocal = (1-math.cos(tLocal*math.pi))/2
            
        # Blend colors
        cA = rc.Display.Color4f(colors[colorID])
        cB = rc.Display.Color4f(colors[colorID+1])
        cC = cA.BlendTo(tLocal,cB)
        blendColor = cC.AsSystemColor()
        
        return blendColor

def colorMeshFaces_V5(mesh,colors):
    
    """ Unwelds and color the faces of a mesh """
    
    # Get faces/vertices
    faces = mesh.Faces
    vertices = mesh.Vertices
    
    # Make empty mesh and face-vertex ID counter 
    cMesh = rc.Geometry.Mesh()
    fID = 0
    for i in range(faces.Count):
        
        # Get face and color
        f = faces[i]
        c = colors[i]
        
        # Add face vertices and colors to empty cMesh
        cMesh.Vertices.Add(vertices[f.A])
        cMesh.Vertices.Add(vertices[f.B])
        cMesh.Vertices.Add(vertices[f.C])
        cMesh.VertexColors.Add(c)
        cMesh.VertexColors.Add(c)
        cMesh.VertexColors.Add(c)
        if f.IsQuad:
            cMesh.Vertices.Add(vertices[f.D])
            cMesh.VertexColors.Add(c)
            
       # Add face
        if f.IsQuad:
            cMesh.Faces.AddFace(fID,fID+1,fID+2,fID+3)
            fID += 4
        elif f.IsTriangle:
            cMesh.Faces.AddFace(fID,fID+1,fID+2)
            fID += 3
            
    return cMesh

def colorMeshFaces_V6(mesh,colors):
    
    """ Unwelds and color the faces of the mesh in place """
    
    mesh.VertexColors.CreateMonotoneMesh(System.Drawing.Color.Black)
    mesh.Unweld(0,False)
    for i in range(mesh.Faces.Count):
        mesh.VertexColors.SetColor(mesh.Faces[i],colors[i])

def makeLegendParams(capLower,capUpper,hueLower,hueUpper,count):
    
    """ Make a list of data following the Ladybug format,
    used for generating a CustomVectorLegend """
    
    hues = floatRange(hueLower,hueUpper,count-1)
    colors = valuesToColors(hues)
    lp = [capLower,capUpper,None,colors]
    return lp

def updateComponent(ghenv,interval):
    
    """ Updates this component, similar to using a grasshopper timer """
    
    # Define callback action
    def callBack(e):
        ghenv.Component.ExpireSolution(False)
        
    # Get grasshopper document
    ghDoc = ghenv.Component.OnPingDocument()
    
    # Schedule this component to expire
    ghDoc.ScheduleSolution(interval,gh.Kernel.GH_Document.GH_ScheduleDelegate(callBack))

def buildDocString_LEGACY(ghenv):
    
    """ Builds a documentation string by iterating the component
    (i.e. ghenv.Component) input and outputs parameters """
    
    # Add component description string
    ds = '"""\n'
    ds += "Write main component documentation here.\n"
    
    # Add input parameter type properties
    ds += " Inputs:\n"
    for v in ghenv.Component.Params.Input:
        dataType = str(v.TypeHint.TypeName).lower()
        vd = list(v.VolatileData.AllData(False))
        if vd and dataType == "system.object":
            vdType = str(vd[0].GetType())
            vdType = vdType.split(".")[-1]
            dataType = vdType.strip("GH_").lower()
        ds += " " + v.Name + ": {" + str(v.Access).lower() + "," + dataType + "}\n"
        
    # Add output parameter type properties
    ds += " Outputs:\n"
    for v in ghenv.Component.Params.Output:
        ds += " " + v.Name + ": \n"
        # print globals()[v.Name]
        
    # Add author, Rhino, and script version
    ds += " Remarks:\n"
    ds += " Author: Anders Holden Deleuran (BIG IDEAS)\n"
    ds += " Rhino: " + str(rc.RhinoApp.Version) + "\n"
    ds += " Version: " + str(date.today()).replace("-","")[2:] + "\n"
    ds += '"""'
    
    print ds
    return ds

def getParameterProperties(p,globalsDict):
    
    """ Extract a component parameter name, access, and data type """

    # Get name, data and set initial type
    pName = p.Name
    pData = globalsDict[pName]
    pDataType = None

    # Determine access and data type
    if type(pData) is list:
        pAccess = "list"
        if pData:
            pDataType = type(pData[0])
    elif type(pData) is gh.DataTree[object]:
        pAccess = "tree"
        if pData: 
            pDataType = type(pData.AllData()[0])
    else:
        pAccess = "item"
        if pData is not None:
            pDataType = type(pData)
        
    # Format data type string
    if pDataType:
        pDataType = pDataType. __name__.lower()
    else:
        pDataType = "?"
    
    return pName,pAccess,pDataType

def buildDocString(globalsDict):
    
    """ Builds a documentation string by iterating the ghenv.Component input
    and outputs parameters. Call with globals() as input at very end of script """

    # Get ghenv
    ghenv = globalsDict["ghenv"]
    
    # Add component description string
    ds = '"""\n'
    ds += "Write main component documentation here.\n"
    
    # Add input parameter type properties
    ds += " Inputs:\n"
    for p in ghenv.Component.Params.Input:
        pName,pAccess,pDataType = getParameterProperties(p,globalsDict)
        ds += " " + pName + ": {" + pAccess + "," + pDataType + "}\n"
        
    # Add output parameter type properties
    ds += " Outputs:\n"
    for p in ghenv.Component.Params.Output:
        pName,pAccess,pDataType = getParameterProperties(p,globalsDict)
        ds += " " + pName + ": {" + pAccess + "," + pDataType + "}\n"
        
    # Add author, Rhino, and script version
    ds += " Remarks:\n"
    ds += " Author: Anders Holden Deleuran (BIG IDEAS)\n"
    ds += " Rhino: " + str(rc.RhinoApp.Version) + "\n"
    ds += " Version: " + str(datetime.date.today()).replace("-","")[2:] + "\n"
    ds += '"""'
    
    print ds
    return ds

def setParametersToDrawName(ghenv):
    
    """ Set all canvas parameters to always draw name """
    
    for obj in ghenv.Component.OnPingDocument().Objects:
        if obj.GetType().Namespace == "Grasshopper.Kernel.Parameters":
            obj.IconDisplayMode = gh.Kernel.GH_IconDisplayMode.name
            obj.ExpireSolution(True)

def setNoTypeHint(ghenv):
    
    """ Set all input parameters to No Type Hint, DO NOT USE YET!!"""
    
    for v in ghenv.Component.Params.Input:
        v.TypeHint = GhPython.Component.NoChangeHint()
    ghenv.Component.ExpireSolution(False)

def setTemplateLayerColors():

    """ Set Rhino layer colors to the AHD style """

    # Set context to Rhino document and disable redraw
    sc.doc = rc.RhinoDoc.ActiveDoc
    rs.EnableRedraw(False)

    # Set layer colors
    for i,l in enumerate(rs.LayerNames()):
        if i == 0:
            rs.LayerColor (l,Color.FromArgb(255,105,105,105))   
        elif i == 1:
            rs.LayerColor (l,Color.FromArgb(255,255,0,90))    
        elif i == 2:
            rs.LayerColor (l,Color.FromArgb(255,70,190,190))   
        elif i == 3:
            rs.LayerColor (l,Color.FromArgb(255,0,85,255))
        elif i == 4:
            rs.LayerColor (l,Color.FromArgb(255,130,255,0))
        elif i == 5:
            rs.LayerColor (l,Color.FromArgb(255,190,190,190))

def capValues(values,lower,upper):
    
    """ Cap values that are smaller than lower and larger than upper """
    
    capped = []
    for v in values:
        if v < lower:
            capped.append(lower)
        elif v > upper:
            capped.append(upper)
        else:
            capped.append(v)
            
    return capped

def floatRange(start,stop,steps):
    
    """ Generate a range of floats, similar to Grasshoppers Range """
    
    stepSize = (stop-start)/steps
    values = [start]
    for i in range(1,steps):
        values.append(i*stepSize+start)
    values.append(stop)
    
    return values

def closestValue(v,values):
    
    """ Find the value that is closest to v in values """
    
    i = bisect.bisect_left(values,v)
    if i == len(values):
        return i-1
    elif values[i] == v:
        return i
    elif i > 0:
        j = i-1
        if values[i] - v > v - values[j]:
            return j
    return i

def discretiseValues(values,steps):
    
    """ Bin/bucket/discretise a list of values into N steps """
    
    # Calculate the bin values
    bins = floatRange(min(values),max(values),int(Steps))
    bins.sort()
    
    # Find the closest bin for each value
    closestBins = [closestValue(v,bins) for v in values]
    
    return closestBins

def meshGrid(points,ptsU,ptsV):
    
    """ Make a quad mesh from a grid of points """ 
    
    if len(points) == ptsU*ptsV:
        
        # Make mesh and add vertices
        mesh = rc.Geometry.Mesh()
        mesh.Vertices.AddVertices(rc.Collections.Point3dList(points))
        
        # Add faces
        for i in range(ptsU-1):
            for j in range(0,ptsU*(ptsV-1),ptsU):
                ij = i+j
                mesh.Faces.AddFace(ij, ij+ptsU, ij+ptsU+1, ij+1)
                
        # Compute normals and return
        mesh.Normals.ComputeNormals()
        
        return mesh

def ghSolutionRecompute(ghenv):
    
    """ Recomputes the Grasshopper solution (ala pressing F5) """
    
    def expireAllComponentsButThis(e):
        for obj in ghenv.Component.OnPingDocument().Objects:
            if not obj.InstanceGuid == ghenv.Component.InstanceGuid:
                obj.ExpireSolution(False)
                
    ghenv.Component.OnPingDocument().ScheduleSolution(1000,expireAllComponentsButThis)

```

Also, figured out why nothing was drawn (updated casting behaviour) and added quickie hot fix:

 ![2025-12-11 16_06_30-Greenshot](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/7/8/9/78914787106880bc2a596c09e1282a3fae528ca3.jpeg)  
[201210\_FAHS\_InteractiveModellingPipeline\_Minimal\_Rhino8\_01.gh](https://discourse.mcneel.com/uploads/short-url/wSIcsHNsV8eLCvBCOihsJC1Z5Yf.gh) (43.1 KB)

That said, I would recommend ditching the custom display class in favour of [using DrawViewportWires in SDK mode](https://discourse.mcneel.com/t/ghpython-content-from-aectech-barcelona-workshop/180533) (much less janky and way more drawing methods).

---

<div class="post-metadata">

**Author:** ![Felix\_Berger](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/felix_berger/32/738691_2.png) [@Felix\_Berger](https://discourse.mcneel.com/u/Felix_Berger)\
**Post date:** [December 11, 2025, 6:43pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/13 "2025-12-11T18:43:17Z")

</div>

I guess to implement the ahd I have to safe it as a .py file, and then reference through `EditPythongScripts` `Search Paths` right? While you nonchalantly fixed old codes light-handed it helped me finally soft launch into understanding the links in cross-platforming in ghcoding a little haha

---

<div class="post-metadata">

**Author:** ![AndersDeleuran](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/andersdeleuran/32/476683_2.png) [@AndersDeleuran](https://discourse.mcneel.com/u/AndersDeleuran)\
**Post date:** [December 12, 2025, 8:52am UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/14 "2025-12-12T08:52:49Z")

</div>

> [@Felix\_Berger](#):
>
> I guess to implement the ahd I have to safe it as a .py file, and then reference through `EditPythongScripts` `Search Paths` right?

I’m not entirely sure how it works on Mac, but yes. Any folder that is in the `sys.path` should work. I usually use the default Rhino scripts folder:

 ![2025-12-12 09_49_49-Grasshopper Python Script Editor](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/d/e/7/de73608eec44317a2648f14317df04ba232a39fd.png)

You can also use `sys.path.append` to dynamically reference stuff within the code.

---

<div class="post-metadata">

**Author:** ![Felix\_Berger](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/felix_berger/32/738691_2.png) [@Felix\_Berger](https://discourse.mcneel.com/u/Felix_Berger)\
**Post date:** [December 12, 2025, 8:12pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/15 "2025-12-12T20:12:14Z")

</div>

Ah okay good to know. I freestyled and did exactly what I thought would work from last comment and it worked, so.. 😃

Thank you very much for your time and insights, they were very helpful and I appreciate your sharing of knowledge.

---

<div class="post-metadata">

**Author:** ![Felix\_Berger](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/felix_berger/32/738691_2.png) [@Felix\_Berger](https://discourse.mcneel.com/u/Felix_Berger)\
**Post date:** [December 20, 2025, 10:52pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/16 "2025-12-20T22:52:05Z")

</div>

Hey there, I sadly did ran into another problem.. When I replace the internalized geometry of two cables and one polyline with my own one (In this case a more or less exact replica of your geometry) the solver spits out this polygon shape. And I cannot figure out exactly why. Does it have to do with my cables being line-like curves instead if linear curves? And otherwise it doesnt even show the `DivideCurve`points created. (Left side of rhino viewport is your geo, right one is mine. Also used entwine to fully replicate your given way)

If you were to spare a minute of your time and maybe help me figure out whats the problem with using own geometries I would really appreciate that, as im currently being stuck with this for my thesis.

Thanks in advance and otherwise a lovely Christmas time!

 ![Screenshot 2025-12-20 at 23.45.50](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/5/a/6/5a60059c3ab562fa3f8f88ff0e65badca3ab9d8d.jpeg)

---

<div class="post-metadata">

**Author:** ![AndersDeleuran](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/andersdeleuran/32/476683_2.png) [@AndersDeleuran](https://discourse.mcneel.com/u/AndersDeleuran)\
**Post date:** [December 22, 2025, 10:55am UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/17 "2025-12-22T10:55:31Z")

</div>

Think I accidentally marked the last reply as spam yesterday, my bad!

> [@Felix\_Berger](#):
>
> … the solver spits out this polygon shape. And I cannot figure out exactly why. Does it have to do with my cables being line-like curves instead if linear curves? And otherwise it doesnt even show the `DivideCurve`points created.

The beam polylines must be subdivided, see e.g. this section from [one of the papers](https://discourse.mcneel.com/uploads/short-url/15dJJEOTIQoFVYB75rqC47HfIAD.pdf) above:

 ![2025-12-22 11_39_27-Microsoft Word - 2016_06_13 Calibrated and Interactive Modelling of FAHS.docx -](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/1/1/a/11a5b92bbebfaba646794f064fd8526dde30a9e0.png)

Here’s a version of the pipeline that includes the discretisation (which was also since updated to automatically find and insert polyline vertices where the cables attach) and dimensioning stages. A Windows update just tanked my Rhino 8 install, so these bits are only known to work in Rhino 7:

 ![2025-12-22 11_51_13-Greenshot](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/e/6/7/e6758fcc14872f9d89defc45d2b9d203fa942bcb.png)

[201210\_FAHS\_InteractiveModellingPipeline\_Minimal\_01.gh](https://discourse.mcneel.com/uploads/short-url/1jHVnK0CW8xEj4hGzUxsYfB1hc8.gh) (52.2 KB)

> [@Felix\_Berger](#):
>
> … as im currently being stuck with this for my thesis.

Be sure to post it if you’re allowed (or by PM maybe). Would be interesting to see how people are designing bendy things these days 🙂

---

<div class="post-metadata">

**Author:** ![Felix\_Berger](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/felix_berger/32/738691_2.png) [@Felix\_Berger](https://discourse.mcneel.com/u/Felix_Berger)\
**Post date:** [December 23, 2025, 1:29pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/18 "2025-12-23T13:29:14Z")

</div>

Oh nice thank you again haha. And for sure I can share my outcome at the end 🙂

Im doing my thesis about fog harvesting methods and how to imply that more into architecture. And my prof wants something ‘fancy’ for a prototype in 1:1, and by this extra parameter I cant just generate wild shapes, as they have to have a certain amount of vertical surface and some commons gutter points where the water droplets run to etc. Thats where im still tryna work out a good combo between water collection and good fitness values giving interesting shapes. I also got a simple EA running for that and rn as I’m thinking about it, combining that outputs with this pipeline could make an interesting case 😃

---

<div class="post-metadata">

**Author:** ![Felix\_Berger](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/felix_berger/32/738691_2.png) [@Felix\_Berger](https://discourse.mcneel.com/u/Felix_Berger)\
**Post date:** [December 23, 2025, 3:36pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/19 "2025-12-23T15:36:48Z")

</div>

Wondering, I thought about if it were possible to somehow ‘reverse engineer’ this generated curve. The curvature is great regarding my fitness criteria and I placed a combined anchor point in the middle of the shape and then use cables to hold it exactly in place. But when now putting this through the Bending-active pipeline it bends the shape even more (logically)

So im wondering if unrolling that curve with having the exact length goals for each of these cables so that the curve will relax and bend into the shape back could work 🤔

 ![Screenshot 2025-12-23 at 16.28.40](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/b/c/e/bce3672975c9f785b1334f4f59325bbbd8cea518.png)

 ![Screenshot 2025-12-23 at 16.32.01](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/2/7/1/2714ae543b57a4bafc985ee9a195cfd4a60a8b2c.png)

Have to say worked my way through the script and occasional errors but made it work at the end! So reverse engineering sounds like my best way to go for that

---

<div class="post-metadata">

**Author:** ![Felix\_Berger](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/felix_berger/32/738691_2.png) [@Felix\_Berger](https://discourse.mcneel.com/u/Felix_Berger)\
**Post date:** [December 23, 2025, 5:38pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/20 "2025-12-23T17:38:21Z")

</div>

If you’re interested in the progress of me trying to reverse engineer that. After changing from a base circular curve to a curve thats similar shaped to my curve, and using the difference of 2D length from cable point to anchor to 3D length from cable point to anchor as the Cable `TargetLengths`, I near myself to a 70% similar replication. Just have to adjust the cable strengths I guess but hey it seems to work somehow. But I think in order for this to really work some use of stiffening would be needed to get the sharp edges e.g.

Or I will use steel stripes for the real model, would probably help in that case

Edit: Picture

 ![Screenshot 2025-12-23 at 19.04.05](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/9/3/e/93ea0ad703d2a14aa1e6691e5636b4a543f9e618.png)

---

<div class="post-metadata">

**Author:** ![AndersDeleuran](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/andersdeleuran/32/476683_2.png) [@AndersDeleuran](https://discourse.mcneel.com/u/AndersDeleuran)\
**Post date:** [December 28, 2025, 4:21pm UTC](https://discourse.mcneel.com/t/bending-active-structure/189450/21 "2025-12-28T16:21:55Z")

</div>

> [@Felix\_Berger](#):
>
> … to somehow ‘reverse engineer’ this generated curve.

I’m not quite sure I follow, but if the goal is to find a given bent elastica curve, I’d have a look at the [Lace Wall](https://discourse.mcneel.com/uploads/short-url/dVKBJlK5I8ReIBzCjLoRUDt86aZ.pdf) paper. Where we developed this pipeline to generate pseudo-Steiner-tree cable networks that constrain two slender beams into a wall unit:

[![](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/e/6/f/e6fcfdba65e5bc7384c4d1ed1c18dacd4e1bca69.jpeg "Lace Wall - Unit Design Modelling Stages") ](https://vimeo.com/181478689)

Which I hooked up to Galapagos and recorded good fit units:

[![](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/8/e/8/8e88b431f86645ee8671c47ccdf2ddd7c0026d5b.jpeg "Lace Wall - Cable Network Generation Search Loop") ](https://vimeo.com/180416305)

That were aggregated into this wall and simulated (using K2Engineering):

[![](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/9/4/c/94c8d4274204e462b343ebb0cc416305add06336.jpeg "Lace Wall - Macro Scale Simulation of Full Wall") ](https://vimeo.com/180564095)

Also, a merry Christmas to all 🎄

[Next page](https://discourse.mcneel.com/t/bending-active-structure/189450.md?page=2)
