Commit 8176593d authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Refactored to have multiple world (needed when scenes can not be

matched)
parent 7e53b24d
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -25,11 +25,11 @@
package com.elphel.imagej.tileprocessor.lwoc;
package com.elphel.imagej.tileprocessor.lwoc;


import java.io.Serializable;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;
///import java.util.concurrent.atomic.AtomicInteger;


public class LwocMesh implements Serializable {
public class LwocMesh implements Serializable {
	private static final long  serialVersionUID = 1L;
	private static final long  serialVersionUID = 1L;
	static AtomicInteger       MESH_ID = new AtomicInteger();
///	static AtomicInteger       MESH_ID = new AtomicInteger();
//	static ArrayList<LwocMesh> LWOC_MESHES;
//	static ArrayList<LwocMesh> LWOC_MESHES;
	int                        id;         // assign unique ID
	int                        id;         // assign unique ID
	String                     stimestamp; // mesh is always referenced to a single scene
	String                     stimestamp; // mesh is always referenced to a single scene
@@ -37,7 +37,7 @@ public class LwocMesh implements Serializable {
	double []                  hdims_xyz;  // world bounding box half-dimensions along x,y,z
	double []                  hdims_xyz;  // world bounding box half-dimensions along x,y,z
	
	
	public static void resetMeshes() {
	public static void resetMeshes() {
		MESH_ID.set(0);
///		MESH_ID.set(0);
//		LWOC_MESHES = new ArrayList<LwocMesh>();
//		LWOC_MESHES = new ArrayList<LwocMesh>();
	}
	}
	// maybe use mesh properties instead of id?
	// maybe use mesh properties instead of id?
@@ -48,7 +48,7 @@ public class LwocMesh implements Serializable {
			String    stimestamp
			String    stimestamp
			) {
			) {
		this.stimestamp = stimestamp;
		this.stimestamp = stimestamp;
		id = MESH_ID.getAndIncrement();
///		id = MESH_ID.getAndIncrement();
//		LWOC_MESHES.add(this);
//		LWOC_MESHES.add(this);
	}
	}
	
	
+83 −147
Original line number Original line Diff line number Diff line
@@ -24,11 +24,11 @@


package com.elphel.imagej.tileprocessor.lwoc;
package com.elphel.imagej.tileprocessor.lwoc;


import java.io.FileInputStream;
//import java.io.FileInputStream;
import java.io.FileOutputStream;
//import java.io.FileOutputStream;
import java.io.IOException;
//import java.io.IOException;
import java.io.ObjectInputStream;
//import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
//import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
@@ -37,99 +37,21 @@ import com.elphel.imagej.common.MultiThreading;
public class LwocOctree implements Serializable {
public class LwocOctree implements Serializable {
	private static final long    serialVersionUID = 1L;
	private static final long    serialVersionUID = 1L;
	public static final int      NUM_CHILDREN =      8;
	public static final int      NUM_CHILDREN =      8;
	public static double         MIN_HSIZE =         0.3; // meter - do not subdivide more
//	static AtomicInteger         OCTREE_ID =        new AtomicInteger();
	// can not be used as intersecting meshes' bb will not decrease number after splitting
	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 AtomicInteger         OCTREE_ID =        new AtomicInteger();


