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;
public class LwocOctree implements Serializable {
private static final long serialVersionUID = 1L;
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<LwocMesh> pendingMeshes; // synchronized - add not-yet-added meshes pending growing world
static List<LwocOctree> pendingLeafNodes;// synchronized - leaf nodes needed to be split
// static List<LwocWorld> lwoc_worlds; //
int id; // assign unique ID
transient LwocWorld world;
transient LwocOctree parent;
......@@ -51,6 +48,7 @@ public class LwocOctree implements Serializable {
LwocLeaf leaf; //
double [] center; // x-center, y-center, z-center
double hsize;
int infinity = 0;
public static void addPendingScene(LwocScene scene) {
synchronized(pendingScenes) {
......@@ -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 parent Parent node
* @param parent_in Parent node
* @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
*/
public LwocOctree (
LwocWorld lwocWorld,
LwocOctree parent,
LwocOctree parent_in,
double [] xyz,
double hsize) {
this.parent = parent;
this.hsize = hsize;
double h_size) {
world = lwocWorld;
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 {
* @return Octree node that includes the point or null if the point
* 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
double [] xyz) { // thread safe
if (!world.getLwocRoot().contains(xyz)) return null; // needs growing world
......@@ -189,7 +202,7 @@ public class LwocOctree implements Serializable {
return; // nothing to do
} else {
for (LwocScene scene: pendingScenes) {
growXYZ(scene.getCameraXYZ());
growXYZ(scene.getCameraXYZ()); // will not grow in infinity direction
LwocOctree node= addScene( // should not be null
scene,
check_existed);
......@@ -215,9 +228,9 @@ public class LwocOctree implements Serializable {
double [] corner_xyz = center.clone();
for (int dm = 0; dm < center.length; dm++) {
corner_xyz[dm] += dims[dm];
growXYZ(corner_xyz);
growXYZ(corner_xyz); // will not grow in infinity direction
corner_xyz[dm] -= 2*dims[dm];
growXYZ(corner_xyz);
growXYZ(corner_xyz); // will not grow in infinity direction
corner_xyz[dm] += dims[dm];
}
boolean ok= addMeshCenter( // should not be null
......@@ -251,17 +264,9 @@ public class LwocOctree implements Serializable {
/**
* Recursively (if needed) splits octree nodes to reduce number of scenes/cameras
* 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.
*/
public static void tendPendingLeafNodes(
final double min_hsize,
final int max_mesh_centers,
final int max_cameras, // scenes
final boolean check_existed) {
// remove any possible duplicates
final ArrayList<LwocOctree> pendingLeafNodesFiltered = new ArrayList<LwocOctree>();
......@@ -270,6 +275,11 @@ public class LwocOctree implements Serializable {
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
final Thread[] threads = MultiThreading.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
......@@ -291,6 +301,7 @@ public class LwocOctree implements Serializable {
}
MultiThreading.startAndJoin(threads);
}
}
/**
* 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 {
/**
* 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
* 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.
*/
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
int indx=0; //direction to grow
double [] new_center = new double[3];
......@@ -405,7 +418,11 @@ public class LwocOctree implements Serializable {
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];
int child = (~indx ) & (NUM_CHILDREN -1); // opposite direction, from new root to old root
for (int ichild = 0; ichild < NUM_CHILDREN; ichild++) {
......@@ -413,7 +430,7 @@ public class LwocOctree implements Serializable {
world.lwoc_root.parent = new_root;
new_root.children[ichild] = world.lwoc_root;
} else { // create empty leaf nodes
new_root.children[ichild] = new LwocOctree(
new_root.children[ichild] = new LwocOctree( // will mark infinities
world,
new_root,
new double [] {
......@@ -437,10 +454,10 @@ public class LwocOctree implements Serializable {
* @param half_whd half width(x), height(y) and depth(z)
* @return True if it intersects
*/
//FIXME: obey border (on the edges of max hsize of the root) nodes
public boolean intersects (
double [] xyz,
double [] half_whd) {
if (infinity == 0) { // this branch is just for performance, it may be removed
for (int dm = 0; dm < center.length; dm++) {
if ((xyz[dm] - half_whd[dm]) >= (center[dm] + hsize)) { // semiinterval
return false;
......@@ -449,6 +466,16 @@ public class LwocOctree implements Serializable {
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;
}
......@@ -457,9 +484,9 @@ public class LwocOctree implements Serializable {
* @param xyz point
* @return True if it intersects
*/
//FIXME: obey border (on the edges of max hsize of the root) nodes
public boolean contains (
double [] xyz) {
if (infinity == 0) { // this branch is just for performance, it may be removed
for (int dm = 0; dm < center.length; dm++) {
if (xyz[dm] < (center[dm] - hsize)) { // semi-interval
return false;
......@@ -469,6 +496,17 @@ public class LwocOctree implements Serializable {
}
}
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 {
* @param half_whd half width(x), height(y) and depth(z)
* @return True if it intersects
*/
//FIXME: obey border (on the edges of max hsize of the root) nodes
public boolean contains (
double [] xyz,
double [] half_whd) {
if (infinity == 0) { // this branch is just for performance, it may be removed
for (int dm = 0; dm < center.length; dm++) {
if ((xyz[dm] - half_whd[dm]) < (center[dm] - hsize)) { // semiinterval
return false;
......@@ -490,6 +527,16 @@ public class LwocOctree implements Serializable {
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;
}
......@@ -500,7 +547,7 @@ public class LwocOctree implements Serializable {
* @param check_existed Add only if the same mesh did not exist
* @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,
boolean check_existed
) {
......@@ -554,7 +601,7 @@ public class LwocOctree implements Serializable {
public int addMesh(
LwocMesh mesh,
boolean check_existed) {
if (!intersects(
if (!intersects( // supports infinity
mesh.getCenter(),
mesh.getDims())) {
return 0;
......@@ -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 parent
*/
......
......@@ -35,11 +35,10 @@ public class LwocWorld implements Serializable {
private static final long serialVersionUID = 1L;
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 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
......@@ -53,7 +52,7 @@ public class LwocWorld implements Serializable {
double [] atr,
double [] xyz) {
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);
setMaxCameras (max_cameras);
setLwocRoot (lwoc_root);
......@@ -69,7 +68,6 @@ public class LwocWorld implements Serializable {
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;}
......
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