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

Updated for synchronized methods in growing lists, regeneration of

intersecting meshes after restoring from files.
parent d35ccbb6
...@@ -27,6 +27,7 @@ package com.elphel.imagej.tileprocessor.lwoc; ...@@ -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 { ...@@ -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);
......
...@@ -28,6 +28,7 @@ import java.util.ArrayList; ...@@ -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
......
...@@ -29,6 +29,7 @@ import java.util.List; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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);
} }
} }
...@@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment