Unroll Curves in one direction only

Hello All,

I m looking a way to automate the process of unrolling curves in one direction.
I give below an example and i have also attached the 3dm file.unroll_crv_1d.3dm (60.9 KB)

The original curves are shown below.
The goal is to unroll them on the Z-axis:

What i manually do is to take the intersection points and split the curves:

Then i measure the length of each segment of the blue lines and create a 1-D line .
Finally i connect the end points of each segment with the longitudinal curves (red)

As this process is very time-consuming to perform it manually, a python script would be the perfect solution.

Any help/advise is highly appreciated.

Thank you in advance

I have written the following code that unroll all lines which are selected but does it individually.

import rhinoscriptsyntax as rs
import Rhino.Geometry.Line as Line
curves = rs.GetObjects("Pick some curves", rs.filter.curve)
expanded_crvs = []
for curve in curves:
    crv_length = rs.CurveLength(curve)
    start_point = rs.CurveStartPoint(curve)
    end_point = rs.CurveEndPoint(curve)
    #expanded point and projected on xz plane
    start_point_new = [start_point[0],0,start_point[2]]
    end_point_new = [start_point[0],0,start_point[2]-crv_length]

    #add all new curves in list

Furthermore, suggestions and advices on the code above are more than welcome.

Does anyone know how to sort the expanded_crvs based on the Z-coordinate?
Furthermore, how can I maintain the layer and the name for each segment?

This should work (not tested), sorting the list by the Z coordinate of the start point - add this at the end outside the for loop:

expanded_crvs.sort(key=lambda crv: crv[0][2])


Thanks Graham,

I ended up using the following for sorting to the Z-axis

for curve in curves:
    layer = rs.ObjectLayer(curve)
    geo = rs.coercegeometry(curve)
    pt = geo.GetBoundingBox(True).Center
    curves_sorted.append([curve, pt.X, pt.Y, pt.Z, pt, layer])
curves_sorted = sorted(curves_sorted, key=itemgetter(1,3), reverse=False )
1 Like

Looks good, you can simplify the final line to just

For others, the above solution needs:

from operator import itemgetter

1 Like