Commit 860cbc5f authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Updated for synchronized methods in growing lists, regeneration of

intersecting meshes after restoring from files.
parent d35ccbb6
Loading
Loading
Loading
Loading
+26 −3
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ package com.elphel.imagej.tileprocessor.lwoc;
import java.util.ArrayList;
import java.util.ArrayList;


public class LwocLeaf {
public class LwocLeaf {
	private static final long    serialVersionUID = 1L;
	ArrayList <LwocMesh>  meshes;
	ArrayList <LwocMesh>  meshes;
	ArrayList <LwocMesh>  mesh_centers;
	ArrayList <LwocMesh>  mesh_centers;
	ArrayList <LwocScene> scenes;
	ArrayList <LwocScene> scenes;
@@ -36,21 +37,43 @@ public class LwocLeaf {
		scenes =       new ArrayList <LwocScene>(); // cameras located in this node
		scenes =       new ArrayList <LwocScene>(); // cameras located in this node
	}
	}
	
	
	public void addScene(LwocScene scene,
	public void initMeshes() {
		meshes =       new ArrayList <LwocMesh>();  // all meshes BB intersecting this node
	}
	public synchronized void addScene( // IS synchronized needed?
			LwocScene scene,
			boolean check_existed) {
			boolean check_existed) {
		if (!check_existed || !scenes.contains(scene)) {
		if (!check_existed || !scenes.contains(scene)) {
			scenes.add(scene);
			scenes.add(scene);
		}
		}
	}
	}
	
	
	public void addMeshCenter(LwocMesh mesh,
	public synchronized void addMeshCenter( // IS synchronized needed?
			LwocMesh mesh,
			boolean check_existed) {
			boolean check_existed) {
		if (!check_existed || !mesh_centers.contains(mesh)) {
		if (!check_existed || !mesh_centers.contains(mesh)) {
			mesh_centers.add(mesh);
			mesh_centers.add(mesh);
		}
		}
	}
	}


