checkpoint
[anneal.git] / src / edu / berkeley / qfat / stl / StlFile.java
1 package edu.berkeley.qfat.stl;
2 import com.sun.j3d.loaders.Loader;
3 import com.sun.j3d.loaders.Scene;
4 import com.sun.j3d.loaders.SceneBase;
5 import com.sun.j3d.loaders.IncorrectFormatException;
6 import com.sun.j3d.loaders.ParsingErrorException;
7 import com.sun.j3d.utils.geometry.GeometryInfo;
8
9 import java.net.URL;
10 import java.net.MalformedURLException;
11
12 import java.io.Reader;
13 import java.io.BufferedReader;
14 import java.io.FileReader;
15 import java.io.InputStreamReader;
16 import java.io.FileInputStream;
17 import java.io.InputStream;
18 import java.io.FileNotFoundException;
19 import java.io.IOException;
20
21 import java.util.StringTokenizer;
22 import java.util.ArrayList;
23
24 import javax.vecmath.Point3f;
25 import javax.vecmath.Vector3f;
26
27 import javax.media.j3d.BranchGroup;
28 import javax.media.j3d.Shape3D;
29
30 // New from JDK 1.4 for endian related problems
31 import java.nio.ByteOrder;
32 import java.nio.ByteBuffer;
33
34
35
36 /**
37  * Title:         STL Loader
38  * Description:   STL files loader (Supports ASCII and binary files) for Java3D
39  *                Needs JDK 1.4 due to endian problems
40  * Company:       Universidad del Pais Vasco (UPV/EHU)
41  * @author:       Carlos Pedrinaci Godoy
42  * @version:      1.0
43  *
44  * Contact : xenicp@yahoo.es
45  *
46  *
47  * Things TO-DO:
48  *    1.-We can't read binary files over the net.
49  *    2.-For binary files if size is lower than expected (calculated with the number of faces)
50  *    the program will block.
51  *    3.-Improve the way for detecting the kind of stl file?
52  *    Can give us problems if the comment of the binary file begins by "solid"
53  */
54
55 public class StlFile implements Loader
56 {
57   private static final int DEBUG = 0;     // Sets mode to Debug: outputs every action done
58
59   // Maximum length (in chars) of basePath
60   private static final int MAX_PATH_LENGTH = 1024;
61
62   // Global variables
63   private int flag;                         // Needed cause implements Loader
64
65   private URL baseUrl = null;               // Reading files over Internet
66   private String basePath = null;           // For local files
67
68   private boolean fromUrl = false;          // Usefull for binary files
69   private boolean Ascii = true;             // File type Ascii -> true o binary -> false
70   private String fileName = null;
71
72   // Arrays with coordinates and normals
73   // Needed for reading ASCII files because its size is unknown until the end
74   private ArrayList coordList;          // Holds Point3f
75   private ArrayList normList;           // Holds Vector3f
76
77   // GeometryInfo needs Arrays
78     public Point3f[] coordArray = null;
79     public Vector3f[] normArray = null;
80
81   // Needed because TRIANGLE_STRIP_ARRAY
82   // As the number of strips = the number of faces it's filled in objectToVectorArray
83     public int[] stripCounts = null;
84
85   // Default = Not available
86   private String objectName=new String("Not available");
87
88   /**
89   *  Constructor
90   */
91   public StlFile()
92   {
93   }
94
95   /**
96    * Method that reads the EOL
97    * Needed for verifying that the file has a correct format
98    *
99    * @param parser The file parser. An instance of StlFileParser.
100    */
101   private void readEOL(StlFileParser parser)
102   {
103     try{
104     parser.nextToken();
105     }
106     catch (IOException e)
107     {
108       System.err.println("IO Error on line " + parser.lineno() + ": " + e.getMessage());
109     }
110     if(parser.ttype != StlFileParser.TT_EOL)
111     {
112       System.err.println("Format Error:expecting End Of Line on line " + parser.lineno());
113     }
114   }
115
116   /**
117    * Method that reads the word "solid" and stores the object name.
118    * It also detects what kind of file it is
119    * TO-DO:
120    *    1.- Better way control of exceptions?
121    *    2.- Better way to decide between Ascii and Binary?
122    *
123    * @param parser The file parser. An instance of StlFileParser.
124    */
125   private void readSolid(StlFileParser parser)
126   {
127     if( !parser.sval.equals("solid"))
128     {
129       //System.out.println("Expecting solid on line " + parser.lineno());
130       // If the first word is not "solid" then we consider the file is binary
131       // Can give us problems if the comment of the binary file begins by "solid"
132       this.setAscii(false);
133     }
134     else  // It's an ASCII file
135     {
136       try{
137           parser.nextToken();
138           }
139       catch (IOException e)
140       {
141         System.err.println("IO Error on line " + parser.lineno() + ": " + e.getMessage());
142       }
143       if( parser.ttype != StlFileParser.TT_WORD)
144       {
145         // Is the object name always provided???
146         System.err.println("Format Error:expecting the object name on line " + parser.lineno());
147       }
148       else
149       { // Store the object Name
150         this.setObjectName(new String(parser.sval));
151         if(DEBUG==1)
152         {
153           System.out.println("Object Name:" + this.getObjectName().toString());
154         }
155         this.readEOL(parser);
156       }
157     }
158   }//End of readSolid
159
160   /**
161    * Method that reads a normal
162    *
163    * @param parser The file parser. An instance of StlFileParser.
164    */
165   private void readNormal(StlFileParser parser)
166   {
167     Vector3f v = new Vector3f();
168
169     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("normal")))
170     {
171       System.err.println("Format Error:expecting 'normal' on line " + parser.lineno());
172     }
173     else
174     {
175       if (parser.getNumber())
176       {
177         v.x=(float)parser.nval;
178
179         if(DEBUG==1)
180         {
181           System.out.println("Normal:");
182           System.out.print("X=" + v.x + " ");
183         }
184
185         if (parser.getNumber())
186         {
187           v.y=(float)parser.nval;
188           if(DEBUG==1)
189             System.out.print("Y=" + v.y + " ");
190
191           if (parser.getNumber())
192           {
193             v.z=(float)parser.nval;
194             if(DEBUG==1)
195               System.out.println("Z=" + v.z);
196
197             // We add that vector to the Normal's array
198             this.normList.add(v);
199             this.readEOL(parser);
200           }
201           else System.err.println("Format Error:expecting coordinate on line " + parser.lineno());
202         }
203         else System.err.println("Format Error:expecting coordinate on line " + parser.lineno());
204       }
205       else System.err.println("Format Error:expecting coordinate on line " + parser.lineno());
206     }
207   }// End of Read Normal
208
209   /**
210    * Method that reads the coordinates of a vector
211    *
212    * @param parser The file parser. An instance of StlFileParser.
213    */
214   private void readVertex(StlFileParser parser)
215   {
216     Point3f p = new Point3f();
217
218     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("vertex")))
219     {
220       System.err.println("Format Error:expecting 'vertex' on line " + parser.lineno());
221     }
222     else
223     {
224       if (parser.getNumber())
225       {
226         p.x=(float)parser.nval;
227
228         if(DEBUG==1)
229         {
230           System.out.println("Vertex:");
231           System.out.print("X=" + p.x + " ");
232         }
233
234         if (parser.getNumber())
235         {
236           p.y=(float)parser.nval;
237           if(DEBUG==1)
238             System.out.print("Y=" + p.y + " ");
239
240           if (parser.getNumber())
241           {
242             p.z=(float)parser.nval;
243             if(DEBUG==1)
244               System.out.println("Z=" + p.z);
245
246             // We add that vertex to the array of vertex
247             coordList.add(p);
248             readEOL(parser);
249           }
250           else System.err.println("Format Error: expecting coordinate on line " + parser.lineno());
251         }
252         else System.err.println("Format Error: expecting coordinate on line " + parser.lineno());
253       }
254       else System.err.println("Format Error: expecting coordinate on line " + parser.lineno());
255     }
256   }//End of read vertex
257
258   /**
259    * Method that reads "outer loop" and then EOL
260    *
261    * @param parser The file parser. An instance of StlFileParser.
262    */
263   private void readLoop(StlFileParser parser)
264   {
265     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("outer")))
266     {
267       System.err.println("Format Error:expecting 'outer' on line " + parser.lineno());
268     }
269     else
270     {
271       try{
272           parser.nextToken();
273           }
274       catch (IOException e)
275       {
276         System.err.println("IO error on line " + parser.lineno() + ": " + e.getMessage());
277       }
278       if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("loop")))
279       {
280         System.err.println("Format Error:expecting 'loop' on line " + parser.lineno());
281       }
282       else readEOL(parser);
283     }
284   }//End of readLoop
285
286   /**
287    * Method that reads "endloop" then EOL
288    *
289    * @param parser The file parser. An instance of StlFileParser.
290    */
291   private void readEndLoop(StlFileParser parser)
292   {
293     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("endloop")))
294     {
295       System.err.println("Format Error:expecting 'endloop' on line " + parser.lineno());
296     }
297     else readEOL(parser);
298   }//End of readEndLoop
299
300   /**
301    * Method that reads "endfacet" then EOL
302    *
303    * @param parser The file parser. An instance of StlFileParser.
304    */
305   private void readEndFacet(StlFileParser parser)
306   {
307     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("endfacet")))
308     {
309       System.err.println("Format Error:expecting 'endfacet' on line " + parser.lineno());
310     }
311     else readEOL(parser);
312   }//End of readEndFacet
313
314   /**
315    * Method that reads a face of the object
316    * (Cares about the format)
317    *
318    * @param parser The file parser. An instance of StlFileParser.
319    */
320   private void readFacet(StlFileParser parser)
321   {
322     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("facet")))
323     {
324       System.err.println("Format Error:expecting 'facet' on line " + parser.lineno());
325     }
326     else
327     {
328       try{
329           parser.nextToken();
330           readNormal(parser);
331
332           parser.nextToken();
333           readLoop(parser);
334
335           parser.nextToken();
336           readVertex(parser);
337
338           parser.nextToken();
339           readVertex(parser);
340
341           parser.nextToken();
342           readVertex(parser);
343
344           parser.nextToken();
345           readEndLoop(parser);
346
347           parser.nextToken();
348           readEndFacet(parser);
349       }
350       catch (IOException e)
351       {
352         System.err.println("IO Error on line " + parser.lineno() + ": " + e.getMessage());
353       }
354     }
355   }// End of readFacet
356
357   /**
358    * Method that reads a face in binary files
359    * All binary versions of the methods end by 'B'
360    * As in binary files we can read the number of faces, we don't need
361    * to use coordArray and normArray (reading binary files should be faster)
362    *
363    * @param in The ByteBuffer with the data of the object.
364    * @param index The facet index
365    *
366    * @throws IOException
367    */
368   private void readFacetB(ByteBuffer in, int index) throws IOException
369   {
370     //File structure: Normal Vertex1 Vertex2 Vertex3
371     Vector3f normal = new Vector3f();
372     Point3f vertex = new Point3f();
373
374     if(DEBUG==1)
375       System.out.println("Reading face number " + index);
376
377     // Read the Normal
378     normArray[index]=new Vector3f();
379     normArray[index].x=in.getFloat();
380     normArray[index].y=in.getFloat();
381     normArray[index].z=in.getFloat();
382
383     if(DEBUG==1)
384       System.out.println("Normal: X=" + normArray[index].x + " Y=" + normArray[index].y + " Z=" + normArray[index].z);
385
386     // Read vertex1
387     coordArray[index*3] = new Point3f();
388     coordArray[index*3].x=in.getFloat();
389     coordArray[index*3].y=in.getFloat();
390     coordArray[index*3].z=in.getFloat();
391
392     if(DEBUG==1)
393       System.out.println("Vertex 1: X=" + coordArray[index*3].x + " Y=" + coordArray[index*3].y + " Z=" + coordArray[index*3].z);
394
395     // Read vertex2
396     coordArray[index*3+1] = new Point3f();
397     coordArray[index*3+1].x=in.getFloat();
398     coordArray[index*3+1].y=in.getFloat();
399     coordArray[index*3+1].z=in.getFloat();
400
401     if(DEBUG==1)
402       System.out.println("Vertex 2: X=" + coordArray[index*3+1].x + " Y=" + coordArray[index*3+1].y + " Z=" + coordArray[index*3+1].z);
403
404     // Read vertex3
405     coordArray[index*3+2] = new Point3f();
406     coordArray[index*3+2].x=in.getFloat();
407     coordArray[index*3+2].y=in.getFloat();
408     coordArray[index*3+2].z=in.getFloat();
409
410     if(DEBUG==1)
411       System.out.println("Vertex 3: X=" + coordArray[index*3+2].x + " Y=" + coordArray[index*3+2].y + " Z=" + coordArray[index*3+2].z);
412
413   }// End of readFacetB
414
415   /**
416    * Method for reading binary files
417    * Execution is completly different
418    * It uses ByteBuffer for reading data and ByteOrder for retrieving the machine's endian
419    * (Needs JDK 1.4)
420    *
421    * TO-DO:
422    *  1.-Be able to read files over Internet
423    *  2.-If the amount of data expected is bigger than what is on the file then
424    *  the program will block forever
425    *
426    * @param file The name of the file
427    *
428    * @throws IOException
429    */
430     public void readBinaryFile(String file, InputStream data) throws IOException
431   {
432     ByteBuffer dataBuffer;                // For reading in the correct endian
433     byte[] Info=new byte[80];             // Header data
434     byte[] Array_number= new byte[4];     // Holds the number of faces
435     byte[] Temp_Info;                     // Intermediate array
436
437     int Number_faces; // First info (after the header) on the file
438
439     if(DEBUG==1)
440       System.out.println("Machine's endian: " + ByteOrder.nativeOrder());
441
442     // Get file's name
443     if(fromUrl)
444     {
445       // FileInputStream can only read local files!?
446       System.out.println("This version doesn't support reading binary files from internet");
447     }
448     else
449     { // It's a local file
450
451       // First 80 bytes aren't important
452       if(80 != data.read(Info))
453       { // File is incorrect
454         //System.out.println("Format Error: 80 bytes expected");
455         throw new IncorrectFormatException();
456       }
457       else
458       { // We must first read the number of faces -> 4 bytes int
459         // It depends on the endian so..
460
461         data.read(Array_number);                      // We get the 4 bytes
462         dataBuffer = ByteBuffer.wrap(Array_number);   // ByteBuffer for reading correctly the int
463         dataBuffer.order(ByteOrder.nativeOrder());    // Set the right order
464         Number_faces = dataBuffer.getInt();
465
466         Temp_Info = new byte[50*Number_faces];        // Each face has 50 bytes of data
467
468         data.read(Temp_Info);                         // We get the rest of the file
469
470         dataBuffer = ByteBuffer.wrap(Temp_Info);      // Now we have all the data in this ByteBuffer
471         dataBuffer.order(ByteOrder.nativeOrder());
472
473         if(DEBUG==1)
474           System.out.println("Number of faces= " + Number_faces);
475
476         // We can create that array directly as we know how big it's going to be
477         coordArray = new Point3f[Number_faces*3]; // Each face has 3 vertex
478         normArray = new Vector3f[Number_faces];
479         stripCounts = new int[Number_faces];
480
481         for(int i=0;i<Number_faces;i++)
482         {
483           stripCounts[i]=3;
484           try
485           {
486             readFacetB(dataBuffer,i);
487             // After each facet there are 2 bytes without information
488             // In the last iteration we dont have to skip those bytes..
489             if(i != Number_faces - 1)
490             {
491               dataBuffer.get();
492               dataBuffer.get();
493             }
494           }
495           catch (IOException e)
496           {
497             // Quitar
498             System.out.println("Format Error: iteration number " + i);
499             throw new IncorrectFormatException();
500           }
501         }//End for
502       }// End file reading
503     }// End else
504   }// End of readBinaryFile
505
506   /**
507    * Method that reads ASCII files
508    * Uses StlFileParser for correct reading and format checking
509    * The beggining of that method is common to binary and ASCII files
510    * We try to detect what king of file it is
511    *
512    * TO-DO:
513    *  1.- Find a best way to decide what kind of file it is
514    *  2.- Is that return (first catch) the best thing to do?
515    *
516    * @param parser The file parser. An instance of StlFileParser.
517    */
518   private void readFile(StlFileParser parser)
519   {
520     int t;
521
522     try{
523         parser.nextToken();
524         }
525     catch (IOException e)
526     {
527       System.err.println("IO Error on line " + parser.lineno() + ": " + e.getMessage());
528       System.err.println("File seems to be empty");
529       return;         // ????? Throw ?????
530     }
531
532     // Here we try to detect what kind of file it is (see readSolid)
533     readSolid(parser);
534
535     if(getAscii())
536     { // Ascii file
537       try
538       {
539           parser.nextToken();
540       }
541       catch (IOException e)
542       {
543        System.err.println("IO Error on line " + parser.lineno() + ": " + e.getMessage());
544       }
545
546       // Read all the facets of the object
547       while (parser.ttype != StlFileParser.TT_EOF && !parser.sval.equals("endsolid"))
548       {
549         readFacet(parser);
550         try
551         {
552           parser.nextToken();
553         }
554         catch (IOException e)
555         {
556           System.err.println("IO Error on line " + parser.lineno() + ": " + e.getMessage());
557         }
558       }// End while
559
560       // Why are we out of the while?: EOF or endsolid
561       if(parser.ttype == StlFileParser.TT_EOF)
562        System.err.println("Format Error:expecting 'endsolid', line " + parser.lineno());
563       else
564       {
565         if(DEBUG==1)
566           System.out.println("File readed");
567       }
568     }//End of Ascii reading
569
570     else
571     { // Binary file
572       try{
573           readBinaryFile(getFileName(), new FileInputStream(getFileName()));
574       }
575       catch(IOException e)
576       {
577         System.err.println("Format Error: reading the binary file");
578       }
579     }// End of binary file
580   }//End of readFile
581
582   /**
583    * The Stl File is loaded from the .stl file specified by
584    * the filename.
585    * To attach the model to your scene, call getSceneGroup() on
586    * the Scene object passed back, and attach the returned
587    * BranchGroup to your scene graph.  For an example, see
588    * $J3D/programs/examples/ObjLoad/ObjLoad.java.
589    *
590    * @param filename The name of the file with the object to load
591    *
592    * @return Scene The scene with the object loaded.
593    *
594    * @throws FileNotFoundException
595    * @throws IncorrectFormatException
596    * @throws ParsingErrorException
597    */
598   public Scene load(String filename) throws FileNotFoundException,
599                                             IncorrectFormatException,
600                                             ParsingErrorException
601   {
602     setBasePathFromFilename(filename);
603     setFileName(filename);     // For binary files
604
605     Reader reader = new BufferedReader(new FileReader(filename));
606     return load(reader);
607   } // End of load(String)
608
609    /**
610    * The Stl file is loaded off of the web.
611    * To attach the model to your scene, call getSceneGroup() on
612    * the Scene object passed back, and attach the returned
613    * BranchGroup to your scene graph.  For an example, see
614    * $J3D/programs/examples/ObjLoad/ObjLoad.java.
615    *
616    * @param url The url to load the onject from
617    *
618    * @return Scene The scene with the object loaded.
619    *
620    * @throws FileNotFoundException
621    * @throws IncorrectFormatException
622    * @throws ParsingErrorException
623    */
624   public Scene load(URL url) throws FileNotFoundException,
625                                     IncorrectFormatException,
626                                     ParsingErrorException
627   {
628     BufferedReader reader;
629
630     setBaseUrlFromUrl(url);
631
632     try {
633       reader = new BufferedReader(new InputStreamReader(url.openStream()));
634     }
635     catch (IOException e) {
636       throw new FileNotFoundException();
637     }
638     fromUrl = true;
639     return load(reader);
640   } // End of load(URL)
641
642   /**
643    * The Stl File is loaded from the already opened file.
644    * To attach the model to your scene, call getSceneGroup() on
645    * the Scene object passed back, and attach the returned
646    * BranchGroup to your scene graph.  For an example, see
647    * $J3D/programs/examples/ObjLoad/ObjLoad.java.
648    *
649    * @param reader The reader to read the object from
650    *
651    * @return Scene The scene with the object loaded.
652    *
653    * @throws FileNotFoundException
654    * @throws IncorrectFormatException
655    * @throws ParsingErrorException
656    */
657   public Scene load(Reader reader) throws FileNotFoundException,
658                                           IncorrectFormatException,
659                                           ParsingErrorException
660   {
661     // That method calls the method that loads the file for real..
662     // Even if the Stl format is not complicated I've decided to use
663     // a parser as in the Obj's loader included in Java3D
664
665     StlFileParser st=new StlFileParser(reader);
666
667     // Initialize data
668     coordList = new ArrayList();
669     normList = new ArrayList();
670     setAscii(true);      // Default ascii
671
672     readFile(st);
673     return makeScene();
674   }
675
676   /**
677    * Method that takes the info from an ArrayList of Point3f
678    * and returns a Point3f[].
679    * Needed for ASCII files as we don't know the number of facets until the end
680    *
681    * @param inList The list to transform into Point3f[]
682    *
683    * @return Point3f[] The result.
684    */
685   private Point3f[] objectToPoint3Array(ArrayList inList)
686   {
687     Point3f outList[] = new Point3f[inList.size()];
688
689     for (int i = 0 ; i < inList.size() ; i++) {
690       outList[i] = (Point3f)inList.get(i);
691     }
692     return outList;
693   } // End of objectToPoint3Array
694
695   /**
696    * Method that takes the info from an ArrayList of Vector3f
697    * and returns a Vector3f[].
698    * Needed for ASCII files as we don't know the number of facets until the end
699    *
700    * TO-DO:
701    *  1.- Here we fill stripCounts...
702    *      Find a better place to do it?
703    *
704    * @param inList The list to transform into Point3f[]
705    *
706    * @return Vector3f[] The result.
707    */
708   private Vector3f[] objectToVectorArray(ArrayList inList)
709   {
710     Vector3f outList[] = new Vector3f[inList.size()];
711
712     if(DEBUG==1)
713       System.out.println("Number of facets of the object=" + inList.size());
714
715     // To-do
716     stripCounts = new int[inList.size()];
717     for (int i = 0 ; i < inList.size() ; i++) {
718       outList[i] = (Vector3f)inList.get(i);
719       // To-do
720       stripCounts[i]=3;
721     }
722     return outList;
723   } // End of objectToVectorArray
724
725   /**
726    * Method that creates the SceneBase with the stl file info
727    *
728    * @return SceneBase The scene
729    */
730   private SceneBase makeScene()
731   {
732     // Create Scene to pass back
733     SceneBase scene = new SceneBase();
734     BranchGroup group = new BranchGroup();
735     scene.setSceneGroup(group);
736
737     // Store the scene info on a GeometryInfo
738     GeometryInfo gi = new GeometryInfo(GeometryInfo.TRIANGLE_STRIP_ARRAY);
739
740     // Convert ArrayLists to arrays: only needed if file was not binary
741     if(this.Ascii)
742     {
743       coordArray = objectToPoint3Array(coordList);
744       normArray = objectToVectorArray(normList);
745     }
746
747     gi.setCoordinates(coordArray);
748     gi.setNormals(normArray);
749     gi.setStripCounts(stripCounts);
750
751     // Put geometry into Shape3d
752     Shape3D shape = new Shape3D();
753     shape.setGeometry(gi.getGeometryArray());
754
755     group.addChild(shape);
756     scene.addNamedObject(objectName, shape);
757
758     return scene;
759   } // end of makeScene
760
761   /////////////////////// Accessors and Modifiers ///////////////////////////
762
763   public URL getBaseUrl()
764   {
765     return baseUrl;
766   }
767
768   /**
769    * Modifier for baseUrl, if accessing internet.
770    *
771    * @param url The new url
772    */
773   public void setBaseUrl(URL url)
774   {
775     baseUrl = url;
776   }
777
778   private void setBaseUrlFromUrl(URL url)
779   {
780     StringTokenizer stok =
781       new StringTokenizer(url.toString(), "/\\", true);
782     int tocount = stok.countTokens() - 1;
783     StringBuffer sb = new StringBuffer(MAX_PATH_LENGTH);
784     for(int i = 0; i < tocount ; i++) {
785         String a = stok.nextToken();
786         sb.append(a);
787 //      if((i == 0) && (!a.equals("file:"))) {
788 //          sb.append(a);
789 //          sb.append(java.io.File.separator);
790 //          sb.append(java.io.File.separator);
791 //      } else {
792 //          sb.append(a);
793 //          sb.append( java.io.File.separator );
794 //      }
795     }
796     try {
797       baseUrl = new URL(sb.toString());
798     }
799     catch (MalformedURLException e) {
800       System.err.println("Error setting base URL: " + e.getMessage());
801     }
802   } // End of setBaseUrlFromUrl
803
804
805   public String getBasePath()
806   {
807     return basePath;
808   }
809
810   /**
811    * Set the path where files associated with this .stl file are
812    * located.
813    * Only needs to be called to set it to a different directory
814    * from that containing the .stl file.
815    *
816    * @param pathName The new Path to the file
817    */
818   public void setBasePath(String pathName)
819   {
820     basePath = pathName;
821     if (basePath == null || basePath == "")
822         basePath = "." + java.io.File.separator;
823     basePath = basePath.replace('/', java.io.File.separatorChar);
824     basePath = basePath.replace('\\', java.io.File.separatorChar);
825     if (!basePath.endsWith(java.io.File.separator))
826         basePath = basePath + java.io.File.separator;
827   } // End of setBasePath
828
829   /*
830    * Takes a file name and sets the base path to the directory
831    * containing that file.
832    */
833   private void setBasePathFromFilename(String fileName)
834   {
835     // Get ready to parse the file name
836     StringTokenizer stok =
837       new StringTokenizer(fileName, java.io.File.separator);
838
839     //  Get memory in which to put the path
840     StringBuffer sb = new StringBuffer(MAX_PATH_LENGTH);
841
842     // Check for initial slash
843     if (fileName!= null && fileName.startsWith(java.io.File.separator))
844       sb.append(java.io.File.separator);
845
846     // Copy everything into path except the file name
847     for(int i = stok.countTokens() - 1 ; i > 0 ; i--) {
848       String a = stok.nextToken();
849       sb.append(a);
850       sb.append(java.io.File.separator);
851     }
852     setBasePath(sb.toString());
853   } // End of setBasePathFromFilename
854
855   public int getFlags()
856   {
857     return flag;
858   }
859
860   public void setFlags(int parm)
861   {
862     this.flag=parm;
863   }
864
865   public boolean getAscii()
866   {
867     return this.Ascii;
868   }
869
870   public void setAscii(boolean tipo)
871   {
872     this.Ascii = tipo;
873   }
874
875
876   public String getFileName()
877   {
878     return this.fileName;
879   }
880
881   public void setFileName(String filename)
882   {
883     this.fileName=new String(filename);
884   }
885
886
887   public String getObjectName()
888   {
889     return this.objectName;
890   }
891
892   public void setObjectName(String name)
893   {
894     this.objectName = name;
895   }
896
897 } // End of package stl_loader