directededgestar.cpp

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

CPP
387
字号
/********************************************************************** * $Id: DirectedEdgeStar.cpp,v 1.5 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. * ********************************************************************** * $Log: DirectedEdgeStar.cpp,v $ * Revision 1.5  2004/12/08 13:54:43  strk * gcc warnings checked and fixed, general cleanups. * * Revision 1.4  2004/07/02 13:28:26  strk * Fixed all #include lines to reflect headers layout change. * Added client application build tips in README. * * Revision 1.3  2004/05/03 10:43:42  strk * Exception specification considered harmful - left as comment. * * Revision 1.2  2004/04/21 14:14:28  strk * Fixed bug in computeDepths * * Revision 1.1  2004/03/19 09:48:45  ybychkov * "geomgraph" and "geomgraph/indexl" upgraded to JTS 1.4 * * Revision 1.17  2003/11/12 15:43:38  strk * Added some more throw specifications * * Revision 1.16  2003/11/07 01:23:42  pramsey * Add standard CVS headers licence notices and copyrights to all cpp and h * files. * * **********************************************************************/#include <geos/geomgraph.h>#include <geos/util.h>namespace geos {DirectedEdgeStar::DirectedEdgeStar(){//	resultAreaEdgeList=new vector<DirectedEdge*>();	resultAreaEdgeList=NULL;	label=new Label();}DirectedEdgeStar::~DirectedEdgeStar(){	delete resultAreaEdgeList;	delete label;}/** * Insert a directed edge in the list */void DirectedEdgeStar::insert(EdgeEnd *ee){	DirectedEdge *de=(DirectedEdge*) ee;	insertEdgeEnd(de,de);}Label* DirectedEdgeStar::getLabel() {	return label;}int DirectedEdgeStar::getOutgoingDegree(){	int degree = 0;	for (vector<EdgeEnd*>::iterator it=getIterator();it<edgeList->end();it++) {		DirectedEdge *de=(DirectedEdge*) *it;		if (de->isInResult()) degree++;	}	return degree;}int DirectedEdgeStar::getOutgoingDegree(EdgeRing *er){	int degree = 0;	for (vector<EdgeEnd*>::iterator it=getIterator();it<edgeList->end();it++) {		DirectedEdge *de=(DirectedEdge*) *it;		if (de->getEdgeRing()==er) degree++;	}	return degree;}DirectedEdge* DirectedEdgeStar::getRightmostEdge() {	vector<EdgeEnd*> *edges=getEdges();	int size=(int)edges->size();	if (size<1) return NULL;//    EdgeEnd* e0=(EdgeEnd*) edges;    DirectedEdge *de0=(DirectedEdge*) (*edges)[0];	if (size==1) return de0;    DirectedEdge *deLast=(DirectedEdge*)(*edges)[size-1];	int quad0=de0->getQuadrant();	int quad1=deLast->getQuadrant();	if (Quadrant::isNorthern(quad0) && Quadrant::isNorthern(quad1))		return de0;	else if (!Quadrant::isNorthern(quad0) && !Quadrant::isNorthern(quad1))		return deLast;	else {		// edges are in different hemispheres - make sure we return one that is non-horizontal		//DirectedEdge *nonHorizontalEdge=NULL;		if (de0->getDy()!=0)			return de0;		else if (deLast->getDy()!=0)			return deLast;	}	Assert::shouldNeverReachHere("found two horizontal edges incident on node");	return NULL;}/** * Compute the labelling for all dirEdges in this star, as well * as the overall labelling */voidDirectedEdgeStar::computeLabelling(vector<GeometryGraph*> *geom)	//throw(TopologyException *){	// this call can throw a TopologyException 	// we don't have any cleanup to do...	EdgeEndStar::computeLabelling(geom);	// determine the overall labelling for this DirectedEdgeStar	// (i.e. for the node it is based at)	delete label;	label=new Label(Location::UNDEF);	for (vector<EdgeEnd*>::iterator it=getIterator();it<edgeList->end();it++) {		EdgeEnd *ee=*it;		Edge *e=ee->getEdge();		Label *eLabel=e->getLabel();		for (int i=0; i<2;i++) {			int eLoc=eLabel->getLocation(i);			if (eLoc==Location::INTERIOR || eLoc==Location::BOUNDARY)				label->setLocation(i,Location::INTERIOR);		}	}}/** * For each dirEdge in the star, * merge the label from the sym dirEdge into the label */void DirectedEdgeStar::mergeSymLabels(){	for (vector<EdgeEnd*>::iterator it=getIterator();it<edgeList->end();it++) {		DirectedEdge *de=(DirectedEdge*) *it;		Label *deLabel=de->getLabel();		deLabel->merge(de->getSym()->getLabel());	}}/** * Update incomplete dirEdge labels from the labelling for the node */void DirectedEdgeStar::updateLabelling(Label *nodeLabel){	for (vector<EdgeEnd*>::iterator it=getIterator();it<edgeList->end();it++) {		DirectedEdge *de=(DirectedEdge*) *it;		Label *deLabel=de->getLabel();		deLabel->setAllLocationsIfNull(0,nodeLabel->getLocation(0));		deLabel->setAllLocationsIfNull(1,nodeLabel->getLocation(1));	}}vector<DirectedEdge*>* DirectedEdgeStar::getResultAreaEdges() {	if (resultAreaEdgeList!=NULL) return resultAreaEdgeList;	resultAreaEdgeList=new vector<DirectedEdge*>();	for (vector<EdgeEnd*>::iterator it=getIterator();it<edgeList->end();it++) {		DirectedEdge *de=(DirectedEdge*) *it;		if (de->isInResult() || de->getSym()->isInResult())		resultAreaEdgeList->push_back(de);	}	return resultAreaEdgeList;}/** * Traverse the star of DirectedEdges, linking the included edges together. * To link two dirEdges, the <next> pointer for an incoming dirEdge * is set to the next outgoing edge. * <p> * DirEdges are only linked if: * <ul> * <li>they belong to an area (i.e. they have sides) * <li>they are marked as being in the result * </ul> * <p> * Edges are linked in CCW order (the order they are stored). * This means that rings have their face on the Right * (in other words, * the topological location of the face is given by the RHS label of the DirectedEdge) * <p> * PRECONDITION: No pair of dirEdges are both marked as being in the result */voidDirectedEdgeStar::linkResultDirectedEdges() 	// throw(TopologyException *){	// make sure edges are copied to resultAreaEdges list	getResultAreaEdges();	// find first area edge (if any) to start linking at	DirectedEdge *firstOut=NULL;	DirectedEdge *incoming=NULL;	int state=SCANNING_FOR_INCOMING;	// link edges in CCW order	for (unsigned int i=0; i<resultAreaEdgeList->size();i++) {        DirectedEdge *nextOut=(DirectedEdge*) (*resultAreaEdgeList)[i];		DirectedEdge *nextIn=nextOut->getSym();		// skip de's that we're not interested in		if (!nextOut->getLabel()->isArea()) continue;		// record first outgoing edge, in order to link the last incoming edge		if (firstOut==NULL && nextOut->isInResult()) firstOut=nextOut;		// assert: sym.isInResult() == false, since pairs of dirEdges should have been removed already		switch (state) {			case SCANNING_FOR_INCOMING:				if (!nextIn->isInResult()) continue;				incoming=nextIn;				state=LINKING_TO_OUTGOING;				break;			case LINKING_TO_OUTGOING:				if (!nextOut->isInResult()) continue;				incoming->setNext(nextOut);				state=SCANNING_FOR_INCOMING;				break;		}	}	if (state==LINKING_TO_OUTGOING) {		if (firstOut==NULL)			throw new TopologyException("no outgoing dirEdge found",&(getCoordinate()));//		Assert::isTrue(firstOut!=NULL, "no outgoing dirEdge found");		Assert::isTrue(firstOut->isInResult(), "unable to link last incoming dirEdge");		incoming->setNext(firstOut);	}}void DirectedEdgeStar::linkMinimalDirectedEdges(EdgeRing *er){	// find first area edge (if any) to start linking at	DirectedEdge *firstOut=NULL;	DirectedEdge *incoming=NULL;	int state=SCANNING_FOR_INCOMING;	// link edges in CW order	for (int i=(int)resultAreaEdgeList->size()-1;i>=0;i--) {        DirectedEdge *nextOut=(DirectedEdge*)(*resultAreaEdgeList)[i];		DirectedEdge *nextIn=nextOut->getSym();		// record first outgoing edge, in order to link the last incoming edge		if (firstOut==NULL && nextOut->getEdgeRing()==er) firstOut=nextOut;		switch (state) {			case SCANNING_FOR_INCOMING:				if (nextIn->getEdgeRing()!=er) continue;				incoming=nextIn;				state = LINKING_TO_OUTGOING;				break;			case LINKING_TO_OUTGOING:				if (nextOut->getEdgeRing()!=er) continue;				incoming->setNextMin(nextOut);				state = SCANNING_FOR_INCOMING;			break;		}	}	if (state==LINKING_TO_OUTGOING) {		Assert::isTrue(firstOut!=NULL, "found null for first outgoing dirEdge");		Assert::isTrue(firstOut->getEdgeRing()==er, "unable to link last incoming dirEdge");		incoming->setNextMin(firstOut);	}}void DirectedEdgeStar::linkAllDirectedEdges(){	getEdges();	// find first area edge (if any) to start linking at	DirectedEdge *prevOut=NULL;	DirectedEdge *firstIn=NULL;	// link edges in CW order	for(int i=(int)edgeList->size()-1;i>=0;i--) {        DirectedEdge *nextOut=(DirectedEdge*)(*edgeList)[i];		DirectedEdge *nextIn=nextOut->getSym();		if (firstIn==NULL) firstIn=nextIn;		if (prevOut!=NULL) nextIn->setNext(prevOut);		// record outgoing edge, in order to link the last incoming edge		prevOut=nextOut;	}	firstIn->setNext(prevOut);}/** * Traverse the star of edges, maintaing the current location in the result * area at this node (if any). * If any L edges are found in the interior of the result, mark them as covered. */void DirectedEdgeStar::findCoveredLineEdges(){	// Since edges are stored in CCW order around the node,	// as we move around the ring we move from the right to the left side of the edge	/**	 * Find first DirectedEdge of result area (if any).	 * The interior of the result is on the RHS of the edge,	 * so the start location will be:	 * - INTERIOR if the edge is outgoing	 * - EXTERIOR if the edge is incoming	 */	int startLoc=Location::UNDEF;    vector<EdgeEnd*>::iterator it;	for (it=getIterator();it<edgeList->end();it++) {		DirectedEdge *nextOut=(DirectedEdge*) *it;		DirectedEdge *nextIn=nextOut->getSym();		if (!nextOut->isLineEdge()) {			if (nextOut->isInResult()) {				startLoc=Location::INTERIOR;				break;			}			if (nextIn->isInResult()) {				startLoc=Location::EXTERIOR;				break;			}		}	}	// no A edges found, so can't determine if L edges are covered or not	if (startLoc==Location::UNDEF) return;	/**	 * move around ring, keeping track of the current location	 * (Interior or Exterior) for the result area.	 * If L edges are found, mark them as covered if they are in the interior	 */	int currLoc=startLoc;	for (it=getIterator();it<edgeList->end();it++) {		DirectedEdge *nextOut=(DirectedEdge*) *it;		DirectedEdge *nextIn=nextOut->getSym();		if (nextOut->isLineEdge()) {			nextOut->getEdge()->setCovered(currLoc==Location::INTERIOR);		} else {  // edge is an Area edge			if (nextOut->isInResult())				currLoc=Location::EXTERIOR;			if (nextIn->isInResult())				currLoc=Location::INTERIOR;		}	}}void DirectedEdgeStar::computeDepths(DirectedEdge *de){	int edgeIndex=findIndex(de);	//Label *deLabel=de->getLabel();	int startDepth=de->getDepth(Position::LEFT);	int targetLastDepth=de->getDepth(Position::RIGHT);	// compute the depths from this edge up to the end of the edge array	int nextDepth=computeDepths(edgeIndex+1, edgeList->size(), startDepth);	// compute the depths for the initial part of the array	int lastDepth=computeDepths(0,edgeIndex,nextDepth);	if (lastDepth!=targetLastDepth)		throw new TopologyException("depth mismatch at ",&(de->getCoordinate()));//	Assert::isTrue(lastDepth==targetLastDepth, "depth mismatch at " + de->getCoordinate().toString());}/** * Compute the DirectedEdge depths for a subsequence of the edge array. * * @return the last depth assigned (from the R side of the last edge visited) */int DirectedEdgeStar::computeDepths(int startIndex,int endIndex,int startDepth){	int currDepth=startDepth;	for (int i=startIndex;i<endIndex;i++) {        DirectedEdge *nextDe=(DirectedEdge*)(*edgeList)[i];		//Label *deLabel=nextDe->getLabel();		nextDe->setEdgeDepths(Position::RIGHT, currDepth);		currDepth=nextDe->getDepth(Position::LEFT);	}	return currDepth;}string DirectedEdgeStar::print() {	string out="DirectedEdgeStar: " + getCoordinate().toString();	for (vector<EdgeEnd*>::iterator it=getIterator();it<edgeList->end();it++) {		DirectedEdge *de=(DirectedEdge*) *it;		out+="out ";		out+=de->print();		out+="\n";		out+="in ";		out+=de->getSym()->print();		out+="\n";	}	return out;}}

⌨️ 快捷键说明

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