Coverage Report

Created: 2025-07-17 06:34

/src/geos/include/geos/noding/snapround/SnapRoundingIntersectionAdder.h
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 Public Licence as published
10
 * by the Free Software Foundation.
11
 * See the COPYING file for more information.
12
 *
13
 **********************************************************************/
14
15
#pragma once
16
17
#include <geos/export.h>
18
19
#include <vector>
20
#include <memory>
21
22
#include <geos/noding/Noder.h> // for inheritance
23
#include <geos/algorithm/LineIntersector.h> // for composition
24
#include <geos/geom/Coordinate.h> // for use in vector
25
#include <geos/geom/CoordinateSequence.h>
26
#include <geos/geom/PrecisionModel.h> // for inlines (should drop)
27
#include <geos/noding/SegmentIntersector.h>
28
29
30
// Forward declarations
31
namespace geos {
32
namespace geom {
33
class PrecisionModel;
34
}
35
namespace noding {
36
class SegmentString;
37
class NodedSegmentString;
38
namespace snapround {
39
class HotPixel;
40
}
41
}
42
}
43
44
namespace geos {
45
namespace noding { // geos::noding
46
namespace snapround { // geos::noding::snapround
47
48
/**
49
 * Finds intersections between line segments which will be snap-rounded,
50
 * and adds them as nodes to the segments.
51
 *
52
 * Intersections are detected and computed using full precision.
53
 * Snapping takes place in a subsequent phase.
54
 *
55
 * The intersection points are recorded, so that HotPixels can be created for them.
56
 *
57
 * To avoid robustness issues with vertices which lie very close to line segments
58
 * a heuristic is used:
59
 * nodes are created if a vertex lies within a tolerance distance
60
 * of the interior of a segment.
61
 * The tolerance distance is chosen to be significantly below the snap-rounding grid size.
62
 * This has empirically proven to eliminate noding failures.
63
 */
64
class GEOS_DLL SnapRoundingIntersectionAdder: public SegmentIntersector { // implements SegmentIntersector
65
66
private:
67
68
    algorithm::LineIntersector li;
69
    geom::CoordinateSequence intersections;
70
    // const geom::PrecisionModel* pm;
71
    double nearnessTol;
72
73
    /**
74
    * If an endpoint of one segment is near
75
    * the interior of the other segment, add it as an intersection.
76
    * EXCEPT if the endpoint is also close to a segment endpoint
77
    * (since this can introduce "zigs" in the linework).
78
    *
79
    * This resolves situations where
80
    * a segment A endpoint is extremely close to another segment B,
81
    * but is not quite crossing.  Due to robustness issues
82
    * in orientation detection, this can
83
    * result in the snapped segment A crossing segment B
84
    * without a node being introduced.
85
    */
86
    void processNearVertex(const geom::CoordinateSequence& seq0,
87
                           std::size_t ptIndex,
88
                           const geom::CoordinateSequence& seq1,
89
                           std::size_t segIndex,
90
                           SegmentString* edge);
91
92
    bool isNearSegmentInterior(const geom::CoordinateXY& p, const geom::CoordinateXY& p0, const geom::CoordinateXY& p1) const;
93
94
public:
95
96
    SnapRoundingIntersectionAdder(double p_nearnessTol)
97
7.12k
        : SegmentIntersector()
98
7.12k
        , intersections(geom::CoordinateSequence::XYZM(0))
99
7.12k
        , nearnessTol(p_nearnessTol)
100
7.12k
    {}
101
102
7.02k
    geom::CoordinateSequence getIntersections() { return std::move(intersections); };
103
104
    /**
105
    * This method is called by clients
106
    * of the {@link SegmentIntersector} class to process
107
    * intersections for two segments of the {@link SegmentString}s being intersected.
108
    * Note that some clients (such as MonotoneChains) may optimize away
109
    * this call for segment pairs which they have determined do not intersect
110
    * (e.g. by an disjoint envelope test).
111
    */
112
    void processIntersections(SegmentString* e0, std::size_t segIndex0, SegmentString* e1, std::size_t segIndex1) override;
113
114
    /**
115
    * Always process all intersections
116
    *
117
    */
118
18.8M
    bool isDone() const override { return false; }
119
120
121
};
122
123
} // namespace geos::noding::snapround
124
} // namespace geos::noding
125
} // namespace geos
126