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

325 lines
8.2 KiB
C++

/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* Copyright (C) 2006 Refractions Research Inc.
*
* 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/index/strtree/AbstractNode.h> // for inlines
#include <vector>
#include <list>
#include <memory> // for unique_ptr
#include <cassert> // for inlines
#include <algorithm>
// Forward declarations
namespace geos {
namespace index {
class ItemVisitor;
namespace strtree {
class Boundable;
class AbstractNode;
}
}
}
namespace geos {
namespace index { // geos::index
namespace strtree { // geos::index::strtree
/// A list of boundables. TODO: use a list
typedef std::vector<Boundable*> BoundableList;
/// list contains boundables or lists of boundables. The lists are owned by
/// this class, the plain boundables are held by reference only.
class ItemsList;
class ItemsListItem {
public:
enum type {
item_is_geometry,
item_is_list
};
ItemsListItem(void* item_)
: t(item_is_geometry)
{
item.g = item_;
}
ItemsListItem(ItemsList* item_)
: t(item_is_list)
{
item.l = item_;
}
type
get_type() const
{
return t;
}
void*
get_geometry() const
{
assert(t == item_is_geometry);
return item.g;
}
ItemsList*
get_itemslist() const
{
assert(t == item_is_list);
return item.l;
}
type t;
union {
void* g;
ItemsList* l;
} item;
};
class ItemsList : public std::vector<ItemsListItem> {
private:
typedef std::vector<ItemsListItem> base_type;
static void
delete_item(ItemsListItem& item)
{
if(ItemsListItem::item_is_list == item.t) {
delete item.item.l;
}
}
public:
~ItemsList()
{
std::for_each(begin(), end(), &ItemsList::delete_item);
}
// lists of items need to be deleted in the end
void
push_back(void* item)
{
this->base_type::push_back(ItemsListItem(item));
}
// lists of items need to be deleted in the end
void
push_back_owned(ItemsList* itemList)
{
this->base_type::push_back(ItemsListItem(itemList));
}
};
/** \brief
* Base class for STRtree and SIRtree.
*
* STR-packed R-trees are described in:
* P. Rigaux, Michel Scholl and Agnes Voisard. Spatial Databases With
* Application To GIS. Morgan Kaufmann, San Francisco, 2002.
*
* This implementation is based on Boundables rather than just AbstractNodes,
* because the STR algorithm operates on both nodes and
* data, both of which are treated here as Boundables.
*
*/
class GEOS_DLL AbstractSTRtree {
private:
bool built;
BoundableList* itemBoundables;
/**
* Creates the levels higher than the given level
*
* @param boundablesOfALevel
* the level to build on
* @param level
* the level of the Boundables, or -1 if the boundables are item
* boundables (that is, below level 0)
* @return the root, which may be a ParentNode or a LeafNode
*/
virtual AbstractNode* createHigherLevels(
BoundableList* boundablesOfALevel,
int level);
std::unique_ptr<BoundableList> sortBoundablesY(const BoundableList* input);
bool remove(const void* searchBounds, AbstractNode& node, void* item);
bool removeItem(AbstractNode& node, void* item);
ItemsList* itemsTree(AbstractNode* node);
AbstractSTRtree(const AbstractSTRtree&) = delete;
AbstractSTRtree& operator=(const AbstractSTRtree&) = delete;
protected:
/** \brief
* A test for intersection between two bounds, necessary because
* subclasses of AbstractSTRtree have different implementations of
* bounds.
*/
class GEOS_DLL IntersectsOp {
public:
/**
* For STRtrees, the bounds will be Envelopes; for
* SIRtrees, Intervals; for other subclasses of
* AbstractSTRtree, some other class.
* @param aBounds the bounds of one spatial object
* @param bBounds the bounds of another spatial object
* @return whether the two bounds intersect
*/
virtual bool intersects(const void* aBounds,
const void* bBounds) = 0;
virtual
~IntersectsOp() {}
};
AbstractNode* root;
std::vector <AbstractNode*>* nodes;
// Ownership to caller (TODO: return by unique_ptr)
virtual AbstractNode* createNode(int level) = 0;
/** \brief
* Sorts the childBoundables then divides them into groups of size M, where
* M is the node capacity.
*/
virtual std::unique_ptr<BoundableList> createParentBoundables(
BoundableList* childBoundables, int newLevel);
virtual AbstractNode*
lastNode(BoundableList* nodeList)
{
assert(!nodeList->empty());
// Cast from Boundable to AbstractNode
return static_cast<AbstractNode*>(nodeList->back());
}
virtual AbstractNode*
getRoot()
{
assert(built);
return root;
}
/// Also builds the tree, if necessary.
virtual void insert(const void* bounds, void* item);
/// Also builds the tree, if necessary.
void query(const void* searchBounds, std::vector<void*>& foundItems);
/// Also builds the tree, if necessary.
void query(const void* searchBounds, ItemVisitor& visitor);
void query(const void* searchBounds, const AbstractNode& node, ItemVisitor& visitor);
/// Also builds the tree, if necessary.
bool remove(const void* itemEnv, void* item);
std::unique_ptr<BoundableList> boundablesAtLevel(int level);
// @@ should be size_t, probably
std::size_t nodeCapacity;
/**
* @return a test for intersection between two bounds,
* necessary because subclasses
* of AbstractSTRtree have different implementations of bounds.
* @see IntersectsOp
*/
virtual IntersectsOp* getIntersectsOp() = 0;
public:
/** \brief
* Constructs an AbstractSTRtree with the specified maximum number of child
* nodes that a node may have.
*/
AbstractSTRtree(std::size_t newNodeCapacity)
:
built(false),
itemBoundables(new BoundableList()),
nodes(new std::vector<AbstractNode *>()),
nodeCapacity(newNodeCapacity)
{
assert(newNodeCapacity > 1);
}
virtual ~AbstractSTRtree();
/** \brief
* Creates parent nodes, grandparent nodes, and so forth up to the root
* node, for the data that has been inserted into the tree.
*
* Can only be
* called once, and thus can be called only after all of the data has been
* inserted into the tree.
*/
virtual void build();
/** \brief
* Returns the maximum number of child nodes that a node may have.
*/
virtual std::size_t
getNodeCapacity()
{
return nodeCapacity;
}
virtual void query(const void* searchBounds, const AbstractNode* node, std::vector<void*>* matches);
/**
* Iterate over all items added thus far. Explicitly does not build
* the tree.
*/
void iterate(ItemVisitor& visitor);
/**
* @param level -1 to get items
* @param top an AbstractNode
* @param boundables a BoundableList
*/
virtual void boundablesAtLevel(int level, AbstractNode* top,
BoundableList* boundables);
/** \brief
* Gets a tree structure (as a nested list) corresponding to the structure
* of the items and nodes in this tree.
*
* The returned Lists contain either Object items, or Lists which
* correspond to subtrees of the tree Subtrees which do not contain
* any items are not included.
*
* Builds the tree if necessary.
*
* @note The caller is responsible for releasing the list
*
* @return a List of items and/or Lists
*/
ItemsList* itemsTree();
};
} // namespace geos::index::strtree
} // namespace geos::index
} // namespace geos