# Closed Mesh Area and Volume

**URL:** https://discourse.processing.org/t/closed-mesh-area-and-volume/15640
**Category:** Libraries
**Created:** [November 19, 2019, 7:54pm UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640 "2019-11-19T19:54:36Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![jNew](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jnew/32/7175_2.png) [@jNew](https://discourse.processing.org/u/jNew)
#### Post date: [November 19, 2019, 7:54pm UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640/1 "2019-11-19T19:54:36Z")

</div>

I am trying to slice a closed mesh and get the new surface area and volume.

HEMesh has a mesh.getArea() in the Ref\_HEM\_Soapfilm example, but the function does not exist in the library and I can’t find documentation for the HEMesh. Am I missing something?

Is there another library I should try for mesh splitting and analysis? I only see a way to split mesh by planes. Is there a way to split a mesh with another mesh?

Thanks for the help in advance. - J

---

<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: [November 22, 2019, 11:21pm UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640/2 "2019-11-22T23:21:48Z")

</div>

> [@jNew](#):
>
> Is there a way to split a mesh with another mesh?

Can you say more about what you mean? Like, given a sphere mesh and cube mesh, split the sphere into between one and seven parts, depending on how it intersects with the cube…?

---

<div class="post-metadata">

### Author: ![jNew](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jnew/32/7175_2.png) [@jNew](https://discourse.processing.org/u/jNew)
#### Post date: [November 26, 2019, 11:04pm UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640/3 "2019-11-26T23:04:22Z")

</div>

After doing more research, I found [CSG](https://en.wikipedia.org/wiki/Constructive_solid_geometry).  
I found a java library (JCSG) that I tried to use for mesh boolean operations, but I didn’t have any luck.

> [@jeremydouglass](#):
>
> an you say more about what you mean? Like, given a sphere mesh and cube mesh, split the sphere into between one and seven parts, depending on how it intersects with the cube…?

This is correct. I want to take two solids and either remove one from the other (difference), add one to the other (union), or get the overlap of the two (intersect). These are the typical boolean operations that I have in most 3d modeling environments.

---

<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: [November 27, 2019, 3:04am UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640/4 "2019-11-27T03:04:15Z")

</div>

Hi @jNew jNew,

I’m afraid JCSG doesn’t work well with Processing 3.

I gave it a try a few months ago and came to the conclusion that the library is not compatible. If I remember correctly, you can do some boolean operations with the bundled primitives (`Cube().toCSG`, `Sphere().toCSG`, …) and convert them to PShapes (as kindly described by GeorgeProfenza [here](https://stackoverflow.com/questions/56999816/is-it-possible-to-use-jcsg-library-with-processing)) but cannot do the opposite: converting a custom PShape to CSG format for transformation.

```auto
# Convert a CSG primitive to PShape (based on George Profenza example code)
def CSGToPShape(mesh, scl):
    
    pshape = createShape(GROUP)
    for p in mesh.getPolygons():
        face = createShape()
        face.beginShape()
        for v in p.vertices:
            face.vertex(v.pos.getX() * scl, v.pos.getY() * scl, v.pos.getZ() * scl)
        face.endShape()
        pshape.addChild(face)
    
    return pshape

# !! Doesn't work: tries to convert a PShape to CSG format for boolean operations
def PShapeToCSG(shp):
    
    polys = []
    for ic in xrange(shp.getChildCount()):
        c = shp.getChild(ic)
        verts = []
        for iv in xrange(c.getVertexCount()):
            v = c.getVertex(iv)
            verts.append(Vector3d(v.x, v.y, v.z))
        polys.append(Polygon.fromPoints(verts))
        
    return CSG.fromPolygons(polys)

```

Regarding Hemesh, Frederik Vanhoutte (the author) told me once that his library doesn’t support boolean operations.

---

<div class="post-metadata">

### Author: ![jNew](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jnew/32/7175_2.png) [@jNew](https://discourse.processing.org/u/jNew)
#### Post date: [November 27, 2019, 3:58pm UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640/5 "2019-11-27T15:58:23Z")

</div>

Thank you solub, this is what I experienced as well. I also found that JCSG uses a newer version of Java that Processing3 does not support, so I couldn’t use newer releases.

---

<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: [November 27, 2019, 5:59pm UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640/6 "2019-11-27T17:59:10Z")

</div>

> [@jNew](#):
>
> JCSG uses a newer version of Java that Processing3 does not support, so I couldn’t use newer releases

Perhaps the pre-Processing 4 private release, which is Java 11 compatible, would work for those recent JCSG releases…

---

<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: [November 29, 2019, 12:20am UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640/7 "2019-11-29T00:20:26Z")

</div>

@jNew a couple of questions:

- Are you working in 2D or in 3D ?
- Is there any particular reason why you want to do the boolean operation in Processing ? (instead of using a third-party software)

It’s probably unlikely but in case you work in 2D, the [Geomerative](http://www.ricardmarxer.com/geomerative/) library has a RPolygon class that allows boolean operations like `union()` or `diff()`.

If you have 3D meshes and your workflow requires to stick to Processing, there is also the possibility to communicate with a third-party software directly from your sketch. From what I understand you are into Computational Design so you might be familiar with Maya or Grasshopper. If so, you could:

- send you meshes to the software of your choice via UDP or TCP
- do the boolean operation
- save the output as an ‘.obj’ file and import it back to your sketch

Here below an example sketch using the [OscP5](http://www.sojamo.de/libraries/oscP5/) library to communicate with Grasshopper through the [gHowl](https://www.food4rhino.com/app/ghowl) component.

 ![Capture%20d%E2%80%99%C3%A9cran%20(286)](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/a/a5d1261232f5a329ceb35a5b4e75fbebc37230c8.png)

Please note that:

- the meshes should intersect the way you want before sending
- only low-poly meshes (\<1000 vertices) can be sent via UDP. If your meshes are denser, I would suggest to use FTP instead but unfortunately I can’t help you with this.

```auto
add_library('peasycam')
add_library('oscP5')

def setup():
    perspective(60 * DEG_TO_RAD, width/float(height), 2, 6000)
    size(1400, 800, P3D)
    smooth(8)
    
    global osc, shp3
    
    #Instantiate the PeasyCam/OscP5 libraries
    cam = PeasyCam(this, 80)
    osc = OscP5(this, 12000) 

    #the two shapes to be used for Boolean Operation
    shp1 = #YourFirstMesh 
    shp2 = #YourSecondMesh
    
    #computes the 'difference' mesh between shp1 and shp2
    mesh = transform([shp1, shp2])
    
    #convert the resulting mesh to a PShape object
    shp3 = meshToPShape(mesh)
    
    
    
def draw():
    background('#FFFFFF')
    
    shape(shp3)
    
    

    
def transform(shpList):
    
    '''Sends the meshes vertices to Grasshopper via UDP using the OscP5 library & gHowl component.
       The Grasshopper definition will then reconstruct the 2 meshes and perform the Boolean Operation of your choice (here "Mesh Difference").
       The resulting mesh is then converted to an .obj file through a C# script and exported to the location of your choice.
       Finally, Processing will import that mesh from the chosen location and return it for PShape conversion. '''
    
    net1 = NetAddress("127.0.0.1", 12001) #remote location for the 1st mesh
    net2 = NetAddress("127.0.0.2", 12002) #remote location for the 2nd mesh
    
    for i, net in enumerate([net1, net2]):
        message = OscMessage("/gHowlTest") 
        
        for child in shpList[i].getChildren():
            for iv in xrange(child.getVertexCount()):
                vert = child.getVertex(iv)
    
                message.add(str(vert.x))
                message.add(str(vert.y))
                message.add(str(vert.z))
                    
        osc.send(message, net)

    #Pausing the sketch for a moment because the '.obj' conversion in Grasshopper may take some time
    delay(1000) 
    
    return loadShape("C:/Select/Your/Path/TheFileName.obj")

def meshToPShape(m):
    
    '''Traverse the selected mesh and construct a PShape object from its faces/vertices'''
    
    shp = createShape(GROUP)
    for c in m.getChildren():
        face = createShape()
        face.beginShape(TRIANGLE)
        face.fill(int(random(30, 50)), int(random(180, 205)), int(random(170, 190)))
        for iv in xrange(c.getVertexCount()):
            v = c.getVertex(iv)
            face.vertex(v.x, v.y, v.z)
        face.endShape()
        shp.addChild(face)
    
    return shp

```

 ![Canvas%20at%2000%3B30%3B40](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/0/079944326b9b5274943146fa97bb3f898e98c87c.png)

[GH file](https://gofile.io/?c=qY9AJV)

---

<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: [November 30, 2019, 8:09pm UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640/8 "2019-11-30T20:09:21Z")

</div>

**Edit** : Giving it a second thought, it would make more sense to send the location of your meshes (as OBJ) instead of transmitting their vertices one by one. This way we can overcome the UDP transmission limitation and have a cleaner workflow.

The example sketch below will:

- convert the 2 base shapes to meshes (both triangular and quadrangular accepted)
- save them as OBJ in `\data` directory with the `HE_Mesh` exporter
- send the Boolean instruction to Grasshopper via UDP (`difference` or `union` or `intersection`)
- load the Grasshopper output as a `PShape`

\_\_

> **Processing Sketch**
>
> ```auto
> import os
> 
> add_library('peasycam')
> add_library('hemesh')
> add_library('oscP5')
> 
> def setup():
> perspective(60 * DEG_TO_RAD, width/float(height), 2, 6000)
> size(1600, 1000, P3D)
> smooth(8)
>     
> global shp3
>         
> cam = PeasyCam(this, 30)
> osc = OscP5(this, 6001)
> 
> shp1 = #Mesh1  
> shp2 = #Mesh2 
>     
> #Location of the future OBJ files
> directory = sketchPath("data")
>     
> #Convert meshes to OBJ and place them in directory
> toObj(shp1, "objName1", directory)
> toObj(shp2, "objName2", directory)
>     
> #Select Boolean Operation of your choice + send instruction via UDP
> operation = "difference" # -----> 'difference' or 'union' or 'intersection'
> filename = "meshDifference"
> osc.flush(directory + '\ ' + operation + ' ' + filename, "127.0.0.1", 6002)
>     
> #Wait for Rhino/Grasshopper to compute the transformation
> delay(8000)
>     
> #Load output + convert to PShape (not mandatory)
> shp = loadShape(sketchPath(filename + '.obj'))
> shp3 = toPShape(shp)
>         
> 
>     
>     
> def draw():
> background('#FFFFFF')
> shape(shp3)
> 
>     
> 
>     
> def toObj(shp, filename, directory):
>     
> '''Traverse the selected mesh and construct a HE_Mesh from its faces.
> The output will be saved as an OBJ in the chosen directory. '''
> 
> #Create 'data' directory if not existent
> if not os.path.isdir(directory):
> os.mkdir(directory)
>         
> #Detect face type (triangular vs quandragular faces)
> type = 'triangular' if shp.getChild(0).getVertexCount() == 3 else 'quadrangular'
>     
> #Reconstruct mesh from faces
> temp = []
> for child in shp.getChildren():
> face = []
> for i in xrange(child.getVertexCount()):
> v = child.getVertex(i)
> face.append(WB_Point(v.x, v.y, v.z))
>             
> if type == 'triangular':
> a, b, c = face
> tri = WB_Triangle(a, b, c)
> temp.append(tri)
> else:
> a, b, c, d = face
> qua = WB_Quad(a, b, c, d)
> temp.append(qua)
>             
> #Convert to HE_Mesh mesh format      
> if type == 'triangular':
> mesh = HE_Mesh(HEC_FromTriangles().setTriangles(temp))
> else:
> mesh = HE_Mesh(HEC_FromQuads().setQuads(temp))
>         
> #Export to OBJ in 'data' directory
> HET_Export.saveToOBJ(mesh, directory, filename)
>     
>     
>     
> def toPShape(s):
>     
> '''Traverse the selected mesh and construct a PShape object from its faces/vertices'''
>     
> shp = createShape(GROUP)
> for c in s.getChildren():
> face = createShape()
> face.beginShape(TRIANGLE)
> face.fill(int(random(30, 50)), int(random(180, 205)), int(random(170, 190)))
> for iv in xrange(c.getVertexCount()):
> v = c.getVertex(iv)
> face.vertex(v.x, v.y, v.z)
> face.endShape()
> shp.addChild(face)
>     
> return shp
> 
> ```

¯¯

On the Grasshopper side, as soon as the Boolean Operation instruction is received, the GhPython component will automatically:

- find the saved OBJs
- convert them to Rhino meshes
- compute the desired transformation (`difference` or `union` or `intersection`)
- save the output as an OBJ (with triangular faces)

\_\_

> **GhPython script**
>
> ```auto
> import os
> import Rhino.Geometry as rg
> 
> directory, operation, filename = iMessage.split()
> meshes = [rg.Mesh(), rg.Mesh()]
> 
> def toMesh(path, i):
>     
> with open(path) as f:
> for l in f:
> if l.startswith('v '):
> x, y, z = map(float, l.split()[1:])
> meshes[i].Vertices.Add(rg.Point3d(x, y, z))
>                 
> elif l.startswith('f '):
> face = [int(e.split('/')[0])-1 for e in l.split()[1:]]
> if len(face) == 3:
> meshes[i].Faces.AddFace(rg.MeshFace(face[0], face[1], face[2]))
> else:
> meshes[i].Faces.AddFace(rg.MeshFace(face[0], face[1], face[2], face[3]))
>                     
> meshes[i].Normals.ComputeNormals()
> meshes[i].Compact()
> rg.Collections.MeshFaceList.ConvertQuadsToTriangles(meshes[i].Faces)
> 
> def toObj(mesh):
>     
> newDirectory = directory.split('data')[0]
> print newDirectory
>     
> if not os.path.isdir(newDirectory):
> os.mkdir(newDirectory)
>     
> filepath = newDirectory + "%s" % filename + ".obj"
>     
> with open(filepath, 'w') as f:
> f.write("# OBJ file\n")
> for vert in mesh.Vertices:
> f.write('v ' + "%s %s %s\n" % tuple([vert.X, vert.Y, vert.Z]))
>             
> for face in mesh.Faces:
> if face.IsTriangle:
> ids = map(lambda x: str(x+1) + '//' + str(x+1), [face.A, face.B, face.C])
> f.write('f ' + ("%s %s %s\n") % tuple(ids))
> elif face.IsQuad:
> ids = map(lambda x: str(x+1) + '//' + str(x+1), [face.A, face.B, face.C, face.D])
> f.write('f ' + ("%s %s %s %s\n") % tuple(ids))
> 
> def run():
> global oMesh
>     
> objs = [file for file in os.listdir(directory) if file.endswith('.obj')]
> for i, obj in enumerate(objs):
> path = directory + obj
> toMesh(path, i)
>         
> if operation == 'difference':
> oMesh = rg.Mesh.CreateBooleanDifference([meshes[0]], [meshes[1]])
> elif operation == 'intersection':
> oMesh = rg.Mesh.CreateBooleanIntersection([meshes[0]], [meshes[1]])
> elif operation == 'union':
> oMesh = rg.Mesh.CreateBooleanUnion(meshes)
>     
> toObj(oMesh[0])
> 
> run()
> 
> ```

¯¯

Definition + Gh file

 ![Canvas%20at%2020%3B29%3B04](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/9/9f57f80d8638c54c6ff6ba4660a86ae553faa8db.png)  
[Gh file](https://filebin.net/04n1w25kxipot0q2)

Below an example with 2 meshes (woman face + roman bust) converted to OBJ in Processing and retrieved by Grasshopper after UDP transmission of their locations. The instruction sent for boolean operation is: `difference`

 ![Capture%20d%E2%80%99%C3%A9cran%20(294)](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/4/4611cd4e809d7fb2608b7cb08529f33eb4f65cbd.png)

The output loaded back in Processing:

 ![ss217](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/6/6f650717a4cc637cd1f4c7903fc624932d03efc4.jpeg)

---

<div class="post-metadata">

### Author: ![jNew](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jnew/32/7175_2.png) [@jNew](https://discourse.processing.org/u/jNew)
#### Post date: [December 2, 2019, 2:07pm UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640/9 "2019-12-02T14:07:37Z")

</div>

I appreciate all the input, but I am trying to make a stand alone app. If I was making the app for myself, I would just develop it as a plugin for Rhino.

It looks like I will not be using processing for the development anymore… back to C++.

---

<div class="post-metadata">

### Author: ![jNew](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jnew/32/7175_2.png) [@jNew](https://discourse.processing.org/u/jNew)
#### Post date: [December 2, 2019, 2:50pm UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640/10 "2019-12-02T14:50:36Z")

</div>

I am considering C++ because it has VTK. Upon further investigation, VTK actually has a java wrapper. I might try using this with processing. VTK has some really nice 3D tools.

---

<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: [December 2, 2019, 4:19pm UTC](https://discourse.processing.org/t/closed-mesh-area-and-volume/15640/11 "2019-12-02T16:19:17Z")

</div>

I see. Don’t know if that’s relevant in your case but it seems the CGAL library also has a [SWIG interface](https://github.com/CGAL/cgal-swig-bindings) for Java.
