[geos-commits] r2415 - in trunk/source: headers/geos/index/quadtree index/quadtree

svn_geos at osgeo.org svn_geos at osgeo.org
Mon Apr 27 15:38:45 EDT 2009


Author: strk
Date: 2009-04-27 15:38:44 -0400 (Mon, 27 Apr 2009)
New Revision: 2415

Modified:
   trunk/source/headers/geos/index/quadtree/Node.h
   trunk/source/headers/geos/index/quadtree/Root.h
   trunk/source/index/quadtree/Node.cpp
   trunk/source/index/quadtree/Root.cpp
Log:
Refactor signatures to make ownership transfers more explicit. Fixed another leak in Node::insertNode.


Modified: trunk/source/headers/geos/index/quadtree/Node.h
===================================================================
--- trunk/source/headers/geos/index/quadtree/Node.h	2009-04-27 19:22:07 UTC (rev 2414)
+++ trunk/source/headers/geos/index/quadtree/Node.h	2009-04-27 19:38:44 UTC (rev 2415)
@@ -52,15 +52,21 @@
 private:
 
 	/// Owned by this class
-	geom::Envelope *env;
+	std::auto_ptr<geom::Envelope> env;
 
 	geom::Coordinate centre;
 
 	int level;
 
+	/**
+	 * Get the subquad for the index.
+	 * If it doesn't exist, create it.
+	 * 
+	 * Ownership of the returned object belongs to this class.
+	 */
 	Node* getSubnode(int index);
 
-	Node* createSubnode(int index);
+	std::auto_ptr<Node> createSubnode(int index);
 
 protected:
 
@@ -70,26 +76,31 @@
 
 public:
 
+	// Create a node computing level from given envelope
 	static std::auto_ptr<Node> createNode(const geom::Envelope& env);
 
-	static std::auto_ptr<Node> createExpanded(Node *node,
-			const geom::Envelope *addEnv);
+	/// Create a node containing the given node and envelope
+	//
+	/// @param node if not null, will be inserted to the returned node
+	/// @param addEnv minimum envelope to use for the node
+	///
+	static std::auto_ptr<Node> createExpanded(std::auto_ptr<Node> node,
+			const geom::Envelope& addEnv);
 
-	// Takes ownership of envelope
-	Node(geom::Envelope *nenv, int nlevel)
+	Node(std::auto_ptr<geom::Envelope> nenv, int nlevel)
 		:
 		env(nenv),
-		centre((nenv->getMinX()+nenv->getMaxX())/2,
-			(nenv->getMinY()+nenv->getMaxY())/2),
+		centre((env->getMinX()+env->getMaxX())/2,
+			(env->getMinY()+env->getMaxY())/2),
 		level(nlevel)
 	{
 	}
 
-	virtual ~Node() { delete env; }
+	virtual ~Node() {}
 
 	/// Return Envelope associated with this node
 	/// ownership retained by this object
-	geom::Envelope* getEnvelope() { return env; }
+	geom::Envelope* getEnvelope() { return env.get(); }
 
 	/** \brief
 	 * Returns the subquad containing the envelope.
@@ -104,7 +115,7 @@
 	 */
 	NodeBase* find(const geom::Envelope *searchEnv);
 
-	void insertNode(Node *node);
+	void insertNode(std::auto_ptr<Node> node);
 
 	std::string toString() const;
 

Modified: trunk/source/headers/geos/index/quadtree/Root.h
===================================================================
--- trunk/source/headers/geos/index/quadtree/Root.h	2009-04-27 19:22:07 UTC (rev 2414)
+++ trunk/source/headers/geos/index/quadtree/Root.h	2009-04-27 19:38:44 UTC (rev 2415)
@@ -51,14 +51,15 @@
 
 private:
 
-	static geom::Coordinate origin;
+	static const geom::Coordinate origin;
 
 	/**
 	 * insert an item which is known to be contained in the tree rooted at
 	 * the given QuadNode root.  Lower levels of the tree will be created
 	 * if necessary to hold the item.
 	 */
-	void insertContained(Node *tree, const geom::Envelope *itemEnv, void* item);
+	void insertContained(Node *tree, const geom::Envelope *itemEnv,
+	                     void* item);
 
 public:
 

