GDAL

polygonize_polygonizer.h
1 /******************************************************************************
2 * Project: GDAL
3 * Purpose: Implements The Two-Arm Chains EdgeTracing Algorithm
4 * Author: kikitte.lee
5 *
6 ******************************************************************************
7 * Copyright (c) 2023, kikitte.lee <kikitte.lee@gmail.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 ****************************************************************************/
27
28 #ifndef POLYGONIZE_POLYGONIZER_H_INCLUDED
29 #define POLYGONIZE_POLYGONIZER_H_INCLUDED
30
33 // Implements Junhua Teng, Fahui Wang, Yu Liu: An Efficient Algorithm for
34 // Raster-to-Vector Data Conversion: https://doi.org/10.1080/10824000809480639
35
36 #include <array>
37 #include <cstdint>
38 #include <vector>
39 #include <limits>
40 #include <map>
41
42 #include "cpl_error.h"
43 #include "ogr_api.h"
44
45 namespace gdal
46 {
47 namespace polygonizer
48 {
49
50 using IndexType = std::uint32_t;
51 using Point = std::array<IndexType, 2>;
52 using Arc = std::vector<Point>;
53 struct IndexedArc
54 {
55 Arc *poArc;
56 std::size_t iIndex;
57 };
58
65 struct RPolygon
66 {
67 IndexType iBottomRightRow{0};
68 IndexType iBottomRightCol{0};
69 // arc object list
70 std::vector<Arc *> oArcs{};
71 // does arc follows the right-hand rule with
72 std::vector<bool> oArcRighthandFollow{};
73 // each element is the next arc index of the current arc
74 std::vector<std::size_t> oArcConnections{};
75
76 RPolygon() = default;
77
78 RPolygon(const RPolygon &) = delete;
79
80 RPolygon &operator=(const RPolygon &) = delete;
81
82 ~RPolygon();
83
87 IndexedArc newArc(bool bFollowRighthand);
88
92 void setArcConnection(IndexedArc &oArc, IndexedArc &oNextArc);
93
97 void updateBottomRightPos(IndexType iRow, IndexType iCol);
98 };
99
103 struct TwoArm
104 {
105 IndexType iRow{0};
106 IndexType iCol{0};
107
108 RPolygon *poPolyInside{nullptr};
109 RPolygon *poPolyAbove{nullptr};
110 RPolygon *poPolyLeft{nullptr};
111
112 IndexedArc oArcHorOuter{};
113 IndexedArc oArcHorInner{};
114 IndexedArc oArcVerInner{};
115 IndexedArc oArcVerOuter{};
116
117 bool bSolidHorizontal{false};
118 bool bSolidVertical{false};
119 };
120
121 template <typename DataType> class PolygonReceiver
122 {
123 public:
124 PolygonReceiver() = default;
125
126 PolygonReceiver(const PolygonReceiver<DataType> &) = delete;
127
128 virtual ~PolygonReceiver() = default;
129
130 PolygonReceiver<DataType> &
131 operator=(const PolygonReceiver<DataType> &) = delete;
132
133 virtual void receive(RPolygon *poPolygon, DataType nPolygonCellValue) = 0;
134 };
135
139 template <typename PolyIdType, typename DataType> class Polygonizer
140 {
141 public:
142 static constexpr PolyIdType THE_OUTER_POLYGON_ID =
143 std::numeric_limits<PolyIdType>::max();
144
145 private:
146 using PolygonMap = std::map<PolyIdType, RPolygon *>;
147 using PolygonMapEntry = typename PolygonMap::value_type;
148
149 PolyIdType nInvalidPolyId_;
150 RPolygon *poTheOuterPolygon_{nullptr};
151 PolygonMap oPolygonMap_{};
152
153 PolygonReceiver<DataType> *poPolygonReceiver_;
154
155 RPolygon *getPolygon(PolyIdType nPolygonId);
156
157 RPolygon *createPolygon(PolyIdType nPolygonId);
158
159 void destroyPolygon(PolyIdType nPolygonId);
160
161 public:
162 explicit Polygonizer(PolyIdType nInvalidPolyId,
163 PolygonReceiver<DataType> *poPolygonReceiver);
164
165 Polygonizer(const Polygonizer<PolyIdType, DataType> &) = delete;
166
167 ~Polygonizer();
168
169 Polygonizer<PolyIdType, DataType> &
170 operator=(const Polygonizer<PolyIdType, DataType> &) = delete;
171
172 RPolygon *getTheOuterPolygon() const
173 {
174 return poTheOuterPolygon_;
175 }
176
177 void processLine(const PolyIdType *panThisLineId,
178 const DataType *panLastLineVal, TwoArm *poThisLineArm,
179 TwoArm *poLastLineArm, IndexType nCurrentRow,
180 IndexType nCols);
181 };
182
186 template <typename DataType>
187 class OGRPolygonWriter : public PolygonReceiver<DataType>
188 {
189 OGRLayerH hOutLayer_;
190 int iPixValField_;
191 double *padfGeoTransform_;
192
193 CPLErr eErr_{CE_None};
194
195 public:
196 OGRPolygonWriter(OGRLayerH hOutLayer, int iPixValField,
197 double *padfGeoTransform);
198
199 OGRPolygonWriter(const OGRPolygonWriter<DataType> &) = delete;
200
201 ~OGRPolygonWriter() = default;
202
203 OGRPolygonWriter<DataType> &
204 operator=(const OGRPolygonWriter<DataType> &) = delete;
205
206 void receive(RPolygon *poPolygon, DataType nPolygonCellValue) override;
207
208 inline CPLErr getErr()
209 {
210 return eErr_;
211 }
212 };
213
214 } // namespace polygonizer
215 } // namespace gdal
216
219 #endif /* POLYGONIZE_POLYGONIZER_H_INCLUDED */
cpl_error.h
ogr_api.h
CPLErr
CPLErr
Error category.
Definition: cpl_error.h:52
OGRLayerH
void * OGRLayerH
Opaque type for a layer (OGRLayer)
Definition: ogr_api.h:623