How To Reference Or Get GUID Of Sub-Curves From Rhino Polyline?

Hello,

Is it possible (I hope so!) to reference sub-curves in Grasshopper?

Currently I leverage various scripts to reference Sub-Objects (such as nested objects in groups) and those work great but I am specifically looking to be able to reference a sub-curve into GH in the following workflow.

-Have a polyline or draw a polyline in Rhino
-Use Ctrl+Shift Click / Sub-Selection to select a single sub curve or multiple sub curves
-Get these specific sub-curves as referenced curves in Grasshopper
-Do things to said specific sub-curves in Grasshopper

I know that I can reference the overall polyline, and then explode it in GH or use edge indices to select the curves I am after but I am trying to enable a workflow where the user can click the specific sub-curves they want without needing to know what index they are at and without the need to reference the entirety of the remaining curve.

An example of how I may use this script is by selecting the sub-curve of a “wall polyline” that resides in a “kitchen” and then having parametric cabinets generated along that specific sub-curve without exploding the overall polyline in Rhino that defines the “wall”.

Does that make sense?

Neither this method: (with “subobjects=true”)
https://developer.rhino3d.com/api/RhinoScriptSyntax/#selection-GetObject

Or this method:
https://developer.rhino3d.com/api/RhinoScriptSyntax/#selection-GetCurveObject

Appear to provide what I am looking for.

Additionally, the “what” command yields the same information for both subcurves.

Thank you for any leads!

1 Like

The grasshopper part is beyond me (I don’t know how you reference componentindices in the calls).

For Rhino:

Within the model geometry, I haven’t been able to find ID’s on anything but RhinoObjects (I don’t consider something like a Material definition to be a direct part of the geometry).

ID is declared at the RhinoObject level, and doesn’t seem to be defined on GeometryBase or the subclasses which might be the spans of a PolyCurve.

Further, the RhinoDoc’s object table returns a RhinoObject for the Find method, not something like GeometryBase or Object- and some subobjects aren’t even classes but structs.

Certain things like SubDFace do have an ID, but that’s simply an Int32 and seems to act like an index (I speculate that they may not want to make certain guarantees about how these behave given the way some recent objects only support ForEach iteration not random access and thus called it an ID rather than an index).

Ultimately, I couldn’t figure out a simpler way to track object and subobject selection than to create my own class. I even create ‘faux’ objects in certain cases, such as polylines in which Rhino seems to maximize efficiency by not storing segments as separate objects.

1 Like

I sat back a bit to see what anyone else would have to say.

Within Rhino, the general flow is:
User selects objects and/or subobjects.
Rhino fires a selection event which references the top level RhinoObject(s) being addressed. Given that reference, you can ask for RhinoObject.GetSelectedSubObjects method (rhino3d.com)

Note that the top level RhinoObject may or may not be selected: the event fires whether the selection is the top level object or just one of the subobjects (like a segment of a curve after the shft-ctrl-click select).

The subobjects method gives you an array of
https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.componentindex

These have a type of subobject and an index/id.

To retrieve the actual subobject, you need to look at the type of RhinoObject and ask for the piece which makes sense given the object type and the type of the ComponentIndex (the appropriate segment of a Curve, for example).

This works as expected for the conventional geometry objects except Extrusion and PolyLineCurve.

The former is a long story. The latter:

So far as I can tell, it doesn’t have objects for each segment. The way I deal with that is to create LineCurves as I need them from the points in the PolyLineCurve’s PolyLine representation.

It gets the job done.

Am I understanding the question you were asking?

1 Like

Thank you @Nathan_Bossett , all of this is very helpful!

I have been able to retrieve sub objects just fine but as you pointed out this doesn’t work with curves because the segments are not considered objects even though you can cut/paste/duplicate them “out” of the parent curve and then they will become their own object. Hmm…

The component index makes sense and I have not specifically looked at how that works under a selection event.

When you say you create line curves, you mean you draw new curves from point to point to create a faux poly line?

My question with this method is, is this any different from exploding the poly line?

What I need is for the poly line to remain intact but as you mentioned return the individual lines/segments or segment indices that are selected.

Curious what your faux pline looks like from a code perspective. Is it it’s own geometry type or class? Or is it still considered a poly line?

I really appreciate your help and response!

Thank you!

EDIT:

Just saw the constructor you linked and I think “Poly curve segment array” is what I need to dig into

