⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linesequencer.cpp

📁 在Linux下做的QuadTree的程序
💻 CPP
字号:
/********************************************************************** * $Id: LineSequencer.cpp 1820 2006-09-06 16:54:23Z mloskot $ * * GEOS - Geometry Engine Open Source * http://geos.refractions.net * * Copyright (C) 2006 Refractions Research 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. * ********************************************************************** * * Last port: operation/linemerge/LineSequencer.java rev. 1.5 (JTS-1.7) * **********************************************************************/#include <geos/operation/linemerge/LineSequencer.h>#include <geos/operation/linemerge/LineMergeEdge.h>#include <geos/geom/Geometry.h>#include <geos/geom/GeometryFactory.h>#include <geos/geom/MultiLineString.h>#include <geos/geom/Coordinate.h>#include <geos/geom/CoordinateSequence.h>#include <geos/geom/LineString.h>#include <geos/planargraph/Node.h>#include <geos/planargraph/DirectedEdge.h>#include <geos/planargraph/Subgraph.h>#include <geos/planargraph/algorithm/ConnectedSubgraphFinder.h>#include <geos/util/Assert.h>#include <cassert>#include <limits>#include <vector>using namespace std;//using namespace geos::planargraph;using namespace geos::geom;//using namespace geos::planargraph::algorithm;namespace geos {namespace operation { // geos.operationnamespace linemerge { // geos.operation.linemerge/* static */boolLineSequencer::isSequenced(const Geometry* geom){	const MultiLineString *mls;	if ( ! (mls=dynamic_cast<const MultiLineString *>(geom)) )	{		return true;	}	// the nodes in all subgraphs which have been completely scanned	Coordinate::ConstSet prevSubgraphNodes;	Coordinate::ConstVect currNodes;	const Coordinate* lastNode = NULL;	for (unsigned int i=0, n=mls->getNumGeometries(); i<n; ++i)	{		assert(dynamic_cast<const LineString*>(mls->getGeometryN(i)));		const LineString& line = \			static_cast<const LineString&>(*(mls->getGeometryN(i)));		const Coordinate* startNode = &(line.getCoordinateN(0));		const Coordinate* endNode = &(line.getCoordinateN(line.getNumPoints() - 1));		/**		 * If this linestring is connected to a previous subgraph,		 * geom is not sequenced		 */		if (prevSubgraphNodes.find(startNode) != prevSubgraphNodes.end())		{			return false;		}		if (prevSubgraphNodes.find(endNode) != prevSubgraphNodes.end())		{			return false;		}		if (lastNode != NULL)		{			if (! startNode->equals2D(*lastNode))			{				// start new connected sequence				prevSubgraphNodes.insert(currNodes.begin(),						currNodes.end());				currNodes.clear();			}		}		currNodes.push_back(startNode);		currNodes.push_back(endNode);		lastNode = endNode;	}	return true;} /* private */boolLineSequencer::hasSequence(planargraph::Subgraph& graph){	int oddDegreeCount = 0;	for (planargraph::NodeMap::container::const_iterator		it=graph.nodeBegin(), endIt=graph.nodeEnd();		it!=endIt;		++it)	{		planargraph::Node* node = it->second;		if (node->getDegree() % 2 == 1)		oddDegreeCount++;	}	return oddDegreeCount <= 2;}/*private*/LineSequencer::Sequences*LineSequencer::findSequences(){	Sequences *sequences = new Sequences();	planargraph::algorithm::ConnectedSubgraphFinder csFinder(graph);	vector<planargraph::Subgraph*>subgraphs;	csFinder.getConnectedSubgraphs(subgraphs);	for (vector<planargraph::Subgraph*>::const_iterator		it=subgraphs.begin(), endIt=subgraphs.end();		it!=endIt;		++it )	{		planargraph::Subgraph* subgraph = *it;		if (hasSequence(*subgraph)) {			planargraph::DirectedEdge::NonConstList* seq=findSequence(*subgraph);			sequences->push_back(seq);		}		else {			// if any subgraph cannot be sequenced, abort			return NULL;		}	}	return sequences;}/*private*/voidLineSequencer::addLine(const LineString *lineString){	if (factory == NULL) {		factory = lineString->getFactory();	}	graph.addEdge(lineString);	++lineCount;}/* private */voidLineSequencer::computeSequence(){	if (isRun) return;	isRun = true;	Sequences* sequences(findSequences());	if (sequences == NULL) return;	sequencedGeometry = auto_ptr<Geometry>(buildSequencedGeometry(*sequences));	isSequenceableVar = true;	// Lines were missing from result	assert(lineCount == sequencedGeometry->getNumGeometries());	// Result is not linear	assert(dynamic_cast<LineString *>(sequencedGeometry.get())		|| dynamic_cast<MultiLineString *>(sequencedGeometry.get())); }/*private*/Geometry*LineSequencer::buildSequencedGeometry(const Sequences& sequences){	auto_ptr<Geometry::NonConstVect> lines(new Geometry::NonConstVect);	for (Sequences::const_iterator		i1=sequences.begin(), i1End=sequences.end();		i1 != i1End;		++i1)	{		planargraph::DirectedEdge::NonConstList& seq = *(*i1);		for(planargraph::DirectedEdge::NonConstList::iterator i2=seq.begin(),			i2End=seq.end(); i2 != i2End; ++i2)		{			const planargraph::DirectedEdge* de = *i2;			assert(dynamic_cast<LineMergeEdge* >(de->getEdge()));			LineMergeEdge* e = static_cast<LineMergeEdge* >(de->getEdge());			const LineString* line = e->getLine();			// lineToAdd will be a *copy* of input things			LineString* lineToAdd;			if ( ! de->getEdgeDirection() && ! line->isClosed() ) {				lineToAdd = reverse(line);			} else {				Geometry* lineClone = line->clone();				assert(dynamic_cast<LineString *>(lineClone));				lineToAdd = static_cast<LineString *>(lineClone); 			}			lines->push_back(lineToAdd);		}	}	if ( lines->size() == 0 ) {		return NULL;	} else {		Geometry::NonConstVect *l=lines.get();		lines.release();		return factory->buildGeometry(l);	}}/*static private*/LineString *LineSequencer::reverse(const LineString *line){	CoordinateSequence* cs=line->getCoordinates();	CoordinateSequence::reverse(cs);	return line->getFactory()->createLineString(cs);}/*private static*/const planargraph::Node*LineSequencer::findLowestDegreeNode(const planargraph::Subgraph& graph){	size_t minDegree = numeric_limits<size_t>::max(); 	const planargraph::Node* minDegreeNode = NULL;	for (planargraph::NodeMap::container::const_iterator		it = graph.nodeBegin(), itEnd = graph.nodeEnd();		it != itEnd;		++it )	{		const planargraph::Node* node = (*it).second;		if (minDegreeNode == NULL || node->getDegree() < minDegree)		{			minDegree = node->getDegree();			minDegreeNode = node;		}	}	return minDegreeNode;}/*private static*/const planargraph::DirectedEdge*LineSequencer::findUnvisitedBestOrientedDE(const planargraph::Node* node){	using planargraph::DirectedEdge;	using planargraph::DirectedEdgeStar;	const DirectedEdge* wellOrientedDE = NULL;	const DirectedEdge* unvisitedDE = NULL;	const DirectedEdgeStar* des=node->getOutEdges();	for (DirectedEdge::NonConstVect::const_iterator i=des->begin(),		e=des->end();		i!=e;		++i)	{		planargraph::DirectedEdge* de = *i;		if (! de->getEdge()->isVisited()) {			unvisitedDE = de;			if (de->getEdgeDirection()) wellOrientedDE = de;		}	}	if (wellOrientedDE != NULL)		return wellOrientedDE;	return unvisitedDE;}/*private*/voidLineSequencer::addReverseSubpath(const planargraph::DirectedEdge *de,		planargraph::DirectedEdge::NonConstList& deList,		planargraph::DirectedEdge::NonConstList::iterator lit,		bool expectedClosed){	using planargraph::Node;	using planargraph::DirectedEdge;	// trace an unvisited path *backwards* from this de	Node* endNode = de->getToNode();	Node* fromNode = NULL;	while (true) {		deList.insert(lit, de->getSym());		de->getEdge()->setVisited(true);		fromNode = de->getFromNode();		const DirectedEdge* unvisitedOutDE = findUnvisitedBestOrientedDE(fromNode);		// this must terminate, since we are continually marking edges as visited		if (unvisitedOutDE == NULL) break;		de = unvisitedOutDE->getSym();	}	if ( expectedClosed ) {		// the path should end at the toNode of this de,		// otherwise we have an error		util::Assert::isTrue(fromNode == endNode, "path not contiguos");		//assert(fromNode == endNode);	}}/*private*/planargraph::DirectedEdge::NonConstList* LineSequencer::findSequence(planargraph::Subgraph& graph){	using planargraph::DirectedEdge;	using planargraph::Node;	using planargraph::GraphComponent;	GraphComponent::setVisited(graph.edgeBegin(),			graph.edgeEnd(), false);	const Node* startNode = findLowestDegreeNode(graph);	const DirectedEdge *startDE = *(startNode->getOutEdges()->begin());	const DirectedEdge *startDESym = startDE->getSym();	DirectedEdge::NonConstList *seq = new DirectedEdge::NonConstList();	DirectedEdge::NonConstList::iterator lit=seq->begin();	addReverseSubpath(startDESym, *seq, lit, false);	lit=seq->end();	while (lit != seq->begin()) {		const DirectedEdge* prev = *(--lit);		const DirectedEdge* unvisitedOutDE = findUnvisitedBestOrientedDE(prev->getFromNode());		if (unvisitedOutDE != NULL)			addReverseSubpath(unvisitedOutDE->getSym(), *seq, lit, true);	}	// At this point, we have a valid sequence of graph DirectedEdges,	// but it is not necessarily appropriately oriented relative to	// the underlying geometry.	DirectedEdge::NonConstList* orientedSeq = orient(seq);	if (orientedSeq != seq) delete seq;	return orientedSeq;}/* private */planargraph::DirectedEdge::NonConstList* LineSequencer::orient(planargraph::DirectedEdge::NonConstList* seq) {	using namespace geos::planargraph;	const DirectedEdge* startEdge = seq->front();	const DirectedEdge* endEdge = seq->back();	Node* startNode = startEdge->getFromNode();	Node* endNode = endEdge->getToNode();	bool flipSeq = false;	bool hasDegree1Node = \		startNode->getDegree() == 1 || endNode->getDegree() == 1;	if (hasDegree1Node)	{		bool hasObviousStartNode = false;		// test end edge before start edge, to make result stable		// (ie. if both are good starts, pick the actual start		if (endEdge->getToNode()->getDegree() == 1 &&				endEdge->getEdgeDirection() == false)		{			hasObviousStartNode = true;			flipSeq = true;		}		if (startEdge->getFromNode()->getDegree() == 1 && 				startEdge->getEdgeDirection() == true)		{			hasObviousStartNode = true;			flipSeq = false;		}		// since there is no obvious start node,		// use any node of degree 1		if (! hasObviousStartNode)		{			// check if the start node should actually			// be the end node			if (startEdge->getFromNode()->getDegree() == 1)				flipSeq = true;			// if the end node is of degree 1, it is			// properly the end node		}	}	// if there is no degree 1 node, just use the sequence as is	// (Could insert heuristic of taking direction of majority of	// lines as overall direction)	if (flipSeq)	{		return reverse(*seq);	}	return seq;}/* private */planargraph::DirectedEdge::NonConstList* LineSequencer::reverse(planargraph::DirectedEdge::NonConstList& seq){	using namespace geos::planargraph;	DirectedEdge::NonConstList* newSeq = new DirectedEdge::NonConstList();	DirectedEdge::NonConstList::iterator it=seq.begin(), itEnd=seq.end();	for (; it!=itEnd; ++it) {		const DirectedEdge *de = *it;		newSeq->push_front(de->getSym());	}	return newSeq;} } // namespace geos.operation.linemerge} // namespace geos.operation} // namespace geos/********************************************************************** * $Log$ * Revision 1.10  2006/06/12 10:49:43  strk * unsigned int => size_t * * Revision 1.9  2006/03/24 11:04:44  strk * Changed assert() with Assert::isTrue in addReverseSubpath * * Revision 1.8  2006/03/24 10:44:07  strk * Fixed to build with -DNDEBUG * * Revision 1.7  2006/03/22 10:13:54  strk * opLinemerge.h split * * Revision 1.6  2006/03/21 21:42:54  strk * planargraph.h header split, planargraph:: classes renamed to match JTS symbols * **********************************************************************/

⌨️ 快捷键说明

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