[geos-commits] [SCM] GEOS branch main updated. d107fccbdffb127af3b571a8f238e700a725984b
git at osgeo.org
git at osgeo.org
Thu Sep 23 17:19:42 PDT 2021
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GEOS".
The branch, main has been updated
via d107fccbdffb127af3b571a8f238e700a725984b (commit)
via c359daa5fa61685be167f6192d84f3f825835bf9 (commit)
from 32602283fbaf0378f263045e342bd699bb14c735 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d107fccbdffb127af3b571a8f238e700a725984b
Merge: 3260228 c359daa
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date: Thu Sep 23 17:18:55 2021 -0700
Merge branch 'rouault-fix_queryNode_stack_overflow' into main
commit c359daa5fa61685be167f6192d84f3f825835bf9
Author: Even Rouault <even.rouault at spatialys.com>
Date: Fri Sep 24 01:22:28 2021 +0200
KdTree::queryNode(): rewrite it to avoid blowing up the stack
Fixes https://github.com/qgis/QGIS/issues/45226
While we are it, also avoid recursive formulation for queryNodePoint()
diff --git a/src/index/kdtree/KdTree.cpp b/src/index/kdtree/KdTree.cpp
index f22cba6..a0c2dfb 100644
--- a/src/index/kdtree/KdTree.cpp
+++ b/src/index/kdtree/KdTree.cpp
@@ -17,6 +17,7 @@
#include <vector>
#include <algorithm>
+#include <stack>
using namespace geos::geom;
@@ -152,34 +153,76 @@ KdTree::insertExact(const geom::Coordinate& p, void* data)
void
KdTree::queryNode(KdNode* currentNode, const geom::Envelope& queryEnv, bool odd, KdNodeVisitor& visitor)
{
- if (currentNode == nullptr)
- return;
-
- double min;
- double max;
- double discriminant;
-
- if (odd) {
- min = queryEnv.getMinX();
- max = queryEnv.getMaxX();
- discriminant = currentNode->getX();
- } else {
- min = queryEnv.getMinY();
- max = queryEnv.getMaxY();
- discriminant = currentNode->getY();
- }
- bool searchLeft = min < discriminant;
- bool searchRight = discriminant <= max;
-
- // search is computed via in-order traversal
- if (searchLeft) {
- queryNode(currentNode->getLeft(), queryEnv, !odd, visitor);
- }
- if (queryEnv.contains(currentNode->getCoordinate())) {
- visitor.visit(currentNode);
- }
- if (searchRight) {
- queryNode(currentNode->getRight(), queryEnv, !odd, visitor);
+ // Non recursive formulation of in-order traversal from
+ // http://web.cs.wpi.edu/~cs2005/common/iterative.inorder
+ // Otherwise we may blow up the stack
+ // See https://github.com/qgis/QGIS/issues/45226
+ typedef std::pair<KdNode*, bool> Pair;
+ std::stack<Pair> activeNodes;
+ while(true)
+ {
+ if( currentNode != nullptr )
+ {
+ double min;
+ double discriminant;
+
+ if (odd) {
+ min = queryEnv.getMinX();
+ discriminant = currentNode->getX();
+ } else {
+ min = queryEnv.getMinY();
+ discriminant = currentNode->getY();
+ }
+ bool searchLeft = min < discriminant;
+
+ activeNodes.emplace(Pair(currentNode, odd));
+
+ // search is computed via in-order traversal
+ KdNode* leftNode = nullptr;
+ if (searchLeft ) {
+ leftNode = currentNode->getLeft();
+ }
+ if( leftNode ) {
+ currentNode = leftNode;
+ odd = !odd;
+ } else {
+ currentNode = nullptr;
+ }
+ }
+ else if( !activeNodes.empty() )
+ {
+ currentNode = activeNodes.top().first;
+ odd = activeNodes.top().second;
+ activeNodes.pop();
+
+ if (queryEnv.contains(currentNode->getCoordinate())) {
+ visitor.visit(currentNode);
+ }
+
+ double max;
+ double discriminant;
+
+ if (odd) {
+ max = queryEnv.getMaxX();
+ discriminant = currentNode->getX();
+ } else {
+ max = queryEnv.getMaxY();
+ discriminant = currentNode->getY();
+ }
+ bool searchRight = discriminant <= max;
+
+ if (searchRight) {
+ currentNode = currentNode->getRight();
+ if( currentNode )
+ odd = !odd;
+ } else {
+ currentNode = nullptr;
+ }
+ }
+ else
+ {
+ break;
+ }
}
}
@@ -187,29 +230,32 @@ KdTree::queryNode(KdNode* currentNode, const geom::Envelope& queryEnv, bool odd,
KdNode*
KdTree::queryNodePoint(KdNode* currentNode, const geom::Coordinate& queryPt, bool odd)
{
- if (currentNode == nullptr)
- return nullptr;
- if (currentNode->getCoordinate().equals2D(queryPt))
- return currentNode;
-
- double ord;
- double discriminant;
- if (odd) {
- ord = queryPt.x;
- discriminant = currentNode->getX();
- }
- else {
- ord = queryPt.y;
- discriminant = currentNode->getY();
- }
+ while (currentNode != nullptr)
+ {
+ if (currentNode->getCoordinate().equals2D(queryPt))
+ return currentNode;
- bool searchLeft = (ord < discriminant);
- if (searchLeft) {
- return queryNodePoint(currentNode->getLeft(), queryPt, !odd);
- }
- else {
- return queryNodePoint(currentNode->getRight(), queryPt, !odd);
+ double ord;
+ double discriminant;
+ if (odd) {
+ ord = queryPt.x;
+ discriminant = currentNode->getX();
+ }
+ else {
+ ord = queryPt.y;
+ discriminant = currentNode->getY();
+ }
+
+ bool searchLeft = (ord < discriminant);
+ odd = !odd;
+ if (searchLeft) {
+ currentNode = currentNode->getLeft();
+ }
+ else {
+ currentNode = currentNode->getRight();
+ }
}
+ return nullptr;
}
-----------------------------------------------------------------------
Summary of changes:
src/index/kdtree/KdTree.cpp | 144 +++++++++++++++++++++++++++++---------------
1 file changed, 95 insertions(+), 49 deletions(-)
hooks/post-receive
--
GEOS
More information about the geos-commits
mailing list