Commit 93ac2c14 authored by Andrey Filippov's avatar Andrey Filippov

Implemented "infinity" so nodes may have sides open to infinity

parent 8176593d
...@@ -37,13 +37,10 @@ import com.elphel.imagej.common.MultiThreading; ...@@ -37,13 +37,10 @@ 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;
// 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
transient LwocWorld world; transient LwocWorld world;
transient LwocOctree parent; transient LwocOctree parent;
...@@ -51,6 +48,7 @@ public class LwocOctree implements Serializable { ...@@ -51,6 +48,7 @@ public class LwocOctree implements Serializable {
LwocLeaf leaf; // LwocLeaf leaf; //
double [] center; // x-center, y-center, z-center double [] center; // x-center, y-center, z-center
double hsize; double hsize;
int infinity = 0;
public static void addPendingScene(LwocScene scene) { public static void addPendingScene(LwocScene scene) {
synchronized(pendingScenes) { synchronized(pendingScenes) {
...@@ -107,20 +105,36 @@ public class LwocOctree implements Serializable { ...@@ -107,20 +105,36 @@ public class LwocOctree implements Serializable {
} }
/** /**
* LwocOctree constructor * LwocOctree constructor. Sets infinity bitmap +1 - no limit for negative X,
* +2 - no limit for positive X, +4 - no limit for negative Y, ...,
* +32 - no limit for positive Z.
* @param lwocWorld World global parameters * @param lwocWorld World global parameters
* @param parent Parent node * @param parent_in 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 h_size 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 ( public LwocOctree (
LwocWorld lwocWorld, LwocWorld lwocWorld,
LwocOctree parent, LwocOctree parent_in,
double [] xyz, double [] xyz,
double hsize) { double h_size) {
this.parent = parent; world = lwocWorld;
this.hsize = hsize; parent = parent_in;
center = xyz;
hsize = h_size;
// set which directions are to infinity (not limited by hsize)
infinity = 0;
double max_hsize = world.getMaxHsize();
LwocOctree lwoc_root = world.getLwocRoot();
for (int dm = 0; dm < center.length; dm++) {
if ((center[dm] - hsize) <= (lwoc_root.center[dm] - max_hsize)) {
infinity |= (1 << (2 * dm));
}
if ((center[dm] + hsize) >= (lwoc_root.center[dm] + max_hsize)) {
infinity |= (1 << (2 * dm + 1));
}
}
} }
/** /**
...@@ -129,7 +143,6 @@ public class LwocOctree implements Serializable { ...@@ -129,7 +143,6 @@ 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)
*/ */
//FIXME: obey border (on the edges of max hsize of the root) nodes
public LwocOctree getLeafNode( // if null - needs growing world public LwocOctree getLeafNode( // if null - needs growing world
double [] xyz) { // thread safe double [] xyz) { // thread safe
if (!world.getLwocRoot().contains(xyz)) return null; // needs growing world if (!world.getLwocRoot().contains(xyz)) return null; // needs growing world
...@@ -189,7 +202,7 @@ public class LwocOctree implements Serializable { ...@@ -189,7 +202,7 @@ public class LwocOctree implements Serializable {
return; // nothing to do return; // nothing to do
} else { } else {
for (LwocScene scene: pendingScenes) { for (LwocScene scene: pendingScenes) {
growXYZ(scene.getCameraXYZ()); growXYZ(scene.getCameraXYZ()); // will not grow in infinity direction
LwocOctree node= addScene( // should not be null LwocOctree node= addScene( // should not be null
scene, scene,
check_existed); check_existed);
...@@ -215,9 +228,9 @@ public class LwocOctree implements Serializable { ...@@ -215,9 +228,9 @@ 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];
growXYZ(corner_xyz); growXYZ(corner_xyz); // will not grow in infinity direction
corner_xyz[dm] -= 2*dims[dm]; corner_xyz[dm] -= 2*dims[dm];
growXYZ(corner_xyz); growXYZ(corner_xyz); // will not grow in infinity direction
corner_xyz[dm] += dims[dm]; corner_xyz[dm] += dims[dm];
} }
boolean ok= addMeshCenter( // should not be null boolean ok= addMeshCenter( // should not be null
...@@ -251,17 +264,9 @@ public class LwocOctree implements Serializable { ...@@ -251,17 +264,9 @@ public class LwocOctree implements Serializable {
/** /**
* 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 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
* triggers node split.
* @param max_cameras Maximasl number of scenes (camera positions) in a node. Larger
* number triggers node split.
* @param check_existed Filter identical meshes or scenes from corresponding lists. * @param check_existed Filter identical meshes or scenes from corresponding lists.
*/ */
public static void tendPendingLeafNodes( public static void tendPendingLeafNodes(
final double min_hsize,
final int max_mesh_centers,
final int max_cameras, // scenes
final boolean check_existed) { final boolean check_existed) {
// remove any possible duplicates // remove any possible duplicates
final ArrayList<LwocOctree> pendingLeafNodesFiltered = new ArrayList<LwocOctree>(); final ArrayList<LwocOctree> pendingLeafNodesFiltered = new ArrayList<LwocOctree>();
...@@ -270,6 +275,11 @@ public class LwocOctree implements Serializable { ...@@ -270,6 +275,11 @@ public class LwocOctree implements Serializable {
pendingLeafNodesFiltered.add(node); pendingLeafNodesFiltered.add(node);
} }
} }
if (!pendingLeafNodesFiltered.isEmpty()) {
LwocWorld world = pendingLeafNodesFiltered.get(0).world;
final double min_hsize = world.getMinHsize();
final int max_mesh_centers = world.getMaxMeshCenters();
final int max_cameras = world.getMaxCameras();
// run splitting multithreaded // run splitting multithreaded
final Thread[] threads = MultiThreading.newThreadArray(); final Thread[] threads = MultiThreading.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0);
...@@ -291,6 +301,7 @@ public class LwocOctree implements Serializable { ...@@ -291,6 +301,7 @@ public class LwocOctree implements Serializable {
} }
MultiThreading.startAndJoin(threads); MultiThreading.startAndJoin(threads);
} }
}
/** /**
* Split recursively the octree node (and its children if needed) to keep number of scenes and * Split recursively the octree node (and its children if needed) to keep number of scenes and
...@@ -388,10 +399,12 @@ public class LwocOctree implements Serializable { ...@@ -388,10 +399,12 @@ public class LwocOctree implements Serializable {
/** /**
* Grow the world to include specified point Will repeat growing twice (in each direction) * Grow the world to include specified point Will repeat growing twice (in each direction)
* 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
* Will mark infinity directions (inside LwocOctree constructor), so contains() will return
* true when the world size is big enough.
* @param xyz The point to be included in the world. * @param xyz The point to be included in the world.
*/ */
public void growXYZ(double [] xyz) { public void growXYZ(double [] xyz) {
while (!world.lwoc_root.contains(xyz)) {// already fits, do not grow while (!world.lwoc_root.contains(xyz)) {// already fits, do not grow. Will obey infinity
// 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];
...@@ -405,7 +418,11 @@ public class LwocOctree implements Serializable { ...@@ -405,7 +418,11 @@ public class LwocOctree implements Serializable {
new_center[dm]= root_center[dm] - root_hsize; new_center[dm]= root_center[dm] - root_hsize;
} }
} }
LwocOctree new_root = new LwocOctree(world,null, new_center, world.lwoc_root.hsize * 2); LwocOctree new_root = new LwocOctree( // will mark infinities
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++) {
...@@ -413,7 +430,7 @@ public class LwocOctree implements Serializable { ...@@ -413,7 +430,7 @@ public class LwocOctree implements Serializable {
world.lwoc_root.parent = new_root; world.lwoc_root.parent = new_root;
new_root.children[ichild] = world.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( // will mark infinities
world, world,
new_root, new_root,
new double [] { new double [] {
...@@ -437,10 +454,10 @@ public class LwocOctree implements Serializable { ...@@ -437,10 +454,10 @@ 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) {
if (infinity == 0) { // this branch is just for performance, it may be removed
for (int dm = 0; dm < center.length; dm++) { for (int dm = 0; dm < center.length; dm++) {
if ((xyz[dm] - half_whd[dm]) >= (center[dm] + hsize)) { // semiinterval if ((xyz[dm] - half_whd[dm]) >= (center[dm] + hsize)) { // semiinterval
return false; return false;
...@@ -449,6 +466,16 @@ public class LwocOctree implements Serializable { ...@@ -449,6 +466,16 @@ public class LwocOctree implements Serializable {
return false; return false;
} }
} }
} else {
for (int dm = 0; dm < center.length; dm++) {
if (((xyz[dm] - half_whd[dm]) >= (center[dm] + hsize)) && (((infinity >> (2 * dm + 1)) & 1 ) == 0)) { // semiinterval
return false;
}
if (((xyz[dm] + half_whd[dm]) < (center[dm] - hsize)) && (((infinity >> (2 * dm)) & 1 ) == 0)) {
return false;
}
}
}
return true; return true;
} }
...@@ -457,9 +484,9 @@ public class LwocOctree implements Serializable { ...@@ -457,9 +484,9 @@ 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) {
if (infinity == 0) { // this branch is just for performance, it may be removed
for (int dm = 0; dm < center.length; dm++) { for (int dm = 0; dm < center.length; dm++) {
if (xyz[dm] < (center[dm] - hsize)) { // semi-interval if (xyz[dm] < (center[dm] - hsize)) { // semi-interval
return false; return false;
...@@ -469,6 +496,17 @@ public class LwocOctree implements Serializable { ...@@ -469,6 +496,17 @@ public class LwocOctree implements Serializable {
} }
} }
return true; return true;
} else {
for (int dm = 0; dm < center.length; dm++) {
if ((xyz[dm] < (center[dm] - hsize)) && (((infinity >> (2 * dm)) & 1 ) == 0)) { // semi-interval
return false;
}
if ((xyz[dm] >= (center[dm] + hsize)) && (((infinity >> (2 * dm + 1)) & 1 ) == 0)) {
return false;
}
}
return true;
}
} }
/** /**
...@@ -477,11 +515,10 @@ public class LwocOctree implements Serializable { ...@@ -477,11 +515,10 @@ 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) {
if (infinity == 0) { // this branch is just for performance, it may be removed
for (int dm = 0; dm < center.length; dm++) { for (int dm = 0; dm < center.length; dm++) {
if ((xyz[dm] - half_whd[dm]) < (center[dm] - hsize)) { // semiinterval if ((xyz[dm] - half_whd[dm]) < (center[dm] - hsize)) { // semiinterval
return false; return false;
...@@ -490,6 +527,16 @@ public class LwocOctree implements Serializable { ...@@ -490,6 +527,16 @@ public class LwocOctree implements Serializable {
return false; return false;
} }
} }
} else {
for (int dm = 0; dm < center.length; dm++) {
if (((xyz[dm] - half_whd[dm]) < (center[dm] - hsize)) && (((infinity >> (2 * dm)) & 1 ) == 0)){ // semiinterval
return false;
}
if (((xyz[dm] + half_whd[dm]) >= (center[dm] + hsize)) && (((infinity >> (2 * dm + 1)) & 1 ) == 0)){
return false;
}
}
}
return true; return true;
} }
...@@ -500,7 +547,7 @@ public class LwocOctree implements Serializable { ...@@ -500,7 +547,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 boolean addMeshCenter( // returns 0 and adds to pendingMeshes if needs growing public boolean addMeshCenter( // returns 0 and adds to pendingMeshes if needs growing. Obeys infinity
LwocMesh mesh, LwocMesh mesh,
boolean check_existed boolean check_existed
) { ) {
...@@ -554,7 +601,7 @@ public class LwocOctree implements Serializable { ...@@ -554,7 +601,7 @@ public class LwocOctree implements Serializable {
public int addMesh( public int addMesh(
LwocMesh mesh, LwocMesh mesh,
boolean check_existed) { boolean check_existed) {
if (!intersects( if (!intersects( // supports infinity
mesh.getCenter(), mesh.getCenter(),
mesh.getDims())) { mesh.getDims())) {
return 0; return 0;
...@@ -605,7 +652,7 @@ public class LwocOctree implements Serializable { ...@@ -605,7 +652,7 @@ public class LwocOctree implements Serializable {
} }
/** /**
* Restore pointers to .parent and .world * Restore pointers to .parent and .world after de-serialization
* @param world * @param world
* @param parent * @param parent
*/ */
......
...@@ -35,11 +35,10 @@ public class LwocWorld implements Serializable { ...@@ -35,11 +35,10 @@ public class LwocWorld implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
static List<LwocWorld> lwoc_worlds; // static List<LwocWorld> lwoc_worlds; //
public final double max_hsize; // = 10000.0; // meter - do not grow more
public double min_hsize; // = 0.3; // meter - do not subdivide more 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_mesh_centers; // = 10; // maximal number of meshes in a leaf;
public int max_cameras; // = 10; // maximal number of cameras 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 LwocOctree lwoc_root; // = null;
public double [] atr; // = null; // Azimuth, tilt, roll - may be used to merge public double [] atr; // = null; // Azimuth, tilt, roll - may be used to merge
public double [] xyz; // = null; // this world offset (before rotation) or public double [] xyz; // = null; // this world offset (before rotation) or
...@@ -53,7 +52,7 @@ public class LwocWorld implements Serializable { ...@@ -53,7 +52,7 @@ public class LwocWorld implements Serializable {
double [] atr, double [] atr,
double [] xyz) { double [] xyz) {
setMinHsize (min_hsize); setMinHsize (min_hsize);
setMaxHsize (max_hsize); this.max_hsize = max_hsize; // it is final, only can and has to be set in the constructor
setMaxMeshCenters(max_mesh_centers); setMaxMeshCenters(max_mesh_centers);
setMaxCameras (max_cameras); setMaxCameras (max_cameras);
setLwocRoot (lwoc_root); setLwocRoot (lwoc_root);
...@@ -69,7 +68,6 @@ public class LwocWorld implements Serializable { ...@@ -69,7 +68,6 @@ public class LwocWorld implements Serializable {
public double [] getXYZ() {return xyz;} public double [] getXYZ() {return xyz;}
public void setMinHsize (double min_hsize) {this.min_hsize = min_hsize;} 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 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 setMaxCameras (int max_cameras) {this.max_cameras = max_cameras;}
public void setLwocRoot (LwocOctree lwoc_root) {this.lwoc_root = lwoc_root;} public void setLwocRoot (LwocOctree lwoc_root) {this.lwoc_root = lwoc_root;}
......
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