	static List<LwocScene>       pendingScenes;   // synchronized - add not-yet-added scenes pending growing world 
	static List<LwocScene>       pendingScenes;   // synchronized - add not-yet-added scenes pending growing world 
	static List<LwocMesh>        pendingMeshes;   // synchronized - add not-yet-added meshes pending growing world
	static List<LwocMesh>        pendingMeshes;   // synchronized - add not-yet-added meshes pending growing world
	static List<LwocOctree>      pendingLeafNodes;// synchronized - leaf nodes needed to be split
	static List<LwocOctree>      pendingLeafNodes;// synchronized - leaf nodes needed to be split
	
	
	
//	static List<LwocWorld>       lwoc_worlds;   //  
	int                          id;         // assign unique ID
	int                          id;         // assign unique ID
	LwocOctree                   parent;
	transient LwocWorld          world; 	
	transient LwocOctree         parent;
	LwocOctree []                children;
	LwocOctree []                children;
	LwocLeaf                     leaf;       //
	LwocLeaf                     leaf;       //
	double []                    center;     // x-center, y-center, z-center
	double []                    center;     // x-center, y-center, z-center
	double                       hsize;
	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) {
	public static void addPendingScene(LwocScene scene) {
		synchronized(pendingScenes) {
		synchronized(pendingScenes) {
			pendingScenes.add(scene);
			pendingScenes.add(scene);
@@ -148,22 +70,6 @@ public class LwocOctree implements Serializable {
		}
		}
	}
	}


	/**
	 * Initialize Octree data and set initial world node. It is possible to grow
	 * world as needed later.
	 * @param center world center: x,y,z in meters. Usually {0,0,0}
	 * @param world_hsize Half linear dimension of the world
	 */
	public static void initOctree(double [] center, double world_hsize) {
		LwocMesh.resetMeshes();
		LwocScene.resetScenes();
		resetPending();
//		LWOK_OCTREE =    new ArrayList<LwocOctree>();
		// Add a single leaf node
		lwoc_root =      new LwocOctree(null, center, world_hsize);
		lwoc_root.leaf = new LwocLeaf();
	}
	
	/**
	/**
	 * Synchronized lists of pending scenes, meshes and nodes are used to delay modification of
	 * Synchronized lists of pending scenes, meshes and nodes are used to delay modification of
	 * the world octree and its elements from the multithreaded environment. These lists should
	 * the world octree and its elements from the multithreaded environment. These lists should
@@ -202,18 +108,19 @@ public class LwocOctree implements Serializable {
	
	
	/**
	/**
	 * LwocOctree constructor
	 * LwocOctree constructor
	 * @param lwocWorld World global parameters
	 * @param parent    Parent node
	 * @param parent    Parent node
	 * @param xyz position of the node center in meters
	 * @param xyz       Position of the node center in meters
	 * @param hsize     Node half size - each of the X,Y,Z coordinates of the internal 
	 * @param hsize     Node half size - each of the X,Y,Z coordinates of the internal 
	 *                  points are limited within +/-hsize from the node center
	 *                  points are limited within +/-hsize from the node center
	 */
	 */
    public LwocOctree (LwocOctree parent,
	public LwocOctree (
			LwocWorld  lwocWorld,
			LwocOctree parent,
			double []  xyz,
			double []  xyz,
			double     hsize) {
			double     hsize) {
    	id = OCTREE_ID.getAndIncrement();
    	this.parent = parent;
    	this.parent = parent;
    	this.hsize =  hsize;
    	this.hsize =  hsize;
//    	LWOK_OCTREE.add(this);
    }
    }
    
    
    /**
    /**
@@ -222,14 +129,15 @@ public class LwocOctree implements Serializable {
     * @return Octree node that includes the point or null if the point
     * @return Octree node that includes the point or null if the point
     *         is outside the root node (the whole world)
     *         is outside the root node (the whole world)
     */
     */
    public static LwocOctree getLeafNode( // if null - needs growing world
	//FIXME: obey border (on the edges of max hsize of the root) nodes
    public LwocOctree getLeafNode( // if null - needs growing world
    		double [] xyz) { // thread safe
    		double [] xyz) { // thread safe
    	if (!lwoc_root.contains(xyz)) return null; // needs growing world
    	if (!world.getLwocRoot().contains(xyz)) return null; // needs growing world
    	LwocOctree node = lwoc_root;
    	LwocOctree node = world.getLwocRoot();
    	while (lwoc_root.children != null) {
    	while (world.getLwocRoot().children != null) {
    		int indx = 0;
    		int indx = 0;
    		for (int dm = 0; dm < 3; dm++) {
    		for (int dm = 0; dm < 3; dm++) {
    			if (xyz[dm] >= lwoc_root.center[dm] ) {
    			if (xyz[dm] >= world.getLwocRoot().center[dm] ) {
    				indx += 1 << dm;
    				indx += 1 << dm;
    			}
    			}
    		}
    		}
@@ -245,7 +153,7 @@ public class LwocOctree implements Serializable {
     * @param check_existed - do not add duplicate scenes and nodes
     * @param check_existed - do not add duplicate scenes and nodes
     * @return An octree node where scene is added or null if the world needs growing
     * @return An octree node where scene is added or null if the world needs growing
     */
     */
    public static LwocOctree addScene(
    public LwocOctree addScene(
    		LwocScene             scene,
    		LwocScene             scene,
    		boolean               check_existed
    		boolean               check_existed
    		) {// returns null and adds to pendingScenes if needs growing
    		) {// returns null and adds to pendingScenes if needs growing
@@ -259,8 +167,8 @@ public class LwocOctree implements Serializable {
    	} else {
    	} else {
    		node.leaf.addScene(scene,check_existed);
    		node.leaf.addScene(scene,check_existed);
    		// Check if leaf node requires splitting
    		// Check if leaf node requires splitting
    		if (node.leaf.getScenes().size() > MAX_CAMERAS) {
    		if (node.leaf.getScenes().size() > world.getMaxCameras()) {
    			if (node.hsize > MIN_HSIZE) {
    			if (node.hsize > world.getMinHsize()) {
        			if (!check_existed || !pendingLeafNodes.contains(node)) {
        			if (!check_existed || !pendingLeafNodes.contains(node)) {
        				addPendingLeafNode(node);
        				addPendingLeafNode(node);
        			}
        			}
@@ -274,7 +182,7 @@ public class LwocOctree implements Serializable {
     * Tend to pending scenes list. Not thread-safe, should be run in a single-thread mode.
     * Tend to pending scenes list. Not thread-safe, should be run in a single-thread mode.
     * @param check_existed - do not add duplicate scenes and nodes
     * @param check_existed - do not add duplicate scenes and nodes
     */
     */
    public static void tendPendingScenes(
    public void tendPendingScenes(
    		boolean               check_existed
    		boolean               check_existed
    		) {
    		) {
    	if (pendingScenes.isEmpty()) {
    	if (pendingScenes.isEmpty()) {
@@ -295,7 +203,7 @@ public class LwocOctree implements Serializable {
     * Only adds mesh centers and grows the world if needed.
     * Only adds mesh centers and grows the world if needed.
     * @param check_existed    do not add duplicate meshes
     * @param check_existed    do not add duplicate meshes
     */
     */
    public static void tendPendingMeshCentersOnly(
    public void tendPendingMeshCentersOnly(
    		boolean               check_existed
    		boolean               check_existed
    		) {
    		) {
    	if (pendingMeshes.isEmpty()) {
    	if (pendingMeshes.isEmpty()) {
@@ -326,14 +234,14 @@ public class LwocOctree implements Serializable {
     * Should be run after tendPendingMeshCentersOnly().
     * Should be run after tendPendingMeshCentersOnly().
     * @param check_existed    do not add duplicate meshes
     * @param check_existed    do not add duplicate meshes
     */
     */
    public static void tendPendingMeshes(
    public void tendPendingMeshes(
    		boolean               check_existed ) {
    		boolean               check_existed ) {
    	if (pendingMeshes.isEmpty()) {
    	if (pendingMeshes.isEmpty()) {
    		return; // nothing to do
    		return; // nothing to do
      	} else {
      	} else {
    		for (LwocMesh mesh: pendingMeshes) {
    		for (LwocMesh mesh: pendingMeshes) {
//    			int num_added = 
//    			int num_added = 
    			lwoc_root.addMesh(
    			world.lwoc_root.addMesh(
    					mesh,
    					mesh,
    					check_existed);
    					check_existed);
    		} 
    		} 
@@ -417,6 +325,7 @@ public class LwocOctree implements Serializable {
    			xyz[dm] +=new_hsize * ((((nchild >> dm) & 1) > 0)? 1 : -1);
    			xyz[dm] +=new_hsize * ((((nchild >> dm) & 1) > 0)? 1 : -1);
    		}
    		}
    		children[nchild] = new LwocOctree(
    		children[nchild] = new LwocOctree(
    				world,
    				this,
    				this,
    				xyz,
    				xyz,
    				new_hsize);
    				new_hsize);
@@ -481,41 +390,44 @@ public class LwocOctree implements Serializable {
     * until the specified point gets inside. Not thread safe, should run in single-thread mode
     * 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.
     * @param xyz The point to be included in the world.
     */
     */
    public static void growXYZ(double [] xyz) {
    public void growXYZ(double [] xyz) {
       	while (!lwoc_root.contains(xyz)) {// already fits, do not grow
       	while (!world.lwoc_root.contains(xyz)) {// already fits, do not grow
    	    // grow once
    	    // grow once
    		int indx=0; //direction to grow
    		int indx=0; //direction to grow
    		double [] new_center = new double[3];
    		double [] new_center = new double[3];
    		double [] root_center = world.lwoc_root.center;
			double root_hsize = world.lwoc_root.hsize;
    		for (int dm = 0; dm < new_center.length; dm++) {
    		for (int dm = 0; dm < new_center.length; dm++) {
    			if (xyz[dm] >= lwoc_root.center[dm] ) {
    			if (xyz[dm] >= root_center[dm] ) {
    				indx += 1 << dm;
    				indx += 1 << dm;
        			new_center[dm]= lwoc_root.center[dm] + lwoc_root.hsize;
        			new_center[dm]= root_center[dm] + root_hsize;
    			} else {
    			} else {
        			new_center[dm]= lwoc_root.center[dm] - lwoc_root.hsize;
        			new_center[dm]= root_center[dm] - root_hsize;
    			}
    			}
    		}
    		}
    		LwocOctree new_root = new LwocOctree(null, new_center, lwoc_root.hsize * 2);
    		LwocOctree new_root = new LwocOctree(world,null, new_center, world.lwoc_root.hsize * 2);
    		new_root.children = new LwocOctree[NUM_CHILDREN];
    		new_root.children = new LwocOctree[NUM_CHILDREN];
    		int child =  (~indx ) & (NUM_CHILDREN -1); // opposite direction, from new root to old root 
    		int child =  (~indx ) & (NUM_CHILDREN -1); // opposite direction, from new root to old root 
    		for (int ichild = 0; ichild < NUM_CHILDREN; ichild++) {
    		for (int ichild = 0; ichild < NUM_CHILDREN; ichild++) {
    			if (ichild == child) {
    			if (ichild == child) {
    				lwoc_root.parent = new_root;
    				world.lwoc_root.parent = new_root;
    				new_root.children[ichild] = lwoc_root;
    				new_root.children[ichild] = world.lwoc_root;
    			} else { // create empty leaf nodes
    			} else { // create empty leaf nodes
    				new_root.children[ichild] = new LwocOctree(
    				new_root.children[ichild] = new LwocOctree(
    						world,
							new_root,
							new_root,
    						new double [] {
    						new double [] {
    								new_center[0] +	lwoc_root.hsize * ((((child >> 0) & 1) > 0)? 1 : -1),
    								new_center[0] +	root_hsize * ((((child >> 0) & 1) > 0)? 1 : -1),
    								new_center[1] +	lwoc_root.hsize * ((((child >> 1) & 1) > 0)? 1 : -1),
    								new_center[1] +	root_hsize * ((((child >> 1) & 1) > 0)? 1 : -1),
    								new_center[2] +	lwoc_root.hsize * ((((child >> 2) & 1) > 0)? 1 : -1)
    								new_center[2] +	root_hsize * ((((child >> 2) & 1) > 0)? 1 : -1)
    						},
    						},
    						lwoc_root.hsize);
    						root_hsize);
    				
    				
    				// add leaf 
    				// add leaf 
    				new_root.children[ichild].leaf = new LwocLeaf();
    				new_root.children[ichild].leaf = new LwocLeaf();
    			}
    			}
    		}
    		}
    		lwoc_root = new_root;
    		world.lwoc_root = new_root;
    	}
    	}
    }
    }
    
    
@@ -525,6 +437,7 @@ public class LwocOctree implements Serializable {
     * @param half_whd  half width(x), height(y) and depth(z)
     * @param half_whd  half width(x), height(y) and depth(z)
     * @return True if it intersects
     * @return True if it intersects
     */
     */
	//FIXME: obey border (on the edges of max hsize of the root) nodes
    public boolean intersects (
    public boolean intersects (
    		double [] xyz,
    		double [] xyz,
    		double [] half_whd) {
    		double [] half_whd) {
@@ -544,6 +457,7 @@ public class LwocOctree implements Serializable {
     * @param xyz point
     * @param xyz point
     * @return True if it intersects
     * @return True if it intersects
     */
     */
	//FIXME: obey border (on the edges of max hsize of the root) nodes
    public boolean contains (
    public boolean contains (
    		double [] xyz) {
    		double [] xyz) {
    	for (int dm = 0; dm < center.length; dm++) {
    	for (int dm = 0; dm < center.length; dm++) {
@@ -563,6 +477,8 @@ public class LwocOctree implements Serializable {
     * @param half_whd  half width(x), height(y) and depth(z)
     * @param half_whd  half width(x), height(y) and depth(z)
     * @return True if it intersects
     * @return True if it intersects
     */
     */
	//FIXME: obey border (on the edges of max hsize of the root) nodes

    public boolean contains (
    public boolean contains (
    		double [] xyz,
    		double [] xyz,
    		double [] half_whd) {
    		double [] half_whd) {
@@ -584,7 +500,7 @@ public class LwocOctree implements Serializable {
     * @param check_existed Add only if the same mesh did not exist
     * @param check_existed Add only if the same mesh did not exist
     * @return number of nodes it was added to (intersecting)
     * @return number of nodes it was added to (intersecting)
     */
     */
    public static boolean addMeshCenter( // returns 0 and adds to pendingMeshes if needs growing
    public boolean addMeshCenter( // returns 0 and adds to pendingMeshes if needs growing
    		LwocMesh              mesh,
    		LwocMesh              mesh,
    		boolean               check_existed
    		boolean               check_existed
    		) {
    		) {
@@ -594,7 +510,7 @@ public class LwocOctree implements Serializable {
		double [] corner_xyz = center.clone();
		double [] corner_xyz = center.clone();
    	for (int dm = 0; dm < center.length; dm++) {
    	for (int dm = 0; dm < center.length; dm++) {
    		corner_xyz[dm] += dims[dm];
    		corner_xyz[dm] += dims[dm];
    		if (!lwoc_root.contains(corner_xyz)){
    		if (!world.lwoc_root.contains(corner_xyz)){
    			if (pendingMeshes != null) {
    			if (pendingMeshes != null) {
    				if (!check_existed || !pendingMeshes.contains(mesh)) {
    				if (!check_existed || !pendingMeshes.contains(mesh)) {
    					addPendingMesh(mesh);
    					addPendingMesh(mesh);
@@ -603,7 +519,7 @@ public class LwocOctree implements Serializable {
    			return false;
    			return false;
    		}
    		}
    		corner_xyz[dm] -= 2*dims[dm];
    		corner_xyz[dm] -= 2*dims[dm];
    		if (!lwoc_root.contains(corner_xyz)){
    		if (!world.lwoc_root.contains(corner_xyz)){
    			if (pendingMeshes != null) {
    			if (pendingMeshes != null) {
    				if (!check_existed || !pendingMeshes.contains(mesh)) {
    				if (!check_existed || !pendingMeshes.contains(mesh)) {
    					addPendingMesh(mesh);
    					addPendingMesh(mesh);
@@ -617,8 +533,8 @@ public class LwocOctree implements Serializable {
    	LwocOctree node = getLeafNode(center);
    	LwocOctree node = getLeafNode(center);
		node.leaf.addMeshCenter(mesh, check_existed);
		node.leaf.addMeshCenter(mesh, check_existed);
		// Check if leaf node requires splitting
		// Check if leaf node requires splitting
		if (node.leaf.getMeshCenters().size() > MAX_MESH_CENTERS) {
		if (node.leaf.getMeshCenters().size() > world.getMaxMeshCenters()) {
			if (node.hsize > MIN_HSIZE) {
			if (node.hsize >  world.getMinHsize()) {
				if (!check_existed || !pendingLeafNodes.contains(node)) {
				if (!check_existed || !pendingLeafNodes.contains(node)) {
					addPendingLeafNode(node);
					addPendingLeafNode(node);
				}
				}
@@ -659,7 +575,7 @@ public class LwocOctree implements Serializable {
     * Should fit in a root node (as it was earlier added)
     * Should fit in a root node (as it was earlier added)
     * @param mesh new mesh to add
     * @param mesh new mesh to add
     */
     */
    public static void removeMeshCenter(
    public void removeMeshCenter(
    		LwocMesh mesh) { // check and remove duplicates
    		LwocMesh mesh) { // check and remove duplicates
    	LwocOctree node = getLeafNode(mesh.getCenter());
    	LwocOctree node = getLeafNode(mesh.getCenter());
		node.leaf.removeMeshCenter(mesh);
		node.leaf.removeMeshCenter(mesh);
@@ -688,6 +604,26 @@ public class LwocOctree implements Serializable {
    	return removed;
    	return removed;
    }
    }
    
    
    /**
     * Restore pointers to .parent and .world
     * @param world
     * @param parent
     */
    public void restoreWorldParent(
    		LwocWorld world,
    		LwocOctree parent) {
    	this.parent = parent;
    	this.world = world;
    	if (!isLeaf()) {
    		for (LwocOctree child:children) {
    			child.restoreWorldParent(
    		    		world, // LwocWorld world,
    		    		this); // LwocOctree parent)
    		}    		
    	}
    }
    
    
    /**
    /**
     * Recursively create a list of all leave nodes in the world.
     * Recursively create a list of all leave nodes in the world.
     * @return A list of all leaf nodes
     * @return A list of all leaf nodes
@@ -708,9 +644,9 @@ public class LwocOctree implements Serializable {
     * Rebuild meshes lists from mesh_centers for all leaf nodes after restoring the world.
     * Rebuild meshes lists from mesh_centers for all leaf nodes after restoring the world.
     * Used after restoring world from serialized form
     * Used after restoring world from serialized form
     */
     */
    public static void rebuildMeshLists(
    public void rebuildMeshLists(
    		final boolean check_existed) {
    		final boolean check_existed) {
    	final List<LwocOctree> leaves = lwoc_root.getAllLeafNodes();
    	final List<LwocOctree> leaves = world.lwoc_root.getAllLeafNodes();
    	final List<LwocMesh> meshes = new ArrayList<LwocMesh>();
    	final List<LwocMesh> meshes = new ArrayList<LwocMesh>();
    	for (LwocOctree node : leaves) {
    	for (LwocOctree node : leaves) {
    		node.leaf.initMeshes();
    		node.leaf.initMeshes();
@@ -726,7 +662,7 @@ public class LwocOctree implements Serializable {
				public void run() {
				public void run() {
					for (int indx_mesh = ai.getAndIncrement(); indx_mesh < meshes.size(); indx_mesh = ai.getAndIncrement()) {
					for (int indx_mesh = ai.getAndIncrement(); indx_mesh < meshes.size(); indx_mesh = ai.getAndIncrement()) {
						LwocMesh mesh = meshes.get(indx_mesh);
						LwocMesh mesh = meshes.get(indx_mesh);
						lwoc_root.addMesh(mesh, check_existed);
						world.lwoc_root.addMesh(mesh, check_existed);
					}
					}
				}
				}
			};
			};
+187 −0
Original line number Original line Diff line number Diff line
/**
 **
 ** LwocWorld.java - Octree world parameters (previous static)
 **
 ** Copyright (C) 2022 Elphel, Inc.
 **
 ** -----------------------------------------------------------------------------**
 **
 **  LwocWorld.java is free software: you can redistribute it and/or modify
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 of the License, or
 **  (at your option) any later version.
 **
 **  This program is distributed in the hope that it will be useful,
 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 **  GNU General Public License for more details.
 **
 **  You should have received a copy of the GNU General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ** -----------------------------------------------------------------------------**
 **
 */

package com.elphel.imagej.tileprocessor.lwoc;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class LwocWorld  implements Serializable {
	private static final long   serialVersionUID = 1L;
	static List<LwocWorld>      lwoc_worlds;   //  
	
	public double               min_hsize; //  =         0.3; // meter - do not subdivide more
	public double               max_hsize; //  =     10000.0; // meter - do not grow more
	public int                  max_mesh_centers; //  = 10;   // maximal number of meshes in a leaf;
	public int                  max_cameras; //  =      10;   // maximal number of cameras in a leaf;
//	public transient LwocOctree lwoc_root; //  =        null;
	public LwocOctree           lwoc_root; //  =        null;
	public double []            atr; //  =              null; // Azimuth, tilt, roll - may be used to merge
	public double []            xyz; //  =              null; // this world offset (before rotation) or
    // null if not known.
	public LwocWorld (
			double     min_hsize,
			double     max_hsize,
			int        max_mesh_centers,
			int        max_cameras,
			LwocOctree lwoc_root,
			double []  atr,
			double []  xyz) {
		setMinHsize      (min_hsize);
		setMaxHsize      (max_hsize);
		setMaxMeshCenters(max_mesh_centers);
		setMaxCameras    (max_cameras);
		setLwocRoot      (lwoc_root);
		setATR           (atr);
		setXYZ           (xyz);
	}
	public double     getMinHsize()       {return min_hsize;}
	public double     getMaxHsize()       {return max_hsize;}
	public int        getMaxMeshCenters() {return max_mesh_centers;}
	public int        getMaxCameras()     {return max_cameras;}
	public LwocOctree getLwocRoot()       {return lwoc_root;}
	public double []  getATR()            {return atr;}
	public double []  getXYZ()            {return xyz;}
	
	public void       setMinHsize      (double     min_hsize)        {this.min_hsize =        min_hsize;}
	public void       setMaxHsize      (double     max_hsize)        {this.max_hsize =        max_hsize;}
	public void       setMaxMeshCenters(int        max_mesh_centers) {this.max_mesh_centers = max_mesh_centers;}
	public void       setMaxCameras    (int        max_cameras)      {this.max_cameras =      max_cameras;}
	public void       setLwocRoot      (LwocOctree lwoc_root)        {this.lwoc_root =        lwoc_root;}
	public void       setATR           (double []  atr)              {this.atr =              atr;}
	public void       setXYZ           (double []  xyz)              {this.xyz =              xyz;}
	
	
	/**
	 * 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();
		// as of now - nothing else, custom for reads only
		
//		if (parent == null) { // write world members
			/*
			oos.writeObject(world.getMinHsize());
			oos.writeObject(world.getMaxHsize());
			oos.writeObject(world.getMaxMeshCenters());
			oos.writeObject(world.getMaxCameras());
			oos.writeObject(world.getATR());
			oos.writeObject(world.getXYZ());
			*/
//			oos.writeObject(world);
			
			// Remove those
//			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();
		// now rebuild transient .parent and .world field for the whole tree 
		lwoc_root.restoreWorldParent(
	    		this, // LwocWorld world,
	    		null); //LwocOctree parent)
		lwoc_root.rebuildMeshLists(
	    		true); // final boolean check_existed)
	}
	
	/**
	 * Init worlds and their list. Multiple worlds may be needed if some world initially can not
	 * be matched. They will grow independently and possibly merged later
	 */
	public static void initWorlds() {
		LwocMesh.resetMeshes();
		LwocScene.resetScenes();
		LwocOctree.resetPending();
		lwoc_worlds = new ArrayList<LwocWorld>();
	}
	
	/**
	 * Create a new empty world and add it to the list of worlds in the universe.
	 * @param center X,Y,Z of the new world 
	 * @param world_hsize new world half-size
	 * @param min_hsize do not subdivide nodes if half-size is smaller than this
	 * @param max_hsize do not grow world if its half-size it >= this
	 * @param max_mesh_centers maximal number of mesh centers in a node to trigger subdivision
	 * @param max_cameras maximal number of scenes (cameras) in a node to trigger subdivision
	 * @param atr world rotation relative to the universe (non-null when defined)
	 * @param xyz world offset in the universe (non-null when defined)
	 * @return new world instance
	 */
	public static LwocWorld newWorld(
			double [] center,
			double    world_hsize,			
			double    min_hsize,
			double    max_hsize,			
			int       max_mesh_centers,
			int       max_cameras,
			double [] atr,
			double [] xyz) {
		LwocWorld new_world = new  LwocWorld (
				min_hsize,        // double     min_hsize,
				max_hsize,        // double     max_hsize,
				max_mesh_centers, // int        max_mesh_centers,
				max_cameras,      // int        max_cameras,
				null,             // LwocOctree lwoc_root,
				null,             //double []  atr,
				null);            //double []  xyz);
		LwocOctree root_node = new LwocOctree (
				new_world, // LwocWorld  lwocWorld,
				null,      // LwocOctree parent,
				center,    // double []  xyz,
				world_hsize); //double     hsize)
		root_node.leaf = new LwocLeaf();
		new_world.setLwocRoot(root_node);
		lwoc_worlds.add(new_world);
		return new_world;
	}

	/**
	 * Delete world from the universe (if existed)
	 * @param world world instance to remove
	 * @return True if removed, false if did not exist. 
	 */
	public static boolean deleteWorld (LwocWorld world) {
		return lwoc_worlds.remove(world);
	}

	
	
}