src/writer/stl-writer.js
/**
* @file STL Writer
* @author Paul Pillot <paul.pillot@cimf.ca>
* @private
*/
import { Vector3 } from '../../lib/three.es6.js'
import Writer from './writer.js'
import IOBuffer from '../utils/io-buffer.js'
// https://en.wikipedia.org/wiki/STL_(file_format)#ASCII_STL
/**
* Create an STL File from a surface Object (e.g. for 3D printing)
*
* @example
* molsurf = new MolecularSurface(structure)
* surf = molsurf.getSurface({type: 'av', probeRadius: 1.4})
* stl = new StlWriter(surf)
* stl.download('myFileName')
*/
class StlWriter extends Writer {
/**
* @param {Surface} surface - the surface to write out
*/
constructor (surface) {
super()
this.surface = surface
this._records = []
}
get mimeType () { return 'application/vnd.ms-pki.stl' }
get defaultName () { return 'surface' }
get defaultExt () { return 'stl' }
/*
* Get STL Binary data
*
* Adapted from: https://github.com/mrdoob/three.js/blob/master/examples/js/exporters/STLBinaryExporter.js
* see https://en.wikipedia.org/wiki/STL_(file_format)#Binary_STL for the file format description
*
* @return {DataView} the data
*/
getData () {
const triangles = this.surface.index.length / 3
const bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4
const output = new IOBuffer(bufferLength)
output.skip(80) // skip header
output.writeUint32(triangles)
const vector = new Vector3()
const vectorNorm1 = new Vector3()
const vectorNorm2 = new Vector3()
const vectorNorm3 = new Vector3()
// traversing vertices
for (let i = 0; i < triangles; i++) {
const indices = [
this.surface.index[i * 3],
this.surface.index[i * 3 + 1],
this.surface.index[i * 3 + 2]
]
vectorNorm1.fromArray(this.surface.normal, indices[0] * 3)
vectorNorm2.fromArray(this.surface.normal, indices[1] * 3)
vectorNorm3.fromArray(this.surface.normal, indices[2] * 3)
vector.addVectors(vectorNorm1, vectorNorm2).add(vectorNorm3).normalize()
output.writeFloat32(vector.x)
output.writeFloat32(vector.y)
output.writeFloat32(vector.z)
for (let j = 0; j < 3; j++) {
vector.fromArray(this.surface.position, indices[j] * 3)
output.writeFloat32(vector.x) // vertices
output.writeFloat32(vector.y)
output.writeFloat32(vector.z)
}
output.writeUint16(0) // attribute byte count
}
return new DataView(output.buffer)
}
}
export default StlWriter