/********************************************************************** * $Id: RobustLineIntersector.cpp,v 1.29.2.1 2005/05/23 16:39:37 strk Exp $ * * 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. * **********************************************************************/ #include #include #define DEBUG 0 #ifndef COMPUTE_Z #define COMPUTE_Z 1 #endif // COMPUTE_Z namespace { // module-statics using namespace geos; void normalizeToEnvCentre(Coordinate &n00, Coordinate &n01, Coordinate &n10, Coordinate &n11, Coordinate &normPt) { double minX0 = n00.x < n01.x ? n00.x : n01.x; double minY0 = n00.y < n01.y ? n00.y : n01.y; double maxX0 = n00.x > n01.x ? n00.x : n01.x; double maxY0 = n00.y > n01.y ? n00.y : n01.y; double minX1 = n10.x < n11.x ? n10.x : n11.x; double minY1 = n10.y < n11.y ? n10.y : n11.y; double maxX1 = n10.x > n11.x ? n10.x : n11.x; double maxY1 = n10.y > n11.y ? n10.y : n11.y; double intMinX = minX0 > minX1 ? minX0 : minX1; double intMaxX = maxX0 < maxX1 ? maxX0 : maxX1; double intMinY = minY0 > minY1 ? minY0 : minY1; double intMaxY = maxY0 < maxY1 ? maxY0 : maxY1; double intMidX = (intMinX + intMaxX) / 2.0; double intMidY = (intMinY + intMaxY) / 2.0; normPt.x = intMidX; normPt.y = intMidY; n00.x -= normPt.x; n00.y -= normPt.y; n01.x -= normPt.x; n01.y -= normPt.y; n10.x -= normPt.x; n10.y -= normPt.y; n11.x -= normPt.x; n11.y -= normPt.y; #if COMPUTE_Z double minZ0 = n00.z < n01.z ? n00.z : n01.z; double minZ1 = n10.z < n11.z ? n10.z : n11.z; double maxZ0 = n00.z > n01.z ? n00.z : n01.z; double maxZ1 = n10.z > n11.z ? n10.z : n11.z; double intMinZ = minZ0 > minZ1 ? minZ0 : minZ1; double intMaxZ = maxZ0 < maxZ1 ? maxZ0 : maxZ1; double intMidZ = (intMinZ + intMaxZ) / 2.0; normPt.z = intMidZ; n00.z -= normPt.z; n01.z -= normPt.z; n10.z -= normPt.z; n11.z -= normPt.z; #endif } } // module-statics namespace geos { RobustLineIntersector::RobustLineIntersector(){} RobustLineIntersector::~RobustLineIntersector(){} void RobustLineIntersector::computeIntersection(const Coordinate& p,const Coordinate& p1,const Coordinate& p2) { isProperVar=false; // do between check first, since it is faster than the orientation test if(Envelope::intersects(p1,p2,p)) { if ((CGAlgorithms::orientationIndex(p1,p2,p)==0)&& (CGAlgorithms::orientationIndex(p2,p1,p)==0)) { isProperVar=true; if ((p==p1)||(p==p2)) // 2d only test { isProperVar=false; } #if COMPUTE_Z intPt[0].setCoordinate(p); double z = interpolateZ(p, p1, p2); if ( !ISNAN(z) ) { if ( ISNAN(intPt[0].z) ) intPt[0].z = z; else intPt[0].z = (intPt[0].z+z)/2; } #endif // COMPUTE_Z result=DO_INTERSECT; return; } } result = DONT_INTERSECT; } int RobustLineIntersector::computeIntersect(const Coordinate& p1,const Coordinate& p2,const Coordinate& q1,const Coordinate& q2) { #if DEBUG cerr<<"RobustLineIntersector::computeIntersect called"<0 && Pq2>0) || (Pq1<0 && Pq2<0)) { #if DEBUG cerr<<" DONT_INTERSECT"<0 && Qp2>0)||(Qp1<0 && Qp2<0)) { #if DEBUG cerr<<" DONT_INTERSECT"<=min(p1.x,p2.x)) && (q.x<=max(p1.x,p2.x))) && // ((q.y>=min(p1.y,p2.y)) && (q.y<=max(p1.y,p2.y)))) { // return true; // } else { // return false; // } //} int RobustLineIntersector::computeCollinearIntersection(const Coordinate& p1,const Coordinate& p2,const Coordinate& q1,const Coordinate& q2) { #if COMPUTE_Z double ztot; int hits; double p2z; double p1z; double q1z; double q2z; #endif // COMPUTE_Z #if DEBUG cerr<<"RobustLineIntersector::computeCollinearIntersection called"<toString()); } intPt->x += normPt.x; intPt->y += normPt.y; /** * * MD - May 4 2005 - This is still a problem. Here is a failure case: * * LINESTRING (2089426.5233462777 1180182.3877339689, * 2085646.6891757075 1195618.7333999649) * LINESTRING (1889281.8148903656 1997547.0560044837, * 2259977.3672235999 483675.17050843034) * int point = (2097408.2633752143,1144595.8008114607) */ if (precisionModel!=NULL) precisionModel->makePrecise(intPt); #if COMPUTE_Z double ztot = 0; double zvals = 0; double zp = interpolateZ(*intPt, p1, p2); double zq = interpolateZ(*intPt, q1, q2); if ( !ISNAN(zp)) { ztot += zp; zvals++; } if ( !ISNAN(zq)) { ztot += zq; zvals++; } if ( zvals ) intPt->z = ztot/zvals; #endif // COMPUTE_Z return intPt; } void RobustLineIntersector::normalize(Coordinate *n1,Coordinate *n2,Coordinate *n3,Coordinate *n4,Coordinate *normPt) const { normPt->x=smallestInAbsValue(n1->x,n2->x,n3->x,n4->x); normPt->y=smallestInAbsValue(n1->y,n2->y,n3->y,n4->y); n1->x-=normPt->x; n1->y-=normPt->y; n2->x-=normPt->x; n2->y-=normPt->y; n3->x-=normPt->x; n3->y-=normPt->y; n4->x-=normPt->x; n4->y-=normPt->y; #if COMPUTE_Z normPt->z=smallestInAbsValue(n1->z,n2->z,n3->z,n4->z); n1->z-=normPt->z; n2->z-=normPt->z; n3->z-=normPt->z; n4->z-=normPt->z; #endif } double RobustLineIntersector::smallestInAbsValue(double x1,double x2,double x3,double x4) const { double x=x1; double xabs=fabs(x); if(fabs(x2)true * for this test. * Since this test is for debugging purposes only, no attempt is * made to optimize the envelope test. * * @return true if the input point lies within both input * segment envelopes */ bool RobustLineIntersector::isInSegmentEnvelopes(const Coordinate& intPt) { Envelope *env0=new Envelope(inputLines[0][0], inputLines[0][1]); Envelope *env1=new Envelope(inputLines[1][0], inputLines[1][1]); return env0->contains(intPt) && env1->contains(intPt); } } // namespace geos /********************************************************************** * $Log: RobustLineIntersector.cpp,v $ * Revision 1.29.2.1 2005/05/23 16:39:37 strk * Ported JTS robustness patch for RobustLineIntersector * * Revision 1.29 2004/12/08 13:54:43 strk * gcc warnings checked and fixed, general cleanups. * * Revision 1.28 2004/11/29 16:05:33 strk * Fixed a bug in LineIntersector::interpolateZ causing NaN values * to come out. * Handled dimensional collapses in ElevationMatrix. * Added ISNAN macro and changed ISNAN/FINITE macros to avoid * dispendious isnan() and finite() calls. * * Revision 1.27 2004/11/26 09:53:48 strk * Added more FINITE calls, and added inf and -inf to FINITE checks * * Revision 1.26 2004/11/23 19:53:06 strk * Had LineIntersector compute Z by interpolation. * * Revision 1.25 2004/11/22 13:02:40 strk * Fixed a bug in Collinear intersection Z computation * * Revision 1.24 2004/11/22 11:34:16 strk * Added Z computation for CollinearIntersections * * Revision 1.23 2004/11/20 15:40:49 strk * Added Z computation in point-segment intersection. * * Revision 1.22 2004/11/17 15:09:08 strk * Changed COMPUTE_Z defaults to be more conservative * * Revision 1.21 2004/11/17 08:41:42 strk * Fixed a bug in Z computation and removed debugging output by default. * * Revision 1.20 2004/11/17 08:13:16 strk * Indentation changes. * Some Z_COMPUTATION activated by default. * * Revision 1.19 2004/10/21 22:29:54 strk * Indentation changes and some more COMPUTE_Z rules * * Revision 1.18 2004/10/20 17:32:14 strk * Initial approach to 2.5d intersection() * * Revision 1.17 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.16 2004/03/25 02:23:55 ybychkov * All "index/" packages upgraded to JTS 1.4 * * Revision 1.15 2004/03/17 02:00:33 ybychkov * "Algorithm" upgraded to JTS 1.4 * * Revision 1.14 2003/11/07 01:23:42 pramsey * Add standard CVS headers licence notices and copyrights to all cpp and h * files. * * **********************************************************************/