/src/geos/src/index/quadtree/Node.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/Node.java rev 1.8 (JTS-1.10) |
17 | | * |
18 | | **********************************************************************/ |
19 | | |
20 | | #include <geos/index/quadtree/Node.h> |
21 | | #include <geos/index/quadtree/Key.h> |
22 | | #include <geos/geom/Envelope.h> |
23 | | |
24 | | #include <string> |
25 | | #include <sstream> |
26 | | #include <cassert> |
27 | | #include <memory> |
28 | | |
29 | | #ifndef GEOS_DEBUG |
30 | | #define GEOS_DEBUG 0 |
31 | | #endif |
32 | | |
33 | | #if GEOS_DEBUG |
34 | | #include <iostream> |
35 | | #endif |
36 | | |
37 | | |
38 | | using namespace geos::geom; |
39 | | |
40 | | namespace geos { |
41 | | namespace index { // geos.index |
42 | | namespace quadtree { // geos.index.quadtree |
43 | | |
44 | | /* public static */ |
45 | | std::unique_ptr<Node> |
46 | | Node::createNode(const Envelope& env) |
47 | 0 | { |
48 | 0 | Key key(env); |
49 | 0 | std::unique_ptr<Envelope> envelope(new Envelope(key.getEnvelope())); |
50 | 0 | std::unique_ptr<Node> node( |
51 | 0 | new Node(std::move(envelope), key.getLevel()) |
52 | 0 | ); |
53 | 0 | return node; |
54 | 0 | } |
55 | | |
56 | | /* static public */ |
57 | | std::unique_ptr<Node> |
58 | | Node::createExpanded(std::unique_ptr<Node> node, const Envelope& addEnv) |
59 | 0 | { |
60 | 0 | Envelope expandEnv(addEnv); |
61 | 0 | if(node.get()) { // should this be asserted ? |
62 | 0 | expandEnv.expandToInclude(node->getEnvelope()); |
63 | 0 | } |
64 | |
|
65 | | #if GEOS_DEBUG |
66 | | std::cerr << "Node::createExpanded computed " << expandEnv.toString() << std::endl; |
67 | | #endif |
68 | |
|
69 | 0 | std::unique_ptr<Node> largerNode = createNode(expandEnv); |
70 | 0 | if(node.get()) { // should this be asserted ? |
71 | 0 | largerNode->insertNode(std::move(node)); |
72 | 0 | } |
73 | |
|
74 | 0 | return largerNode; |
75 | 0 | } |
76 | | |
77 | | /*public*/ |
78 | | Node* |
79 | | Node::getNode(const Envelope* searchEnv) |
80 | 0 | { |
81 | 0 | int subnodeIndex = getSubnodeIndex(searchEnv, centre); |
82 | | // if subquadIndex is -1 searchEnv is not contained in a subquad |
83 | 0 | if(subnodeIndex != -1) { |
84 | | // create the quad if it does not exist |
85 | 0 | Node* node = getSubnode(subnodeIndex); |
86 | | // recursively search the found/created quad |
87 | 0 | return node->getNode(searchEnv); |
88 | 0 | } |
89 | 0 | else { |
90 | 0 | return this; |
91 | 0 | } |
92 | 0 | } |
93 | | |
94 | | /*public*/ |
95 | | NodeBase* |
96 | | Node::find(const Envelope* searchEnv) |
97 | 0 | { |
98 | 0 | int subnodeIndex = getSubnodeIndex(searchEnv, centre); |
99 | 0 | if(subnodeIndex == -1) { |
100 | 0 | return this; |
101 | 0 | } |
102 | 0 | if(subnodes[static_cast<std::size_t>(subnodeIndex)] != nullptr) { |
103 | | // query lies in subquad, so search it |
104 | 0 | Node* node = subnodes[static_cast<std::size_t>(subnodeIndex)]; |
105 | 0 | return node->find(searchEnv); |
106 | 0 | } |
107 | | // no existing subquad, so return this one anyway |
108 | 0 | return this; |
109 | 0 | } |
110 | | |
111 | | void |
112 | | Node::insertNode(std::unique_ptr<Node> node) |
113 | 0 | { |
114 | 0 | assert(env->contains(node->getEnvelope())); |
115 | |
|
116 | 0 | int index = getSubnodeIndex(node->getEnvelope(), centre); |
117 | 0 | assert(index >= 0); |
118 | |
|
119 | 0 | if(node->level == level - 1) { |
120 | | // We take ownership of node |
121 | 0 | delete subnodes[static_cast<std::size_t>(index)]; |
122 | 0 | subnodes[static_cast<std::size_t>(index)] = node.release(); |
123 | | |
124 | | //System.out.println("inserted"); |
125 | 0 | } |
126 | 0 | else { |
127 | | // the quad is not a direct child, so make a new child |
128 | | // quad to contain it and recursively insert the quad |
129 | 0 | std::unique_ptr<Node> childNode(createSubnode(index)); |
130 | | |
131 | | // childNode takes ownership of node |
132 | 0 | childNode->insertNode(std::move(node)); |
133 | | |
134 | | // We take ownership of childNode |
135 | 0 | delete subnodes[static_cast<std::size_t>(index)]; |
136 | 0 | subnodes[static_cast<std::size_t>(index)] = childNode.release(); |
137 | 0 | } |
138 | 0 | } |
139 | | |
140 | | Node* |
141 | | Node::getSubnode(int index) |
142 | 0 | { |
143 | 0 | assert(index >= 0 && index < 4); |
144 | 0 | if(subnodes[static_cast<std::size_t>(index)] == nullptr) { |
145 | 0 | subnodes[static_cast<std::size_t>(index)] = createSubnode(index).release(); |
146 | 0 | } |
147 | 0 | return subnodes[static_cast<std::size_t>(index)]; |
148 | 0 | } |
149 | | |
150 | | std::unique_ptr<Node> |
151 | | Node::createSubnode(int index) |
152 | 0 | { |
153 | | // create a new subquad in the appropriate quadrant |
154 | 0 | double minx = 0.0; |
155 | 0 | double maxx = 0.0; |
156 | 0 | double miny = 0.0; |
157 | 0 | double maxy = 0.0; |
158 | |
|
159 | 0 | switch(index) { |
160 | 0 | case 0: |
161 | 0 | minx = env->getMinX(); |
162 | 0 | maxx = centre.x; |
163 | 0 | miny = env->getMinY(); |
164 | 0 | maxy = centre.y; |
165 | 0 | break; |
166 | 0 | case 1: |
167 | 0 | minx = centre.x; |
168 | 0 | maxx = env->getMaxX(); |
169 | 0 | miny = env->getMinY(); |
170 | 0 | maxy = centre.y; |
171 | 0 | break; |
172 | 0 | case 2: |
173 | 0 | minx = env->getMinX(); |
174 | 0 | maxx = centre.x; |
175 | 0 | miny = centre.y; |
176 | 0 | maxy = env->getMaxY(); |
177 | 0 | break; |
178 | 0 | case 3: |
179 | 0 | minx = centre.x; |
180 | 0 | maxx = env->getMaxX(); |
181 | 0 | miny = centre.y; |
182 | 0 | maxy = env->getMaxY(); |
183 | 0 | break; |
184 | 0 | } |
185 | 0 | std::unique_ptr<Envelope> sqEnv(new Envelope(minx, maxx, miny, maxy)); |
186 | 0 | std::unique_ptr<Node> node(new Node(std::move(sqEnv), level - 1)); |
187 | 0 | return node; |
188 | 0 | } |
189 | | |
190 | | std::string |
191 | | Node::toString() const |
192 | 0 | { |
193 | 0 | std::ostringstream os; |
194 | 0 | os << "L" << level << " " << env->toString() << " Ctr[" << centre.toString() << "]"; |
195 | 0 | os << " " << NodeBase::toString(); |
196 | 0 | return os.str(); |
197 | 0 | } |
198 | | |
199 | | |
200 | | } // namespace geos.index.quadtree |
201 | | } // namespace geos.index |
202 | | } // namespace geos |