Issue when porting an example sketch from the Hemesh library to Python mode

WB_Render3D::drawTriangle() got 6 overloaded versions of it:

And outta those 6, there are 2 w/ the 1 parameter signature that is a container:

And 1 w/ 1 parameter that is a single WB_Triangle:

Method WB_IsoSurface::getTriangles() returns a List<WB_Triangle>:

But if we call print type(triangles), we’ll find out its actual datatype is:
<type 'org.eclipse.collections.impl.list.mutable.FastList'>

Eclipse.org/collections/javadoc/9.0.0/org/eclipse/collections/impl/list/mutable/FastList.html

Now it seems like when we invoke render.drawTriangle(triangles), the overloaded signature chosen is:

Which causes processing.app.SketchException: java.lang.ClassCastException: wblut.geom.WB_Triangle cannot be cast to wblut.geom.WB_Coord

But what we’re looking for is this 1:

I’ve tried searching for some Jython builtin way to force a method invocation to pick a specific signature.

However, if there’s 1, it’s unpublished or it’s almost impossible to find!
As a workaround, I’ve attempted Java’s reflection capabilities.

  1. Class::getMethod():
    Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Class.html#getMethod(java.lang.String,java.lang.Class...)
  2. Method::invoke():
    Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/lang/reflect/Method.html#invoke(java.lang.Object,java.lang.Object...)

There’s a subtle diff. between the container parameter type signatures.
The 1 for WB_Coord is a List, but the 1 for WB_Triangle is a Collection.

So in order to grab the overloaded method signature we need we do like this:
method = WB_Render.getMethod('drawTriangle', Collection)

Now, inside draw(), we replace render.drawTriangle(triangles) w/ method.invoke(render, triangles).

Here’s the full sketch solution: :angel:

"""
 Ref_WB_IsoSurface (v1.0.1)
 ported by GoToLoop (2019-Feb-21)

 https://Discourse.Processing.org/t/
 issue-when-porting-an-example-sketch-from-the-
 hemesh-library-to-python-mode/8570/6
 
 https://GitHub.com/wblut/HE_Mesh/blob/master/examples/
 geom/isosurface/Ref_WB_IsoSurface/Ref_WB_IsoSurface.pde
"""

add_library('hemesh')

from java.util import Collection
METHOD = WB_Render.getMethod('drawTriangle', Collection)

DIM, N = 51, .07
DRANGE = tuple(range(DIM))

BG, FG, FILL = 070, 0, -1
FPS = 'FPS: '

def setup():
    size(800, 700, P3D)
    smooth(8)

    fill(FILL)
    stroke(FG)

    creator = WB_IsoSurface()

    creator.setSize(8, 8, 8)
    creator.isolevel = .6
    creator.boundary = -200
    creator.gamma = .3
    creator.invert = False

    creator.setValues(
        [[[noise(N*x, N*y, N*z) for z in DRANGE]
        for y in DRANGE] for x in DRANGE]
    )

    global render, triangles
    render, triangles = WB_Render(this), creator.triangles


def draw():
    background(BG)
    lights()

    translate(width>>1, height>>1)
    rotateY(TAU * mouseX / width)
    rotateX(TAU * mouseY / height)

    # render.drawTriangle(triangles) # invokes wrong sig!
    METHOD.invoke(render, triangles)

    this.surface.title = FPS + `this.round(frameRate)`
3 Likes