74 static double computeEdgeDistance(
const geom::CoordinateXY& p,
const geom::CoordinateXY& p0,
const geom::CoordinateXY& p1);
81 precisionModel(initialPrecisionModel),
98 if(isInteriorIntersection(0)) {
101 if(isInteriorIntersection(1)) {
116 for(std::size_t i = 0; i < result; ++i) {
117 if(!(intPt[i].equals2D(*inputLines[inputLineIndex][0])
118 || intPt[i].equals2D(*inputLines[inputLineIndex][1]))) {
134 precisionModel = newPM;
142 POINT_INTERSECTION = 1,
145 COLLINEAR_INTERSECTION = 2
149 template<
typename C1,
typename C2>
151 const C2& p3,
const C2& p4)
153 inputLines[0][0] = &p1;
154 inputLines[0][1] = &p2;
155 inputLines[1][0] = &p3;
156 inputLines[1][1] = &p4;
157 result = computeIntersect(p1, p2, p3, p4);
168 std::string toString()
const;
178 return result != NO_INTERSECTION;
189 const geom::CoordinateXY*
192 return inputLines[segmentIndex][ptIndex];
212 const geom::CoordinateXYZM&
215 return intPt[intIndex];
236 for(std::size_t i = 0; i < result; ++i) {
237 if(intPt[i].equals2D(pt)) {
261 return hasIntersection() && isProperVar;
308 const geom::CoordinateXY* inputLines[2][2];
314 geom::CoordinateXYZM intPt[2];
320 std::size_t intLineIndex[2][2];
329 return result == COLLINEAR_INTERSECTION;
332 template<
typename C1,
typename C2>
333 uint8_t computeIntersect(
const C1& p1,
const C1& p2,
const C2& q1,
const C2& q2)
338 if(!geom::Envelope::intersects(p1, p2, q1, q2)) {
339 return NO_INTERSECTION;
345 int Pq1 = Orientation::index(p1, p2, q1);
346 int Pq2 = Orientation::index(p1, p2, q2);
348 if((Pq1 > 0 && Pq2 > 0) || (Pq1 < 0 && Pq2 < 0)) {
349 return NO_INTERSECTION;
352 int Qp1 = Orientation::index(q1, q2, p1);
353 int Qp2 = Orientation::index(q1, q2, p2);
355 if((Qp1 > 0 && Qp2 > 0) || (Qp1 < 0 && Qp2 < 0)) {
356 return NO_INTERSECTION;
362 bool collinear = Pq1 == 0 && Pq2 == 0 && Qp1 == 0 && Qp2 == 0;
364 return computeCollinearIntersection(p1, p2, q1, q2);
382 geom::CoordinateXYZM p;
383 double z = DoubleNotANumber;
384 double m = DoubleNotANumber;
386 if(Pq1 == 0 || Pq2 == 0 || Qp1 == 0 || Qp2 == 0) {
407 if (p1.equals2D(q1)) {
409 z = Interpolate::zGet(p1, q1);
410 m = Interpolate::mGet(p1, q1);
412 else if (p1.equals2D(q2)) {
414 z = Interpolate::zGet(p1, q2);
415 m = Interpolate::mGet(p1, q2);
417 else if (p2.equals2D(q1)) {
419 z = Interpolate::zGet(p2, q1);
420 m = Interpolate::mGet(p2, q1);
422 else if (p2.equals2D(q2)) {
424 z = Interpolate::zGet(p2, q2);
425 m = Interpolate::mGet(p2, q2);
432 z = Interpolate::zGetOrInterpolate(q1, p1, p2);
433 m = Interpolate::mGetOrInterpolate(q1, p1, p2);
437 z = Interpolate::zGetOrInterpolate(q2, p1, p2);
438 m = Interpolate::mGetOrInterpolate(q2, p1, p2);
442 z = Interpolate::zGetOrInterpolate(p1, q1, q2);
443 m = Interpolate::mGetOrInterpolate(p1, q1, q2);
447 z = Interpolate::zGetOrInterpolate(p2, q1, q2);
448 m = Interpolate::mGetOrInterpolate(p2, q1, q2);
452 p = intersection(p1, p2, q1, q2);
453 z = Interpolate::zInterpolate(p, p1, p2, q1, q2);
454 m = Interpolate::mInterpolate(p, p1, p2, q1, q2);
456 intPt[0] = geom::CoordinateXYZM(p.x, p.y, z, m);
458 std::cerr <<
" POINT_INTERSECTION; intPt[0]:" << intPt[0].toString() << std::endl;
460 return POINT_INTERSECTION;
466 return hasIntersection() && !isProperVar;
469 void computeIntLineIndex();
471 void computeIntLineIndex(std::size_t segmentIndex);
473 template<
typename C1,
typename C2>
474 uint8_t computeCollinearIntersection(
const C1& p1,
const C1& p2,
const C2& q1,
const C2& q2)
476 bool q1inP = geom::Envelope::intersects(p1, p2, q1);
477 bool q2inP = geom::Envelope::intersects(p1, p2, q2);
478 bool p1inQ = geom::Envelope::intersects(q1, q2, p1);
479 bool p2inQ = geom::Envelope::intersects(q1, q2, p2);
482 intPt[0] = zmGetOrInterpolateCopy(q1, p1, p2);
483 intPt[1] = zmGetOrInterpolateCopy(q2, p1, p2);
484 return COLLINEAR_INTERSECTION;
487 intPt[0] = zmGetOrInterpolateCopy(p1, q1, q2);
488 intPt[1] = zmGetOrInterpolateCopy(p2, q1, q2);
489 return COLLINEAR_INTERSECTION;
493 intPt[0] = zmGetOrInterpolateCopy(q1, p1, p2);
494 intPt[1] = zmGetOrInterpolateCopy(p1, q1, q2);
496 return (q1 == p1) && !q2inP && !p2inQ ? POINT_INTERSECTION : COLLINEAR_INTERSECTION;
500 intPt[0] = zmGetOrInterpolateCopy(q1, p1, p2);
501 intPt[1] = zmGetOrInterpolateCopy(p2, q1, q2);
503 return (q1 == p2) && !q2inP && !p1inQ ? POINT_INTERSECTION : COLLINEAR_INTERSECTION;
507 intPt[0] = zmGetOrInterpolateCopy(q2, p1, p2);
508 intPt[1] = zmGetOrInterpolateCopy(p1, q1, q2);
510 return (q2 == p1) && !q1inP && !p2inQ ? POINT_INTERSECTION : COLLINEAR_INTERSECTION;
514 intPt[0] = zmGetOrInterpolateCopy(q2, p1, p2);
515 intPt[1] = zmGetOrInterpolateCopy(p2, q1, q2);
516 return (q2 == p2) && !q1inP && !p1inQ ? POINT_INTERSECTION : COLLINEAR_INTERSECTION;
518 return NO_INTERSECTION;
530 template<
typename C1,
typename C2>
531 geom::CoordinateXYZM intersection (
const C1& p1,
const C1& p2,
const C2& q1,
const C2& q2)
const {
532 auto intPtOut = intersectionSafe(p1, p2, q1, q2);
549 if(! isInSegmentEnvelopes(intPtOut)) {
551 intPtOut = nearestEndpoint(p1, p2, q1, q2);
554 if(precisionModel !=
nullptr) {
571 bool isInSegmentEnvelopes(
const geom::CoordinateXY& pt)
const
573 geom::Envelope env0(*inputLines[0][0], *inputLines[0][1]);
574 geom::Envelope env1(*inputLines[1][0], *inputLines[1][1]);
575 return env0.contains(pt) && env1.contains(pt);
590 template<
typename C1,
typename C2>
591 geom::CoordinateXYZM intersectionSafe(
const C1& p1,
const C1& p2,
592 const C2& q1,
const C2& q2)
const
594 geom::CoordinateXYZM ptInt(Intersection::intersection(p1, p2, q1, q2));
595 if (ptInt.isNull()) {
596 const geom::CoordinateXY& nearest = nearestEndpoint(p1, p2, q1, q2);
597#if __cplusplus >= 201703L
598 if constexpr (std::is_same<C1, C2>::value) {
600 if (std::is_same<C1, C2>::value) {
602 ptInt =
static_cast<const C1&
>(nearest);
604 if (&nearest ==
static_cast<const geom::CoordinateXY*
>(&p1) || &nearest ==
static_cast<const geom::CoordinateXY*
>(&p2)) {
605 ptInt =
static_cast<const C1&
>(nearest);
607 ptInt =
static_cast<const C2&
>(nearest);
633 static const geom::CoordinateXY& nearestEndpoint(
const geom::CoordinateXY& p1,
634 const geom::CoordinateXY& p2,
635 const geom::CoordinateXY& q1,
636 const geom::CoordinateXY& q2);
639 template<
typename C1,
typename C2>
640 static geom::CoordinateXYZM zmGetOrInterpolateCopy(
645 geom::CoordinateXYZM pCopy(p);
646 pCopy.z = Interpolate::zGetOrInterpolate(p, p1, p2);
647 pCopy.m = Interpolate::mGetOrInterpolate(p, p1, p2);