Kangaroo2 MeshCorners: exception on meshes without naked edges

Tested in Rhino 7.38 (IronPython 2.7.12), Rhino 8.35 (CPython 3.9.10) and Rhino 9.0.26251.12303 (WIP, CPython 3.13.13), Windows x64, each with the Kangaroo2Component 2.5.3.0 that ships with it. The attached script builds all meshes itself, runs the real component (through ghpythonlib and on a GH_Document, as on the canvas) and judges every result against the expected answer, never against another Rhino version. It runs unmodified in all three versions and leaves the scene shown in the screenshot in the document.

What happens

Kangaroo2 > Mesh > MeshCorners throws a NullReferenceException for every mesh without naked edges, at every angle. On the canvas the component turns red (Error) with Solution exception: Object reference not set to an instance of an object. The message does not mention naked edges or closed meshes.

With a list input, Grasshopper stops the component at the exception. Items before the closed mesh get corners; the closed mesh and every item after it get nothing, so a closed mesh at the start of the list loses the whole list. In a typical definition (several meshes from one layer, one of them closed) this looks like valid meshes silently losing their corners.

The behaviour is identical in all three versions.

Reproduction

  1. Put any closed mesh, e.g. from Mesh Box, into MeshCorners, any angle.
  2. The component turns red with the message above.
  3. Feed one list [open mesh, closed mesh, open mesh]: only the first mesh gets corners.

The attached script runs every case below and prints PASS / FAIL for each check.

Measurement

15 test meshes × 7 angles (0.5, 1.0, 1.6, 2.0, 2.5, 3.0, 3.5 rad) through ghpythonlib:

                                              Rhino 7.38   Rhino 8.35   Rhino 9 WIP
7 meshes without naked edges: exception       49 / 49      49 / 49      49 / 49
8 meshes with naked edges: exception           0 / 56       0 / 56       0 / 56
GetNakedEdges() on the 7 meshes                null         null         null
missing (null) mesh input                      exception    exception    exception

Meshes without naked edges: tetrahedron, welded box, unwelded box, sphere, capped cylinder, empty mesh, one vertex without faces. Meshes with naked edges: triangle, quad, 3×3 grid, L-shape, grid with a hole, pentagon fan, star, open box.

List input on a GH_Document, angle 1.6 rad, same in all three versions:

item                                current                     expected
A       12×12 quad grid, open       4 corners                   4 corners
Column  capped cylinder, closed     exception (level Error)     empty list, no error
B       L-shaped grid, open         no output                   6 corners
C       grid with atrium, open      no output                   8 corners

Expected is what the component returns for each open mesh fed on its own, and an empty list for the closed mesh. With the closed mesh first in the list, no item gets output.

The screenshot shows this list: row 1 is the current result, row 2 the expected one. Meshes with corners are relaxed with a simple spring model for illustration only, not with the Kangaroo solver.

Possible lead

The exception is thrown in Kangaroo2Component.UtilityComponents.MeshCorners.SolveInstance(IGH_DataAccess DA) (first-chance exception). For every mesh that triggers it, Mesh.GetNakedEdges() returns null rather than an empty array, and the component works for every mesh where it returns an array. This suggests the result of GetNakedEdges() is used without a null check. A missing mesh throws in the same method, which suggests the result of DA.GetData is not checked either. If so, checking both would remove both exceptions. This is an inference from measurements only.

Expected

An empty list for a mesh without naked edges, no error, and normal results for the other items of a list.

Workaround

Keep only meshes with at least one naked edge before MeshCorners: Mesh Edges → List Length of E1 → Larger Than 0 → Dispatch. Filter on the naked-edge count, not on “closed”, because empty meshes and meshes without faces are not closed but fail too. Clean Tree removes null items, which also fail.

Separately

Lower priority, measured in all three versions with identical results, for your judgement:

  • Concave boundary vertices. The 270° vertex of a planar L-shape is returned as a corner at 1.6 rad, and so are the four corners of a hole. The input description says Interior angle below which a vertex is considered a corner. This may be intended (columns at re-entrant corners); if so, the description could say so.
  • Non-manifold meshes only. Where an edge is shared by three faces, a vertex whose two naked edges meet at 90° is returned at 1.0 rad (57°). A vertex joining two naked loops (bowtie) can be returned twice; in the tested bowtie the naked polyline runs straight through that vertex, so it only qualifies above π (1 duplicate at 3.5 rad).
  • Angle unit. The angle input is a plain Number in radians with a default of 2.3562 (3π/4); the description does not mention the unit. An angle typed in degrees (90) returns every naked vertex (12 of 12 on a 3×3 grid) without a warning.
  • Similar behaviour elsewhere. TriRemesh throws a NullReferenceException on an open curve; NakedVertices and Conicalize throw a NullReferenceException on a mesh with vertices but no faces (for that mesh GetNakedEdgePointStatus() returns null). Possibly related threads: TriReMesh – Object reference not set and Nakedvertices error.

Python script: meshcorners_bugreport.py (38.6 KB)