distanceop.cpp
来自「一个很好的vc底层代码」· C++ 代码 · 共 444 行
CPP
444 行
/********************************************************************** * $Id: DistanceOp.cpp,v 1.15 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: DistanceOp.cpp,v $ * Revision 1.15 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.14 2004/07/13 08:33:53 strk * Added missing virtual destructor to virtual classes. * Fixed implicit unsigned int -> int casts * * Revision 1.13 2004/07/08 19:34:50 strk * Mirrored JTS interface of CoordinateSequence, factory and * default implementations. * Added DefaultCoordinateSequenceFactory::instance() function. * * Revision 1.12 2004/07/02 13:28:28 strk * Fixed all #include lines to reflect headers layout change. * Added client application build tips in README. * * Revision 1.11 2004/05/14 13:42:46 strk * DistanceOp bug removed, cascading errors fixed. * * Revision 1.10 2004/04/14 10:56:38 strk * Uncommented initializzazion and destruction of DistanceOp::minDistanceLocation * * Revision 1.9 2004/04/13 10:05:51 strk * GeometryLocation constructor made const-correct. * Fixed erroneus down-casting in DistanceOp::computeMinDistancePoints. * * Revision 1.8 2004/04/05 06:35:14 ybychkov * "operation/distance" upgraded to JTS 1.4 * * Revision 1.7 2003/11/07 01:23:42 pramsey * Add standard CVS headers licence notices and copyrights to all cpp and h * files. * * Revision 1.6 2003/10/16 08:50:00 strk * Memory leak fixes. Improved performance by mean of more calls to * new getCoordinatesRO() when applicable. * **********************************************************************/#include <geos/opDistance.h>#include <geos/geomUtil.h>namespace geos {/*** Compute the distance between the closest points of two geometries.* @param g0 a {@link Geometry}* @param g1 another {@link Geometry}* @return the distance between the geometries*/double DistanceOp::distance(const Geometry *g0, const Geometry *g1) { DistanceOp distOp(g0,g1); return distOp.distance();}/*** Compute the the closest points of two geometries.* The points are presented in the same order as the input Geometries.** @param g0 a {@link Geometry}* @param g1 another {@link Geometry}* @return the closest points in the geometries*/CoordinateSequence* DistanceOp::closestPoints(Geometry *g0,Geometry *g1){ DistanceOp distOp(g0,g1); return distOp.closestPoints();}DistanceOp::DistanceOp(const Geometry *g0, const Geometry *g1): geom(2){ geom[0]=g0; geom[1]=g1; minDistance=DoubleInfinity; minDistanceLocation=NULL;}DistanceOp::~DistanceOp(){ unsigned int i; for (i=0; i<newCoords.size(); i++) delete newCoords[i]; if ( minDistanceLocation ) { for (i=0; i<minDistanceLocation->size(); i++) { delete (*minDistanceLocation)[i]; } delete minDistanceLocation; }}/*** Report the distance between the closest points on the input geometries.** @return the distance between the geometries*/double DistanceOp::distance() { computeMinDistance(); return minDistance;}/*** Report the coordinates of the closest points in the input geometries.* The points are presented in the same order as the input Geometries.** @return a pair of Coordinate s of the closest points*/CoordinateSequence* DistanceOp::closestPoints() { computeMinDistance(); CoordinateSequence* closestPts=new DefaultCoordinateSequence(); closestPts->add((*minDistanceLocation)[0]->getCoordinate()); closestPts->add((*minDistanceLocation)[1]->getCoordinate()); return closestPts;}/*** Report the locations of the closest points in the input geometries.* The locations are presented in the same order as the input Geometries.** @return a pair of {@link GeometryLocation}s for the closest points*/vector<GeometryLocation*>* DistanceOp::closestLocations(){ computeMinDistance(); return minDistanceLocation;}void DistanceOp::updateMinDistance(double dist) { if (dist<minDistance) minDistance=dist;}void DistanceOp::updateMinDistance(vector<GeometryLocation*> *locGeom, bool flip){ // if not set then don't update if ((*locGeom)[0]==NULL) return; delete (*minDistanceLocation)[0]; delete (*minDistanceLocation)[1]; if (flip) { (*minDistanceLocation)[0]=(*locGeom)[1]; (*minDistanceLocation)[1]=(*locGeom)[0]; } else { (*minDistanceLocation)[0]=(*locGeom)[0]; (*minDistanceLocation)[1]=(*locGeom)[1]; }}void DistanceOp::computeMinDistance() { if (minDistanceLocation!=NULL) return; minDistanceLocation = new vector<GeometryLocation*>(2); computeContainmentDistance(); if (minDistance<=0.0) return; computeLineDistance();}void DistanceOp::computeContainmentDistance() { vector<Geometry*> *polys0 = PolygonExtracter::getPolygons(geom[0]); vector<Geometry*> *polys1 = PolygonExtracter::getPolygons(geom[1]); vector<GeometryLocation*> *locPtPoly = new vector<GeometryLocation*>(2); // test if either geometry is wholely inside the other if (polys1->size()>0) { vector<GeometryLocation*> *insideLocs0 = ConnectedElementLocationFilter::getLocations(geom[0]); computeInside(insideLocs0, polys1, locPtPoly); if (minDistance <= 0.0) { (*minDistanceLocation)[0] = (*locPtPoly)[0]; (*minDistanceLocation)[1] = (*locPtPoly)[1]; delete polys0; delete polys1; delete locPtPoly; for (unsigned int i=0; i<insideLocs0->size(); i++) { GeometryLocation *l = (*insideLocs0)[i]; if ( l != (*minDistanceLocation)[0] && l != (*minDistanceLocation)[1] ) { delete l; } } delete insideLocs0; return; } for (unsigned int i=0; i<insideLocs0->size(); i++) delete (*insideLocs0)[i]; delete insideLocs0; } if (polys0->size()>0) { vector<GeometryLocation*> *insideLocs1 = ConnectedElementLocationFilter::getLocations(geom[1]); computeInside(insideLocs1, polys0, locPtPoly); if (minDistance <= 0.0) {// flip locations, since we are testing geom 1 VS geom 0 (*minDistanceLocation)[0] = (*locPtPoly)[1]; (*minDistanceLocation)[1] = (*locPtPoly)[0]; delete polys0; delete polys1; delete locPtPoly; for (unsigned int i=0; i<insideLocs1->size(); i++) { GeometryLocation *l = (*insideLocs1)[i]; if ( l != (*minDistanceLocation)[0] && l != (*minDistanceLocation)[1] ) { delete l; } } delete insideLocs1; return; } for (unsigned int i=0; i<insideLocs1->size(); i++) delete (*insideLocs1)[i]; delete insideLocs1; } delete polys0; delete polys1; delete locPtPoly;}void DistanceOp::computeInside(vector<GeometryLocation*> *locs,vector<Geometry*> *polys,vector<GeometryLocation*> *locPtPoly){ for (unsigned int i=0;i<locs->size();i++) { GeometryLocation *loc=(*locs)[i]; for (unsigned int j=0;j<polys->size();j++) { Polygon *poly=(Polygon*) (*polys)[j]; computeInside(loc, poly, locPtPoly); if (minDistance<=0.0) return; } }}void DistanceOp::computeInside(GeometryLocation *ptLoc,Polygon *poly,vector<GeometryLocation*> *locPtPoly){ Coordinate &pt=ptLoc->getCoordinate(); if (Location::EXTERIOR!=ptLocator.locate(pt, poly)) { minDistance = 0.0; (*locPtPoly)[0] = ptLoc; GeometryLocation *locPoly = new GeometryLocation(poly, pt); (*locPtPoly)[1] = locPoly; return; }}void DistanceOp::computeLineDistance() { vector<GeometryLocation*> locGeom(2); /** * Geometries are not wholely inside, so compute distance from lines and points * of one to lines and points of the other */ vector<Geometry*> *lines0=LinearComponentExtracter::getLines(geom[0]); vector<Geometry*> *lines1=LinearComponentExtracter::getLines(geom[1]); vector<Geometry*> *pts0=PointExtracter::getPoints(geom[0]); vector<Geometry*> *pts1=PointExtracter::getPoints(geom[1]); // bail whenever minDistance goes to zero, since it can't get any less computeMinDistanceLines(lines0, lines1, &locGeom); updateMinDistance(&locGeom, false); if (minDistance <= 0.0) { delete lines0; delete lines1; delete pts0; delete pts1; return; }; locGeom[0]=NULL; locGeom[1]=NULL; computeMinDistanceLinesPoints(lines0, pts1, &locGeom); updateMinDistance(&locGeom, false); if (minDistance <= 0.0) { delete lines0; delete lines1; delete pts0; delete pts1; return; }; locGeom[0]=NULL; locGeom[1]=NULL; computeMinDistanceLinesPoints(lines1, pts0, &locGeom); updateMinDistance(&locGeom, true); if (minDistance <= 0.0){ delete lines0; delete lines1; delete pts0; delete pts1; return; }; locGeom[0]=NULL; locGeom[1]=NULL; computeMinDistancePoints(pts0, pts1, &locGeom); updateMinDistance(&locGeom, false); delete lines0; delete lines1; delete pts0; delete pts1;}void DistanceOp::computeMinDistanceLines(vector<Geometry*> *lines0,vector<Geometry*> *lines1,vector<GeometryLocation*> *locGeom){ for (unsigned int i=0;i<lines0->size();i++) { LineString *line0=(LineString*) (*lines0)[i]; for (unsigned int j=0;j<lines1->size();j++) { LineString *line1=(LineString*) (*lines1)[j]; computeMinDistance(line0,line1,locGeom); if (minDistance<=0.0) return; } }}voidDistanceOp::computeMinDistancePoints(vector<Geometry*> *points0,vector<Geometry*> *points1,vector<GeometryLocation*> *locGeom){ for (unsigned int i=0;i<points0->size();i++) { //Point *pt0=(Point*) (*points0)[i]; Geometry *pt0=(*points0)[i]; for (unsigned int j=0;j<points1->size();j++) { //Point *pt1=(Point*) (*points1)[j]; Geometry *pt1=(*points1)[j]; double dist=pt0->getCoordinate()->distance(*(pt1->getCoordinate())); if (dist < minDistance) { minDistance = dist; // this is wrong - need to determine closest points on both segments!!! (*locGeom)[0] = new GeometryLocation(pt0, 0, *(pt0->getCoordinate())); (*locGeom)[1] = new GeometryLocation(pt1, 0, *(pt1->getCoordinate())); } if (minDistance<=0.0) return; if ( i<points0->size()-1 || j<points1->size()-1) { delete (*locGeom)[0]; (*locGeom)[0]=NULL; delete (*locGeom)[1]; (*locGeom)[1]=NULL; } } }}voidDistanceOp::computeMinDistanceLinesPoints(vector<Geometry*> *lines,vector<Geometry*> *points,vector<GeometryLocation*> *locGeom){ for (unsigned int i=0;i<lines->size();i++) { LineString *line=(LineString*) (*lines)[i]; for (unsigned int j=0;j<points->size();j++) { Point *pt=(Point*)(*points)[j]; computeMinDistance(line,pt,locGeom); if (minDistance<=0.0) return; if ( i<lines->size()-1 || j<points->size()-1) { delete (*locGeom)[0]; (*locGeom)[0]=NULL; delete (*locGeom)[1]; (*locGeom)[1]=NULL; } } }}void DistanceOp::computeMinDistance(const LineString *line0, const LineString *line1,vector<GeometryLocation*> *locGeom) { const Envelope *env0=line0->getEnvelopeInternal(); const Envelope *env1=line1->getEnvelopeInternal(); if (env0->distance(env1)>minDistance) { //delete env0; //delete env1; return; } //delete env0; //delete env1; const CoordinateSequence *coord0=line0->getCoordinatesRO(); const CoordinateSequence *coord1=line1->getCoordinatesRO(); // brute force approach! for(int i=0;i<coord0->getSize()-1;i++) { for(int j=0;j<coord1->getSize()-1;j++) { double dist=CGAlgorithms::distanceLineLine(coord0->getAt(i),coord0->getAt(i+1), coord1->getAt(j),coord1->getAt(j+1)); if (dist < minDistance) { minDistance = dist; LineSegment *seg0 = new LineSegment(coord0->getAt(i), coord0->getAt(i + 1)); LineSegment *seg1 = new LineSegment(coord1->getAt(j), coord1->getAt(j + 1)); CoordinateSequence* closestPt = seg0->closestPoints(seg1); delete seg0; delete seg1; Coordinate *c1 = new Coordinate(closestPt->getAt(0)); Coordinate *c2 = new Coordinate(closestPt->getAt(1)); newCoords.push_back(c1); newCoords.push_back(c2); delete closestPt; (*locGeom)[0] = new GeometryLocation(line0, i, *c1); (*locGeom)[1] = new GeometryLocation(line1, j, *c2); } if (minDistance<=0.0) return; if ( i<coord0->getSize()-1 || j<coord1->getSize()-1) { delete (*locGeom)[0]; (*locGeom)[0]=NULL; delete (*locGeom)[1]; (*locGeom)[1]=NULL; } } }}voidDistanceOp::computeMinDistance(const LineString *line, const Point *pt,vector<GeometryLocation*> *locGeom){ const Envelope *env0=line->getEnvelopeInternal(); const Envelope *env1=pt->getEnvelopeInternal(); if (env0->distance(env1)>minDistance) { //delete env0; //delete env1; return; } //delete env0; //delete env1; const CoordinateSequence *coord0=line->getCoordinatesRO(); Coordinate *coord=new Coordinate(*(pt->getCoordinate())); newCoords.push_back(coord); // brute force approach! for(int i=0;i<coord0->getSize()-1;i++) { double dist=CGAlgorithms::distancePointLine(*coord,coord0->getAt(i),coord0->getAt(i+1)); if (dist < minDistance) { minDistance = dist; LineSegment *seg = new LineSegment(coord0->getAt(i), coord0->getAt(i + 1)); Coordinate *segClosestPoint = seg->closestPoint(*coord); delete seg; newCoords.push_back(segClosestPoint); delete (*locGeom)[0]; (*locGeom)[0] = new GeometryLocation(line, i, *segClosestPoint); delete (*locGeom)[1]; (*locGeom)[1] = new GeometryLocation(pt, 0, *coord); } if (minDistance<=0.0) return; }}}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?