All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.mihosoft.vrl.v3d.ext.imagej.STLLoader Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version


package eu.mihosoft.vrl.v3d.ext.imagej;

/**
 * Fork of
 * https://github.com/fiji/fiji/blob/master/src-plugins/3D_Viewer/src/main/java/customnode/STLLoader.java
 * 
 * TODO: license unclear
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.ArrayList;

import javax.vecmath.Point3f;

// TODO: Auto-generated Javadoc
/**
 * The Class STLLoader.
 */
public class STLLoader {

//        /**
//         * Load the specified stl file and returns the result as a hash map, mapping
//         * the object names to the corresponding CustomMesh objects.
//         */
//        public static Map load(String stlfile)
//                        throws IOException {
//                STLLoader sl = new STLLoader();
//                try {
//                        sl.parse(stlfile);
//                } catch (RuntimeException e) {
//                        System.out.println("error reading " + sl.name);
//                        throw e;
//                }
//                return sl.meshes;
//        }
//
/**
 * Instantiates a new STL loader.
 */
//        private HashMap meshes;
    public STLLoader() {
    }

    /** The line. */
    String line;
    
    /** The in. */
    BufferedReader in;

    /** The vertices. */
    // attributes of the currently read mesh
    private ArrayList vertices = new ArrayList<>();
    
    /** The normal. */
    private Point3f normal = new Point3f(0.0f, 0.0f, 0.0f); //to be used for file checking
    
    /** The fis. */
    private FileInputStream fis;
    
    /** The triangles. */
    private int triangles;
//    private DecimalFormat decimalFormat = new DecimalFormat("0.0E0");



    /**
 * Parses the.
 *
 * @param f the f
 * @return the array list
 * @throws IOException Signals that an I/O exception has occurred.
 */
public ArrayList parse(File f) throws IOException {
        vertices.clear();

                // determine if this is a binary or ASCII STL
        // and send to the appropriate parsing method
        // Hypothesis 1: this is an ASCII STL
        try { BufferedReader br = new BufferedReader(new FileReader(f));
	        String line = br.readLine();
	        String[] words = line.trim().split("\\s+");
	        if (line.indexOf('\0') < 0 && words[0].equalsIgnoreCase("solid")) {
	            //System.out.println("Looks like an ASCII STL");
	            parseAscii(f);
	            br.close();
	            return vertices;
	        }
	        br.close();}catch(java.lang.NullPointerException ex) {}// the split cna fail on binary stls
        // Hypothesis 2: this is a binary STL
        FileInputStream fs = new FileInputStream(f);

                // bytes 80, 81, 82 and 83 form a little-endian int
        // that contains the number of triangles
        byte[] buffer = new byte[84];
        fs.read(buffer, 0, 84);
        fs.close();
        triangles = (int) (((buffer[83] & 0xff) << 24)
                | ((buffer[82] & 0xff) << 16) | ((buffer[81] & 0xff) << 8) | (buffer[80] & 0xff));
        if (((f.length() - 84) / 50) == triangles) {
            //System.out.println("Looks like a binary STL");
            parseBinary(f);
            return vertices;
        }
        System.err.println("File is not a valid STL");
        
        return vertices;
    }

    /**
     * Parses the ascii.
     *
     * @param f the f
     */
    private void parseAscii(File f) {
        try {
            in = new BufferedReader(new FileReader(f));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        vertices = new ArrayList<>();
        try {
            while ((line = in.readLine()) != null) {
                String[] numbers = line.trim().split("\\s+");
                if (numbers[0].equals("vertex")) {
                    float x = parseFloat(numbers[1]);
                    float y = parseFloat(numbers[2]);
                    float z = parseFloat(numbers[3]);
                    Point3f vertex = new Point3f(x, y, z);
                    vertices.add(vertex);
                } else if (numbers[0].equals("facet") && numbers[1].equals("normal")) {
                    normal.x = parseFloat(numbers[2]);
                    normal.y = parseFloat(numbers[3]);
                    normal.z = parseFloat(numbers[4]);
                }
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    /**
     * Parses the binary.
     *
     * @param f the f
     */
    private void parseBinary(File f) {
        vertices = new ArrayList();
        try {
            fis = new FileInputStream(f);
            for (int h = 0; h < 84; h++) {
                fis.read();// skip the header bytes
            }
            for (int t = 0; t < triangles; t++) {
                byte[] tri = new byte[50];
                for (int tb = 0; tb < 50; tb++) {
                    tri[tb] = (byte) fis.read();
                }
                normal.x = leBytesToFloat(tri[0], tri[1], tri[2], tri[3]);
                normal.y = leBytesToFloat(tri[4], tri[5], tri[6], tri[7]);
                normal.z = leBytesToFloat(tri[8], tri[9], tri[10], tri[11]);
                for (int i = 0; i < 3; i++) {
                    final int j = i * 12 + 12;
                    float px = leBytesToFloat(tri[j], tri[j + 1], tri[j + 2],
                            tri[j + 3]);
                    float py = leBytesToFloat(tri[j + 4], tri[j + 5],
                            tri[j + 6], tri[j + 7]);
                    float pz = leBytesToFloat(tri[j + 8], tri[j + 9],
                            tri[j + 10], tri[j + 11]);
                    Point3f p = new Point3f(px, py, pz);
                    vertices.add(p);
                }
            }
            fis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

//    private float parseFloat(String string) throws ParseException {
//        //E+05 -> E05, e+05 -> E05
//        string = string.replaceFirst("[eE]\\+", "E");
//        //E-05 -> E-05, e-05 -> E-05
//        string = string.replaceFirst("e\\-", "E-");
//        return decimalFormat.parse(string).floatValue();
//    }
    
    /**
 * Parses the float.
 *
 * @param string the string
 * @return the float
 * @throws ParseException the parse exception
 */
private float parseFloat(String string) throws ParseException {

        return Float.parseFloat(string);
    }

    /**
     * Le bytes to float.
     *
     * @param b0 the b0
     * @param b1 the b1
     * @param b2 the b2
     * @param b3 the b3
     * @return the float
     */
    private float leBytesToFloat(byte b0, byte b1, byte b2, byte b3) {
        return Float.intBitsToFloat((((b3 & 0xff) << 24) | ((b2 & 0xff) << 16)
                | ((b1 & 0xff) << 8) | (b0 & 0xff)));
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy