Ejemplo n.º 1
0
    void nearestNeighbour(KDNode<T> *node, KDNode<T> **currentBest, double &currentBestDistance, const KDNode<T> *newNode) {
        if(node == NULL) {
            return;
        } else {
            double sqDistance = node->sqDistance(newNode);
            if(sqDistance < currentBestDistance) {
                (*currentBest) = node;
                currentBestDistance = sqDistance;
            }

            BinaryDecision binaryDecision = node->getNextDirection(newNode);

            T newNodeSplitData = (*newNode).data[node->getSplittingAxis()];
            T nodeSplitData = node->getSplittingValue();
            if(binaryDecision == LEFT) {
                if(newNodeSplitData - currentBestDistance <= nodeSplitData) {
                    nearestNeighbour(node->left, currentBest, currentBestDistance, newNode);
                }

                if(newNodeSplitData + currentBestDistance > nodeSplitData) {
                    nearestNeighbour(node->right, currentBest, currentBestDistance, newNode);
                }

            } else {
                if(newNodeSplitData + currentBestDistance > nodeSplitData) {
                    nearestNeighbour(node->right, currentBest, currentBestDistance, newNode);
                }

                if(newNodeSplitData - currentBestDistance <= nodeSplitData) {
                    nearestNeighbour(node->left, currentBest, currentBestDistance, newNode);
                }
            }
        }
    }
