Coverage Report

Created: 2025-10-28 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/src/noding/snapround/SnapRoundingIntersectionAdder.cpp
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 2020 Paul Ramsey <pramsey@cleverelephant.ca>
7
 *
8
 * This is free software; you can redistribute and/or modify it under
9
 * the terms of the GNU Lesser General Licence as published
10
 * by the Free Software Foundation.
11
 * See the COPYING file for more information.
12
 *
13
 **********************************************************************/
14
15
#include <geos/noding/snapround/SnapRoundingIntersectionAdder.h>
16
#include <geos/noding/snapround/HotPixel.h>
17
#include <geos/noding/SegmentString.h>
18
#include <geos/noding/NodedSegmentString.h>
19
#include <geos/noding/NodingValidator.h>
20
#include <geos/noding/IntersectionFinderAdder.h>
21
#include <geos/geom/Coordinate.h>
22
#include <geos/geom/CoordinateSequence.h>
23
#include <geos/algorithm/LineIntersector.h>
24
#include <geos/algorithm/Distance.h>
25
#include <geos/util.h>
26
27
#include <vector>
28
#include <exception>
29
#include <iostream>
30
#include <cassert>
31
32
33
using namespace geos::algorithm;
34
using namespace geos::geom;
35
36
namespace geos {
37
namespace noding { // geos.noding
38
namespace snapround { // geos.noding.snapround
39
40
41
/*public*/
42
void
43
SnapRoundingIntersectionAdder::processIntersections(
44
    SegmentString* e0, std::size_t segIndex0,
45
    SegmentString* e1, std::size_t segIndex1)
46
23.2M
{
47
    // don't bother intersecting a segment with itself
48
23.2M
    if (e0 == e1 && segIndex0 == segIndex1) return;
49
50
23.2M
    const CoordinateSequence& seq0 = *e0->getCoordinates();
51
23.2M
    const CoordinateSequence& seq1 = *e1->getCoordinates();
52
53
23.2M
    li.computeIntersection(seq0, segIndex0, seq1, segIndex1);
54
55
23.2M
    if (li.hasIntersection()) {
56
6.67M
        if (li.isInteriorIntersection()) {
57
10.3M
            for (std::size_t intIndex = 0, intNum = li.getIntersectionNum(); intIndex < intNum; intIndex++) {
58
                // Take a copy of the intersection coordinate
59
5.54M
                intersections.add(li.getIntersection(intIndex));
60
5.54M
            }
61
4.80M
            static_cast<NodedSegmentString*>(e0)->addIntersections(&li, segIndex0, 0);
62
4.80M
            static_cast<NodedSegmentString*>(e1)->addIntersections(&li, segIndex1, 1);
63
4.80M
            return;
64
4.80M
        }
65
6.67M
    }
66
67
    /**
68
     * Segments did not actually intersect, within the limits of orientation index robustness.
69
     *
70
     * To avoid certain robustness issues in snap-rounding,
71
     * also treat very near vertex-segment situations as intersections.
72
     */
73
18.4M
    processNearVertex(seq0, segIndex0, seq1, segIndex1, e1);
74
18.4M
    processNearVertex(seq0, segIndex0 + 1, seq1, segIndex1, e1);
75
18.4M
    processNearVertex(seq1, segIndex1, seq0, segIndex0, e0);
76
18.4M
    processNearVertex(seq1, segIndex1 + 1, seq0, segIndex0, e0);
77
18.4M
}
78
79
bool
80
SnapRoundingIntersectionAdder::isNearSegmentInterior(
81
    const geom::CoordinateXY& p, const geom::CoordinateXY& p0, const geom::CoordinateXY& p1) const
82
73.7M
{
83
73.7M
    if (p.distance(p0) < nearnessTol) return false;
84
18.2M
    if (p.distance(p1) < nearnessTol) return false;
85
86
13.7M
    double distSeg = algorithm::Distance::pointToSegment(p, p0, p1);
87
13.7M
    return distSeg < nearnessTol;
88
18.2M
}
89
90
/*private*/
91
void
92
SnapRoundingIntersectionAdder::processNearVertex(
93
        const CoordinateSequence& ptSeq, std::size_t ptIndex,
94
        const CoordinateSequence& segSeq, std::size_t segIndex,
95
        SegmentString* edge)
96
73.7M
{
97
73.7M
    const CoordinateXY& pt = ptSeq.getAt<CoordinateXY>(ptIndex);
98
73.7M
    const CoordinateXY& seg0 = segSeq.getAt<CoordinateXY>(segIndex);
99
73.7M
    const CoordinateXY& seg1 = segSeq.getAt<CoordinateXY>(segIndex + 1);
100
73.7M
    if (isNearSegmentInterior(pt, seg0, seg1)) {
101
65.9k
        intersections.add(ptSeq, ptIndex, ptIndex);
102
65.9k
        static_cast<NodedSegmentString*>(edge)->addIntersection(intersections.back<CoordinateXYZM>(), segIndex);
103
65.9k
    }
104
73.7M
}
105
106
} // namespace geos.noding.snapround
107
} // namespace geos.noding
108
} // namespace geos