DYT/Tool/OpenSceneGraph-3.6.5/include/geos/index/kdtree/KdTree.h
2024-12-25 07:49:36 +08:00

192 lines
5.6 KiB
C++

/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* Copyright (C) 2020 Paul Ramsey <pramsey@cleverelephant.ca>
*
* This is free software; you can redistribute and/or modify it under
* the terms of the GNU Lesser General Public Licence as published
* by the Free Software Foundation.
* See the COPYING file for more information.
*
**********************************************************************/
#pragma once
#include <geos/export.h>
#include <geos/geom/Envelope.h>
#include <geos/index/kdtree/KdNodeVisitor.h>
#include <geos/index/kdtree/KdNode.h>
#include <memory>
#include <vector>
#include <string>
#include <deque>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class
#endif
namespace geos {
namespace index { // geos::index
namespace kdtree { // geos::index::kdtree
/**
* An implementation of a 2-D KD-Tree. KD-trees provide fast range searching on
* point data.
* <p>
* This implementation supports detecting and snapping points which are closer
* than a given distance tolerance.
* If the same point (up to tolerance) is inserted
* more than once, it is snapped to the existing node.
* In other words, if a point is inserted which lies within the tolerance of a node already in the index,
* it is snapped to that node.
* When a point is snapped to a node then a new node is not created but the count of the existing node
* is incremented.
* If more than one node in the tree is within tolerance of an inserted point,
* the closest and then lowest node is snapped to.
*
* @author David Skea
* @author Martin Davis
*/
class GEOS_DLL KdTree {
private:
std::deque<KdNode> nodeQue;
KdNode *root;
std::size_t numberOfNodes;
double tolerance;
KdNode* findBestMatchNode(const geom::Coordinate& p);
KdNode* insertExact(const geom::Coordinate& p, void* data);
void queryNode(KdNode* currentNode, const geom::Envelope& queryEnv, bool odd, KdNodeVisitor& visitor);
KdNode* queryNodePoint(KdNode* currentNode, const geom::Coordinate& queryPt, bool odd);
/**
* Create a node on a locally managed deque to allow easy
* disposal and hopefully faster allocation as well.
*/
KdNode* createNode(const geom::Coordinate& p, void* data);
/**
* BestMatchVisitor used to query the tree for a match
* within tolerance.
*/
class BestMatchVisitor : public KdNodeVisitor {
public:
BestMatchVisitor(const geom::Coordinate& p_p, double p_tolerance);
geom::Envelope queryEnvelope();
KdNode* getNode();
void visit(KdNode* node) override;
private:
// Members
double tolerance;
KdNode* matchNode;
double matchDist;
const geom::Coordinate& p;
// Declare type as noncopyable
BestMatchVisitor(const BestMatchVisitor& other);
BestMatchVisitor& operator=(const BestMatchVisitor& rhs);
};
/**
* AccumulatingVisitor used to query the tree and get list
* of matching nodes.
*/
class AccumulatingVisitor : public KdNodeVisitor {
public:
AccumulatingVisitor(std::vector<KdNode*>& p_nodeList) :
nodeList(p_nodeList) {};
void visit(KdNode* node) override { nodeList.push_back(node); }
private:
// Members
std::vector<KdNode*>& nodeList;
// Declare type as noncopyable
AccumulatingVisitor(const AccumulatingVisitor& other);
AccumulatingVisitor& operator=(const AccumulatingVisitor& rhs);
};
public:
/**
* Converts a collection of {@link KdNode}s to an vector of {@link geom::Coordinate}s.
*
* @param kdnodes a collection of nodes
* @return an vector of the coordinates represented by the nodes
*/
static std::unique_ptr<std::vector<geom::Coordinate>> toCoordinates(std::vector<KdNode*>& kdnodes);
/**
* Converts a collection of {@link KdNode}s
* to an vector of {@link geom::Coordinate}s,
* specifying whether repeated nodes should be represented
* by multiple coordinates.
*
* @param kdnodes a collection of nodes
* @param includeRepeated true if repeated nodes should
* be included multiple times
* @return an vector of the coordinates represented by the nodes
*/
static std::unique_ptr<std::vector<geom::Coordinate>> toCoordinates(std::vector<KdNode*>& kdnodes, bool includeRepeated);
KdTree() :
root(nullptr),
numberOfNodes(0),
tolerance(0.0)
{};
KdTree(double p_tolerance) :
root(nullptr),
numberOfNodes(0),
tolerance(p_tolerance)
{};
bool isEmpty() { return root == nullptr; }
/**
* Inserts a new point in the kd-tree.
*/
KdNode* insert(const geom::Coordinate& p);
KdNode* insert(const geom::Coordinate& p, void* data);
/**
* Performs a range search of the points in the index and visits all nodes found.
*/
void query(const geom::Envelope& queryEnv, KdNodeVisitor& visitor);
/**
* Performs a range search of the points in the index.
*/
std::unique_ptr<std::vector<KdNode*>> query(const geom::Envelope& queryEnv);
/**
* Performs a range search of the points in the index.
*/
void query(const geom::Envelope& queryEnv, std::vector<KdNode*>& result);
/**
* Searches for a given point in the index and returns its node if found.
*/
KdNode* query(const geom::Coordinate& queryPt);
};
} // namespace geos::index::kdtree
} // namespace geos::index
} // namespace geos
#ifdef _MSC_VER
#pragma warning(pop)
#endif