Long run time

Hi everyone!
Hope you are doing well,
I created a program in grasshopper with a loop using anemone, the loop is running a python script and looks like the code is creating the geometries as I expected, but there is an issue with the run time, it is so long around 5.4 s for each repetition. Please have a look at the image below:

So as the loop is executing the script 4 times, the total computing time is around 24.2 sec, and it causes my program goes so slow. I wonder if some of you can give some advice on what can I do to reduce the run time. Do you think that in my script I’m using not good practices? or it is normal that the program takes a lot of time for its execution?.
Many thanks in advance, any sugestion will be much aprecciate.
CTS-RunTime.gh (265.9 KB)

To be clear, the slow part appears to be the Python, based on your image alone? So conventional GH/Anemone experience isn’t much use here.

And all these plugins required, which makes it impossible to see much of anything without them:


P.S. It appears to me that five or six inputs to the Anemone loop could be internalized?


Hi Joseph,

Many thanks for spending some time on my enquiry.
Yea sorry, I remove some unnecessary blocks and I bake/internalize some data. Just I leave the Anemone blocks and the GH script, please have a look at the new Grashopper file and also I include the . PY file.
I’m using ghpythonlib.components and I’m not sure if that library is causing the long run time or maybe I did something wrong on the scrip.

Basically what the script do is create/propagate more curves over a 3D surface using one Reference Curve and one Shifting curve, it runs an algorithm to find the next Reference curve, and the use it for to generate the next Reference curve and so on.

Run_time.py (2.4 KB)
CTS-RunTime_ver2.gh (37.6 KB)

Much better but I can’t help with the Python, sorry. I can open and read the Python code in your GH file though, so don’t need the separate .py file.

Hi Joseph,
Anyway many thanks for your reply,
Honestly, I’m a beginner using GHpython , so is very probably that I’m not using good practices on my program or maybe I’m doing something wrong. But I going to read more about it and try to find something that can help me.

Many thanks for your time.

Maybe someone else can look at your Python, but I can easily do this (and more) with standard components, which is a very similar result and very fast.

CTS_2021Oct14a.gh (21.4 KB)

P.S. It goes a little wacky and crosses itself around the 15th offset, but that’s to be expected.


This part:

Sphere_01 = ghcomp.Sphere(Current_Point, Tow_width)
Sphere_02 = ghcomp.Sphere(ShiftingDir_Point, Segmentation)
Circle = ghcomp.BrepXBrep(Sphere_01,Sphere_02)

Is heavy but unneeded. Creating spheres and colliding them, and using ghcomp instead of rhinocommon.
Once you have two points and two radiuses, you can calculate your circle.
Simple number calculations will be faster than clashing nurbs objects.
2021-10-14 21_17_34-Window

