/********************************************************************** * $Id: STRtree.cpp,v 1.18 2004/12/08 13:54:43 strk Exp $ * * GEOS - Geometry Engine Open Source * http://geos.refractions.net * * Copyright (C) 2001-2002 Vivid Solutions 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. * **********************************************************************/ #include #include #include namespace geos { //static bool xComparator(Boundable *a, Boundable *b){ //return AbstractSTRtree::compareDoubles(STRtree::centreX((Envelope*)a->getBounds()), STRtree::centreX((Envelope*)b->getBounds())); //} static bool yComparator(Boundable *a, Boundable *b){ return AbstractSTRtree::compareDoubles(STRtree::centreY((Envelope*)a->getBounds()), STRtree::centreY((Envelope*)b->getBounds())); } /** * Constructs an STRtree with the default node capacity. */ STRtree::STRtree(): AbstractSTRtree(10) { //intersectsOp(new STRIntersectsOp()) } /** * Constructs an STRtree with the given maximum number of child nodes that * a node may have */ STRtree::STRtree(int nodeCapacity): AbstractSTRtree(nodeCapacity) { //intersectsOp(new STRIntersectsOp()) } STRtree::~STRtree() { //delete intersectsOp; } double STRtree::centreX(Envelope *e) { return STRtree::avg(e->getMinX(),e->getMaxX()); } double STRtree::avg(double a, double b) { return (a + b) / 2.0; } double STRtree::centreY(Envelope *e) { return STRtree::avg(e->getMinY(), e->getMaxY()); } bool STRtree::STRIntersectsOp::intersects(const void* aBounds, const void* bBounds) { return ((Envelope*)aBounds)->intersects((Envelope*)bBounds); } /** * Creates the parent level for the given child level. First, orders the items * by the x-values of the midpoints, and groups them into vertical slices. * For each slice, orders the items by the y-values of the midpoints, and * group them into runs of size M (the node capacity). For each run, creates * a new (parent) node. */ vector* STRtree::createParentBoundables(vector *childBoundables, int newLevel) { Assert::isTrue(!childBoundables->empty()); int minLeafCount=(int) ceil((double)childBoundables->size()/(double)getNodeCapacity()); vector *sortedChildBoundables=sortBoundables(childBoundables); vector*>* verticalSlicesV = verticalSlices(sortedChildBoundables,(int)ceil(sqrt((double)minLeafCount))); delete sortedChildBoundables; vector *ret; ret = createParentBoundablesFromVerticalSlices(verticalSlicesV, newLevel); for (unsigned int i=0; isize(); i++) { vector*inner = (*verticalSlicesV)[i]; //for (unsigned int j=0; jsize(); j++) //{ // some of these might be provided, // some of these might be created //delete (*inner)[j]; //} delete inner; } delete verticalSlicesV; return ret; } vector* STRtree::createParentBoundablesFromVerticalSlices(vector*> *verticalSlices, int newLevel) { Assert::isTrue(verticalSlices->size()>0); vector *parentBoundables=new vector(); for (unsigned int i = 0; i size(); i++) { vector *toAdd=createParentBoundablesFromVerticalSlice((*verticalSlices)[i], newLevel); parentBoundables->insert(parentBoundables->end(),toAdd->begin(),toAdd->end()); delete toAdd; } return parentBoundables; } vector* STRtree::createParentBoundablesFromVerticalSlice(vector *childBoundables, int newLevel) { return AbstractSTRtree::createParentBoundables(childBoundables, newLevel); } /** * @param childBoundables Must be sorted by the x-value of * the envelope midpoints * @return */ vector*>* STRtree::verticalSlices(vector* childBoundables, int sliceCount) { int sliceCapacity = (int) ceil((double)childBoundables->size() / (double) sliceCount); vector*>* slices = new vector*>(sliceCount); unsigned int i=0; for (int j=0; j(); int boundablesAddedToSlice = 0; while (isize() && boundablesAddedToSlice < sliceCapacity) { Boundable *childBoundable=(*childBoundables)[i]; i++; (*slices)[j]->push_back(childBoundable); boundablesAddedToSlice++; } } return slices; } STRAbstractNode::STRAbstractNode(int level):AbstractNode(level) { } STRAbstractNode::~STRAbstractNode() { delete (Envelope *)bounds; } void * STRAbstractNode::computeBounds() { Envelope* bounds=NULL; vector *b=getChildBoundables(); unsigned int bsize=b->size(); if ( bsize ) bounds=new Envelope(*(Envelope*)(*b)[0]->getBounds()); for(unsigned int i=1; iexpandToInclude((Envelope*)childBoundable->getBounds()); } return bounds; } AbstractNode* STRtree::createNode(int level) { AbstractNode *an = new STRAbstractNode(level); nodes->push_back(an); return an; } void STRtree::insert(const Envelope *itemEnv, void* item) { if (itemEnv->isNull()) { return; } AbstractSTRtree::insert(itemEnv, item); } vector* STRtree::query(const Envelope *searchEnv) { vector *ret = AbstractSTRtree::query(searchEnv); return ret; } vector * STRtree::sortBoundables(const vector *input) { vector *output=new vector(*input); sort(output->begin(),output->end(),yComparator); return output; } } // namespace geos /********************************************************************** * $Log: STRtree.cpp,v $ * Revision 1.18 2004/12/08 13:54:43 strk * gcc warnings checked and fixed, general cleanups. * * Revision 1.17 2004/11/08 18:33:47 strk * Just another small improvement. * * Revision 1.16 2004/11/08 15:58:13 strk * More performance tuning. * * Revision 1.15 2004/11/04 19:08:07 strk * Cleanups, initializers list, profiling. * * Revision 1.14 2004/11/01 16:43:04 strk * Added Profiler code. * Temporarly patched a bug in DoubleBits (must check drawbacks). * Various cleanups and speedups. * * Revision 1.13 2004/07/27 16:35:46 strk * Geometry::getEnvelopeInternal() changed to return a const Envelope *. * This should reduce object copies as once computed the envelope of a * geometry remains the same. * **********************************************************************/