Complete Note#1 in the http://wiki.osgeo.org/wiki/GEOS_Provenance_Review to get out...
[geos.git] / src / index / quadtree / Node.cpp
bloba56cec57fceba118447069402d762638806473e5
1 /**********************************************************************
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
6 * Copyright (C) 2006 Refractions Research Inc.
7 * Copyright (C) 2001-2002 Vivid Solutions Inc.
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.
14 **********************************************************************
16 * Last port: index/quadtree/Node.java rev 1.8 (JTS-1.10)
18 **********************************************************************/
20 #include <geos/index/quadtree/Node.h>
21 #include <geos/index/quadtree/Key.h>
22 #include <geos/geom/Envelope.h>
24 #include <string>
25 #include <sstream>
26 #include <cassert>
28 #ifndef GEOS_DEBUG
29 #define GEOS_DEBUG 0
30 #endif
32 #if GEOS_DEBUG
33 #include <iostream>
34 #endif
36 using namespace std;
37 using namespace geos::geom;
39 namespace geos {
40 namespace index { // geos.index
41 namespace quadtree { // geos.index.quadtree
43 /* public static */
44 std::auto_ptr<Node>
45 Node::createNode(const Envelope& env)
47 Key key(env);
49 std::auto_ptr<Envelope> nenv ( new Envelope(key.getEnvelope()) );
50 std::auto_ptr<Node> node (
51 new Node(nenv, key.getLevel())
53 return node;
56 /* static public */
57 std::auto_ptr<Node>
58 Node::createExpanded(std::auto_ptr<Node> node, const Envelope& addEnv)
60 Envelope expandEnv(addEnv);
61 if ( node.get() ) // should this be asserted ?
63 expandEnv.expandToInclude(node->getEnvelope());
66 #if GEOS_DEBUG
67 cerr<<"Node::createExpanded computed "<<expandEnv.toString()<<endl;
68 #endif
70 std::auto_ptr<Node> largerNode = createNode(expandEnv);
71 if ( node.get() ) // should this be asserted ?
73 largerNode->insertNode(node);
76 return largerNode;
79 /*public*/
80 Node*
81 Node::getNode(const Envelope *searchEnv)
83 int subnodeIndex = getSubnodeIndex(searchEnv, centre);
84 // if subquadIndex is -1 searchEnv is not contained in a subquad
85 if (subnodeIndex != -1)
87 // create the quad if it does not exist
88 Node *node = getSubnode(subnodeIndex);
89 // recursively search the found/created quad
90 return node->getNode(searchEnv);
92 else
94 return this;
98 /*public*/
99 NodeBase*
100 Node::find(const Envelope *searchEnv)
102 int subnodeIndex=getSubnodeIndex(searchEnv, centre);
103 if (subnodeIndex==-1)
104 return this;
105 if (subnode[subnodeIndex]!=NULL) {
106 // query lies in subquad, so search it
107 Node *node=subnode[subnodeIndex];
108 return node->find(searchEnv);
110 // no existing subquad, so return this one anyway
111 return this;
114 void
115 Node::insertNode(std::auto_ptr<Node> node)
117 assert( env->contains(node->getEnvelope()) );
119 int index = getSubnodeIndex(node->getEnvelope(), centre);
120 assert(index >= 0);
122 if (node->level == level-1)
124 // We take ownership of node
125 delete subnode[index];
126 subnode[index] = node.release();
128 //System.out.println("inserted");
130 else
132 // the quad is not a direct child, so make a new child
133 // quad to contain it and recursively insert the quad
134 std::auto_ptr<Node> childNode ( createSubnode(index) );
136 // childNode takes ownership of node
137 childNode->insertNode(node);
139 // We take ownership of childNode
140 delete subnode[index];
141 subnode[index] = childNode.release();
145 Node*
146 Node::getSubnode(int index)
148 assert(index >=0 && index < 4);
149 if (subnode[index] == NULL)
151 subnode[index] = createSubnode(index).release();
153 return subnode[index];
156 std::auto_ptr<Node>
157 Node::createSubnode(int index)
159 // create a new subquad in the appropriate quadrant
160 double minx=0.0;
161 double maxx=0.0;
162 double miny=0.0;
163 double maxy=0.0;
165 switch (index) {
166 case 0:
167 minx=env->getMinX();
168 maxx=centre.x;
169 miny=env->getMinY();
170 maxy=centre.y;
171 break;
172 case 1:
173 minx=centre.x;
174 maxx=env->getMaxX();
175 miny=env->getMinY();
176 maxy=centre.y;
177 break;
178 case 2:
179 minx=env->getMinX();
180 maxx=centre.x;
181 miny=centre.y;
182 maxy=env->getMaxY();
183 break;
184 case 3:
185 minx=centre.x;
186 maxx=env->getMaxX();
187 miny=centre.y;
188 maxy=env->getMaxY();
189 break;
191 std::auto_ptr<Envelope> sqEnv ( new Envelope(minx,maxx,miny,maxy) );
192 std::auto_ptr<Node> node ( new Node(sqEnv, level-1) );
193 return node;
196 string
197 Node::toString() const
199 ostringstream os;
200 os <<"L"<<level<<" "<<env->toString()<<" Ctr["<<centre.toString()<<"]";
201 os <<" "+NodeBase::toString();
202 return os.str();
206 } // namespace geos.index.quadtree
207 } // namespace geos.index
208 } // namespace geos
210 /**********************************************************************
211 * $Log$
212 * Revision 1.2 2006/03/23 13:31:58 strk
213 * Fixed to allow build with GEOS_DEBUG
215 * Revision 1.1 2006/03/22 14:28:53 strk
216 * Filenames renamed to match class names (matching JTS)
218 * Revision 1.17 2006/03/22 12:22:50 strk
219 * indexQuadtree.h split
221 **********************************************************************/