Dynamo crashed when trying node to code with the node Curve.IntersectAll from BimorphNodes

When i try node to code with the node Curve.IntersectAll from BimorphNodes dynamo crashed @Thomas_Mahon
That node works much better than the OOTB node. It would be wonderful if it can be used in code blocks

this is the warning:
Object reference not set to an instance of an object.

at ProtoCore.Utils.CoreUtils.CreateNodeFromString(String name)
at Dynamo.Engine.NodeToCode.ShortestQualifiedNameReplacer.CreateNodeFromShortName(String className, String qualifiedName)
at Dynamo.Engine.NodeToCode.ShortestQualifiedNameReplacer.RewriteNodeWithShortName(IdentifierListNode node)
at Dynamo.Engine.NodeToCode.ShortestQualifiedNameReplacer.VisitIdentifierListNode(IdentifierListNode node)
at ProtoCore.SyntaxAnalysis.AstReplacer.VisitBinaryExpressionNode(BinaryExpressionNode node)
at Dynamo.Engine.NodeToCode.NodeToCodeCompiler.ReplaceWithShortestQualifiedName(ClassTable classTable, IEnumerable`1 asts, ElementResolver resolver)
at Dynamo.Graph.Workspaces.NodesToCodeExtensions.ConvertNodesToCodeInternal(WorkspaceModel workspace, EngineController engineController, INamingProvider namingProvider)
at Dynamo.Models.DynamoModel.ConvertNodesToCodeImpl(ConvertNodesToCodeCommand command)
at Dynamo.Models.DynamoModel.ExecuteCommand(RecordableCommand command)
at MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource, Boolean userInitiated)
at System.Windows.Controls.MenuItem.InvokeClickAfterRender(Object arg)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

Hi @Nico_Stegeman are you able to share some test files which reproduce the bug so I can look into it (thanks for the feedback too!)? DM me if they are confidential.

Also, you should be able to call it in a codeblock using BimorphNodes.Curve.IntersectAll() but let me know if thats not the case.

Hi @Thomas_Mahon in a very simple graph i have this problem also.
Here is a dyn file.
I am also not able to call it in a codeblock using BimorphNodes.Curve.IntersectAll()

I use the most recent install of Bimorph
I have Dynamo Revit 2.0.3.8107 and Revit 2019.2 installed

BimorphIntersectAllTest.dyn (12.8 KB)

Thanks Nico,

Firstly I tested in 2019.2, Dynamo 2.0.2.7833 and BimorphNodes 2.5.1 and everything appears to be working. Is there anything in particular you do which triggers the exception? Note that the node converts all Dynamo lines into Revit API lines and back again, so it might be a particular curve type which is failing conversion which may help you to isolate the problem.

And to call Curve.IntersectsAll n DS you just need to pass a 1D list into the input. You shouldn’t need to qualify the Curve class as its in a different namespace to the class of the same name in Dynamo’s ProtoGeometry library, but there’s no harm in qualifying the class (i.e. adding BimorphNodes.Curve…) in the unlikely event that either BimorphNodes or ProtoGeometry libraries change in the future:

Thanks Thomas

I still can not use node to code. But i keep on trying to find the problem.

When i type it in the code block works. But i get a warning.
And when i type BimorphNodes before Curve.IntersectAll it doesnt work. It doesn’t reconize it

Hmm, ok this is a major drawback in Dynamo it seems, as it shouldn’t be clashing. Incidentally I managed to hack it, by qualifying the class from Dynamo’s own library (ProtoGeometry). At least, I think this is whats happening given that the Curve class in the ProtoGeometry library has no method called IntersectAll. Geometry class does however, but it takes two inputs, not one so I’m not sure if there is something else going on here (Edit: it looks like the IntersectAll method from Dynamo’s geometry class is the one being called here).

cc @Michael_Kirschner2 this looks like a major flaw/bug in Dynamo. I take it this is not dynamic dispatch at play but some other magic Dynamo’s VM is performing. Does it collate the same imported class names under one alias - see my edit above, I think I’ve solved my own theory, in which case, can you suggest a solution?:

Also, node to code with BimorphNodes Curve.IntersectAll throws a fatal exception.

Hello @Thomas_Mahon and @Michael_Kirschner2
Maybey off topic but
this all started because in a graph of mine the OOTB node Geometry.Intersect didn,t worked. So i wanted it to replace it with the bimorph node .
In another graph it always works well. The both graphs are almost identical.
it doesn’t matter if i use Geometry.Intersect in a code block or just with Nodes.

The files are confidential. So I will send it in a pm

Nico

Hi @Thomas_Mahon what version of Dynamo is this example from?

Old versions of Dynamo could call across types based on the input type and function name - and would look for functions with matching names even on the wrong (not in the inheritance chain) type… this was removed (because like are you finding it is too confusing once conflicts occur between function names) in Dynamo 2.x You might be seeing that here if you’re in 1.3.

Instead most methods are now compiled down to static functions before they are called so the specific function should be known.

I’m not sure if it should have also appeared when using code blocks though… @Aparajit_Pratap thoughts? - or are you only finding the issue when using nodes directly (not calling them in code blocks)?

Hi @Michael_Kirschner2 it was 2.0.2 in Revit 2019. It doesn’t look like there is anyway to qualify the class without modifying the BimorphNode codebase, but I wouldn’t have thought this is necessary considering the namespaces I’m using are distinct from ProtoGeometry? Is this a different problem or the historic issue which has blighted external libraries?

Hi @Thomas_Mahon I think I’m starting to go in circles. Can you tell me which function in a codeblock you are finding is getting confused between your methods and the protogeometry ones?
Ie What you expect to happen and what happened?

I looked at @Nico_Stegeman’s files and inside the elementResolver and Curve is mapped to the protogeometry namespace there as an alias, so when he types Curve - he really gets something like Autodesk.Designscript.Geometry.Curve.

In the original screenshot, it’s very odd that the bimorphNodes namespace is seen as an unbound variable…

Hi @Michael_Kirschner2: Calling BimorphNodes Curve.IntersectAll in a code block. I think the issue is twofold: as my Curve class has a method called IntersectAll and the ProtoGeometry library has its Geometry (base?) class with a method also called IntersectAll, I’m guessing that calling Curve.IntersectAll() using DS is ambiguous as it could refer to either BimorphNodes or the downcast from ProtoGeometry.Curve to execute the call to Geometry.IntersectAll?

This would explain why Autodesk.DesignScript.Geometry.Curve.IntersectAll() resolves to the ProtoGeometry, but there is no means of achieving this in a code block using BimorphNodes as the class is not in a namespace (purely to achieve the desired library structure as I had no luck using the custom node category XML).

I suppose the ‘solution’ is, create a namespace? Not unless you can suggest an alternative?

@Thomas_Mahon - what is the fully qualified name of your Curve.IntersectAll method? - is it just Curve.IntersectAll ?

Its not in a namespace, so yes, Curve.IntersectAll()!

@Thomas_Mahon, you’re right in observing that your class “Curve” conflicts with “Autodesk.DesignScript.Geometry.Curve” but if you type “Curve.IntersectAll(list_of_curves);”, in a code block, it should resolve unambiguously and call your method from Bimorph package, not “Autodesk.DesignScript.Geometry.Geometry.IntersectAll” as the “Geometry.IntersectAll(Geometry, Geometry)” accepts 2 parameters and not one. That is why typing “Curve.IntersectAll(list_of_curves);” in a code block node works (by calling your method). @Nico_Stegeman, it should also work using NodeToCode, which it does not and is a bug. We’ll make a note of this.

1 Like

Also you’re right in saying that Bimorph Curve class does not belong to any namespace so prefixing “BimorphNodes” to it is not going to work.

@Aparajit_Pratap thanks for the clarification. I initially thought there was no way that there would be any ambiguity since Geometry.IntersectAll takes two inputs as you’ve rightly pointed out…but this is the dodgy thing with DesignScript - which I really don’t find very useful - all methods are static and non-static if I am not mistaken, and therein lies the problem because you can call Geometry.IntersectAll with 1 input if you call it on a curve instance?

I did the following tests and discovered:
Dynamo 1.3 works in code block and node-to-code works without any issues
Dynamo 2.0 ambiguous reference (fails) in code block and node-to-code causes a fatal exception
Dynamo 2.1 works in code block and node-to-code works without any issues

2 Likes

Thanks @Thomas_Mahon, for testing this behaviour in all 3 versions. We’ll track this and make sure it continues to work as expected.

To your point about instance (non-static) and static methods, we recognized that not all users were familiar with these concepts and therefore found it confusing. In order to therefore make their usage in DesignScript consistent with their node counterparts, we decided to make all methods; even instance methods, callable as static methods in 2.0. Prior to that, a node like Geometry.IntersectAll that took 2 inputs - Geometry, and Geometry[] could only be invoked in DesignScript as an instance method - geometry.IntersectAll(list_geometries), a method that took an object (or instance) and 1 input. This, as you can see was also confusing. So we decided to allow for these methods to be also callable as - Geometry.IntersectAll(Geometry, Geometry[]) to look like the node; in other words static methods.

Having done so, we also needed to avoid breaking the language and ended up keeping instance methods in DS as well, which now gives users the “choice” (confusion) of calling the same method as either an instance method or a static method. Yes, I agree this is somewhat counter-intuitive to other languages but it’s what we chose to end up doing.

1 Like

Thanks Thomas and Aparajit

I am going to update to 2.1 and mark it as the solution