/*
* Copyright (C) 2010-2014 Andreas Maier
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/
package edu.stanford.rsl.conrad.io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import edu.stanford.rsl.conrad.geometry.AbstractShape;
import edu.stanford.rsl.conrad.geometry.shapes.compound.CompoundShape;
import edu.stanford.rsl.conrad.geometry.shapes.compound.TriangleMesh;
import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
import edu.stanford.rsl.conrad.geometry.shapes.simple.Triangle;
import edu.stanford.rsl.conrad.numerics.SimpleOperators;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
import edu.stanford.rsl.conrad.phantom.AnalyticPhantom;
import edu.stanford.rsl.conrad.phantom.MTFBeadPhantom;
import edu.stanford.rsl.conrad.physics.PhysicalObject;
import edu.stanford.rsl.conrad.rendering.PrioritizableScene;
import edu.stanford.rsl.conrad.utils.FileUtil;
public class STLFileUtil {
public static void writeToSTLFile(String filename, PrioritizableScene scene) throws IOException{
// Open file to write
FileWriter fw = new FileWriter(new File(filename));
BufferedWriter bw = new BufferedWriter(fw);
for (PhysicalObject o: scene){
writePhysicalObject(bw, o);
}
bw.flush();
bw.close();
}
private static void writePhysicalObject(BufferedWriter bw, PhysicalObject o) throws IOException{
bw.write("solid " + o.getNameString() + "\r\n");
writeShape(bw, o.getShape());
bw.write("endsolid "+ o.getNameString() + "\r\n");
}
private static void writeShape(BufferedWriter bw, AbstractShape shape) throws IOException{
if (shape instanceof CompoundShape){
for (AbstractShape s2: (CompoundShape)shape){
writeShape(bw, s2);
}
}
if (shape instanceof Triangle){
Triangle tri = (Triangle) shape;
bw.write(" facet normal " + vectorToString(tri.getNormal())+"\r\n");
bw.write(" outer loop\r\n");
bw.write(" vertex " + vectorToString(tri.getA().getAbstractVector())+"\r\n");
bw.write(" vertex " + vectorToString(tri.getB().getAbstractVector())+"\r\n");
bw.write(" vertex " + vectorToString(tri.getC().getAbstractVector())+"\r\n");
bw.write(" endloop\r\n");
bw.write(" endfacet\r\n");
}
}
private static String vectorToString(SimpleVector vec){
return "" + vec.getElement(0) + " " + vec.getElement(1) + " " + vec.getElement(2);
}
/**
* @param args
*/
public static void main(String[] args) {
boolean testWrite = false;
if (testWrite){
AnalyticPhantom phantom = new MTFBeadPhantom();
try {
String filename = FileUtil.myFileChoose(".stl", true);
STLFileUtil.writeToSTLFile(filename, phantom.tessellatePhantom(0.5));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
try {
CompoundShape mesh = readSTLMesh(FileUtil.myFileChoose(".stl", false));
System.out.println("Read mesh with " + mesh.size() + " triangles");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* Method to read an ascii STL Mesh from a file.
* @param filename the filename
* @return the mesh
* @throws IOException may occur
*/
public static CompoundShape readSTLMesh(String filename) throws IOException{
return readSTLMesh(filename, 100);
}
public static CompoundShape readSTLMesh(String filename, int subCompoundStep) throws IOException{
BufferedReader br = new BufferedReader(new FileReader(filename));
String lineString = br.readLine();
CompoundShape mesh = new TriangleMesh();
if (lineString.startsWith("solid")){
int currentCount = 0;
CompoundShape currentShape = new CompoundShape();
SimpleVector normal = null;
// read solid
lineString = br.readLine();
while (lineString !=null) {
if (lineString.contains("facet normal")){
normal = readVector(lineString);
lineString = br.readLine();
}
if (lineString.contains("outer loop")){
PointND one = new PointND(readVector(br.readLine()));
PointND two = new PointND(readVector(br.readLine()));
PointND three = new PointND(readVector(br.readLine()));
Triangle tri = new Triangle(one, two, three);
double test = SimpleOperators.multiplyInnerProd(normal, tri.getNormal());
if (test<0) tri.flipNormal();
currentShape.add(tri);
currentCount++;
if (currentCount >= subCompoundStep){
currentCount = 0;
mesh.add(currentShape);
currentShape = new CompoundShape();
}
lineString = br.readLine();
if (!lineString.contains("endloop")) throw new RuntimeException("Mesh did not contain triangular data!");
lineString = br.readLine();
}
if (!lineString.contains("endfacet")) throw new RuntimeException("Malformed facet detected!");
lineString = br.readLine();
if (lineString.contains("endsolid")) break;
}
if (currentShape.size() > 0) mesh.add(currentShape);
}
mesh.getMax();
mesh.getMin();
return mesh;
}
public static SimpleVector readVector(String lineString){
String [] substr = lineString.split("\\s+");
double one = Double.parseDouble(substr[substr.length-3]);
double two = Double.parseDouble(substr[substr.length-2]);
double three = Double.parseDouble(substr[substr.length-1]);
return new SimpleVector(one, two, three);
}
}