Pretty much. Here are two examples, one in which the subobjects/components are ‘real’ in a McNeel object sense and one in which they’re ‘faux’.

Real:


That line segment, which is a span of a PolyCurve, actually exists in Rhino’s object model. I retrieve information about it from the parent Curve and draw it (Rhino’s select in yellow, my select in red).

Faux:


These segments don’t actually exist in Rhino’s model, which is why I display them in parentheses. I keep track of the PolyLineCurve and extract data as required. In this case ‘as required’ means to pull tabular information about each segment and to do the red highlight.

What it looks like in code:
If you’ve got a PolyLineCurve (like the one pictured), from that you can get a .ToPolyLine(). This gives you the points of the polyline. From there, I just look at the points or create temporary LineCurves as needed.

These are all temporary constructions outside of the persistent Rhino Document but they could easily be used to make updates to the Doc. I don’t make any changes to the Rhino model: this plugin is a review/audit tool.

Interesting, thank you for sharing this! The visual examples are helpful as well!

This is essentially what I am after, instead highlighting the red selected line segment, I want to reference that into GH and I’ll then use properties of that segment such as tangency and length, start and end points, to create other geometry based on that as an underlying “guide curve”

My idea being, if that original polyline gets moved, control points shifted, etc. the sub-curve (your red curve) will of course get manipulated along with the parent curve and will then update the grasshopper definition logic downstream.

Example:

Like lets say we scale the overall parent curve by .75, the red segment will now be shorter slightly, meaning the grasshopper definition would now create a “shorter” element at that location.

Elements I am creating are mostly architectural focused such as walls, cabinets, doors, windows, etc.

So if the pentagon example was a building footprint boundary and I wanted to add a glazed curtain wall, I would select the red line you show, and the curtain wall would be created at that segment only, but if I selected the segment to the left or right as well, the curtain wall would be created “around the corner” to include both sub-curves.

Am I making sense?

I could sketch it out if you think it’d be helpful

Yes, but tracking the actual segment across changes to the parent RhinoObject will require some bookkeeping since there’s no direct changed event and ID for components the way we have for RhinoObjects with the replacement and related events.

A scaling should be easy. Dragging a segment or deleting one might get more complicated.

Yes.

Sure. Your use case is interesting and parallels some problems which I either have solutions for or need to explore myself.

This is exactly why I was trying to move a way from an index based approach and get the actual segment (id) if that even exists.

If it’s just an index based array either way then yes some kind of tracking will need to be implemented.

I don’t think there are events for adding or removing segments from a parent polyline?

There’s insertion of control points but that route would get a little convoluted I think.

Here’s a crude sketch with CC representing a “Control Curve” or Parent curve.

By changing the sub-curve selection, the extrusion would update accordingly.

And here’s an example diagramming a persistent index tracking based on the original first implementation of the parent curve. I think we would have to store the original indices and the curve that would get “kept” would be whichever was extended such as the 3rd example we keep 4 and 7 because those were extended by the user.

In some ways it’s similar to how trimmed surface work where a surface is trimmed with a unique shape but you can “untrim” it at any point as well. Not quite that obviously but similar in concept.

Above in left example (example 1) the logic is “hosted” to index 6 sub-curve, when we modify the parent curve in example 2, the logic “extends”, and the way we modified the parent curve in example 3, the logic goes null as the “host” sub-curve was removed. I would probably add a warning here before executing the script letting the user know the host is about to be removed… but that’s down the road.

I’m not sure if you’ve worked with these before and the phrasing there is a little ambiguous (an event for the change, or a specific event for that change): There are events, but they don’t specify details of the change.

In this case, you’d get a replacing object event, a deleting object event and then an adding object event.

The replacing event is to let you know that the next pair of delete and add are an edit to the same object.

That’s at the RhinoObject level.

The extra bookkeeping we were discussing would be to figure out exactly what changed.

Undo makes everything even more fun :slight_smile:

On my wish list is a “User is about to do x” event with a chance to modify or cancel it and a “User has finished doing x” event.

I’ll need to think about your diagrams and explanations a bit… not ignoring them.

Okay yes, the way you described events makes sense.

Thank you, I really appreciate your insights!

When I have some free time again I’m going to explore the polyline arrays and see how far I can get with that alone.

I barely got to play with the WIP constraints that were being worked on and subsequently were removed from R8 but I recall there perhaps being a constraint that would work on sub-curves that would have been great to have exposed in GH. Oh well! Maybe next version!