polygonizegraph.cpp
来自「一个很好的vc底层代码」· C++ 代码 · 共 466 行
CPP
466 行
/********************************************************************** * $Id: PolygonizeGraph.cpp,v 1.8 2004/12/14 10:35:44 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 <geos/opPolygonize.h>#include <geos/util.h>namespace geos {int PolygonizeGraph::getDegreeNonDeleted(planarNode *node) { vector<planarDirectedEdge*> *edges=node->getOutEdges()->getEdges(); int degree=0; for(int i=0;i<(int)edges->size();i++) { PolygonizeDirectedEdge *de=(PolygonizeDirectedEdge*) (*edges)[i]; if (!de->isMarked()) degree++; } return degree;}int PolygonizeGraph::getDegree(planarNode *node, long label){ vector<planarDirectedEdge*> *edges=node->getOutEdges()->getEdges(); int degree=0; for(int i=0;i<(int)edges->size();i++) { PolygonizeDirectedEdge *de=(PolygonizeDirectedEdge*) (*edges)[i]; if (de->getLabel()==label) degree++; } return degree;}/** * Deletes all edges at a node */voidPolygonizeGraph::deleteAllEdges(planarNode *node){ vector<planarDirectedEdge*> *edges=node->getOutEdges()->getEdges(); for(int i=0;i<(int)edges->size();i++) { PolygonizeDirectedEdge *de=(PolygonizeDirectedEdge*) (*edges)[i]; de->setMarked(true); PolygonizeDirectedEdge *sym=(PolygonizeDirectedEdge*) de->getSym(); if (sym!=NULL) sym->setMarked(true); }}/* * Create a new polygonization graph. */PolygonizeGraph::PolygonizeGraph(const GeometryFactory *newFactory){ factory=newFactory;}/* * Destroy a PolygonizeGraph */PolygonizeGraph::~PolygonizeGraph(){ unsigned int i; for (i=0; i<newEdges.size(); i++) delete newEdges[i]; for (i=0; i<newDirEdges.size(); i++) delete newDirEdges[i]; for (i=0; i<newNodes.size(); i++) delete newNodes[i]; for (i=0; i<newEdgeRings.size(); i++) delete newEdgeRings[i]; for (i=0; i<newCoords.size(); i++) delete newCoords[i];}/* * Add a LineString forming an edge of the polygon graph. * @param line the line to add */voidPolygonizeGraph::addEdge(const LineString *line){ if (line->isEmpty()) return; CoordinateSequence *linePts=CoordinateSequence::removeRepeatedPoints(line->getCoordinatesRO()); const Coordinate& startPt=linePts->getAt(0); const Coordinate& endPt=linePts->getAt(linePts->getSize()-1); planarNode *nStart=getNode(startPt); planarNode *nEnd=getNode(endPt); planarDirectedEdge *de0=new PolygonizeDirectedEdge(nStart, nEnd, linePts->getAt(1), true); newDirEdges.push_back(de0); planarDirectedEdge *de1=new PolygonizeDirectedEdge(nEnd, nStart, linePts->getAt(linePts->getSize()-2), false); newDirEdges.push_back(de1); planarEdge *edge=new PolygonizeEdge(line); newEdges.push_back(edge); edge->setDirectedEdges(de0, de1); add(edge); newCoords.push_back(linePts);}planarNode *PolygonizeGraph::getNode(const Coordinate& pt){ planarNode *node=findNode(pt); if (node==NULL) { node=new planarNode(pt); newNodes.push_back(node); // ensure node is only added once to graph add(node); } return node;}voidPolygonizeGraph::computeNextCWEdges(){ vector<planarNode*> *pns=getNodes(); // set the next pointers for the edges around each node for(int i=0;i<(int)pns->size();i++) { planarNode *node=(*pns)[i]; computeNextCWEdges(node); } delete pns;}/* * Convert the maximal edge rings found by the initial graph traversal * into the minimal edge rings required by JTS polygon topology rules. * * @param ringEdges the list of start edges for the edgeRings to convert. */voidPolygonizeGraph::convertMaximalToMinimalEdgeRings(vector<PolygonizeDirectedEdge*> *ringEdges){ for(int i=0;i<(int)ringEdges->size();i++) { PolygonizeDirectedEdge *de=(*ringEdges)[i]; long label=de->getLabel(); vector<planarNode*> *intNodes=findIntersectionNodes(de, label); if (intNodes==NULL) continue; // flip the next pointers on the intersection nodes to // create minimal edge rings //vector<planarNode*> *pns=getNodes(); // set the next pointers for the edges around each node for(int j=0;j<(int)intNodes->size();j++) { planarNode *node=(*intNodes)[j]; computeNextCCWEdges(node, label); } delete intNodes; }}/* * Finds all nodes in a maximal edgering which are self-intersection nodes * @param startDE * @param label * @return the list of intersection nodes found, * or <code>NULL</code> if no intersection nodes were found. * Ownership of returned object goes to caller. */vector<planarNode*>*PolygonizeGraph::findIntersectionNodes(PolygonizeDirectedEdge *startDE, long label){ PolygonizeDirectedEdge *de=startDE; vector<planarNode*> *intNodes=NULL; do { planarNode *node=de->getFromNode(); if (getDegree(node, label) > 1) { if (intNodes==NULL) intNodes=new vector<planarNode*>(); intNodes->push_back(node); } de=de->getNext(); Assert::isTrue(de!=NULL, "found NULL DE in ring"); Assert::isTrue(de==startDE || !de->isInRing(), "found DE already in ring"); } while (de!=startDE); return intNodes;}/** * Computes the EdgeRings formed by the edges in this graph. * @return a list of the EdgeRing found by the polygonization process. */vector<polygonizeEdgeRing*>*PolygonizeGraph::getEdgeRings(){ // maybe could optimize this, since most of these pointers should // be set correctly already // by deleteCutEdges() computeNextCWEdges(); // clear labels of all edges in graph label(dirEdges,-1); vector<PolygonizeDirectedEdge*> *maximalRings=findLabeledEdgeRings(dirEdges); convertMaximalToMinimalEdgeRings(maximalRings); delete maximalRings; // find all edgerings vector<polygonizeEdgeRing*> *edgeRingList=new vector<polygonizeEdgeRing*>(); for(int i=0;i<(int)dirEdges->size();i++) { PolygonizeDirectedEdge *de=(PolygonizeDirectedEdge*)(*dirEdges)[i]; if (de->isMarked()) continue; if (de->isInRing()) continue; polygonizeEdgeRing *er=findEdgeRing(de); edgeRingList->push_back(er); } return edgeRingList;}/**** @param dirEdges a List of the DirectedEdges in the graph* @return a List of DirectedEdges, one for each edge ring found*/vector<PolygonizeDirectedEdge*>*PolygonizeGraph::findLabeledEdgeRings(vector<planarDirectedEdge*> *dirEdges){ vector<PolygonizeDirectedEdge*> *edgeRingStarts=new vector<PolygonizeDirectedEdge*>(); // label the edge rings formed long currLabel=1; for(int i=0;i<(int)dirEdges->size();i++) { PolygonizeDirectedEdge *de=(PolygonizeDirectedEdge*)(*dirEdges)[i]; if (de->isMarked()) continue; if (de->getLabel() >= 0) continue; edgeRingStarts->push_back(de); vector<planarDirectedEdge*> *edges=findDirEdgesInRing(de); label(edges, currLabel); delete edges; currLabel++; } return edgeRingStarts;}/* * Finds and removes all cut edges from the graph. * @return a list of the LineString forming the removed cut edges */vector<const LineString*> *PolygonizeGraph::deleteCutEdges(){ computeNextCWEdges(); // label the current set of edgerings delete findLabeledEdgeRings(dirEdges); /* * Cut Edges are edges where both dirEdges have the same label. * Delete them, and record them */ vector<const LineString*> *cutLines=new vector<const LineString*>(); for(int i=0;i<(int)dirEdges->size();i++) { PolygonizeDirectedEdge *de=(PolygonizeDirectedEdge*)(*dirEdges)[i]; if (de->isMarked()) continue; PolygonizeDirectedEdge *sym=(PolygonizeDirectedEdge*) de->getSym(); if (de->getLabel()==sym->getLabel()) { de->setMarked(true); sym->setMarked(true); // save the line as a cut edge PolygonizeEdge *e=(PolygonizeEdge*) de->getEdge(); cutLines->push_back(e->getLine()); } } return cutLines;}void PolygonizeGraph::label(vector<planarDirectedEdge*> *dirEdges, long label){ for(int i=0;i<(int)dirEdges->size();i++) { PolygonizeDirectedEdge *de=(PolygonizeDirectedEdge*)(*dirEdges)[i]; de->setLabel(label); }}void PolygonizeGraph::computeNextCWEdges(planarNode *node){ planarDirectedEdgeStar *deStar=node->getOutEdges(); PolygonizeDirectedEdge *startDE=NULL; PolygonizeDirectedEdge *prevDE=NULL; // the edges are stored in CCW order around the star vector<planarDirectedEdge*> *pde=deStar->getEdges(); for(int i=0;i<(int)pde->size();i++) { PolygonizeDirectedEdge *outDE=(PolygonizeDirectedEdge*)(*pde)[i]; if (outDE->isMarked()) continue; if (startDE==NULL) startDE=outDE; if (prevDE!=NULL) { PolygonizeDirectedEdge *sym=(PolygonizeDirectedEdge*) prevDE->getSym(); sym->setNext(outDE); } prevDE=outDE; } if (prevDE!=NULL) { PolygonizeDirectedEdge *sym=(PolygonizeDirectedEdge*) prevDE->getSym(); sym->setNext(startDE); }}/*** Computes the next edge pointers going CCW around the given node, for the* given edgering label.* This algorithm has the effect of converting maximal edgerings into minimal edgerings*/void PolygonizeGraph::computeNextCCWEdges(planarNode *node, long label) { planarDirectedEdgeStar *deStar=node->getOutEdges(); PolygonizeDirectedEdge *firstOutDE=NULL; PolygonizeDirectedEdge *prevInDE=NULL; // the edges are stored in CCW order around the star vector<planarDirectedEdge*> *edges=deStar->getEdges(); for(int i=(int)edges->size()-1;i>=0;i--) { PolygonizeDirectedEdge *de=(PolygonizeDirectedEdge*)(*edges)[i]; PolygonizeDirectedEdge *sym=(PolygonizeDirectedEdge*) de->getSym(); PolygonizeDirectedEdge *outDE=NULL; if (de->getLabel()==label) outDE=de; PolygonizeDirectedEdge *inDE=NULL; if (sym->getLabel()==label) inDE= sym; if (outDE==NULL && inDE==NULL) continue; // this edge is not in edgering if (inDE != NULL) { prevInDE=inDE; } if (outDE != NULL) { if (prevInDE != NULL) { prevInDE->setNext(outDE); prevInDE=NULL; } if (firstOutDE==NULL) firstOutDE=outDE; } } if (prevInDE != NULL) { Assert::isTrue(firstOutDE != NULL); prevInDE->setNext(firstOutDE); }}/* * Traverse a ring of DirectedEdges, accumulating them into a list. * This assumes that all dangling directed edges have been removed * from the graph, so that there is always a next dirEdge. * * @param startDE the DirectedEdge to start traversing at * @return a List of DirectedEdges that form a ring */vector<planarDirectedEdge*>*PolygonizeGraph::findDirEdgesInRing(PolygonizeDirectedEdge *startDE){ PolygonizeDirectedEdge *de=startDE; vector<planarDirectedEdge*> *edges=new vector<planarDirectedEdge*>(); do { edges->push_back(de); de=de->getNext(); Assert::isTrue(de != NULL, "found NULL DE in ring"); Assert::isTrue(de==startDE || !de->isInRing(), "found DE already in ring"); } while (de != startDE); return edges;}polygonizeEdgeRing *PolygonizeGraph::findEdgeRing(PolygonizeDirectedEdge *startDE){ PolygonizeDirectedEdge *de=startDE; polygonizeEdgeRing *er=new polygonizeEdgeRing(factory); // Now, when will we delete those polygonizeEdgeRings ? newEdgeRings.push_back(er); do { er->add(de); de->setRing(er); de=de->getNext(); Assert::isTrue(de != NULL, "found NULL DE in ring"); Assert::isTrue(de==startDE || ! de->isInRing(), "found DE already in ring"); } while (de != startDE); return er;}/** * Marks all edges from the graph which are "dangles". * Dangles are which are incident on a node with degree 1. * This process is recursive, since removing a dangling edge * may result in another edge becoming a dangle. * In order to handle large recursion depths efficiently, * an explicit recursion stack is used * * @return a List containing the LineStrings that formed dangles */vector<const LineString*>*PolygonizeGraph::deleteDangles(){ vector<planarNode*> *nodesToRemove=findNodesOfDegree(1); vector<const LineString*> *dangleLines=new vector<const LineString*>(); vector<planarNode*> nodeStack; for(int i=0;i<(int)nodesToRemove->size();i++) { nodeStack.push_back((*nodesToRemove)[i]); } delete nodesToRemove; while (!nodeStack.empty()) { planarNode *node=nodeStack[nodeStack.size()-1]; nodeStack.pop_back(); deleteAllEdges(node); vector<planarDirectedEdge*> *nodeOutEdges=node->getOutEdges()->getEdges(); for(int j=0;j<(int)nodeOutEdges->size();j++) { PolygonizeDirectedEdge *de=(PolygonizeDirectedEdge*) (*nodeOutEdges)[j]; // delete this edge and its sym de->setMarked(true); PolygonizeDirectedEdge *sym=(PolygonizeDirectedEdge*) de->getSym(); if (sym != NULL) sym->setMarked(true); // save the line as a dangle PolygonizeEdge *e=(PolygonizeEdge*) de->getEdge(); dangleLines->push_back(e->getLine()); planarNode *toNode=de->getToNode(); // add the toNode to the list to be processed, if it is now a dangle if (getDegreeNonDeleted(toNode)==1) nodeStack.push_back(toNode); } } return dangleLines;}}/********************************************************************** * $Log: PolygonizeGraph.cpp,v $ * Revision 1.8 2004/12/14 10:35:44 strk * Comments cleanup. PolygonizeGraph keeps track of generated CoordinateSequence * for delayed destruction. * * Revision 1.7 2004/12/08 13:54:44 strk * gcc warnings checked and fixed, general cleanups. * * Revision 1.6 2004/10/26 16:09:21 strk * Some more intentation and envelope equality check fix. * * Revision 1.5 2004/10/19 19:51:14 strk * Fixed many leaks and bugs in Polygonizer. * Output still bogus. * * Revision 1.4 2004/10/13 10:03:02 strk * Added missing linemerge and polygonize operation. * Bug fixes and leaks removal from the newly added modules and * planargraph (used by them). * Some comments and indentation changes. * * Revision 1.3 2004/07/08 19:34:50 strk * Mirrored JTS interface of CoordinateSequence, factory and * default implementations. * Added DefaultCoordinateSequenceFactory::instance() function. * * Revision 1.2 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.1 2004/04/08 04:53:56 ybychkov * "operation/polygonize" ported from JTS 1.4 * * **********************************************************************/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?