Loading src/main/java/com/elphel/imagej/tileprocessor/lwoc/LwocLeaf.java +3 −2 Original line number Diff line number Diff line Loading @@ -24,11 +24,12 @@ package com.elphel.imagej.tileprocessor.lwoc; import java.io.Serializable; import java.util.ArrayList; public class LwocLeaf { public class LwocLeaf implements Serializable{ private static final long serialVersionUID = 1L; ArrayList <LwocMesh> meshes; transient ArrayList <LwocMesh> meshes; // will be rebuilt with LwocOctree.rebuildMeshLists() ArrayList <LwocMesh> mesh_centers; ArrayList <LwocScene> scenes; public LwocLeaf() { Loading src/main/java/com/elphel/imagej/tileprocessor/lwoc/LwocMesh.java +6 −6 Original line number Diff line number Diff line Loading @@ -24,13 +24,13 @@ package com.elphel.imagej.tileprocessor.lwoc; import java.util.ArrayList; import java.io.Serializable; import java.util.concurrent.atomic.AtomicInteger; public class LwocMesh { public class LwocMesh implements Serializable { private static final long serialVersionUID = 1L; static AtomicInteger MESH_ID = new AtomicInteger(); static ArrayList<LwocMesh> LWOC_MESHES; // static ArrayList<LwocMesh> LWOC_MESHES; int id; // assign unique ID String stimestamp; // mesh is always referenced to a single scene double [] world_xyz; // world coordinates of the center Loading @@ -38,7 +38,7 @@ public class LwocMesh { public static void resetMeshes() { MESH_ID.set(0); LWOC_MESHES = new ArrayList<LwocMesh>(); // LWOC_MESHES = new ArrayList<LwocMesh>(); } // maybe use mesh properties instead of id? public boolean equals (LwocMesh other_mesh) { Loading @@ -49,7 +49,7 @@ public class LwocMesh { ) { this.stimestamp = stimestamp; id = MESH_ID.getAndIncrement(); LWOC_MESHES.add(this); // LWOC_MESHES.add(this); } public double [] getCenter() { Loading src/main/java/com/elphel/imagej/tileprocessor/lwoc/LwocOctree.java +96 −24 Original line number Diff line number Diff line Loading @@ -24,11 +24,17 @@ package com.elphel.imagej.tileprocessor.lwoc; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import com.elphel.imagej.common.MultiThreading; public class LwocOctree { public class LwocOctree implements Serializable { private static final long serialVersionUID = 1L; public static final int NUM_CHILDREN = 8; public static double MIN_HSIZE = 0.3; // meter - do not subdivide more Loading @@ -36,7 +42,7 @@ public class LwocOctree { public static int MAX_MESH_CENTERS = 10; // maximal number of meshes in a leaf; public static int MAX_CAMERAS = 10; // maximal number of cameras in a leaf; public static LwocOctree lwoc_root = null; static ArrayList<LwocOctree> LWOK_OCTREE = new ArrayList<LwocOctree>(); // static ArrayList<LwocOctree> LWOK_OCTREE = new ArrayList<LwocOctree>(); static AtomicInteger OCTREE_ID = new AtomicInteger(); static List<LwocScene> pendingScenes; // synchronized - add not-yet-added scenes pending growing world Loading @@ -51,6 +57,79 @@ public class LwocOctree { double [] center; // x-center, y-center, z-center double hsize; /** * Serialize and write world to an output stream * @param oos ObjectOutputStream to write to. * @throws IOException */ private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); if (parent == null) { // write static members oos.writeObject(MIN_HSIZE); oos.writeObject(MAX_MESH_CENTERS); oos.writeObject(MAX_CAMERAS); oos.writeObject(OCTREE_ID.get()); oos.writeObject(LwocMesh.MESH_ID.get()); } } /** * Read input stream and deserialize it to world octree structure. * @param ois ObjectInputStream to read from * @throws ClassNotFoundException * @throws IOException */ private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); if (parent == null) { // read static members MIN_HSIZE = (Double) ois.readObject(); MAX_MESH_CENTERS = (Integer) ois.readObject(); MAX_CAMERAS = (Integer) ois.readObject(); OCTREE_ID.set( (Integer) ois.readObject()); LwocMesh.MESH_ID.set((Integer) ois.readObject()); } } /** * * @param path */ public static void saveWorld(String path) { try { FileOutputStream fileOut = new FileOutputStream(path); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(lwoc_root); // will cause all world to be saved out.close(); fileOut.close(); System.out.printf("Serialized data is saved in "+path); } catch (IOException e) { e.printStackTrace(); } } public static void restoreWorld(String path) { try { FileInputStream fileIn = new FileInputStream(path); ObjectInputStream in = new ObjectInputStream(fileIn); lwoc_root = (LwocOctree) in.readObject(); in.close(); fileIn.close(); } catch (IOException e) { e.printStackTrace(); return; } catch (ClassNotFoundException c) { System.out.println(path+" not found"); c.printStackTrace(); return; } } public static void addPendingScene(LwocScene scene) { synchronized(pendingScenes) { pendingScenes.add(scene); Loading @@ -69,10 +148,6 @@ public class LwocOctree { } } // just for testing // List<List<LwocScene>> group = new ArrayList<List<LwocScene>>(4); /** * Initialize Octree data and set initial world node. It is possible to grow * world as needed later. Loading @@ -83,7 +158,7 @@ public class LwocOctree { LwocMesh.resetMeshes(); LwocScene.resetScenes(); resetPending(); LWOK_OCTREE = new ArrayList<LwocOctree>(); // LWOK_OCTREE = new ArrayList<LwocOctree>(); // Add a single leaf node lwoc_root = new LwocOctree(null, center, world_hsize); lwoc_root.leaf = new LwocLeaf(); Loading @@ -100,8 +175,6 @@ public class LwocOctree { pendingMeshes = new ArrayList<LwocMesh>(); pendingLeafNodes = new ArrayList<LwocOctree>(); } // use per-thread lists and then combine them avoiding synchronizations? //Pass list to any function that may grow it /** * Test if it is leaf node Loading Loading @@ -140,7 +213,7 @@ public class LwocOctree { id = OCTREE_ID.getAndIncrement(); this.parent = parent; this.hsize = hsize; LWOK_OCTREE.add(this); // LWOK_OCTREE.add(this); } /** Loading Loading @@ -267,7 +340,6 @@ public class LwocOctree { } } /** * Recursively (if needed) splits octree nodes to reduce number of scenes/cameras * and mesh centers below specified thresholds (limited by the minimal node size) Loading @@ -276,7 +348,7 @@ public class LwocOctree { * triggers node split. * @param max_cameras Maximasl number of scenes (camera positions) in a node. Larger * number triggers node split. * @param check_existed * @param check_existed Filter identical meshes or scenes from corresponding lists. */ public static void tendPendingLeafNodes( final double min_hsize, Loading Loading @@ -312,7 +384,16 @@ public class LwocOctree { MultiThreading.startAndJoin(threads); } // Split recursively until satisfied conditions /** * Split recursively the octree node (and its children if needed) to keep number of scenes and * mesh centers below thresholds. * @param min_hsize do not split nodes smaller than this (half size in each direction) even if * it has over-threshold number of scenes and/or mesh centers. * @param max_mesh_centers Split node if it has more mesh centers in its list. * @param max_cameras Split node if it has more scenes (camera positions) than this. * @param check_existed * @return */ public int splitNode( double min_hsize, int max_mesh_centers, Loading Loading @@ -395,14 +476,9 @@ public class LwocOctree { return num_added; } // not thread safe // grow world to include xyz (all 8 corners for a bounding box of as mesh /** * Grow the world to include specified point Will repeat growing twice (in each direction) * until the specified point gets inside. * until the specified point gets inside. Not thread safe, should run in single-thread mode * @param xyz The point to be included in the world. */ public static void growXYZ(double [] xyz) { Loading Loading @@ -442,6 +518,7 @@ public class LwocOctree { lwoc_root = new_root; } } /** * Test if the specified box intersects this node * @param xyz box center Loading Loading @@ -480,8 +557,6 @@ public class LwocOctree { return true; } /** * Test if the specified box completely fits in this node * @param xyz box center Loading Loading @@ -513,8 +588,6 @@ public class LwocOctree { LwocMesh mesh, boolean check_existed ) { // should in check before adding? // mesh.equals(mesh); double [] center = mesh.getCenter(); double [] dims = mesh.getDims(); // First - check that all 8 corners fit in the world Loading Loading @@ -555,7 +628,6 @@ public class LwocOctree { return true; } // recursive /** * Recursively add mesh to all leaf nodes that intersect with its bounding box. * Usually starts with lwoc_root. Loading Loading
src/main/java/com/elphel/imagej/tileprocessor/lwoc/LwocLeaf.java +3 −2 Original line number Diff line number Diff line Loading @@ -24,11 +24,12 @@ package com.elphel.imagej.tileprocessor.lwoc; import java.io.Serializable; import java.util.ArrayList; public class LwocLeaf { public class LwocLeaf implements Serializable{ private static final long serialVersionUID = 1L; ArrayList <LwocMesh> meshes; transient ArrayList <LwocMesh> meshes; // will be rebuilt with LwocOctree.rebuildMeshLists() ArrayList <LwocMesh> mesh_centers; ArrayList <LwocScene> scenes; public LwocLeaf() { Loading
src/main/java/com/elphel/imagej/tileprocessor/lwoc/LwocMesh.java +6 −6 Original line number Diff line number Diff line Loading @@ -24,13 +24,13 @@ package com.elphel.imagej.tileprocessor.lwoc; import java.util.ArrayList; import java.io.Serializable; import java.util.concurrent.atomic.AtomicInteger; public class LwocMesh { public class LwocMesh implements Serializable { private static final long serialVersionUID = 1L; static AtomicInteger MESH_ID = new AtomicInteger(); static ArrayList<LwocMesh> LWOC_MESHES; // static ArrayList<LwocMesh> LWOC_MESHES; int id; // assign unique ID String stimestamp; // mesh is always referenced to a single scene double [] world_xyz; // world coordinates of the center Loading @@ -38,7 +38,7 @@ public class LwocMesh { public static void resetMeshes() { MESH_ID.set(0); LWOC_MESHES = new ArrayList<LwocMesh>(); // LWOC_MESHES = new ArrayList<LwocMesh>(); } // maybe use mesh properties instead of id? public boolean equals (LwocMesh other_mesh) { Loading @@ -49,7 +49,7 @@ public class LwocMesh { ) { this.stimestamp = stimestamp; id = MESH_ID.getAndIncrement(); LWOC_MESHES.add(this); // LWOC_MESHES.add(this); } public double [] getCenter() { Loading
src/main/java/com/elphel/imagej/tileprocessor/lwoc/LwocOctree.java +96 −24 Original line number Diff line number Diff line Loading @@ -24,11 +24,17 @@ package com.elphel.imagej.tileprocessor.lwoc; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import com.elphel.imagej.common.MultiThreading; public class LwocOctree { public class LwocOctree implements Serializable { private static final long serialVersionUID = 1L; public static final int NUM_CHILDREN = 8; public static double MIN_HSIZE = 0.3; // meter - do not subdivide more Loading @@ -36,7 +42,7 @@ public class LwocOctree { public static int MAX_MESH_CENTERS = 10; // maximal number of meshes in a leaf; public static int MAX_CAMERAS = 10; // maximal number of cameras in a leaf; public static LwocOctree lwoc_root = null; static ArrayList<LwocOctree> LWOK_OCTREE = new ArrayList<LwocOctree>(); // static ArrayList<LwocOctree> LWOK_OCTREE = new ArrayList<LwocOctree>(); static AtomicInteger OCTREE_ID = new AtomicInteger(); static List<LwocScene> pendingScenes; // synchronized - add not-yet-added scenes pending growing world Loading @@ -51,6 +57,79 @@ public class LwocOctree { double [] center; // x-center, y-center, z-center double hsize; /** * Serialize and write world to an output stream * @param oos ObjectOutputStream to write to. * @throws IOException */ private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); if (parent == null) { // write static members oos.writeObject(MIN_HSIZE); oos.writeObject(MAX_MESH_CENTERS); oos.writeObject(MAX_CAMERAS); oos.writeObject(OCTREE_ID.get()); oos.writeObject(LwocMesh.MESH_ID.get()); } } /** * Read input stream and deserialize it to world octree structure. * @param ois ObjectInputStream to read from * @throws ClassNotFoundException * @throws IOException */ private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); if (parent == null) { // read static members MIN_HSIZE = (Double) ois.readObject(); MAX_MESH_CENTERS = (Integer) ois.readObject(); MAX_CAMERAS = (Integer) ois.readObject(); OCTREE_ID.set( (Integer) ois.readObject()); LwocMesh.MESH_ID.set((Integer) ois.readObject()); } } /** * * @param path */ public static void saveWorld(String path) { try { FileOutputStream fileOut = new FileOutputStream(path); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(lwoc_root); // will cause all world to be saved out.close(); fileOut.close(); System.out.printf("Serialized data is saved in "+path); } catch (IOException e) { e.printStackTrace(); } } public static void restoreWorld(String path) { try { FileInputStream fileIn = new FileInputStream(path); ObjectInputStream in = new ObjectInputStream(fileIn); lwoc_root = (LwocOctree) in.readObject(); in.close(); fileIn.close(); } catch (IOException e) { e.printStackTrace(); return; } catch (ClassNotFoundException c) { System.out.println(path+" not found"); c.printStackTrace(); return; } } public static void addPendingScene(LwocScene scene) { synchronized(pendingScenes) { pendingScenes.add(scene); Loading @@ -69,10 +148,6 @@ public class LwocOctree { } } // just for testing // List<List<LwocScene>> group = new ArrayList<List<LwocScene>>(4); /** * Initialize Octree data and set initial world node. It is possible to grow * world as needed later. Loading @@ -83,7 +158,7 @@ public class LwocOctree { LwocMesh.resetMeshes(); LwocScene.resetScenes(); resetPending(); LWOK_OCTREE = new ArrayList<LwocOctree>(); // LWOK_OCTREE = new ArrayList<LwocOctree>(); // Add a single leaf node lwoc_root = new LwocOctree(null, center, world_hsize); lwoc_root.leaf = new LwocLeaf(); Loading @@ -100,8 +175,6 @@ public class LwocOctree { pendingMeshes = new ArrayList<LwocMesh>(); pendingLeafNodes = new ArrayList<LwocOctree>(); } // use per-thread lists and then combine them avoiding synchronizations? //Pass list to any function that may grow it /** * Test if it is leaf node Loading Loading @@ -140,7 +213,7 @@ public class LwocOctree { id = OCTREE_ID.getAndIncrement(); this.parent = parent; this.hsize = hsize; LWOK_OCTREE.add(this); // LWOK_OCTREE.add(this); } /** Loading Loading @@ -267,7 +340,6 @@ public class LwocOctree { } } /** * Recursively (if needed) splits octree nodes to reduce number of scenes/cameras * and mesh centers below specified thresholds (limited by the minimal node size) Loading @@ -276,7 +348,7 @@ public class LwocOctree { * triggers node split. * @param max_cameras Maximasl number of scenes (camera positions) in a node. Larger * number triggers node split. * @param check_existed * @param check_existed Filter identical meshes or scenes from corresponding lists. */ public static void tendPendingLeafNodes( final double min_hsize, Loading Loading @@ -312,7 +384,16 @@ public class LwocOctree { MultiThreading.startAndJoin(threads); } // Split recursively until satisfied conditions /** * Split recursively the octree node (and its children if needed) to keep number of scenes and * mesh centers below thresholds. * @param min_hsize do not split nodes smaller than this (half size in each direction) even if * it has over-threshold number of scenes and/or mesh centers. * @param max_mesh_centers Split node if it has more mesh centers in its list. * @param max_cameras Split node if it has more scenes (camera positions) than this. * @param check_existed * @return */ public int splitNode( double min_hsize, int max_mesh_centers, Loading Loading @@ -395,14 +476,9 @@ public class LwocOctree { return num_added; } // not thread safe // grow world to include xyz (all 8 corners for a bounding box of as mesh /** * Grow the world to include specified point Will repeat growing twice (in each direction) * until the specified point gets inside. * until the specified point gets inside. Not thread safe, should run in single-thread mode * @param xyz The point to be included in the world. */ public static void growXYZ(double [] xyz) { Loading Loading @@ -442,6 +518,7 @@ public class LwocOctree { lwoc_root = new_root; } } /** * Test if the specified box intersects this node * @param xyz box center Loading Loading @@ -480,8 +557,6 @@ public class LwocOctree { return true; } /** * Test if the specified box completely fits in this node * @param xyz box center Loading Loading @@ -513,8 +588,6 @@ public class LwocOctree { LwocMesh mesh, boolean check_existed ) { // should in check before adding? // mesh.equals(mesh); double [] center = mesh.getCenter(); double [] dims = mesh.getDims(); // First - check that all 8 corners fit in the world Loading Loading @@ -555,7 +628,6 @@ public class LwocOctree { return true; } // recursive /** * Recursively add mesh to all leaf nodes that intersect with its bounding box. * Usually starts with lwoc_root. Loading