checkpoint
[anneal.git] / src / StlFile.java
1 import com.sun.j3d.loaders.Loader;
2 import com.sun.j3d.loaders.Scene;
3 import com.sun.j3d.loaders.SceneBase;
4 import com.sun.j3d.loaders.IncorrectFormatException;
5 import com.sun.j3d.loaders.ParsingErrorException;
6 import com.sun.j3d.utils.geometry.GeometryInfo;
7
8 import java.net.URL;
9 import java.net.MalformedURLException;
10
11 import java.io.Reader;
12 import java.io.BufferedReader;
13 import java.io.FileReader;
14 import java.io.InputStreamReader;
15 import java.io.FileInputStream;
16 import java.io.FileNotFoundException;
17 import java.io.IOException;
18
19 import java.util.StringTokenizer;
20 import java.util.ArrayList;
21
22 import javax.vecmath.Point3f;
23 import javax.vecmath.Vector3f;
24
25 import javax.media.j3d.BranchGroup;
26 import javax.media.j3d.Shape3D;
27
28 // New from JDK 1.4 for endian related problems
29 import java.nio.ByteOrder;
30 import java.nio.ByteBuffer;
31
32
33
34 /**
35  * Title:         STL Loader
36  * Description:   STL files loader (Supports ASCII and binary files) for Java3D
37  *                Needs JDK 1.4 due to endian problems
38  * Company:       Universidad del Pais Vasco (UPV/EHU)
39  * @author:       Carlos Pedrinaci Godoy
40  * @version:      1.0
41  *
42  * Contact : xenicp@yahoo.es
43  *
44  *
45  * Things TO-DO:
46  *    1.-We can't read binary files over the net.
47  *    2.-For binary files if size is lower than expected (calculated with the number of faces)
48  *    the program will block.
49  *    3.-Improve the way for detecting the kind of stl file?
50  *    Can give us problems if the comment of the binary file begins by "solid"
51  */
52
53 public class StlFile implements Loader
54 {
55   private static final int DEBUG = 0;     // Sets mode to Debug: outputs every action done
56
57   // Maximum length (in chars) of basePath
58   private static final int MAX_PATH_LENGTH = 1024;
59
60   // Global variables
61   private int flag;                         // Needed cause implements Loader
62
63   private URL baseUrl = null;               // Reading files over Internet
64   private String basePath = null;           // For local files
65
66   private boolean fromUrl = false;          // Usefull for binary files
67   private boolean Ascii = true;             // File type Ascii -> true o binary -> false
68   private String fileName = null;
69
70   // Arrays with coordinates and normals
71   // Needed for reading ASCII files because its size is unknown until the end
72   private ArrayList coordList;          // Holds Point3f
73   private ArrayList normList;           // Holds Vector3f
74
75   // GeometryInfo needs Arrays
76     public Point3f[] coordArray = null;
77     public Vector3f[] normArray = null;
78
79   // Needed because TRIANGLE_STRIP_ARRAY
80   // As the number of strips = the number of faces it's filled in objectToVectorArray
81     public int[] stripCounts = null;
82
83   // Default = Not available
84   private String objectName=new String("Not available");
85
86   /**
87   *  Constructor
88   */
89   public StlFile()
90   {
91   }
92
93   /**
94    * Method that reads the EOL
95    * Needed for verifying that the file has a correct format
96    *
97    * @param parser The file parser. An instance of StlFileParser.
98    */
99   private void readEOL(StlFileParser parser)
100   {
101     try{
102     parser.nextToken();
103     }
104     catch (IOException e)
105     {
106       System.err.println("IO Error on line " + parser.lineno() + ": " + e.getMessage());
107     }
108     if(parser.ttype != StlFileParser.TT_EOL)
109     {
110       System.err.println("Format Error:expecting End Of Line on line " + parser.lineno());
111     }
112   }
113
114   /**
115    * Method that reads the word "solid" and stores the object name.
116    * It also detects what kind of file it is
117    * TO-DO:
118    *    1.- Better way control of exceptions?
119    *    2.- Better way to decide between Ascii and Binary?
120    *
121    * @param parser The file parser. An instance of StlFileParser.
122    */
123   private void readSolid(StlFileParser parser)
124   {
125     if( !parser.sval.equals("solid"))
126     {
127       //System.out.println("Expecting solid on line " + parser.lineno());
128       // If the first word is not "solid" then we consider the file is binary
129       // Can give us problems if the comment of the binary file begins by "solid"
130       this.setAscii(false);
131     }
132     else  // It's an ASCII file
133     {
134       try{
135           parser.nextToken();
136           }
137       catch (IOException e)
138       {
139         System.err.println("IO Error on line " + parser.lineno() + ": " + e.getMessage());
140       }
141       if( parser.ttype != StlFileParser.TT_WORD)
142       {
143         // Is the object name always provided???
144         System.err.println("Format Error:expecting the object name on line " + parser.lineno());
145       }
146       else
147       { // Store the object Name
148         this.setObjectName(new String(parser.sval));
149         if(DEBUG==1)
150         {
151           System.out.println("Object Name:" + this.getObjectName().toString());
152         }
153         this.readEOL(parser);
154       }
155     }
156   }//End of readSolid
157
158   /**
159    * Method that reads a normal
160    *
161    * @param parser The file parser. An instance of StlFileParser.
162    */
163   private void readNormal(StlFileParser parser)
164   {
165     Vector3f v = new Vector3f();
166
167     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("normal")))
168     {
169       System.err.println("Format Error:expecting 'normal' on line " + parser.lineno());
170     }
171     else
172     {
173       if (parser.getNumber())
174       {
175         v.x=(float)parser.nval;
176
177         if(DEBUG==1)
178         {
179           System.out.println("Normal:");
180           System.out.print("X=" + v.x + " ");
181         }
182
183         if (parser.getNumber())
184         {
185           v.y=(float)parser.nval;
186           if(DEBUG==1)
187             System.out.print("Y=" + v.y + " ");
188
189           if (parser.getNumber())
190           {
191             v.z=(float)parser.nval;
192             if(DEBUG==1)
193               System.out.println("Z=" + v.z);
194
195             // We add that vector to the Normal's array
196             this.normList.add(v);
197             this.readEOL(parser);
198           }
199           else System.err.println("Format Error:expecting coordinate on line " + parser.lineno());
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   }// End of Read Normal
206
207   /**
208    * Method that reads the coordinates of a vector
209    *
210    * @param parser The file parser. An instance of StlFileParser.
211    */
212   private void readVertex(StlFileParser parser)
213   {
214     Point3f p = new Point3f();
215
216     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("vertex")))
217     {
218       System.err.println("Format Error:expecting 'vertex' on line " + parser.lineno());
219     }
220     else
221     {
222       if (parser.getNumber())
223       {
224         p.x=(float)parser.nval;
225
226         if(DEBUG==1)
227         {
228           System.out.println("Vertex:");
229           System.out.print("X=" + p.x + " ");
230         }
231
232         if (parser.getNumber())
233         {
234           p.y=(float)parser.nval;
235           if(DEBUG==1)
236             System.out.print("Y=" + p.y + " ");
237
238           if (parser.getNumber())
239           {
240             p.z=(float)parser.nval;
241             if(DEBUG==1)
242               System.out.println("Z=" + p.z);
243
244             // We add that vertex to the array of vertex
245             coordList.add(p);
246             readEOL(parser);
247           }
248           else System.err.println("Format Error: expecting coordinate on line " + parser.lineno());
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   }//End of read vertex
255
256   /**
257    * Method that reads "outer loop" and then EOL
258    *
259    * @param parser The file parser. An instance of StlFileParser.
260    */
261   private void readLoop(StlFileParser parser)
262   {
263     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("outer")))
264     {
265       System.err.println("Format Error:expecting 'outer' on line " + parser.lineno());
266     }
267     else
268     {
269       try{
270           parser.nextToken();
271           }
272       catch (IOException e)
273       {
274         System.err.println("IO error on line " + parser.lineno() + ": " + e.getMessage());
275       }
276       if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("loop")))
277       {
278         System.err.println("Format Error:expecting 'loop' on line " + parser.lineno());
279       }
280       else readEOL(parser);
281     }
282   }//End of readLoop
283
284   /**
285    * Method that reads "endloop" then EOL
286    *
287    * @param parser The file parser. An instance of StlFileParser.
288    */
289   private void readEndLoop(StlFileParser parser)
290   {
291     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("endloop")))
292     {
293       System.err.println("Format Error:expecting 'endloop' on line " + parser.lineno());
294     }
295     else readEOL(parser);
296   }//End of readEndLoop
297
298   /**
299    * Method that reads "endfacet" then EOL
300    *
301    * @param parser The file parser. An instance of StlFileParser.
302    */
303   private void readEndFacet(StlFileParser parser)
304   {
305     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("endfacet")))
306     {
307       System.err.println("Format Error:expecting 'endfacet' on line " + parser.lineno());
308     }
309     else readEOL(parser);
310   }//End of readEndFacet
311
312   /**
313    * Method that reads a face of the object
314    * (Cares about the format)
315    *
316    * @param parser The file parser. An instance of StlFileParser.
317    */
318   private void readFacet(StlFileParser parser)
319   {
320     if(!(parser.ttype==StlFileParser.TT_WORD && parser.sval.equals("facet")))
321     {
322       System.err.println("Format Error:expecting 'facet' on line " + parser.lineno());
323     }
324     else
325     {
326       try{
327           parser.nextToken();
328           readNormal(parser);
329
330           parser.nextToken();
331           readLoop(parser);
332
333           parser.nextToken();
334           readVertex(parser);
335
336           parser.nextToken();
337           readVertex(parser);
338
339           parser.nextToken();
340           readVertex(parser);
341
342           parser.nextToken();
343           readEndLoop(parser);
344
345           parser.nextToken();
346           readEndFacet(parser);
347       }
348       catch (IOException e)
349       {
350         System.err.println("IO Error on line " + parser.lineno() + ": " + e.getMessage());
351       }
352     }
353   }// End of readFacet
354
355   /**
356    * Method that reads a face in binary files
357    * All binary versions of the methods end by 'B'
358    * As in binary files we can read the number of faces, we don't need
359    * to use coordArray and normArray (reading binary files should be faster)
360    *
361    * @param in The ByteBuffer with the data of the object.
362    * @param index The facet index
363    *
364    * @throws IOException
365    */
366   private void readFacetB(ByteBuffer in, int index) throws IOException
367   {
368     //File structure: Normal Vertex1 Vertex2 Vertex3
369     Vector3f normal = new Vector3f();
370     Point3f vertex = new Point3f();
371
372     if(DEBUG==1)
373       System.out.println("Reading face number " + index);
374
375     // Read the Normal
376     normArray[index]=new Vector3f();
377     normArray[index].x=in.getFloat();
378     normArray[index].y=in.getFloat();
379     normArray[index].z=in.getFloat();
380
381     if(DEBUG==1)
382       System.out.println("Normal: X=" + normArray[index].x + " Y=" + normArray[index].y + " Z=" + normArray[index].z);
383
384     // Read vertex1
385     coordArray[index*3] = new Point3f();
386     coordArray[index*3].x=in.getFloat();
387     coordArray[index*3].y=in.getFloat();
388     coordArray[index*3].z=in.getFloat();
389
390     if(DEBUG==1)
391       System.out.println("Vertex 1: X=" + coordArray[index*3].x + " Y=" + coordArray[index*3].y + " Z=" + coordArray[index*3].z);
392
393     // Read vertex2
394     coordArray[index*3+1] = new Point3f();
395     coordArray[index*3+1].x=in.getFloat();
396     coordArray[index*3+1].y=in.getFloat();
397     coordArray[index*3+1].z=in.getFloat();
398
399     if(DEBUG==1)
400       System.out.println("Vertex 2: X=" + coordArray[index*3+1].x + " Y=" + coordArray[index*3+1].y + " Z=" + coordArray[index*3+1].z);
401
402     // Read vertex3
403     coordArray[index*3+2] = new Point3f();
404     coordArray[index*3+2].x=in.getFloat();
405     coordArray[index*3+2].y=in.getFloat();
406     coordArray[index*3+2].z=in.getFloat();
407
408     if(DEBUG==1)
409       System.out.println("Vertex 3: X=" + coordArray[index*3+2].x + " Y=" + coordArray[index*3+2].y + " Z=" + coordArray[index*3+2].z);
410
411   }// End of readFacetB
412
413   /**
414    * Method for reading binary files
415    * Execution is completly different
416    * It uses ByteBuffer for reading data and ByteOrder for retrieving the machine's endian
417    * (Needs JDK 1.4)
418    *
419    * TO-DO:
420    *  1.-Be able to read files over Internet
421    *  2.-If the amount of data expected is bigger than what is on the file then
422    *  the program will block forever
423    *
424    * @param file The name of the file
425    *
426    * @throws IOException
427    */
428   private void readBinaryFile(String file) throws IOException
429   {
430     FileInputStream data;                 // For reading the file
431     ByteBuffer dataBuffer;                // For reading in the correct endian
432     byte[] Info=new byte[80];             // Header data
433     byte[] Array_number= new byte[4];     // Holds the number of faces
434     byte[] Temp_Info;                     // Intermediate array
435
436     int Number_faces; // First info (after the header) on the file
437
438     if(DEBUG==1)
439       System.out.println("Machine's endian: " + ByteOrder.nativeOrder());
440
441     // Get file's name
442     if(fromUrl)
443     {
444       // FileInputStream can only read local files!?
445       System.out.println("This version doesn't support reading binary files from internet");
446     }
447     else
448     { // It's a local file
449       data = new FileInputStream(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());
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