Modified: trunk/source/index/quadtree/Node.cpp
===================================================================
--- trunk/source/index/quadtree/Node.cpp	2009-04-27 19:22:07 UTC (rev 2414)
+++ trunk/source/index/quadtree/Node.cpp	2009-04-27 19:38:44 UTC (rev 2415)
@@ -46,24 +46,34 @@
 Node::createNode(const Envelope& env)
 {
 	Key key(env);
+
+	std::auto_ptr<Envelope> nenv ( new Envelope(key.getEnvelope()) );
 	std::auto_ptr<Node> node (
-		new Node(new Envelope(key.getEnvelope()),
-	                 key.getLevel())
+		new Node(nenv, key.getLevel())
 	);
 	return node;
 }
 
 /* static public */
 std::auto_ptr<Node>
-Node::createExpanded(Node *node, const Envelope *addEnv)
+Node::createExpanded(std::auto_ptr<Node> node, const Envelope& addEnv)
 {
-	Envelope expandEnv(*addEnv);
-	if (node!=NULL) expandEnv.expandToInclude(node->env);
+	Envelope expandEnv(addEnv);
+	if ( node.get() ) // should this be asserted ?
+	{
+		expandEnv.expandToInclude(node->getEnvelope());
+	}
+
 #if GEOS_DEBUG
 	cerr<<"Node::createExpanded computed "<<expandEnv.toString()<<endl;
 #endif
+
 	std::auto_ptr<Node> largerNode = createNode(expandEnv);
-	if (node!=NULL) largerNode->insertNode(node);
+	if ( node.get() ) // should this be asserted ?
+	{
+		largerNode->insertNode(node);
+	}
+
 	return largerNode;
 }
 
@@ -71,14 +81,17 @@
 Node*
 Node::getNode(const Envelope *searchEnv)
 {
-	int subnodeIndex=getSubnodeIndex(searchEnv, centre);
+	int subnodeIndex = getSubnodeIndex(searchEnv, centre);
 	// if subquadIndex is -1 searchEnv is not contained in a subquad
-	if (subnodeIndex!=-1) {
+	if (subnodeIndex != -1)
+	{
 		// create the quad if it does not exist
-		Node *node=getSubnode(subnodeIndex);
+		Node *node = getSubnode(subnodeIndex);
 		// recursively search the found/created quad
 		return node->getNode(searchEnv);
-	} else {
+	}
+	else
+	{
 		return this;
 	}
 }
@@ -99,36 +112,50 @@
 	return this;
 }
 
-void Node::insertNode(Node* node) {
-	assert(env==NULL || env->contains(node->env));
-	//System.out.println(env);
-	//System.out.println(quad.env);
-	int index=getSubnodeIndex(node->env, centre);
-	//System.out.println(index);
-	if (node->level==level-1) {
-		subnode[index]=node;
+void
+Node::insertNode(std::auto_ptr<Node> node)
+{
+	assert( env->contains(node->getEnvelope()) );
+
+	int index = getSubnodeIndex(node->getEnvelope(), centre);
+
+	if (node->level == level-1)
+	{
+		// We take ownership of node 
+		delete subnode[index];
+		subnode[index] = node.release();
+
 		//System.out.println("inserted");
-	} else {
-		// the quad is not a direct child, so make a new child quad to contain it
-		// and recursively insert the quad
-		Node *childNode=createSubnode(index);
+	}
+	else
+	{
+		// the quad is not a direct child, so make a new child
+		// quad to contain it and recursively insert the quad
+		std::auto_ptr<Node> childNode ( createSubnode(index) );
+
+		// childNode takes ownership of node
 		childNode->insertNode(node);
-		subnode[index]=childNode;
+
+		// We take ownership of childNode 
+		delete subnode[index];
+		subnode[index] = childNode.release();
 	}
 }
 
-/**
-* get the subquad for the index.
-* If it doesn't exist, create it
-*/
-Node* Node::getSubnode(int index){
-	if (subnode[index]==NULL) {
-		subnode[index]=createSubnode(index);
+Node*
+Node::getSubnode(int index)
+{
+	assert(index >=0 && index < 4);
+	if (subnode[index] == NULL)
+	{
+		subnode[index] = createSubnode(index).release();
 	}
 	return subnode[index];
 }
 
-Node* Node::createSubnode(int index) {
+std::auto_ptr<Node>
+Node::createSubnode(int index)
+{
 	// create a new subquad in the appropriate quadrant
 	double minx=0.0;
 	double maxx=0.0;
@@ -148,21 +175,21 @@
 			miny=env->getMinY();
 			maxy=centre.y;
 			break;
-	case 2:
+		case 2:
 			minx=env->getMinX();
 			maxx=centre.x;
 			miny=centre.y;
 			maxy=env->getMaxY();
 			break;
-	case 3:
+		case 3:
 			minx=centre.x;
 			maxx=env->getMaxX();
 			miny=centre.y;
 			maxy=env->getMaxY();
 			break;
 	}
-	Envelope *sqEnv=new Envelope(minx,maxx,miny,maxy);
-	Node *node=new Node(sqEnv,level-1);
+	std::auto_ptr<Envelope> sqEnv ( new Envelope(minx,maxx,miny,maxy) );
+	std::auto_ptr<Node> node ( new Node(sqEnv, level-1) );
 	return node;
 }
 
@@ -175,6 +202,7 @@
 	return os.str();
 }
 
+
 } // namespace geos.index.quadtree
 } // namespace geos.index
 } // namespace geos

