📄 isvalidop.cpp
字号:
/********************************************************************** * $Id: IsValidOp.cpp 1820 2006-09-06 16:54:23Z mloskot $ * * GEOS - Geometry Engine Open Source * http://geos.refractions.net * * Copyright (C) 2001-2002 Vivid Solutions Inc. * Copyright (C) 2005 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/valid/IsValidOp.java rev. 1.39 (JTS-1.7) * **********************************************************************/#include <geos/operation/valid/IsValidOp.h>#include <geos/operation/valid/ConsistentAreaTester.h>#include <geos/operation/valid/QuadtreeNestedRingTester.h>#include <geos/operation/valid/ConnectedInteriorTester.h>#include <geos/util/UnsupportedOperationException.h>#include <geos/geomgraph/index/SegmentIntersector.h> #include <geos/geomgraph/GeometryGraph.h> #include <geos/geomgraph/Edge.h> #include <geos/algorithm/MCPointInRing.h> #include <geos/algorithm/CGAlgorithms.h> #include <geos/algorithm/LineIntersector.h> #include <geos/geom/CoordinateSequence.h>#include <geos/geom/LineString.h>#include <geos/geom/LinearRing.h>#include <geos/geom/Point.h>#include <geos/geom/Polygon.h>#include <geos/geom/MultiPolygon.h>#include <geos/geom/GeometryCollection.h>#include <typeinfo>#include <set>#include <cassert>using namespace std;using namespace geos::algorithm;using namespace geos::geomgraph;using namespace geos::geom;namespace geos {namespace operation { // geos.operationnamespace valid { // geos.operation.valid/** * Find a point from the list of testCoords * that is NOT a node in the edge for the list of searchCoords * * @return the point found, or <code>null</code> if none found */const Coordinate *IsValidOp::findPtNotNode(const CoordinateSequence *testCoords, const LinearRing *searchRing, GeometryGraph *graph){ // find edge corresponding to searchRing. Edge *searchEdge=graph->findEdge(searchRing); // find a point in the testCoords which is not a node of the searchRing EdgeIntersectionList &eiList=searchEdge->getEdgeIntersectionList(); // somewhat inefficient - is there a better way? (Use a node map, for instance?) unsigned int npts=testCoords->getSize(); for(unsigned int i=0; i<npts; ++i) { const Coordinate& pt=testCoords->getAt(i); if (!eiList.isIntersection(pt)) { return &pt; } } return NULL;}boolIsValidOp::isValid(){ checkValid(parentGeometry); return validErr==NULL;}/* * Checks whether a coordinate is valid for processing. * Coordinates are valid iff their x and y coordinates are in the * range of the floating point representation. * * @param coord the coordinate to validate * @return <code>true</code> if the coordinate is valid */boolIsValidOp::isValid(const Coordinate &coord){ if (! FINITE(coord.x) ) return false; if (! FINITE(coord.y) ) return false; return true;}TopologyValidationError *IsValidOp::getValidationError(){ checkValid(parentGeometry); return validErr;}voidIsValidOp::checkValid(const Geometry *g){ if (isChecked) return; validErr=NULL; // empty geometries are always valid! if (g->isEmpty()) return; const GeometryCollection *gc; if (typeid(*g)==typeid(Point)) checkValid((Point *)g); else if (typeid(*g)==typeid(LinearRing)) checkValid((LinearRing*)g); else if (typeid(*g)==typeid(LineString)) checkValid((LineString*)g); else if (typeid(*g)==typeid(Polygon)) checkValid((Polygon*)g); else if (typeid(*g)==typeid(MultiPolygon)) checkValid((MultiPolygon*)g); else if ((gc=dynamic_cast<const GeometryCollection *>(g))) checkValid(gc); else throw util::UnsupportedOperationException();}/* * Checks validity of a Point. */voidIsValidOp::checkValid(const Point *g){ checkInvalidCoordinates(g->getCoordinatesRO());}/* * Checks validity of a LineString. Almost anything goes for linestrings! */voidIsValidOp::checkValid(const LineString *g){ checkInvalidCoordinates(g->getCoordinatesRO()); if (validErr != NULL) return; GeometryGraph graph(0,g); checkTooFewPoints(&graph);}/** * Checks validity of a LinearRing. */voidIsValidOp::checkValid(const LinearRing *g){ checkInvalidCoordinates(g->getCoordinatesRO()); if (validErr != NULL) return; checkClosedRing(g); if (validErr != NULL) return; GeometryGraph graph(0, g); checkTooFewPoints(&graph); if (validErr!=NULL) return; LineIntersector li; delete graph.computeSelfNodes(&li, true); checkNoSelfIntersectingRings(&graph);}/** * Checks the validity of a polygon. * Sets the validErr flag. */voidIsValidOp::checkValid(const Polygon *g){ checkInvalidCoordinates(g); if (validErr != NULL) return; checkClosedRings(g); if (validErr != NULL) return; GeometryGraph graph(0,g); checkTooFewPoints(&graph); if (validErr!=NULL) return; checkConsistentArea(&graph); if (validErr!=NULL) return; if (!isSelfTouchingRingFormingHoleValid) { checkNoSelfIntersectingRings(&graph); if (validErr!=NULL) return; } checkHolesInShell(g,&graph); if (validErr!=NULL) return; checkHolesNotNested(g,&graph); if (validErr!=NULL) return; checkConnectedInteriors(graph);}voidIsValidOp::checkValid(const MultiPolygon *g){ unsigned int ngeoms = g->getNumGeometries(); vector<const Polygon *>polys(ngeoms); for (unsigned int i=0; i<ngeoms; ++i) { const Polygon *p = (const Polygon *)g->getGeometryN(i); checkInvalidCoordinates(p); if (validErr != NULL) return; checkClosedRings(p); if (validErr != NULL) return; polys[i]=p; } GeometryGraph graph(0,g); checkTooFewPoints(&graph); if (validErr!=NULL) return; checkConsistentArea(&graph); if (validErr!=NULL) return; if (!isSelfTouchingRingFormingHoleValid) { checkNoSelfIntersectingRings(&graph); if (validErr!=NULL) return; } for(unsigned int i=0; i<ngeoms; ++i) { const Polygon *p=polys[i]; checkHolesInShell(p, &graph); if (validErr!=NULL) return; } for(unsigned int i=0; i<ngeoms; ++i) { const Polygon *p=polys[i]; checkHolesNotNested(p, &graph); if (validErr!=NULL) return; } checkShellsNotNested(g,&graph); if (validErr!=NULL) return; checkConnectedInteriors(graph);}voidIsValidOp::checkValid(const GeometryCollection *gc){ for(unsigned int i=0, ngeoms=gc->getNumGeometries(); i<ngeoms; ++i) { const Geometry *g=gc->getGeometryN(i); checkValid(g); if (validErr!=NULL) return; }}voidIsValidOp::checkTooFewPoints(GeometryGraph *graph){ if (graph->hasTooFewPoints()) { validErr=new TopologyValidationError( TopologyValidationError::eTooFewPoints, graph->getInvalidPoint()); return; }}/** * Checks that the arrangement of edges in a polygonal geometry graph * forms a consistent area. * * @param graph * * @see ConsistentAreaTester */voidIsValidOp::checkConsistentArea(GeometryGraph *graph){ ConsistentAreaTester cat(graph); bool isValidArea=cat.isNodeConsistentArea(); if (!isValidArea) { validErr=new TopologyValidationError( TopologyValidationError::eSelfIntersection, cat.getInvalidPoint()); return; } if (cat.hasDuplicateRings()) { validErr=new TopologyValidationError( TopologyValidationError::eDuplicatedRings, cat.getInvalidPoint()); }}/*private*/voidIsValidOp::checkNoSelfIntersectingRings(GeometryGraph *graph){ vector<Edge*> *edges=graph->getEdges(); for(unsigned int i=0; i<edges->size(); ++i) { Edge *e=(*edges)[i]; checkNoSelfIntersectingRing(e->getEdgeIntersectionList()); if(validErr!=NULL) return; }}/*private*/voidIsValidOp::checkNoSelfIntersectingRing(EdgeIntersectionList &eiList){ set<const Coordinate*,CoordinateLessThen>nodeSet; bool isFirst=true; EdgeIntersectionList::iterator it=eiList.begin(); EdgeIntersectionList::iterator end=eiList.end(); for(; it!=end; ++it) { EdgeIntersection *ei=*it; if (isFirst) { isFirst=false; continue; } if (nodeSet.find(&ei->coord)!=nodeSet.end()) { validErr=new TopologyValidationError( TopologyValidationError::eRingSelfIntersection, ei->coord); return; } else { nodeSet.insert(&ei->coord); } }}/*private*/voidIsValidOp::checkHolesInShell(const Polygon *p, GeometryGraph *graph){ assert(dynamic_cast<const LinearRing*>(p->getExteriorRing())); const LinearRing *shell=static_cast<const LinearRing*>( p->getExteriorRing()); //SimplePointInRing pir(shell); //SIRtreePointInRing pir(shell); MCPointInRing pir(shell); int nholes = p->getNumInteriorRing(); for(int i=0; i<nholes; ++i) { assert(dynamic_cast<const LinearRing*>( p->getInteriorRingN(i))); const LinearRing *hole=static_cast<const LinearRing*>( p->getInteriorRingN(i)); const Coordinate *holePt=findPtNotNode( hole->getCoordinatesRO(), shell, graph); /** * If no non-node hole vertex can be found, the hole must * split the polygon into disconnected interiors. * This will be caught by a subsequent check. */ if (holePt==NULL) return; bool outside = !pir.isInside(*holePt); if (outside) { validErr=new TopologyValidationError( TopologyValidationError::eHoleOutsideShell, *holePt); return; } }}/*private*/voidIsValidOp::checkHolesNotNested(const Polygon *p, GeometryGraph *graph){ //SimpleNestedRingTester nestedTester(graph); //SweeplineNestedRingTester nestedTester(graph); QuadtreeNestedRingTester nestedTester(graph); int nholes=p->getNumInteriorRing(); for(int i=0; i<nholes; ++i) { assert(dynamic_cast<const LinearRing*>( p->getInteriorRingN(i))); const LinearRing *innerHole=static_cast<const LinearRing*>( p->getInteriorRingN(i)); nestedTester.add(innerHole); } bool isNonNested=nestedTester.isNonNested(); if (!isNonNested)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -