/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 | | |