polygonbuilder.cpp

来自「一个很好的vc底层代码」· C++ 代码 · 共 346 行

CPP
346
字号
/********************************************************************** * $Id: PolygonBuilder.cpp,v 1.18 2004/07/27 16:35:47 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. * ********************************************************************** * $Log: PolygonBuilder.cpp,v $ * Revision 1.18  2004/07/27 16:35:47  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. * * Revision 1.17  2004/07/08 19:34:50  strk * Mirrored JTS interface of CoordinateSequence, factory and * default implementations. * Added DefaultCoordinateSequenceFactory::instance() function. * * Revision 1.16  2004/07/02 13:28:29  strk * Fixed all #include lines to reflect headers layout change. * Added client application build tips in README. * * Revision 1.15  2004/06/30 20:59:13  strk * Removed GeoemtryFactory copy from geometry constructors. * Enforced const-correctness on GeometryFactory arguments. * * Revision 1.14  2004/05/03 10:43:43  strk * Exception specification considered harmful - left as comment. * * Revision 1.13  2004/04/10 08:40:01  ybychkov * "operation/buffer" upgraded to JTS 1.4 * * Revision 1.12  2003/11/12 18:02:57  strk * Added throw specification. Fixed leaks on exceptions. * * Revision 1.11  2003/11/07 01:23:42  pramsey * Add standard CVS headers licence notices and copyrights to all cpp and h * files. * * Revision 1.10  2003/11/06 18:48:30  strk * added throw information comment in PolygonBuilder * * Revision 1.9  2003/10/13 17:47:49  strk * delete statement removed * **********************************************************************/#include <geos/opOverlay.h>#include <stdio.h>#include <geos/util.h>namespace geos {PolygonBuilder::PolygonBuilder(const GeometryFactory *newGeometryFactory, CGAlgorithms *newCga) {	geometryFactory=newGeometryFactory;	cga=newCga;	shellList=new vector<EdgeRing*>();}PolygonBuilder::~PolygonBuilder() {	for(int i=0;i<(int)shellList->size();i++) {		delete (*shellList)[i];	}	delete shellList;}voidPolygonBuilder::add(PlanarGraph *graph)	//throw(TopologyException *){	vector<DirectedEdge*> *dirEdges=new vector<DirectedEdge*>();	vector<Node*> *nodes=new vector<Node*>();	vector<EdgeEnd*> *ee=graph->getEdgeEnds();	for(int i=0;i<(int)ee->size();i++) {		dirEdges->push_back((DirectedEdge*)(*ee)[i]);	}	map<Coordinate,Node*,CoordLT> *nodeMap=graph->getNodeMap()->nodeMap;	map<Coordinate,Node*,CoordLT>::iterator	it=nodeMap->begin();	for (;it!=nodeMap->end();it++) {		Node *node=it->second;		nodes->push_back(node);	}	try {		add(dirEdges,nodes); // might throw a TopologyException *	} catch (...) {		delete dirEdges;		delete nodes;		throw;	}	delete dirEdges;	delete nodes;}voidPolygonBuilder::add(vector<DirectedEdge*> *dirEdges,vector<Node*> *nodes)	//throw(TopologyException *){	//	PlanarGraph::linkResultDirectedEdgesS(nodes);	for(vector<Node*>::iterator nodeit=nodes->begin();nodeit<nodes->end();nodeit++) {		Node *node=*nodeit;		// This might throw a TopologyException		((DirectedEdgeStar*) node->getEdges())->linkResultDirectedEdges();	}	vector<MaximalEdgeRing*>* maxEdgeRings=buildMaximalEdgeRings(dirEdges);	vector<EdgeRing*> *freeHoleList=new vector<EdgeRing*>();	vector<MaximalEdgeRing*> *edgeRings=buildMinimalEdgeRings(maxEdgeRings,shellList,freeHoleList);	sortShellsAndHoles(edgeRings,shellList,freeHoleList);	placeFreeHoles(shellList, freeHoleList);	delete freeHoleList;	delete maxEdgeRings;	delete edgeRings;	//Assert: every hole on freeHoleList has a shell assigned to it}vector<Geometry*>* PolygonBuilder::getPolygons() {	vector<Geometry*> *resultPolyList=computePolygons(shellList);	return resultPolyList;}/*** for all DirectedEdges in result, form them into MaximalEdgeRings*/vector<MaximalEdgeRing*> *PolygonBuilder::buildMaximalEdgeRings(vector<DirectedEdge*> *dirEdges){	vector<MaximalEdgeRing*> *maxEdgeRings=new vector<MaximalEdgeRing*>();	for(int i=0;i<(int)dirEdges->size();i++) {		DirectedEdge *de=(*dirEdges)[i];		if (de->isInResult() && de->getLabel()->isArea()) {			// if this edge has not yet been processed			if (de->getEdgeRing()==NULL) {				MaximalEdgeRing *er=new MaximalEdgeRing(de,geometryFactory,cga);				maxEdgeRings->push_back(er);				//System.out.println("max node degree=" + er.getMaxDegree());			}		}	}	return maxEdgeRings;}vector<MaximalEdgeRing*> *PolygonBuilder::buildMinimalEdgeRings(vector<MaximalEdgeRing*> *maxEdgeRings,	vector<EdgeRing*> *newShellList, vector<EdgeRing*> *freeHoleList) {	vector<MaximalEdgeRing*> *edgeRings=new vector<MaximalEdgeRing*>();	for(int i=0;i<(int)maxEdgeRings->size();i++) {		MaximalEdgeRing *er=(*maxEdgeRings)[i];		if (er->getMaxNodeDegree()>2) {			er->linkDirectedEdgesForMinimalEdgeRings();			vector<MinimalEdgeRing*> *minEdgeRings=er->buildMinimalRings();			// at this point we can go ahead and attempt to place holes, if this EdgeRing is a polygon			//computePoints(minEdgeRings);			EdgeRing *shell=findShell(minEdgeRings);			if(shell!=NULL){				placePolygonHoles(shell,minEdgeRings);				newShellList->push_back(shell);			} else {				freeHoleList->insert(freeHoleList->end(),minEdgeRings->begin(),minEdgeRings->end());			}			delete er;			delete minEdgeRings;		} else {			edgeRings->push_back(er);		}	}	return edgeRings;}/*** This method takes a list of MinimalEdgeRings derived from a MaximalEdgeRing,* and tests whether they form a Polygon.  This is the case if there is a single shell* in the list.  In this case the shell is returned.* The other possibility is that they are a series of connected holes, in which case* no shell is returned.** @return the shell EdgeRing, if there is one* @return null, if all the rings are holes*/EdgeRing* PolygonBuilder::findShell(vector<MinimalEdgeRing*> *minEdgeRings) {	int shellCount=0;	EdgeRing *shell=NULL;	for(int i=0;i<(int)minEdgeRings->size();i++) {		EdgeRing *er=(*minEdgeRings)[i];		if (!er->isHole()) {			shell=er;			shellCount++;			// Should MinimalEdgeRing object pointed to			minEdgeRings->erase(minEdgeRings->begin()+i);			i--;		}	}	Assert::isTrue(shellCount <= 1, "found two shells in MinimalEdgeRing list");	return shell;}/*** This method assigns the holes for a Polygon (formed from a list of* MinimalEdgeRings) to its shell.* Determining the holes for a MinimalEdgeRing polygon serves two purposes:* <ul>* <li>it is faster than using a point-in-polygon check later on.* <li>it ensures correctness, since if the PIP test was used the point* chosen might lie on the shell, which might return an incorrect result from the* PIP test* </ul>*/void PolygonBuilder::placePolygonHoles(EdgeRing *shell,vector<MinimalEdgeRing*> *minEdgeRings) {	for(int i=0;i<(int)minEdgeRings->size();i++) {		MinimalEdgeRing *er=(*minEdgeRings)[i];		if (er->isHole()) {			er->setShell(shell);			minEdgeRings->erase(minEdgeRings->begin()+i);			i--;		}	}}/*** For all rings in the input list,* determine whether the ring is a shell or a hole* and add it to the appropriate list.* Due to the way the DirectedEdges were linked,* a ring is a shell if it is oriented CW, a hole otherwise.*/void PolygonBuilder::sortShellsAndHoles(vector<MaximalEdgeRing*> *edgeRings,												vector<EdgeRing*> *newShellList,												vector<EdgeRing*> *freeHoleList) {	for(int i=0;i<(int)edgeRings->size();i++) {		EdgeRing *er=(*edgeRings)[i];		er->setInResult();		if (er->isHole() ) {			freeHoleList->push_back(er);		} else {			newShellList->push_back(er);		}	}}/*** This method determines finds a containing shell for all holes* which have not yet been assigned to a shell.* These "free" holes should* all be <b>properly</b> contained in their parent shells, so it is safe to use the* <code>findEdgeRingContaining</code> method.* (This is the case because any holes which are NOT* properly contained (i.e. are connected to their* parent shell) would have formed part of a MaximalEdgeRing* and been handled in a previous step).*/void PolygonBuilder::placeFreeHoles(vector<EdgeRing*>* newShellList, vector<EdgeRing*> *freeHoleList) {	for(int i=0;i<(int)freeHoleList->size();i++) {		EdgeRing *hole=(*freeHoleList)[i];		// only place this hole if it doesn't yet have a shell		if (hole->getShell()==NULL) {			EdgeRing *shell=findEdgeRingContaining(hole,newShellList);			Assert::isTrue(shell!=NULL, "unable to assign hole to a shell");			hole->setShell(shell);		}	}}/*** Find the innermost enclosing shell EdgeRing containing the argument EdgeRing, if any.* The innermost enclosing ring is the <i>smallest</i> enclosing ring.* The algorithm used depends on the fact that:* <br>*  ring A contains ring B iff envelope(ring A) contains envelope(ring B)* <br>* This routine is only safe to use if the chosen point of the hole* is known to be properly contained in a shell* (which is guaranteed to be the case if the hole does not touch its shell)** @return containing EdgeRing, if there is one* @return null if no containing EdgeRing is found*/EdgeRing* PolygonBuilder::findEdgeRingContaining(EdgeRing *testEr,vector<EdgeRing*> *newShellList) {	LinearRing *testRing=testEr->getLinearRing();	const Envelope *testEnv=testRing->getEnvelopeInternal();	const Coordinate& testPt=testRing->getCoordinateN(0);	EdgeRing *minShell=NULL;	const Envelope *minEnv=NULL;	for(int i=0;i<(int)newShellList->size();i++) {		LinearRing *lr=NULL;		EdgeRing *tryShell=(*newShellList)[i];		LinearRing *tryRing=tryShell->getLinearRing();		const Envelope *tryEnv=tryRing->getEnvelopeInternal();		if (minShell!=NULL) {			lr=minShell->getLinearRing();			minEnv=lr->getEnvelopeInternal();		}		bool isContained=false;		CoordinateSequence *rcl = tryRing->getCoordinates();		if (tryEnv->contains(testEnv)			&& cga->isPointInRing(testPt,rcl))				isContained=true;		delete rcl;		// check if this new containing ring is smaller than the current minimum ring		if (isContained) {			if (minShell==NULL				|| minEnv->contains(tryEnv)) {					minShell=tryShell;			}		}		delete tryRing;		delete lr;		//delete tryEnv;	}	//delete minEnv;	delete testRing;	//delete testEnv;	return minShell;}vector<Geometry*>* PolygonBuilder::computePolygons(vector<EdgeRing*> *newShellList) {	vector<Geometry*> *resultPolyList=new vector<Geometry*>();	// add Polygons for all shells	for(int i=0;i<(int)newShellList->size();i++) {		EdgeRing *er=(*newShellList)[i];		Polygon *poly=er->toPolygon(geometryFactory);		resultPolyList->push_back(poly);	}	return resultPolyList;}/*** Checks the current set of shells (with their associated holes) to* see if any of them contain the point.*/bool PolygonBuilder::containsPoint(Coordinate& p) {	for(int i=0;i<(int)shellList->size();i++) {		EdgeRing *er=(*shellList)[i];		if (er->containsPoint(p))			return true;	}	return false;}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?