In visuallization GUI, fix the surface saving issues with .ply and .stl
authorruida@NIH.GOV <ruida@NIH.GOV@ba61647d-9d00-f842-95cd-605cb4296b96>
Thu, 15 Feb 2018 22:01:39 +0000 (22:01 +0000)
committerruida@NIH.GOV <ruida@NIH.GOV@ba61647d-9d00-f842-95cd-605cb4296b96>
Thu, 15 Feb 2018 22:01:39 +0000 (22:01 +0000)
git-svn-id: https://citdcbmipav.cit.nih.gov/repos-pub/mipav/trunk@15378 ba61647d-9d00-f842-95cd-605cb4296b96

mipav/src/gov/nih/mipav/view/renderer/WildMagic/Interface/FileSurface_WM.java
mipav/src/gov/nih/mipav/view/renderer/WildMagic/Interface/JPanelSurface_WM.java

index 4e16ae5..469436b 100644 (file)
@@ -1,6 +1,5 @@
 package gov.nih.mipav.view.renderer.WildMagic.Interface;\r
 \r
 package gov.nih.mipav.view.renderer.WildMagic.Interface;\r
 \r
-\r
 import gov.nih.mipav.util.MipavCoordinateSystems;\r
 import gov.nih.mipav.model.file.FileBase;\r
 import gov.nih.mipav.model.file.FileInfoSurfaceRefXML;\r
 import gov.nih.mipav.util.MipavCoordinateSystems;\r
 import gov.nih.mipav.model.file.FileBase;\r
 import gov.nih.mipav.model.file.FileInfoSurfaceRefXML;\r
@@ -16,7 +15,6 @@ import gov.nih.mipav.view.renderer.J3D.surfaceview.JPanelSurface;
 import gov.nih.mipav.view.renderer.J3D.surfaceview.SurfaceAttributes;\r
 import gov.nih.mipav.view.renderer.J3D.surfaceview.SurfaceRender;\r
 \r
 import gov.nih.mipav.view.renderer.J3D.surfaceview.SurfaceAttributes;\r
 import gov.nih.mipav.view.renderer.J3D.surfaceview.SurfaceRender;\r
 \r
-\r
 import java.io.BufferedInputStream;\r
 import java.io.BufferedReader;\r
 import java.io.DataInputStream;\r
 import java.io.BufferedInputStream;\r
 import java.io.BufferedReader;\r
 import java.io.DataInputStream;\r
