# Sorting Concave/Convex corners of planar polylines

I’m trying to create an efficient cluster that will sort the inside (concave) and outside (convex) corners of planar surface edges.

I found a definition which will work for planar surface edges and planar polylines that are parallel to the XY plane, at the end of this thread:

InternalCross.gh (8.0 KB)

I can easily make this definition work for planar surface edges on the XZ and YZ plane just by swapping out one unit vector component, but that would mean I’d have to use three different clusters, and I’d have to sort the input surfaces, and it’d still only work on surfaces and polylines that are parallel to the orthogonal planes.

Any suggestions for how to make a more universal definition that works with any planar surface or polyline, in any orientation?

This is only a partial solution, using the ‘Z’ (normal) of Plane Fit instead of ‘World Z’. The problem is that Plane Fit is “upside down” at certain angles.

InternalCross_2019Jul7a.gh (13.3 KB)

This version is more robust. Instead of Plane Fit it uses the first two segments of the curve with LnLn (Line + Line) to create the reference plane and Z-normal:

InternalCross_2019Jul7b.gh (14.7 KB)

1 Like

You could also make use of this method to check the orientation

https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Curve_ClosedCurveOrientation.htm

(since I think with your second method you still don’t know if the angle between the first 2 segments you pick is convex)

You are right, of course… back to the drawing board.

The second one works in all orientations but it also seems to be identifying closed polyline seams as concave corners.

Here it is with internalized example geometry on all three world planes, minus the initial rotation you had…InternalCross_2019Jul7c.gh (28.4 KB)

I suppose I could just cull the seams, but that would become an issue if a seam happened to be at concave corner.

…wait: if the polylines I’m dealing with in my application are all the edges of planar faces of solids, can’t I just use the normals of those solid faces to orient?

Whenever I try to make a little sorting cluster I try to make it as universally applicable as possible, so if it can be done for polylines alone that’d be awesome, but I’m gonna try to make it work with face borders too. After I put the kid down for a nap, though… Thanks for all your help so far, folks.

I think all you need is this little check for the orientation and your first definition works
InternalCross_2019Jul7a_orientation.gh (16.0 KB)

I had to invert the Dispatch ‘P’ (Pattern) input to get concave “corners”, it was showing convex by default.

The extra point is coming from the DePlane component. Just disable preview on that component.

1 Like

Oh, duh, silly me, didn’t see that for some reason. In that case, so far with my test geometry, your definition works perfectly. Thank you so much.

Basically what we’ve got here is the polyline version of what the Convex Edges component does for polysurfaces. I think this is a universally useful enough tool that it should be nominated to become a standard component that lives in the curve analysis tab.

Also, how do you make component names show up in white boxes in your posts?

No, @DanielPiker is correct, it depends on being lucky about “if the angle between the first 2 segments you pick is convex”, as this version demonstrates. The purple group allows you to move the seam to different vertex points, which causes it to fail. The white group offers a switch between “blind faith” or using Daniel’s “CurveOrientation”, which appears to handle all cases (though again, I had to invert the dispatch pattern):

InternalCross_2019Jul7d_orientation.gh (24.4 KB)

P.S. You might want to flatten the input to Avr to get a single center of rotation for all the curves.

Can this be done without the C# component?

Like this: `<kbd>Dispatch</kbd>`

1 Like

Just to be sure, is the initial rotation in @DanielPiker’s definition critical to reliable function, or is it just there to test at a different orientation than the original?

I think Joseph just put that rotation in there for testing.

Here’s one way
InternalCross_2019Jul7a_orientation_noscript.gh (14.5 KB)
You can get the signed area of a planar polygon by summing areas of the triangles formed by the directed edges with an arbitrary point, then use the sign of this to know its orientation.

2 Likes

Right again, same with the seam adjustent - just a test bench. Here it is clustered: ccVerts in green group:

InternalCross_2019Jul7d2_orientation.gh (19.2 KB)

Whoa… I’m studying your code, it works but I don’t understand why yet. Thanks.

1 Like

I’m obviously still trying to figure it out too, but it works and thanks for the lesson!

It relates to Gauss’s ‘shoelace formula’

Here’s an even simpler example of how signed area can be found:

shoelace.gh (10.0 KB)

http://www.sunshine2k.de/coding/javascript/polygonarea/polygonarea_js.html

1 Like

Wonderful, thanks again. The explanation is great. Can we please have an R5 version?

Would be REALLY GREAT if we could use Javascript with GH… sigh.

converting JS to C# usually isn’t too bad, especially for mathematical stuff like this

So I took your definition, and basically just added two plugin components to get it to do the task I’d originally aimed to get done. Then clustered it.

Here’s both unclustered and clustered in one file.

I added ggSimplifyPolyline to the input because it’s common to get more than one segment on a straight line edge in an object someone else drew in rhino, and I want to prevent extraneous vertices from popping up.

And then I duplicated the definition, and ran the Sasquatch surface border output into each duplicate, and re-labelled the outputs appropriately.

All of this could have hypothetically been accomplished on a polysurface using convex edges, except that any input with naked edges or non-manifold edges is a pain. By directly sorting the surface border edges, I think you’ve helped me avoid making a whole lot of unnecessary spaghetti.

Here’s my small additional contribution, with internalized test geometry.

Being dependent on plugins leaves me out:

I modified shoelace.gh to create a cClock cluster:

Then modified the ccVerts cluster to use it, using negative Z instead of flipping the plane, though I could have (and probably should have) done that inside the cClock cluster:

InternalCross_2019Jul7e_orientation.gh (27.2 KB)

I’m sure there’s a non-plugin solution. I just had two components I knew would get the job done quicker.

Those two components are super simple and should absolutely be made into standard components in GH2, though.

Simplify polyline is super useful for putting in the chain right after importing rhino geometry that was generated with curveboolean or curves that come from polysurface edges: people are super sloppy about cleaning those sorts of things up in their drawings.

And the surface border component, if only because it differentiates between interior and exterior edges and a bunch of the native components for exploding and deconstructing don’t, is also either a worthy addition or maybe it’s function of sorting interior and exterior should be incorporated into existing deconstructors.