3
3
4
4
#include < sstream>
5
5
6
+ #include < s2/s2edge_tessellator.h>
7
+
6
8
#include " geoarrow-imports.h"
7
9
#include " geography.h"
8
10
@@ -14,28 +16,32 @@ class Constructor : public Handler {
14
16
public:
15
17
class Options {
16
18
public:
17
- Options () : oriented_(false ), check_(true ) {}
18
- bool oriented () { return oriented_; }
19
+ Options () : oriented_(false ), check_(true ), tessellate_tolerance_(S1Angle::Infinity()) {}
20
+ bool oriented () const { return oriented_; }
19
21
void set_oriented (bool oriented) { oriented_ = oriented; }
20
- bool check () { return check_; }
22
+ bool check () const { return check_; }
21
23
void set_check (bool check) { check_ = check; }
24
+ S1Angle tessellate_tolerance () const { return tessellate_tolerance_; }
25
+ void set_tessellate_tolerance (S1Angle tessellate_tolerance) {
26
+ tessellate_tolerance_ = tessellate_tolerance;
27
+ }
22
28
23
29
private:
24
30
bool oriented_;
25
31
bool check_;
32
+ S1Angle tessellate_tolerance_;
26
33
};
27
34
28
- Constructor (const Options& options) : options_(options) {}
35
+ Constructor (const Options& options) :
36
+ options_ (options),
37
+ projection_lnglat_ (180 ),
38
+ tessellator_ (new S2EdgeTessellator(&projection_lnglat_, options.tessellate_tolerance())) {}
29
39
30
40
virtual ~Constructor () {}
31
41
32
- Options* mutable_options () { return &options_; }
33
-
34
42
virtual Result coords (const double * coord, int64_t n, int32_t coord_size) {
35
43
for (int64_t i = 0 ; i < n; i++) {
36
- S2LatLng pt = S2LatLng::FromDegrees (coord[i * coord_size + 1 ],
37
- coord[i * coord_size]);
38
- points_.push_back (pt.Normalized ().ToPoint ());
44
+ input_points_.push_back (R2Point (coord[i * coord_size], coord[i * coord_size + 1 ]));
39
45
}
40
46
41
47
return Result::CONTINUE;
@@ -44,8 +50,28 @@ class Constructor : public Handler {
44
50
virtual std::unique_ptr<Geography> finish () = 0;
45
51
46
52
protected:
53
+ std::vector<R2Point> input_points_;
47
54
std::vector<S2Point> points_;
48
55
Options options_;
56
+ S2::PlateCarreeProjection projection_lnglat_;
57
+ std::unique_ptr<S2EdgeTessellator> tessellator_;
58
+
59
+ void finish_points () {
60
+ points_.clear ();
61
+ points_.reserve (input_points_.size ());
62
+
63
+ if (options_.tessellate_tolerance () != S1Angle::Infinity ()) {
64
+ for (size_t i = 1 ; i < input_points_.size (); i++) {
65
+ tessellator_->AppendUnprojected (input_points_[i - 1 ], input_points_[i], &points_);
66
+ }
67
+ } else {
68
+ for (const auto & input_point: input_points_) {
69
+ points_.push_back (projection_lnglat_.Unproject (input_point));
70
+ }
71
+ }
72
+
73
+ input_points_.clear ();
74
+ }
49
75
};
50
76
51
77
class PointConstructor : public Constructor {
@@ -74,9 +100,8 @@ class PointConstructor : public Constructor {
74
100
continue ;
75
101
}
76
102
77
- S2LatLng pt = S2LatLng::FromDegrees (coord[i * coord_size + 1 ],
78
- coord[i * coord_size]);
79
- points_.push_back (pt.ToPoint ());
103
+ R2Point pt = R2Point (coord[i * coord_size], coord[i * coord_size + 1 ]);
104
+ points_.push_back (projection_lnglat_.Unproject (pt));
80
105
}
81
106
82
107
return Result::CONTINUE;
@@ -114,13 +139,15 @@ class PolylineConstructor : public Constructor {
114
139
}
115
140
116
141
if (size > 0 && geometry_type == util::GeometryType::LINESTRING) {
117
- points_ .reserve (size);
142
+ input_points_ .reserve (size);
118
143
}
119
144
120
145
return Result::CONTINUE;
121
146
}
122
147
123
148
Result geom_end () {
149
+ finish_points ();
150
+
124
151
if (points_.size () > 0 ) {
125
152
auto polyline = absl::make_unique<S2Polyline>();
126
153
polyline->Init (std::move (points_));
@@ -131,7 +158,6 @@ class PolylineConstructor : public Constructor {
131
158
}
132
159
133
160
polylines_.push_back (std::move (polyline));
134
- points_.clear ();
135
161
}
136
162
137
163
return Result::CONTINUE;
@@ -160,20 +186,21 @@ class PolygonConstructor : public Constructor {
160
186
PolygonConstructor (const Options& options) : Constructor(options) {}
161
187
162
188
Result ring_start (int64_t size) {
163
- points_ .clear ();
189
+ input_points_ .clear ();
164
190
if (size > 0 ) {
165
- points_ .reserve (size);
191
+ input_points_ .reserve (size);
166
192
}
167
193
168
194
return Result::CONTINUE;
169
195
}
170
196
171
197
Result ring_end () {
198
+ finish_points ();
199
+
172
200
if (points_.size () == 0 ) {
173
201
return Result::CONTINUE;
174
202
}
175
203
176
- // S2Loop is open instead of closed
177
204
points_.pop_back ();
178
205
auto loop = absl::make_unique<S2Loop>();
179
206
loop->set_s2debug_override (S2Debug::DISABLE);
0 commit comments