@@ -58,2219 +56,2285 @@ import WildMagic.LibGraphics.SceneGraph.VertexBuffer;
 import javax.vecmath.Point3f;\r
 \r
 /**\r
 import javax.vecmath.Point3f;\r
 \r
 /**\r
- * FileSurface. Reads and writes surface files for the JPanelSurface class. When surface files are loaded by the user in\r
- * the JPanelSurface.java class through the "Add" button, when surfaces are loaded as surfaces attached to .xml image\r
- * files, or surfaces loaded through the FlyThruRender class. Any time a surface file is read from disk for display in\r
- * the JPanelSurface (SurfaceRender) class the FileSurface.java class is used to provide the interface. Loaded surfaces\r
- * are returned in an array of SurfaceAttributes[] which are then used to add the surfaces to the SurfaceRender scene\r
- * graph.\r
+ * FileSurface. Reads and writes surface files for the JPanelSurface class. When\r
+ * surface files are loaded by the user in the JPanelSurface.java class through\r
+ * the "Add" button, when surfaces are loaded as surfaces attached to .xml image\r
+ * files, or surfaces loaded through the FlyThruRender class. Any time a surface\r
+ * file is read from disk for display in the JPanelSurface (SurfaceRender) class\r
+ * the FileSurface.java class is used to provide the interface. Loaded surfaces\r
+ * are returned in an array of SurfaceAttributes[] which are then used to add\r
+ * the surfaces to the SurfaceRender scene graph.\r
  *\r
  *\r
- * <p>This class also handles saving files from the JPanelSurface class. Surfaces are saved as surface files (.sur),\r
- * single-level (.wrl), multi-level (.wrl) or XML surfaces (.xml).</p>\r
+ * <p>\r
+ * This class also handles saving files from the JPanelSurface class. Surfaces\r
+ * are saved as surface files (.sur), single-level (.wrl), multi-level (.wrl) or\r
+ * XML surfaces (.xml).\r
+ * </p>\r
  *\r
  *\r
- * @see  JPanelSurface.java\r
- * @see  SurfaceRender.java\r
- * @see  SurfaceAttributes.java\r
- * @see  FileSurfaceXML.java\r
+ * @see JPanelSurface.java\r
+ * @see SurfaceRender.java\r
+ * @see SurfaceAttributes.java\r
+ * @see FileSurfaceXML.java\r
  */\r
 public class FileSurface_WM {\r
 \r
        /** flag indicates to flip y, z coordinate or not. */\r
        private static boolean flip;\r
  */\r
 public class FileSurface_WM {\r
 \r
        /** flag indicates to flip y, z coordinate or not. */\r
        private static boolean flip;\r
-       \r
+\r
        /** flag indicates to read dicom matrix or not. */\r
        private static boolean dicom;\r
        /** flag indicates to read dicom matrix or not. */\r
        private static boolean dicom;\r
-       \r
+\r
        /** inverse dicom matrix array. */\r
        private static double[][] inverseDicomArray;\r
        /** inverse dicom matrix array. */\r
        private static double[][] inverseDicomArray;\r
-       \r
+\r
        /** inverset dicom matrix. */\r
        private static TransMatrix inverseDicomMatrix = new TransMatrix(4);\r
        /** inverset dicom matrix. */\r
        private static TransMatrix inverseDicomMatrix = new TransMatrix(4);\r
-       \r
+\r
        /** image x, y, z orientation. */\r
        private static int[] direction = new int[3];\r
        /** image x, y, z orientation. */\r
        private static int[] direction = new int[3];\r
-       \r
+\r
        /** image start location. */\r
        private static float[] startLocation = new float[3];\r
        /** image start location. */\r
        private static float[] startLocation = new float[3];\r
-       \r
+\r
        /** image volume bounding box. */\r
        private static float[] box = new float[3];\r
        /** image volume bounding box. */\r
        private static float[] box = new float[3];\r
-       \r
-       /** coordinate used to transform data point from image coordinate to dicom coordinate. */\r
+\r
+       /**\r
+        * coordinate used to transform data point from image coordinate to dicom\r
+        * coordinate.\r
+        */\r
        private static float[] tCoord = new float[3];\r
        private static float[] tCoord = new float[3];\r
-       \r
-       /** coordinate used to transform data point from image coordinate to dicom coordinate */\r
+\r
+       /**\r
+        * coordinate used to transform data point from image coordinate to dicom\r
+        * coordinate\r
+        */\r
        private static float[] coord = new float[3];\r
        private static float[] coord = new float[3];\r
-       \r
+\r
        /** dicom matrix file. */\r
        private static File dicomMatrixFile = null;\r
        /** dicom matrix file. */\r
        private static File dicomMatrixFile = null;\r
-       \r
-         // GeometryInfo needs Arrays\r
-         private Point3f[] coordArray = null;\r
-         private Vector3f[] normArray = null;\r
-\r
-         // Needed because TRIANGLE_STRIP_ARRAY\r
-         // As the number of strips = the number of faces it's filled in objectToVectorArray\r
-         private int[] stripCounts = null;\r
-       \r
-       //~ Methods --------------------------------------------------------------------------------------------------------\r
-\r
-    /**\r
-     * Load the clod mesh from a binary file. The caller must have already opened the file and read the mesh type (0 =\r
-     * TriMesh, 1 = ModelClodMesh) and the number of meshes in the file. The caller then calls this function\r
-     * for each mesh. The format for a mesh is\r
-     *\r
-     * <pre>\r
-     int vCount;  // number of vertices\r
-     Point3f vertices[vCount];\r
-     Point3f normals[vCount];\r
-     int iCount;  // number of indices in the connectivity array\r
-     int indices[iCount];\r
-     int rCount;\r
-     ModelCollapseRecord collapses[rCount];\r
-     * </pre>\r
-     *\r
-     * with 4-byte quantities stored in Big Endian format.\r
-     *\r
-     * @param      kIn    the file from which the triangle mesh is loaded\r
-     * @param      pBar   DOCUMENT ME!\r
-     * @param      added  DOCUMENT ME!\r
-     * @param      piece  DOCUMENT ME!\r
-     *\r
-     * @return     the loaded triangle mesh\r
-     *\r
-     * @exception  IOException  if there is an error reading from the file\r
-     */\r
-    public static ClodMesh loadCMesh(RandomAccessFile kIn, ViewJProgressBar pBar, int added, int piece)\r
-    {\r
-        MaterialState kMaterial = new MaterialState();\r
-        float[] startLocation = new float[3];\r
-        float[] direction = new float[3];\r
-        float[] box = new float[3]; \r
-        TriMesh kMesh = loadTMesh(kIn, pBar, added, piece,\r
-                true, kMaterial,\r
-                startLocation, direction, box );\r
-        \r
-        try {\r
-            int iRecordCount = kIn.readInt();\r
-            CollapseRecord[] akRecord = new CollapseRecord[iRecordCount];\r
-            int prog = iRecordCount * piece / 25;\r
-\r
-            for (int i = 0; i < iRecordCount; i++) {\r
-                akRecord[i] = load(kIn);\r
-\r
-                if ((pBar != null) && (prog != 0) && ((i % prog) == 0)) {\r
-                    pBar.updateValueImmed(Math.round(75 / piece) + added + (i / prog));\r
-                    pBar.update(pBar.getGraphics());\r
-                }\r
-            }\r
-\r
-            return new ClodMesh( kMesh.VBuffer, \r
-                                 kMesh.IBuffer, new CollapseRecordArray(iRecordCount,akRecord));\r
-        } catch (IOException e) {\r
-            return null;\r
-        }\r
-    }\r
-\r
-\r
-    /**\r
-     * Load the TriMesh from a binary file. The caller must have already opened the file and read the mesh type (0 =\r
-     * TriMesh, 1 = ClodMesh) and the number of meshes in the file. The caller then calls this function\r
-     * for each mesh. The format for a mesh is\r
-     *\r
-     * <pre>\r
-     int vCount;  // number of vertices\r
-     Point3f vertices[vCount];\r
-     Point3f normals[vCount];\r
-     int iCount;  // number of indices in the connectivity array\r
-     int indices[iCount];\r
-     * @param kIn file containing TriMesh data\r
-     * @param progress progress bar\r
-     * @param added number of meshes added so far\r
-     * @param total total number of meshes to add\r
-     * @param isVisible sets the visibility of the progress bar\r
-     * @param kMaterial MaterialState for the new mesh\r
-     * @param startLocation 3D location of the mesh\r
-     * @param direction 3D orientation of the mesh\r
-     * @param box mesh bounding box\r
-     * @return new TriMesh\r
-     */\r
-    public static TriMesh loadTMesh(RandomAccessFile kIn, ViewJProgressBar progress,\r
-                                    int added, int total, boolean isVisible, MaterialState kMaterial,\r
-                                    float[] startLocation, float[] direction, float[] box )\r
-{\r
-\r
-        try {\r
-            int i, index, tmpInt;\r
-            int b1 = 0, b2 = 0, b3 = 0, b4 = 0;\r
-            int actions;\r
-            boolean flip;\r
-            boolean dicom;\r
-            long c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0, c7 = 0, c8 = 0;\r
-            long tmpLong;\r
-            int j;\r
-            double[][] inverseDicomArray;\r
-            TransMatrix inverseDicomMatrix = new TransMatrix(4);\r
-            float[] tCoord = new float[3];\r
-            float[] coord = new float[3];\r
-\r
-            actions = kIn.readInt();\r
-\r
-            if ((actions == 1) || (actions == 3)) {\r
-                flip = true;\r
-            } else {\r
-                flip = false;\r
-            }\r
-            flip = !flip;\r
-            if ((actions == 2) || (actions == 3)) {\r
-                dicom = true;\r
-            } else {\r
-                dicom = false;\r
-            }\r
-\r
-            direction[0] = kIn.readInt();\r
-            direction[1] = kIn.readInt();\r
-            direction[2] = kIn.readInt();\r
-\r
-            byte[] buffer = new byte[24];\r
-\r
-            kIn.read(buffer);\r
-            index = 0;\r
-            b1 = buffer[index++] & 0xff;\r
-            b2 = buffer[index++] & 0xff;\r
-            b3 = buffer[index++] & 0xff;\r
-            b4 = buffer[index++] & 0xff;\r
-\r
-            tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-\r
-            startLocation[0] = Float.intBitsToFloat(tmpInt);\r
-\r
-            b1 = buffer[index++] & 0xff;\r
-            b2 = buffer[index++] & 0xff;\r
-            b3 = buffer[index++] & 0xff;\r
-            b4 = buffer[index++] & 0xff;\r
-\r
-            tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-\r
-            startLocation[1] = Float.intBitsToFloat(tmpInt);\r
-\r
-            b1 = buffer[index++] & 0xff;\r
-            b2 = buffer[index++] & 0xff;\r
-            b3 = buffer[index++] & 0xff;\r
-            b4 = buffer[index++] & 0xff;\r
-\r
-            tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-\r
-            startLocation[2] = Float.intBitsToFloat(tmpInt);\r
-            \r
-            b1 = buffer[index++] & 0xff;\r
-            b2 = buffer[index++] & 0xff;\r
-            b3 = buffer[index++] & 0xff;\r
-            b4 = buffer[index++] & 0xff;\r
-\r
-            tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-\r
-            box[0] = Float.intBitsToFloat(tmpInt);\r
-\r
-            b1 = buffer[index++] & 0xff;\r
-            b2 = buffer[index++] & 0xff;\r
-            b3 = buffer[index++] & 0xff;\r
-            b4 = buffer[index++] & 0xff;\r
-\r
-            tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-\r
-            box[1] = Float.intBitsToFloat(tmpInt);\r
-\r
-            b1 = buffer[index++] & 0xff;\r
-            b2 = buffer[index++] & 0xff;\r
-            b3 = buffer[index++] & 0xff;\r
-            b4 = buffer[index++] & 0xff;\r
-\r
-            tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-\r
-            box[2] = Float.intBitsToFloat(tmpInt);\r
-            \r
-            if (dicom) {\r
-                buffer = new byte[128];\r
-                kIn.read(buffer);\r
-                index = 0;\r
-                inverseDicomArray = new double[4][4];\r
-\r
-                for (i = 0; i <= 3; i++) {\r
 \r
 \r
-                    for (j = 0; j <= 3; j++) {\r
-                        c1 = buffer[index++] & 0xffL;\r
-                        c2 = buffer[index++] & 0xffL;\r
-                        c3 = buffer[index++] & 0xffL;\r
-                        c4 = buffer[index++] & 0xffL;\r
-                        c5 = buffer[index++] & 0xffL;\r
-                        c6 = buffer[index++] & 0xffL;\r
-                        c7 = buffer[index++] & 0xffL;\r
-                        c8 = buffer[index++] & 0xffL;\r
-                        tmpLong = ((c1 << 56) | (c2 << 48) | (c3 << 40) | (c4 << 32) | (c5 << 24) | (c6 << 16) |\r
-                                   (c7 << 8) | c8);\r
-                        inverseDicomArray[i][j] = Double.longBitsToDouble(tmpLong);\r
-                    }\r
-                }\r
+       // GeometryInfo needs Arrays\r
+       private Point3f[] coordArray = null;\r
+       private Vector3f[] normArray = null;\r
+\r
+       // Needed because TRIANGLE_STRIP_ARRAY\r
+       // As the number of strips = the number of faces it's filled in\r
+       // objectToVectorArray\r
+       private int[] stripCounts = null;\r
+\r
+       // ~ Methods\r
+       // --------------------------------------------------------------------------------------------------------\r
+\r
+       /**\r
+        * Load the clod mesh from a binary file. The caller must have already opened\r
+        * the file and read the mesh type (0 = TriMesh, 1 = ModelClodMesh) and the\r
+        * number of meshes in the file. The caller then calls this function for each\r
+        * mesh. The format for a mesh is\r
+        *\r
+        * <pre>\r
+        int vCount;  // number of vertices\r
+        Point3f vertices[vCount];\r
+        Point3f normals[vCount];\r
+        int iCount;  // number of indices in the connectivity array\r
+        int indices[iCount];\r
+        int rCount;\r
+        ModelCollapseRecord collapses[rCount];\r
+        * </pre>\r
+        *\r
+        * with 4-byte quantities stored in Big Endian format.\r
+        *\r
+        * @param kIn\r
+        *            the file from which the triangle mesh is loaded\r
+        * @param pBar\r
+        *            DOCUMENT ME!\r
+        * @param added\r
+        *            DOCUMENT ME!\r
+        * @param piece\r
+        *            DOCUMENT ME!\r
+        *\r
+        * @return the loaded triangle mesh\r
+        *\r
+        * @exception IOException\r
+        *                if there is an error reading from the file\r
+        */\r
+       public static ClodMesh loadCMesh(RandomAccessFile kIn, ViewJProgressBar pBar, int added, int piece) {\r
+               MaterialState kMaterial = new MaterialState();\r
+               float[] startLocation = new float[3];\r
+               float[] direction = new float[3];\r
+               float[] box = new float[3];\r
+               TriMesh kMesh = loadTMesh(kIn, pBar, added, piece, true, kMaterial, startLocation, direction, box);\r
+\r
+               try {\r
+                       int iRecordCount = kIn.readInt();\r
+                       CollapseRecord[] akRecord = new CollapseRecord[iRecordCount];\r
+                       int prog = iRecordCount * piece / 25;\r
+\r
+                       for (int i = 0; i < iRecordCount; i++) {\r
+                               akRecord[i] = load(kIn);\r
+\r
+                               if ((pBar != null) && (prog != 0) && ((i % prog) == 0)) {\r
+                                       pBar.updateValueImmed(Math.round(75 / piece) + added + (i / prog));\r
+                                       pBar.update(pBar.getGraphics());\r
+                               }\r
+                       }\r
+\r
+                       return new ClodMesh(kMesh.VBuffer, kMesh.IBuffer, new CollapseRecordArray(iRecordCount, akRecord));\r
+               } catch (IOException e) {\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Load the TriMesh from a binary file. The caller must have already opened the\r
+        * file and read the mesh type (0 = TriMesh, 1 = ClodMesh) and the number of\r
+        * meshes in the file. The caller then calls this function for each mesh. The\r
+        * format for a mesh is\r
+        *\r
+        * <pre>\r
+        * int vCount; // number of vertices Point3f vertices[vCount]; Point3f\r
+        * normals[vCount]; int iCount; // number of indices in the connectivity array\r
+        * int indices[iCount];\r
+        * \r
+        * @param kIn\r
+        *            file containing TriMesh data\r
+        * @param progress\r
+        *            progress bar\r
+        * @param added\r
+        *            number of meshes added so far\r
+        * @param total\r
+        *            total number of meshes to add\r
+        * @param isVisible\r
+        *            sets the visibility of the progress bar\r
+        * @param kMaterial\r
+        *            MaterialState for the new mesh\r
+        * @param startLocation\r
+        *            3D location of the mesh\r
+        * @param direction\r
+        *            3D orientation of the mesh\r
+        * @param box\r
+        *            mesh bounding box\r
+        * @return new TriMesh\r
+        */\r
+       public static TriMesh loadTMesh(RandomAccessFile kIn, ViewJProgressBar progress, int added, int total,\r
+                       boolean isVisible, MaterialState kMaterial, float[] startLocation, float[] direction, float[] box) {\r
+\r
+               try {\r
+                       int i, index, tmpInt;\r
+                       int b1 = 0, b2 = 0, b3 = 0, b4 = 0;\r
+                       int actions;\r
+                       boolean flip;\r
+                       boolean dicom;\r
+                       long c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0, c7 = 0, c8 = 0;\r
+                       long tmpLong;\r
+                       int j;\r
+                       double[][] inverseDicomArray;\r
+                       TransMatrix inverseDicomMatrix = new TransMatrix(4);\r
+                       float[] tCoord = new float[3];\r
+                       float[] coord = new float[3];\r
+\r
+                       actions = kIn.readInt();\r
+\r
+                       if ((actions == 1) || (actions == 3)) {\r
+                               flip = true;\r
+                       } else {\r
+                               flip = false;\r
+                       }\r
+                       flip = !flip;\r
+                       if ((actions == 2) || (actions == 3)) {\r
+                               dicom = true;\r
+                       } else {\r
+                               dicom = false;\r
+                       }\r
+\r
+                       direction[0] = kIn.readInt();\r
+                       direction[1] = kIn.readInt();\r
+                       direction[2] = kIn.readInt();\r
+\r
+                       byte[] buffer = new byte[24];\r
+\r
+                       kIn.read(buffer);\r
+                       index = 0;\r
+                       b1 = buffer[index++] & 0xff;\r
+                       b2 = buffer[index++] & 0xff;\r
+                       b3 = buffer[index++] & 0xff;\r
+                       b4 = buffer[index++] & 0xff;\r
+\r
+                       tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                       startLocation[0] = Float.intBitsToFloat(tmpInt);\r
+\r
+                       b1 = buffer[index++] & 0xff;\r
+                       b2 = buffer[index++] & 0xff;\r
+                       b3 = buffer[index++] & 0xff;\r
+                       b4 = buffer[index++] & 0xff;\r
+\r
+                       tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                       startLocation[1] = Float.intBitsToFloat(tmpInt);\r
+\r
+                       b1 = buffer[index++] & 0xff;\r
+                       b2 = buffer[index++] & 0xff;\r
+                       b3 = buffer[index++] & 0xff;\r
+                       b4 = buffer[index++] & 0xff;\r
 \r
 \r
-                inverseDicomMatrix.copyMatrix(inverseDicomArray);\r
+                       tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
 \r
 \r
-            } // if (dicom)\r
+                       startLocation[2] = Float.intBitsToFloat(tmpInt);\r
 \r
 \r
-            int iVertexCount = kIn.readInt();\r
-            Vector3f[] akVertex = new Vector3f[iVertexCount];\r
-            int bufferSize = 12 * iVertexCount;\r
-            byte[] bufferVertex = new byte[bufferSize];\r
-            byte[] bufferNormal = new byte[bufferSize];\r
+                       b1 = buffer[index++] & 0xff;\r
+                       b2 = buffer[index++] & 0xff;\r
+                       b3 = buffer[index++] & 0xff;\r
+                       b4 = buffer[index++] & 0xff;\r
 \r
 \r
-            progress.setLocation(200, 200);\r
-            progress.setVisible(isVisible);\r
+                       tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
 \r
 \r
-            //          read vertices\r
-            kIn.read(bufferVertex);\r
-            kIn.read(bufferNormal);\r
+                       box[0] = Float.intBitsToFloat(tmpInt);\r
 \r
 \r
-            for (i = 0, index = 0; i < iVertexCount; i++) {\r
-                akVertex[i] = new Vector3f();\r
+                       b1 = buffer[index++] & 0xff;\r
+                       b2 = buffer[index++] & 0xff;\r
+                       b3 = buffer[index++] & 0xff;\r
+                       b4 = buffer[index++] & 0xff;\r
 \r
 \r
-                b1 = bufferVertex[index++] & 0xff;\r
-                b2 = bufferVertex[index++] & 0xff;\r
-                b3 = bufferVertex[index++] & 0xff;\r
-                b4 = bufferVertex[index++] & 0xff;\r
+                       tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
 \r
 \r
-                tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+                       box[1] = Float.intBitsToFloat(tmpInt);\r
 \r
 \r
-                akVertex[i].X = Float.intBitsToFloat(tmpInt);\r
+                       b1 = buffer[index++] & 0xff;\r
+                       b2 = buffer[index++] & 0xff;\r
+                       b3 = buffer[index++] & 0xff;\r
+                       b4 = buffer[index++] & 0xff;\r
 \r
 \r
-                b1 = bufferVertex[index++] & 0xff;\r
-                b2 = bufferVertex[index++] & 0xff;\r
-                b3 = bufferVertex[index++] & 0xff;\r
-                b4 = bufferVertex[index++] & 0xff;\r
+                       tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
 \r
 \r
-                tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+                       box[2] = Float.intBitsToFloat(tmpInt);\r
 \r
 \r
-                akVertex[i].Y = Float.intBitsToFloat(tmpInt);\r
+                       if (dicom) {\r
+                               buffer = new byte[128];\r
+                               kIn.read(buffer);\r
+                               index = 0;\r
+                               inverseDicomArray = new double[4][4];\r
 \r
 \r
-                b1 = bufferVertex[index++] & 0xff;\r
-                b2 = bufferVertex[index++] & 0xff;\r
-                b3 = bufferVertex[index++] & 0xff;\r
-                b4 = bufferVertex[index++] & 0xff;\r
+                               for (i = 0; i <= 3; i++) {\r
 \r
 \r
-                tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+                                       for (j = 0; j <= 3; j++) {\r
+                                               c1 = buffer[index++] & 0xffL;\r
+                                               c2 = buffer[index++] & 0xffL;\r
+                                               c3 = buffer[index++] & 0xffL;\r
+                                               c4 = buffer[index++] & 0xffL;\r
+                                               c5 = buffer[index++] & 0xffL;\r
+                                               c6 = buffer[index++] & 0xffL;\r
+                                               c7 = buffer[index++] & 0xffL;\r
+                                               c8 = buffer[index++] & 0xffL;\r
+                                               tmpLong = ((c1 << 56) | (c2 << 48) | (c3 << 40) | (c4 << 32) | (c5 << 24) | (c6 << 16)\r
+                                                               | (c7 << 8) | c8);\r
+                                               inverseDicomArray[i][j] = Double.longBitsToDouble(tmpLong);\r
+                                       }\r
+                               }\r
 \r
 \r
-                akVertex[i].Z = Float.intBitsToFloat(tmpInt);\r
+                               inverseDicomMatrix.copyMatrix(inverseDicomArray);\r
 \r
 \r
-                if (dicom) {\r
-                    tCoord[0] = akVertex[i].X - startLocation[0];\r
-                    tCoord[1] = akVertex[i].Y - startLocation[1];\r
-                    tCoord[2] = akVertex[i].Z - startLocation[2];\r
-                    inverseDicomMatrix.transform(tCoord, coord);\r
-                    akVertex[i].X = (coord[0] * direction[0]) + startLocation[0];\r
-                    akVertex[i].Y = (coord[1] * direction[1]) + startLocation[1];\r
-                    akVertex[i].Z = (coord[2] * direction[2]) + startLocation[2];\r
-                } // if (dicom)\r
+                       } // if (dicom)\r
 \r
 \r
-                if (flip) {\r
+                       int iVertexCount = kIn.readInt();\r
+                       Vector3f[] akVertex = new Vector3f[iVertexCount];\r
+                       int bufferSize = 12 * iVertexCount;\r
+                       byte[] bufferVertex = new byte[bufferSize];\r
+                       byte[] bufferNormal = new byte[bufferSize];\r
 \r
 \r
-                    //                  Flip (kVertex.y - startLocation[1], but\r
-                    //                  don't flip startLocation[1]\r
-                    akVertex[i].Y = ( (2 * startLocation[1]) + (box[1] * direction[1]) - akVertex[i].Y );\r
-                    akVertex[i].Z = ( (2 * startLocation[2]) + (box[2] * direction[2]) - akVertex[i].Z );\r
-                }\r
+                       progress.setLocation(200, 200);\r
+                       progress.setVisible(isVisible);\r
 \r
 \r
-            }\r
+                       // read vertices\r
+                       kIn.read(bufferVertex);\r
+                       kIn.read(bufferNormal);\r
 \r
 \r
-            progress.updateValueImmed(added + (33 / total));\r
+                       for (i = 0, index = 0; i < iVertexCount; i++) {\r
+                               akVertex[i] = new Vector3f();\r
+\r
+                               b1 = bufferVertex[index++] & 0xff;\r
+                               b2 = bufferVertex[index++] & 0xff;\r
+                               b3 = bufferVertex[index++] & 0xff;\r
+                               b4 = bufferVertex[index++] & 0xff;\r
+\r
+                               tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                               akVertex[i].X = Float.intBitsToFloat(tmpInt);\r
+\r
+                               b1 = bufferVertex[index++] & 0xff;\r
+                               b2 = bufferVertex[index++] & 0xff;\r
+                               b3 = bufferVertex[index++] & 0xff;\r
+                               b4 = bufferVertex[index++] & 0xff;\r
+\r
+                               tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                               akVertex[i].Y = Float.intBitsToFloat(tmpInt);\r
+\r
+                               b1 = bufferVertex[index++] & 0xff;\r
+                               b2 = bufferVertex[index++] & 0xff;\r
+                               b3 = bufferVertex[index++] & 0xff;\r
+                               b4 = bufferVertex[index++] & 0xff;\r
+\r
+                               tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                               akVertex[i].Z = Float.intBitsToFloat(tmpInt);\r
+\r
+                               if (dicom) {\r
+                                       tCoord[0] = akVertex[i].X - startLocation[0];\r
+                                       tCoord[1] = akVertex[i].Y - startLocation[1];\r
+                                       tCoord[2] = akVertex[i].Z - startLocation[2];\r
+                                       inverseDicomMatrix.transform(tCoord, coord);\r
+                                       akVertex[i].X = (coord[0] * direction[0]) + startLocation[0];\r
+                                       akVertex[i].Y = (coord[1] * direction[1]) + startLocation[1];\r
+                                       akVertex[i].Z = (coord[2] * direction[2]) + startLocation[2];\r
+                               } // if (dicom)\r
+\r
+                               if (flip) {\r
+\r
+                                       // Flip (kVertex.y - startLocation[1], but\r
+                                       // don't flip startLocation[1]\r
+                                       akVertex[i].Y = ((2 * startLocation[1]) + (box[1] * direction[1]) - akVertex[i].Y);\r
+                                       akVertex[i].Z = ((2 * startLocation[2]) + (box[2] * direction[2]) - akVertex[i].Z);\r
+                               }\r
+\r
+                       }\r
+\r
+                       progress.updateValueImmed(added + (33 / total));\r
+\r
+                       // read normals\r
+                       Vector3f[] akNormal = new Vector3f[iVertexCount];\r
+\r
+                       for (i = 0, index = 0; i < iVertexCount; i++) {\r
+                               akNormal[i] = new Vector3f();\r
+\r
+                               b1 = bufferNormal[index++] & 0xff;\r
+                               b2 = bufferNormal[index++] & 0xff;\r
+                               b3 = bufferNormal[index++] & 0xff;\r
+                               b4 = bufferNormal[index++] & 0xff;\r
+\r
+                               tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                               akNormal[i].X = Float.intBitsToFloat(tmpInt);\r
+\r
+                               b1 = bufferNormal[index++] & 0xff;\r
+                               b2 = bufferNormal[index++] & 0xff;\r
+                               b3 = bufferNormal[index++] & 0xff;\r
+                               b4 = bufferNormal[index++] & 0xff;\r
+\r
+                               tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                               akNormal[i].Y = Float.intBitsToFloat(tmpInt);\r
+\r
+                               b1 = bufferNormal[index++] & 0xff;\r
+                               b2 = bufferNormal[index++] & 0xff;\r
+                               b3 = bufferNormal[index++] & 0xff;\r
+                               b4 = bufferNormal[index++] & 0xff;\r
+\r
+                               tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                               akNormal[i].Z = Float.intBitsToFloat(tmpInt);\r
+                       }\r
+\r
+                       progress.updateValueImmed(added + (66 / total));\r
+\r
+                       // read connectivity\r
+                       int iIndexCount = kIn.readInt();\r
+\r
+                       // System.out.println("connect count = " + iIndexCount);\r
+                       int[] aiConnect = new int[iIndexCount];\r
+                       byte[] bufferConnect = new byte[iIndexCount * 4];\r
+\r
+                       kIn.read(bufferConnect);\r
+\r
+                       for (i = 0, index = 0; i < iIndexCount; i++) {\r
+                               b1 = bufferConnect[index++] & 0x000000ff;\r
+                               b2 = bufferConnect[index++] & 0x000000ff;\r
+                               b3 = bufferConnect[index++] & 0x000000ff;\r
+                               b4 = bufferConnect[index++] & 0x000000ff;\r
+\r
+                               aiConnect[i] = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                               // System.out.println("connect[" + i + "]" + aiConnect[i]);\r
+                       }\r
+\r
+                       // read per vertex color array\r
+                       int R, G, B, A;\r
+                       int isPerVertexColor = kIn.readInt();\r
+                       ColorRGBA[] perVertexColor = null;\r
+                       if (isPerVertexColor == 1) {\r
+                               perVertexColor = new ColorRGBA[iVertexCount];\r
+                               byte[] bufferPerVertexColor = new byte[iVertexCount * 4 * 4];\r
+                               kIn.read(bufferPerVertexColor);\r
+                               for (i = 0, index = 0; i < iVertexCount; i++) {\r
+                                       perVertexColor[i] = new ColorRGBA();\r
+\r
+                                       b1 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b2 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b3 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b4 = bufferPerVertexColor[index++] & 0xff;\r
+\r
+                                       R = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                                       perVertexColor[i].R = Float.intBitsToFloat(R);\r
+\r
+                                       b1 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b2 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b3 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b4 = bufferPerVertexColor[index++] & 0xff;\r
+\r
+                                       G = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                                       perVertexColor[i].G = Float.intBitsToFloat(G);\r
+\r
+                                       b1 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b2 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b3 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b4 = bufferPerVertexColor[index++] & 0xff;\r
+\r
+                                       B = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                                       perVertexColor[i].B = Float.intBitsToFloat(B);\r
+\r
+                                       b1 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b2 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b3 = bufferPerVertexColor[index++] & 0xff;\r
+                                       b4 = bufferPerVertexColor[index++] & 0xff;\r
+\r
+                                       A = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+\r
+                                       perVertexColor[i].A = Float.intBitsToFloat(A);\r
+\r
+                               }\r
+                       }\r
+\r
+                       progress.updateValueImmed(added + (100 / total));\r
+\r
+                       Attributes kAttr = new Attributes();\r
+                       kAttr.SetPChannels(3);\r
+                       kAttr.SetNChannels(3);\r
+                       kAttr.SetTChannels(0, 3);\r
+                       kAttr.SetCChannels(0, 4);\r
+                       /*\r
+                        * if ( perVertexColor != null ) { kAttr.SetCChannels(1,4); }\r
+                        */\r
+                       VertexBuffer pkVB = new VertexBuffer(kAttr, iVertexCount);\r
+                       for (i = 0; i < iVertexCount; i++) {\r
+                               pkVB.SetPosition3(i, akVertex[i]);\r
+                               pkVB.SetNormal3(i, akNormal[i]);\r
+\r
+                               if (perVertexColor != null) {\r
+                                       pkVB.SetColor4(0, i, perVertexColor[i].R, perVertexColor[i].G, perVertexColor[i].B,\r
+                                                       perVertexColor[i].A);\r
+                               } else {\r
+                                       pkVB.SetColor4(0, i, 1f, 1f, 1f, 1f);\r
+                               }\r
+\r
+                       }\r
+                       IndexBuffer pkIB = new IndexBuffer(iIndexCount, aiConnect);\r
+                       TriMesh kMesh = new TriMesh(pkVB, pkIB);\r
+                       if (kMaterial != null) {\r
+                               kMesh.AttachGlobalState(kMaterial);\r
+                       }\r
+                       return kMesh;\r
+               } catch (IOException e) {\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Load the triangle mesh from a VRML file specifically written by MIPAV. The\r
+        * caller must have already opened the file.\r
+        * \r
+        * @param kIn\r
+        *            the file from which the triangle mesh is loaded\r
+        * @param progress\r
+        *            progress bar\r
+        * @param added\r
+        *            number of meshes added so far\r
+        * @param total\r
+        *            number of meshes to add\r
+        * @param flag\r
+        *            when true this is the first mesh, read header info.\r
+        * @param startLocation\r
+        *            3D location of mesh\r
+        * @param direction\r
+        *            3D orientation of mesh\r
+        * @param box\r
+        *            mesh bounding box\r
+        * @return new TriMesh\r
+        */\r
+       public static TriMesh loadVRMLMesh(RandomAccessFile kIn, ViewJProgressBar progress, int added, int total,\r
+                       boolean flag, float[] startLocation, float[] direction, float[] box) {\r
+\r
+               String str = null;\r
+               String str2 = null;\r
+               String str3 = null;\r
+               StringTokenizer stoken = null;\r
+               try {\r
+                       // read vertices\r
+                       if (flag) {\r
+\r
+                               if (kIn.getFilePointer() == 0) {\r
+                                       str = kIn.readLine().trim();\r
+                                       str2 = kIn.readLine().trim();\r
+                                       str3 = kIn.readLine().trim();\r
+\r
+                                       if (!str.equals("#VRML V2.0 utf8") || !str2.equals("#MIPAV")\r
+                                                       || (str3.indexOf("#Number of shapes =") == -1)) {\r
+                                               MipavUtil.displayWarning("File doesn't appear to be a VRML 2.0 file written by MIPAV");\r
+                                               Preferences.debug(\r
+                                                               "TriMesh.loadVRMLMesh: File doesn't appear to be a VRML 2.0 file written by MIPAV.\n");\r
+\r
+                                               // or throw error.\r
+                                               return null;\r
+                                       }\r
+\r
+                                       // read flip line\r
+                                       str = kIn.readLine().trim();\r
+                                       stoken = new StringTokenizer(str);\r
+\r
+                                       if (stoken.nextToken().equals("#flip")) {\r
+                                               stoken.nextToken();\r
+                                       }\r
+\r
+                                       // read direction line\r
+                                       str = kIn.readLine().trim();\r
+                                       stoken = new StringTokenizer(str);\r
+\r
+                                       if (stoken.nextToken().equals("#direction")) {\r
+                                               stoken.nextToken();\r
+                                               direction[0] = Integer.valueOf(stoken.nextToken()).intValue();\r
+                                               direction[1] = Integer.valueOf(stoken.nextToken()).intValue();\r
+                                               direction[2] = Integer.valueOf(stoken.nextToken()).intValue();\r
+                                       }\r
+\r
+                                       // read start location line\r
+                                       str = kIn.readLine().trim();\r
+                                       stoken = new StringTokenizer(str);\r
+\r
+                                       if (stoken.nextToken().equals("#startLocation")) {\r
+                                               stoken.nextToken();\r
+                                               startLocation[0] = Float.valueOf(stoken.nextToken()).floatValue();\r
+                                               startLocation[1] = Float.valueOf(stoken.nextToken()).floatValue();\r
+                                               startLocation[2] = Float.valueOf(stoken.nextToken()).floatValue();\r
+                                       }\r
+\r
+                                       // read box line\r
+                                       str = kIn.readLine().trim();\r
+                                       stoken = new StringTokenizer(str);\r
+\r
+                                       if (stoken.nextToken().equals("#box")) {\r
+                                               stoken.nextToken();\r
+                                               box[0] = Float.valueOf(stoken.nextToken()).floatValue();\r
+                                               box[1] = Float.valueOf(stoken.nextToken()).floatValue();\r
+                                               box[2] = Float.valueOf(stoken.nextToken()).floatValue();\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       str = kIn.readLine().trim();\r
+\r
+                       if (!str.equals("Shape")) {\r
+                               return null;\r
+                       }\r
+\r
+                       str = kIn.readLine();\r
+\r
+                       str = kIn.readLine().trim();\r
+                       stoken = new StringTokenizer(str);\r
+\r
+                       MaterialState kMaterial = null;\r
+                       float transparency = 0f;\r
+                       if (stoken.nextToken().equals("appearance")) {\r
+                               kMaterial = new MaterialState();\r
+\r
+                               str = kIn.readLine(); // material Material {\r
+                               str = kIn.readLine().trim(); // emissive Color\r
+                               stoken = new StringTokenizer(str);\r
+                               stoken.nextToken();\r
+                               float red = Float.valueOf(stoken.nextToken()).floatValue();\r
+                               float green = Float.valueOf(stoken.nextToken()).floatValue();\r
+                               float blue = Float.valueOf(stoken.nextToken()).floatValue();\r
+                               kMaterial.Emissive.R = red;\r
+                               kMaterial.Emissive.G = green;\r
+                               kMaterial.Emissive.B = blue;\r
+\r
+                               str = kIn.readLine().trim(); // diffuse color\r
+                               stoken = new StringTokenizer(str);\r
+                               stoken.nextToken();\r
+                               red = Float.valueOf(stoken.nextToken()).floatValue();\r
+                               green = Float.valueOf(stoken.nextToken()).floatValue();\r
+                               blue = Float.valueOf(stoken.nextToken()).floatValue();\r
+                               kMaterial.Diffuse.R = red;\r
+                               kMaterial.Diffuse.G = green;\r
+                               kMaterial.Diffuse.B = blue;\r
+\r
+                               str = kIn.readLine().trim(); // specular Color\r
+                               stoken = new StringTokenizer(str);\r
+                               stoken.nextToken();\r
+                               red = Float.valueOf(stoken.nextToken()).floatValue();\r
+                               green = Float.valueOf(stoken.nextToken()).floatValue();\r
+                               blue = Float.valueOf(stoken.nextToken()).floatValue();\r
+                               kMaterial.Specular.R = red;\r
+                               kMaterial.Specular.G = green;\r
+                               kMaterial.Specular.B = blue;\r
+\r
+                               str = kIn.readLine().trim(); // transparency\r
+                               stoken = new StringTokenizer(str);\r
+                               stoken.nextToken();\r
+                               transparency = Float.valueOf(stoken.nextToken()).floatValue();\r
+\r
+                               str = kIn.readLine(); // }\r
+                               str = kIn.readLine(); // }\r
+                       }\r
+\r
+                       str = kIn.readLine().trim();\r
+\r
+                       if (!str.equals("geometry IndexedFaceSet")) {\r
+                               return null;\r
+                       }\r
+\r
+                       str = kIn.readLine();\r
+\r
+                       str = kIn.readLine().trim();\r
+\r
+                       if (!str.equals("coord Coordinate")) {\r
+                               return null;\r
+                       }\r
+\r
+                       str = kIn.readLine();\r
+                       str = kIn.readLine().trim();\r
+\r
+                       if (!str.equals("point [")) {\r
+                               return null;\r
+                       }\r
+\r
+                       ArrayList<Vector3f> vertexPts = new ArrayList<Vector3f>(1000);\r
+                       ArrayList<Integer> connArray = new ArrayList<Integer>(1000);\r
+\r
+                       boolean readMore = true;\r
+                       Vector3f fPt;\r
+\r
+                       while (readMore) {\r
+\r
+                               str = kIn.readLine().trim();\r
+\r
+                               if (str.equals("]")) {\r
+                                       break;\r
+                               }\r
+\r
+                               stoken = new StringTokenizer(str);\r
+                               fPt = new Vector3f();\r
+                               fPt.set(Float.valueOf(stoken.nextToken()).floatValue(), Float.valueOf(stoken.nextToken()).floatValue(),\r
+                                               Float.valueOf(stoken.nextToken()).floatValue());\r
+\r
+                               vertexPts.add(fPt);\r
+                       }\r
+\r
+                       progress.updateValueImmed(added + (25 / total));\r
+\r
+                       Attributes kAttr = new Attributes();\r
+                       kAttr.SetPChannels(3);\r
+                       kAttr.SetNChannels(3);\r
+                       kAttr.SetTChannels(0, 3);\r
+                       kAttr.SetCChannels(0, 4);\r
+                       VertexBuffer kVBuffer = new VertexBuffer(kAttr, vertexPts.size());\r
+                       for (int i = 0; i < vertexPts.size(); i++) {\r
+                               Vector3f kVertex = vertexPts.get(i);\r
+\r
+                               kVBuffer.SetPosition3(i, kVertex);\r
+                               kVBuffer.SetColor4(0, i, kMaterial.Diffuse.R, kMaterial.Diffuse.G, kMaterial.Diffuse.B,\r
+                                               1.0f - transparency);\r
+                       }\r
+\r
+                       vertexPts = null;\r
+                       System.gc();\r
+                       progress.updateValueImmed(added + (50 / total));\r
+\r
+                       str = kIn.readLine().trim();\r
+                       str = kIn.readLine().trim();\r
+\r
+                       if (!str.equals("coordIndex [")) {\r
+                               return null;\r
+                       }\r
+\r
+                       while (readMore) {\r
+\r
+                               str = kIn.readLine().trim();\r
+\r
+                               if (str.equals("]")) {\r
+                                       break;\r
+                               }\r
+\r
+                               stoken = new StringTokenizer(str);\r
+\r
+                               Integer iConn;\r
+\r
+                               iConn = Integer.valueOf(stoken.nextToken());\r
+                               connArray.add(iConn);\r
+\r
+                               iConn = Integer.valueOf(stoken.nextToken());\r
+                               connArray.add(iConn);\r
+\r
+                               iConn = Integer.valueOf(stoken.nextToken());\r
+                               connArray.add(iConn);\r
+                       }\r
+\r
+                       progress.updateValueImmed(added + (75 / total));\r
+\r
+                       long position = kIn.getFilePointer();\r
+\r
+                       while ((str != null) && (str.indexOf("Shape") == -1)) {\r
+                               position = kIn.getFilePointer();\r
+                               str = kIn.readLine();\r
+                       }\r
+\r
+                       kIn.seek(position);\r
+\r
+                       int[] aiConnect = new int[connArray.size()];\r
+\r
+                       for (int i = 0; i < connArray.size(); i++) {\r
+                               aiConnect[i] = connArray.get(i).intValue();\r
+                       }\r
+\r
+                       progress.updateValueImmed(added + (100 / total));\r
+\r
+                       IndexBuffer kIBuffer = new IndexBuffer(aiConnect.length, aiConnect);\r
+                       TriMesh kMesh = new TriMesh(kVBuffer, kIBuffer);\r
+                       kMesh.AttachGlobalState(kMaterial);\r
+                       return kMesh;\r
+               } catch (IOException e) {\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * The action taken when the Add button is clicked in the JPanelSurface class. A\r
+        * file dialog is launched that allows the user to select new surfaces to load\r
+        * from disk.\r
+        * \r
+        * @param kImage\r
+        *            ModelImage for location/orientation and scale information.\r
+        * @return array of TriMesh objects.\r
+        */\r
+       public static TriMesh[] openSurfaces(ModelImage kImage) {\r
+               return openSurfaces(kImage, false);\r
+       }\r
+\r
+       /**\r
+        * The action taken when the Add button is clicked in the JPanelSurface class. A\r
+        * file dialog is launched that allows the user to select new surfaces to load\r
+        * from disk.\r
+        * \r
+        * @param kImage\r
+        *            ModelImage for location/orientation and scale information.\r
+        * @return array of TriMesh objects.\r
+        */\r
+       public static TriMesh[] openSurfaces(ModelImage kImage, boolean toFileCoords) {\r
+               File[] akFiles = openFiles(true);\r
+\r
+               if (akFiles == null) {\r
+                       return null;\r
+               }\r
+\r
+               TriMesh[] kSurface = new TriMesh[akFiles.length];\r
+               for (int i = 0; i < akFiles.length; i++) {\r
+                       String kName = akFiles[i].getName();\r
+                       if ((kName.indexOf(".sur") != -1) || (kName.indexOf(".wrl") != -1) || (kName.indexOf(".vtk") != -1)\r
+                                       || (kName.indexOf(".vtp") != -1) || (kName.indexOf(".stl") != -1) || (kName.indexOf(".ply") != -1)\r
+                                       || (kName.indexOf(".txt") != -1) || (kName.indexOf(".gii") != -1)) {\r
+                               kSurface[i] = readSurface(kImage, akFiles[i], null, toFileCoords);\r
+                       } else if (kName.indexOf(".xml") != -1) {\r
+                               FileSurfaceRefXML_WM kSurfaceXML = new FileSurfaceRefXML_WM(kName, akFiles[i].getParent());\r
+                               FileInfoSurfaceRefXML_WM kFileInfo = kSurfaceXML.readSurfaceXML(kName, akFiles[i].getParent());\r
+                               akFiles[i] = new File(akFiles[i].getParent() + File.separatorChar + kFileInfo.getSurfaceFileName());\r
+                               kSurface[i] = readSurface(kImage, akFiles[i], kFileInfo.getMaterial(), toFileCoords);\r
+                       }\r
+               }\r
+\r
+               return kSurface;\r
+       }\r
+\r
+       /**\r
+        * Parses the VRML to see how many surfaces there are.\r
+        * \r
+        * @param kIn\r
+        *            the file to parse\r
+        * @return int value for the number of surfaces in the file.\r
+        * @throws IOException\r
+        * @throws NoSuchElementException\r
+        */\r
+       public static int parseVRMLMesh(RandomAccessFile kIn) throws IOException, NoSuchElementException {\r
+               String str = kIn.readLine();\r
+\r
+               str = kIn.readLine();\r
+               str = kIn.readLine();\r
+\r
+               StringTokenizer token = new StringTokenizer(str);\r
+\r
+               token.nextToken();\r
+               token.nextToken();\r
+               token.nextToken();\r
+               token.nextToken();\r
+\r
+               return Integer.valueOf(token.nextToken()).intValue();\r
+       }\r
+\r
+       public static void save(String kName, TriMesh kMesh, ModelImage image, boolean transform) throws IOException {\r
+               int iXDim = image.getExtents().length > 0 ? image.getExtents()[0] : 1;\r
+               int iYDim = image.getExtents().length > 1 ? image.getExtents()[1] : 1;\r
+               int iZDim = image.getExtents().length > 2 ? image.getExtents()[2] : 1;\r
+\r
+               float fXRes = image.getExtents().length > 0 ? image.getFileInfo()[0].getResolutions()[0] : 1;\r
+               float fYRes = image.getExtents().length > 1 ? image.getFileInfo()[0].getResolutions()[1] : 1;\r
+               float fZRes = image.getExtents().length > 2 ? image.getFileInfo()[0].getResolutions()[2] : 1;\r
+\r
+               float[] box = new float[] { (iXDim - 1) * fXRes, (iYDim - 1) * fYRes, (iZDim - 1) * fZRes };\r
+\r
+               /* Read the direction vector from the MipavCoordinateSystems class: */\r
+               final int[] direction = MipavCoordinateSystems.getModelDirections(image);\r
+               final float[] startLocation = image.getFileInfo(0).getOrigin();\r
+\r
+               TransMatrix dicomMatrix = null;\r
+               TransMatrix inverseDicomMatrix = null;\r
+               if (image.getMatrixHolder().containsType(TransMatrix.TRANSFORM_SCANNER_ANATOMICAL)) {\r
+\r
+                       // Get the DICOM transform that describes the transformation from\r
+                       // axial to this image orientation\r
+                       dicomMatrix = new TransMatrix(image.getMatrix());\r
+                       inverseDicomMatrix = new TransMatrix(image.getMatrix());\r
+                       inverseDicomMatrix.Inverse();\r
+               }\r
+\r
+               if (transform) {\r
+                       for (int i = 0; i < kMesh.VBuffer.GetVertexQuantity(); i++) {\r
+                               Vector3f kV = kMesh.VBuffer.GetPosition3(i);\r
+\r
+                               if (dicomMatrix != null) {\r
+\r
+                                       // Change the voxel coordinate into millimeters\r
+                                       coord[0] = kV.X * fXRes;\r
+                                       coord[1] = kV.Y * fYRes;\r
+                                       coord[2] = kV.Z * fZRes;\r
+\r
+                                       // Convert the point to axial millimeter DICOM space\r
+                                       dicomMatrix.transform(coord, tCoord);\r
+\r
+                                       // Add in the DICOM origin\r
+                                       tCoord[0] = tCoord[0] + startLocation[0];\r
+                                       tCoord[1] = tCoord[1] + startLocation[1];\r
+                                       tCoord[2] = tCoord[2] + startLocation[2];\r
+                                       kV = new Vector3f(tCoord[0], tCoord[1], tCoord[2]);\r
+                               } else {\r
+                                       kV.X = (kV.X * fXRes * direction[0]) + startLocation[0];\r
+                                       kV.Y = (kV.Y * fYRes * direction[1]) + startLocation[1];\r
+                                       kV.Z = (kV.Z * fZRes * direction[2]) + startLocation[2];\r
+                               }\r
+                               kMesh.VBuffer.SetPosition3(i, kV);\r
+                       }\r
+               }\r
+\r
+               save(kName, kMesh, 0, kMesh.VBuffer, true, direction, startLocation, box, inverseDicomMatrix);\r
+       }\r
+\r
+       /**\r
+        * Save a TriMesh to disk\r
+        * \r
+        * @param kName\r
+        *            file name\r
+        * @param kMesh\r
+        *            TriMesh\r
+        * @param iType\r
+        *            type of mesh TriMesh or ClodMesh\r
+        * @param kVBuffer\r
+        *            VertexBuffer\r
+        * @param flip\r
+        *            invert y,z values\r
+        * @param direction\r
+        *            3D orientation of mesh\r
+        * @param startLocation\r
+        *            3D location of mesh\r
+        * @param box\r
+        *            3D bounding box\r
+        * @param inverseDicomMatrix\r
+        *            dicom matrix\r
+        * @throws IOException\r
+        *             file I/O exception\r
+        */\r
+       public static void save(String kName, TriMesh kMesh, int iType, VertexBuffer kVBuffer, boolean flip,\r
+                       int[] direction, float[] startLocation, float[] box, TransMatrix inverseDicomMatrix) throws IOException {\r
+               if (kName == null) {\r
+                       return;\r
+               }\r
+\r
+               int i = kName.lastIndexOf('.');\r
+               String kExt = kName.substring(i);\r
+               if (kExt.equals(".sur")) {\r
+                       saveSur(kName, kMesh, iType, kVBuffer, flip, direction, startLocation, box, inverseDicomMatrix);\r
+               } else if (kExt.equals(".ply")) {\r
+                       saveSinglePlyMesh(kName, null, kMesh);\r
+               } else if (kExt.equals(".stl")) {\r
+                       saveSingleSTLMesh(kName, null, kMesh);\r
+               } else if (kExt.equals(".txt")) {\r
+                       saveAsTextFile(kName, kMesh);\r
+               } else if (kExt.equals(".vtk")) {\r
+                       saveAsVTKLegacy(kName, kMesh);\r
+               } else if (kExt.equals(".vtp")) {\r
+                       saveAsVTKXML(kName, kMesh);\r
+               } else if (kExt.equals(".gii")) {\r
+                       saveAsGiftiXML(kName, kMesh);\r
+               } else if (kExt.equals(".xml")) {\r
+                       try {\r
+                               FileSurfaceRefXML_WM kSurfaceXML = new FileSurfaceRefXML_WM(null, null);\r
+                               MaterialState kMaterial = (MaterialState) kMesh.GetGlobalState(GlobalState.StateType.MATERIAL);\r
+                               if (kMaterial == null) {\r
+                                       kMaterial = new MaterialState();\r
+                               }\r
+                               float fOpacity = 0f;\r
+                               if (kMesh.VBuffer.GetAttributes().GetCChannels(0) == 4) {\r
+                                       fOpacity = 1.0f - kMesh.VBuffer.GetColor4(0, 0).A;\r
+                               }\r
+                               int iLOD = 0;\r
+                               kSurfaceXML.writeXMLsurface_WM(kName, kMaterial, fOpacity, iLOD);\r
+                               String surfaceName = kName.substring(0, i) + ".sur";\r
+                               saveSur(surfaceName, kMesh, iType, kVBuffer, flip, direction, startLocation, box, inverseDicomMatrix);\r
+                       } catch (IOException kError) {\r
+                       }\r
+               } else if (kExt.equals(".wrl")) {\r
+                       saveAsVRML(kName, kMesh, kVBuffer, flip, direction, startLocation, box);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Save a TriMesh to disk\r
+        * \r
+        * @param kName\r
+        *            file name\r
+        * @param kMesh\r
+        *            TriMesh\r
+        * @param keyImage\r
+        *            image\r
+        * @throws IOException\r
+        *             file I/O exception\r
+        */\r
+       public static void saveProstateSurface(String kName, TriMesh kMesh, ModelImage keyImage) throws IOException {\r
+               if (kName == null) {\r
+                       return;\r
+               }\r
+\r
+               int i = kName.lastIndexOf('.');\r
+               String kExt = kName.substring(i);\r
+               if (kExt.equals(".ply")) {\r
+                       // saveProstatePlyMesh(kName, keyImage, kMesh);\r
+                       saveSinglePlyMesh(kName, keyImage, kMesh);\r
+               } else if (kExt.equals(".stl")) {\r
+                   // saveProstateSTLMesh(kName, keyImage, kMesh);\r
+                       saveSingleSTLMesh(kName, keyImage, kMesh);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Save ClodMesh to disk\r
+        * \r
+        * @param kName\r
+        *            file name\r
+        * @param akComponent\r
+        *            array of ClodMesh to save\r
+        * @param flip\r
+        *            invert y,z values\r
+        * @param direction\r
+        *            3D mesh orientation\r
+        * @param startLocation\r
+        *            3D mesh location\r
+        * @param box\r
+        *            mesh bounding box\r
+        * @param inverseDicomMatrix\r
+        *            dicom matrix\r
+        */\r
+       public static void saveClodMesh(String kName, ClodMesh[] akComponent, boolean flip, int[] direction,\r
+                       float[] startLocation, float[] box, TransMatrix inverseDicomMatrix) {\r
+               if (akComponent.length == 0) {\r
+                       return;\r
+               }\r
+               try {\r
+                       for (int i = 0; i < akComponent.length; i++) {\r
+                               saveSur(kName, akComponent[i], 1, akComponent[i].VBuffer, flip, direction, startLocation, box,\r
+                                               inverseDicomMatrix);\r
+                       }\r
+               } catch (IOException kIOError) {\r
+               }\r
+       }\r
+\r
+       /**\r
+        * The action taken when the one of the save surface buttons is pressed in the\r
+        * JPanelSurface class. A file dialog is launched that allows the user to select\r
+        * where to save the surfaces.\r
+        *\r
+        * @param kImage\r
+        *            the ModelImage displayed in the SurfaceRender class\r
+        * @param akSurfaces\r
+        *            an array of surfaces described by their SurfaceAttributes,\r
+        *            containing information that is saved with the TriMesh\r
+        * @param kCommand\r
+        *            the type of save operation to perform\r
+        */\r
+       public static void saveSurfaces(ModelImage kImage, TriMesh[] akSurfaces, String kCommand) {\r
+\r
+               if (akSurfaces.length == 0) {\r
+                       MipavUtil.displayError("Select a surface to save.");\r
+\r
+                       return;\r
+               }\r
+\r
+               if (kCommand.equals("LevelS") || kCommand.equals("LevelV")) {\r
+\r
+                       for (int i = 0; i < akSurfaces.length; i++) {\r
+                               saveSingleMesh(kImage, kCommand.equals("LevelS"), akSurfaces[i]);\r
+                       }\r
+               }\r
+               // else if (kCommand.equals("LevelW")) {\r
+               // saveMultiMesh(kImage, akSurfaces);\r
+               // }\r
+               else if (kCommand.equals("LevelXML")) {\r
+\r
+                       for (int i = 0; i < akSurfaces.length; i++) {\r
+                               writeTriangleMeshXML(null, kImage, akSurfaces[i]);\r
+                       }\r
+               } else if (kCommand.equals("LevelSTL")) {\r
+\r
+                       for (int i = 0; i < akSurfaces.length; i++) {\r
+                               saveSingleSTLMesh(null, kImage, akSurfaces[i]);\r
+                       }\r
+               } else if (kCommand.equals("LevelPLY")) {\r
+\r
+                       for (int i = 0; i < akSurfaces.length; i++) {\r
+                               saveSinglePlyMesh(null, kImage, akSurfaces[i]);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Saves the triangle mesh in VRML97 (VRML 2.0) format. File name should end\r
+        * with ".wrl"\r
+        *\r
+        * @param kOut\r
+        *            the file to which the triangle mesh is saved\r
+        * @param flip\r
+        *            if the y and z axes should be flipped - true in extract and in\r
+        *            save of JDialogSurface To have proper orientations in surface file\r
+        *            if flip is true flip y and z on reading.\r
+        * @param direction\r
+        *            1 or -1 for each axis\r
+        * @param startLocation\r
+        *            DOCUMENT ME!\r
+        * @param box\r
+        *            (dimension-1)*resolution\r
+        * @param color\r
+        *            DOCUMENT ME!\r
+        *\r
+        * @exception IOException\r
+        *                if there is an error writing to the file\r
+        */\r
+       protected static void saveAsVRML(PrintWriter kOut, TriMesh kMesh, VertexBuffer kVBuffer, boolean flip,\r
+                       int[] direction, float[] startLocation, float[] box) {\r
+               kOut.print("#flip { ");\r
+\r
+               if (flip) {\r
+                       kOut.print(1);\r
+               } else {\r
+                       kOut.print(0);\r
+               }\r
+\r
+               kOut.print(" }\n");\r
+\r
+               kOut.print("#direction { ");\r
+               kOut.print(direction[0]);\r
+               kOut.print(' ');\r
+               kOut.print(direction[1]);\r
+               kOut.print(' ');\r
+               kOut.print(direction[2]);\r
+               kOut.print(" }\n");\r
+\r
+               kOut.print("#startLocation { ");\r
+               kOut.print(startLocation[0]);\r
+               kOut.print(' ');\r
+               kOut.print(startLocation[1]);\r
+               kOut.print(' ');\r
+               kOut.print(startLocation[2]);\r
+               kOut.print(" }\n");\r
+\r
+               kOut.print("#box { ");\r
+               kOut.print(box[0]);\r
+               kOut.print(' ');\r
+               kOut.print(box[1]);\r
+               kOut.print(' ');\r
+               kOut.print(box[2]);\r
+               kOut.print(" }\n");\r
+\r
+               MaterialState kMaterial = (MaterialState) kMesh.GetGlobalState(GlobalState.StateType.MATERIAL);\r
+               if (kMaterial == null) {\r
+                       kMaterial = new MaterialState();\r
+               }\r
+\r
+               kOut.print("Shape\n{\n");\r
+               kOut.print("\tappearance Appearance {\n");\r
+               kOut.print("\t\tmaterial Material {\n");\r
+               kOut.print("\t\t\temissiveColor\t");\r
+               kOut.print(kMaterial.Emissive.R + " ");\r
+               kOut.print(kMaterial.Emissive.G + " ");\r
+               kOut.print(kMaterial.Emissive.B);\r
+               kOut.print("\n\t\t\tdiffuseColor\t");\r
+               kOut.print(kMaterial.Diffuse.R + " ");\r
+               kOut.print(kMaterial.Diffuse.G + " ");\r
+               kOut.print(kMaterial.Diffuse.B);\r
+               kOut.print("\n\t\t\tspecularColor\t");\r
+               kOut.print(kMaterial.Specular.R + " ");\r
+               kOut.print(kMaterial.Specular.G + " ");\r
+               kOut.print(kMaterial.Specular.B);\r
+\r
+               float fTransparency = 0f;\r
+               if (kVBuffer.GetAttributes().GetCChannels(0) == 4) {\r
+                       fTransparency = 1.0f - kVBuffer.GetColor4(0, 0).A;\r
+               }\r
+               kOut.print("\n\t\t\ttransparency " + fTransparency + "\n");\r
+               kOut.print("\t\t}\n");\r
+               kOut.print("\t}\n");\r
+\r
+               kOut.print("\tgeometry IndexedFaceSet\n\t{\n");\r
+\r
+               kOut.print("\t\tcoord Coordinate\n");\r
+               kOut.print("\t\t{\n");\r
+               kOut.print("\t\t\tpoint [\n\t\t\t\t");\r
+\r
+               // write vertices\r
+               Vector3f kPos = new Vector3f();\r
+               int i;\r
+               for (i = 0; i < kVBuffer.GetVertexQuantity(); i++) {\r
+                       kVBuffer.GetPosition3(i, kPos);\r
+                       kOut.print(kPos.X);\r
+                       kOut.print(' ');\r
+\r
+                       kOut.print(kPos.Y);\r
+                       kOut.print(' ');\r
+\r
+                       kOut.print(kPos.Z);\r
+\r
+                       if (i < (kVBuffer.GetVertexQuantity() - 1)) {\r
+                               kOut.print(" ,\n\t\t\t\t");\r
+                       } else {\r
+                               kOut.print("\n\t\t\t\t]\n");\r
+                       }\r
+               }\r
+\r
+               // write connectivity\r
+               kOut.print("\t\t\t}\n\t\t\tcoordIndex [\n\t\t\t\t");\r
+               int iTriangleCount = kMesh.IBuffer.GetIndexQuantity() / 3;\r
+               int[] aiIndex = kMesh.IBuffer.GetData();\r
+               for (i = 0; i < iTriangleCount; i++) {\r
+                       kOut.print(aiIndex[3 * i]);\r
+                       kOut.print(' ');\r
+                       kOut.print(aiIndex[(3 * i) + 1]);\r
+                       kOut.print(' ');\r
+                       kOut.print(aiIndex[(3 * i) + 2]);\r
+\r
+                       if (i < (iTriangleCount - 1)) {\r
+                               kOut.print(" -1\n\t\t\t\t");\r
+                       } else {\r
+                               kOut.print("\n\t\t\t\t]\n");\r
+                       }\r
+               }\r
+\r
+               kOut.print("\t\t\tconvex FALSE\n");\r
+               kOut.print("\t\t\tcreaseAngle 1.5\n");\r
+               kOut.print("\t}\n}\n");\r
+       }\r
+\r
+       /**\r
+        * Calls a dialog to get a file name.\r
+        * \r
+        * @param bLoad\r
+        *            if <code>true</code>, make it a load dialog.\r
+        * @return File name.\r
+        */\r
+       private static String getFileName(boolean bLoad) {\r
+               File[] files = openFiles(bLoad);\r
+\r
+               if (files != null) {\r
+                       return new String(files[0].getPath());\r
+               }\r
+\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * Support for loading the collapse records from a binary file.\r
+        * \r
+        * @param kIn\r
+        *            the file from which the records are loaded\r
+        * @return CollapseRecord\r
+        * @exception IOException\r
+        *                if the there is an error reading from the file\r
+        */\r
+       private static CollapseRecord load(RandomAccessFile kIn) {\r
+               try {\r
+                       int iVKeep = kIn.readInt();\r
+                       int iVThrow = kIn.readInt();\r
+                       int iVQuantity = kIn.readInt();\r
+                       int iTQuantity = kIn.readInt();\r
+                       CollapseRecord kRecord = new CollapseRecord(iVKeep, iVThrow, iVQuantity, iTQuantity);\r
+                       kRecord.IQuantity = kIn.readInt();\r
+                       if (kRecord.IQuantity > 0) {\r
+                               byte[] bufferByte = new byte[kRecord.IQuantity * 4];\r
+                               int b1 = 0, b2 = 0, b3 = 0, b4 = 0;\r
+                               kRecord.Index = new int[kRecord.IQuantity];\r
+                               kIn.read(bufferByte);\r
+\r
+                               for (int i = 0, index = 0; i < kRecord.IQuantity; i++) {\r
+                                       b1 = bufferByte[index++] & 0x000000ff;\r
+                                       b2 = bufferByte[index++] & 0x000000ff;\r
+                                       b3 = bufferByte[index++] & 0x000000ff;\r
+                                       b4 = bufferByte[index++] & 0x000000ff;\r
+                                       kRecord.Index[i] = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+                               }\r
+                       }\r
+                       return kRecord;\r
+               } catch (IOException kIOError) {\r
+               }\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * Read a TriMesh from a Ply ascii file.\r
+        * \r
+        * @param file\r
+        *            file storing the mesh\r
+        * @return TriMesh\r
+        */\r
+       private static TriMesh loadPlyAsciiMesh(File file, ModelImage kImage) {\r
+\r
+               TriMesh mesh;\r
+               int i;\r
+               int iVertexCount = 0;\r
+               int iTriangleCount = 0;\r
+               boolean readHeader = true;\r
+               float x = 0f, y = 0f, z = 0f;\r
+               int idx1 = 0, idx2 = 0, idx3 = 0;\r
+\r
+               Vector<Vector3f> vertexArray = new Vector<Vector3f>();\r
+               Vector<Integer> connectivity = new Vector<Integer>();\r
+               VertexBuffer kVBuffer;\r
+               int[] aiConnect;\r
+               float _res[] = kImage.getFileInfo(0).getResolutions();\r
+               float[] _startLocation = kImage.getFileInfo()[0].getOrigin();\r
+               int[] _direction = MipavCoordinateSystems.getModelDirections(kImage);\r
+\r
+               Vector3f ptIn = new Vector3f();\r
+               Vector3f ptOut = new Vector3f();\r
+\r
+               try {\r
+\r
+                       DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));\r
+                       String s, token;\r
+                       while ((s = readLine(in)).length() > 0) {\r
+                               StringTokenizer st = new StringTokenizer(s);\r
+                               while (st.hasMoreTokens() && readHeader) {\r
+                                       // System.err.print(st.nextToken() + " ");\r
+                                       token = st.nextToken();\r
+                                       if (token.equals("vertex")) {\r
+                                               iVertexCount = Integer.valueOf(st.nextToken());\r
+                                       } else if (token.equals("face")) {\r
+                                               iTriangleCount = Integer.valueOf(st.nextToken());\r
+                                               readLine(in);\r
+                                               readLine(in); // skip two lines follow the face count attribute in PLY file format.\r
+                                               readHeader = false;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               if (readHeader == false)\r
+                                       break;\r
+                       }\r
+\r
+                       // read Vertex\r
+                       for (i = 0; i < iVertexCount; i++) {\r
+                               s = readLine(in);\r
+                               StringTokenizer st = new StringTokenizer(s);\r
+                               x = Float.valueOf(st.nextToken());\r
+                               y = Float.valueOf(st.nextToken());\r
+                               z = Float.valueOf(st.nextToken());\r
+\r
+                               ptIn.X = x;\r
+                               ptIn.Y = y;\r
+                               ptIn.Z = z;\r
+\r
+                               MipavCoordinateSystems.scannerToFile(ptIn, ptOut, kImage);\r
+\r
+                               x = (ptOut.X * _res[0] * _direction[0]) + _startLocation[0];\r
+                               y = (ptOut.Y * _res[1] * _direction[1]) + _startLocation[1];\r
+                               z = (ptOut.Z * _res[2] * _direction[2]) + _startLocation[2];\r
+\r
+                               vertexArray.add(new Vector3f(x, y, z));\r
+                       }\r
+\r
+                       // read connectivity\r
+                       for (i = 0; i < iTriangleCount; i++) {\r
+                               s = readLine(in);\r
+                               StringTokenizer st = new StringTokenizer(s);\r
+                               st.nextToken(); // skip 3\r
+                               idx1 = Integer.valueOf(st.nextToken());\r
+                               connectivity.add(idx1);\r
+                               idx2 = Integer.valueOf(st.nextToken());\r
+                               connectivity.add(idx2);\r
+                               idx3 = Integer.valueOf(st.nextToken());\r
+                               connectivity.add(idx3);\r
+                       }\r
+\r
+                       int vertexCount = vertexArray.size();\r
+                       Attributes kAttr = new Attributes();\r
+                       kAttr.SetPChannels(3);\r
+                       kAttr.SetNChannels(3);\r
+                       kAttr.SetTChannels(0, 3);\r
+                       kAttr.SetCChannels(0, 4);\r
+                       kVBuffer = new VertexBuffer(kAttr, vertexCount);\r
+\r
+                       int index = 0;\r
+                       Vector3f pos;\r
+                       for (i = 0; i < vertexCount; i++) {\r
+                               pos = vertexArray.elementAt(i);\r
+                               kVBuffer.SetPosition3(index, pos);\r
+                               kVBuffer.SetColor4(0, index, 1.0f, 1.0f, 1.0f, 1.0f);\r
+                               index++;\r
+                       }\r
+\r
+                       int indexCount = connectivity.size();\r
+                       aiConnect = new int[indexCount];\r
+                       for (i = 0; i < indexCount; i++) {\r
+                               aiConnect[i] = connectivity.get(i);\r
+                       }\r
+\r
+                       IndexBuffer kIBuffer = new IndexBuffer(aiConnect.length, aiConnect);\r
+                       mesh = new TriMesh(kVBuffer, kIBuffer);\r
+                       MaterialState kMaterial = new MaterialState();\r
+                       mesh.AttachGlobalState(kMaterial);\r
+                       return mesh;\r
+               } catch (FileNotFoundException e) {\r
+                       System.err.println("ERROR: Can't find file " + file);\r
+                       return null;\r
+               } catch (IOException e) {\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Load the STL ASCII file.\r
+        * \r
+        * @param file\r
+        *            STL surface file reference\r
+        * @param source\r
+        *            image\r
+        * @return TriMesh\r
+        */\r
+       private static TriMesh loadSTLAsciiMesh(File file, ModelImage kImage) {\r
+\r
+               TriMesh mesh;\r
+               try {\r
+                       BufferedReader reader;\r
+                       reader = new BufferedReader(new FileReader(file));\r
+                       StreamTokenizer tokenizer = new StreamTokenizer(reader);\r
+                       tokenizer.resetSyntax();\r
+                       tokenizer.whitespaceChars(0, 0x20);\r
+                       tokenizer.wordChars(0x21, 0xff);\r
+                       mesh = readSTLAscii(tokenizer, kImage);\r
+                       reader.close();\r
+                       return mesh;\r
+               } catch (FileNotFoundException e) {\r
+                       System.err.println("ERROR: Can't find file " + file);\r
+                       return null;\r
+               } catch (IOException e) {\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Load legacy VTK mesh.\r
+        * \r
+        * @param kIn\r
+        *            file containing mesh\r
+        * @param progress\r
+        *            progress bar\r
+        * @param added\r
+        *            number of meshes read from file so far\r
+        * @param total\r
+        *            total number of meshes in file\r
+        * @param flag\r
+        *            invert y,z values\r
+        * @return TriMesh\r
+        * @throws IOException\r
+        */\r
+       private static TriMesh loadVTKLegacyMesh(RandomAccessFile kIn, ViewJProgressBar progress, int added, int total,\r
+                       String fileName) {\r
+               TriMesh kMesh;\r
+\r
+               System.out.println(fileName);\r
+\r
+               StringBuffer buff = new StringBuffer();\r
+               try {\r
+                       // progress.setLocation(200, 200);\r
+                       progress.setVisible(true);\r
+                       String str;\r
+                       // Read file as string\r
+                       while ((str = kIn.readLine()) != null) {\r
+                               buff.append(str + "\n");\r
+                       }\r
+               } catch (Exception e) {\r
+                       System.err.println("Error occured while reading parameter file:\n" + e.getMessage());\r
+                       e.printStackTrace();\r
+                       return null;\r
+               }\r
+               Pattern header = Pattern.compile("POINTS\\s\\d+\\sfloat");\r
+               Matcher m = header.matcher(buff);\r
+               int vertexCount = 0;\r
+               int indexCount = 0;\r
+\r
+               Attributes kAttr = new Attributes();\r
+               kAttr.SetPChannels(3);\r
+               kAttr.SetNChannels(3);\r
+               kAttr.SetTChannels(0, 3);\r
+               kAttr.SetCChannels(0, 4);\r
+               // kAttr.SetCChannels(1,4);\r
+\r
+               VertexBuffer kVBuffer = null;\r
+               int[] indices;\r
+               if (m.find()) {\r
+                       String head = buff.substring(m.start(), m.end());\r
+                       String[] vals = head.split("\\D+");\r
+                       if (vals.length > 0) {\r
+                               try {\r
+                                       vertexCount = Integer.parseInt(vals[vals.length - 1]);\r
+                               } catch (NumberFormatException e) {\r
+                                       System.err.println("CANNOT DETERMINE VERTEX COUNT");\r
+                                       return null;\r
+                               }\r
+                       }\r
+\r
+                       kVBuffer = new VertexBuffer(kAttr, vertexCount);\r
+\r
+                       System.out.println("vertex count is " + vertexCount);\r
+                       progress.updateValueImmed(added + (25 / total));\r
+                       System.out.println(m.end());\r
+                       System.out.println(buff.length());\r
+                       String[] strs = buff.substring(m.end(), buff.length()).split("\\s+", vertexCount * 3 + 2);\r
+                       System.out.println(strs[0]);\r
+                       System.out.println(strs[1]);\r
+                       for (int i = 1; i < strs.length - 1; i += 3) {\r
+                               try {\r
+                                       kVBuffer.SetPosition3((i - 1) / 3, Float.parseFloat(strs[i]), Float.parseFloat(strs[i + 1]),\r
+                                                       Float.parseFloat(strs[i + 2]));\r
+                                       kVBuffer.SetColor4(0, (i - 1) / 3, 1f, 1f, 1f, 1f);\r
+                                       // System.out.println(i/3+")"+p);\r
+                               } catch (NumberFormatException e) {\r
+                                       System.err.println("CANNOT FORMAT VERTS");\r
+                                       return null;\r
+                               }\r
+                       }\r
+               } else {\r
+                       return null;\r
+               }\r
+\r
+               progress.updateValueImmed(added + (50 / total));\r
+\r
+               header = Pattern.compile("POLYGONS\\s+\\d+\\s+\\d+");\r
+               m = header.matcher(buff);\r
+               if (m.find()) {\r
+                       String head = buff.substring(m.start(), m.end());\r
+                       String[] vals = head.split("\\D+");\r
+                       if (vals.length > 1) {\r
+                               try {\r
+                                       indexCount = Integer.parseInt(vals[1]);\r
+                               } catch (NumberFormatException e) {\r
+                                       System.err.println("CANNOT DETERMINE INDEX COUNT");\r
+                                       return null;\r
+                               }\r
+                       }\r
+                       indices = new int[indexCount * 3];\r
+                       System.out.println("INDICES " + indexCount);\r
+                       String[] strs = buff.substring(m.end(), buff.length()).split("\\s+", indexCount * 4 + 2);\r
+                       int count = 0;\r
+                       System.out.println(strs[0]);\r
+                       System.out.println(strs[1]);\r
+                       for (int i = 1; i < strs.length - 1; i += 4) {\r
+                               try {\r
+                                       if (Integer.parseInt(strs[i]) != 3) {\r
+                                               System.err.println("CANNOT FORMAT INDICES");\r
+                                               return null;\r
+                                       }\r
+                                       indices[count++] = Integer.parseInt(strs[i + 1]);\r
+                                       indices[count++] = Integer.parseInt(strs[i + 2]);\r
+                                       indices[count++] = Integer.parseInt(strs[i + 3]);\r
+                               } catch (NumberFormatException e) {\r
+                                       System.err.println("CANNOT FORMAT INDICES");\r
+                                       return null;\r
+                               }\r
+                       }\r
+               } else {\r
+                       return null;\r
+               }\r
+\r
+               header = Pattern.compile("POINT_DATA\\s+\\d+\\D+float\\s+\\d+\\nLOOKUP_TABLE\\s");\r
+               m = header.matcher(buff);\r
+               double[][] dat;\r
+               int count = 0;\r
+               int dim = 0;\r
+               if (m.find()) {\r
+                       String head = buff.substring(m.start(), m.end());\r
+                       String[] vals = head.split("\\D+");\r
+                       if (vals.length > 0) {\r
+                               try {\r
+                                       count = Integer.parseInt(vals[1]);\r
+                                       dim = Integer.parseInt(vals[2]);\r
+                               } catch (NumberFormatException e) {\r
+                                       System.err.println("CANNOT DETERMINE DATA POINTS");\r
+                                       return null;\r
+                               }\r
+                       }\r
+                       dat = new double[count][dim];\r
+                       System.out.println("DATA POINTS " + count + " by " + dim);\r
+                       String[] strs = buff.substring(m.end(), buff.length()).split("\\s+", count * dim + 2);\r
+                       int index = 0;\r
+                       for (int i = 1; i < strs.length && index < count * dim; i++) {\r
+                               try {\r
+                                       dat[index / dim][index % dim] = Double.parseDouble(strs[i]);\r
+                                       index++;\r
+                               } catch (NumberFormatException e) {\r
+                                       System.err.println("CANNOT FORMAT DATA [" + strs[i] + "]");\r
+                                       // return null;\r
+                               }\r
+                       }\r
+                       // System.out.println(index+" "+count);\r
+\r
+                       progress.updateValueImmed(added + (100 / total));\r
+\r
+               } else {\r
+\r
+               }\r
+               IndexBuffer kIBuffer = new IndexBuffer(indices.length, indices);\r
+               kMesh = new TriMesh(kVBuffer, kIBuffer);\r
+               return kMesh;\r
+       }\r
+\r
+       /**\r
+        * Read VTK mesh from file.\r
+        * \r
+        * @param absPath\r
+        *            file path\r
+        * @param fileName\r
+        *            file name\r
+        * @param dir\r
+        *            file directory\r
+        * @return TriMesh\r
+        */\r
+       private static TriMesh loadVTKXMLMesh(String absPath, String fileName, String dir) {\r
+               TriMesh kMesh = null;\r
+\r
+               FileSurfaceVTKXML_WM surfaceVTKXML = new FileSurfaceVTKXML_WM(fileName, dir);\r
+               kMesh = surfaceVTKXML.readXMLSurface_WM(absPath);\r
+\r
+               return kMesh;\r
+       }\r
+\r
+       /**\r
+        * Read Gifti mesh from file.\r
+        * \r
+        * @param absPath\r
+        *            file path\r
+        * @param fileName\r
+        *            file name\r
+        * @param dir\r
+        *            file directory\r
+        * @return TriMesh\r
+        */\r
+       private static TriMesh loadGiftiXMLMesh(String absPath, String fileName, String dir) {\r
+               TriMesh kMesh = null;\r
+\r
+               FileSurfaceGiftiXML_WM surfaceGiftiXML = new FileSurfaceGiftiXML_WM(fileName, dir);\r
+               kMesh = surfaceGiftiXML.readSurfaceXML(fileName, dir);\r
+\r
+               return kMesh;\r
+       }\r
+\r
+       /**\r
+        * Returns an array of File objects, based on the user-selected files from the\r
+        * FileChooser dialog.\r
+        * \r
+        * @param bLoad\r
+        *            whether the files are opened for reading (bLoad = true) or writing\r
+        *            (bLoad = false)\r
+        * @return File[] array of opened files.\r
+        */\r
+       public static File[] openFiles(boolean bLoad) {\r
+\r
+               // file dialog to select surface mesh files (*.sur)\r
+               JFileChooser chooser = new JFileChooser();\r
+               chooser.setMultiSelectionEnabled(bLoad);\r
+               chooser.resetChoosableFileFilters();\r
+               chooser.addChoosableFileFilter(new ViewImageFileFilter(ViewImageFileFilter.SURFACE));\r
+\r
+               if (ViewUserInterface.getReference().getDefaultDirectory() != null) {\r
+                       chooser.setCurrentDirectory(new File(ViewUserInterface.getReference().getDefaultDirectory()));\r
+               } else {\r
+                       chooser.setCurrentDirectory(new File(System.getProperties().getProperty("user.dir")));\r
+               }\r
+\r
+               int returnVal;\r
+\r
+               if (bLoad) {\r
+                       returnVal = chooser.showOpenDialog(null);\r
+               } else {\r
+                       returnVal = chooser.showSaveDialog(null);\r
+               }\r
+\r
+               if (returnVal == JFileChooser.APPROVE_OPTION) {\r
+                       ViewUserInterface.getReference()\r
+                                       .setDefaultDirectory(String.valueOf(chooser.getCurrentDirectory()) + File.separatorChar);\r
+\r
+                       if (bLoad) {\r
+                               File[] files = chooser.getSelectedFiles();\r
+\r
+                               return files;\r
+                       }\r
+                       File[] files = new File[1];\r
+                       files[0] = chooser.getSelectedFile();\r
+                       return files;\r
+               }\r
+\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * Returns a dicomMatrix file objects, based on the user-selected filed from the\r
+        * FileChooser dialog.\r
+        * \r
+        * @param bLoad\r
+        *            whether the files are opened for reading (bLoad = true) or writing\r
+        *            (bLoad = false)\r
+        * @return File of opened file.\r
+        */\r
+       private static File openDicomMatrixFiles(boolean bLoad) {\r
+\r
+               // file dialog to select the dicom matrix info file\r
+               JFileChooser chooser = new JFileChooser();\r
+               chooser.setMultiSelectionEnabled(bLoad);\r
+               chooser.resetChoosableFileFilters();\r
+               chooser.addChoosableFileFilter(new ViewImageFileFilter(ViewImageFileFilter.DICOMMATRIX));\r
+\r
+               if (ViewUserInterface.getReference().getDefaultDirectory() != null) {\r
+                       chooser.setCurrentDirectory(new File(ViewUserInterface.getReference().getDefaultDirectory()));\r
+               } else {\r
+                       chooser.setCurrentDirectory(new File(System.getProperties().getProperty("user.dir")));\r
+               }\r
+\r
+               int returnVal;\r
+\r
+               if (bLoad) {\r
+                       returnVal = chooser.showOpenDialog(null);\r
+               } else {\r
+                       returnVal = chooser.showSaveDialog(null);\r
+               }\r
+\r
+               if (returnVal == JFileChooser.APPROVE_OPTION) {\r
+                       ViewUserInterface.getReference()\r
+                                       .setDefaultDirectory(String.valueOf(chooser.getCurrentDirectory()) + File.separatorChar);\r
+\r
+                       if (bLoad) {\r
+                               File file = chooser.getSelectedFile();\r
+\r
+                               return file;\r
+                       }\r
+                       File[] file = new File[1];\r
+                       file[0] = chooser.getSelectedFile();\r
+                       return file[0];\r
+               }\r
+\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * Print the contents of the TriMesh in ascii format.\r
+        * \r
+        * @param kOut\r
+        *            output\r
+        * @param kMesh\r
+        *            TriMesh\r
+        */\r
+       private static void printAscii(PrintWriter kOut, TriMesh kMesh) {\r
+               Vector3f kVertex = new Vector3f();\r
+               Vector3f kNormal = new Vector3f();\r
+\r
+               // write vertices\r
+               kOut.println(kMesh.VBuffer.GetVertexQuantity());\r
+               kOut.println("Vertices");\r
+\r
+               int i;\r
+\r
+               for (i = 0; i < kMesh.VBuffer.GetVertexQuantity(); i++) {\r
+                       kMesh.VBuffer.GetPosition3(i, kVertex);\r
+                       kOut.print(kVertex.X);\r
+                       kOut.print(' ');\r
+                       kOut.print(kVertex.Y);\r
+                       kOut.print(' ');\r
+                       kOut.println(kVertex.Z);\r
+               }\r
+\r
+               kOut.println("Normals");\r
+\r
+               // write normals\r
+               for (i = 0; i < kMesh.VBuffer.GetVertexQuantity(); i++) {\r
+                       kMesh.VBuffer.GetNormal3(i, kNormal);\r
+                       kOut.print(kNormal.X);\r
+                       kOut.print(' ');\r
+                       kOut.print(kNormal.Y);\r
+                       kOut.print(' ');\r
+                       kOut.println(kNormal.Z);\r
+               }\r
+\r
+               kOut.println("Connectivity");\r
+\r
+               // write connectivity\r
+               int iTriangleCount = kMesh.GetTriangleQuantity();\r
+               int[] aiIndex = kMesh.IBuffer.GetData();\r
+               kOut.println(iTriangleCount);\r
+\r
+               for (i = 0; i < iTriangleCount; i++) {\r
+                       kOut.print(aiIndex[(3 * i)]);\r
+                       kOut.print(' ');\r
+                       kOut.print(aiIndex[((3 * i) + 1)]);\r
+                       kOut.print(' ');\r
+                       kOut.println(aiIndex[((3 * i) + 2)]);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Print the contents of the TriMesh in STL ascii format.\r
+        * \r
+        * @param kOut\r
+        *            output\r
+        * @param kMesh\r
+        *            TriMesh\r
+        */\r
+       private static void printSTLAscii(PrintWriter kOut, ModelImage kImage, TriMesh kMesh) {\r
+               int i;\r
+               int index1, index2, index3;\r
+               VertexBuffer kVBuffer;\r
+               int iTriangleCount = kMesh.IBuffer.GetIndexQuantity() / 3;\r
+               int[] aiIndex = kMesh.IBuffer.GetData();\r
+               Vector3f kVertex = new Vector3f();\r
+               Vector3f kNormal = new Vector3f();\r
+               \r
+               Vector3f kVertex1 = new Vector3f();\r
+               Vector3f kVertex2 = new Vector3f();\r
+               Vector3f kVertex3 = new Vector3f();\r
+               \r
+        float x1, y1, z1;\r
+        float x2, y2, z2;\r
+        float x3, y3, z3;\r
+        float nx, ny, nz;\r
+               \r
+               if (kImage != null) {\r
+                       kVBuffer = convertVertex(kImage, kMesh);\r
+               } else {\r
+                       kVBuffer = kMesh.VBuffer;\r
+               }\r
+\r
+               kOut.println("solid");\r
+\r
+               for (i = 0; i < iTriangleCount; i++) {\r
+                       \r
+                       index1 = aiIndex[(3 * i)];\r
+                       index2 = aiIndex[((3 * i) + 1)];\r
+                       index3 = aiIndex[((3 * i) + 2)];\r
+\r
+                       kVBuffer.GetPosition3(index1, kVertex1);\r
+                       kVBuffer.GetPosition3(index2, kVertex2);\r
+                       kVBuffer.GetPosition3(index3, kVertex3);\r
+\r
+                       x1 = kVertex1.X; y1 = kVertex1.Y; z1 = kVertex1.Z;\r
+                       x2 = kVertex2.X; y2 = kVertex2.Y; z2 = kVertex2.Z;\r
+                       x3 = kVertex3.X; y3 = kVertex3.Y; z3 = kVertex3.Z;\r
+                       \r
+                       nx = (y2-y1)*(z3-z1) - (y3-y1)*(z2-z1);\r
+                       ny = (z2-z1)*(x3-x1) - (x2-x1)*(z3-z1);\r
+                       nz = (x2-x1)*(y3-y1) - (x3-x1)*(y2-y1);\r
+                       \r
+                       // Compute facet normal\r
+                       kNormal.set(nx, ny, nz);\r
+                       \r
+                       kOut.print(" facet normal  ");\r
+                       kOut.print(kNormal.X);\r
+                       kOut.print(' ');\r
+                       kOut.print(kNormal.Y);\r
+                       kOut.print(' ');\r
+                       kOut.println(kNormal.Z);\r
+\r
+                       kOut.println("   outer loop");\r
+                       // index 1\r
+                       kVBuffer.GetPosition3(index1, kVertex);\r
+                       kOut.print("     vertex ");\r
+                       kOut.print(kVertex.X);\r
+                       kOut.print(' ');\r
+                       kOut.print(kVertex.Y);\r
+                       kOut.print(' ');\r
+                       kOut.println(kVertex.Z);\r
+                       // index 2\r
+                       kVBuffer.GetPosition3(index2, kVertex);\r
+                       kOut.print("     vertex ");\r
+                       kOut.print(kVertex.X);\r
+                       kOut.print(' ');\r
+                       kOut.print(kVertex.Y);\r
+                       kOut.print(' ');\r
+                       kOut.println(kVertex.Z);\r
+                       // index 3\r
+                       kVBuffer.GetPosition3(index3, kVertex);\r
+                       kOut.print("     vertex ");\r
+                       kOut.print(kVertex.X);\r
+                       kOut.print(' ');\r
+                       kOut.print(kVertex.Y);\r
+                       kOut.print(' ');\r
+                       kOut.println(kVertex.Z);\r
+\r
+                       kOut.println("   endloop");\r
+                       kOut.println(" endfacet");\r
+               }\r
+               kOut.println("endsolid");\r
+       }\r
+\r
+       /**\r
+        * Print the contents of the TriMesh in STL ascii format.\r
+        * \r
+        * @param kOut\r
+        *            output\r
+        * @param kMesh\r
+        *            TriMesh\r
+        */\r
+       private static void printProstateSTLAscii(PrintWriter kOut, ModelImage kImage, TriMesh kMesh) {\r
+               int i;\r
+               int index1, index2, index3;\r
+               VertexBuffer kVBuffer;\r
+               float res[] = kImage.getFileInfo(0).getResolutions();\r
+               int iTriangleCount = kMesh.IBuffer.GetIndexQuantity() / 3;\r
+               int[] aiIndex = kMesh.IBuffer.GetData();\r
+\r
+               Vector3f kNormal = new Vector3f();\r
+               Vector3f kNormal1 = new Vector3f();\r
+               Vector3f kNormal2 = new Vector3f();\r
+               Vector3f kNormal3 = new Vector3f();\r
+\r
+               Vector3f kVertex1 = new Vector3f();\r
+               Vector3f kVertex2 = new Vector3f();\r
+               Vector3f kVertex3 = new Vector3f();\r
+\r
+               kVBuffer = kMesh.VBuffer;\r
+\r
+               kOut.println("solid");\r
+\r
+               for (i = 0; i < iTriangleCount; i++) {\r
+                       index1 = aiIndex[(3 * i)];\r
+                       index2 = aiIndex[((3 * i) + 1)];\r
+                       index3 = aiIndex[((3 * i) + 2)];\r
+\r
+                       kVBuffer.GetPosition3(index1, kNormal1);\r
+                       kVBuffer.GetPosition3(index2, kNormal2);\r
+                       kVBuffer.GetPosition3(index3, kNormal3);\r
+\r
+                       MipavCoordinateSystems.scannerToFile(kNormal1, kVertex1, kImage);\r
+                       MipavCoordinateSystems.scannerToFile(kNormal2, kVertex2, kImage);\r
+                       MipavCoordinateSystems.scannerToFile(kNormal3, kVertex3, kImage);\r
+\r
+                       kVertex1.X *= res[0];\r
+                       kVertex1.Y *= res[1];\r
+                       kVertex1.Z *= res[2];\r
+                       kVertex2.X *= res[0];\r
+                       kVertex2.Y *= res[1];\r
+                       kVertex2.Z *= res[2];\r
+                       kVertex3.X *= res[0];\r
+                       kVertex3.Y *= res[1];\r
+                       kVertex3.Z *= res[2];\r
+\r
+                       // Compute facet normal\r
+                       kNormal.set(0f, 0f, 0f).add(kVertex1).add(kVertex2).add(kVertex3).scale(1f / 3f);\r
+\r
+                       kOut.print(" facet normal  ");\r
+                       kOut.print(kNormal.X);\r
+                       kOut.print(' ');\r
+                       kOut.print(kNormal.Y);\r
+                       kOut.print(' ');\r
+                       kOut.println(kNormal.Z);\r
+\r
+                       kOut.println("   outer loop");\r
+\r
+                       // index 1\r
+                       kOut.print("     vertex ");\r
+                       kOut.print(kVertex1.X);\r
+                       kOut.print(' ');\r
+                       kOut.print(kVertex1.Y);\r
+                       kOut.print(' ');\r
+                       kOut.println(kVertex1.Z);\r
+                       // index 2\r
+                       kOut.print("     vertex ");\r
+                       kOut.print(kVertex2.X);\r
+                       kOut.print(' ');\r
+                       kOut.print(kVertex2.Y);\r
+                       kOut.print(' ');\r
+                       kOut.println(kVertex2.Z);\r
+                       // index 3\r
+                       kOut.print("     vertex ");\r
+                       kOut.print(kVertex3.X);\r
+                       kOut.print(' ');\r
+                       kOut.print(kVertex3.Y);\r
+                       kOut.print(' ');\r
+                       kOut.println(kVertex3.Z);\r
+\r
+                       kOut.println("   endloop");\r
+                       kOut.println(" endfacet");\r
+               }\r
+               kOut.println("endsolid");\r
+       }\r
+\r
+       /**\r
+        * Read a TriMesh from an ascii file.\r
+        * \r
+        * @param kFile\r
+        *            file containing TriMesh\r
+        * @return TriMesh\r
+        * @throws IOException\r
+        *             I/O exception\r
+        */\r
+       private static TriMesh readAscii(File kFile) throws IOException {\r
+               DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(kFile)));\r
+               String s, token;\r
+               s = readLine(in);\r
+               s = readLine(in);\r
+               s = readLine(in);\r
+               StringTokenizer st = new StringTokenizer(s);\r
+               int iNumVertices = 1;\r
+               if (st.hasMoreTokens()) {\r
+                       token = st.nextToken();\r
+                       iNumVertices = Integer.valueOf(token).intValue();\r
+               }\r
+               Attributes kAttr = new Attributes();\r
+               kAttr.SetPChannels(3);\r
+               kAttr.SetNChannels(3);\r
+               kAttr.SetTChannels(0, 3);\r
+               kAttr.SetCChannels(0, 4);\r
+               VertexBuffer kVBuffer = new VertexBuffer(kAttr, iNumVertices);\r
+               float fX, fY, fZ;\r
+               s = readLine(in);\r
+               for (int i = 0; i < iNumVertices; i++) {\r
+                       s = readLine(in);\r
+                       st = new StringTokenizer(s);\r
+                       token = st.nextToken();\r
+                       fX = Float.valueOf(token).floatValue();\r
+                       token = st.nextToken();\r
+                       fY = Float.valueOf(token).floatValue();\r
+                       token = st.nextToken();\r
+                       fZ = Float.valueOf(token).floatValue();\r
+                       kVBuffer.SetPosition3(i, fX, fY, fZ);\r
+                       kVBuffer.SetColor4(0, i, ColorRGBA.WHITE);\r
+               }\r
+               s = readLine(in);\r
+               for (int i = 0; i < iNumVertices; i++) {\r
+                       s = readLine(in);\r
+                       st = new StringTokenizer(s);\r
+                       token = st.nextToken();\r
+                       fX = Float.valueOf(token).floatValue();\r
+                       token = st.nextToken();\r
+                       fY = Float.valueOf(token).floatValue();\r
+                       token = st.nextToken();\r
+                       fZ = Float.valueOf(token).floatValue();\r
+                       kVBuffer.SetNormal3(i, fX, fY, fZ);\r
+               }\r
 \r
 \r
-            //          read normals\r
-            Vector3f[] akNormal = new Vector3f[iVertexCount];\r
+               int iTriangleCount = 0;\r
+               s = readLine(in);\r
+               s = readLine(in);\r
+               st = new StringTokenizer(s);\r
+               if (st.hasMoreTokens()) {\r
+                       token = st.nextToken();\r
+                       iTriangleCount = Integer.valueOf(token).intValue();\r
+               }\r
 \r
 \r
-            for (i = 0, index = 0; i < iVertexCount; i++) {\r
-                akNormal[i] = new Vector3f();\r
+               int[] aiIndex = new int[iTriangleCount * 3];\r
+\r
+               for (int i = 0; i < iTriangleCount; i++) {\r
+                       s = readLine(in);\r
+                       st = new StringTokenizer(s);\r
+                       token = st.nextToken();\r
+                       aiIndex[(3 * i)] = Integer.valueOf(token).intValue();\r
+                       token = st.nextToken();\r
+                       aiIndex[((3 * i) + 1)] = Integer.valueOf(token).intValue();\r
+                       token = st.nextToken();\r
+                       aiIndex[((3 * i) + 2)] = Integer.valueOf(token).intValue();\r
+               }\r
+               return new TriMesh(kVBuffer, new IndexBuffer(aiIndex));\r
+       }\r
 \r
 \r
-                b1 = bufferNormal[index++] & 0xff;\r
-                b2 = bufferNormal[index++] & 0xff;\r
-                b3 = bufferNormal[index++] & 0xff;\r
-                b4 = bufferNormal[index++] & 0xff;\r
+       /**\r
+        * Read a line of ASCII text from the input stream.\r
+        * \r
+        * @param in\r
+        *            InputStream\r
+        * @return line of the ascii file as a String\r
+        * @throws IOException\r
+        *             I/O exception\r
+        */\r
+       private static String readLine(InputStream in) throws IOException {\r
+               StringBuffer buf = new StringBuffer();\r
+               int c;\r
+               while ((c = in.read()) > -1 && c != '\n') {\r
+                       buf.append((char) c);\r
+               }\r
+               return buf.toString();\r
+       }\r
 \r
 \r
-                tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+       /**\r
+        * Find the given label in the tokenizer stream and then return the next three\r
+        * numbers as a point. Return null if end of stream\r
+        * \r
+        * @param tokenizer\r
+        *            stream in\r
+        * @param label\r
+        *            string label (vertex, normal ) in the STL ASCII file.\r
+        * @return Vector3f point coordinate.\r
+        * @throws IOException\r
+        */\r
+       private static Vector3f readPoint(StreamTokenizer tokenizer, String label) throws IOException {\r
+               while (true) {\r
+                       if (tokenizer.nextToken() == StreamTokenizer.TT_EOF)\r
+                               return null;\r
+                       if (tokenizer.sval.equals(label))\r
+                               break;\r
+               }\r
 \r
 \r
-                akNormal[i].X = Float.intBitsToFloat(tmpInt);\r
+               if (tokenizer.nextToken() == StreamTokenizer.TT_EOF)\r
+                       return null;\r
+               float x = Float.valueOf(tokenizer.sval).floatValue();\r
+               if (tokenizer.nextToken() == StreamTokenizer.TT_EOF)\r
+                       return null;\r
+               float y = Float.valueOf(tokenizer.sval).floatValue();\r
+               if (tokenizer.nextToken() == StreamTokenizer.TT_EOF)\r
+                       return null;\r
+               float z = Float.valueOf(tokenizer.sval).floatValue();\r
 \r
 \r
-                b1 = bufferNormal[index++] & 0xff;\r
-                b2 = bufferNormal[index++] & 0xff;\r
-                b3 = bufferNormal[index++] & 0xff;\r
-                b4 = bufferNormal[index++] & 0xff;\r
+               return new Vector3f(x, y, z);\r
+       }\r
 \r
 \r
-                tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+       /**\r
+        * Read the STL ASCII file as a single stream tokenizer.\r
+        * \r
+        * @param tokenizer\r
+        *            stream in\r
+        * @return Triangle mesh\r
+        * @throws IOException\r
+        */\r
+       private static TriMesh readSTLAscii(StreamTokenizer tokenizer, ModelImage kImage) throws IOException {\r
 \r
 \r
-                akNormal[i].Y = Float.intBitsToFloat(tmpInt);\r
+               Vector3f temp = new Vector3f();\r
+               Vector3f normal = new Vector3f();\r
+               Vector3f side1 = new Vector3f();\r
+               Vector3f side2 = new Vector3f();\r
+               Vector3f surfaceNormal = new Vector3f();\r
+               Vector<Vector3f> vertexArray = new Vector<Vector3f>();\r
+               VertexBuffer kVBuffer;\r
+               int[] aiConnect;\r
 \r
 \r
-                b1 = bufferNormal[index++] & 0xff;\r
-                b2 = bufferNormal[index++] & 0xff;\r
-                b3 = bufferNormal[index++] & 0xff;\r
-                b4 = bufferNormal[index++] & 0xff;\r
+               TriMesh kMesh = null;\r
+               float x, y, z;\r
+               Vector3f vertex1, vertex2, vertex3;\r
+               int index = 0;\r
+               Integer searchIndex;\r
+               Vector<Integer> connectivity = new Vector<Integer>();\r
+               HashMap<String, Integer> vertexHashtable = new HashMap<String, Integer>();\r
 \r
 \r
-                tmpInt = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
+               float _res[] = kImage.getFileInfo(0).getResolutions();\r
+               float[] _startLocation = kImage.getFileInfo()[0].getOrigin();\r
+               int[] _direction = MipavCoordinateSystems.getModelDirections(kImage);\r
 \r
 \r
-                akNormal[i].Z = Float.intBitsToFloat(tmpInt);\r
-            }\r
+               Vector3f ptIn = new Vector3f();\r
+               Vector3f ptOut = new Vector3f();\r
 \r
 \r
-            progress.updateValueImmed(added + (66 / total));\r
+               try {\r
+\r
+                       while (true) {\r
+                               if ((temp = readPoint(tokenizer, "normal")) == null)\r
+                                       break;\r
+                               normal = new Vector3f(temp);\r
+\r
+                               vertex1 = readPoint(tokenizer, "vertex");\r
+                               vertex2 = readPoint(tokenizer, "vertex");\r
+                               vertex3 = readPoint(tokenizer, "vertex");\r
+\r
+                               // Check that the normal is in the correct direction\r
+                               side1.copy(vertex2).sub(vertex1);\r
+                               side2.copy(vertex3).sub(vertex2);\r
+\r
+                               surfaceNormal.copy(side1).cross(side2);\r
+                               if (normal.dot(surfaceNormal) < 0) {\r
+                                       // vertices were specified in the wrong order, so reverse\r
+                                       // two of them\r
+                                       temp.copy(vertex2);\r
+                                       vertex2.copy(vertex3);\r
+                                       vertex3.copy(temp);\r
+                               }\r
+\r
+                               // index 1;\r
+                               x = vertex1.X;\r
+                               y = vertex1.Y;\r
+                               z = vertex1.Z;\r
+\r
+                               ptIn.X = x;\r
+                               ptIn.Y = y;\r
+                               ptIn.Z = z;\r
+\r
+                               MipavCoordinateSystems.scannerToFile(ptIn, ptOut, kImage);\r
+\r
+                               x = (ptOut.X * _res[0] * _direction[0]) + _startLocation[0];\r
+                               y = (ptOut.Y * _res[1] * _direction[1]) + _startLocation[1];\r
+                               z = (ptOut.Z * _res[2] * _direction[2]) + _startLocation[2];\r
+\r
+                               searchIndex = vertexHashtable.get((x + " " + y + " " + z));\r
+                               if (searchIndex == null) { // not found\r
+                                       vertexHashtable.put((x + " " + y + " " + z), new Integer(index));\r
+                                       connectivity.add(new Integer(index));\r
+                                       vertexArray.add(new Vector3f(x, y, z));\r
+                                       index++;\r
+                               } else {\r
+                                       connectivity.add(searchIndex);\r
+                               }\r
+\r
+                               // index 2;\r
+                               x = vertex2.X;\r
+                               y = vertex2.Y;\r
+                               z = vertex2.Z;\r
+\r
+                               ptIn.X = x;\r
+                               ptIn.Y = y;\r
+                               ptIn.Z = z;\r
+\r
+                               MipavCoordinateSystems.scannerToFile(ptIn, ptOut, kImage);\r
+\r
+                               x = (ptOut.X * _res[0] * _direction[0]) + _startLocation[0];\r
+                               y = (ptOut.Y * _res[1] * _direction[1]) + _startLocation[1];\r
+                               z = (ptOut.Z * _res[2] * _direction[2]) + _startLocation[2];\r
+\r
+                               searchIndex = vertexHashtable.get((x + " " + y + " " + z));\r
+                               if (searchIndex == null) { // not found\r
+                                       vertexHashtable.put((x + " " + y + " " + z), new Integer(index));\r
+                                       connectivity.add(new Integer(index));\r
+                                       vertexArray.add(new Vector3f(x, y, z));\r
+                                       index++;\r
+                               } else {\r
+                                       connectivity.add(searchIndex);\r
+                               }\r
+\r
+                               // index 3;\r
+                               x = vertex3.X;\r
+                               y = vertex3.Y;\r
+                               z = vertex3.Z;\r
+\r
+                               ptIn.X = x;\r
+                               ptIn.Y = y;\r
+                               ptIn.Z = z;\r
+\r
+                               MipavCoordinateSystems.scannerToFile(ptIn, ptOut, kImage);\r
+\r
+                               x = (ptOut.X * _res[0] * _direction[0]) + _startLocation[0];\r
+                               y = (ptOut.Y * _res[1] * _direction[1]) + _startLocation[1];\r
+                               z = (ptOut.Z * _res[2] * _direction[2]) + _startLocation[2];\r
+\r
+                               searchIndex = vertexHashtable.get((x + " " + y + " " + z));\r
+                               if (searchIndex == null) { // not found\r
+                                       vertexHashtable.put((x + " " + y + " " + z), new Integer(index));\r
+                                       connectivity.add(new Integer(index));\r
+                                       vertexArray.add(new Vector3f(x, y, z));\r
+                                       index++;\r
+                               } else {\r
+                                       connectivity.add(searchIndex);\r
+                               }\r
 \r
 \r
-            //          read connectivity\r
-            int iIndexCount = kIn.readInt();\r
+                       }\r
 \r
 \r
-            //          System.out.println("connect count = " + iIndexCount);\r
-            int[] aiConnect = new int[iIndexCount];\r
-            byte[] bufferConnect = new byte[iIndexCount * 4];\r
+                       int vertexCount = vertexArray.size();\r
+                       Attributes kAttr = new Attributes();\r
+                       kAttr.SetPChannels(3);\r
+                       kAttr.SetNChannels(3);\r
+                       kAttr.SetTChannels(0, 3);\r
+                       kAttr.SetCChannels(0, 4);\r
+                       kVBuffer = new VertexBuffer(kAttr, vertexCount);\r
+\r
+                       index = 0;\r
+                       Vector3f pos;\r
+                       for (int i = 0; i < vertexCount; i++) {\r
+                               pos = vertexArray.elementAt(i);\r
+                               kVBuffer.SetPosition3(index, pos);\r
+                               kVBuffer.SetColor4(0, index, 1.0f, 1.0f, 1.0f, 1.0f);\r
+                               index++;\r
+                       }\r
 \r
 \r
-            kIn.read(bufferConnect);\r
+                       int indexCount = connectivity.size();\r
+                       aiConnect = new int[indexCount];\r
+                       for (int i = 0; i < indexCount; i++) {\r
+                               aiConnect[i] = connectivity.get(i);\r
+                       }\r
 \r
 \r
-            for (i = 0, index = 0; i < iIndexCount; i++) {\r
-                b1 = bufferConnect[index++] & 0x000000ff;\r
-                b2 = bufferConnect[index++] & 0x000000ff;\r
-                b3 = bufferConnect[index++] & 0x000000ff;\r
-                b4 = bufferConnect[index++] & 0x000000ff;\r
+               } catch (IOException e) {\r
+                       throw e;\r
+               }\r
+               IndexBuffer kIBuffer = new IndexBuffer(aiConnect.length, aiConnect);\r
+               kMesh = new TriMesh(kVBuffer, kIBuffer);\r
+               MaterialState kMaterial = new MaterialState();\r
+               kMesh.AttachGlobalState(kMaterial);\r
+               return kMesh;\r
+       }\r
 \r
 \r
-                aiConnect[i] = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-\r
-                //              System.out.println("connect[" + i + "]" + aiConnect[i]);\r
-            }\r
-\r
-            //          read per vertex color array\r
-            int R, G, B, A;\r
-            int isPerVertexColor = kIn.readInt();\r
-            ColorRGBA[] perVertexColor = null;\r
-            if ( isPerVertexColor == 1 ) {\r
-                perVertexColor = new ColorRGBA[iVertexCount];\r
-                byte[] bufferPerVertexColor = new byte[iVertexCount * 4 * 4];\r
-                kIn.read(bufferPerVertexColor);\r
-                for (i = 0, index = 0; i < iVertexCount; i++) {\r
-                    perVertexColor[i] = new ColorRGBA();\r
-\r
-                    b1 = bufferPerVertexColor[index++] & 0xff;\r
-                    b2 = bufferPerVertexColor[index++] & 0xff;\r
-                    b3 = bufferPerVertexColor[index++] & 0xff;\r
-                    b4 = bufferPerVertexColor[index++] & 0xff;\r
-\r
-                    R = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-\r
-                    perVertexColor[i].R = Float.intBitsToFloat(R);\r
-\r
-                    b1 = bufferPerVertexColor[index++] & 0xff;\r
-                    b2 = bufferPerVertexColor[index++] & 0xff;\r
-                    b3 = bufferPerVertexColor[index++] & 0xff;\r
-                    b4 = bufferPerVertexColor[index++] & 0xff;\r
-\r
-                    G = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-\r
-                    perVertexColor[i].G = Float.intBitsToFloat(G);\r
-\r
-                    b1 = bufferPerVertexColor[index++] & 0xff;\r
-                    b2 = bufferPerVertexColor[index++] & 0xff;\r
-                    b3 = bufferPerVertexColor[index++] & 0xff;\r
-                    b4 = bufferPerVertexColor[index++] & 0xff;\r
-\r
-                    B = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-\r
-                    perVertexColor[i].B = Float.intBitsToFloat(B);\r
-\r
-                    b1 = bufferPerVertexColor[index++] & 0xff;\r
-                    b2 = bufferPerVertexColor[index++] & 0xff;\r
-                    b3 = bufferPerVertexColor[index++] & 0xff;\r
-                    b4 = bufferPerVertexColor[index++] & 0xff;\r
-\r
-                    A = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-\r
-                    perVertexColor[i].A = Float.intBitsToFloat(A);\r
-\r
-                }\r
-            }\r
-\r
-            progress.updateValueImmed(added + (100 / total));\r
-\r
-            Attributes kAttr = new Attributes();\r
-            kAttr.SetPChannels(3);\r
-            kAttr.SetNChannels(3);\r
-            kAttr.SetTChannels(0,3);\r
-            kAttr.SetCChannels(0,4);\r
-            /*\r
-              if ( perVertexColor != null )\r
-              {\r
-              kAttr.SetCChannels(1,4);\r
-              }\r
-            */\r
-            VertexBuffer pkVB = new VertexBuffer(kAttr,iVertexCount);\r
-            for ( i = 0; i < iVertexCount; i++ )\r
-            {\r
-                pkVB.SetPosition3(i, akVertex[i]);\r
-                pkVB.SetNormal3(i, akNormal[i]);\r
-\r
-                if ( perVertexColor != null )\r
-                {\r
-                    pkVB.SetColor4(0, i, perVertexColor[i].R, perVertexColor[i].G, perVertexColor[i].B, perVertexColor[i].A);\r
-                }\r
-                else\r
-                {\r
-                    pkVB.SetColor4(0, i, 1f, 1f, 1f, 1f );\r
-                }\r
-\r
-            }\r
-            IndexBuffer pkIB = new IndexBuffer(iIndexCount, aiConnect);\r
-            TriMesh kMesh = new TriMesh(pkVB,pkIB);\r
-            if ( kMaterial != null )\r
-            {\r
-                kMesh.AttachGlobalState( kMaterial );\r
-            }\r
-            return kMesh;\r
-        } catch (IOException e) {\r
-            return null;\r
-        }\r
-    }\r
-    \r
-    /**\r
-     *Load the triangle mesh from a VRML file specifically written by MIPAV. The caller must have already opened the\r
-     * file. \r
-     * @param kIn the file from which the triangle mesh is loaded\r
-     * @param progress progress bar\r
-     * @param added number of meshes added so far\r
-     * @param total number of meshes to add\r
-     * @param flag when true this is the first mesh, read header info.\r
-     * @param startLocation 3D location of mesh\r
-     * @param direction 3D orientation of mesh\r
-     * @param box mesh bounding box\r
-     * @return new TriMesh\r
-     */\r
-    public static TriMesh loadVRMLMesh(RandomAccessFile kIn, ViewJProgressBar progress, int added, int total,\r
-                                       boolean flag,\r
-                                       float[] startLocation, float[] direction, float[] box\r
-                                       ) {\r
-\r
-        String str = null;\r
-        String str2 = null;\r
-        String str3 = null;\r
-        StringTokenizer stoken = null;\r
-        try {\r
-            // read vertices\r
-            if (flag) {\r
-\r
-                if (kIn.getFilePointer() == 0) {\r
-                    str = kIn.readLine().trim();\r
-                    str2 = kIn.readLine().trim();\r
-                    str3 = kIn.readLine().trim();\r
-\r
-                    if (!str.equals("#VRML V2.0 utf8") || !str2.equals("#MIPAV") ||\r
-                        (str3.indexOf("#Number of shapes =") == -1)) {\r
-                        MipavUtil.displayWarning("File doesn't appear to be a VRML 2.0 file written by MIPAV");\r
-                        Preferences.debug("TriMesh.loadVRMLMesh: File doesn't appear to be a VRML 2.0 file written by MIPAV.\n");\r
-\r
-                        // or throw error.\r
-                        return null;\r
-                    }\r
-\r
-                    // read flip line\r
-                    str = kIn.readLine().trim();\r
-                    stoken = new StringTokenizer(str);\r
-\r
-                    if (stoken.nextToken().equals("#flip")) {\r
-                        stoken.nextToken();\r
-                    }\r
-\r
-                    // read direction line\r
-                    str = kIn.readLine().trim();\r
-                    stoken = new StringTokenizer(str);\r
-\r
-                    if (stoken.nextToken().equals("#direction")) {\r
-                        stoken.nextToken();\r
-                        direction[0] = Integer.valueOf(stoken.nextToken()).intValue();\r
-                        direction[1] = Integer.valueOf(stoken.nextToken()).intValue();\r
-                        direction[2] = Integer.valueOf(stoken.nextToken()).intValue();\r
-                    }\r
-\r
-                    // read start location line\r
-                    str = kIn.readLine().trim();\r
-                    stoken = new StringTokenizer(str);\r
-\r
-                    if (stoken.nextToken().equals("#startLocation")) {\r
-                        stoken.nextToken();\r
-                        startLocation[0] = Float.valueOf(stoken.nextToken()).floatValue();\r
-                        startLocation[1] = Float.valueOf(stoken.nextToken()).floatValue();\r
-                        startLocation[2] = Float.valueOf(stoken.nextToken()).floatValue();\r
-                    }\r
-\r
-                    // read box line\r
-                    str = kIn.readLine().trim();\r
-                    stoken = new StringTokenizer(str);\r
-\r
-                    if (stoken.nextToken().equals("#box")) {\r
-                        stoken.nextToken();\r
-                        box[0] = Float.valueOf(stoken.nextToken()).floatValue();\r
-                        box[1] = Float.valueOf(stoken.nextToken()).floatValue();\r
-                        box[2] = Float.valueOf(stoken.nextToken()).floatValue();\r
-                    }\r
-                }\r
-            }\r
-\r
-            str = kIn.readLine().trim();\r
-\r
-            if (!str.equals("Shape")) {\r
-                return null;\r
-            }\r
-\r
-            str = kIn.readLine();\r
-\r
-            str = kIn.readLine().trim();\r
-            stoken = new StringTokenizer(str);\r
-\r
-            MaterialState kMaterial = null;\r
-            float transparency = 0f;\r
-            if (stoken.nextToken().equals("appearance")) {\r
-                kMaterial = new MaterialState();\r
-                \r
-                str = kIn.readLine(); // material Material {\r
-                str = kIn.readLine().trim(); // emissive Color\r
-                stoken = new StringTokenizer(str);  stoken.nextToken();\r
-                float red = Float.valueOf( stoken.nextToken() ).floatValue();\r
-                float green = Float.valueOf( stoken.nextToken() ).floatValue();\r
-                float blue = Float.valueOf( stoken.nextToken() ).floatValue();\r
-                kMaterial.Emissive.R = red;\r
-                kMaterial.Emissive.G = green; \r
-                kMaterial.Emissive.B = blue;\r
-\r
-                str = kIn.readLine().trim(); // diffuse color\r
-                stoken = new StringTokenizer(str);  stoken.nextToken();\r
-                red = Float.valueOf( stoken.nextToken() ).floatValue();\r
-                green = Float.valueOf( stoken.nextToken() ).floatValue();\r
-                blue = Float.valueOf( stoken.nextToken() ).floatValue();\r
-                kMaterial.Diffuse.R = red;\r
-                kMaterial.Diffuse.G = green;\r
-                kMaterial.Diffuse.B = blue;\r
-\r
-                str = kIn.readLine().trim(); // specular Color\r
-                stoken = new StringTokenizer(str);  stoken.nextToken();\r
-                red = Float.valueOf( stoken.nextToken() ).floatValue();\r
-                green = Float.valueOf( stoken.nextToken() ).floatValue();\r
-                blue = Float.valueOf( stoken.nextToken() ).floatValue();\r
-                kMaterial.Specular.R = red;\r
-                kMaterial.Specular.G = green;\r
-                kMaterial.Specular.B = blue;\r
-\r
-                str = kIn.readLine().trim(); // transparency\r
-                stoken = new StringTokenizer(str);  stoken.nextToken();\r
-                transparency = Float.valueOf( stoken.nextToken() ).floatValue();\r
-\r
-                str = kIn.readLine(); // }\r
-                str = kIn.readLine(); // }\r
-            }\r
-\r
-            str = kIn.readLine().trim();\r
-\r
-            if (!str.equals("geometry IndexedFaceSet")) {\r
-                return null;\r
-            }\r
-\r
-            str = kIn.readLine();\r
-\r
-            str = kIn.readLine().trim();\r
-\r
-            if (!str.equals("coord Coordinate")) {\r
-                return null;\r
-            }\r
-\r
-            str = kIn.readLine();\r
-            str = kIn.readLine().trim();\r
-\r
-            if (!str.equals("point [")) {\r
-                return null;\r
-            }\r
-\r
-            ArrayList<Vector3f> vertexPts = new ArrayList<Vector3f>(1000);\r
-            ArrayList<Integer> connArray = new ArrayList<Integer>(1000);\r
-\r
-            boolean readMore = true;\r
-            Vector3f fPt;\r
-\r
-            while (readMore) {\r
-\r
-                str = kIn.readLine().trim();\r
-\r
-                if (str.equals("]")) {\r
-                    break;\r
-                }\r
-\r
-                stoken = new StringTokenizer(str);\r
-                fPt = new Vector3f();\r
-                fPt.set( Float.valueOf(stoken.nextToken()).floatValue(),\r
-                         Float.valueOf(stoken.nextToken()).floatValue(),\r
-                         Float.valueOf(stoken.nextToken()).floatValue() );\r
-\r
-                vertexPts.add(fPt);\r
-            }\r
-\r
-            progress.updateValueImmed(added + (25 / total));\r
-\r
-            Attributes kAttr = new Attributes();\r
-            kAttr.SetPChannels(3);\r
-            kAttr.SetNChannels(3);\r
-            kAttr.SetTChannels(0,3);\r
-            kAttr.SetCChannels(0,4);\r
-            VertexBuffer kVBuffer = new VertexBuffer( kAttr, vertexPts.size() );\r
-            for (int i = 0; i < vertexPts.size(); i++) {\r
-                Vector3f kVertex = vertexPts.get(i);\r
-                \r
-                kVBuffer.SetPosition3(i, kVertex);      \r
-                kVBuffer.SetColor4( 0, i,\r
-                                    kMaterial.Diffuse.R,\r
-                                    kMaterial.Diffuse.G,\r
-                                    kMaterial.Diffuse.B, 1.0f - transparency );\r
-            }\r
-\r
-            vertexPts = null;\r
-            System.gc();\r
-            progress.updateValueImmed(added + (50 / total));\r
-\r
-            str = kIn.readLine().trim();\r
-            str = kIn.readLine().trim();\r
-\r
-            if (!str.equals("coordIndex [")) {\r
-                return null;\r
-            }\r
-\r
-            while (readMore) {\r
-\r
-                str = kIn.readLine().trim();\r
-\r
-                if (str.equals("]")) {\r
-                    break;\r
-                }\r
-\r
-                stoken = new StringTokenizer(str);\r
-\r
-                Integer iConn;\r
-\r
-                iConn = Integer.valueOf(stoken.nextToken());\r
-                connArray.add(iConn);\r
-\r
-                iConn = Integer.valueOf(stoken.nextToken());\r
-                connArray.add(iConn);\r
-\r
-                iConn = Integer.valueOf(stoken.nextToken());\r
-                connArray.add(iConn);\r
-            }\r
-\r
-            progress.updateValueImmed(added + (75 / total));\r
-\r
-            long position = kIn.getFilePointer();\r
-\r
-            while ((str != null) && (str.indexOf("Shape") == -1)) {\r
-                position = kIn.getFilePointer();\r
-                str = kIn.readLine();\r
-            }\r
-\r
-            kIn.seek(position);\r
-\r
-            int[] aiConnect = new int[connArray.size()];\r
-\r
-            for (int i = 0; i < connArray.size(); i++) {\r
-                aiConnect[i] = connArray.get(i).intValue();\r
-            }\r
-\r
-            progress.updateValueImmed(added + (100 / total));\r
-            \r
-            IndexBuffer kIBuffer = new IndexBuffer( aiConnect.length, aiConnect );\r
-            TriMesh kMesh = new TriMesh(kVBuffer, kIBuffer);\r
-            kMesh.AttachGlobalState( kMaterial );\r
-            return kMesh;\r
-        } catch (IOException e) {\r
-            return null;\r
-        }\r
-    }\r
-\r
-\r
-    /**\r
-     * The action taken when the Add button is clicked in the JPanelSurface class. A file dialog is launched that allows\r
-     * the user to select new surfaces to load from disk.\r
-     * @param kImage ModelImage for location/orientation and scale information.\r
-     * @return array of TriMesh objects.\r
-     */\r
-    public static TriMesh[] openSurfaces(ModelImage kImage) {\r
-        return openSurfaces(kImage, false);\r
-    }\r
-\r
-\r
-    /**\r
-     * The action taken when the Add button is clicked in the JPanelSurface class. A file dialog is launched that allows\r
-     * the user to select new surfaces to load from disk.\r
-     * @param kImage ModelImage for location/orientation and scale information.\r
-     * @return array of TriMesh objects.\r
-     */\r
-    public static TriMesh[] openSurfaces(ModelImage kImage, boolean toFileCoords ) {\r
-        File[] akFiles = openFiles(true);\r
-\r
-        if (akFiles == null) {\r
-            return null;\r
-        }\r
-\r
-        TriMesh[] kSurface = new TriMesh[akFiles.length];\r
-        for (int i = 0; i < akFiles.length; i++) {\r
-            String kName = akFiles[i].getName();\r
-            if ((kName.indexOf(".sur") != -1) || (kName.indexOf(".wrl") != -1) || \r
-               (kName.indexOf(".vtk") != -1) || (kName.indexOf(".vtp") != -1) || \r
-               (kName.indexOf(".stl")!= -1) || \r
-               (kName.indexOf(".ply") != -1) || (kName.indexOf(".txt") != -1) || \r
-               (kName.indexOf(".gii") != -1)) {\r
-                kSurface[i] = readSurface(kImage, akFiles[i], null, toFileCoords);\r
-            } else if (kName.indexOf(".xml") != -1) {\r
-                FileSurfaceRefXML_WM kSurfaceXML = new FileSurfaceRefXML_WM(kName, akFiles[i].getParent());\r
-                FileInfoSurfaceRefXML_WM kFileInfo = kSurfaceXML.readSurfaceXML(kName, akFiles[i].getParent());\r
-                akFiles[i] = new File(akFiles[i].getParent()+ File.separatorChar + kFileInfo.getSurfaceFileName());\r
-                kSurface[i] = readSurface(kImage, akFiles[i], kFileInfo.getMaterial(), toFileCoords);\r
-            } \r
-        }\r
-\r
-        return kSurface;\r
-    }\r
-\r
-    /**\r
-     * Parses the VRML to see how many surfaces there are.\r
-     * @param   kIn  the file to parse\r
-     * @return  int value for the number of surfaces in the file.\r
-     * @throws  IOException             \r
-     * @throws  NoSuchElementException  \r
-     */\r
-    public static int parseVRMLMesh(RandomAccessFile kIn) throws IOException, NoSuchElementException {\r
-        String str = kIn.readLine();\r
-\r
-        str = kIn.readLine();\r
-        str = kIn.readLine();\r
-\r
-        StringTokenizer token = new StringTokenizer(str);\r
-\r
-        token.nextToken();\r
-        token.nextToken();\r
-        token.nextToken();\r
-        token.nextToken();\r
-\r
-        return Integer.valueOf(token.nextToken()).intValue();\r
-    }\r
-\r
-    public static void save(String kName, TriMesh kMesh, ModelImage image, boolean transform ) throws IOException\r
-    {\r
-        int iXDim = image.getExtents().length > 0 ? image.getExtents()[0] : 1;\r
-        int iYDim = image.getExtents().length > 1 ? image.getExtents()[1] : 1;\r
-        int iZDim = image.getExtents().length > 2 ? image.getExtents()[2] : 1;\r
-\r
-        float fXRes = image.getExtents().length > 0 ? image.getFileInfo()[0].getResolutions()[0] : 1;\r
-        float fYRes = image.getExtents().length > 1 ? image.getFileInfo()[0].getResolutions()[1] : 1;\r
-        float fZRes = image.getExtents().length > 2 ? image.getFileInfo()[0].getResolutions()[2] : 1;\r
-\r
-        float[] box = new float[]{ (iXDim - 1) * fXRes, (iYDim - 1) * fYRes, (iZDim - 1) * fZRes};\r
-\r
-        /* Read the direction vector from the MipavCoordinateSystems class: */\r
-        final int[] direction = MipavCoordinateSystems.getModelDirections(image);\r
-        final float[] startLocation = image.getFileInfo(0).getOrigin();\r
-\r
-        TransMatrix dicomMatrix = null;\r
-        TransMatrix inverseDicomMatrix = null;\r
-        if (image.getMatrixHolder().containsType(TransMatrix.TRANSFORM_SCANNER_ANATOMICAL)) {\r
-\r
-            // Get the DICOM transform that describes the transformation from\r
-            // axial to this image orientation\r
-               dicomMatrix = new TransMatrix(image.getMatrix());\r
-            inverseDicomMatrix = new TransMatrix(image.getMatrix());\r
-            inverseDicomMatrix.Inverse();\r
-        }\r
-        \r
-        if ( transform )\r
-        {\r
-               for ( int i = 0; i < kMesh.VBuffer.GetVertexQuantity(); i++ )\r
-               {\r
-                       Vector3f kV = kMesh.VBuffer.GetPosition3(i);\r
-\r
-                       if (dicomMatrix != null) {\r
-\r
-                               // Change the voxel coordinate into millimeters\r
-                               coord[0] = kV.X * fXRes;\r
-                               coord[1] = kV.Y * fYRes;\r
-                               coord[2] = kV.Z * fZRes;\r
-\r
-                               // Convert the point to axial millimeter DICOM space\r
-                               dicomMatrix.transform(coord, tCoord);\r
-\r
-                               // Add in the DICOM origin\r
-                               tCoord[0] = tCoord[0] + startLocation[0];\r
-                               tCoord[1] = tCoord[1] + startLocation[1];\r
-                               tCoord[2] = tCoord[2] + startLocation[2];\r
-                               kV = new Vector3f(tCoord[0], tCoord[1], tCoord[2]);\r
-                       } else {\r
-                               kV.X = (kV.X * fXRes * direction[0]) + startLocation[0];\r
-                               kV.Y = (kV.Y * fYRes * direction[1]) + startLocation[1];\r
-                               kV.Z = (kV.Z * fZRes * direction[2]) + startLocation[2];\r
-                       }\r
-                       kMesh.VBuffer.SetPosition3(i, kV);\r
-               }\r
-        }\r
-        \r
-        save(kName, kMesh, 0, kMesh.VBuffer, true, direction, startLocation, box, inverseDicomMatrix);\r
-    }\r
-    \r
-    /**\r
-     * Save a TriMesh to disk\r
-     * @param kName file name\r
-     * @param kMesh TriMesh\r
-     * @param iType type of mesh TriMesh or ClodMesh\r
-     * @param kVBuffer VertexBuffer\r
-     * @param flip invert y,z values\r
-     * @param direction 3D orientation of mesh\r
-     * @param startLocation 3D location of mesh\r
-     * @param box 3D bounding box\r
-     * @param inverseDicomMatrix dicom matrix\r
-     * @throws IOException file I/O exception\r
-     */\r
-    public static void save(String kName, TriMesh kMesh,\r
-                            int iType, VertexBuffer kVBuffer,\r
-                            boolean flip, int[] direction, float[] startLocation, float[] box,\r
-                            TransMatrix inverseDicomMatrix)\r
-    throws IOException\r
-    {\r
-        if (kName == null)\r
-        {\r
-            return;\r
-        }\r
-        \r
-        int i = kName.lastIndexOf('.');\r
-        String kExt = kName.substring(i);\r
-        if ( kExt.equals(".sur" ) )\r
-        { \r
-               saveSur(kName,kMesh,iType,kVBuffer,flip,direction,startLocation,box,inverseDicomMatrix);\r
-        }\r
-        else if ( kExt.equals(".ply" ) )\r
-        {\r
-               saveSinglePlyMesh(kName, null, kMesh);\r
-        }\r
-        else if ( kExt.equals(".stl" ) )\r
-        {\r
-               saveSingleSTLMesh(kName, null, kMesh);\r
-        }\r
-        else if ( kExt.equals(".txt" ) )\r
-        {\r
-            saveAsTextFile(kName, kMesh );\r
-        }\r
-        else if ( kExt.equals(".vtk" ) )\r
-        {\r
-            saveAsVTKLegacy(kName, kMesh);\r
-        }\r
-        else if ( kExt.equals(".vtp" ) )\r
-        {\r
-            saveAsVTKXML(kName, kMesh);\r
-        } \r
-        else if ( kExt.equals(".gii" ) )\r
-        {\r
-               saveAsGiftiXML(kName, kMesh);\r
-        }\r
-        else if ( kExt.equals(".xml" ) )\r
-        {\r
-            try {\r
-                FileSurfaceRefXML_WM kSurfaceXML = new FileSurfaceRefXML_WM(null, null);\r
-                MaterialState kMaterial = (MaterialState)kMesh.GetGlobalState(GlobalState.StateType.MATERIAL);\r
-                if ( kMaterial == null )\r
-                {\r
-                    kMaterial = new MaterialState();\r
-                }\r
-                float fOpacity = 0f;\r
-                if ( kMesh.VBuffer.GetAttributes().GetCChannels(0) == 4 )\r
-                {\r
-                    fOpacity = 1.0f - kMesh.VBuffer.GetColor4(0, 0).A;\r
-                }\r
-                int iLOD = 0;\r
-                kSurfaceXML.writeXMLsurface_WM(kName, kMaterial, fOpacity, iLOD );     \r
-                String surfaceName = kName.substring(0, i) + ".sur"; \r
-                saveSur(surfaceName,kMesh,iType,kVBuffer,flip,direction,startLocation,box,inverseDicomMatrix);\r
-            } catch ( IOException kError ) { }\r
-        }\r
-        else if ( kExt.equals(".wrl" ) )\r
-        {\r
-            saveAsVRML( kName, kMesh, kVBuffer, flip, direction, startLocation,  box );\r
-        }\r
-    }\r
-    \r
-    \r
-    /**\r
-     * Save a TriMesh to disk\r
-     * @param kName file name\r
-     * @param kMesh TriMesh\r
-     * @param iType type of mesh TriMesh or ClodMesh\r
-     * @param kVBuffer VertexBuffer\r
-     * @param flip invert y,z values\r
-     * @param direction 3D orientation of mesh\r
-     * @param startLocation 3D location of mesh\r
-     * @param box 3D bounding box\r
-     * @param inverseDicomMatrix dicom matrix\r
-     * @throws IOException file I/O exception\r
-     */\r
-    public static void saveProstateSurface(String kName, TriMesh kMesh,\r
-                            int iType, VertexBuffer kVBuffer,\r
-                            boolean flip, int[] direction, float[] startLocation, float[] box,\r
-                            TransMatrix inverseDicomMatrix, ModelImage keyImage)\r
-    throws IOException\r
-    {\r
-        if (kName == null)\r
-        {\r
-            return;\r
-        }\r
-        \r
-        int i = kName.lastIndexOf('.');\r
-        String kExt = kName.substring(i);\r
-        if ( kExt.equals(".ply" ) )\r
-        {\r
-               saveProstatePlyMesh(kName, keyImage, kMesh);\r
-        }\r
-        else if ( kExt.equals(".stl" ) )\r
-        {\r
-               saveProstateSTLMesh(kName, keyImage, kMesh);\r
-        }\r
-      }\r
-    \r
-    \r
-    \r
-    /**\r
-     * Save ClodMesh to disk\r
-     * @param kName file name\r
-     * @param akComponent array of ClodMesh to save\r
-     * @param flip invert y,z values\r
-     * @param direction 3D mesh orientation\r
-     * @param startLocation 3D mesh location\r
-     * @param box mesh bounding box\r
-     * @param inverseDicomMatrix dicom matrix\r
-     */\r
-    public static void saveClodMesh(String kName, ClodMesh[] akComponent,\r
-                                    boolean flip, int[] direction,\r
-                                    float[] startLocation, float[] box,\r
-                                    TransMatrix inverseDicomMatrix)\r
-    {\r
-        if (akComponent.length == 0) {\r
-            return;\r
-        }\r
-        try {\r
-            for (int i = 0; i < akComponent.length; i++) {\r
-                saveSur(kName, akComponent[i], 1, akComponent[i].VBuffer, flip,\r
-                     direction, startLocation, box, inverseDicomMatrix);\r
-            }\r
-        } catch ( IOException kIOError ) {}\r
-    }\r
-\r
-    /**\r
-     * The action taken when the one of the save surface buttons is pressed in the JPanelSurface class. A file dialog is\r
-     * launched that allows the user to select where to save the surfaces.\r
-     *\r
-     * @param  kImage      the ModelImage displayed in the SurfaceRender class\r
-     * @param  akSurfaces  an array of surfaces described by their SurfaceAttributes, containing information that is\r
-     *                     saved with the TriMesh\r
-     * @param  kCommand    the type of save operation to perform\r
-     */\r
-    public static void saveSurfaces(ModelImage kImage, TriMesh[] akSurfaces, String kCommand) {\r
-\r
-        if (akSurfaces.length == 0) {\r
-            MipavUtil.displayError("Select a surface to save.");\r
-\r
-            return;\r
-        }\r
-\r
-        if (kCommand.equals("LevelS") || kCommand.equals("LevelV")) {\r
-\r
-            for (int i = 0; i < akSurfaces.length; i++) {\r
-                saveSingleMesh(kImage, kCommand.equals("LevelS"), akSurfaces[i]);\r
-            }\r
-        }\r
-        //         else if (kCommand.equals("LevelW")) {\r
-        //             saveMultiMesh(kImage, akSurfaces);\r
-        //         }\r
-        else if (kCommand.equals("LevelXML")) {\r
-\r
-            for (int i = 0; i < akSurfaces.length; i++) {\r
-                writeTriangleMeshXML(null, kImage, akSurfaces[i]);\r
-            }\r
-        }\r
-        else if (kCommand.equals("LevelSTL")) {\r
-\r
-            for (int i = 0; i < akSurfaces.length; i++) {\r
-               saveSingleSTLMesh(null, kImage, akSurfaces[i]);\r
-            }\r
-        }\r
-        else if (kCommand.equals("LevelPLY")) {\r
-\r
-            for (int i = 0; i < akSurfaces.length; i++) {\r
-               saveSinglePlyMesh(null, kImage, akSurfaces[i] );\r
-            }\r
-        }                           \r
-    }\r
-    \r
-    \r
-    /**\r
-     * Saves the triangle mesh in VRML97 (VRML 2.0) format. File name should end with ".wrl"\r
-     *\r
-     * @param      kOut           the file to which the triangle mesh is saved\r
-     * @param      flip           if the y and z axes should be flipped - true in extract and in save of JDialogSurface\r
-     *                            To have proper orientations in surface file if flip is true flip y and z on reading.\r
-     * @param      direction      1 or -1 for each axis\r
-     * @param      startLocation  DOCUMENT ME!\r
-     * @param      box            (dimension-1)*resolution\r
-     * @param      color          DOCUMENT ME!\r
-     *\r
-     * @exception  IOException  if there is an error writing to the file\r
-     */\r
-    protected static void saveAsVRML(PrintWriter kOut, TriMesh kMesh, VertexBuffer kVBuffer, boolean flip, int[] direction, float[] startLocation, float[] box)\r
-    {\r
-        kOut.print("#flip { ");\r
-\r
-        if (flip) {\r
-            kOut.print(1);\r
-        } else {\r
-            kOut.print(0);\r
-        }\r
-\r
-        kOut.print(" }\n");\r
-\r
-        kOut.print("#direction { ");\r
-        kOut.print(direction[0]);\r
-        kOut.print(' ');\r
-        kOut.print(direction[1]);\r
-        kOut.print(' ');\r
-        kOut.print(direction[2]);\r
-        kOut.print(" }\n");\r
-\r
-        kOut.print("#startLocation { ");\r
-        kOut.print(startLocation[0]);\r
-        kOut.print(' ');\r
-        kOut.print(startLocation[1]);\r
-        kOut.print(' ');\r
-        kOut.print(startLocation[2]);\r
-        kOut.print(" }\n");\r
-\r
-        kOut.print("#box { ");\r
-        kOut.print(box[0]);\r
-        kOut.print(' ');\r
-        kOut.print(box[1]);\r
-        kOut.print(' ');\r
-        kOut.print(box[2]);\r
-        kOut.print(" }\n");\r
-\r
-        MaterialState kMaterial = (MaterialState)kMesh.GetGlobalState( GlobalState.StateType.MATERIAL );\r
-        if ( kMaterial == null )\r
-        {\r
-            kMaterial = new MaterialState();\r
-        }\r
-\r
-        kOut.print("Shape\n{\n");\r
-        kOut.print("\tappearance Appearance {\n");\r
-        kOut.print("\t\tmaterial Material {\n");\r
-        kOut.print("\t\t\temissiveColor\t");\r
-        kOut.print( kMaterial.Emissive.R + " ");\r
-        kOut.print( kMaterial.Emissive.G + " ");\r
-        kOut.print( kMaterial.Emissive.B );\r
-        kOut.print("\n\t\t\tdiffuseColor\t");\r
-        kOut.print( kMaterial.Diffuse.R + " ");\r
-        kOut.print( kMaterial.Diffuse.G + " ");\r
-        kOut.print( kMaterial.Diffuse.B );\r
-        kOut.print("\n\t\t\tspecularColor\t");\r
-        kOut.print( kMaterial.Specular.R + " ");\r
-        kOut.print( kMaterial.Specular.G + " ");\r
-        kOut.print( kMaterial.Specular.B );\r
-\r
-        float fTransparency = 0f;\r
-        if ( kVBuffer.GetAttributes().GetCChannels(0) == 4)\r
-        {\r
-               fTransparency = 1.0f - kVBuffer.GetColor4(0, 0).A;\r
-        }\r
-        kOut.print("\n\t\t\ttransparency " + fTransparency + "\n");\r
-        kOut.print("\t\t}\n");\r
-        kOut.print("\t}\n");\r
-\r
-        kOut.print("\tgeometry IndexedFaceSet\n\t{\n");\r
-\r
-        kOut.print("\t\tcoord Coordinate\n");\r
-        kOut.print("\t\t{\n");\r
-        kOut.print("\t\t\tpoint [\n\t\t\t\t");\r
-\r
-        // write vertices\r
-        Vector3f kPos = new Vector3f();\r
-        int i;\r
-        for (i = 0; i < kVBuffer.GetVertexQuantity(); i++) {\r
-            kVBuffer.GetPosition3(i, kPos);\r
-            kOut.print(kPos.X);\r
-            kOut.print(' ');\r
-\r
-            kOut.print(kPos.Y);\r
-            kOut.print(' ');\r
-\r
-            kOut.print(kPos.Z);\r
-\r
-            if (i < (kVBuffer.GetVertexQuantity() - 1)) {\r
-                kOut.print(" ,\n\t\t\t\t");\r
-            } else {\r
-                kOut.print("\n\t\t\t\t]\n");\r
-            }\r
-        }\r
-\r
-        // write connectivity\r
-        kOut.print("\t\t\t}\n\t\t\tcoordIndex [\n\t\t\t\t");\r
-        int iTriangleCount = kMesh.IBuffer.GetIndexQuantity() / 3;\r
-        int[] aiIndex = kMesh.IBuffer.GetData();\r
-        for (i = 0; i < iTriangleCount; i++) {\r
-            kOut.print(aiIndex[3 * i]);\r
-            kOut.print(' ');\r
-            kOut.print(aiIndex[(3 * i) + 1]);\r
-            kOut.print(' ');\r
-            kOut.print(aiIndex[(3 * i) + 2]);\r
-\r
-            if (i < (iTriangleCount - 1)) {\r
-                kOut.print(" -1\n\t\t\t\t");\r
-            } else {\r
-                kOut.print("\n\t\t\t\t]\n");\r
-            }\r
-        }\r
-\r
-        kOut.print("\t\t\tconvex FALSE\n");\r
-        kOut.print("\t\t\tcreaseAngle 1.5\n");\r
-        kOut.print("\t}\n}\n");\r
-    }\r
-    \r
-    \r
-    /**\r
-     * Calls a dialog to get a file name.\r
-     * @param   bLoad  if <code>true</code>, make it a load dialog.\r
-     * @return  File name.\r
-     */\r
-    private static String getFileName(boolean bLoad) {\r
-        File[] files = openFiles(bLoad);\r
-\r
-        if (files != null) {\r
-            return new String(files[0].getPath());\r
-        }\r
-\r
-        return null;\r
-    }\r
-    \r
-    \r
-    /**\r
-     * Support for loading the collapse records from a binary file. \r
-     * @param      kIn  the file from which the records are loaded\r
-     * @return CollapseRecord \r
-     * @exception  IOException  if the there is an error reading from the file\r
-     */\r
-    private static CollapseRecord load(RandomAccessFile kIn)\r
-    {\r
-       try {\r
-            int iVKeep = kIn.readInt();\r
-            int iVThrow = kIn.readInt();\r
-            int iVQuantity = kIn.readInt();\r
-            int iTQuantity = kIn.readInt();\r
-            CollapseRecord kRecord = new CollapseRecord(iVKeep, iVThrow, iVQuantity, iTQuantity);\r
-            kRecord.IQuantity = kIn.readInt();\r
-            if ( kRecord.IQuantity > 0 ) {\r
-                byte[] bufferByte = new byte[ kRecord.IQuantity * 4 ];\r
-                int b1 = 0, b2 = 0, b3 = 0, b4 = 0;\r
-                kRecord.Index = new int[kRecord.IQuantity];\r
-                kIn.read(bufferByte);\r
-\r
-                for (int i = 0, index = 0; i < kRecord.IQuantity; i++) {\r
-                    b1 = bufferByte[index++] & 0x000000ff;\r
-                    b2 = bufferByte[index++] & 0x000000ff;\r
-                    b3 = bufferByte[index++] & 0x000000ff;\r
-                    b4 = bufferByte[index++] & 0x000000ff;\r
-                    kRecord.Index[i] = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);\r
-                }\r
-            }\r
-            return kRecord;\r
-       } catch (IOException kIOError ) {}\r
-       return null;\r
-    }\r
-\r
-\r
-    /**\r
-     * Read a TriMesh from a Ply ascii file.\r
-     * @param file file storing the mesh\r
-     * @return TriMesh\r
-     */\r
-    private static TriMesh loadPlyAsciiMesh(File file, ModelImage kImage) {\r
-\r
-        TriMesh mesh;\r
-        int i;\r
-        int iVertexCount = 0;\r
-        int iTriangleCount = 0;\r
-        boolean readHeader = true;\r
-        float x = 0f, y = 0f, z = 0f;\r
-        int idx1 = 0, idx2 = 0, idx3 = 0;\r
-       \r
-        Vector<Vector3f> vertexArray = new Vector<Vector3f>();\r
-        Vector<Integer> connectivity = new Vector<Integer>();\r
-        VertexBuffer kVBuffer;\r
-        int[] aiConnect;\r
-        float _res[] = kImage.getFileInfo(0).getResolutions();\r
-        float[] _startLocation = kImage.getFileInfo()[0].getOrigin();\r
-        int[] _direction = MipavCoordinateSystems.getModelDirections(kImage);\r
-        \r
-        Vector3f ptIn = new Vector3f();\r
-        Vector3f ptOut = new Vector3f();\r
-        \r
-        try {\r
-               \r
-            DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));\r
-            String s, token;\r
-            while ( (s = readLine(in)).length() > 0) {\r
-                StringTokenizer st = new StringTokenizer(s);\r
-                while ( st.hasMoreTokens() && readHeader ) {\r
-                    // System.err.print(st.nextToken() + " ");\r
-                    token = st.nextToken();\r
-                    if ( token.equals("vertex")) {\r
-                        iVertexCount = Integer.valueOf(st.nextToken());\r
-                    } else if ( token.equals("face") ) {\r
-                        iTriangleCount = Integer.valueOf(st.nextToken());\r
-                        readLine(in);\r
-                        readLine(in);  // skip two lines follow the face count attribute in PLY file format.\r
-                        readHeader = false;\r
-                        break;\r
-                    }\r
-                }\r
-                if ( readHeader == false) break;\r
-            }\r
-                  \r
-            // read Vertex \r
-            for ( i = 0; i < iVertexCount; i++ ) {\r
-                s = readLine(in);\r
-                StringTokenizer st = new StringTokenizer(s);\r
-                x = Float.valueOf(st.nextToken());\r
-                y = Float.valueOf(st.nextToken());\r
-                z = Float.valueOf(st.nextToken());\r
-               \r
-                ptIn.X = x;\r
-                ptIn.Y = y;\r
-                ptIn.Z = z;\r
-                \r
-                MipavCoordinateSystems.scannerToFile(ptIn, ptOut, kImage);\r
-                \r
-                       x = (ptOut.X * _res[0] * _direction[0]) + _startLocation[0];\r
-                       y = (ptOut.Y * _res[1] * _direction[1]) + _startLocation[1];\r
-                       z = (ptOut.Z * _res[2] * _direction[2]) + _startLocation[2];\r
-                \r
-                vertexArray.add(new Vector3f(x, y, z));\r
-            }\r
-                   \r
-            // read connectivity\r
-            for ( i = 0; i < iTriangleCount; i++ ) {\r
-                s = readLine(in);\r
-                StringTokenizer st = new StringTokenizer(s);\r
-                st.nextToken();  // skip 3\r
-                idx1 = Integer.valueOf(st.nextToken());\r
-                connectivity.add(idx1);\r
-                idx2 = Integer.valueOf(st.nextToken());\r
-                connectivity.add(idx2);\r
-                idx3 = Integer.valueOf(st.nextToken());\r
-                connectivity.add(idx3);\r
-            }\r
-                   \r
-            int vertexCount = vertexArray.size();\r
-            Attributes kAttr = new Attributes();\r
-            kAttr.SetPChannels(3);\r
-            kAttr.SetNChannels(3);\r
-            kAttr.SetTChannels(0, 3);\r
-            kAttr.SetCChannels(0, 4);\r
-            kVBuffer = new VertexBuffer(kAttr, vertexCount);\r
-\r
-            int index = 0;\r
-            Vector3f pos;\r
-            for (i = 0; i < vertexCount; i++) {\r
-                pos = vertexArray.elementAt(i);\r
-                kVBuffer.SetPosition3(index, pos);\r
-                kVBuffer.SetColor4(0, index, 1.0f, 1.0f, 1.0f, 1.0f);\r
-                index++;\r
-            }\r
-\r
-            int indexCount = connectivity.size();\r
-            aiConnect = new int[indexCount];\r
-            for (i = 0; i < indexCount; i++) {\r
-                aiConnect[i] = connectivity.get(i);\r
-            }\r
-                   \r
-            IndexBuffer kIBuffer = new IndexBuffer( aiConnect.length, aiConnect );\r
-            mesh = new TriMesh(kVBuffer, kIBuffer);\r
-            MaterialState kMaterial = new MaterialState();\r
-            mesh.AttachGlobalState( kMaterial );\r
-            return mesh;\r
-        } catch (FileNotFoundException e) {\r
-            System.err.println("ERROR: Can't find file " + file);\r
-            return null;\r
-        } catch (IOException e) {\r
-            return null;\r
-        }\r
-    }\r
-    \r
-    /**\r
-     * Load the STL ASCII file.\r
-     * @param file STL surface file reference\r
-     * @param source image\r
-     * @return TriMesh\r
-     */\r
-    private static TriMesh loadSTLAsciiMesh(File file, ModelImage kImage) {\r
-\r
-        TriMesh mesh; \r
-        try {\r
-            BufferedReader reader;\r
-            reader = new BufferedReader(new FileReader(file));\r
-            StreamTokenizer tokenizer = new StreamTokenizer(reader);\r
-            tokenizer.resetSyntax();\r
-            tokenizer.whitespaceChars(0, 0x20);\r
-            tokenizer.wordChars(0x21, 0xff);\r
-            mesh = readSTLAscii(tokenizer, kImage);\r
-            reader.close();\r
-            return mesh;\r
-        } catch (FileNotFoundException e) {\r
-            System.err.println("ERROR: Can't find file " + file);\r
-            return null;\r
-        } catch (IOException e) {\r
-            return null;\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Load legacy VTK mesh.\r
-     * @param kIn file containing mesh\r
-     * @param progress progress bar\r
-     * @param added number of meshes read from file so far\r
-     * @param total total number of meshes in file\r
-     * @param flag invert y,z values\r
-     * @return TriMesh\r
-     * @throws IOException\r
-     */\r
-    private static TriMesh loadVTKLegacyMesh(RandomAccessFile kIn, ViewJProgressBar progress, \r
-            int added, int total, String fileName) {\r
-        TriMesh kMesh;\r
-       \r
-        System.out.println(fileName);\r
-        \r
-        StringBuffer buff = new StringBuffer();\r
-        try {\r
-            //progress.setLocation(200, 200);\r
-            progress.setVisible(true);\r
-            String str;\r
-            // Read file as string\r
-            while ((str = kIn.readLine()) != null) {\r
-                buff.append(str+"\n");\r
-            }\r
-        } catch (Exception e) {\r
-            System.err.println("Error occured while reading parameter file:\n"+e.getMessage());\r
-            e.printStackTrace();\r
-            return null;\r
-        }\r
-        Pattern header=Pattern.compile("POINTS\\s\\d+\\sfloat");\r
-        Matcher m=header.matcher(buff);\r
-        int vertexCount=0;\r
-        int indexCount=0;\r
-\r
-        Attributes kAttr = new Attributes();\r
-        kAttr.SetPChannels(3);\r
-        kAttr.SetNChannels(3);\r
-        kAttr.SetTChannels(0,3);\r
-        kAttr.SetCChannels(0,4);\r
-        //kAttr.SetCChannels(1,4);\r
-\r
-        VertexBuffer kVBuffer = null;\r
-        int[] indices;\r
-        if(m.find()){\r
-            String head=buff.substring(m.start(),m.end());\r
-            String[] vals=head.split("\\D+");\r
-            if(vals.length>0){\r
-                try {\r
-                    vertexCount=Integer.parseInt(vals[vals.length-1]);\r
-                } catch(NumberFormatException e){\r
-                    System.err.println("CANNOT DETERMINE VERTEX COUNT");\r
-                    return null;\r
-                }\r
-            }\r
-\r
-            kVBuffer = new VertexBuffer( kAttr, vertexCount );\r
-\r
-            System.out.println("vertex count is " + vertexCount);\r
-            progress.updateValueImmed(added + (25 / total));\r
-            System.out.println(m.end());\r
-            System.out.println(buff.length());\r
-            String[] strs=buff.substring(m.end(),buff.length()).split("\\s+",vertexCount*3+2);\r
-            System.out.println(strs[0]);\r
-            System.out.println(strs[1]);\r
-            for(int i=1;i<strs.length-1;i+=3){\r
-                try {\r
-                    kVBuffer.SetPosition3( (i-1)/3,\r
-                                           Float.parseFloat(strs[i]),\r
-                                           Float.parseFloat(strs[i+1]),\r
-                                           Float.parseFloat(strs[i+2]));\r
-                    kVBuffer.SetColor4(0, (i-1)/3, 1f, 1f, 1f, 1f );\r
-                    //System.out.println(i/3+")"+p);\r
-                } catch(NumberFormatException e){\r
-                    System.err.println("CANNOT FORMAT VERTS");\r
-                    return null;\r
-                }\r
-            }\r
-        } else {\r
-            return null;\r
-        }\r
-        \r
-        progress.updateValueImmed(added + (50 / total));\r
-        \r
-        header=Pattern.compile("POLYGONS\\s+\\d+\\s+\\d+");\r
-        m=header.matcher(buff);\r
-        if(m.find()){\r
-            String head=buff.substring(m.start(),m.end());\r
-            String[] vals=head.split("\\D+");\r
-            if(vals.length>1){\r
-                try {\r
-                    indexCount=Integer.parseInt(vals[1]);\r
-                } catch(NumberFormatException e){\r
-                    System.err.println("CANNOT DETERMINE INDEX COUNT");\r
-                    return null;\r
-                }\r
-            }\r
-            indices=new int[indexCount*3];\r
-            System.out.println("INDICES "+indexCount);\r
-            String[] strs=buff.substring(m.end(),buff.length()).split("\\s+",indexCount*4+2);  \r
-            int count=0;\r
-            System.out.println(strs[0]);\r
-            System.out.println(strs[1]);\r
-            for(int i=1;i<strs.length-1;i+=4){                 \r
-                try {\r
-                    if(Integer.parseInt(strs[i]) != 3) {\r
-                        System.err.println("CANNOT FORMAT INDICES");\r
-                        return null;\r
-                    }\r
-                    indices[count++]=Integer.parseInt(strs[i+1]);\r
-                    indices[count++]=Integer.parseInt(strs[i+2]);\r
-                    indices[count++]=Integer.parseInt(strs[i+3]);\r
-                } catch(NumberFormatException e){\r
-                    System.err.println("CANNOT FORMAT INDICES");\r
-                    return null;\r
-                }\r
-            }\r
-        } else {\r
-            return null;\r
-        }\r
-        \r
-        header=Pattern.compile("POINT_DATA\\s+\\d+\\D+float\\s+\\d+\\nLOOKUP_TABLE\\s");\r
-        m=header.matcher(buff);\r
-        double[][] dat;\r
-        int count=0;\r
-        int dim=0;\r
-        if(m.find()){\r
-            String head=buff.substring(m.start(),m.end());\r
-            String[] vals=head.split("\\D+");\r
-            if(vals.length>0){\r
-                try {\r
-                    count=Integer.parseInt(vals[1]);\r
-                    dim=Integer.parseInt(vals[2]);\r
-                } catch(NumberFormatException e){\r
-                    System.err.println("CANNOT DETERMINE DATA POINTS");\r
-                    return null;\r
-                }\r
-            }\r
-            dat=new double[count][dim];\r
-            System.out.println("DATA POINTS "+count+" by "+dim);\r
-            String[] strs=buff.substring(m.end(),buff.length()).split("\\s+",count*dim+2);\r
-            int index=0;\r
-            for(int i=1;i<strs.length&&index<count*dim;i++){\r
-                try {          \r
-                    dat[index/dim][index%dim]=Double.parseDouble(strs[i]);\r
-                    index++;\r
-                } catch(NumberFormatException e){\r
-                    System.err.println("CANNOT FORMAT DATA ["+strs[i]+"]");\r
-                    //return null;\r
-                }\r
-            }\r
-            //System.out.println(index+" "+count);\r
-            \r
-            progress.updateValueImmed(added + (100 / total));\r
-            \r
-        } else { \r
-            \r
-        }\r
-        IndexBuffer kIBuffer = new IndexBuffer( indices.length, indices );\r
-        kMesh = new TriMesh( kVBuffer, kIBuffer );\r
-        return kMesh;\r
-    }\r
-    \r
-    \r
-    /**\r
-     * Read VTK mesh from file.\r
-     * @param absPath file path\r
-     * @param fileName file name\r
-     * @param dir file directory\r
-     * @return TriMesh\r
-     */\r
-    private static TriMesh loadVTKXMLMesh(String absPath, String fileName, String dir)\r
-    {\r
-        TriMesh kMesh = null;\r
-        \r
-        FileSurfaceVTKXML_WM surfaceVTKXML = new FileSurfaceVTKXML_WM(fileName, dir);\r
-        kMesh = surfaceVTKXML.readXMLSurface_WM(absPath);\r
-\r
-        return kMesh;\r
-    }\r
-    \r
-    /**\r
-     * Read Gifti mesh from file.\r
-     * @param absPath file path\r
-     * @param fileName file name\r
-     * @param dir file directory\r
-     * @return TriMesh\r
-     */\r
-    private static TriMesh loadGiftiXMLMesh(String absPath, String fileName, String dir)\r
-    {\r
-        TriMesh kMesh = null;\r
-        \r
-        FileSurfaceGiftiXML_WM surfaceGiftiXML = new FileSurfaceGiftiXML_WM(fileName, dir);\r
-        kMesh = surfaceGiftiXML.readSurfaceXML(fileName, dir);\r
-\r
-        return kMesh;\r
-    }\r
-   \r
-    /**\r
-     * Returns an array of File objects, based on the user-selected files from the FileChooser dialog.\r
-     * @param   bLoad  whether the files are opened for reading (bLoad = true) or writing (bLoad = false)\r
-     * @return  File[] array of opened files.\r
-     */\r
-    public static File[] openFiles(boolean bLoad) {\r
-\r
-        // file dialog to select surface mesh files (*.sur)\r
-        JFileChooser chooser = new JFileChooser();\r
-        chooser.setMultiSelectionEnabled(bLoad);\r
-        chooser.resetChoosableFileFilters();\r
-        chooser.addChoosableFileFilter(new ViewImageFileFilter(ViewImageFileFilter.SURFACE));\r
-\r
-        if (ViewUserInterface.getReference().getDefaultDirectory() != null) {\r
-            chooser.setCurrentDirectory(new File(ViewUserInterface.getReference().getDefaultDirectory()));\r
-        } else {\r
-            chooser.setCurrentDirectory(new File(System.getProperties().getProperty("user.dir")));\r
-        }\r
-\r
-        int returnVal;\r
-\r
-        if (bLoad) {\r
-            returnVal = chooser.showOpenDialog(null);\r
-        } else {\r
-            returnVal = chooser.showSaveDialog(null);\r
-        }\r
-\r
-        if (returnVal == JFileChooser.APPROVE_OPTION) {\r
-            ViewUserInterface.getReference().setDefaultDirectory(String.valueOf(chooser.getCurrentDirectory()) +\r
-                                                                 File.separatorChar);\r
-\r
-            if (bLoad) {\r
-                File[] files = chooser.getSelectedFiles();\r
-\r
-                return files;\r
-            } \r
-            File[] files = new File[1];\r
-            files[0] = chooser.getSelectedFile();\r
-            return files;\r
-        }\r
-\r
-        return null;\r
-    }\r
-\r
-    \r
-    /**\r
-     * Returns a dicomMatrix file objects, based on the user-selected filed from the FileChooser dialog.\r
-     * @param   bLoad  whether the files are opened for reading (bLoad = true) or writing (bLoad = false)\r
-     * @return  File of opened file.\r
-     */\r
-    private static File openDicomMatrixFiles(boolean bLoad) {\r
-\r
-        // file dialog to select the dicom matrix info file\r
-        JFileChooser chooser = new JFileChooser();\r
-        chooser.setMultiSelectionEnabled(bLoad);\r
-        chooser.resetChoosableFileFilters();\r
-        chooser.addChoosableFileFilter(new ViewImageFileFilter(ViewImageFileFilter.DICOMMATRIX));\r
-\r
-        if (ViewUserInterface.getReference().getDefaultDirectory() != null) {\r
-            chooser.setCurrentDirectory(new File(ViewUserInterface.getReference().getDefaultDirectory()));\r
-        } else {\r
-            chooser.setCurrentDirectory(new File(System.getProperties().getProperty("user.dir")));\r
-        }\r
-\r
-        int returnVal;\r
-\r
-        if (bLoad) {\r
-            returnVal = chooser.showOpenDialog(null);\r
-        } else {\r
-            returnVal = chooser.showSaveDialog(null);\r
-        }\r
-\r
-        if (returnVal == JFileChooser.APPROVE_OPTION) {\r
-            ViewUserInterface.getReference().setDefaultDirectory(String.valueOf(chooser.getCurrentDirectory()) +\r
-                                                                 File.separatorChar);\r
-\r
-            if (bLoad) {\r
-                File file = chooser.getSelectedFile();\r
-\r
-                return file;\r
-            } \r
-            File[] file = new File[1];\r
-            file[0] = chooser.getSelectedFile();\r
-            return file[0];\r
-        }\r
-\r
-        return null;\r
-    }\r
-     \r
-    /**\r
-        * Print the contents of the TriMesh in ascii format.\r
+       /**\r
+        * Load the STL ASCII file.\r
         * \r
         * \r
-        * @param kOut\r
-        *            output\r
-        * @param kMesh\r
-        *            TriMesh\r
+        * @param file\r
+        *            STL surface file reference\r
+        * @param source\r
+        *            image\r
+        * @return TriMesh\r
         */\r
         */\r
-    private static void printAscii(PrintWriter kOut, TriMesh kMesh) {\r
-       Vector3f kVertex = new Vector3f();\r
-        Vector3f kNormal = new Vector3f();\r
-\r
-        // write vertices\r
-        kOut.println(kMesh.VBuffer.GetVertexQuantity());\r
-        kOut.println("Vertices");\r
-\r
-        int i;\r
-\r
-        for (i = 0; i < kMesh.VBuffer.GetVertexQuantity(); i++) {\r
-            kMesh.VBuffer.GetPosition3(i, kVertex);\r
-            kOut.print(kVertex.X);\r
-            kOut.print(' ');\r
-            kOut.print(kVertex.Y);\r
-            kOut.print(' ');\r
-            kOut.println(kVertex.Z);\r
-        }\r
-\r
-        kOut.println("Normals");\r
-\r
-        // write normals\r
-        for (i = 0; i < kMesh.VBuffer.GetVertexQuantity(); i++) {\r
-               kMesh.VBuffer.GetNormal3(i, kNormal);\r
-            kOut.print(kNormal.X);\r
-            kOut.print(' ');\r
-            kOut.print(kNormal.Y);\r
-            kOut.print(' ');\r
-            kOut.println(kNormal.Z);\r
-        }\r
-\r
-        kOut.println("Connectivity");\r
-\r
-        // write connectivity\r
-        int iTriangleCount = kMesh.GetTriangleQuantity();\r
-        int[] aiIndex = kMesh.IBuffer.GetData();\r
-        kOut.println(iTriangleCount);\r
-\r
-        for (i = 0; i < iTriangleCount; i++) {\r
-            kOut.print(aiIndex[(3 * i)]);\r
-            kOut.print(' ');\r
-            kOut.print(aiIndex[((3 * i) + 1)]);\r
-            kOut.print(' ');\r
-            kOut.println(aiIndex[((3 * i) + 2)]);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Print the contents of the TriMesh in STL ascii format.\r
-     * @param kOut output\r
-     * @param kMesh TriMesh\r
-     */\r
-    private static void printSTLAscii(PrintWriter kOut, ModelImage kImage, TriMesh kMesh)\r
-    {\r
-        int i;\r
-        int index1, index2, index3;\r
-        VertexBuffer kVBuffer;\r
-        int iTriangleCount = kMesh.IBuffer.GetIndexQuantity() / 3;\r
-        int[] aiIndex = kMesh.IBuffer.GetData();\r
-        Vector3f kVertex = new Vector3f();\r
-        Vector3f kNormal = new Vector3f();\r
-        Vector3f kNormal1 = new Vector3f();\r
-        Vector3f kNormal2 = new Vector3f();\r
-        Vector3f kNormal3 = new Vector3f();\r
-\r
-        if ( kImage != null ) {\r
-          kVBuffer = convertVertex(kImage, kMesh);\r
-        } else {\r
-          kVBuffer = kMesh.VBuffer;\r
-        }\r
-        \r
-        kOut.println("solid");\r
-        \r
-        for (i = 0; i < iTriangleCount; i++) {\r
-            index1 = aiIndex[(3 * i)];    \r
-            index2 = aiIndex[((3 * i) + 1)];\r
-            index3 = aiIndex[((3 * i) + 2)];\r
-            \r
-            kVBuffer.GetPosition3(index1, kNormal1);\r
-            kVBuffer.GetPosition3(index2, kNormal2);\r
-            kVBuffer.GetPosition3(index3, kNormal3);\r
-                   \r
-            // Compute facet normal\r
-            kNormal.set(0f, 0f, 0f).add(kNormal1).add(kNormal2).add(kNormal3).scale(1f/3f);\r
-            \r
-            kOut.print(" facet normal  ");\r
-            kOut.print(kNormal.X);\r
-            kOut.print(' ');\r
-            kOut.print(kNormal.Y);\r
-            kOut.print(' ');\r
-            kOut.println(kNormal.Z);\r
-            \r
-            kOut.println("   outer loop");\r
-            // index 1\r
-            kVBuffer.GetPosition3(index1, kVertex);\r
-            kOut.print("     vertex ");\r
-            kOut.print(kVertex.X);\r
-            kOut.print(' ');\r
-            kOut.print(kVertex.Y);\r
-            kOut.print(' ');\r
-            kOut.println(kVertex.Z);\r
-            // index 2\r
-            kVBuffer.GetPosition3(index2, kVertex);\r
-            kOut.print("     vertex ");\r
-            kOut.print(kVertex.X);\r
-            kOut.print(' ');\r
-            kOut.print(kVertex.Y);\r
-            kOut.print(' ');\r
-            kOut.println(kVertex.Z);\r
-            // index 3\r
-            kVBuffer.GetPosition3(index3, kVertex);\r
-            kOut.print("     vertex ");\r
-            kOut.print(kVertex.X);\r
-            kOut.print(' ');\r
-            kOut.print(kVertex.Y);\r
-            kOut.print(' ');\r
-            kOut.println(kVertex.Z);\r
-            \r
-            kOut.println("   endloop");\r
-            kOut.println(" endfacet");\r
-        }\r
-        kOut.println("endsolid");\r
-    }\r
-    \r
-    /**\r
-     * Print the contents of the TriMesh in STL ascii format.\r
-     * @param kOut output\r
-     * @param kMesh TriMesh\r
-     */\r
-    private static void printProstateSTLAscii(PrintWriter kOut, ModelImage kImage, TriMesh kMesh)\r
-    {\r
-        int i;\r
-        int index1, index2, index3;\r
-        VertexBuffer kVBuffer;\r
-        float res[] = kImage.getFileInfo(0).getResolutions();\r
-        int iTriangleCount = kMesh.IBuffer.GetIndexQuantity() / 3;\r
-        int[] aiIndex = kMesh.IBuffer.GetData();\r
-        \r
-        Vector3f kNormal = new Vector3f();\r
-        Vector3f kNormal1 = new Vector3f();\r
-        Vector3f kNormal2 = new Vector3f();\r
-        Vector3f kNormal3 = new Vector3f();\r
-        \r
-        Vector3f kVertex1 = new Vector3f();\r
-        Vector3f kVertex2 = new Vector3f();\r
-        Vector3f kVertex3 = new Vector3f();\r
-        \r
-        kVBuffer = kMesh.VBuffer;\r
-       \r
-        kOut.println("solid");\r
-        \r
-        for (i = 0; i < iTriangleCount; i++) {\r
-            index1 = aiIndex[(3 * i)];    \r
-            index2 = aiIndex[((3 * i) + 1)];\r
-            index3 = aiIndex[((3 * i) + 2)];\r
-        \r
-            kVBuffer.GetPosition3(index1, kNormal1);\r
-            kVBuffer.GetPosition3(index2, kNormal2);\r
-            kVBuffer.GetPosition3(index3, kNormal3);\r
-            \r
-            MipavCoordinateSystems.scannerToFile(kNormal1, kVertex1, kImage);\r
-            MipavCoordinateSystems.scannerToFile(kNormal2, kVertex2, kImage);\r
-            MipavCoordinateSystems.scannerToFile(kNormal3, kVertex3, kImage);\r
-            \r
-            kVertex1.X *= res[0]; kVertex1.Y *= res[1]; kVertex1.Z *= res[2];\r
-            kVertex2.X *= res[0]; kVertex2.Y *= res[1]; kVertex2.Z *= res[2];\r
-            kVertex3.X *= res[0]; kVertex3.Y *= res[1]; kVertex3.Z *= res[2];\r
-            \r
-            // Compute facet normal\r
-            kNormal.set(0f, 0f, 0f).add(kVertex1).add(kVertex2).add(kVertex3).scale(1f/3f);\r
-            \r
-            kOut.print(" facet normal  ");\r
-            kOut.print(kNormal.X);\r
-            kOut.print(' ');\r
-            kOut.print(kNormal.Y);\r
-            kOut.print(' ');\r
-            kOut.println(kNormal.Z);\r
-            \r
-            kOut.println("   outer loop");\r
-               \r
-            // index 1\r
-            kOut.print("     vertex ");\r
-            kOut.print(kVertex1.X);\r
-            kOut.print(' ');\r
-            kOut.print(kVertex1.Y);\r
-            kOut.print(' ');\r
-            kOut.println(kVertex1.Z);\r
-            // index 2\r
-            kOut.print("     vertex ");\r
-            kOut.print(kVertex2.X);\r
-            kOut.print(' ');\r
-            kOut.print(kVertex2.Y);\r
-            kOut.print(' ');\r
-            kOut.println(kVertex2.Z);\r
-            // index 3\r
-            kOut.print("     vertex ");\r
-            kOut.print(kVertex3.X);\r
-            kOut.print(' ');\r
-            kOut.print(kVertex3.Y);\r
-            kOut.print(' ');\r
-            kOut.println(kVertex3.Z);\r
-            \r
-            kOut.println("   endloop");\r
-            kOut.println(" endfacet");\r
-        }\r
-        kOut.println("endsolid");\r
-    }\r
-    \r
-    /**\r
-     * Read a TriMesh from an ascii file.\r
-     * @param kFile file containing TriMesh\r
-     * @return TriMesh\r
-     * @throws IOException I/O exception\r
-     */\r
-    private static TriMesh readAscii(File kFile) throws IOException {\r
-        DataInputStream in =\r
-            new DataInputStream(new BufferedInputStream(new FileInputStream(kFile)));\r
-        String s, token;\r
-        s = readLine(in);\r
-        s = readLine(in);\r
-        s = readLine(in);\r
-        StringTokenizer st = new StringTokenizer(s);\r
-        int iNumVertices = 1;\r
-        if ( st.hasMoreTokens() )\r
-        {\r
-            token = st.nextToken();\r
-            iNumVertices = Integer.valueOf(token).intValue();\r
-        }\r
-        Attributes kAttr = new Attributes();\r
-        kAttr.SetPChannels(3);\r
-        kAttr.SetNChannels(3);\r
-        kAttr.SetTChannels(0, 3);\r
-        kAttr.SetCChannels(0, 4);\r
-        VertexBuffer kVBuffer = new VertexBuffer(kAttr, iNumVertices);\r
-        float fX, fY, fZ;\r
-        s = readLine(in);\r
-        for ( int i = 0; i < iNumVertices; i++ )\r
-        {\r
-            s = readLine(in);\r
-            st = new StringTokenizer(s);\r
-            token = st.nextToken();\r
-            fX = Float.valueOf(token).floatValue();\r
-            token = st.nextToken();\r
-            fY = Float.valueOf(token).floatValue();\r
-            token = st.nextToken();\r
-            fZ = Float.valueOf(token).floatValue();\r
-            kVBuffer.SetPosition3( i, fX, fY, fZ );\r
-            kVBuffer.SetColor4( 0, i, ColorRGBA.WHITE);\r
-        }\r
-        s = readLine(in);\r
-        for ( int i = 0; i < iNumVertices; i++ )\r
-        {\r
-            s = readLine(in);\r
-            st = new StringTokenizer(s);\r
-            token = st.nextToken();\r
-            fX = Float.valueOf(token).floatValue();\r
-            token = st.nextToken();\r
-            fY = Float.valueOf(token).floatValue();\r
-            token = st.nextToken();\r
-            fZ = Float.valueOf(token).floatValue();\r
-            kVBuffer.SetNormal3( i, fX, fY, fZ );\r
-        }\r
-        \r
-        int iTriangleCount = 0;\r
-        s = readLine(in);\r
-        s = readLine(in);\r
-        st = new StringTokenizer(s);\r
-        if ( st.hasMoreTokens() )\r
-        {\r
-            token = st.nextToken();\r
-            iTriangleCount = Integer.valueOf(token).intValue();\r
-        }\r
-\r
-        int[] aiIndex = new int[ iTriangleCount * 3 ];\r
-\r
-        for (int i = 0; i < iTriangleCount; i++) {\r
-            s = readLine(in);\r
-            st = new StringTokenizer(s);\r
-            token = st.nextToken();\r
-            aiIndex[(3 * i)] = Integer.valueOf(token).intValue();\r
-            token = st.nextToken();\r
-            aiIndex[((3 * i) + 1)] = Integer.valueOf(token).intValue();\r
-            token = st.nextToken();\r
-            aiIndex[((3 * i) + 2)] = Integer.valueOf(token).intValue();\r
-        }\r
-        return new TriMesh( kVBuffer, new IndexBuffer(aiIndex) );\r
-    }\r
-    \r
-    /** Read a line of ASCII text from the input stream. \r
-     * @param in InputStream\r
-     * @return line of the ascii file as a String\r
-     * @throws IOException I/O exception\r
-     */\r
-    private static String readLine(InputStream in) throws IOException\r
-    {\r
-        StringBuffer buf = new StringBuffer();\r
-        int c;\r
-        while ((c = in.read()) > -1 && c != '\n')\r
-        {\r
-            buf.append((char) c);\r
-        }\r
-        return buf.toString();\r
-    }\r
-\r
-    /**\r
-     * Find the given label in the tokenizer stream and then return the next\r
-     * three numbers as a point. Return null if end of stream\r
-     * @param tokenizer stream in\r
-     * @param label string label (vertex, normal ) in the STL ASCII file.\r
-     * @return Vector3f point coordinate.\r
-     * @throws IOException\r
-     */\r
-    private static Vector3f readPoint(StreamTokenizer tokenizer, String label)\r
-        throws IOException {\r
-        while (true) {\r
-            if (tokenizer.nextToken() == StreamTokenizer.TT_EOF)\r
-                return null;\r
-            if (tokenizer.sval.equals(label))\r
-                break;\r
-        }\r
-\r
-        if (tokenizer.nextToken() == StreamTokenizer.TT_EOF)\r
-            return null;\r
-        float x = Float.valueOf(tokenizer.sval).floatValue();\r
-        if (tokenizer.nextToken() == StreamTokenizer.TT_EOF)\r
-            return null;\r
-        float y = Float.valueOf(tokenizer.sval).floatValue();\r
-        if (tokenizer.nextToken() == StreamTokenizer.TT_EOF)\r
-            return null;\r
-        float z = Float.valueOf(tokenizer.sval).floatValue();\r
-\r
-        return new Vector3f(x, y, z);\r
-    }\r
-    \r
-    /**\r
-     * Read the STL ASCII file as a single stream tokenizer.\r
-     * @param tokenizer  stream in\r
-     * @return  Triangle mesh\r
-     * @throws IOException\r
-     */\r
-    private static TriMesh readSTLAscii(StreamTokenizer tokenizer, ModelImage kImage) throws IOException {\r
-               \r
-        Vector3f temp = new Vector3f();\r
-        Vector3f normal = new Vector3f(); \r
-        Vector3f side1 = new Vector3f();\r
-        Vector3f side2 = new Vector3f();\r
-        Vector3f surfaceNormal = new Vector3f();\r
-        Vector<Vector3f> vertexArray = new Vector<Vector3f>();\r
-        VertexBuffer kVBuffer;\r
-        int[] aiConnect;\r
-        \r
-        TriMesh kMesh = null;\r
-        float x, y, z;\r
-        Vector3f vertex1, vertex2, vertex3;\r
-        int index = 0;\r
-        Integer searchIndex;\r
-        Vector<Integer> connectivity = new Vector<Integer>();\r
-        HashMap<String, Integer> vertexHashtable = new HashMap<String, Integer>();\r
-        \r
-        float _res[] = kImage.getFileInfo(0).getResolutions();\r
-        float[] _startLocation = kImage.getFileInfo()[0].getOrigin();\r
-        int[] _direction = MipavCoordinateSystems.getModelDirections(kImage);\r
-        \r
-        Vector3f ptIn = new Vector3f();\r
-        Vector3f ptOut = new Vector3f();\r
-        \r
-        try {\r
-               \r
-            while (true) {\r
-                if ((temp = readPoint(tokenizer, "normal")) == null)\r
-                    break;\r
-                normal = new Vector3f(temp);\r
-\r
-                vertex1 = readPoint(tokenizer, "vertex");\r
-                vertex2 = readPoint(tokenizer, "vertex");\r
-                vertex3 = readPoint(tokenizer, "vertex");\r
-\r
-                // Check that the normal is in the correct direction\r
-                side1.copy(vertex2).sub(vertex1);\r
-                side2.copy(vertex3).sub(vertex2);\r
-\r
-                surfaceNormal.copy(side1).cross(side2);\r
-                if (normal.dot(surfaceNormal) < 0) {\r
-                    // vertices were specified in the wrong order, so reverse\r
-                    // two of them\r
-                    temp.copy(vertex2);\r
-                    vertex2.copy(vertex3);\r
-                    vertex3.copy(temp);\r
-                }\r
-\r
-                // index 1;\r
-                x = vertex1.X;\r
-                y = vertex1.Y;\r
-                z = vertex1.Z;\r
-\r
-                ptIn.X = x;\r
-                ptIn.Y = y;\r
-                ptIn.Z = z;\r
-                \r
-                MipavCoordinateSystems.scannerToFile(ptIn, ptOut, kImage);\r
-                \r
-                       x = (ptOut.X * _res[0] * _direction[0]) + _startLocation[0];\r
-                       y = (ptOut.Y * _res[1] * _direction[1]) + _startLocation[1];\r
-                       z = (ptOut.Z * _res[2] * _direction[2]) + _startLocation[2];\r
-                \r
-                searchIndex = vertexHashtable.get((x + " " + y + " " + z));\r
-                if (searchIndex == null) { // not found\r
-                    vertexHashtable.put((x + " " + y + " " + z), new Integer(\r
-                                                                             index));\r
-                    connectivity.add(new Integer(index));\r
-                    vertexArray.add(new Vector3f(x, y, z));\r
-                    index++;\r
-                } else {\r
-                    connectivity.add(searchIndex);\r
-                }\r
-                               \r
-                // index 2;\r
-                x = vertex2.X;\r
-                y = vertex2.Y;\r
-                z = vertex2.Z;\r
-\r
-                ptIn.X = x;\r
-                ptIn.Y = y;\r
-                ptIn.Z = z;\r
-                \r
-                MipavCoordinateSystems.scannerToFile(ptIn, ptOut, kImage);\r
-                \r
-                       x = (ptOut.X * _res[0] * _direction[0]) + _startLocation[0];\r
-                       y = (ptOut.Y * _res[1] * _direction[1]) + _startLocation[1];\r
-                       z = (ptOut.Z * _res[2] * _direction[2]) + _startLocation[2];\r
-                \r
-                searchIndex = vertexHashtable.get((x + " " + y + " " + z));\r
-                if (searchIndex == null) { // not found\r
-                    vertexHashtable.put((x + " " + y + " " + z), new Integer(\r
-                                                                             index));\r
-                    connectivity.add(new Integer(index));\r
-                    vertexArray.add(new Vector3f(x, y, z));\r
-                    index++;\r
-                } else {\r
-                    connectivity.add(searchIndex);\r
-                }\r
-                               \r
-                // index 3;\r
-                x = vertex3.X;\r
-                y = vertex3.Y;\r
-                z = vertex3.Z;\r
-\r
-                ptIn.X = x;\r
-                ptIn.Y = y;\r
-                ptIn.Z = z;\r
-                \r
-                MipavCoordinateSystems.scannerToFile(ptIn, ptOut, kImage);\r
-                \r
-                       x = (ptOut.X * _res[0] * _direction[0]) + _startLocation[0];\r
-                       y = (ptOut.Y * _res[1] * _direction[1]) + _startLocation[1];\r
-                       z = (ptOut.Z * _res[2] * _direction[2]) + _startLocation[2];\r
-                \r
-                searchIndex = vertexHashtable.get((x + " " + y + " " + z));\r
-                if (searchIndex == null) { // not found\r
-                    vertexHashtable.put((x + " " + y + " " + z), new Integer(\r
-                                                                             index));\r
-                    connectivity.add(new Integer(index));\r
-                    vertexArray.add(new Vector3f(x, y, z));\r
-                    index++;\r
-                } else {\r
-                    connectivity.add(searchIndex);\r
-                }\r
-\r
-            }\r
-\r
-            int vertexCount = vertexArray.size();\r
-            Attributes kAttr = new Attributes();\r
-            kAttr.SetPChannels(3);\r
-            kAttr.SetNChannels(3);\r
-            kAttr.SetTChannels(0, 3);\r
-            kAttr.SetCChannels(0, 4);\r
-            kVBuffer = new VertexBuffer(kAttr, vertexCount);\r
-\r
-            index = 0;\r
-            Vector3f pos;\r
-            for (int i = 0; i < vertexCount; i++) {\r
-                pos = vertexArray.elementAt(i);\r
-                kVBuffer.SetPosition3(index, pos);\r
-                kVBuffer.SetColor4(0, index, 1.0f, 1.0f, 1.0f, 1.0f);\r
-                index++;\r
-            }\r
-\r
-            int indexCount = connectivity.size();\r
-            aiConnect = new int[indexCount];\r
-            for (int i = 0; i < indexCount; i++) {\r
-                aiConnect[i] = connectivity.get(i);\r
-            }\r
-\r
-        } catch (IOException e) {\r
-            throw e;\r
-        }\r
-        IndexBuffer kIBuffer = new IndexBuffer( aiConnect.length, aiConnect );\r
-        kMesh = new TriMesh(kVBuffer, kIBuffer);\r
-        MaterialState kMaterial = new MaterialState();\r
-        kMesh.AttachGlobalState( kMaterial );\r
-        return kMesh;\r
-    }\r
-    \r
-\r
-    /**\r
-     * Load the STL ASCII file.\r
-     * @param file STL surface file reference\r
-     * @param source image\r
-     * @return TriMesh\r
-     */\r
-    private static TriMesh loadSTLBinaryMesh(File file, ModelImage kImage) {\r
-\r
-        TriMesh mesh; \r
-        try {\r
-               FileInputStream data;    \r
-               data = new FileInputStream(file);\r
-            mesh = readSTLBinary(data, kImage);\r
-            // reader.close();\r
-            return mesh;\r
-        } catch (FileNotFoundException e) {\r
-            System.err.println("ERROR: Can't find file " + file);\r
-            return null;\r
-        } catch (IOException e) {\r
-            return null;\r
-        }\r
-    }\r
-\r
-    \r
-    /**\r
-     * Method for reading binary files Execution is completly different\r
-     * It uses ByteBuffer for reading data and ByteOrder for retrieving the machine's endian\r
-     * (Needs JDK 1.4)\r
-     *\r
-     * TO-DO:\r
-     *  1.-Be able to read files over Internet\r
-     *  2.-If the amount of data expected is bigger than what is on the file then\r
-     *  the program will block forever\r
-     *\r
-     * @param file The name of the file\r
-     *\r
-     * @throws IOException\r
-     */\r
-    private static TriMesh readSTLBinary(FileInputStream data, ModelImage kImage) throws IOException {\r
+       private static TriMesh loadSTLBinaryMesh(File file, ModelImage kImage) {\r
+\r
+               TriMesh mesh;\r
+               try {\r
+                       FileInputStream data;\r
+                       data = new FileInputStream(file);\r
+                       mesh = readSTLBinary(data, kImage);\r
+                       // reader.close();\r
+                       return mesh;\r
+               } catch (FileNotFoundException e) {\r
+                       System.err.println("ERROR: Can't find file " + file);\r
+                       return null;\r
+               } catch (IOException e) {\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Method for reading binary files Execution is completly different It uses\r
+        * ByteBuffer for reading data and ByteOrder for retrieving the machine's endian\r
+        * (Needs JDK 1.4)\r
+        *\r
+        * TO-DO: 1.-Be able to read files over Internet 2.-If the amount of data\r
+        * expected is bigger than what is on the file then the program will block\r
+        * forever\r
+        *\r
+        * @param file\r
+        *            The name of the file\r
+        *\r
+        * @throws IOException\r
+        */\r
+       private static TriMesh readSTLBinary(FileInputStream data, ModelImage kImage) throws IOException {\r
                ByteBuffer dataBuffer; // For reading in the correct endian\r
                byte[] Info = new byte[80]; // Header data\r
                byte[] Array_number = new byte[4]; // Holds the number of faces\r
                ByteBuffer dataBuffer; // For reading in the correct endian\r
                byte[] Info = new byte[80]; // Header data\r
                byte[] Array_number = new byte[4]; // Holds the number of faces\r
@@ -2346,7 +2410,8 @@ public class FileSurface_WM {
                        normal.Y = dataBuffer.getFloat();\r
                        normal.Z = dataBuffer.getFloat();\r
 \r
                        normal.Y = dataBuffer.getFloat();\r
                        normal.Z = dataBuffer.getFloat();\r
 \r
-                       // System.out.println("Normal: X=" + normal.X + " Y=" + normal.Y + " Z=" + normal.Z);\r
+                       // System.out.println("Normal: X=" + normal.X + " Y=" + normal.Y + " Z=" +\r
+                       // normal.Z);\r
 \r
                        // Read vertex1\r
                        vertex1 = new Vector3f();\r
 \r
                        // Read vertex1\r
                        vertex1 = new Vector3f();\r
@@ -2354,7 +2419,8 @@ public class FileSurface_WM {
                        vertex1.Y = dataBuffer.getFloat();\r
                        vertex1.Z = dataBuffer.getFloat();\r
 \r
                        vertex1.Y = dataBuffer.getFloat();\r
                        vertex1.Z = dataBuffer.getFloat();\r
 \r
-                       // System.out.println("Vertex 1: X=" + vertex1.X + " Y=" + vertex1.Y + " Z=" + vertex1.Z);\r
+                       // System.out.println("Vertex 1: X=" + vertex1.X + " Y=" + vertex1.Y + " Z=" +\r
+                       // vertex1.Z);\r
 \r
                        x = vertex1.X;\r
                        y = vertex1.Y;\r
 \r
                        x = vertex1.X;\r
                        y = vertex1.Y;\r
@@ -2385,7 +2451,8 @@ public class FileSurface_WM {
                        vertex2.X = dataBuffer.getFloat();\r
                        vertex2.Y = dataBuffer.getFloat();\r
                        vertex2.Z = dataBuffer.getFloat();\r
                        vertex2.X = dataBuffer.getFloat();\r
                        vertex2.Y = dataBuffer.getFloat();\r
                        vertex2.Z = dataBuffer.getFloat();\r
-                       // System.out.println("Vertex 2: X=" + vertex2.X + " Y=" + vertex2.Y + " Z=" + vertex2.Z);\r
+                       // System.out.println("Vertex 2: X=" + vertex2.X + " Y=" + vertex2.Y + " Z=" +\r
+                       // vertex2.Z);\r
 \r
                        x = vertex2.X;\r
                        y = vertex2.Y;\r
 \r
                        x = vertex2.X;\r
                        y = vertex2.Y;\r
@@ -2416,7 +2483,8 @@ public class FileSurface_WM {
                        vertex3.X = dataBuffer.getFloat();\r
                        vertex3.Y = dataBuffer.getFloat();\r
                        vertex3.Z = dataBuffer.getFloat();\r
                        vertex3.X = dataBuffer.getFloat();\r
                        vertex3.Y = dataBuffer.getFloat();\r
                        vertex3.Z = dataBuffer.getFloat();\r
-                       // System.out.println("Vertex 3: X=" + vertex3.X + " Y=" + vertex3.Y + " Z=" + vertex3.Z);\r
+                       // System.out.println("Vertex 3: X=" + vertex3.X + " Y=" + vertex3.Y + " Z=" +\r
+                       // vertex3.Z);\r
 \r
                        x = vertex3.X;\r
                        y = vertex3.Y;\r
 \r
                        x = vertex3.X;\r
                        y = vertex3.Y;\r
@@ -2481,20 +2549,19 @@ public class FileSurface_WM {
 \r
        }// End of readBinaryFile\r
 \r
 \r
        }// End of readBinaryFile\r
 \r
-    \r
-    /**\r
-     * Method that reads a face in binary files\r
-     * All binary versions of the methods end by 'B'\r
-     * As in binary files we can read the number of faces, we don't need\r
-     * to use coordArray and normArray (reading binary files should be faster)\r
-     *\r
-     * @param in The ByteBuffer with the data of the object.\r
-     * @param index The facet index\r
-     *\r
-     * @throws IOException\r
-     */\r
-    private void readFacetB(ByteBuffer in, int index) throws IOException\r
- {\r
+       /**\r
+        * Method that reads a face in binary files All binary versions of the methods\r
+        * end by 'B' As in binary files we can read the number of faces, we don't need\r
+        * to use coordArray and normArray (reading binary files should be faster)\r
+        *\r
+        * @param in\r
+        *            The ByteBuffer with the data of the object.\r
+        * @param index\r
+        *            The facet index\r
+        *\r
+        * @throws IOException\r
+        */\r
+       private void readFacetB(ByteBuffer in, int index) throws IOException {\r
                // File structure: Normal Vertex1 Vertex2 Vertex3\r
                Vector3f normal = new Vector3f();\r
                Point3f vertex = new Point3f();\r
                // File structure: Normal Vertex1 Vertex2 Vertex3\r
                Vector3f normal = new Vector3f();\r
                Point3f vertex = new Point3f();\r
@@ -2538,1031 +2605,1064 @@ public class FileSurface_WM {
 \r
        }// End of readFacetB\r
 \r
 \r
        }// End of readFacetB\r
 \r
-    \r
-    /**\r
-     * Load a triangle mesh from the specified file and assign to it the MaterialState.\r
-     * @param   kImage  ModelImage displayed in the SurfaceRender class\r
-     * @param   file    The triangle mesh file to load.\r
-     * @param   kMaterial The Material for the surface.\r
-     * @return  TriMesh\r
-     */\r
-    public static TriMesh readSurface(ModelImage kImage, File file, MaterialState kMaterial )\r
-    {\r
-       return readSurface(kImage, file, kMaterial, false);\r
-    }\r
-\r
-    /**\r
-     * Load a triangle mesh from the specified file and assign to it the MaterialState.\r
-     * @param   kImage  ModelImage displayed in the SurfaceRender class\r
-     * @param   file    The triangle mesh file to load.\r
-     * @param   kMaterial The Material for the surface.\r
-     * @return  TriMesh\r
-     */\r
-    public static TriMesh readSurface(ModelImage kImage, File file, MaterialState kMaterial, boolean toFileCoords )\r
-    {\r
-        int iType = 0, iQuantity = 0;\r
-        boolean isSur = true;\r
-        int[] extents = kImage.getExtents();\r
-        int xDim = extents[0];\r
-        int yDim = extents[1];\r
-        int zDim = extents[2];\r
-\r
-\r
-        float[] resols = kImage.getFileInfo()[0].getResolutions();\r
-        float xBox = (xDim - 1) * resols[0];\r
-        float yBox = (yDim - 1) * resols[1];\r
-        float zBox = (zDim - 1) * resols[2];\r
-        float maxBox = Math.max(xBox, Math.max(yBox, zBox));\r
-\r
-        FileSurfaceRefXML_WM kSurfaceXML;\r
-        FileInfoSurfaceRefXML kFileInfo = null;\r
-        RandomAccessFile in = null;\r
-        \r
-        if (file.getName().endsWith("sur")) {\r
-            try {\r
-                in = new RandomAccessFile(file, "r");\r
-                iType = in.readInt();\r
-                iQuantity = in.readInt();\r
-                isSur = true;\r
-            } catch (IOException e) {\r
-                return null;\r
-            }\r
-        } \r
-        else if ( file.getName().endsWith("xml") ) {\r
-            kSurfaceXML = new FileSurfaceRefXML_WM(file.getName(), file.getParent());\r
-            kFileInfo = kSurfaceXML.readSurfaceXML(file.getName(), file.getParent());\r
-\r
-            file = new File(file.getParent()+ File.separatorChar + kFileInfo.getSurfaceFileName());\r
-            try {\r
-                in = new RandomAccessFile(file, "r");\r
-                iType = in.readInt();\r
-                iQuantity = in.readInt();\r
-                isSur = true;\r
-            } catch (IOException e) {\r
-                return null;\r
-            }\r
-        } else if ( file.getName().endsWith("wrl") ) {\r
-\r
-            try {\r
-                in = new RandomAccessFile(file, "r");\r
-                iType = 0;\r
-                iQuantity = parseVRMLMesh(in);\r
-                in.seek(0);\r
-                isSur = false;\r
-            } catch (NoSuchElementException e) {\r
-                MipavUtil.displayError("Only load VRML file specifically written by MIPAV! ");\r
-\r
-                return null;\r
-            } catch (IOException e) {\r
-                return null;\r
-            }\r
-        } else if ( file.getName().endsWith("stl") ) {\r
-            iType = 0;\r
-            iQuantity = 1;\r
-            isSur = false;\r
-        } else if ( file.getName().endsWith("ply") ) {\r
-            iType = 0;\r
-            iQuantity = 1;\r
-            isSur = false;\r
-        } else if ( file.getName().endsWith("gii") ) {\r
-            try {\r
-                in = new RandomAccessFile(file, "r");\r
-                iType = 0;\r
-                iQuantity = 1;\r
-                isSur = false;\r
-            } catch (IOException e) {\r
-                return null;\r
-            }\r
-        } else {\r
-            //has to be vtk legacy or vtk xml\r
-            try {\r
-                in = new RandomAccessFile(file, "r");\r
-                iType = 0;\r
-                iQuantity = 1;\r
-                in.seek(0);\r
-                //not sure what this flag means\r
-                isSur = false;\r
-            }\r
-            catch (IOException e) {\r
-                return null;\r
-            }\r
-        }\r
-\r
-        TriMesh[] akComponent = new TriMesh[iQuantity];\r
-        ViewJProgressBar progress = new ViewJProgressBar("Loading surface", "Loading surface", 0, 100, false, null,\r
-                                                         null);\r
-        progress.setVisible(true);\r
-\r
-        try {\r
-            // meshes are type TriangleMesh\r
-            for (int i = 0; i < iQuantity; i++) {\r
-                \r
-                float[] startLocation = kImage.getFileInfo(0).getOrigin();\r
-                int[] aiModelDirection = MipavCoordinateSystems.getModelDirections(kImage);\r
-                float[] direction = new float[] { aiModelDirection[0], aiModelDirection[1], aiModelDirection[2]}; \r
-                float[] box = new float[]{0f,0f,0f};\r
-                if (iType == 0) {\r
-\r
-                    if (isSur == true) {\r
-                        akComponent[i] = loadTMesh(in, progress, i * 100 / iQuantity, iQuantity,\r
-                                                   true, kMaterial,\r
-                                                   startLocation, direction, box );\r
-                        //xBox = box[0];\r
-                        //yBox = box[1];\r
-                        //zBox = box[2];\r
-                        //maxBox = Math.max(xBox, Math.max(yBox, zBox));\r
-                    }\r
-                    else {\r
-                       if ( file.getName().endsWith("wrl") ) {\r
-                            akComponent[i] = loadVRMLMesh(in, progress, i * 100 / iQuantity, iQuantity,\r
-                                                          (i == 0),\r
-                                                          startLocation, direction, box );\r
-                       }\r
-                        else if (file.getName().endsWith("vtk")){\r
-                            //vtk legacy\r
-                            akComponent[i] = loadVTKLegacyMesh(in, progress, i * 100 / iQuantity, iQuantity, file.getName());\r
-                        }\r
-                       else if(file.getName().endsWith("vtp")) {\r
-                            //vtk xml\r
-                            akComponent[i] = loadVTKXMLMesh( file.getAbsolutePath(), file.getName(), file.getParent());\r
-                       }\r
-                       else if(file.getName().endsWith("gii")) {\r
-                            akComponent[i] = loadGiftiXMLMesh( file.getAbsolutePath(), file.getName(), file.getParent());\r
-                       }\r
-                       else if (file.getName().endsWith("stl")) {\r
-                               \r
-                               try {\r
-                                       BufferedReader br = new BufferedReader(new FileReader(file));\r
-                                   String line = br.readLine();\r
-                                   if ( line.contains("solid")) {\r
-                                       akComponent[i] = loadSTLAsciiMesh( file, kImage);\r
-                                   } else {\r
-                                       akComponent[i] = loadSTLBinaryMesh( file, kImage);\r
-                                   }\r
-                               } catch ( IOException e ) {\r
-                                       e.printStackTrace();\r
-                               }\r
-                       }\r
-                       \r
-                       else if (file.getName().endsWith("ply")) {\r
-                            akComponent[i] = loadPlyAsciiMesh( file, kImage );\r
-                       }\r
-                        else if (file.getName().endsWith("txt")) {\r
-                            akComponent[i] = readAscii( file );\r
-                        }\r
-                    }\r
-                }\r
-                else\r
-                {\r
-                    ClodMesh kClod = loadCMesh(in, progress, i * 100 / iQuantity, iQuantity );\r
-                    kClod.TargetRecord(0);\r
-                    kClod.SelectLevelOfDetail();\r
-                    akComponent[i] = kClod;\r
-                }\r
-                if (akComponent[i] != null) \r
-                {\r
-                    for (int j = 0; j < akComponent[i].VBuffer.GetVertexQuantity(); j++) {\r
-\r
-                       if ( toFileCoords )\r
-                       {\r
-                               // The mesh files save the vertex positions as\r
-                               // pt.x*resX*direction[0] + startLocation\r
-                               // Return the loaded positions in file index coordinates:\r
-                               akComponent[i].VBuffer.SetPosition3( j, \r
-                                               (akComponent[i].VBuffer.GetPosition3fX(j) - startLocation[0]) / (direction[0] * resols[0]),\r
-                                               (akComponent[i].VBuffer.GetPosition3fY(j) - startLocation[1]) / (direction[1] * resols[1]),\r
-                                               (akComponent[i].VBuffer.GetPosition3fZ(j) - startLocation[2]) / (direction[2] * resols[2]));\r
-                       }\r
-                       else\r
-                       {\r
-                               //System.err.println( akComponent[i].VBuffer.GetPosition3( j ) ); \r
-                               // The mesh files save the verticies as\r
-                               // pt.x*resX*direction[0] + startLocation\r
-                               // The loaded vertices go from -1 to 1\r
-                               // The loaded vertex is at (2.0f*pt.x*xRes - (xDim-1)*xRes)/((dim-1)*res)max\r
-                               akComponent[i].VBuffer.SetPosition3( j, \r
-                                               ((2.0f * (akComponent[i].VBuffer.GetPosition3fX(j) - startLocation[0]) / direction[0]) -\r
-                                                               xBox) / (2.0f*maxBox),\r
-                                                               ((2.0f * (akComponent[i].VBuffer.GetPosition3fY(j) - startLocation[1]) / direction[1]) -\r
-                                                                               yBox) / (2.0f*maxBox),\r
-                                                                               ((2.0f * (akComponent[i].VBuffer.GetPosition3fZ(j) - startLocation[2]) / direction[2]) -\r
-                                                                                               zBox) / (2.0f*maxBox) );\r
-                       }\r
-                    }\r
-                    akComponent[i].SetName( file.getName() );\r
-                }\r
-                if (akComponent[i] == null) {\r
-                    MipavUtil.displayError("Error while reading in triangle mesh.");\r
-                    return null;\r
-                }\r
-            }\r
-        } catch (IOException e) {\r
-            return null;\r
-        }\r
-\r
-        progress.dispose();\r
-        akComponent[0].UpdateMS();\r
-        return akComponent[0];\r
-    }\r
+       /**\r
+        * Load a triangle mesh from the specified file and assign to it the\r
+        * MaterialState.\r
+        * \r
+        * @param kImage\r
+        *            ModelImage displayed in the SurfaceRender class\r
+        * @param file\r
+        *            The triangle mesh file to load.\r
+        * @param kMaterial\r
+        *            The Material for the surface.\r
+        * @return TriMesh\r
+        */\r
+       public static TriMesh readSurface(ModelImage kImage, File file, MaterialState kMaterial) {\r
+               return readSurface(kImage, file, kMaterial, false);\r
+       }\r
+\r
+       /**\r
+        * Load a triangle mesh from the specified file and assign to it the\r
+        * MaterialState.\r
+        * \r
+        * @param kImage\r
+        *            ModelImage displayed in the SurfaceRender class\r
+        * @param file\r
+        *            The triangle mesh file to load.\r
+        * @param kMaterial\r
+        *            The Material for the surface.\r
+        * @return TriMesh\r
+        */\r
+       public static TriMesh readSurface(ModelImage kImage, File file, MaterialState kMaterial, boolean toFileCoords) {\r
+               int iType = 0, iQuantity = 0;\r
+               boolean isSur = true;\r
+               int[] extents = kImage.getExtents();\r
+               int xDim = extents[0];\r
+               int yDim = extents[1];\r
+               int zDim = extents[2];\r
+\r
+               float[] resols = kImage.getFileInfo()[0].getResolutions();\r
+               float xBox = (xDim - 1) * resols[0];\r
+               float yBox = (yDim - 1) * resols[1];\r
+               float zBox = (zDim - 1) * resols[2];\r
+               float maxBox = Math.max(xBox, Math.max(yBox, zBox));\r
+\r
+               FileSurfaceRefXML_WM kSurfaceXML;\r
+               FileInfoSurfaceRefXML kFileInfo = null;\r
+               RandomAccessFile in = null;\r
+\r
+               if (file.getName().endsWith("sur")) {\r
+                       try {\r
+                               in = new RandomAccessFile(file, "r");\r
+                               iType = in.readInt();\r
+                               iQuantity = in.readInt();\r
+                               isSur = true;\r
+                       } catch (IOException e) {\r
+                               return null;\r
+                       }\r
+               } else if (file.getName().endsWith("xml")) {\r
+                       kSurfaceXML = new FileSurfaceRefXML_WM(file.getName(), file.getParent());\r
+                       kFileInfo = kSurfaceXML.readSurfaceXML(file.getName(), file.getParent());\r
+\r
+                       file = new File(file.getParent() + File.separatorChar + kFileInfo.getSurfaceFileName());\r
+                       try {\r
+                               in = new RandomAccessFile(file, "r");\r
+                               iType = in.readInt();\r
+                               iQuantity = in.readInt();\r
+                               isSur = true;\r
+                       } catch (IOException e) {\r
+                               return null;\r
+                       }\r
+               } else if (file.getName().endsWith("wrl")) {\r
+\r
+                       try {\r
+                               in = new RandomAccessFile(file, "r");\r
+                               iType = 0;\r
+                               iQuantity = parseVRMLMesh(in);\r
+                               in.seek(0);\r
+                               isSur = false;\r
+                       } catch (NoSuchElementException e) {\r
+                               MipavUtil.displayError("Only load VRML file specifically written by MIPAV! ");\r
+\r
+                               return null;\r
+                       } catch (IOException e) {\r
+                               return null;\r
+                       }\r
+               } else if (file.getName().endsWith("stl")) {\r
+                       iType = 0;\r
+                       iQuantity = 1;\r
+                       isSur = false;\r
+               } else if (file.getName().endsWith("ply")) {\r
+                       iType = 0;\r
+                       iQuantity = 1;\r
+                       isSur = false;\r
+               } else if (file.getName().endsWith("gii")) {\r
+                       try {\r
+                               in = new RandomAccessFile(file, "r");\r
+                               iType = 0;\r
+                               iQuantity = 1;\r
+                               isSur = false;\r
+                       } catch (IOException e) {\r
+                               return null;\r
+                       }\r
+               } else {\r
+                       // has to be vtk legacy or vtk xml\r
+                       try {\r
+                               in = new RandomAccessFile(file, "r");\r
+                               iType = 0;\r
+                               iQuantity = 1;\r
+                               in.seek(0);\r
+                               // not sure what this flag means\r
+                               isSur = false;\r
+                       } catch (IOException e) {\r
+                               return null;\r
+                       }\r
+               }\r
+\r
+               TriMesh[] akComponent = new TriMesh[iQuantity];\r
+               ViewJProgressBar progress = new ViewJProgressBar("Loading surface", "Loading surface", 0, 100, false, null,\r
+                               null);\r
+               progress.setVisible(true);\r
+\r
+               try {\r
+                       // meshes are type TriangleMesh\r
+                       for (int i = 0; i < iQuantity; i++) {\r
+\r
+                               float[] startLocation = kImage.getFileInfo(0).getOrigin();\r
+                               int[] aiModelDirection = MipavCoordinateSystems.getModelDirections(kImage);\r
+                               float[] direction = new float[] { aiModelDirection[0], aiModelDirection[1], aiModelDirection[2] };\r
+                               float[] box = new float[] { 0f, 0f, 0f };\r
+                               if (iType == 0) {\r
+\r
+                                       if (isSur == true) {\r
+                                               akComponent[i] = loadTMesh(in, progress, i * 100 / iQuantity, iQuantity, true, kMaterial,\r
+                                                               startLocation, direction, box);\r
+                                               // xBox = box[0];\r
+                                               // yBox = box[1];\r
+                                               // zBox = box[2];\r
+                                               // maxBox = Math.max(xBox, Math.max(yBox, zBox));\r
+                                       } else {\r
+                                               if (file.getName().endsWith("wrl")) {\r
+                                                       akComponent[i] = loadVRMLMesh(in, progress, i * 100 / iQuantity, iQuantity, (i == 0),\r
+                                                                       startLocation, direction, box);\r
+                                               } else if (file.getName().endsWith("vtk")) {\r
+                                                       // vtk legacy\r
+                                                       akComponent[i] = loadVTKLegacyMesh(in, progress, i * 100 / iQuantity, iQuantity,\r
+                                                                       file.getName());\r
+                                               } else if (file.getName().endsWith("vtp")) {\r
+                                                       // vtk xml\r
+                                                       akComponent[i] = loadVTKXMLMesh(file.getAbsolutePath(), file.getName(), file.getParent());\r
+                                               } else if (file.getName().endsWith("gii")) {\r
+                                                       akComponent[i] = loadGiftiXMLMesh(file.getAbsolutePath(), file.getName(), file.getParent());\r
+                                               } else if (file.getName().endsWith("stl")) {\r
+\r
+                                                       try {\r
+                                                               BufferedReader br = new BufferedReader(new FileReader(file));\r
+                                                               String line = br.readLine();\r
+                                                               if (line.contains("solid")) {\r
+                                                                       akComponent[i] = loadSTLAsciiMesh(file, kImage);\r
+                                                               } else {\r
+                                                                       akComponent[i] = loadSTLBinaryMesh(file, kImage);\r
+                                                               }\r
+                                                       } catch (IOException e) {\r
+                                                               e.printStackTrace();\r
+                                                       }\r
+                                               }\r
+\r
+                                               else if (file.getName().endsWith("ply")) {\r
+                                                       akComponent[i] = loadPlyAsciiMesh(file, kImage);\r
+                                               } else if (file.getName().endsWith("txt")) {\r
+                                                       akComponent[i] = readAscii(file);\r
+                                               }\r
+                                       }\r
+                               } else {\r
+                                       ClodMesh kClod = loadCMesh(in, progress, i * 100 / iQuantity, iQuantity);\r
+                                       kClod.TargetRecord(0);\r
+                                       kClod.SelectLevelOfDetail();\r
+                                       akComponent[i] = kClod;\r
+                               }\r
+                               if (akComponent[i] != null) {\r
+                                       for (int j = 0; j < akComponent[i].VBuffer.GetVertexQuantity(); j++) {\r
+\r
+                                               if (toFileCoords) {\r
+                                                       // The mesh files save the vertex positions as\r
+                                                       // pt.x*resX*direction[0] + startLocation\r
+                                                       // Return the loaded positions in file index coordinates:\r
+                                                       akComponent[i].VBuffer.SetPosition3(j,\r
+                                                                       (akComponent[i].VBuffer.GetPosition3fX(j) - startLocation[0])\r
+                                                                                       / (direction[0] * resols[0]),\r
+                                                                       (akComponent[i].VBuffer.GetPosition3fY(j) - startLocation[1])\r
+                                                                                       / (direction[1] * resols[1]),\r
+                                                                       (akComponent[i].VBuffer.GetPosition3fZ(j) - startLocation[2])\r
+                                                                                       / (direction[2] * resols[2]));\r
+                                               } else {\r
+                                                       // System.err.println( akComponent[i].VBuffer.GetPosition3( j ) );\r
+                                                       // The mesh files save the verticies as\r
+                                                       // pt.x*resX*direction[0] + startLocation\r
+                                                       // The loaded vertices go from -1 to 1\r
+                                                       // The loaded vertex is at (2.0f*pt.x*xRes - (xDim-1)*xRes)/((dim-1)*res)max\r
+                                                       akComponent[i].VBuffer.SetPosition3(j,\r
+                                                                       ((2.0f * (akComponent[i].VBuffer.GetPosition3fX(j) - startLocation[0])\r
+                                                                                       / direction[0]) - xBox) / (2.0f * maxBox),\r
+                                                                       ((2.0f * (akComponent[i].VBuffer.GetPosition3fY(j) - startLocation[1])\r
+                                                                                       / direction[1]) - yBox) / (2.0f * maxBox),\r
+                                                                       ((2.0f * (akComponent[i].VBuffer.GetPosition3fZ(j) - startLocation[2])\r
+                                                                                       / direction[2]) - zBox) / (2.0f * maxBox));\r
+                                               }\r
+                                       }\r
+                                       akComponent[i].SetName(file.getName());\r
+                               }\r
+                               if (akComponent[i] == null) {\r
+                                       MipavUtil.displayError("Error while reading in triangle mesh.");\r
+                                       return null;\r
+                               }\r
+                       }\r
+               } catch (IOException e) {\r
+                       return null;\r
+               }\r
+\r
+               progress.dispose();\r
+               akComponent[0].UpdateMS();\r
+               return akComponent[0];\r
+       }\r
+\r
+       /**\r
+        * Save the TriMesh as an ascii text file.\r
+        * \r
+        * @param kName\r
+        *            file name\r
+        * @param kMesh\r
+        *            TriMesh\r
+        * @throws IOException\r
+        *             I/O exception\r
+        */\r
+       private static void saveAsTextFile(String kName, TriMesh kMesh) throws IOException {\r
+\r
+               PrintWriter kOut = new PrintWriter(new FileWriter(kName));\r
+\r
+               kOut.println('0');\r
+               kOut.println(1);\r
+\r
+               printAscii(kOut, kMesh);\r
+\r
+               kOut.close();\r
+       }\r
+\r
+       /**\r
+        * Saves the triangle mesh in VRML97 (VRML 2.0) format (text format).\r
+        *\r
+        * @param kName\r
+        *            the name of file to which the triangle mesh is saved\r
+        * @param kMesh\r
+        *            TriMesh to save.\r
+        * @param kVBuffer\r
+        *            TriMesh VertexBuffer\r
+        * @param flip\r
+        *            if the y and z axes should be flipped - true in extract and in\r
+        *            save of JDialogSurface To have proper orientations in surface file\r
+        *            if flip is true flip y and z on reading. param direction 1 or -1\r
+        *            for each axis param startLocation param box (dim-1)*resolution\r
+        * \r
+        * @param direction\r
+        *            3D mesh orientation\r
+        * @param startLocation\r
+        *            3D mesh location\r
+        * @param box\r
+        *            3D mesh bounding box\r
+        * @throws IOException\r
+        *             if the specified file could not be opened for writing\r
+        */\r
+       private static void saveAsVRML(String kName, TriMesh kMesh, VertexBuffer kVBuffer, boolean flip, int[] direction,\r
+                       float[] startLocation, float[] box) throws IOException {\r
+               PrintWriter kOut = new PrintWriter(new FileWriter(kName));\r
+\r
+               kOut.println("#VRML V2.0 utf8");\r
+               kOut.println("#MIPAV");\r
+               kOut.println("#Number of shapes = " + 1);\r
+               saveAsVRML(kOut, kMesh, kVBuffer, flip, direction, startLocation, box);\r
+               kOut.close();\r
+       }\r
+\r
+       /**\r
+        * Save the TriMesh in VTK legacy format.\r
+        * \r
+        * @param kName\r
+        *            file name\r
+        * @param kMesh\r
+        *            TriMesh\r
+        * @throws IOException\r
+        *             I/O exception\r
+        */\r
+       private static void saveAsVTKLegacy(String kName, TriMesh kMesh) throws IOException {\r
+               PrintWriter kOut = new PrintWriter(new FileWriter(kName));\r
+               int pointCount = kMesh.VBuffer.GetVertexQuantity();\r
+               int indexCount = kMesh.IBuffer.GetIndexQuantity();\r
+               kOut.println("# vtk DataFile Version 2.0");\r
+               kOut.println(kMesh.GetName());\r
+               kOut.println("ASCII");\r
+               kOut.println("DATASET POLYDATA");\r
+               kOut.println("POINTS " + pointCount + " float");\r
+               Vector3f p = new Vector3f();\r
+               String tmp;\r
+               for (int i = 0; i < pointCount; i++) {\r
+                       kMesh.VBuffer.GetPosition3(i, p);\r
+                       tmp = String.format("%.5f %.5f %.5f\n", p.X, p.Y, p.Z);\r
+                       kOut.print(tmp);\r
+               }\r
+               kOut.println("POLYGONS " + indexCount / 3 + " " + (4 * indexCount / 3));\r
+               int[] aiIndex = kMesh.IBuffer.GetData();\r
+               for (int i = 0; i < indexCount; i += 3) {\r
+                       kOut.println(3 + " " + aiIndex[i] + " " + aiIndex[i + 1] + " " + aiIndex[i + 2]);\r
+               }\r
+               kOut.close();\r
+       }\r
+\r
+       /**\r
+        * Save the TriMesh in VTK format.\r
+        * \r
+        * @param fileName\r
+        *            file name\r
+        * @param kMesh\r
+        *            TriMesh\r
+        */\r
+       private static void saveAsVTKXML(String fileName, TriMesh kMesh) {\r
+               try {\r
+                       FileSurfaceVTKXML_WM surfaceVTKXML = new FileSurfaceVTKXML_WM(null, null);\r
+                       surfaceVTKXML.writeXMLsurface(fileName, kMesh);\r
+               } catch (IOException kError) {\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Save the TriMesh in Gifti format.\r
+        * \r
+        * @param fileName\r
+        *            file name\r
+        * @param kMesh\r
+        *            TriMesh\r
+        */\r
+       private static void saveAsGiftiXML(String fileName, TriMesh kMesh) {\r
+               try {\r
+                       FileSurfaceGiftiXML_WM surfaceGiftiXML = new FileSurfaceGiftiXML_WM(null, null);\r
+                       surfaceGiftiXML.writeXMLsurface(fileName, kMesh);\r
+               } catch (IOException kError) {\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Support for saving the collapse records to a binary file.\r
+        * \r
+        * @param kOut\r
+        *            the file to which the records are saved\r
+        * @param kRecord\r
+        *            CollapseRecord to save.\r
+        * @exception IOException\r
+        *                if the there is an error writing to the file\r
+        */\r
+       private static void saveCollapseRecord(RandomAccessFile kOut, CollapseRecord kRecord) throws IOException {\r
+               kOut.writeInt(kRecord.VKeep);\r
+               kOut.writeInt(kRecord.VThrow);\r
+               kOut.writeInt(kRecord.VQuantity);\r
+               kOut.writeInt(kRecord.TQuantity);\r
+               kOut.writeInt(kRecord.IQuantity);\r
+\r
+               byte[] bufferInt = new byte[kRecord.IQuantity * 4];\r
+               int tmpInt;\r
+               for (int i = 0, index = 0; i < kRecord.IQuantity; i++) {\r
+                       tmpInt = kRecord.Index[i];\r
+                       bufferInt[index++] = (byte) (tmpInt >>> 24);\r
+                       bufferInt[index++] = (byte) (tmpInt >>> 16);\r
+                       bufferInt[index++] = (byte) (tmpInt >>> 8);\r
+                       bufferInt[index++] = (byte) (tmpInt & 0xff);\r
+               }\r
+               kOut.write(bufferInt);\r
+       }\r
+\r
+       /**\r
+        * Saves a single level of detail to a mesh file. Opens a file dialog to get the\r
+        * output file name from the user.\r
+        *\r
+        * @param kImage\r
+        *            ModelImage displayed in the SurfaceRender object\r
+        * @param isSur\r
+        *            true if .sur file, otherwise .wrl file\r
+        * @param kMesh\r
+        *            TruNesg\r
+        */\r
+       private static void saveSingleMesh(ModelImage kImage, boolean isSur, TriMesh kMesh) {\r
+               String name = getFileName(false);\r
+\r
+               if (name == null) {\r
+                       return;\r
+               }\r
+\r
+               int i = name.lastIndexOf('.');\r
+\r
+               if ((i > 0) && (i < (name.length() - 1))) {\r
+                       String extension = name.substring(i + 1).toLowerCase();\r
+\r
+                       if (isSur && !extension.equals("sur")) {\r
+                               MipavUtil.displayError("Extension must be .sur");\r
+\r
+                               return;\r
+                       } else if (!isSur && !extension.equals("wrl")) {\r
+                               MipavUtil.displayError("Extension must be .wrl");\r
+\r
+                               return;\r
+                       }\r
+               } else if (isSur) {\r
+                       name = name + ".sur";\r
+               } else {\r
+                       name = name + ".wrl";\r
+               }\r
+\r
+               saveSingleMesh(name, kImage, isSur, kMesh);\r
+       }\r
+\r
+       /**\r
+        * Saves a single level of detail to a mesh file. The file name is passed as a\r
+        * parameter.\r
+        *\r
+        * @param name\r
+        *            the file name\r
+        * @param kImage\r
+        *            ModelImage displayed in the SurfaceRender object\r
+        * @param isSur\r
+        *            true if .sur file, otherwise .wrl file\r
+        * @param kMesh\r
+        *            TriMesh\r
+        */\r
+       private static void saveSingleMesh(String name, ModelImage kImage, boolean isSur, TriMesh kMesh) {\r
+               if (name != null) {\r
+\r
+                       try {\r
+                               float[] startLocation = kImage.getFileInfo(0).getOrigin();\r
+                               int[] extents = kImage.getExtents();\r
+                               int xDim = extents[0];\r
+                               int yDim = extents[1];\r
+                               int zDim = extents[2];\r
+\r
+                               float[] resols = kImage.getFileInfo()[0].getResolutions();\r
+                               float xBox = (xDim - 1) * resols[0];\r
+                               float yBox = (yDim - 1) * resols[1];\r
+                               float zBox = (zDim - 1) * resols[2];\r
+                               float maxBox = Math.max(xBox, Math.max(yBox, zBox));\r
+\r
+                               int[] direction = MipavCoordinateSystems.getModelDirections(kImage);\r
+                               float[] box = new float[] { xBox, yBox, zBox };\r
+\r
+                               // for (int i = 0; i < meshes.length; i++) {\r
+                               VertexBuffer kVBuffer = new VertexBuffer(kMesh.VBuffer);\r
+\r
+                               // The loaded vertices go from -(xDim-1)*resX/maxBox to (xDim-1)*resX/maxBox\r
+                               // The loaded vertex is at 2.0f*pt.x*resX - (xDim-1)*resX\r
+                               // The mesh files must save the verticies as\r
+                               // pt.x*resX*direction[0] + startLocation\r
+                               for (int j = 0; j < kVBuffer.GetVertexQuantity(); j++) {\r
+                                       kVBuffer.SetPosition3(j,\r
+                                                       ((((kMesh.VBuffer.GetPosition3fX(j) * 2.0f * maxBox) + xBox) / 2.0f) * direction[0])\r
+                                                                       + startLocation[0],\r
+                                                       ((((kMesh.VBuffer.GetPosition3fY(j) * 2.0f * maxBox) + yBox) / 2.0f) * direction[1])\r
+                                                                       + startLocation[1],\r
+                                                       ((((kMesh.VBuffer.GetPosition3fZ(j) * 2.0f * maxBox) + zBox) / 2.0f) * direction[2])\r
+                                                                       + startLocation[2]);\r
+\r
+                                       // flip y and z\r
+                                       // kVBuffer.SetPosition3( j, kVBuffer.GetPosition3fX(j),\r
+                                       // (2 * startLocation[1]) + (box[1] * direction[1]) -\r
+                                       // kVBuffer.GetPosition3fY(j),\r
+                                       // (2 * startLocation[2]) + (box[2] * direction[2]) - kVBuffer.GetPosition3fZ(j)\r
+                                       // );\r
+\r
+                                       if (isSur && (kImage.getMatrixHolder().containsType(TransMatrix.TRANSFORM_SCANNER_ANATOMICAL))) {\r
+\r
+                                               // Get the DICOM transform that describes the transformation from\r
+                                               // axial to this image orientation\r
+                                               TransMatrix dicomMatrix = kImage.getMatrix().clone();\r
+                                               float[] coord = new float[3];\r
+                                               float[] tCoord = new float[3];\r
+\r
+                                               // Change the voxel coordinate into millimeter space\r
+                                               coord[0] = (kVBuffer.GetPosition3fX(j) - startLocation[0]) / direction[0];\r
+                                               coord[1] = (kVBuffer.GetPosition3fY(j) - startLocation[1]) / direction[1];\r
+                                               coord[2] = (kVBuffer.GetPosition3fZ(j) - startLocation[2]) / direction[2];\r
+\r
+                                               // Convert the point to axial millimeter DICOM space\r
+                                               dicomMatrix.transform(coord, tCoord);\r
+\r
+                                               // Add in the DICOM origin\r
+                                               tCoord[0] = tCoord[0] + startLocation[0];\r
+                                               tCoord[1] = tCoord[1] + startLocation[1];\r
+                                               tCoord[2] = tCoord[2] + startLocation[2];\r
+                                               kVBuffer.SetPosition3(j, tCoord[0], tCoord[1], tCoord[2]);\r
+                                       }\r
+                               }\r
+                               // }\r
+\r
+                               if (isSur == true) {\r
+                                       // double[][] inverseDicomArray = null;\r
+                                       TransMatrix inverse_DicomMatrix = null;\r
+                                       if (kImage.getMatrixHolder().containsType(TransMatrix.TRANSFORM_SCANNER_ANATOMICAL)) {\r
+                                               inverse_DicomMatrix = kImage.getMatrix().clone();\r
+                                               inverse_DicomMatrix.Inverse();\r
+                                               // inverseDicomArray = inverseDicomMatrix.getMatrix();\r
+                                       }\r
+\r
+                                       saveSur(name, kMesh, 0, kVBuffer, true, direction, startLocation, box, inverse_DicomMatrix);\r
+                               } else {\r
+                                       saveAsVRML(name, kMesh, kVBuffer, true, direction, startLocation, box);\r
+                               }\r
+                       } catch (IOException error) {\r
+                               MipavUtil.displayError("Error while trying to save single mesh");\r
+                       }\r
+               }\r