Using the NodeInCode namespace

Note: if you are planning on using this functionality in Python, you can also use the ghpythonlib.components wrapper library, which is easier to use in Python.


As some noticed some time ago, we have been working on NodeInCode functionality.

The goal was to make this functionality more understandable – with warnings that could give useful suggestions, stable – also when used with multi-threading, and more robust to cases where third-party libraries would not cooperate.

While at it, we decided to allow every .Net language to access this functionality. Some of you noticed a while back, when we were actively changing this most weeks: Rhino.NodeInCode namespace?

Here is how NodeInCode works.

1. Finding a loaded Grasshopper component.

All components that are loaded (with a minimal set of exceptions^) can be found. You just need to know their full name. If the component names comes from a library, then the library names is pre-pended, with an underscore _ as separator. The exact spelling of the library depends from the AssemblyName of the GHA. If you are having issues finding what it exactly is, you can just query all dynamic names like this:

A = Rhino.NodeInCode.Components.NodeInCodeFunctions.GetDynamicMemberNames();
node-in-code-dynamic-names.gh (13.9 KB)

2. Evaluating a component

Any component that can be found can then be evaluated.

node-in-code.gh (7.8 KB)

The same is also possible outside of Grasshopper, for example,

node-in-code.py (539 Bytes)

The only catch is that, at present, there is no way to switch components that have special settings to any alternative. For example,

no-conversion

3. .Net delegates (“function pointers”)

Some developers are used to directly evaluating a method without going through an “Evaluate” function. Especially when writing functional code in .Net, it might be beneficial to get directly a delegate.

This is also supported, in a few different flavors. The flavor mostly deal with how warnings are issues, thereby making it simpler to develop and then possibly switch to a more warning-tolerant system^^. The ComponentFunctionInfo has Delegate, DelegateNoWarnings, DelegateTree and DelegateTreeNoWarnings properties, returning the appropriate type of result.

Delegates are returned in the form of a Func<object,object,...> generic instance. Because of this, the number of inputs needs to match exactly the amount of inputs of the component. This is in contrast with the Evaluate() method, where Optional inputs at the bottom of a component can just be omitted.

node-in-code-delegates.gh (11.9 KB)

Notes

^ at present you cannot find: scripting components themselves, GHPY compiled components, params and third-party add-ons components that have names consisting of only non-ASCII characters.

^^ please note that DynamicInvoke() will wrap exceptions within TargetInvocationExceptions. You can retrieve the inner exception with the InnerException property. You can get Grasshopper to visualize the exception by writing:

try
{
  B = ((Delegate) y).DynamicInvoke(new object[]{"1,1,0", "2,3,0", "-2,3,0"}, "World XY", "1.1,2,0", null);
}
catch (TargetInvocationException tex)
{
  throw tex.InnerException;
}
7 Likes

A post was split to a new topic: Asynchronous issues with NodeInCode

Here is an example for Mass Addition:

1 Like

A few questions:

  1. By "node" do you mean "component"?
  2. Do you need grasshopper opened in order to access a component from Rhino PythonEditor?
  3. Do you need component to be instantiated (placed in the canvas) before you can access it this way?

“NodeInCode” is the trademark name of this feature. We do not mean something in particular. I guess whoever thought of this, could have had this in mind.

The answer is no. It was designed so that GH is started upon need.

Everything is handled automatically by the system.

1 Like

@piac, correct me if I’m wrong, but ideally this library will allow us to transform a GH algorithm into Rhino.python script. If developed further so it also can detect links between the components.

Also, create GH algorithm from Rhino PythonEditor.

That would be cool :slight_smile:

Yes it can be used with that purpose in mind.

This, it doesn’t currently do. Nor it creates a definition from a script.

How about this?
image

In the standardization process to give all components Python-compatible names, the space is removed. You can use auto-completion like so (this returns functions, not “ComponentInfo” objects):

image

So, print(rh.NodeInCode.Components.FindComponent("CullPattern") ) should work

1 Like

Thanks that’s it!

1 Like

Hello Everyone, and as always thanks to Giulio for your work.

I have a very silly question (not so silly for me sorry)… if I call a grasshopper component in C# and for instance, I get one of the different results that the component provides (through your point 1) example), I have some difficulties in using the “result”.

I mean if I want to recall the ConvexHull component and I want to grab the result[2] ( it is a list of integers)…

dynamic GHConvexHull ( Point3d Pts, Plane Plane)
{
    at some point in the code...
    var index=results[2]; 
 }
    return (index)

in the Main Code at some point:

var idPt=ConvexHull (Pts, Pl);

Now if I want to know the idPt length in the main code and apply the “.Count” definition (idPt.Count), I get this error below:

  1. ‘Grasshopper.DataTree’ does not contain a definition for ‘Count’ (line: 0)

So the “result” appears as Grasshopper.DataTree type, although I see this “result” as a list in the output variable.

This behaviour is extendible to all the object types that come by the Rhino NodeInCode function to recall the GH components inside a C# code (the C# GH component).

In Python, everything works like a charm (by importing ghpythonlib).

***I hope that some experts can share with me tips or solutions. ***
Thank you very much in advance!

It’s true, in fact DataTree(T) Class does not contain a definition of Count. You can get autocompletion by casting to the right type. I think this is going to be DataTree, if memory serves.

Thanks,

Giulio


Giulio Piacentino
for Robert McNeel & Associates
giulio@mcneel.com

Hello Everyone.
I use NodeinCode name DivideCurve but i have a problems. I want to used result[0] as List but it didn’t work. So how i can fix it, please tell me. Thanks


Hi @ngthanhlong82,

Instead of this:

foreach (var obj in result[0])

Try this:

foreach (var obj in result)

– Dale

Hi @dale . Thanks for helping me but i modifiled my code. The Result sitll problems.

Hi @ngthanhlong82,

Sorry - I am unable to read your screen capture.

I know NodeInCode is “cool”, but why not just call Curve.DivideByCount or Curve.DivideByLength, which is what GH does…

test_divide_curve.gh (8.0 KB)

– Dale

1 Like

Hi @dale . Thanks for answers me. I know 2 component as you told . But i want use this code to make something for me. I can use Method of Rhino" DivideByCount", but I curious about the NodeInCode. How to used it, so i try. Thanks.

I’d start by searching Discourse for NodeInCode.

Also, here are a couple of simple samples you can review. These scripts call the QuickHull component found in RhinoPolyhedra.

test_quickhull1.py (874 Bytes)

test_quickhull2.py (1.2 KB)

– Dale

Thanks @dale !


The result type is IronPython.Runtime.List,how to Convert to C#LIst?