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


knowrob_cad_parser
Author(s): Stefan Profanter
autogenerated on Sat Dec 28 2013 17:09:45