Ejemplo n.º 2
0
const KDTree::TreeNode* KDTree::nearestNeighbour(const unode& root, const float lon, const float lat) {

    const TreeNode * nearLeaf = firstGuess(root, lon, lat);

    float currBest = Util::getDistance(lat, lon, nearLeaf->lat, nearLeaf->lon);

    const TreeNode * currentLeaf = nearLeaf;
    const TreeNode * nearestLeaf = nearLeaf;

    while (currentLeaf) {
        float dist = Util::getDistance(lat, lon, currentLeaf->lat, currentLeaf->lon);

        if(dist < currBest) {
            currBest = dist;
            nearestLeaf = currentLeaf;
        }

        bool cross;
        if(currentLeaf->xsection) {
            cross = Util::getDistance(lat, lon, lat, currentLeaf->lon) < currBest;
        } else {
            cross = Util::getDistance(lat, lon, currentLeaf->lat, lon) < currBest;
        }

        if(cross) {
            if(currentLeaf->left.get() == nearLeaf) {
                nearLeaf = NULL;
                if(currentLeaf->right) nearLeaf = nearestNeighbour( currentLeaf->right, lon, lat);
            } else {
                nearLeaf = NULL;
                if(currentLeaf->left) nearLeaf = nearestNeighbour(currentLeaf->left, lon, lat);
            }

            if(nearLeaf) {
                float dist = Util::getDistance(lat, lon, nearLeaf->lat, nearLeaf->lon);
                if(dist < currBest) {
                    currBest = dist;
                    nearestLeaf = nearLeaf;
                }
            }
        }

        nearLeaf = currentLeaf;
        if(currentLeaf == root.get()) {
            currentLeaf = NULL;
        } else {
            currentLeaf = currentLeaf->parent;
        }
    }

    return nearestLeaf;
}
Ejemplo n.º 3
0
void KDTree::getNearestNeighbour(const File& iTo, vec2Int& iI, vec2Int& iJ) const {

    vec2 olats = iTo.getLats();
    vec2 olons = iTo.getLons();
    size_t nLon = iTo.getNumLon();
    size_t nLat = iTo.getNumLat();

    iI.resize(nLat);
    iJ.resize(nLat);

    if(!mRoot) {
        for(size_t i = 0; i < nLat; ++i) {
            iI[i].resize(nLon, Util::MV);
            iJ[i].resize(nLon, Util::MV);
        }
        return;
    }

    const TreeNode * nearest;

    for(size_t i = 0; i < nLat; ++i) {
        iI[i].resize(nLon, Util::MV);
        iJ[i].resize(nLon, Util::MV);
    }
    #pragma omp parallel for private(nearest)
    for(size_t i = 0; i < nLat; ++i) {
        for(size_t j = 0; j < nLon; ++j) {
            if(Util::isValid(olats[i][j]) && Util::isValid(olons[i][j])) {
                // Find the nearest neighbour from input grid (ii, jj)
                nearest = nearestNeighbour(mRoot, olons[i][j], olats[i][j]);
                iI[i][j] = nearest->ipos;
                iJ[i][j] = nearest->jpos;
            }
        }
    }
}
Ejemplo n.º 4
0
std::vector<Location> NeighbourhoodElevation::selectCore(const Input* iInput, const Location& iLocation) const {
   // Get the nearest neighbour, in case we need it
   std::vector<Location> temp;
   iInput->getSurroundingLocations(iLocation, temp);
   std::vector<Location> nearestNeighbour(1,temp[0]);

   float thisElev = iLocation.getElev();
   // Cannot downscale if we do not have elevation information
   if(!Global::isValid(thisElev)) {
      return nearestNeighbour;
   }

   // Check if the nearest neighbour is close enough in elevation
   float elevNearestNeighbour = nearestNeighbour[0].getElev();
   if(!Global::isValid(elevNearestNeighbour) || fabs(elevNearestNeighbour - thisElev) < mMinElevDiff) {
      // The true nearest neighbour is close enough in elevation to the desired point.
      return nearestNeighbour;
   }

   // Get a neighbourhood of locations
   std::vector<Location> locations;
   if(Global::isValid(mNum))
      iInput->getSurroundingLocations(iLocation, locations, mNum);
   else if(Global::isValid(mSearchRadius))
      iInput->getSurroundingLocationsByRadius(iLocation, locations, mSearchRadius);
   else
      locations = iInput->getLocations();

   // Check that there are locations within the search radius
   if(locations.size() == 0) {
      return nearestNeighbour;
   }

   // Compute gradient at desired point
   float thisGradX = iLocation.getGradientX();
   float thisGradY = iLocation.getGradientY();

   std::vector<std::pair<int,float> > values; // location index, factor
   for(int i = 0; i < locations.size(); i++) {
      // Compute gradient factor
      float gradientFactor = 0;
      if(mGradientWeight > 0) {
         float gradX       = locations[i].getGradientX();
         float gradY       = locations[i].getGradientY();
         if(Global::isValid(gradX) && Global::isValid(gradY)) {
            float lenGrad     = sqrt(gradX*gradX + gradY*gradY + 1);
            float lenThisGrad = sqrt(thisGradX*thisGradX + thisGradY*thisGradY + 1);
            float cosAngle    = (gradX*thisGradX + gradY*thisGradY + 1) / lenGrad / lenThisGrad;
            gradientFactor    = fabs(1 - cosAngle);
         }
         else {
            gradientFactor = Global::MV;
         }
      }

      // Compute distance factor
      float distanceFactor = 0;
      if(mDistanceWeight > 0) {
         distanceFactor = iLocation.getDistance(locations[i]);
      }

      // Compute elevation factor
      float elevationFactor = 0;
      if(mElevationWeight > 0) {
         float elev = locations[i].getElev();
         if(Global::isValid(elev))
            elevationFactor = fabs(elev - thisElev);
         else
            elevationFactor = Global::MV;
      }

      // Compute total factor
      if(Global::isValid(distanceFactor) && Global::isValid(gradientFactor) && Global::isValid(elevationFactor)) {
         float totalFactor = gradientFactor*mGradientWeight + distanceFactor*mDistanceWeight + elevationFactor * mElevationWeight;
         values.push_back(std::pair<int,float>(i, totalFactor));
      }
   }
   if(values.size() > 0) {
      std::sort(values.begin(), values.end(), Global::sort_pair_second<int, float>());
      int N = std::min((int) values.size(), mNumBest);
      std::vector<Location> returnLocations(N);
      for(int i = 0; i < N; i++) {
         int index = values[i].first;
         returnLocations[i] = locations[index];
      }
      return returnLocations;
   }
   else {
      return nearestNeighbour;
   }
}
Ejemplo n.º 5
0
void KDTree::getNearestNeighbour(float iLat, float iLon, int& iI, int& iJ) const {
    const TreeNode * nearest = nearestNeighbour(mRoot, iLon, iLat);
    iI = nearest->ipos;
    iJ = nearest->jpos;
    return;
}