/src/geos/src/index/quadtree/Root.cpp
Line | Count | Source |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (C) 2006 Refractions Research Inc. |
7 | | * Copyright (C) 2001-2002 Vivid Solutions Inc. |
8 | | * |
9 | | * This is free software; you can redistribute and/or modify it under |
10 | | * the terms of the GNU Lesser General Public Licence as published |
11 | | * by the Free Software Foundation. |
12 | | * See the COPYING file for more information. |
13 | | * |
14 | | ********************************************************************** |
15 | | * |
16 | | * Last port: index/quadtree/Root.java rev 1.7 (JTS-1.10) |
17 | | * |
18 | | **********************************************************************/ |
19 | | |
20 | | #include <geos/index/quadtree/Root.h> |
21 | | #include <geos/index/quadtree/Node.h> |
22 | | #include <geos/index/quadtree/IntervalSize.h> |
23 | | #include <geos/geom/Coordinate.h> |
24 | | #include <geos/geom/Envelope.h> |
25 | | #include <geos/util/IllegalArgumentException.h> |
26 | | |
27 | | #include <cassert> |
28 | | |
29 | | #ifndef GEOS_DEBUG |
30 | | #define GEOS_DEBUG 0 |
31 | | #endif |
32 | | |
33 | | #if GEOS_DEBUG |
34 | | #include <iostream> |
35 | | #endif |
36 | | |
37 | | using namespace geos::geom; |
38 | | |
39 | | namespace geos { |
40 | | namespace index { // geos.index |
41 | | namespace quadtree { // geos.index.quadtree |
42 | | |
43 | | // the singleton root quad is centred at the origin. |
44 | | //Coordinate* Root::origin=new Coordinate(0.0, 0.0); |
45 | | const Coordinate Root::origin(0.0, 0.0); |
46 | | |
47 | | /*public*/ |
48 | | void |
49 | | Root::insert(const Envelope* itemEnv, void* item) |
50 | 129k | { |
51 | | |
52 | | #if GEOS_DEBUG |
53 | | std::cerr << "Root(" << this << ")::insert(" << itemEnv->toString() << ", " << item << ") called" << std::endl; |
54 | | #endif |
55 | 129k | if (!itemEnv->isfinite()) { |
56 | 4.08k | throw util::IllegalArgumentException("Non-finite envelope bounds passed to index insert"); |
57 | 4.08k | } |
58 | 125k | int index = getSubnodeIndex(itemEnv, origin); |
59 | | // if index is -1, itemEnv must cross the X or Y axis. |
60 | 125k | if(index == -1) { |
61 | | #if GEOS_DEBUG |
62 | | std::cerr << " -1 subnode index" << std::endl; |
63 | | #endif |
64 | 24.5k | add(item); |
65 | 24.5k | return; |
66 | 24.5k | } |
67 | | |
68 | | /* |
69 | | * the item must be contained in one quadrant, so insert it into the |
70 | | * tree for that quadrant (which may not yet exist) |
71 | | */ |
72 | 101k | Node* node = subnodes[static_cast<std::size_t>(index)]; |
73 | | |
74 | | #if GEOS_DEBUG |
75 | | std::cerr << "(" << this << ") subnode[" << index << "] @ " << node << std::endl; |
76 | | #endif |
77 | | |
78 | | /* |
79 | | * If the subquad doesn't exist or this item is not contained in it, |
80 | | * have to expand the tree upward to contain the item. |
81 | | */ |
82 | 101k | if(node == nullptr || !node->getEnvelope()->contains(itemEnv)) { |
83 | 21.2k | std::unique_ptr<Node> snode(node); // may be NULL |
84 | 21.2k | node = nullptr; |
85 | 21.2k | subnodes[static_cast<std::size_t>(index)] = nullptr; |
86 | | |
87 | 21.2k | std::unique_ptr<Node> largerNode = |
88 | 21.2k | Node::createExpanded(std::move(snode), *itemEnv); |
89 | | |
90 | | #if GEOS_DEBUG |
91 | | std::cerr << "(" << this << ") created expanded node " << largerNode.get() << " containing previously reported subnode" |
92 | | << std::endl; |
93 | | #endif |
94 | | |
95 | | // Previous subnode was passed as a child of the larger one |
96 | 21.2k | assert(!subnodes[static_cast<std::size_t>(index)]); |
97 | 21.2k | subnodes[static_cast<std::size_t>(index)] = largerNode.release(); |
98 | 21.2k | } |
99 | | |
100 | | #if GEOS_DEBUG |
101 | | std::cerr << "(" << this << ") calling insertContained with subnode " << subnodes[index] << std::endl; |
102 | | #endif |
103 | | /* |
104 | | * At this point we have a subquad which exists and must contain |
105 | | * contains the env for the item. Insert the item into the tree. |
106 | | */ |
107 | 101k | insertContained(subnodes[static_cast<std::size_t>(index)], itemEnv, item); |
108 | | |
109 | | #if GEOS_DEBUG |
110 | | std::cerr << "(" << this << ") done calling insertContained with subnode " << subnodes[index] << std::endl; |
111 | | #endif |
112 | | |
113 | | //System.out.println("depth = " + root.depth() + " size = " + root.size()); |
114 | | //System.out.println(" size = " + size()); |
115 | 101k | } |
116 | | |
117 | | /*private*/ |
118 | | void |
119 | | Root::insertContained(Node* tree, const Envelope* itemEnv, void* item) |
120 | 101k | { |
121 | 101k | assert(tree->getEnvelope()->contains(itemEnv)); |
122 | | |
123 | | /* |
124 | | * Do NOT create a new quad for zero-area envelopes - this would lead |
125 | | * to infinite recursion. Instead, use a heuristic of simply returning |
126 | | * the smallest existing quad containing the query |
127 | | */ |
128 | 101k | bool isZeroX = IntervalSize::isZeroWidth(itemEnv->getMinX(), |
129 | 101k | itemEnv->getMaxX()); |
130 | 101k | bool isZeroY = IntervalSize::isZeroWidth(itemEnv->getMinY(), |
131 | 101k | itemEnv->getMaxY()); |
132 | | |
133 | 101k | NodeBase* node; |
134 | | |
135 | 101k | if(isZeroX || isZeroY) { |
136 | 11.6k | node = tree->find(itemEnv); |
137 | 11.6k | } |
138 | 89.4k | else { |
139 | 89.4k | node = tree->getNode(itemEnv); |
140 | 89.4k | } |
141 | | |
142 | 101k | node->add(item); |
143 | 101k | } |
144 | | |
145 | | } // namespace geos.index.quadtree |
146 | | } // namespace geos.index |
147 | | } // namespace geos |