	public void addMesh(LwocMesh mesh,
	public synchronized void removeScene(
			LwocScene scene) {
		while (scenes.remove(scene)); // will remove all
	}

	public synchronized void removeMeshCenter(
			LwocMesh mesh) {
		while (mesh_centers.remove(mesh)); // will remove all
	}

	public synchronized void removeMesh(
			LwocMesh mesh) {
		while (meshes.remove(mesh)); // will remove all
	}
	
	
	public synchronized void addMesh( // synchronized IS needed
			LwocMesh mesh,
			boolean check_existed) {
			boolean check_existed) {
		if (!check_existed || !meshes.contains(mesh)) {
		if (!check_existed || !meshes.contains(mesh)) {
			meshes.add(mesh);
			meshes.add(mesh);
+1 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicInteger;


public class LwocMesh {
public class LwocMesh {
	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
+109 −139
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicInteger;
import com.elphel.imagej.common.MultiThreading;
import com.elphel.imagej.common.MultiThreading;
public class LwocOctree {
public class LwocOctree {
	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
	public static double         MIN_HSIZE =         0.3; // meter - do not subdivide more
	// can not be used as intersecting meshes' bb will not decrease number after splitting
	// can not be used as intersecting meshes' bb will not decrease number after splitting
@@ -37,14 +38,10 @@ public class LwocOctree {
	public static LwocOctree     lwoc_root =        null;
	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 AtomicInteger         OCTREE_ID =        new AtomicInteger();
	// synchronized lists to handle thread-unsafe operations: growing world and splitting leaves
///	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<LwocOctree>      pendingLeafNodes;// synchronized - leaf nodes needed to be split


	static AtomicInteger         numPendingScenes;
	static List<LwocScene>       pendingScenes;   // synchronized - add not-yet-added scenes pending growing world 
	static AtomicInteger         numPendingMeshes;
	static List<LwocMesh>        pendingMeshes;   // synchronized - add not-yet-added meshes pending growing world
	static AtomicInteger         numPendingLeafNodes;
	static List<LwocOctree>      pendingLeafNodes;// synchronized - leaf nodes needed to be split
	
	
	
	
	int                          id;         // assign unique ID
	int                          id;         // assign unique ID
@@ -53,6 +50,26 @@ public class LwocOctree {
	LwocLeaf                     leaf;       //
	LwocLeaf                     leaf;       //
	double []                    center;     // x-center, y-center, z-center
	double []                    center;     // x-center, y-center, z-center
	double                       hsize;
	double                       hsize;
	
	public static void addPendingScene(LwocScene scene) {
		synchronized(pendingScenes) {
			pendingScenes.add(scene);
		}
	}
	
	public static void addPendingMesh(LwocMesh mesh) {
		synchronized(pendingMeshes) {
			pendingMeshes.add(mesh);
		}
	}
	
	public static void addPendingLeafNode(LwocOctree node) {
		synchronized(pendingLeafNodes) {
			pendingLeafNodes.add(node);
		}
	}
	
	
// just for testing	
// just for testing	
//	List<List<LwocScene>> group = new ArrayList<List<LwocScene>>(4);	
//	List<List<LwocScene>> group = new ArrayList<List<LwocScene>>(4);	
	
	
@@ -79,9 +96,9 @@ public class LwocOctree {
	 * processes by a single-thread method. 
	 * processes by a single-thread method. 
	 */
	 */
	public static void resetPending() {
	public static void resetPending() {
		numPendingScenes.set(0);    // = Collections.synchronizedList(new ArrayList<LwocScene>());
		pendingScenes =    new ArrayList<LwocScene>();
		numPendingMeshes.set(0);    // = Collections.synchronizedList(new ArrayList<LwocMesh>());
		pendingMeshes =    new ArrayList<LwocMesh>();
		numPendingLeafNodes.set(0); // = Collections.synchronizedList(new ArrayList<LwocOctree>());
		pendingLeafNodes = new ArrayList<LwocOctree>();
	}
	}
	// use per-thread lists and then combine them avoiding synchronizations?
	// use per-thread lists and then combine them avoiding synchronizations?
	//Pass list to any function that may grow it
	//Pass list to any function that may grow it
@@ -99,7 +116,7 @@ public class LwocOctree {
	 * @return if world needs growing.
	 * @return if world needs growing.
	 */
	 */
	public static boolean pendingGrow() {
	public static boolean pendingGrow() {
		return (numPendingScenes.get()  + numPendingMeshes.get()) > 0;
		return (pendingScenes.size()  + pendingMeshes.size()) > 0;
	}
	}
	
	
	/**
	/**
@@ -107,7 +124,7 @@ public class LwocOctree {
	 * @return if any leaf nodes require splitting
	 * @return if any leaf nodes require splitting
	 */
	 */
	public static boolean pendingSplit() {
	public static boolean pendingSplit() {
		return numPendingLeafNodes.get() > 0;
		return pendingLeafNodes.size() > 0;
	}
	}
	
	
	/**
	/**
@@ -152,23 +169,18 @@ public class LwocOctree {
     * Add scene to the world in a thread-safe mode, or put it to pending list if the world
     * Add scene to the world in a thread-safe mode, or put it to pending list if the world
     * needs growing.
     * needs growing.
     * @param scene Scene to add.
     * @param scene Scene to add.
     * @param pendingScenes per thread list of scenes to be combined after merging threads
     * @param pendingLeafNodes  per thread list of nodes to be combined after merging threads
     * @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 static LwocOctree addScene(
    		LwocScene             scene,
    		LwocScene             scene,
    		ArrayList<LwocScene>  pendingScenes,
    		ArrayList<LwocOctree> pendingLeafNodes,
    		boolean               check_existed
    		boolean               check_existed
    		) {// returns null and adds to pendingScenes if needs growing
    		) {// returns null and adds to pendingScenes if needs growing
    	LwocOctree node = getLeafNode(scene.getCameraXYZ());
    	LwocOctree node = getLeafNode(scene.getCameraXYZ());
    	if (node == null) {
    	if (node == null) {
    		if (pendingScenes != null) {
    		if (pendingScenes != null) {
    			if (!check_existed || !pendingScenes.contains(scene)) {
    			if (!check_existed || !pendingScenes.contains(scene)) {
    				pendingScenes.add(scene);
    				addPendingScene(scene);
    				numPendingScenes.getAndIncrement();
    			}
    			}
    		}
    		}
    	} else {
    	} else {
@@ -177,8 +189,7 @@ public class LwocOctree {
    		if (node.leaf.getScenes().size() > MAX_CAMERAS) {
    		if (node.leaf.getScenes().size() > MAX_CAMERAS) {
    			if (node.hsize > MIN_HSIZE) {
    			if (node.hsize > MIN_HSIZE) {
        			if (!check_existed || !pendingLeafNodes.contains(node)) {
        			if (!check_existed || !pendingLeafNodes.contains(node)) {
        				pendingLeafNodes.add(node);
        				addPendingLeafNode(node);
        				numPendingLeafNodes.getAndIncrement();
        			}
        			}
    			}
    			}
    		}
    		}
@@ -188,13 +199,9 @@ public class LwocOctree {
    
    
    /**
    /**
     * 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 pendingScenes    combined list of scenes to be added growing world (merged from per-thread ones)
     * @param pendingLeafNodes a list of nodes that will need splitting (here in single-thread mode - single one)
     * @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 static void tendPendingScenes(
    		ArrayList<LwocScene>  pendingScenes, 
    		ArrayList<LwocOctree> pendingLeafNodes,
    		boolean               check_existed
    		boolean               check_existed
    		) {
    		) {
    	if (pendingScenes.isEmpty()) {
    	if (pendingScenes.isEmpty()) {
@@ -204,8 +211,6 @@ public class LwocOctree {
    			growXYZ(scene.getCameraXYZ());
    			growXYZ(scene.getCameraXYZ());
    			LwocOctree node= addScene(  // should not be null
    			LwocOctree node= addScene(  // should not be null
    					scene,
    					scene,
    		    		pendingScenes,
    		    		pendingLeafNodes,
    		    		check_existed);
    		    		check_existed);
    			assert node != null : "addScene() should not fail after growing world";
    			assert node != null : "addScene() should not fail after growing world";
    		} 
    		} 
@@ -216,13 +221,9 @@ public class LwocOctree {
     * Tend to pending meshes list. Not thread-safe, should be run in a single-thread mode.
     * Tend to pending meshes list. Not thread-safe, should be run in a single-thread mode.
     * 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
     * @param pendingMeshes    combined list of meshes to be added (merged from per-thread ones). Will only be read.
     * @param pendingLeafNodes a list of nodes that will need splitting (here in single-thread mode - single one). May grow.
     */
     */
    public static void tendPendingMeshCentersOnly(
    public static void tendPendingMeshCentersOnly(
    		boolean               check_existed,
    		boolean               check_existed
    		ArrayList<LwocMesh>   pendingMeshes,   // will read
    		ArrayList<LwocOctree> pendingLeafNodes // may add to
    		) {
    		) {
    	if (pendingMeshes.isEmpty()) {
    	if (pendingMeshes.isEmpty()) {
    		return; // nothing to do
    		return; // nothing to do
@@ -240,9 +241,7 @@ public class LwocOctree {
    	    	}    			
    	    	}    			
    			boolean ok= addMeshCenter(  // should not be null
    			boolean ok= addMeshCenter(  // should not be null
    					mesh,
    					mesh,
    					check_existed,
    					check_existed);
    					null, // pendingMeshes,
    		    		pendingLeafNodes);
    			assert ok : "addMeshCenter() should not fail after growing world";
    			assert ok : "addMeshCenter() should not fail after growing world";
    		} 
    		} 
    	}
    	}
@@ -253,13 +252,9 @@ public class LwocOctree {
     * Only adds mesh themselves that do not trigger node splits.
     * Only adds mesh themselves that do not trigger node splits.
     * 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
     * @param pendingMeshes    combined list of meshes to be added (merged from per-thread ones).
     *                         Will only be read.
     */
     */
    public static void tendPendingMeshes(
    public static void tendPendingMeshes(
    		boolean               check_existed,
    		boolean               check_existed ) {
    		ArrayList<LwocMesh>   pendingMeshes   // will read
    		) {
    	if (pendingMeshes.isEmpty()) {
    	if (pendingMeshes.isEmpty()) {
    		return; // nothing to do
    		return; // nothing to do
      	} else {
      	} else {
@@ -276,8 +271,6 @@ public class LwocOctree {
    /**
    /**
     * Recursively (if needed) splits octree nodes to reduce number of scenes/cameras
     * Recursively (if needed) splits octree nodes to reduce number of scenes/cameras
     * and mesh centers below specified thresholds (limited by the minimal node size) 
     * and mesh centers below specified thresholds (limited by the minimal node size) 
     * @param pendingLeafNodesIn array list of nodes to be split. Will be filtered to
     *        remove any duplicates and non-leaf nodes
     * @param min_hsize Minimal half-size of the node (in meters). Smaller nodes will not be split
     * @param min_hsize Minimal half-size of the node (in meters). Smaller nodes will not be split
     * @param max_mesh_centers Maximal number of mesh centers in a node. Larger number 
     * @param max_mesh_centers Maximal number of mesh centers in a node. Larger number 
     *        triggers node split.
     *        triggers node split.
@@ -286,17 +279,15 @@ public class LwocOctree {
     * @param check_existed 
     * @param check_existed 
     */
     */
    public static void tendPendingLeafNodes(
    public static void tendPendingLeafNodes(
    		ArrayList<LwocOctree> pendingLeafNodesIn,
    		final double          min_hsize,
    		final double          min_hsize,
    		final int             max_mesh_centers,
    		final int             max_mesh_centers,
    		final int             max_cameras, // scenes
    		final int             max_cameras, // scenes
    		final boolean         check_existed) {
    		final boolean         check_existed) {
    	// remove any possible duplicates
    	// remove any possible duplicates
    	final ArrayList<LwocOctree> pendingLeafNodes = new ArrayList<LwocOctree>();
    	final ArrayList<LwocOctree> pendingLeafNodesFiltered = new ArrayList<LwocOctree>();
    	for (LwocOctree node:pendingLeafNodesIn) {
    	for (LwocOctree node:pendingLeafNodes) {
    		if (!pendingLeafNodes.contains(node) && node.isLeaf()) {// filter already split nodes 
    		if (!pendingLeafNodesFiltered.contains(node) && node.isLeaf()) {// filter already split nodes 
    			pendingLeafNodes.add(node);
    			pendingLeafNodesFiltered.add(node);
    			numPendingLeafNodes.getAndIncrement();    			
    		}
    		}
    	}
    	}
    	// run splitting multithreaded
    	// run splitting multithreaded
@@ -306,8 +297,8 @@ public class LwocOctree {
			threads[ithread] = new Thread() {
			threads[ithread] = new Thread() {
				@Override
				@Override
				public void run() {
				public void run() {
					for (int indx_node = ai.getAndIncrement(); indx_node < pendingLeafNodes.size(); indx_node = ai.getAndIncrement()) {
					for (int indx_node = ai.getAndIncrement(); indx_node < pendingLeafNodesFiltered.size(); indx_node = ai.getAndIncrement()) {
						LwocOctree node = pendingLeafNodes.get(indx_node);
						LwocOctree node = pendingLeafNodesFiltered.get(indx_node);
					    // Split recursively until satisfied conditions
					    // Split recursively until satisfied conditions
						node.splitNode(
						node.splitNode(
								min_hsize,        // double  min_hsize,
								min_hsize,        // double  min_hsize,
@@ -319,7 +310,6 @@ public class LwocOctree {
			};
			};
		}
		}
		MultiThreading.startAndJoin(threads);
		MultiThreading.startAndJoin(threads);
		ai.set(0);
    }
    }
    
    
    // Split recursively until satisfied conditions
    // Split recursively until satisfied conditions
@@ -517,15 +507,11 @@ public class LwocOctree {
     * add to pending list if does not fit in a root node
     * add to pending list if does not fit in a root node
     * @param mesh new mesh to add
     * @param mesh new mesh to add
     * @param check_existed Add only if the same mesh did not exist
     * @param check_existed Add only if the same mesh did not exist
     * @param pendingMeshes per thread list of meshes to be combined after merging threads
     * @param pendingLeafNodes  per thread list of nodes to be combined after merging threads
     * @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 static boolean addMeshCenter( // returns 0 and adds to pendingMeshes if needs growing
    		LwocMesh              mesh,
    		LwocMesh              mesh,
    		boolean               check_existed,
    		boolean               check_existed
    		ArrayList<LwocMesh>   pendingMeshes, 
    		ArrayList<LwocOctree> pendingLeafNodes
    		) {
    		) {
    	// should in check before adding?
    	// should in check before adding?
    	// mesh.equals(mesh);
    	// mesh.equals(mesh);
@@ -538,8 +524,7 @@ public class LwocOctree {
    		if (!lwoc_root.contains(corner_xyz)){
    		if (!lwoc_root.contains(corner_xyz)){
    			if (pendingMeshes != null) {
    			if (pendingMeshes != null) {
    				if (!check_existed || !pendingMeshes.contains(mesh)) {
    				if (!check_existed || !pendingMeshes.contains(mesh)) {
    					pendingMeshes.add(mesh);
    					addPendingMesh(mesh);
    					numPendingMeshes.getAndIncrement();
    				}
    				}
    			}
    			}
    			return false;
    			return false;
@@ -548,8 +533,7 @@ public class LwocOctree {
    		if (!lwoc_root.contains(corner_xyz)){
    		if (!lwoc_root.contains(corner_xyz)){
    			if (pendingMeshes != null) {
    			if (pendingMeshes != null) {
    				if (!check_existed || !pendingMeshes.contains(mesh)) {
    				if (!check_existed || !pendingMeshes.contains(mesh)) {
    					pendingMeshes.add(mesh);
    					addPendingMesh(mesh);
    					numPendingMeshes.getAndIncrement();
    				}
    				}
    			}
    			}
    			return false;
    			return false;
@@ -563,8 +547,7 @@ public class LwocOctree {
		if (node.leaf.getMeshCenters().size() > MAX_MESH_CENTERS) {
		if (node.leaf.getMeshCenters().size() > MAX_MESH_CENTERS) {
			if (node.hsize > MIN_HSIZE) {
			if (node.hsize > MIN_HSIZE) {
				if (!check_existed || !pendingLeafNodes.contains(node)) {
				if (!check_existed || !pendingLeafNodes.contains(node)) {
					pendingLeafNodes.add(node);
					addPendingLeafNode(node);
					numPendingLeafNodes.getAndIncrement();					
				}
				}
			}
			}
		}
		}
@@ -573,6 +556,13 @@ public class LwocOctree {
    }
    }


    // recursive
    // recursive
    /**
     * Recursively add mesh to all leaf nodes that intersect with its bounding box. 
     * Usually starts with lwoc_root.
     * @param mesh Mesh instance to be added
     * @param check_existed verify node lists does not already have this mesh if true
     * @return number of nodes to which this mesh was added
     */
    public int addMesh(
    public int addMesh(
    		LwocMesh mesh,
    		LwocMesh mesh,
    		boolean check_existed) {
    		boolean check_existed) {
@@ -593,102 +583,82 @@ public class LwocOctree {
    }
    }
    
    
    /**
    /**
     * Remove mesh to from each node intersecting with the mesh bounding box.
     * Remove mesh center from the world.
     * 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
     * @param check_existed Add only if the same mesh did not exist 
     * @return The number of nodes it was removed from
     */
     */
    public static int removeMesh(
    public static void removeMeshCenter(
    		LwocMesh mesh,
    		LwocMesh mesh) { // check and remove duplicates
    		boolean remove_all) { // check and remove duplicates
    	LwocOctree node = getLeafNode(mesh.getCenter());
    	// should in check before adding?
		node.leaf.removeMeshCenter(mesh);
    	return 0;
    }
    }


    /**
    /**
     * Prepare list of lists to add scenes in multithreaded environment, one inner
     * Remove mesh from each node intersecting with the mesh bounding box.
     * list for each thread.
     * Should fit in a root node (as it was earlier added)
     * @param threads Array of threads, only length is used
     * @param mesh mesh to remove
     * @return list of lists to provide to threads
     */
     */
    public static List<List<LwocScene>> getMultiPendingScenes(Thread [] threads){
    public int removeMesh(
    	List<List<LwocScene>> multiPendingScenes = new ArrayList<List<LwocScene>>(threads.length);
    		LwocMesh mesh) { // check and remove duplicates
    	for (int i = 0; i < threads.length; i++) {
    	if (!intersects(
    		multiPendingScenes.add(i, new ArrayList<LwocScene>());
    			mesh.getCenter(),
    			mesh.getDims())) {
    		return 0;
    	}
    	}
    	return multiPendingScenes;
    	if (isLeaf()) {
    		leaf.removeMesh(mesh);
    		return 1;
    	}
    	}
    
    	int removed = 0;
    /**
    	for (LwocOctree node: children) {
     * Combine a List of list of scenes (created in multithreaded method getMultiPendingScenes())
    		removed += node.removeMesh(mesh);
     * into a single list.
     * @param multiPendingScenes list of list of scenes
     * @return flattened single list of scenes
     */
    public static List<LwocScene> mergeMultiPendingScenes(List<List<LwocScene>> multiPendingScenes){
    	List<LwocScene> pendingScenes =  new ArrayList<LwocScene>();
    	for (List<LwocScene> scenes:multiPendingScenes) {
    		pendingScenes.addAll(scenes);
    	}
    	}
    	return pendingScenes;
    	return removed;
    }
    }
    
    
    /**
    /**
     * Prepare list of lists to add meshes in multithreaded environment, one inner
     * Recursively create a list of all leave nodes in the world.
     * list for each thread.
     * @return A list of all leaf nodes
     * @param threads Array of threads, only length is used
     * @return list of lists to provide to threads
     */
     */
    public static List<List<LwocMesh>> getMultiPendingMeshes(Thread [] threads){
    public List<LwocOctree> getAllLeafNodes(){
    	List<List<LwocMesh>> multiPendingMeshes = new ArrayList<List<LwocMesh>>(threads.length);
    	List<LwocOctree> leaves = new ArrayList<LwocOctree>();
    	for (int i = 0; i < threads.length; i++) {
    	if (isLeaf()) {
    		multiPendingMeshes.add(i, new ArrayList<LwocMesh>());
    		leaves.add(this);
    	} else {
    		for (LwocOctree child:children) {
    			leaves.addAll(child.getAllLeafNodes());
    		}
    		}
    	return multiPendingMeshes;
    	}
    	return leaves;
    }
    }
    
    
    /**
    /**
     * Combine a List of list of meshes (created in multithreaded method getMultiPendingMeshes())
     * Rebuild meshes lists from mesh_centers for all leaf nodes after restoring the world.
     * into a single list.
     * Used after restoring world from serialized form
     * @param multiPendingMeshes list of list of meshes
     * @return flattened single list of meshes
     */
     */
    public static List<LwocMesh> mergeMultiPendingMeshes(List<List<LwocMesh>> multiPendingMeshes){
    public static void rebuildMeshLists(
    	List<LwocMesh> pendingMeshes =  new ArrayList<LwocMesh>();
    		final boolean check_existed) {
    	for (List<LwocMesh> meshes:multiPendingMeshes) {
    	final List<LwocOctree> leaves = lwoc_root.getAllLeafNodes();
    		pendingMeshes.addAll(meshes);
    	final List<LwocMesh> meshes = new ArrayList<LwocMesh>();
    	}
    	for (LwocOctree node : leaves) {
    	return pendingMeshes;
    		node.leaf.initMeshes();
    		meshes.addAll(node.leaf.getMeshCenters());
    	}
    	}
    	
    	
    /**
		final Thread[] threads = MultiThreading.newThreadArray();
     * Prepare list of lists to add scenes in multithreaded environment, one inner
		final AtomicInteger ai = new AtomicInteger(0);
     * list for each thread.
		
     * @param threads Array of threads, only length is used
		for (int ithread = 0; ithread < threads.length; ithread++) {
     * @return list of lists to provide to threads
			threads[ithread] = new Thread() {
     */
				@Override
    public static List<List<LwocOctree>> getMultiPendingLeafNodes(Thread [] threads){
				public void run() {
    	List<List<LwocOctree>> multiPendingLeafNodes = new ArrayList<List<LwocOctree>>(threads.length);
					for (int indx_mesh = ai.getAndIncrement(); indx_mesh < meshes.size(); indx_mesh = ai.getAndIncrement()) {
    	for (int i = 0; i < threads.length; i++) {
						LwocMesh mesh = meshes.get(indx_mesh);
    		multiPendingLeafNodes.add(i, new ArrayList<LwocOctree>());
						lwoc_root.addMesh(mesh, check_existed);
					}
					}
    	return multiPendingLeafNodes;
				}
				}
    
			};
    /**
     * Combine a List of list of scenes (created in multithreaded method getMultiPendingScenes())
     * into a single list.
     * @param multiPendingLeafNodes list of list of scenes
     * @return flattened single list of scenes
     */
    public static List<LwocOctree> mergeMultiPendingLeafNodes(List<List<LwocOctree>> multiPendingLeafNodes){
    	List<LwocOctree> pendingLeafNodes =  new ArrayList<LwocOctree>();
    	for (List<LwocOctree> nodes:multiPendingLeafNodes) {
    		pendingLeafNodes.addAll(nodes);
		}
		}
    	return pendingLeafNodes;
		MultiThreading.startAndJoin(threads);
    }
    }
    
    
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import com.elphel.imagej.tileprocessor.GeometryCorrection;
import com.elphel.imagej.tileprocessor.GeometryCorrection;


public class LwocScene {
public class LwocScene {
	private static final long    serialVersionUID = 1L;
	static AtomicInteger SCENE_ID = new AtomicInteger();
	static AtomicInteger SCENE_ID = new AtomicInteger();
	static ArrayList<LwocScene> LWOC_SCENES;
	static ArrayList<LwocScene> LWOC_SCENES;