Modified: trunk/source/index/quadtree/Root.cpp
===================================================================
--- trunk/source/index/quadtree/Root.cpp	2009-04-27 19:22:07 UTC (rev 2414)
+++ trunk/source/index/quadtree/Root.cpp	2009-04-27 19:38:44 UTC (rev 2415)
@@ -42,7 +42,7 @@
 
 // the singleton root quad is centred at the origin.
 //Coordinate* Root::origin=new Coordinate(0.0, 0.0);
-Coordinate Root::origin(0.0, 0.0);
+const Coordinate Root::origin(0.0, 0.0);
 
 /*public*/
 void
@@ -50,11 +50,12 @@
 {
 
 #if GEOS_DEBUG
-	std::cerr<<"("<<this<<") insert("<<itemEnv->toString()<<", "<<item<<") called"<<std::endl;
+	std::cerr<< "Root("<<this<<")::insert("<<itemEnv->toString()<<", "<<item<<") called"<<std::endl;
 #endif
-	int index=getSubnodeIndex(itemEnv,origin);
+	int index = getSubnodeIndex(itemEnv, origin);
 	// if index is -1, itemEnv must cross the X or Y axis.
-	if (index==-1) {
+	if (index==-1)
+	{
 #if GEOS_DEBUG
 	std::cerr<<"  -1 subnode index"<<std::endl;
 #endif
@@ -66,7 +67,7 @@
 	 * the item must be contained in one quadrant, so insert it into the
 	 * tree for that quadrant (which may not yet exist)
 	 */
-	Node *node=subnode[index];
+	Node *node = subnode[index];
 
 #if GEOS_DEBUG
 	std::cerr<<"("<<this<<") subnode["<<index<<"] @ "<<node<<std::endl;
@@ -76,20 +77,36 @@
 	 *  If the subquad doesn't exist or this item is not contained in it,
 	 *  have to expand the tree upward to contain the item.
 	 */
-	if (node==NULL || !node->getEnvelope()->contains(itemEnv)) {
-		std::auto_ptr<Node> largerNode = Node::createExpanded(node,
-							              itemEnv);
-		//delete subnode[index];
-		// TODO: should subnode[] be an array of auto_ptrs ?
-		subnode[index]=largerNode.release();
+	if (node==NULL || !node->getEnvelope()->contains(itemEnv))
+	{
+		std::auto_ptr<Node> snode (node); // may be NULL
+		node = 0; subnode[index] = 0;
+
+		std::auto_ptr<Node> largerNode =
+			Node::createExpanded(snode, *itemEnv);
+
+#if GEOS_DEBUG
+		std::cerr<<"("<<this<<") created expanded node " << largerNode.get() << " containing previously reported subnode" << std::endl;
+#endif
+
+		// Previous subnode was passed as a child of the larger one
+		assert(!subnode[index]);
+		subnode[index] = largerNode.release();
 	}
 
+#if GEOS_DEBUG
+	std::cerr<<"("<<this<<") calling insertContained with subnode " << subnode[index] << std::endl;
+#endif
 	/*
 	 * At this point we have a subquad which exists and must contain
 	 * contains the env for the item.  Insert the item into the tree.
 	 */
-	insertContained(subnode[index],itemEnv,item);
+	insertContained(subnode[index], itemEnv, item);
 
+#if GEOS_DEBUG
+	std::cerr<<"("<<this<<") done calling insertContained with subnode " << subnode[index] << std::endl;
+#endif
+
 	//System.out.println("depth = " + root.depth() + " size = " + root.size());
 	//System.out.println(" size = " + size());
 }
@@ -113,9 +130,13 @@
 	NodeBase *node;
 
 	if (isZeroX || isZeroY)
-		node=tree->find(itemEnv);
+	{
+		node = tree->find(itemEnv);
+	}
 	else
-		node=tree->getNode(itemEnv);
+	{
+		node = tree->getNode(itemEnv);
+	}
 
 	node->add(item);
 }



More information about the geos-commits mailing list