Polyline.IsClosed super slow - Bug?

After a long journey with a strange performance issue:
Polyline.IsClosed seams to be the bottle-neck.
why ?
a bug ?
do i miss something ?

UPDATE: test also for IsClosedWithinTolerance

void PolylineIsClosedPerformance(Polyline pl, int testNum = 10000)
{
    Stopwatch watch = new();
    //
    // Rhino is Closed
    //
    watch.Start();
    for (int i = 0; i < testNum; i++)
    {
        //
        //  SUPER SLOW - WHY ??
        //
        bool isClosed = pl.IsClosed;
        //
        //
    }
    watch.Stop();
    Console.WriteLine($"Time taken IsClosed {testNum} times: {watch.ElapsedMilliseconds} ms");
    //
    // Rhino is Closed
    //
    watch.Start();
    for (int i = 0; i < testNum; i++)
    {
        //
        //  Even slower
        //
        bool isClosed = pl.IsClosedWithinTolerance(1e-06); // similar results for 0.0 and 1e-06
        //
        //
    }
    watch.Stop();
    Console.WriteLine($"Time taken IsClosedWithinTolerance {testNum} times: {watch.ElapsedMilliseconds} ms");
    //
    // compare with distance first to last
    //
    watch.Reset();
    watch.Start();
    for (int i = 0; i < testNum; i++)
    {
        bool isClosed = pl[0].DistanceTo(pl[pl.Count - 1]) < 1e-06;
    }
    watch.Stop();
    Console.WriteLine($"Time taken Distance first to last {testNum} times: {watch.ElapsedMilliseconds} ms");
}
Time taken IsClosed 10000 times: 4706 ms
Time taken IsClosedWithinTolerance 10000 times: 9325 ms
Time taken Distance first to last 10000 times: 1 ms

here is the script run from the script-Editor and the 3dm with the 11158-points-polyline

Helix-Polyline-IsClosed-Test.3dm (472.0 KB)
testPolylineIsClosed_01_forum_02.cs (1.9 KB)

my system-info
(Rhino 8, Version 8 (8.26.25349.19002, 2025-12-15) on a mac intel)
systeminfo_tom_p_2026_01_07.txt (6.4 KB)

@dale - are you the right person to look at this ? or can you please add / “@” the responsible person - or tell me what s wrong. many Thanks.

kind regards, happy 2026
:champagne:
-tom

Hi @Tom_P,

OpenNURBS does more than what you’re doing.

– Dale

Dear Dale - thanks for the fast reply - really appreciate it.

but where do the nearly 5 seconds

come from in above script for 10 000 tests ?
vs. less then a ms for the pure distance test ?

EDIT:

but the second part of the implementation might be the bottle neck. ?!
Rhinocommon accesses the Polyline.IsClosed as Property without a tolerance parameter.

Does Rhinocommon send a tolerance = 0.0 ?

bool ON_Polyline::IsClosed( double tolerance ) const
{
  bool rc = false;
  const int count = m_count-1;
  int i;
  if ( count >= 3 )
  {
    if ( tolerance > 0.0 )
    {
      if ( m_a[0].DistanceTo(m_a[count]) <= tolerance ) {
        for ( i = 1; i < count; i++ ) {
          if (   m_a[i].DistanceTo(m_a[0]) > tolerance 
              && m_a[i].DistanceTo(m_a[count]) > tolerance ) 
          {
             rc = true;
             break;
          }
        }
      }
    }
    else
    {
      if ( ON_PointsAreCoincident(3,false,&m_a[0].x,&m_a[count].x) ) 
      {
        //
        // here all points are potentially tested - this is expensive for my 11158 polyline called 10000 times
        // not sure what s the idea behind this test
        //
        for ( i = 1; i < count; i++ ) {
          if (    !ON_PointsAreCoincident(3,false,&m_a[i].x,&m_a[0].x) 
               && !ON_PointsAreCoincident(3,false,&m_a[i].x,&m_a[count].x) 
             )
          {
            rc = true;
            break;
          }
        }
      }
    }
  }
  return rc;
}

Yes.

Try using Polyline.IsClosedWithinTolerance and specify a tolerance > 0.0.

– Dale

1 Like

is even worth…

So the link between c# and the underlaying cpp core is the bottleneck ?

I looked into the old csharp rhinocommon rhino 5.0 code on github and it looks like the DistanceTo Method is not calling underlaying native cpp code but is implemented in c#
?

I am assuming this is the cause.

– Dale

Knit picking here, but you could save a couple square roots in this code. (Sorry couldn’t help myself!)