use of maspack.geometry.SpatialHashTable in project artisynth_core by artisynth.
the class StlReader method readBinary.
public static PolygonalMesh readBinary(PolygonalMesh mesh, InputStream is, double tol) throws IOException {
boolean _printDebug = false;
// Byte ordering is assumed to be Little Endian (see wikipedia on STL format).
// Format of binary STL is
// 80 byte header (skip)
// 4 byte int indicating num facets to follow
is.skip(80);
byte[] bbuf = new byte[4];
is.read(bbuf, 0, 4);
// This is a simple way to read unsigned long from 4 bytes (LittleEndian)
// There is no other method for reading unsigned 4-byte Int with ByteBuffer!
long numFacets = 0;
numFacets |= bbuf[3] & 0xFF;
numFacets <<= 8;
numFacets |= bbuf[2] & 0xFF;
numFacets <<= 8;
numFacets |= bbuf[1] & 0xFF;
numFacets <<= 8;
numFacets |= bbuf[0] & 0xFF;
if (_printDebug) {
System.out.println("Num facets: " + numFacets);
}
ArrayList<Point3d> nodeList = new ArrayList<Point3d>();
ArrayList<ArrayList<Integer>> faceList = new ArrayList<ArrayList<Integer>>();
if (_printDebug) {
System.out.print("Reading file... ");
}
// For big files, it is slightly faster to read one facet
// at a time than the whole file at once (for some reason).
long start = System.nanoTime();
int facetSize = 50;
bbuf = new byte[facetSize];
List<Point3d> allPoints = new ArrayList<Point3d>(3 * (int) numFacets);
List<Point3d[]> allFaces = new ArrayList<Point3d[]>((int) numFacets);
for (long i = 0; i < numFacets; i++) {
int nBytesRead = is.read(bbuf, 0, facetSize);
if (nBytesRead < facetSize) {
throw new IOException("Invalid STL file detected! (non-matching size)");
}
ByteBuffer bb = ByteBuffer.wrap(bbuf);
bb.order(ByteOrder.LITTLE_ENDIAN);
// Ignore normal
bb.getFloat();
bb.getFloat();
bb.getFloat();
Point3d[] face = new Point3d[3];
// Read all 3 vertices
double[] vals = new double[3];
for (int j = 0; j < 3; j++) {
vals[0] = bb.getFloat();
vals[1] = bb.getFloat();
vals[2] = bb.getFloat();
Point3d pnt;
pnt = new Point3d(vals);
allPoints.add(pnt);
face[j] = pnt;
}
allFaces.add(face);
// Attribute byte count should = 0
bb.getShort();
}
if (_printDebug) {
System.out.println("(" + 1.e-9 * (System.nanoTime() - start) + ")");
System.out.print("Building spatial hash table... ");
start = System.nanoTime();
}
SpatialHashTable<Point3d> table = new SpatialHashTable<Point3d>(tol);
table.setup(allPoints, allPoints);
if (_printDebug) {
System.out.println("(" + 1.e-9 * (System.nanoTime() - start) + ")");
System.out.print("Scanning for unique verts... ");
start = System.nanoTime();
}
HashMap<Point3d, Integer> allToUniqueMap = new HashMap<Point3d, Integer>(allPoints.size());
double tolSq = tol * tol;
for (Point3d pnt : allPoints) {
if (allToUniqueMap.containsKey(pnt)) {
continue;
}
// Find all points within tol of pnt
List<Point3d> results = new ArrayList<Point3d>();
// table.getCellsNearOld (pnt);
List<Point3d> cell = table.getElsNear(pnt);
// continue;
if (cell != null) {
for (Point3d neighbour : cell) {
if (neighbour.distanceSquared(pnt) < tolSq) {
results.add(neighbour);
}
}
}
int idx = nodeList.size();
nodeList.add(pnt);
for (Point3d neighbour : results) {
allToUniqueMap.put(neighbour, idx);
}
}
if (_printDebug) {
System.out.println("(" + 1.e-9 * (System.nanoTime() - start) + ")");
System.out.print("Building faceList... ");
start = System.nanoTime();
}
// Build face list by looking up the index of the Unique vert through hashmap.
for (Point3d[] face : allFaces) {
ArrayList<Integer> faceNodes = new ArrayList<Integer>(3);
for (int i = 0; i < 3; i++) {
int idx = allToUniqueMap.get(face[i]);
faceNodes.add(idx);
}
faceList.add(faceNodes);
}
if (_printDebug) {
System.out.println("(" + 1.e-9 * (System.nanoTime() - start) + ")");
System.out.print("building mesh... ");
start = System.nanoTime();
}
mesh = buildMesh(mesh, nodeList, faceList);
if (_printDebug) {
System.out.println("(" + 1.e-9 * (System.nanoTime() - start) + ")");
System.out.println("Done!");
System.out.println("Unique verts: " + nodeList.size());
System.out.println("Unique faces: " + allFaces.size());
}
return mesh;
}
Aggregations