I am attempting to render the output from SciPy SphericalVoronoi using the THREE.js library. I was hoping it would be relatively straight forward based on the matplotlib example in the scipy docs.
Update 2/18/17:
I didn't originally account for the voronoi regions being quads, so this splits them into triangles now. I did get the unit cube example working; however, scaling up the geometry doesn't seem to be complete.
Python script:
import json
import numpy as np
from scipy.spatial import SphericalVoronoi
# http://stackoverflow.com/questions/27050108/convert-numpy-type-to-python/27050186#27050186
class NumpyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.integer):
return int(obj)
elif isinstance(obj, np.floating):
return float(obj)
elif isinstance(obj, np.ndarray):
return obj.tolist()
else:
return super(NumpyEncoder, self).default(obj)
def computeVoronoi( data ):
vertices = np.array( data['vertices'] )
lenVerts = int( vertices.shape[0] / 3 )
vertices = np.reshape( vertices, ( lenVerts, 3 ) )
voronoi = SphericalVoronoi( vertices, data['regularRadius'] )
'''
points = np.array([[0, 0, 1], [0, 0, -1], [1, 0, 0], [0, 1, 0], [0, -1, 0], [-1, 0, 0], ])
voronoi = SphericalVoronoi( points, 1, np.array([0, 0, 0]) )
'''
voronoi.sort_vertices_of_regions()
return voronoi
if __name__ == '__main__':
with open( './map.json' ) as infile:
voronoi = computeVoronoi( json.load( infile ) )
indices = []
for region in voronoi.regions:
# need to split the quad into tris for rendering
i1 = region[0]
i2 = region[1]
i3 = region[2]
i4 = region[3]
indices.append( i1 )
indices.append( i2 )
indices.append( i3 )
indices.append( i3 )
indices.append( i4 )
indices.append( i1 )
with open( './voronoi.json', 'w' ) as outfile:
json.dump( {
'indices': indices,
'colors': np.random.random( (len( voronoi.vertices ),3) ).flatten(),
'vertices': voronoi.vertices.flatten()
}, outfile, cls=NumpyEncoder )
THREE.js script:
var loader = new THREE.FileLoader()
loader.load( 'voronoi.json', function( data ) {
vJson = JSON.parse( data )
var geometry = new THREE.BufferGeometry()
geometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vJson.vertices ), 3 ) )
geometry.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( vJson.colors ), 3 ) )
geometry.setIndex( new THREE.BufferAttribute( new Uint32Array( vJson.indices ), 1 ) )
var voronoiMesh = new THREE.Mesh(
geometry,
new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
vertexColors: THREE.VertexColors,
})
)
scene.add( voronoiMesh )
})
Here's what the render looks like now: render link