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â.
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.
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).
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.
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â.
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).
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.
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
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!