#!/usr/bin/env python
# writing js data structure for a mesh
import sys
from numpy import *
from struct import unpack

def read_binary_stl(fname):
	#all numpy binary stl reader
	#adapted from http://sukhbinder.wordpress.com/2013/11/28/binary-stl-file-reader-in-python-powered-by-numpy/
	#but use numpy.unique instead of python set conversion
    fp = open(fname, 'rb')
    Header = fp.read(80)
    nn = fp.read(4)
    Numtri = unpack('i', nn)[0]
    record_dtype = dtype([
                   ('normals', float32,(3,)),  
                   ('Vertex1', float32,(3,)),
                   ('Vertex2', float32,(3,)),
                   ('Vertex3', float32,(3,)) ,              
                   ('atttr', '<i2',(1,) )
    ])
    data = fromfile(fp , dtype = record_dtype , count =Numtri)
    fp.close()
    
    v1= data['Vertex1']
    v2= data['Vertex2']
    v3= data['Vertex3']
    #n= data['normals']
    X = vstack((v1,v2,v3))
    #use a new view to do 3 dimensional unique calculation
    Xc = ascontiguousarray(X).view(dtype((void, X.dtype.itemsize * X.shape[1])))
    _,idx,inv = unique(Xc, return_index=True,return_inverse=True)
    X = X[idx] #grab unique points
    n = shape(v1)[0]
    tris = dstack((arange(n),arange(n)+n,arange(n)+2*n))[0]
    tris = inv[tris] #map triangle indices to unique point indices
    return tris,X

def write(jsname,(tris,X)):
	f = open(jsname,'w')
	xmax = amax(X,axis=0)
	xmin = amin(X,axis=0)
	X = (X - (xmin+xmax)/2)/amax(xmax-xmin)
	f.write('var mesh_vertices = [')
	for x in X:
		f.write('%.4f,%.4f,%.4f,'%tuple(x))
	f.write('];\n')
	f.write('var mesh_colors = [')
	x0_max = amax(X[:,0])
	for x in X:
		f.write('%.4f,%.4f,%.4f,%.4f,'%(x[0],x[1],x[2],.7))
	f.write('];\n')
	f.write('var mesh_elements = [')
	for tri in tris:
		f.write('%d,%d,%d,'%tuple(tri))
	f.write('];\n')

def main():
	if len(sys.argv) != 3:
		print 'usage: mesh_writer meshname jsname'
		sys.exit(0)
	meshname = sys.argv[1] 
	jsname = sys.argv[2]
	write(jsname,read_binary_stl(meshname))

if __name__ == '__main__':
	main()