Generating a voxel representation of a CAD model

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
hestenes
Posts: 6
Joined: Wed Aug 01, 2018 8:56 pm

Generating a voxel representation of a CAD model

Post by hestenes »

In my project, I am trying to voxelize a 3D CAD model to a (lets say a30 x 30 x 30) voxel grid.

I have a collection of models in STEP file format, which I am able to load into FreeCAD. Below is my current plan.

Create a bounding box around cad model, divide the box into voxels, do a boolean intersection of each voxel with CAD model geometry, and return the fraction of voxel filled by the model for each voxel.

Parts workbench has the boolean operations I need, but since I am very new to FreeCAD, I wanted to know what people here think.

I would like to find out if someone here have previously done voxelization in FreeCAD, if so what was your approach.
Last edited by hestenes on Mon Aug 06, 2018 6:25 pm, edited 1 time in total.
User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: Generating a voxel representation of a CAD model

Post by Kunda1 »

Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
hestenes
Posts: 6
Joined: Wed Aug 01, 2018 8:56 pm

Re: Generating a voxel representation of a CAD model

Post by hestenes »

Kunda1 wrote: Mon Aug 06, 2018 6:24 pm related: https://forum.freecadweb.org/viewtopic.php?t=20013
Thanks for sharing that post. I did look at that post, during my research on how to approach my problem using FreeCAD. That workbench is specifically for drawing using voxels.

My project instead is voxelizing a given 3D model.
UR_
Veteran
Posts: 1355
Joined: Tue Jan 03, 2017 8:42 pm

Re: Generating a voxel representation of a CAD model

Post by UR_ »

User avatar
sgrogan
Veteran
Posts: 6499
Joined: Wed Oct 22, 2014 5:02 pm

Re: Generating a voxel representation of a CAD model

Post by sgrogan »

hestenes wrote: Mon Aug 06, 2018 6:28 pm My project instead is voxelizing a given 3D model.
Maybe this offers some insight. https://forum.freecadweb.org/viewtopic. ... 10#p136893
"fight the good fight"
hestenes
Posts: 6
Joined: Wed Aug 01, 2018 8:56 pm

Re: Generating a voxel representation of a CAD model

Post by hestenes »

Thanks for the links.

To put more context, here is an example of what I am trying to do,

This is a simple rectangular plate with a hole.
before_voxel.png
before_voxel.png (14.88 KiB) Viewed 5143 times
Below is a visualization of volume fractions, with 40x40x4 regular voxel grid.
voxel_vis.jpg
voxel_vis.jpg (161.83 KiB) Viewed 5143 times
TheMarkster
Veteran
Posts: 5513
Joined: Thu Apr 05, 2018 1:53 am

Re: Generating a voxel representation of a CAD model

Post by TheMarkster »

The function getVolume() will get the volume of the intersection of a cube and the object where the cube is placed at x,y,z relative to the object's boundbox xmin,ymin,zmin values.

Code: Select all

import FreeCAD
import Part


def getVolume(object,x,y,z,cubeSize=1):
    box = Part.makeBox(cubeSize,cubeSize,cubeSize)
    bb = object.Shape.BoundBox
    x1,y1,z1,x2,y2,z2 = bb.XMin,bb.YMin,bb.ZMin,bb.XMax,bb.YMax,bb.ZMax
    targetX,targetY,targetZ = x1+x,y1+y,z1+z
    if targetX > x2 or targetY > y2 or targetZ > z2:
        raise StandardError('Out of bounds error.')
    box.Placement = App.Placement(App.Vector(targetX,targetY,targetZ),App.Rotation(0,0,0),App.Vector(0,0,0)) #location, eular angles, center
    intersection = box.common(object.Shape)
    vol = intersection.Volume
    Part.show(box)
    return vol


obj = App.ActiveDocument.getObject('Cut')
vol = getVolume(obj,10,17,0)
I only did very minimal testing using the attached model.

Are you looking to make a model of the results are is your main interest just getting the data? If you try to model 40x40x4 little cubes that's 6400 objects, quite a lot for FreeCAD to try to deal with. The function above shows the box, which adds it to the document object, but I only did it to be able to see where the box was getting put. Performance will be better if you don't show the box every time through.

Here is slightly more complete example, with loops to generate the data. Enable report panel view to see the data.

