Inconsistencies with closed (3d)Polylines and Polycurve.Points?

Hello,

my confusion startet last week, when I was working on a script that imports (3d)polyline-geometry from a textfile and I noticed that AutoCAD would draw an additional point that is not really needed.
I still think it’s confusing and somewhat inconcise but it got the job done so all is good.

Now I’m working on the next script that should do the opposite and write out AutoCAD-geometry to a textfile. I’m facing the same issue again but this time I can’t really shrug it off because the geometry in this textfile needs to be precise and I can’t have one Schroedingers point that might or might not exist. :grinning_face:

Let’s take Civil3d surface boundaries as an example:
You can click on a surface and let Civil3d export the surface boundary as a 3d polylinie. This polyline should be closed by its very nature as it is a boundary - the Is-closed-flag however is set to false. This might not be the cleanest implementation but it shouldn’t be a problem because I can just loop through the points (in my example AutoCAD tells me there are 10 points), figure out that the start- and endpoint are identical and export it as a closed polyline to my textfile.

PolyCurve.Points however doesn’t recognize the duplicate start- and endpoint (and only shows me 9 points in my example). My assumption is that it does some data sanitization and since the polyline isn’t set to “closed” it can’t have an identical start- and endpoint and therefore deletes it.

This leaves me with the situation that I can’t really identify closed polylines.
I can’t just look at the Is-Closed?-flag as it might be set wrong (as in the surface-boundary example) but I can’t also just look at the points as they arn’t all showing up in PolyCurve.Points.
This also results in the funny situation that Dynamo, Camber (@zachri.jensen) and The Civil Nodes (@Anton_Huizinga) are in disagreement wether a surface boundary is closed or not:

They are all right, depending on how you look at it - the polyline isn’t closed, as the Is-Closed flag is Set to false. It is closed however, as its start- and endpoint are identical.

My solution for now has been to just stick with the “The Civil Nodes”-node, as it does seem to look at the points and not just the flag. Another approach would be to loop through the curves of the polycurve and check this way, if start- and endpoint are identical.

PolyCurve.Points is much easier though and I think it would be better if it was consistent with what we see in AutoCAD. Maybe it could be improved by adding a flag like “Filter out duplicates” or something like that.

Edit:
I just now realized that the Civil-Nodes-Node has this flag “IsReallyClosed”.
This is exactly what I’m talking about and even the solution I suggested for the PolyCurve.Points-Node.
So consider this post a live-feed of an old man slowly realizing things and thank you for the Civil-Nodes! :slight_smile:

ClosedPolys.dyn (16.1 KB)

SampleDrawing.dwg (1.1 MB)

2 Likes

I just wanted to reply that the Polyline3D.IsClosed from The Civil Nodes has an extra input port.

I have 2 Polylines, one is really closed, the other just have similar start and end coordinates. It returns the same values as the Curve.IsClosed node, the one that reads AutoCAD curve objects:

Apparently, the Object.Geometry is smart enough to convert a not-really-closed Polyline into a PolyCurve without duplicate points but with the IsClosed flag:

It is actually smart, but not in all cases the desired result.

You could use the Polyline3D.ConvertToPolyCurve node from The Civil Nodes, but while testing, it seems it does not convert the Polylines in a correct way, though it seems the desired result:

But the generated PolyCurve is missing the closing element.

I’ll add this to the development list to fix.

1 Like

The PolyCurve nodes are probably not the ones to work with in your case anyway:

When designing a PolyCurve, it will remove the last point if similar to the first point, and adds the IsClosed flag.

You could have a look at the Polyline3D.Vertices node, which returns all points of the 3D Polyline without removing duplicates.

1 Like

Thank you for your reply!
For now everything works great when using the “The Civil Nodes”-Polyline3D.IsClosed-Node so I’ll just roll with that but it’s good to know about Polyline3D.Vertices!

This issue also applies to featurelines and I couldn’t find any dedicated “IsClosed”-nodes for those so, for reference, here’s my brute-force approach:

FeatureLines don’t have many public API functions available, so there are not many nodes for these objects.

Personally, I wouldn’t rely on the == operator. If a Point is an object (which is probably not), two objects with the same geometry are different objects (e.g., “this apple == that apple is false“).

You better look for functions that test equality, with names as Equals, EqualTo, IsEqual, or similar. Those functions will look at similarities (e.g., “this apple is equal to that apple is true (if same color, same weight, same size, same shape)“).

But working with numeric values sometimes fools you. Calculations like 9.0 / 3.0 = 2.999999999834 can occur. So, “9.0 / 3.0 == 3.0“ is false, and probably “9.0 / 3.0 equals 3.0“ too.

The node Geometry.IsAlmostEqualTo can compare two points, and you see that if the number of decimals is more then 5, numbers are rounded:

Which is perfectly fine in infrastructure.

In Python I would use something like:

if startpoint.DistanceTo(endpoint) < 0.00001 then {consider true}

@Anton_Huizinga I like pnt1.DistanceTo(pnt2) < tollerance; for comparison of point equality. :slight_smile:

1 Like

Ok… so I think it’s important to put a ‘why’ to all of this stuff before things go much further. So… I’m going to try and do that.

When building a digital geometry system there are a LOT of things to consider. An in no-way inclusive list:

  • Do you have points (as in Civil 3D), or something else (as in Revit where XYZ functions as a point and a vector).
  • Do you allow curves (AutoCAD) or only straight lines (Sketchup)?
  • Do you allow non-planar curves (Dynamo) or require they be on the XY plane (GIS formats)?
  • Do you require the curve’s normal be on the Z axis, or can it vary?
  • Do you use an additional property for closed curves (Dynamo) or do you reuse the first point as the last point (GeoJSON), or do you allow both (AutoCAD)?
  • Do you enforce a point order or direction to ensure the normal is consistent or otherwise identify a loop’s intent (GeoJSON), or do you allow any valid sequence (Dynamo)
  • Do you allow self intersections (Dynamo), or do you prevent them to ensure area calculations work (shape files)?

Each decision has impacts far beyond what you’re considering as a software developer today. Looking only at closed curves as an example:

  1. If you opt for an additional “closed” property there are steps you have to take to allow closing shapes which don’t consist of lines
  2. If you opt for reusing the first point as the last point you have to keep 3 extra doubles in place of a single boolean, causing files to grow much larger
  3. If you opt for both you have better flexibility on imported data, but you risk confusing the users and have to deal with the most edge cases which slows things down, in some cases significantly.

Unfortunately modern digital practice means you have to know the decision which was made for any given format you’re working with. So if you’re exporting data to push into GeoJSON you need to know all of it’s rules… this is both tedious to author and error prone due to the trial and error nature (you don’t know something violates the rule until it’s been violated). It’s also why software companies build importers and exporters for you - there are simply too many things for any one person who isn’t a full time developer to build import export routines for everything. When you do run into the need, look into the applications required rules before you start.

2 Likes