17#include <geos/constants.h>
18#include <geos/index/strtree/TemplateSTRNode.h>
19#include <geos/index/strtree/TemplateSTRNodePair.h>
20#include <geos/util/IllegalArgumentException.h>
31template<
typename ItemType,
typename BoundsType,
typename ItemDistance>
32class TemplateSTRtreeDistance {
33 using Node = TemplateSTRNode<ItemType, BoundsType>;
34 using NodePair = TemplateSTRNodePair<ItemType, BoundsType, ItemDistance>;
35 using ItemPair = std::pair<ItemType, ItemType>;
37 struct PairQueueCompare {
38 bool operator()(
const NodePair& a,
const NodePair& b) {
39 return a.getDistance() > b.getDistance();
43 using PairQueue = std::priority_queue<NodePair, std::vector<NodePair>, PairQueueCompare>;
46 explicit TemplateSTRtreeDistance(ItemDistance&
id) : m_id(id) {}
48 ItemPair nearestNeighbour(
const Node& root1,
const Node& root2) {
49 NodePair initPair(root1, root2, m_id);
50 return nearestNeighbour(initPair);
53 ItemPair nearestNeighbour(NodePair& initPair) {
54 return nearestNeighbour(initPair, DoubleInfinity);
57 bool isWithinDistance(
const Node& root1,
const Node& root2,
double maxDistance) {
58 NodePair initPair(root1, root2, m_id);
59 return isWithinDistance(initPair, maxDistance);
64 ItemPair nearestNeighbour(NodePair& initPair,
double maxDistance) {
65 double distanceLowerBound = maxDistance;
66 std::unique_ptr<NodePair> minPair;
71 while (!priQ.empty() && distanceLowerBound > 0) {
72 NodePair pair = priQ.top();
74 double currentDistance = pair.getDistance();
83 if (minPair && currentDistance >= distanceLowerBound) {
94 if (pair.isLeaves()) {
95 distanceLowerBound = currentDistance;
99 minPair = detail::make_unique<NodePair>(pair);
107 expandToQueue(pair, priQ, distanceLowerBound);
112 throw util::GEOSException(
"Error computing nearest neighbor");
115 return minPair->getItems();
118 void expandToQueue(
const NodePair& pair, PairQueue& priQ,
double minDistance) {
119 const Node& node1 = pair.getFirst();
120 const Node& node2 = pair.getSecond();
122 bool isComp1 = node1.isComposite();
123 bool isComp2 = node2.isComposite();
130 if (isComp1 && isComp2) {
131 if (node1.getSize() > node2.getSize()) {
132 expand(node1, node2,
false, priQ, minDistance);
135 expand(node2, node1,
true, priQ, minDistance);
138 }
else if (isComp1) {
139 expand(node1, node2,
false, priQ, minDistance);
141 }
else if (isComp2) {
142 expand(node2, node1,
true, priQ, minDistance);
146 throw util::IllegalArgumentException(
"neither boundable is composite");
150 void expand(
const Node &nodeComposite,
const Node &nodeOther,
bool isFlipped, PairQueue& priQ,
151 double minDistance) {
152 for (
const auto *child = nodeComposite.beginChildren();
153 child < nodeComposite.endChildren(); ++child) {
154 NodePair sp = isFlipped ? NodePair(nodeOther, *child, m_id) : NodePair(*child, nodeOther, m_id);
157 if (minDistance == DoubleInfinity || sp.getDistance() < minDistance) {
163 bool isWithinDistance(
const NodePair& initPair,
double maxDistance) {
164 double distanceUpperBound = DoubleInfinity;
170 while (! priQ.empty()) {
172 NodePair pair = priQ.top();
173 double pairDistance = pair.getDistance();
182 if (pairDistance > maxDistance)
198 if (pair.maximumDistance() <= maxDistance)
205 if (pair.isLeaves()) {
207 distanceUpperBound = pairDistance;
212 if (distanceUpperBound <= maxDistance)
221 expandToQueue(pair, priQ, distanceUpperBound);
Basic namespace for all GEOS functionalities.
Definition geos.h:39