17#include <geos/index/strtree/TemplateSTRNode.h>
18#include <geos/index/strtree/TemplateSTRNodePair.h>
19#include <geos/util/IllegalArgumentException.h>
28template<
typename ItemType,
typename BoundsType,
typename ItemDistance>
29class TemplateSTRtreeDistance {
30 using Node = TemplateSTRNode<ItemType, BoundsType>;
31 using NodePair = TemplateSTRNodePair<ItemType, BoundsType, ItemDistance>;
32 using ItemPair = std::pair<ItemType, ItemType>;
34 struct PairQueueCompare {
35 bool operator()(
const NodePair& a,
const NodePair& b) {
36 return a.getDistance() > b.getDistance();
40 using PairQueue = std::priority_queue<NodePair, std::vector<NodePair>, PairQueueCompare>;
43 explicit TemplateSTRtreeDistance(ItemDistance&
id) : m_id(id) {}
45 ItemPair nearestNeighbour(
const Node& root1,
const Node& root2) {
46 NodePair initPair(root1, root2, m_id);
47 return nearestNeighbour(initPair);
50 ItemPair nearestNeighbour(NodePair& initPair) {
51 return nearestNeighbour(initPair, DoubleInfinity);
56 ItemPair nearestNeighbour(NodePair& initPair,
double maxDistance) {
57 double distanceLowerBound = maxDistance;
58 std::unique_ptr<NodePair> minPair;
63 while (!priQ.empty() && distanceLowerBound > 0) {
64 NodePair pair = priQ.top();
66 double currentDistance = pair.getDistance();
75 if (minPair && currentDistance >= distanceLowerBound) {
86 if (pair.isLeaves()) {
87 distanceLowerBound = currentDistance;
91 minPair = detail::make_unique<NodePair>(pair);
99 expandToQueue(pair, priQ, distanceLowerBound);
104 throw util::GEOSException(
"Error computing nearest neighbor");
107 return minPair->getItems();
110 void expandToQueue(
const NodePair& pair, PairQueue& priQ,
double minDistance) {
111 const Node& node1 = pair.getFirst();
112 const Node& node2 = pair.getSecond();
114 bool isComp1 = node1.isComposite();
115 bool isComp2 = node2.isComposite();
122 if (isComp1 && isComp2) {
123 if (node1.getSize() > node2.getSize()) {
124 expand(node1, node2,
false, priQ, minDistance);
127 expand(node2, node1,
true, priQ, minDistance);
130 }
else if (isComp1) {
131 expand(node1, node2,
false, priQ, minDistance);
133 }
else if (isComp2) {
134 expand(node2, node1,
true, priQ, minDistance);
138 throw util::IllegalArgumentException(
"neither boundable is composite");
142 void expand(
const Node &nodeComposite,
const Node &nodeOther,
bool isFlipped, PairQueue& priQ,
143 double minDistance) {
144 for (
const auto *child = nodeComposite.beginChildren();
145 child < nodeComposite.endChildren(); ++child) {
146 NodePair sp = isFlipped ? NodePair(nodeOther, *child, m_id) : NodePair(*child, nodeOther, m_id);
149 if (minDistance == DoubleInfinity || sp.getDistance() < minDistance) {
Basic namespace for all GEOS functionalities.
Definition: geos.h:39