/********************************************************************** * $Id: RobustLineIntersector.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. * * 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 1 #ifndef COMPUTE_Z #define COMPUTE_Z 1 #endif // COMPUTE_Z namespace geos { namespace algorithm { // geos.algorithm 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); #if DEBUG cerr<<"RobustIntersector::computeIntersection(Coordinate,Coordinate,Coordinate) calling interpolateZ"<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()<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 DEBUG if (! isInSegmentEnvelopes(intPt)) { cerr<<"Intersection outside segment envelopes: "<< intPt->toString(); } #endif 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); } void RobustLineIntersector::normalizeToEnvCentre(Coordinate &n00, Coordinate &n01, Coordinate &n10, Coordinate &n11, Coordinate &normPt) const { 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 } } // namespace geos.algorithm } // namespace geos /********************************************************************** * $Log$ * Revision 1.36 2006/03/21 11:12:23 strk * Cleanups: headers inclusion and Log section * * Revision 1.35 2006/02/19 19:46:49 strk * Packages <-> namespaces mapping for most GEOS internal code (uncomplete, but working). Dir-level libs for index/ subdirs. **********************************************************************/