Created
March 16, 2017 22:07
-
-
Save julesghub/df35115d1247f7f75f1eafa6461d2d83 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Complex shapes in Underworld: Voxels, binvox and the Cow\n", | |
"\n", | |
"This notebook describes a possible method for importing complex geometries onto Underworld particles\n", | |
"\n", | |
"Given a supported 3D model file format (based on binvox):\n", | |
" VRML V2.0: almost fully supported\n", | |
" UG, OBJ, OFF, DXF, XGL, POV, BREP, PLY, JOT: only polygons supported\n", | |
"\n", | |
"The workflow is:\n", | |
" 1. Use **binvox** to convert 3D model file into a voxel binary file.\n", | |
" 2. Use numpy to read in the voxel file.\n", | |
" 3. Setup an uw particle distribution.\n", | |
" 4. Use scipy to interpolate (ndimage) the voxel field onto the particles" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Input 3D model: \n", | |
"downloaded from http://tf3dm.com/3d-model/cow-39025.html\n", | |
"\n", | |
"**Note**: We can also use 3D software like 'blender' to manipulate the model file\n", | |
"\n", | |
"Binvox \n", | |
"downloaded http://www.patrickmin.com/binvox/\n", | |
"\n", | |
"Run this command on the input image \n", | |
"`./binvox -c -t vtk <filename>.obj`\n", | |
"\n", | |
"This will output a file named `<filename>.vtk`" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import numpy as np\n", | |
"from scipy import ndimage\n", | |
"import underworld as uw\n", | |
"import glucifer" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# read in the vtk file, create a binary file from it\n", | |
"prefix = '/home/julian/Downloads/theCow/cleanCow'\n", | |
"with open(prefix+'.vtk') as fp, open(prefix+'.binary','w') as ff:\n", | |
" \n", | |
" for line in fp:\n", | |
" if line.startswith(\"DIMENSIONS\"):\n", | |
" shape = line.partition(\" \")[2].rstrip().split(\" \")\n", | |
" if line.startswith(\"LOOKUP_TABLE default\"):\n", | |
" # stop reading ascii\n", | |
" break\n", | |
" \n", | |
" # create new binary file\n", | |
" for line in fp:\n", | |
" ff.write(line) " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# size of binary voxel field\n", | |
"shape = [int(ii) for ii in shape]\n", | |
"shape" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# read in binary information into a numpy array\n", | |
"wtf = np.fromfile(prefix+'.binary', dtype=np.uint8 )" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# UW part - create particle distribution across geometry\n", | |
"mesh = uw.mesh.FeMesh_Cartesian(elementRes=(10,10,10), \n", | |
" minCoord=(0.0,0.0,0.0),\n", | |
" maxCoord=(150.0,260.0,150.0) )\n", | |
"\n", | |
"swarm = uw.swarm.Swarm(mesh)\n", | |
"colour = swarm.add_variable('double',count=1)\n", | |
"layout = uw.swarm.layouts.GlobalSpaceFillerLayout(swarm, particlesPerCell=50)\n", | |
"swarm.populate_using_layout(layout)\n", | |
"\n", | |
"colour.data[:]=0.0" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# reshape the coordinates appropriately\n", | |
"cow = wtf.reshape((shape[0],shape[1],shape[2]))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# evaluate the cow coordinates at the particle coordinates - order is 0 but can be [0 - 5] for spline interpolation\n", | |
"mapping = ndimage.map_coordinates(cow, \n", | |
" [swarm.particleCoordinates.data[:,0].T-50,\n", | |
" swarm.particleCoordinates.data[:,1].T,\n", | |
" swarm.particleCoordinates.data[:,2].T], \n", | |
" order=0)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# how many unique numbers \n", | |
"np.unique(mapping)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"np.histogram(mapping)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"colour.data[:]=mapping.reshape(-1,1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# output as xdmf file to visualise\n", | |
"sH = swarm.save('swarm.h5')\n", | |
"cH = colour.save('colour.h5')\n", | |
"\n", | |
"colour.xdmf('colour', cH, 'colour',sH,'swarm')" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 2", | |
"language": "python", | |
"name": "python2" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 2 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython2", | |
"version": "2.7.11+" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment