PlyParser.java
Go to the documentation of this file.
00001 /*******************************************************************************
00002  * Copyright (c) 2012 Stefan Profanter. All rights reserved. This program and the accompanying
00003  * materials are made available under the terms of the GNU Public License v3.0 which accompanies
00004  * this distribution, and is available at http://www.gnu.org/licenses/gpl.html
00005  * 
00006  * Contributors: Stefan Profanter - initial API and implementation, Year: 2012 Andrei Stoica - minor
00007  * refactor during Google Summer of Code 2014
00008  ******************************************************************************/
00009 package edu.tum.cs.vis.model.parser;
00010 
00011 import java.awt.Color;
00012 import java.io.FileNotFoundException;
00013 import java.io.IOException;
00014 import java.io.RandomAccessFile;
00015 import java.nio.BufferOverflowException;
00016 import java.nio.BufferUnderflowException;
00017 import java.nio.ByteBuffer;
00018 import java.nio.ByteOrder;
00019 import java.util.ArrayList;
00020 
00021 import edu.tum.cs.vis.model.Model;
00022 import edu.tum.cs.vis.model.util.Group;
00023 import edu.tum.cs.vis.model.util.Mesh;
00024 import edu.tum.cs.vis.model.util.Triangle;
00025 import edu.tum.cs.vis.model.util.Vertex;
00026 
00033 public class PlyParser extends ModelParser {
00034 
00041         private enum FileFormat {
00045                 ASCII,
00049                 LITTLE_ENDIAN,
00053                 BIG_ENDIAN
00054         };
00055 
00059         private ByteBuffer      byteBuffer;
00060 
00064         private FileFormat      fileFormat;
00065 
00072         private class Property {
00080                 public Property(String name) {
00081                         this.name = name;
00082                 }
00083 
00087                 String  type1   = null; //
00091                 String  type2   = null;
00095                 String  name;
00096         }
00097 
00104         private class ValueLine {
00108                 ArrayList<Number>       values  = new ArrayList<Number>();
00109         }
00110 
00117         private class Element {
00126                 public Element(String n, int cnt) {
00127                         this.name = n;
00128                         this.cnt = cnt;
00129                 }
00130 
00134                 String                                  name;
00138                 int                                             cnt;
00142                 ArrayList<Property>             properties      = new ArrayList<Property>();
00146                 ArrayList<ValueLine>    lines           = new ArrayList<ValueLine>();
00147         };
00148 
00152         private ArrayList<Element>      elements                = new ArrayList<Element>();
00153 
00157         private int                                     currentElement  = 0;
00158 
00162         @SuppressWarnings("unused")
00163         private void dump() {
00164                 for (Element e : elements) {
00165                         System.out.println(e.name);
00166                         for (Property p : e.properties) {
00167                                 System.out.println("prop: " + p.name);
00168                                 System.out.println("prop:     " + p.type1);
00169                                 System.out.println("prop:     " + p.type2);
00170                         }
00171                         for (ValueLine l : e.lines) {
00172                                 for (Number n : l.values)
00173                                         System.out.print(n.toString() + " ");
00174                                 System.out.println("");
00175                         }
00176                 }
00177         }
00178 
00179         @Override
00180         protected boolean loadModel(String filename) {
00181 
00182                 RandomAccessFile raf = null;
00183 
00184                 try {
00185                         raf = new RandomAccessFile(filename, "r");
00186                         boolean cont = false;
00187                         String line = "";
00188                         line = raf.readLine();
00189                         if (line == null || line.compareTo("ply") != 0) {
00190                                 System.err.println("ERRROR: magic bytes 'ply' not found in file.");
00191                                 return false;
00192                         }
00193                         do {
00194                                 line = raf.readLine();
00195                                 if (line != null)
00196                                         cont = processLine(line.split(" "));
00197                         } while (cont && line.compareTo("end_header") != 0);
00198 
00199                         if (cont) {
00200                                 if (fileFormat == FileFormat.ASCII) {
00201                                         do {
00202                                                 line = raf.readLine();
00203                                                 if (line != null)
00204                                                         cont = processDataLine(line.split(" "));
00205                                         } while (cont && line != null);
00206                                 } else {
00207                                         int remain = (int) (raf.length() - raf.getFilePointer());
00208                                         byteBuffer = ByteBuffer.allocate(remain);
00209                                         if (fileFormat == FileFormat.BIG_ENDIAN)
00210                                                 byteBuffer.order(ByteOrder.BIG_ENDIAN);
00211                                         else
00212                                                 byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
00213 
00214                                         for (int i = 0; i < remain; i++) {
00215                                                 byte b = raf.readByte();
00216                                                 byteBuffer.put(b);
00217                                         }
00218                                         byteBuffer.position(0);
00219                                         try {
00220                                                 processDataBuffer();
00221 
00222                                         } catch (BufferUnderflowException e) {
00223                                                 System.err.println("Couldn't parse model. " + e.toString() + " "
00224                                                                 + e.getMessage());
00225                                                 return false;
00226                                         } catch (BufferOverflowException e) {
00227                                                 System.err.println("Couldn't parse model. " + e.toString() + " "
00228                                                                 + e.getMessage());
00229                                                 return false;
00230                                         }
00231 
00232                                 }
00233                         }
00234                 } catch (FileNotFoundException e) {
00235                         System.out.println("ERROR: File not found: " + filename);
00236                         return false;
00237                 } catch (IOException e) {
00238                         System.out.println("ERROR reading file: " + e.getMessage());
00239                 } finally {
00240                         try {
00241                                 if (raf != null)
00242                                         raf.close();
00243                         } catch (IOException e) {
00244                                 System.out.println("ERROR closing file: " + e.getMessage());
00245                         }
00246                 }
00247 
00248                 // dump();
00249 
00250                 try {
00251 
00252                         byteBuffer = null;
00253 
00254                         Element vertexElement = null;
00255                         Element faceElement = null;
00256                         for (Element e : elements) {
00257                                 if (e.name.compareTo("vertex") == 0) {
00258                                         vertexElement = e;
00259                                 }
00260                                 if (e.name.compareTo("face") == 0) {
00261                                         faceElement = e;
00262                                 }
00263                                 if (vertexElement != null && faceElement != null)
00264                                         break;
00265                         }
00266 
00267                         if (vertexElement == null) {
00268                                 System.err.println("ERROR: .ply file doesn't contain vertex definition.");
00269                                 return false;
00270                         }
00271 
00272                         if (faceElement == null) {
00273                                 System.err.println("ERROR: .ply file doesn't contain face definition.");
00274                                 return false;
00275                         }
00276 
00277                         model = new Model();
00278                         Group g = new Group(model);
00279                         model.setGroup(g);
00280                         Mesh m = new Mesh();
00281                         g.setMesh(m);
00282 
00283                         model.setTextureBasePath(null);
00284 
00285                         int coordIdx[] = new int[] { -1, -1, -1 };
00286                         int colorIdx[] = new int[] { -1, -1, -1 };
00287                         int idxOk = 0;
00288                         int colorOk = 0;
00289                         for (int i = 0; i < vertexElement.properties.size(); i++) {
00290                                 Property p = vertexElement.properties.get(i);
00291                                 if (p.name.equals("x")) {
00292                                         coordIdx[0] = i;
00293                                         idxOk++;
00294                                 } else if (p.name.equals("y")) {
00295                                         coordIdx[1] = i;
00296                                         idxOk++;
00297                                 } else if (p.name.equals("z")) {
00298                                         coordIdx[2] = i;
00299                                         idxOk++;
00300                                 } else if (p.name.equals("red")) {
00301                                         colorIdx[0] = i;
00302                                         colorOk++;
00303                                 } else if (p.name.equals("green")) {
00304                                         colorIdx[1] = i;
00305                                         colorOk++;
00306                                 } else if (p.name.equals("nlue")) {
00307                                         colorIdx[2] = i;
00308                                         colorOk++;
00309                                 }
00310                         }
00311 
00312                         if (idxOk != 3) {
00313                                 System.err.println("ERROR: x,y,z not properly defined for vertices in header.");
00314                                 model = null;
00315                                 return false;
00316                         }
00317 
00318                         for (ValueLine l : vertexElement.lines) {
00319                                 if (l.values.size() < 3) {
00320                                         System.err.println("ERROR: invalid vertex coordinate count: " + l.values.size()
00321                                                         + " for vertex index " + model.getVertices().size());
00322                                         model = null;
00323                                         return false;
00324                                 }
00325                                 Vertex v = new Vertex(l.values.get(coordIdx[0]).floatValue(), l.values.get(
00326                                                 coordIdx[1]).floatValue(), l.values.get(coordIdx[2]).floatValue());
00327                                 if (colorOk == 3) {
00328                                         v.color = new Color(l.values.get(colorIdx[0]).intValue(), l.values.get(
00329                                                         colorIdx[1]).intValue(), l.values.get(colorIdx[2]).intValue());
00330                                 }
00331                                 model.getVertices().add(v);
00332                         }
00333 
00334                         for (ValueLine l : faceElement.lines) {
00335                                 if (l.values.size() < 3) {
00336                                         System.err.println("WARN: Skipping face with less than 3 points");
00337                                 } else if (l.values.size() == 3) {
00338                                         Triangle t = new Triangle();
00339                                         Vertex[] vert = new Vertex[3];
00340                                         for (int i = 0; i < 3; i++) {
00341                                                 vert[i] = model.getVertices().get(l.values.get(i).intValue());
00342                                         }
00343                                         t.setPosition(vert);
00344                                         t.updateEdges();
00345                                         if (!t.calculateNormalVector()) {
00346                                                 continue;
00347                                         }
00348                                         g.addTriangle(t);
00349                                 } else {
00350 
00351                                         Vertex[] polyVert = new Vertex[l.values.size()];
00352                                         for (int i = 0; i < l.values.size(); i++) {
00353                                                 polyVert[i] = model.getVertices().get(l.values.get(i).intValue());
00354                                         }
00355                                         int triangleIndices[] = polygonTriangulation(polyVert);
00356                                         for (int i = 0; i < triangleIndices.length / 3; i++) {
00357                                                 Triangle t = new Triangle();
00358                                                 Vertex[] vert = new Vertex[3];
00359                                                 for (int j = 0; j < 3; j++) {
00360                                                         vert[j] = polyVert[triangleIndices[i * 3 + j]];
00361                                                 }
00362                                                 t.setPosition(vert);
00363                                                 if (!t.calculateNormalVector()) {
00364                                                         continue;
00365                                                 }
00366                                                 g.addTriangle(t);
00367                                         }
00368                                 }
00369                         }
00370                 } catch (IndexOutOfBoundsException e) {
00371                         System.err.println("Couldn't parse model. " + e.toString() + " " + e.getMessage());
00372                         return false;
00373                 } catch (BufferUnderflowException e) {
00374                         System.err.println("Couldn't parse model. " + e.toString() + " " + e.getMessage());
00375                         return false;
00376                 } catch (BufferOverflowException e) {
00377                         System.err.println("Couldn't parse model. " + e.toString() + " " + e.getMessage());
00378                         return false;
00379                 }
00380 
00381                 elements = null;
00382 
00383                 return true;
00384         }
00385 
00394         private boolean processLine(String parts[]) {
00395                 if (parts.length < 2)
00396                         return true;
00397                 if (parts[0].compareTo("format") == 0) {
00398                         if (parts[1].compareTo("ascii") == 0)
00399                                 fileFormat = FileFormat.ASCII;
00400                         else if (parts[1].compareTo("binary_little_endian") == 0)
00401                                 fileFormat = FileFormat.LITTLE_ENDIAN;
00402                         else if (parts[1].compareTo("binary_big_endian") == 0)
00403                                 fileFormat = FileFormat.BIG_ENDIAN;
00404                         else {
00405                                 System.err.println("ERROR: " + parts[0] + " header unknown: " + parts[1]);
00406                                 return false;
00407                         }
00408                         return true;
00409                 } else if (parts[0].compareTo("element") == 0) {
00410                         elements.add(new Element(parts[1], Integer.valueOf(parts[2])));
00411                         return true;
00412                 } else if (parts[0].compareTo("property") == 0) {
00413                         Property p = new Property(parts[parts.length - 1]);
00414                         if (parts[1].compareTo("list") == 0) {
00415                                 p.type1 = parts[2];
00416                                 p.type2 = parts[3];
00417                         } else {
00418                                 p.type1 = parts[1];
00419                         }
00420                         elements.get(elements.size() - 1).properties.add(p);
00421                         return true;
00422                 }
00423                 return true;
00424         }
00425 
00433         private boolean processDataLine(String parts[]) {
00434                 int offset = 0;
00435                 int cnt = 1;
00436 
00437                 if (elements.get(currentElement).properties.get(0).type2 != null) {
00438                         // it is list
00439                         cnt = Integer.valueOf(parts[0]);
00440                         offset = 1;
00441                 } else {
00442                         cnt = elements.get(currentElement).properties.size();
00443                 }
00444 
00445                 ValueLine l = new ValueLine();
00446                 for (int i = offset; i < cnt + offset; i++) {
00447                         l.values.add(Float.valueOf(parts[i]));
00448                 }
00449                 elements.get(currentElement).lines.add(l);
00450                 if (elements.get(currentElement).lines.size() == elements.get(currentElement).cnt)
00451                         currentElement++;
00452                 return true;
00453         }
00454 
00464         private Number parseType(String type) {
00465                 if (type.equals("char")) {
00466                         return new Integer(byteBuffer.get());
00467                 } else if (type.equals("uchar")) {
00468                         return new Integer(byteBuffer.get());
00469                 } else if (type.equals("short")) {
00470                         short c = byteBuffer.getShort();
00471                         return new Integer(c);
00472                 } else if (type.equals("ushort")) {
00473                         short c = byteBuffer.getShort();
00474                         int v = new Integer(c);
00475                         v += 32768; // TODO not yet tested
00476                         return new Integer(v);
00477                 } else if (type.equals("int")) {
00478                         return new Integer(byteBuffer.getInt());
00479                 } else if (type.equals("uint")) {
00480                         int v = byteBuffer.getInt();
00481                         v += 2147483648l; // TODO not yet tested
00482                         return new Integer(v);
00483                 } else if (type.equals("float")) {
00484                         return new Float(byteBuffer.getFloat());
00485                 } else if (type.equals("int")) {
00486                         return new Float(byteBuffer.getDouble());
00487                 } else {
00488                         System.err.println("ERROR: invalid data type: " + type);
00489                         return null;
00490                 }
00491         }
00492 
00499         private boolean processDataBuffer() {
00500 
00501                 for (int el = 0; el < elements.size(); el++) {
00502                         for (int j = 0; j < elements.get(el).cnt; j++) {
00503                                 int valCnt;
00504                                 String listType = null;
00505                                 if (elements.get(el).properties.get(0).type2 != null) {
00506                                         listType = elements.get(el).properties.get(0).type2;
00507                                         valCnt = (Integer) parseType(elements.get(el).properties.get(0).type1);
00508                                 } else {
00509                                         listType = null;
00510                                         valCnt = elements.get(el).properties.size();
00511                                 }
00512 
00513                                 ValueLine l = new ValueLine();
00514                                 for (int i = 0; i < valCnt; i++) {
00515                                         String type = listType;
00516                                         if (type == null) {
00517                                                 type = elements.get(el).properties.get(i).type1;
00518                                         }
00519                                         l.values.add(parseType(type));
00520                                 }
00521                                 elements.get(el).lines.add(l);
00522                         }
00523                 }
00524                 return true;
00525         }
00526 }


knowrob_cad_parser
Author(s): Stefan Profanter
autogenerated on Mon Oct 6 2014 01:29:56