I don’t know python, but you might be able to translate this method here:
CTS-RunTime_ver2_re.gh (33.6 KB)

 private void RunScript(Point3d P1, Point3d P2, double R1, double R2, ref object C)
    C = FakeSphereSphereX(P1, P2, R1, R2);
  // <Custom additional code>
  public Circle FakeSphereSphereX(Point3d p1, Point3d p2, double r1, double r2){
    Rhino.Geometry.Vector3d v = p2 - p1;
    double d = v.Length;
    if((d > r1 + r2) || (d < Math.Abs(r1 - r2))){
      // No intersections
      return Rhino.Geometry.Circle.Unset;
    double h = 0.5 + (r1 * r1 - r2 * r2) / (2 * d * d);
    double r = Math.Sqrt(r1 * r1 - h * h * d * d);
    Point3d p = p1 + v * h;
    return new Rhino.Geometry.Circle(new Plane(p, v), r);

Making 500 “fake intersections” (that will still return more accurate circles) take the same time as calculating a single sphere-sphere nurbs intersection

Also, the result of BrepXBrep is a “circle”, but actually a really heavy nurbs curve with many control points, so, using instead a proper circle (8 control points) will make the subsequent steps in your script go faster… probably.


This screen shot is a little confusing but will make more sense when you open the file.

If OffsetS (Offset on Srf) didn’t exist, I would do this with a series of circles on pFrames as seen in the white group. If you look closely, those circle intersections with the surface (not implemented) are very close to the results from your Python/Anemone approach (white curves). CORRECTION: in Top View, the circles are closer to the OffsetS curves (cyan) than your curves (white).

Yours diverge in places from the OffsetS curves (cyan) which now appear on both sides of the ‘ReferenceCurve’ (blue) because I applied Flip Curve to it and passed both original and flipped through Entwine to OffsetS. I suspect that the OffsetS results might be more accurate than either of the alternate methods (yours or mine)?

CTS_2021Oct14b.gh (37.8 KB)

Well, why stop there, let’s take this “perp circles” idea further…

It turns out that the circle intersection method matches OffsetS (Offset on Srf) curves exactly (!) and appears to be faster? Disable OffsetS to see the white group alone.

Naturally, the pFrames had to be aligned with the surface to avoid twisted results so the white group was expanded to use EvalSrf and the machinations added to replace PFrame with an aligned and rotated EvalSrf ‘F’ frame (plane).

CTS_2021Oct14c.gh (85.1 KB)

For reference, the ‘Python/Anemone Crvs’ are internalized without the slow Python/Anemone loop.

Two things:

  1. If you increase the number of offsets in the previous model, the Flip Last component caused confusion for interpolated curves when the “perp circles” intersected the surface on only one side instead of both. To fix that, I used Curve Side (teal group at bottom) to separate points to either the left side (yellow curves) or right side (green curves). Flip Last is no longer used.

  2. In the process, I realized I had used the ‘Segmentation’ slider incorrectly so added a second slider for ‘Count’ (number of offset curves) and kept ‘Segmentation’ for the DivLength ‘L’ value.

Still, the perp circle method is substantially faster than OffsetS (Offset on Srf, gray group at top right), though the latter is visibly more well behaved in some cases.

CTS_2021Oct14d.gh (85.2 KB)

P.S. I suspect that as the radius of the “perp circles” gets larger, accuracy is lost due to surface curvature? So it might be better to iteratively offset the guide curve in one direction or the other (left or right), then use that offset curve as the new reference curve.

1 Like

… likely… but is that even needed? Who knows…

You made me give it a go… whatever this is…
curved lines3

CTS-RunTime_ver2_re2.gh (30.5 KB)

1 Like

Heh, heh, very nice. I’ve never used Geodesic before, that’s cool. I will quibble about using DivDist instead of DivLength though, since the latter measures curve length along the surface instead of straight line distance between points, which is the flaw with “perp circles”. Pipe intersection on a curved surface (which we haven’t mentioned here) also has the same flaw.

Hi Riccardo,

First of all, many thanks for your time and sorry for my delay in reply.
Yes, as you said creating spheres a colliding them is the heavy part, I implemented the method that you suggested and I got the same circle as I did with BrepXBrep command, I was going through the formulas and especially how you calculate h seems very cool/interesting to me, with this improving I could reduce the runtime by 70% less.

I found that there are three main libraries provided by Rhino/Grasshopper which allow Python to access geometric data; 1. ghpythonlib.components, 2. Rhino.Geometry, 3. rhinoscriptsyntax, but to be honest im not sure what library should I use? or why do you think is better to use rhinocommon instead o ghcomp? Any suggestion/comment will be much appreciated.
Finally, many thanks again.
Best regards,

Probably the “Rhino.Geometry” is the less abstract one, ghcomp is useful when you want access functions and methods that are only on GH , but for the other methods i would go with straight rhinocommon without detours.

Nothing against ghcomp, ghpythonlib.components or rhinoscriptsyntax. Lucky us to have so much versatility at our hands!
But talking about optimization, saving 1% runtime here, 2% runtime there is what you want…

The next step into optimizating your code would be to add multithreading… if the situation make it possible.

Re-using the other example.
using multithreading let me save 50% of the time, in this particular case
CTS-RunTime_ver2_re2.gh (39.0 KB)

1 Like

by the way - there is also a sphere-sphere intersection method in RhinoCommon:

For intersections of curves or surfaces, if any of them are primitives like circles/lines/spheres/planes, it’s worth using the specific intersector methods for these, as they will usually be much faster and more accurate than treating them as NURBS.