/src/geos/src/coverage/CoverageSimplifier.cpp
Line | Count | Source |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (C) 2023 Paul Ramsey <pramsey@cleverelephant.ca> |
7 | | * Copyright (c) 2023 Martin Davis. |
8 | | * |
9 | | * This is free software; you can redistribute and/or modify it under |
10 | | * the terms of the GNU Lesser General Public Licence as published |
11 | | * by the Free Software Foundation. |
12 | | * See the COPYING file for more information. |
13 | | * |
14 | | **********************************************************************/ |
15 | | |
16 | | #include <geos/coverage/CoverageSimplifier.h> |
17 | | #include <geos/coverage/CoverageEdge.h> |
18 | | #include <geos/coverage/CoverageRingEdges.h> |
19 | | #include <geos/coverage/TPVWSimplifier.h> |
20 | | #include <geos/geom/Geometry.h> |
21 | | #include <geos/geom/GeometryFactory.h> |
22 | | #include <geos/geom/MultiLineString.h> |
23 | | #include <geos/util/IllegalArgumentException.h> |
24 | | |
25 | | |
26 | | using geos::geom::Geometry; |
27 | | using geos::geom::GeometryFactory; |
28 | | using geos::geom::MultiLineString; |
29 | | using geos::util::ProgressFunction; |
30 | | |
31 | | namespace geos { // geos |
32 | | namespace coverage { // geos.coverage |
33 | | |
34 | | /* public static */ |
35 | | std::vector<std::unique_ptr<Geometry>> |
36 | | CoverageSimplifier::simplify( |
37 | | std::vector<const Geometry*>& coverage, |
38 | | double tolerance, |
39 | | ProgressFunction* progressFunction) |
40 | 0 | { |
41 | 0 | CoverageSimplifier simplifier(coverage); |
42 | 0 | return simplifier.simplify(tolerance, progressFunction); |
43 | 0 | } |
44 | | |
45 | | /* public static */ |
46 | | std::vector<std::unique_ptr<Geometry>> |
47 | | CoverageSimplifier::simplify( |
48 | | const std::vector<std::unique_ptr<Geometry>>& coverage, |
49 | | double tolerance, |
50 | | ProgressFunction* progressFunction) |
51 | 0 | { |
52 | 0 | std::vector<const Geometry*> geoms; |
53 | 0 | for (auto& geom : coverage) { |
54 | 0 | geoms.push_back(geom.get()); |
55 | 0 | } |
56 | 0 | return simplify(geoms, tolerance, progressFunction); |
57 | 0 | } |
58 | | |
59 | | |
60 | | /* public static */ |
61 | | std::vector<std::unique_ptr<Geometry>> |
62 | | CoverageSimplifier::simplifyInner( |
63 | | std::vector<const Geometry*>& coverage, |
64 | | double tolerance, |
65 | | ProgressFunction* progressFunction) |
66 | 0 | { |
67 | 0 | CoverageSimplifier simplifier(coverage); |
68 | 0 | return simplifier.simplifyInner(tolerance, progressFunction); |
69 | 0 | } |
70 | | |
71 | | |
72 | | /* public static */ |
73 | | std::vector<std::unique_ptr<Geometry>> |
74 | | CoverageSimplifier::simplifyInner( |
75 | | const std::vector<std::unique_ptr<Geometry>>& coverage, |
76 | | double tolerance, |
77 | | ProgressFunction* progressFunction) |
78 | 0 | { |
79 | 0 | std::vector<const Geometry*> geoms; |
80 | 0 | for (auto& geom : coverage) { |
81 | 0 | geoms.push_back(geom.get()); |
82 | 0 | } |
83 | 0 | return simplifyInner(geoms, tolerance, progressFunction); |
84 | 0 | } |
85 | | |
86 | | |
87 | | /* public */ |
88 | | CoverageSimplifier::CoverageSimplifier(const std::vector<const Geometry*>& coverage) |
89 | 0 | : m_input(coverage) |
90 | 0 | , m_geomFactory(coverage.empty() ? nullptr : coverage[0]->getFactory()) |
91 | 0 | { |
92 | 0 | for (const Geometry* g: m_input) { |
93 | 0 | auto typeId = g->getGeometryTypeId(); |
94 | 0 | if (typeId != geom::GEOS_POLYGON && typeId != geom::GEOS_MULTIPOLYGON) |
95 | 0 | throw util::IllegalArgumentException("Argument is non-polygonal"); |
96 | 0 | } |
97 | 0 | } |
98 | | |
99 | | /* public */ |
100 | | std::vector<std::unique_ptr<Geometry>> |
101 | | CoverageSimplifier::simplify(double tolerance, |
102 | | ProgressFunction* progressFunction) |
103 | 0 | { |
104 | 0 | CoverageRingEdges cov(m_input); |
105 | 0 | simplifyEdges(cov.getEdges(), nullptr, tolerance, progressFunction); |
106 | 0 | return cov.buildCoverage(); |
107 | 0 | } |
108 | | |
109 | | /* public */ |
110 | | std::vector<std::unique_ptr<Geometry>> |
111 | | CoverageSimplifier::simplifyInner(double tolerance, |
112 | | ProgressFunction* progressFunction) |
113 | 0 | { |
114 | 0 | CoverageRingEdges cov(m_input); |
115 | 0 | std::vector<CoverageEdge*> innerEdges = cov.selectEdges(2); |
116 | 0 | std::vector<CoverageEdge*> outerEdges = cov.selectEdges(1); |
117 | 0 | std::unique_ptr<MultiLineString> constraintEdges = CoverageEdge::createLines(outerEdges, m_geomFactory); |
118 | |
|
119 | 0 | simplifyEdges(innerEdges, constraintEdges.get(), tolerance, progressFunction); |
120 | 0 | return cov.buildCoverage(); |
121 | 0 | } |
122 | | |
123 | | /* private */ |
124 | | void |
125 | | CoverageSimplifier::simplifyEdges( |
126 | | std::vector<CoverageEdge*> edges, |
127 | | const MultiLineString* constraints, |
128 | | double tolerance, |
129 | | ProgressFunction* progressFunction) |
130 | 0 | { |
131 | 0 | std::unique_ptr<MultiLineString> lines = CoverageEdge::createLines(edges, m_geomFactory); |
132 | 0 | std::vector<bool> freeRings = getFreeRings(edges); |
133 | 0 | std::unique_ptr<MultiLineString> linesSimp = TPVWSimplifier::simplify(lines.get(), freeRings, constraints, tolerance, progressFunction); |
134 | | //Assert: mlsSimp.getNumGeometries = edges.length |
135 | |
|
136 | 0 | setCoordinates(edges, linesSimp.get()); |
137 | 0 | } |
138 | | |
139 | | |
140 | | /* private */ |
141 | | void |
142 | | CoverageSimplifier::setCoordinates(std::vector<CoverageEdge*>& edges, const MultiLineString* lines) |
143 | 0 | { |
144 | 0 | for (std::size_t i = 0; i < edges.size(); i++) { |
145 | 0 | CoverageEdge* edge = edges[i]; |
146 | 0 | edge->setCoordinates(lines->getGeometryN(i)->getSharedCoordinates()); |
147 | 0 | } |
148 | 0 | } |
149 | | |
150 | | |
151 | | /* private */ |
152 | | std::vector<bool> |
153 | | CoverageSimplifier::getFreeRings(const std::vector<CoverageEdge*>& edges) const |
154 | 0 | { |
155 | 0 | std::vector<bool> freeRings; |
156 | 0 | for (auto edge: edges) { |
157 | 0 | freeRings.push_back(edge->isFreeRing()); |
158 | 0 | } |
159 | 0 | return freeRings; |
160 | 0 | } |
161 | | |
162 | | |
163 | | } // geos.coverage |
164 | | } // geos |