Grasshopper

algorithmic modeling for Rhino

Morning,

I am looking for the most correct way of casting of existing Rhino geometry to certain geometry type to be used further in Grasshopper.

Let say, Rhino objects are selected based on the input layer as following:

Dim rhobjs As Rhino.DocObjects.RhinoObject() = doc.Objects.FindByLayer(lname)

 

then casting for Breps only can look like this:

For Each rhobj As RhinoObject In rhobjs

       Dim cbrep As Brep=TryCast(rhobj.Geometry,Brep)

 Next

Is that most correct?

What would be the difference if I need to extend the filter to second geometry type, for instance - Surface?

Thanks in advance,

Dmitriy

Views: 1809

Replies to This Discussion

Ultimately Grasshopper needs to have types that implement IGH_Goo. Thus Grasshopper.Types.GH_Brep or Grasshopper.Types.GH_Surface etc.

Grasshopper defines a lot of 'automatic' casting operations and sometimes they are lossy (like for example curve -> number, which returns the curve length) and sometimes they generate a lot of new data (like for example curve -> brep, which tries to create a planar region).

The easiest thing for you is to use the Grasshopper.Kernel.GH_Convert class. It defines a boatload of conversion functions one of which will most likely do what you need.

--

David Rutten

david@mcneel.com

Poprad, Slovakia

Hi David,

Thanks for reply.

I have tried the following:

Dim cbrep As GH_Brep=Nothing

Dim conv As Boolean=GH_Convert.ToGHBrep(rhobj,0,cbrep)

then conv gives FALSE.

If using Dim cbrep As Brep=TryCast(rhobj.Geometry,Brep) - I get a Brep.

Where is the trick?

And more issue: after converting to GH_Brep - how to convert it to Brep?

Thanks,

 Dmitriy

Don't use 0 as an argument in the conversion methods. It specifically requires an enumeration of type GH_Conversion. So either use GH_Conversion.Primary, GH_Conversion.Secondary or GH_Conversion.Both.

Primary conversion only works if the source is already of a similar type as the target. So Breps and GH_Breps can be cast to GH_Brep using primary. Secondary conversion uses all predefined casts. So if the source is a GUID, then the method will try to find the Rhino object with that GUID and get the Brep geometry inside of it. If the source is a string it will try and find an object with the proper name etc. etc.

Since you were looking for multiple casts (breps, surface etc.) I thought you could use one of the following:

  • GH_Convert.ToGoo
  • GH_Convert.ToGeometricGoo
  • GH_Convert.ObjRefToGeometry

You'll need to decide whether you want to create a referenced GH_Brep or not though. A referenced GH_Brep knows that it is representing an existing Rhino object. You may or may not want this.

And more issue: after converting to GH_Brep - how to convert it to Brep?

GH_Brep has a Value property which allows you to access the Brep inside of it. But be careful, instances of GH_Brep may be shared amongst multiple parameters so don't change them unless you know for a fact that you have a unique instance. 

--

David Rutten

david@mcneel.com

Poprad, Slovakia

Hi David,

Thank you for the comprehensive reply. It brings my understanding further.

I have actually checked both methods:

  • GH_Convert.ToGeometricGoo
  • GH_Convert.ObjRefToGeometry

Both work fine.

However, I thought that if you use ObjRefToGeometry - then your component should react immediately after the source object in Rhino is changed(moved, modified, trimmed ... etc). But it is not. I got the same behavior for both methods.

So, what I am looking is the immediate running of SolveInstance after reference object in Rhino is modified. Alternatively I can use timer but that is not an elegant solution.

I think, it has to do with the Event Watcher principle - but not 100% sure.

Thanks again,

Dmitriy

However, I thought that if you use ObjRefToGeometry - then your component should react immediately after the source object in Rhino is changed [...]

Depends. If the data is stored in an input or floating parameter which is capable of informing Grasshopper about the fact that it needs to be kept in sync with the Rhino model then yes. Otherwise no.

Where are you storing these IGH_GeometricGoo instances?

--

David Rutten

david@mcneel.com

Poprad, Slovakia

Basically all definitions are done in the SolveInstance as following:

Dim breps As New List(Of Brep)

...

Dim rhobjs As Rhino.DocObjects.RhinoObject() = doc.Objects.FindByLayer(lname)

For Each rhobj As Rhino.DocObjects.RhinoObject In rhobjs

            Dim ref As New DocObjects.ObjRef(rhobj)
            Dim goo As IGH_GeometricGoo = GH_Convert.ObjRefToGeometry(ref)
          
            If (goo Is NothingThen Continue For
            If (TypeOf goo Is GH_Brep) OrElse (TypeOf goo Is GH_Surface)  Then
                Dim cbrep As GH_Brep = DirectCast(goo, GH_Brep)
                breps.Add(cbrep.Value)
            End If
          Next

So, as you can see - not in the input.

floating parameter which is capable of informing Grasshopper about the fact that it needs to be kept in sync with the Rhino model

As for the floating parameter - that sound interesting but is it needed in that case?

Thanks,

Dmitriy

Hi David,

Is floating parameter smth. I should look at in this case or other solution is available to follow an update of the Rhino geomerty?

Thanks,

Dmitriy

You could try overriding RegisterRemoteIDs on your component class. Basically every GH_Document has an event watcher which keeps track of stuff happening in Rhino. For example new objects getting added, existing objects getting changed, new 3dm files being loaded that sort of thing.

This event watcher knows which components and parameters in the document are interested in these sorts of events. It knows this because it asks all of them using the RegisterRemoteIDs() method. The default implementation of this method in GH_Component is to only look at input parameters.

If you have an internal list of referenced geometry that you want to keep live, then do something like the following (untested):

Public Overrides Sub RegisterRemoteIDs(table As GH_GuidTable)
  MyBase.RegisterRemoteIDs(table)

  For Each cachedId As Guid In m_cachedIDs
    table.Add(cachedId, Me)
  Next
End Sub

You'll have to build a list of GUIDs though, probably in SolveInstance().

If you've registered your Rhino object guids and they change, then your component will be expired whenever one of those rhino object changes.

--

David Rutten

david@mcneel.com

Poprad, Slovakia

Hi David,

Amazing... It is working exactly as I want it.

Thank you very much for support.

Thanks,

Dmitriy

RSS

About

Translate

Search

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service