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