JavaCAD
STLLoader.java
Go to the documentation of this file.
1 
2 
3 package eu.mihosoft.vrl.v3d.ext.imagej;
4 
12 import java.io.BufferedReader;
13 import java.io.File;
14 import java.io.FileInputStream;
15 import java.io.FileNotFoundException;
16 import java.io.FileReader;
17 import java.io.IOException;
18 import java.text.DecimalFormat;
19 import java.text.ParseException;
20 import java.util.ArrayList;
21 
22 import javax.vecmath.Point3f;
23 
24 // TODO: Auto-generated Javadoc
28 public class STLLoader {
29 
30 // /**
31 // * Load the specified stl file and returns the result as a hash map, mapping
32 // * the object names to the corresponding <code>CustomMesh</code> objects.
33 // */
34 // public static Map<String, CustomMesh> load(String stlfile)
35 // throws IOException {
36 // STLLoader sl = new STLLoader();
37 // try {
38 // sl.parse(stlfile);
39 // } catch (RuntimeException e) {
40 // System.out.println("error reading " + sl.name);
41 // throw e;
42 // }
43 // return sl.meshes;
44 // }
45 //
49 // private HashMap<String, CustomMesh> meshes;
50  public STLLoader() {
51  }
52 
54  String line;
55 
57  BufferedReader in;
58 
60  // attributes of the currently read mesh
61  private ArrayList<Point3f> vertices = new ArrayList<>();
62 
64  private Point3f normal = new Point3f(0.0f, 0.0f, 0.0f); //to be used for file checking
65 
67  private FileInputStream fis;
68 
70  private int triangles;
71 // private DecimalFormat decimalFormat = new DecimalFormat("0.0E0");
72 
73 
74 
82 public ArrayList<Point3f> parse(File f) throws IOException {
83  vertices.clear();
84 
85  // determine if this is a binary or ASCII STL
86  // and send to the appropriate parsing method
87  // Hypothesis 1: this is an ASCII STL
88  BufferedReader br = new BufferedReader(new FileReader(f));
89  String line = br.readLine();
90  String[] words = line.trim().split("\\s+");
91  if (line.indexOf('\0') < 0 && words[0].equalsIgnoreCase("solid")) {
92  //System.out.println("Looks like an ASCII STL");
93  parseAscii(f);
94  br.close();
95  return vertices;
96  }
97  br.close();
98  // Hypothesis 2: this is a binary STL
99  FileInputStream fs = new FileInputStream(f);
100 
101  // bytes 80, 81, 82 and 83 form a little-endian int
102  // that contains the number of triangles
103  byte[] buffer = new byte[84];
104  fs.read(buffer, 0, 84);
105  fs.close();
106  triangles = (int) (((buffer[83] & 0xff) << 24)
107  | ((buffer[82] & 0xff) << 16) | ((buffer[81] & 0xff) << 8) | (buffer[80] & 0xff));
108  if (((f.length() - 84) / 50) == triangles) {
109  //System.out.println("Looks like a binary STL");
110  parseBinary(f);
111  return vertices;
112  }
113  System.err.println("File is not a valid STL");
114 
115  return vertices;
116  }
117 
123  private void parseAscii(File f) {
124  try {
125  in = new BufferedReader(new FileReader(f));
126  } catch (FileNotFoundException e) {
127  e.printStackTrace();
128  }
129  vertices = new ArrayList<>();
130  try {
131  while ((line = in.readLine()) != null) {
132  String[] numbers = line.trim().split("\\s+");
133  if (numbers[0].equals("vertex")) {
134  float x = parseFloat(numbers[1]);
135  float y = parseFloat(numbers[2]);
136  float z = parseFloat(numbers[3]);
137  Point3f vertex = new Point3f(x, y, z);
138  vertices.add(vertex);
139  } else if (numbers[0].equals("facet") && numbers[1].equals("normal")) {
140  normal.x = parseFloat(numbers[2]);
141  normal.y = parseFloat(numbers[3]);
142  normal.z = parseFloat(numbers[4]);
143  }
144  }
145  in.close();
146  } catch (IOException e) {
147  e.printStackTrace();
148  } catch (ParseException e) {
149  e.printStackTrace();
150  }
151  }
152 
158  private void parseBinary(File f) {
159  vertices = new ArrayList<Point3f>();
160  try {
161  fis = new FileInputStream(f);
162  for (int h = 0; h < 84; h++) {
163  fis.read();// skip the header bytes
164  }
165  for (int t = 0; t < triangles; t++) {
166  byte[] tri = new byte[50];
167  for (int tb = 0; tb < 50; tb++) {
168  tri[tb] = (byte) fis.read();
169  }
170  normal.x = leBytesToFloat(tri[0], tri[1], tri[2], tri[3]);
171  normal.y = leBytesToFloat(tri[4], tri[5], tri[6], tri[7]);
172  normal.z = leBytesToFloat(tri[8], tri[9], tri[10], tri[11]);
173  for (int i = 0; i < 3; i++) {
174  final int j = i * 12 + 12;
175  float px = leBytesToFloat(tri[j], tri[j + 1], tri[j + 2],
176  tri[j + 3]);
177  float py = leBytesToFloat(tri[j + 4], tri[j + 5],
178  tri[j + 6], tri[j + 7]);
179  float pz = leBytesToFloat(tri[j + 8], tri[j + 9],
180  tri[j + 10], tri[j + 11]);
181  Point3f p = new Point3f(px, py, pz);
182  vertices.add(p);
183  }
184  }
185  fis.close();
186  } catch (FileNotFoundException e) {
187  e.printStackTrace();
188  } catch (IOException e) {
189  e.printStackTrace();
190  }
191  }
192 
193 // private float parseFloat(String string) throws ParseException {
194 // //E+05 -> E05, e+05 -> E05
195 // string = string.replaceFirst("[eE]\\+", "E");
196 // //E-05 -> E-05, e-05 -> E-05
197 // string = string.replaceFirst("e\\-", "E-");
198 // return decimalFormat.parse(string).floatValue();
199 // }
200 
208 private float parseFloat(String string) throws ParseException {
209 
210  return Float.parseFloat(string);
211  }
212 
222  private float leBytesToFloat(byte b0, byte b1, byte b2, byte b3) {
223  return Float.intBitsToFloat((((b3 & 0xff) << 24) | ((b2 & 0xff) << 16)
224  | ((b1 & 0xff) << 8) | (b0 & 0xff)));
225  }
226 
227 }
float leBytesToFloat(byte b0, byte b1, byte b2, byte b3)
Definition: STLLoader.java:222
ArrayList< Point3f > parse(File f)
Definition: STLLoader.java:82