Measure curve-curve overlap

Given large curves (red) and smaller curves (blue) I want to return only blue curves that overlap red curves by more than 99% of its area. Blue curves that have more than 1% area outside of red curves are ignored. My script utilizes Rhino.Geometry.Curve.CreateBooleanDifference() to find if the excess area is more than 1%. My question is: how do you get the area of a closed planar curve via rhinocommon? And/or is there a better way of approaching this?

The red curves start out as un-joined halves, so I join them in the script

import Rhino.Geometry as rg

redclosed=rg.Curve.JoinCurves(red)[0]
bluelist=[]
arealist=[]
for i in blue:
    temp1=rg.Curve.CreateBooleanDifference(i,redclosed)
    if len(temp1)==0:
        arealist.append(0)
    else:
        area=0
        for j in temp1:
            area+=#get area of j
        arealist.append(area)
    if arealist[-1]/ #area of i<.01:
        bluelist.append(i)
a=bluelist
b=arealist

I’ve attached a model and a grasshopper script.
160616 Temp.3dm (72.7 KB)<a class=“attachment” 160616 Area Analysis.gh (7.9 KB)

#crv is a closed planar curve object
import Rhino
amp=Rhino.Geometry.AreaMassProperties.Compute(crv)
if amp: crv_area=amp.Area

–Mitch

Thanks.

Remind me, what does if amp: do? Is it equivalent to if amp!=None: ?

Yes. Just makes sure that AreaMassProperties actually returns something. --Mitch

Kind of a side question. In grasshopper you can reparameterize a curve so that the t values are between 0 and 1. Is there a way to do this in Rhinocommon?

Why do you need to do this? If not done correctly, Reparameterizing objects can lead to issues later on. Check the Rhino help file for the Reparameterize command for more details.

I guess you could just reset its domain this way:

interval=Rhino.Geometry.Interval(0,1)
crv.Domain=(interval)

However, if Dale says this can lead to issues, I guess I would be cautious…

–Mitch

If I have two reparameterized curves, I know that crv1.PointAt(0) will be at the start, crv1.PointAt(.5) will be in the middle, and crv.PointAt(1) will be at the end. And those t values will do the same for crv2. Currently I have to Rhino.Geometry.Curve.DivideByCount() for each curve which returns numbers that do not apply to other curves because of their different lengths. Is there a better way to do this?

I always reparameterize in grasshopper because it just seems cleaner.

Try something like this instead:

rc, t = curve.NormalizedLengthParameter(0.0)
if rc: 
    start_point = curve.PointAt(t)

rc, t = curve.NormalizedLengthParameter(0.5)
if rc: 
    mid_point = curve.PointAt(t)

rc, t = curve.NormalizedLengthParameter(1.0)
if rc: 
    end_point = curve.PointAt(t)
1 Like

Thanks @dale,

I know that your rc is a boolean. I feel like I have seen people use this abbreviation before. What does it stand for?

rc = result code

Another side question: in the case where a method will return different sets of data, how do I select which set I get?

Rhino.Geometry.Curve.DivideByCount() will either return floats and points or just floats. How do I know which one will be the output. Only the “just floats” version seems to work for me.

Calling overloaded function in IronPython can be painful. Calling overloaded functions with an argument that is passed by reference is even more so.

The overloaded version of DivideCurveCount is declared in C# line this:

public double[] DivideByCount(int segmentCount, bool includeEnds, out Point3d[] points);

The out keyword causes arguments to be passed by reference.

The Python language passes all arguments by-value. There is no syntax to indicate that an argument should be passed by-reference like there is in .NET languages like C# via the ref and out keywords.

Anyway, with some CLR voo-doo and a .NET class named StrongBox, you can get there.

https://github.com/dalefugier/SamplePy/blob/master/SampleCurveDivideByCount.py

More info:

https://blogs.msdn.microsoft.com/haibo_luo/2007/10/05/ironpython-provide-or-not-argument-for-by-ref-parameter/