Code: Select all

import FreeCAD
import Part


def getVolume(object,x,y,z,cubeSize=1):
    box = Part.makeBox(cubeSize,cubeSize,cubeSize)
    bb = object.Shape.BoundBox
    x1,y1,z1,x2,y2,z2 = bb.XMin,bb.YMin,bb.ZMin,bb.XMax,bb.YMax,bb.ZMax
    targetX,targetY,targetZ = x1+x,y1+y,z1+z
    if targetX > x2 or targetY > y2 or targetZ > z2:
        raise StandardError('Out of bounds error.')
    box.Placement = App.Placement(App.Vector(targetX,targetY,targetZ),App.Rotation(0,0,0),App.Vector(0,0,0)) #location, eular angles, center of rotation
    intersection = box.common(object.Shape)
    vol = intersection.Volume
    #Part.show(box)
    return vol


obj = App.ActiveDocument.getObject('Cut')
#vol = getVolume(obj,10,17,0)


data=[]
for xx in range (0,40):
    for yy in range(0,40):
        for zz in range(0,4):
            data.append([(xx,yy,zz),round(getVolume(obj,xx,yy,zz),4)])

pass
for d in data:
    FreeCAD.Console.PrintMessage(str(d)+'\n')     
Attachments
plate-with-hole.FCStd
(9.32 KiB) Downloaded 82 times
hestenes
Posts: 6
Joined: Wed Aug 01, 2018 8:56 pm

Re: Generating a voxel representation of a CAD model

Post by hestenes »

Are you looking to make a model of the results are is your main interest just getting the data?
Yes. My main interest is just getting the data.
TheMarkster
Veteran
Posts: 5513
Joined: Thu Apr 05, 2018 1:53 am

Re: Generating a voxel representation of a CAD model

Post by TheMarkster »

hestenes wrote: Fri Aug 10, 2018 2:25 pm Yes. My main interest is just getting the data.
In that case I think FreeCAD will be up to the task. It's when you start trying to add large numbers of objects to the document when performance begins to lag. If you only need the data there's no need to display all the cubes, except during testing/debugging, and even then perhaps a random sampling will suffice. 40x40x4 = 6400 objects, too many for FreeCAD to easily manage in the document tree, but if you randomly add 1 in every 10 that brings the number down to a more manageable 640 (on average). The actual data will use all the cubes, but only 1 in 10 would be displayed with the code below.

Code: Select all

import FreeCAD
import Part
import random
from PySide import QtCore,QtGui


def getVolume(object,x,y,z,cubeSize=1):
    box = Part.makeBox(cubeSize,cubeSize,cubeSize)
    bb = object.Shape.BoundBox
    x1,y1,z1,x2,y2,z2 = bb.XMin,bb.YMin,bb.ZMin,bb.XMax,bb.YMax,bb.ZMax
    targetX,targetY,targetZ = x1+x,y1+y,z1+z
    if targetX > x2 or targetY > y2 or targetZ > z2:
        raise StandardError('Out of bounds error.')
    box.Placement = App.Placement(App.Vector(targetX,targetY,targetZ),App.Rotation(0,0,0),App.Vector(0,0,0)) #location, eular angles, center of rotation
    intersection = box.common(object.Shape)
    vol = intersection.Volume
    if random.randint(1,10)==1:
        Part.show(box)
        App.ActiveDocument.recompute()
        b = App.ActiveDocument.ActiveObject
        color = vol/float(cubeSize**3)
        b.ViewObject.ShapeColor=(color,color,color) #grayscale

    return vol


obj = App.ActiveDocument.getObject('Cut')
#vol = getVolume(obj,10,17,0)


data=[]
for xx in range (0,40):
    for yy in range(0,40):
        for zz in range(0,4):
            data.append([(xx,yy,zz),round(getVolume(obj,xx,yy,zz),4)])
            QtGui.QApplication.processEvents()

pass
for d in data:
    FreeCAD.Console.PrintMessage(str(d)+'\n')            
Another refinement would be to add the boxes to a compound and then display the compound at the end, which should give much better performance. You could also take the volume of the cut object and compare it to a running tally of the cube volumes as a crosscheck.
volex.gif
volex.gif (501.56 KiB) Viewed 5047 times
Post Reply