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

**URL:** <https://discourse.processing.org/t/issue-when-porting-an-example-sketch-from-the-hemesh-library-to-python-mode/8570>\
**Category:** Processing.py\
**Created:** [February 20, 2019, 5:25pm UTC](https://discourse.processing.org/t/issue-when-porting-an-example-sketch-from-the-hemesh-library-to-python-mode/8570 "2019-02-20T17:25:50Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![solub](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/solub/32/333_2.png) [@solub](https://discourse.processing.org/u/solub)\
**Post date:** [February 20, 2019, 5:25pm UTC](https://discourse.processing.org/t/issue-when-porting-an-example-sketch-from-the-hemesh-library-to-python-mode/8570/1 "2019-02-20T17:25:50Z")

</div>

Hi,

For some reason I get a `ClassCastException` error when porting [this sketch](https://github.com/wblut/HE_Mesh/blob/master/examples/hemesh/create/Ref_HEC_IsoSurface/Ref_HEC_IsoSurface.pde) (code below) to Python mode.

> processing.app.SketchException: java.lang.ClassCastException: wblut.geom.WB\_Triangle cannot be cast to wblut.geom.WB\_Coord

For comparison, the original code:

```auto
import wblut.math.*;
import wblut.processing.*;
import wblut.core.*;
import wblut.hemesh.*;
import wblut.geom.*;

HE_Mesh mesh;
WB_Render render;

void setup() {
  size(1000,1000,P3D);
  smooth(8);

// Create an isosurface from an explicit grid of values.
// Potentially uses a lot of memory.

  float[][][] values=new float[51][51][51];
  for (int i = 0; i < 51; i++) {
    for (int j = 0; j < 51; j++) {
      for (int k = 0; k < 51; k++) {
        values[i][j][k]=noise(0.07*i, 0.07*j, 0.07*k);
      }
    }
  }

  HEC_IsoSurface creator=new HEC_IsoSurface();
  creator.setResolution(50, 50,50);// number of cells in x,y,z direction
  creator.setSize(8, 8, 8);// cell size
  creator.setValues(values);// values corresponding to the grid points
  // values can also be double[][][]
  creator.setIsolevel(.6);// isolevel to mesh
  creator.setInvert(false);// invert mesh
  creator.setBoundary(-200);// value of isoFunction outside grid
  // use creator.clearBoundary() to rest boundary values to "no value".
  // A boundary value of "no value" results in an open mesh
  
  //Gamma controls level of grid snap, 0.0-0.5. Can improve the 
  //quality of the triangles, but can give small changes in topology.
  creator.setGamma(0.3); 
  

  mesh=new HE_Mesh(creator);

  render=new WB_Render(this);
}

void draw() {
  background(55);
  lights();
  translate(width/2, height/2);
  rotateY(mouseX*1.0f/width*TWO_PI);
  rotateX(mouseY*1.0f/height*TWO_PI);
  noStroke();
  render.drawFaces(mesh);
  stroke(0);
  render.drawEdges(mesh);
}

```

In Python:

```auto
add_library('hemesh')

def setup():
    size(1000, 600, P3D)
    smooth(8)
    
    locations = [[[noise(0.07 * x, 0.07*y, 0.07*z) for z in range(51)] for y in range(51)] for x in range(51)]
    
    creator = WB_IsoSurface()
    creator.setSize(8, 8, 8)
    creator.setValues(locations)
    creator.setIsolevel(.6)
    creator.setInvert(False)
    creator.setBoundary(-200)
    creator.setGamma(.3)
    
    global triangles, render
    triangles = creator.getTriangles()
    render = WB_Render(this)
    
def draw():
    background(12)
    
    render.drawTriangle(triangles)

```

Do you have an idea of what could possibly be the issue here ?

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [February 21, 2019, 1:52pm UTC](https://discourse.processing.org/t/issue-when-porting-an-example-sketch-from-the-hemesh-library-to-python-mode/8570/2 "2019-02-21T13:52:57Z")

</div>

Your port is using WB\_IsoSurface instead of HEC\_IsoSurface used by the original sketch.

I still haven’t dug why your WB\_IsoSurface fails.  
But I did a Python Mode port of the original using HEC\_IsoSurface.

Actually I did 2 versions: A java-ish and a pythonic.

The java-ish 1 uses an actual `double[][][]` array w/ a triple loop.  
While the pythonic 1 uses a 3d list comprehension as you did too.

## “Ref\_HEC\_IsoSurface\_Javaish.pyde”:

```auto
"""
 Ref_HEC_IsoSurface (Java-ish version) (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/2

 https://GitHub.com/wblut/HE_Mesh/blob/master/examples/
 hemesh/create/Ref_HEC_IsoSurface/Ref_HEC_IsoSurface.pde
"""

add_library('hemesh')

from java.lang.reflect import Array
from java.lang import Double

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

BG, FG = 070, 0
FPS = 'FPS: '

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

    creator = HEC_IsoSurface()

    creator.setResolution(50, 50, 50)
    creator.setSize(8, 8, 8)
    creator.setIsolevel(.6)
    creator.setBoundary(-200)
    creator.setGamma(.3)
    creator.setInvert(False)

    arr3d = Array.newInstance(Double.TYPE, DIM, DIM, DIM)
    creator.setValues(arr3d)

    for z, arr2d in enumerate(arr3d):
        for y, arr1d in enumerate(arr2d):
            for x in DRANGE: arr1d[x] = noise(N*x, N*y, N*z)

    global render, mesh
    render, mesh = WB_Render(this), HE_Mesh(creator)

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

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

    noStroke()
    render.drawFaces(mesh)

    stroke(FG)
    render.drawEdges(mesh)

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

```

## “Ref\_HEC\_IsoSurface\_Pythonic.pyde”:

```auto
"""
 Ref_HEC_IsoSurface (Pythonic version) (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/2

 https://GitHub.com/wblut/HE_Mesh/blob/master/examples/
 hemesh/create/Ref_HEC_IsoSurface/Ref_HEC_IsoSurface.pde
"""

add_library('hemesh')

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

BG, FG = 070, 0
FPS = 'FPS: '

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

    creator = HEC_IsoSurface()

    creator.setResolution(50, 50, 50)
    creator.setSize(8, 8, 8)
    creator.setIsolevel(.6)
    creator.setBoundary(-200)
    creator.setGamma(.3)
    creator.setInvert(False)

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

    global render, mesh
    render, mesh = WB_Render(this), HE_Mesh(creator)

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

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

    noStroke()
    render.drawFaces(mesh)

    stroke(FG)
    render.drawEdges(mesh)

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

```

---

<div class="post-metadata">

**Author:** ![solub](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/solub/32/333_2.png) [@solub](https://discourse.processing.org/u/solub)\
**Post date:** [February 21, 2019, 3:01pm UTC](https://discourse.processing.org/t/issue-when-porting-an-example-sketch-from-the-hemesh-library-to-python-mode/8570/3 "2019-02-21T15:01:54Z")

</div>

Sweet, clever workaround ! (Thanks)

The `ClassCastException` error from the `getTriangles()` function is still a mystery though.

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [February 21, 2019, 3:05pm UTC](https://discourse.processing.org/t/issue-when-porting-an-example-sketch-from-the-hemesh-library-to-python-mode/8570/4 "2019-02-21T15:05:22Z")

</div>

Do you have a Java Mode example using WB\_IsoSurface? 😀

---

<div class="post-metadata">

**Author:** ![solub](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/solub/32/333_2.png) [@solub](https://discourse.processing.org/u/solub)\
**Post date:** [February 21, 2019, 3:55pm UTC](https://discourse.processing.org/t/issue-when-porting-an-example-sketch-from-the-hemesh-library-to-python-mode/8570/5 "2019-02-21T15:55:05Z")

</div>

I just realized the Java example sketch I posted is different from the one in the Hemesh examples folder on my computer (the one with `WB_IsoSurface` that I was trying to port to Python mode !). Here it is:

```auto
List<WB_Triangle> triangles;
WB_Render render;

void setup() {
  size(1000,1000,P3D);
  smooth(8);

  float[][][] values=new float[51][51][51];
  for (int i = 0; i < 51; i++) {
    for (int j = 0; j < 51; j++) {
      for (int k = 0; k < 51; k++) {
        values[i][j][k]=noise(0.07*i, 0.07*j, 0.07*k);
      }
    }
  }

  WB_IsoSurface creator=new WB_IsoSurface();
  creator.setSize(8, 8, 8);
  creator.setValues(values);

  creator.setIsolevel(.6);
  creator.setInvert(false);
  creator.setBoundary(-200);// value outside grid
  // use creator.clearBoundary() to rest boundary values to "no value".
  // A boundary value of "no value" results in an open mesh
  
  //Gamma controls level of grid snap, 0.0-0.5. Can improve the 
  //quality of the triangles, but can give small changes in topology.
  //For 3D, gamma=0.3 is a good value.
  creator.setGamma(0.3); 
  
  triangles=creator.getTriangles();
  render=new WB_Render(this);
}

void draw() {
  background(55);
  lights();
  translate(width/2, height/2);
  rotateY(mouseX*1.0f/width*TWO_PI);
  rotateX(mouseY*1.0f/height*TWO_PI);
  fill(255);
  stroke(0);
  render.drawTriangle(triangles);
}

```

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [February 22, 2019, 12:35am UTC](https://discourse.processing.org/t/issue-when-porting-an-example-sketch-from-the-hemesh-library-to-python-mode/8570/6 "2019-02-22T00:35:10Z")

</div>

WB\_Render3D::**drawTriangle()** got 6 overloaded versions of it:

> <https://github.com/wblut/HE_Mesh/blob/4d7c02a9775429c8f7c1872194b8a7aadd038f08/src/processing/wblut/processing/WB_Render3D.java#L3475-L3553>

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

> <https://github.com/wblut/HE_Mesh/blob/4d7c02a9775429c8f7c1872194b8a7aadd038f08/src/processing/wblut/processing/WB_Render3D.java#L3475-L3476>

> <https://github.com/wblut/HE_Mesh/blob/4d7c02a9775429c8f7c1872194b8a7aadd038f08/src/processing/wblut/processing/WB_Render3D.java#L3500-L3500>

And 1 w/ 1 parameter that is a single WB\_Triangle:

> <https://github.com/wblut/HE_Mesh/blob/4d7c02a9775429c8f7c1872194b8a7aadd038f08/src/processing/wblut/processing/WB_Render3D.java#L3547-L3547>

Method WB\_IsoSurface::**getTriangles()** returns a List\<WB\_Triangle\>:

> <https://github.com/wblut/HE_Mesh/blob/4d7c02a9775429c8f7c1872194b8a7aadd038f08/src/geom/wblut/geom/WB_IsoSurface.java#L405-L421>

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](http://Eclipse.org/collections/javadoc/9.0.0/org/eclipse/collections/impl/list/mutable/FastList.html)

> <https://github.com/wblut/HE_Mesh/blob/4d7c02a9775429c8f7c1872194b8a7aadd038f08/src/geom/wblut/geom/WB_IsoSurface.java#L154-L154>

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

> <https://github.com/wblut/HE_Mesh/blob/4d7c02a9775429c8f7c1872194b8a7aadd038f08/src/processing/wblut/processing/WB_Render3D.java#L3500-L3500>

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:

> <https://github.com/wblut/HE_Mesh/blob/4d7c02a9775429c8f7c1872194b8a7aadd038f08/src/processing/wblut/processing/WB_Render3D.java#L3475-L3476>

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...)](http://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...)](http://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: 👼

```auto
"""
 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)`

```

---

<div class="post-metadata">

**Author:** ![solub](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/solub/32/333_2.png) [@solub](https://discourse.processing.org/u/solub)\
**Post date:** [February 22, 2019, 12:41pm UTC](https://discourse.processing.org/t/issue-when-porting-an-example-sketch-from-the-hemesh-library-to-python-mode/8570/7 "2019-02-22T12:41:14Z")

</div>

Thanks a ton for the comprehensive explanation.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [February 23, 2019, 6:49pm UTC](https://discourse.processing.org/t/issue-when-porting-an-example-sketch-from-the-hemesh-library-to-python-mode/8570/8 "2019-02-23T18:49:59Z")

</div>

> [@GoToLoop](#):
>
> So in order to grab the overloaded method signature […] Here’s the full sketch solution:

bravo 👏 👏 👏
