00001
00028 #ifndef KDTREE_H_
00029 #define KDTREE_H_
00030
00031 #include<vector>
00032 #include<limits>
00033 #include"Point3.h"
00034 #include"NodeWrapper.h"
00035 #include"KdCell.h"
00036 #include"PotentialCluster.h"
00037
00038 using namespace std;
00039
00040 class KdTree: public KdCell {
00041 private:
00042 double minLightIntensity;
00043 double maxConeCosine;
00044 Point3 minHalfSize;
00045
00046 KdTree():KdCell(), minHalfSize(std::numeric_limits<double>::max()){
00047 minLightIntensity=std::numeric_limits<double>::max();
00048 maxConeCosine = -1.0f;
00049 }
00050 KdTree(int st, double sv):KdCell(st,sv), minHalfSize(0){
00051 minLightIntensity=0;
00052 maxConeCosine = -1.0f;
00053 }
00054
00055 public:
00059 static KdTree * createTree(vector<NodeWrapper*> & inPoints){
00060 KdTree * factory = new KdTree();
00061 KdTree * root = (KdTree *) KdTree::subDivide(inPoints, 0, inPoints.size(), NULL, *factory);
00062 delete factory;
00063 return root;
00064 }
00068 virtual KdCell *createNewBlankCell(int inSplitType, double inSplitValue) {
00069
00070 return new KdTree(inSplitType, inSplitValue);
00071 }
00075 static void getAll(KdCell & tree, vector<NodeWrapper * > & allLeaves){
00076 tree.getAll(allLeaves);
00077 }
00081 bool notifyPointAdded(NodeWrapper & nw, bool inChange){
00082 if(inChange){
00083 double b3 = nw.getLight().getScalarTotalIntensity();
00084 minLightIntensity = (minLightIntensity >= b3) ? b3 : minLightIntensity;
00085 maxConeCosine = (maxConeCosine >= nw.getConeCosine()) ? maxConeCosine : nw.getConeCosine();
00086 double b2 = nw.getHalfSizeX();
00087 double minHalfSizeX = (minHalfSizeX >= b2) ? b2 : minHalfSizeX;
00088 double b1 = nw.getHalfSizeY();
00089 double minHalfSizeY = (minHalfSizeY >= b1) ? b1 : minHalfSizeY;
00090 double b = nw.getHalfSizeZ();
00091 double minHalfSizeZ = (minHalfSizeZ >= b) ? b : minHalfSizeZ;
00092 minHalfSize.set(minHalfSizeX,minHalfSizeY,minHalfSizeZ);
00093
00094 }
00095 else{
00096 double newIntensity = nw.getLight().getScalarTotalIntensity();
00097 if(minLightIntensity>newIntensity){
00098 minLightIntensity = newIntensity;
00099 inChange=true;
00100 }
00101 if(maxConeCosine < nw.getConeCosine()){
00102 maxConeCosine= nw.getConeCosine();
00103 inChange=true;
00104 }
00105 inChange |= minHalfSize.setIfMin(nw.getHalfSizeX(),nw.getHalfSizeY(),nw.getHalfSizeZ());
00106 }
00107 return inChange;
00108 }
00112 NodeWrapper *findBestMatch(NodeWrapper &inLight) {
00113
00114
00115 PotentialCluster cluster(inLight);
00116 if (splitType == LEAF) {
00117 findNearestRecursive(cluster);
00118 } else if (splitType == KdCell::SPLIT_X) {
00119 recurse(cluster, inLight.getLocationX());
00120 } else if (splitType == KdCell::SPLIT_Y) {
00121 recurse(cluster, inLight.getLocationY());
00122 } else if (splitType == KdCell::SPLIT_Z) {
00123 recurse(cluster, inLight.getLocationZ());
00124 } else {
00125 assert(false&& "Invalid split type!");
00126 }
00127 NodeWrapper * res = cluster.closest;
00128
00129
00130
00131
00132 return res;
00133 }
00134
00135 void findNearestRecursive(PotentialCluster &potentialCluster) {
00136
00137
00138 if (couldBeCloser(potentialCluster)==false) {
00139 return;
00140 }
00141 const NodeWrapper &from = potentialCluster.original;
00142 if (splitType == KdCell::LEAF) {
00143
00144 for(int i=0;i<KdCell::MAX_POINTS_IN_CELL;i++){
00145 if(pointList[i]!=NULL && pointList[i]->equals(potentialCluster.original)==false){
00146 double size = NodeWrapper::potentialClusterSize(from, *(pointList[i]));
00147 if (size < potentialCluster.clusterSize) {
00148
00149 potentialCluster.closest = pointList[i];
00150 potentialCluster.clusterSize = size;
00151 }
00152
00153 }
00154 }
00155 } else if (splitType == KdCell::SPLIT_X) {
00156 recurse(potentialCluster, from.getLocationX());
00157 } else if (splitType == KdCell::SPLIT_Y) {
00158 recurse(potentialCluster, from.getLocationY());
00159 } else if (splitType == KdCell::SPLIT_Z) {
00160 recurse(potentialCluster, from.getLocationZ());
00161 } else {
00162 assert(false&&"Invalid split type in find nearest recursive");
00163 }
00164 }
00165
00166 void recurse(PotentialCluster &potentialCluster, double which) {
00167
00168
00169
00170 if (which <= splitValue) {
00171 if(leftChild!=NULL &&
00172 leftChild->removeFromTree==false)
00173 ((KdTree*) leftChild)->findNearestRecursive(potentialCluster);
00174 if(rightChild!=NULL && rightChild->removeFromTree==false)
00175 ((KdTree*) rightChild)->findNearestRecursive(potentialCluster);
00176 } else {
00177 if(rightChild!=NULL && rightChild->removeFromTree==false)
00178 ((KdTree*) rightChild)->findNearestRecursive(potentialCluster);
00179 if(leftChild!=NULL && leftChild->removeFromTree==false)
00180 ((KdTree*) leftChild)->findNearestRecursive(potentialCluster);
00181 }
00182 }
00183
00192 bool couldBeCloser(PotentialCluster &outCluster) {
00193
00194 const NodeWrapper &from = outCluster.original;
00195
00196 double a2 = min.getX() - from.getLocationX() >= from.getLocationX() - max.getX() ? min.getX() - from.getLocationX() : from.getLocationX() - max.getX();
00197
00198 double dx = (a2 >= 0) ? a2 : 0;
00199 double a1 = (min.getY() - from.getLocationY() >= from.getLocationY()- max.getY()) ? min.getY() - from.getLocationY() : from.getLocationY() - max.getY();
00200 double dy = a1 >= 0 ? a1 : 0;
00201 double a = (min.getZ() - from.getLocationZ() >= from.getLocationZ() - max.getZ()) ? min.getZ() - from.getLocationZ() : from.getLocationZ() - max.getZ();
00202 double dz = a >= 0 ? a : 0;
00203
00204
00205
00206 dx += from.getHalfSizeX() + minHalfSize.getX();
00207 dy += from.getHalfSizeY() + minHalfSize.getY();
00208 dz += from.getHalfSizeZ() + minHalfSize.getZ();
00209
00210 double coneCos = (maxConeCosine >= from.getConeCosine()) ? from.getConeCosine() : maxConeCosine;
00211
00212 double intensity = minLightIntensity + from.getLight().getScalarTotalIntensity();
00213 Point3 diff(dx,dy,dz);
00214
00215 double testSize = NodeWrapper::clusterSizeMetric(diff, coneCos, intensity);
00216
00217
00218
00219 return (outCluster.clusterSize >= 0.9999 * testSize);
00220 }
00221
00222
00223
00224 private:
00225
00226 };
00227
00228 #endif