Coverage Report

Created: 2025-11-15 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/s2geometry/src/s2/s2loop.cc
Line
Count
Source
1
// Copyright 2005 Google Inc. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
//
15
16
// Author: ericv@google.com (Eric Veach)
17
18
#include "s2/s2loop.h"
19
20
#include <algorithm>
21
#include <atomic>
22
#include <bitset>
23
#include <cmath>
24
#include <cstddef>
25
#include <cstdint>
26
#include <memory>
27
#include <utility>
28
#include <vector>
29
30
#include "absl/container/flat_hash_set.h"
31
#include "absl/flags/flag.h"
32
#include "absl/log/absl_check.h"
33
#include "absl/log/absl_log.h"
34
#include "absl/strings/str_format.h"
35
#include "absl/types/span.h"
36
#include "absl/utility/utility.h"
37
38
#include "s2/base/casts.h"
39
#include "s2/mutable_s2shape_index.h"
40
#include "s2/r1interval.h"
41
#include "s2/r2.h"
42
#include "s2/r2rect.h"
43
#include "s2/s1angle.h"
44
#include "s2/s1chord_angle.h"
45
#include "s2/s1interval.h"
46
#include "s2/s2cap.h"
47
#include "s2/s2cell.h"
48
#include "s2/s2cell_id.h"
49
#include "s2/s2cell_union.h"
50
#include "s2/s2closest_edge_query.h"
51
#include "s2/s2coords.h"
52
#include "s2/s2crossing_edge_query.h"
53
#include "s2/s2debug.h"
54
#include "s2/s2edge_clipping.h"
55
#include "s2/s2edge_crosser.h"
56
#include "s2/s2edge_crossings.h"
57
#include "s2/s2edge_distances.h"
58
#include "s2/s2error.h"
59
#include "s2/s2latlng_rect.h"
60
#include "s2/s2latlng_rect_bounder.h"
61
#include "s2/s2loop_measures.h"
62
#include "s2/s2padded_cell.h"
63
#include "s2/s2point.h"
64
#include "s2/s2point_compression.h"
65
#include "s2/s2pointutil.h"
66
#include "s2/s2predicates.h"
67
#include "s2/s2region.h"
68
#include "s2/s2shape.h"
69
#include "s2/s2shape_index.h"
70
#include "s2/s2shapeutil_visit_crossing_edge_pairs.h"
71
#include "s2/s2wedge_relations.h"
72
#include "s2/util/coding/coder.h"
73
#include "s2/util/math/matrix3x3.h"
74
75
using absl::flat_hash_set;
76
using absl::MakeSpan;
77
using absl::Span;
78
using std::make_unique;
79
using std::pair;
80
using std::unique_ptr;
81
using std::vector;
82
83
// The maximum number of vertices we'll allow when decoding a loop.
84
// The default value of 50 million is about 30x bigger than the number of
85
0
ABSL_FLAG(int32_t, s2polygon_decode_max_num_vertices, 50000000,
Unexecuted instantiation: AbslFlagDefaultGenFors2polygon_decode_max_num_vertices::Gen(void*)
Unexecuted instantiation: AbslFlagHelpGenFors2polygon_decode_max_num_vertices::Value(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: AbslFlagHelpGenFors2polygon_decode_max_num_vertices::NonConst()
86
0
          "The upper limit on the number of loops that are allowed by the "
87
0
          "S2Polygon::Decode method.");
88
0
89
0
static const unsigned char kCurrentLosslessEncodingVersionNumber = 1;
90
0
91
0
// Boolean properties for compressed loops.
92
0
// See GetCompressedEncodingProperties.
93
0
enum CompressedLoopProperty {
94
0
  kOriginInside,
95
0
  kBoundEncoded,
96
0
  kNumProperties
97
0
};
98
0
99
0
// These could be constexpr in s2loop.h, but gcc-13 gives an error.
100
0
const S2Point S2Loop::kEmptyVertex(0, 0, 1);
101
0
const S2Point S2Loop::kFullVertex(0, 0, -1);
102
0
103
0
S2Loop::S2Loop() {
104
  // The loop is not valid until Init() is called.
105
0
}
106
107
S2Loop::S2Loop(S2Loop&& b) noexcept
108
    // S2Region has no members, so does not need to be moved.
109
0
    : depth_(std::exchange(b.depth_, 0)),
110
0
      num_vertices_(std::exchange(b.num_vertices_, 0)),
111
0
      vertices_(std::move(b.vertices_)),
112
0
      s2debug_override_(std::move(b.s2debug_override_)),
113
0
      origin_inside_(std::move(b.origin_inside_)),
114
0
      unindexed_contains_calls_(
115
0
          b.unindexed_contains_calls_.exchange(0, std::memory_order_relaxed)),
116
0
      bound_(std::move(b.bound_)),
117
0
      subregion_bound_(std::move(b.subregion_bound_)),
118
0
      index_(std::move(b.index_)) {
119
  // Our index points to S2Loop::Shape instances which point back to S2Loop,
120
  // we need to update those S2Loop pointers now that we've moved.
121
0
  for (const S2Shape* shape : index_) {
122
0
    const_cast<Shape*>(down_cast<const Shape*>(shape))->loop_ = this;
123
0
  }
124
0
}
125
126
0
S2Loop& S2Loop::operator=(S2Loop&& b) noexcept {
127
  // S2Region has no members, so does not need to be assigned.
128
0
  depth_ = std::exchange(b.depth_, 0);
129
0
  num_vertices_ = std::exchange(b.num_vertices_, 0);
130
0
  vertices_ = std::move(b.vertices_);
131
0
  s2debug_override_ = std::move(b.s2debug_override_);
132
0
  origin_inside_ = std::move(b.origin_inside_);
133
0
  unindexed_contains_calls_.store(
134
0
      b.unindexed_contains_calls_.exchange(0, std::memory_order_relaxed),
135
0
      std::memory_order_relaxed);
136
0
  bound_ = std::move(b.bound_);
137
0
  subregion_bound_ = std::move(b.subregion_bound_);
138
0
  index_ = std::move(b.index_);
139
140
  // Our index points to S2Loop::Shape instances which point back to S2Loop,
141
  // we need to update those S2Loop pointers now that we've moved.
142
0
  for (const S2Shape* shape : index_) {
143
0
    const_cast<Shape*>(down_cast<const Shape*>(shape))->loop_ = this;
144
0
  }
145
146
0
  return *this;
147
0
}
148
149
S2Loop::S2Loop(Span<const S2Point> vertices)
150
0
  : S2Loop(vertices, S2Debug::ALLOW) {}
151
152
S2Loop::S2Loop(Span<const S2Point> vertices, S2Debug override)
153
0
  : s2debug_override_(override) {
154
0
  Init(vertices);
155
0
}
156
157
0
void S2Loop::set_s2debug_override(S2Debug override) {
158
0
  s2debug_override_ = override;
159
0
}
160
161
0
S2Debug S2Loop::s2debug_override() const {
162
0
  return s2debug_override_;
163
0
}
164
165
0
void S2Loop::ClearIndex() {
166
0
  unindexed_contains_calls_.store(0, std::memory_order_relaxed);
167
0
  index_.Clear();
168
0
}
169
170
0
void S2Loop::Init(Span<const S2Point> vertices) {
171
0
  ClearIndex();
172
0
  num_vertices_ = vertices.size();
173
0
  vertices_ = make_unique<S2Point[]>(num_vertices_);
174
0
  std::copy(vertices.begin(), vertices.end(), &vertices_[0]);
175
0
  InitOriginAndBound();
176
0
}
177
178
0
bool S2Loop::IsValid() const {
179
0
  S2Error error;
180
0
  if (FindValidationError(&error)) {
181
0
    ABSL_LOG_IF(ERROR, absl::GetFlag(FLAGS_s2debug)) << error;
182
0
    return false;
183
0
  }
184
0
  return true;
185
0
}
186
187
0
bool S2Loop::FindValidationError(S2Error* error) const {
188
0
  return (FindValidationErrorNoIndex(error) ||
189
0
          s2shapeutil::FindSelfIntersection(index_, error));
190
0
}
191
192
0
bool S2Loop::FindValidationErrorNoIndex(S2Error* error) const {
193
  // subregion_bound_ must be at least as large as bound_.  (This is an
194
  // internal consistency check rather than a test of client data.)
195
0
  ABSL_DCHECK(subregion_bound_.Contains(bound_));
196
197
  // All vertices must be unit length.  (Unfortunately this check happens too
198
  // late in debug mode, because S2Loop construction calls s2pred::Sign which
199
  // expects vertices to be unit length.  But it is still a useful check in
200
  // optimized builds.)
201
0
  for (int i = 0; i < num_vertices(); ++i) {
202
0
    if (!S2::IsUnitLength(vertex(i))) {
203
0
      *error = S2Error(S2Error::NOT_UNIT_LENGTH,
204
0
                       absl::StrFormat("Vertex %d is not unit length", i));
205
0
      return true;
206
0
    }
207
0
  }
208
  // Loops must have at least 3 vertices (except for the empty and full loops).
209
0
  if (num_vertices() < 3) {
210
0
    if (is_empty_or_full()) {
211
0
      return false;  // Skip remaining tests.
212
0
    }
213
0
    *error = S2Error(S2Error::LOOP_NOT_ENOUGH_VERTICES,
214
0
                     "Non-empty, non-full loops must have at least 3 vertices");
215
0
    return true;
216
0
  }
217
  // Loops are not allowed to have any duplicate vertices or edge crossings.
218
  // We split this check into two parts.  First we check that no edge is
219
  // degenerate (identical endpoints).  Then we check that there are no
220
  // intersections between non-adjacent edges (including at vertices).  The
221
  // second part needs the S2ShapeIndex, so it does not fall within the scope
222
  // of this method.
223
0
  for (int i = 0; i < num_vertices(); ++i) {
224
0
    if (vertex(i) == vertex(i+1)) {
225
0
      *error = S2Error(
226
0
          S2Error::DUPLICATE_VERTICES,
227
0
          absl::StrFormat("Edge %d is degenerate (duplicate vertex)", i));
228
0
      return true;
229
0
    }
230
0
    if (vertex(i) == -vertex(i + 1)) {
231
0
      *error = S2Error(S2Error::ANTIPODAL_VERTICES,
232
0
                       absl::StrFormat("Vertices %d and %d are antipodal", i,
233
0
                                       (i + 1) % num_vertices()));
234
0
      return true;
235
0
    }
236
0
  }
237
0
  return false;
238
0
}
239
240
0
void S2Loop::InitOriginAndBound() {
241
0
  if (num_vertices() < 3) {
242
    // Check for the special empty and full loops (which have one vertex).
243
0
    if (!is_empty_or_full()) {
244
0
      origin_inside_ = false;
245
0
      return;  // Bail out without trying to access non-existent vertices.
246
0
    }
247
    // If the vertex is in the southern hemisphere then the loop is full,
248
    // otherwise it is empty.
249
0
    origin_inside_ = (vertex(0).z() < 0);
250
0
  } else {
251
    // The brute force point containment algorithm works by counting edge
252
    // crossings starting at a fixed reference point (chosen as S2::Origin()
253
    // for historical reasons).  Loop initialization would be more efficient
254
    // if we used a loop vertex such as vertex(0) as the reference point
255
    // instead, however making this change would be a lot of work because
256
    // origin_inside_ is currently part of the Encode() format.
257
    //
258
    // In any case, we initialize origin_inside_ by first guessing that it is
259
    // outside, and then seeing whether we get the correct containment result
260
    // for vertex 1.  If the result is incorrect, the origin must be inside
261
    // the loop instead.  Note that the S2Loop is not necessarily valid and so
262
    // we need to check the requirements of S2::AngleContainsVertex() first.
263
0
    bool v1_inside = vertex(0) != vertex(1) && vertex(2) != vertex(1) &&
264
0
                     S2::AngleContainsVertex(vertex(0), vertex(1), vertex(2));
265
0
    origin_inside_ = false;  // Initialize before calling Contains().
266
267
    // Note that Contains(S2Point) only does a bounds check once InitIndex()
268
    // has been called, so it doesn't matter that bound_ is undefined here.
269
0
    if (v1_inside != Contains(vertex(1))) {
270
0
      origin_inside_ = true;
271
0
    }
272
0
  }
273
  // We *must* call InitBound() before InitIndex(), because InitBound() calls
274
  // Contains(S2Point), and Contains(S2Point) does a bounds check whenever the
275
  // index is not fresh (i.e., the loop has been added to the index but the
276
  // index has not been updated yet).
277
  //
278
  // TODO(ericv): When fewer S2Loop methods depend on internal bounds checks,
279
  // consider computing the bound on demand as well.
280
0
  InitBound();
281
0
  InitIndex();
282
0
}
283
284
0
void S2Loop::InitBound() {
285
  // Check for the special empty and full loops.
286
0
  if (is_empty_or_full()) {
287
0
    if (is_empty()) {
288
0
      subregion_bound_ = bound_ = S2LatLngRect::Empty();
289
0
    } else {
290
0
      subregion_bound_ = bound_ = S2LatLngRect::Full();
291
0
    }
292
0
    return;
293
0
  }
294
295
  // The bounding rectangle of a loop is not necessarily the same as the
296
  // bounding rectangle of its vertices.  First, the maximal latitude may be
297
  // attained along the interior of an edge.  Second, the loop may wrap
298
  // entirely around the sphere (e.g. a loop that defines two revolutions of a
299
  // candy-cane stripe).  Third, the loop may include one or both poles.
300
  // Note that a small clockwise loop near the equator contains both poles.
301
302
0
  S2LatLngRectBounder bounder;
303
0
  for (int i = 0; i <= num_vertices(); ++i) {
304
0
    bounder.AddPoint(vertex(i));
305
0
  }
306
0
  S2LatLngRect b = bounder.GetBound();
307
0
  if (Contains(S2Point(0, 0, 1))) {
308
0
    b = S2LatLngRect(R1Interval(b.lat().lo(), M_PI_2), S1Interval::Full());
309
0
  }
310
  // If a loop contains the south pole, then either it wraps entirely
311
  // around the sphere (full longitude range), or it also contains the
312
  // north pole in which case b.lng().is_full() due to the test above.
313
  // Either way, we only need to do the south pole containment test if
314
  // b.lng().is_full().
315
0
  if (b.lng().is_full() && Contains(S2Point(0, 0, -1))) {
316
0
    b.mutable_lat()->set_lo(-M_PI_2);
317
0
  }
318
0
  bound_ = b;
319
0
  subregion_bound_ = S2LatLngRectBounder::ExpandForSubregions(bound_);
320
0
}
321
322
0
void S2Loop::InitIndex() {
323
0
  index_.Add(make_unique<Shape>(this));
324
0
  if (absl::GetFlag(FLAGS_s2debug) && s2debug_override_ == S2Debug::ALLOW) {
325
    // Note that FLAGS_s2debug is false in optimized builds (by default).
326
0
    ABSL_CHECK(IsValid());
327
0
  }
328
0
}
329
330
S2Loop::S2Loop(const S2Cell& cell)
331
0
    : num_vertices_(4), vertices_(new S2Point[num_vertices_]) {
332
0
  for (int i = 0; i < 4; ++i) {
333
0
    vertices_[i] = cell.GetVertex(i);
334
0
  }
335
  // We recompute the bounding rectangle ourselves, since S2Cell uses a
336
  // different method and we need all the bounds to be consistent.
337
0
  InitOriginAndBound();
338
0
}
339
340
0
S2Loop::~S2Loop() = default;
341
342
S2Loop::S2Loop(const S2Loop& src)
343
0
    : depth_(src.depth_),
344
0
      num_vertices_(src.num_vertices_),
345
0
      vertices_(make_unique<S2Point[]>(num_vertices_)),
346
0
      s2debug_override_(src.s2debug_override_),
347
0
      origin_inside_(src.origin_inside_),
348
0
      bound_(src.bound_),
349
0
      subregion_bound_(src.subregion_bound_) {
350
0
  std::copy(&src.vertices_[0], &src.vertices_[num_vertices_], &vertices_[0]);
351
0
  InitIndex();
352
0
}
353
354
0
S2Loop* S2Loop::Clone() const {
355
0
  return new S2Loop(*this);
356
0
}
357
358
0
int S2Loop::FindVertex(const S2Point& p) const {
359
0
  if (num_vertices() < 10) {
360
    // Exhaustive search.  Return value must be in the range [1..N].
361
0
    for (int i = 1; i <= num_vertices(); ++i) {
362
0
      if (vertex(i) == p) return i;
363
0
    }
364
0
    return -1;
365
0
  }
366
0
  MutableS2ShapeIndex::Iterator it(&index_);
367
0
  if (!it.Locate(p)) return -1;
368
369
0
  const S2ClippedShape& a_clipped = it.cell().clipped(0);
370
0
  for (int i = a_clipped.num_edges() - 1; i >= 0; --i) {
371
0
    int ai = a_clipped.edge(i);
372
    // Return value must be in the range [1..N].
373
0
    if (vertex(ai) == p) return (ai == 0) ? num_vertices() : ai;
374
0
    if (vertex(ai+1) == p) return ai+1;
375
0
  }
376
0
  return -1;
377
0
}
378
379
0
bool S2Loop::IsNormalized() const {
380
  // Optimization: if the longitude span is less than 180 degrees, then the
381
  // loop covers less than half the sphere and is therefore normalized.
382
0
  if (bound_.lng().GetLength() < M_PI) return true;
383
384
0
  return S2::IsNormalized(vertices_span());
385
0
}
386
387
0
void S2Loop::Normalize() {
388
0
  if (!IsNormalized()) Invert();
389
0
  ABSL_DCHECK(IsNormalized());
390
0
}
391
392
0
void S2Loop::Invert() {
393
0
  ClearIndex();
394
0
  if (is_empty_or_full()) {
395
0
    vertices_[0] = is_full() ? kEmptyVertex : kFullVertex;
396
0
  } else {
397
0
    std::reverse(&vertices_[0], &vertices_[num_vertices()]);
398
0
  }
399
  // origin_inside_ must be set correctly before building the S2ShapeIndex.
400
0
  origin_inside_ ^= true;
401
0
  if (bound_.lat().lo() > -M_PI_2 && bound_.lat().hi() < M_PI_2) {
402
    // The complement of this loop contains both poles.
403
0
    subregion_bound_ = bound_ = S2LatLngRect::Full();
404
0
  } else {
405
0
    InitBound();
406
0
  }
407
0
  InitIndex();
408
0
}
409
410
0
double S2Loop::GetArea() const {
411
  // S2Loop has its own convention for empty and full loops.
412
0
  if (is_empty_or_full()) {
413
0
    return contains_origin() ? (4 * M_PI) : 0;
414
0
  }
415
0
  return S2::GetArea(vertices_span());
416
0
}
417
418
0
S2Point S2Loop::GetCentroid() const {
419
  // Empty and full loops are handled correctly.
420
0
  return S2::GetCentroid(vertices_span());
421
0
}
422
423
0
S2::LoopOrder S2Loop::GetCanonicalLoopOrder() const {
424
0
  return S2::GetCanonicalLoopOrder(vertices_span());
425
0
}
426
427
0
S1Angle S2Loop::GetDistance(const S2Point& x) const {
428
  // Note that S2Loop::Contains(S2Point) is slightly more efficient than the
429
  // generic version used by S2ClosestEdgeQuery.
430
0
  if (Contains(x)) return S1Angle::Zero();
431
0
  return GetDistanceToBoundary(x);
432
0
}
433
434
0
S1Angle S2Loop::GetDistanceToBoundary(const S2Point& x) const {
435
0
  S2ClosestEdgeQuery::Options options;
436
0
  options.set_include_interiors(false);
437
0
  S2ClosestEdgeQuery::PointTarget t(x);
438
0
  return S2ClosestEdgeQuery(&index_, options).GetDistance(&t).ToAngle();
439
0
}
440
441
0
S2Point S2Loop::Project(const S2Point& x) const {
442
0
  if (Contains(x)) return x;
443
0
  return ProjectToBoundary(x);
444
0
}
445
446
0
S2Point S2Loop::ProjectToBoundary(const S2Point& x) const {
447
0
  S2ClosestEdgeQuery::Options options;
448
0
  options.set_include_interiors(false);
449
0
  S2ClosestEdgeQuery q(&index_, options);
450
0
  S2ClosestEdgeQuery::PointTarget target(x);
451
0
  S2ClosestEdgeQuery::Result edge = q.FindClosestEdge(&target);
452
0
  return q.Project(x, edge);
453
0
}
454
455
0
double S2Loop::GetCurvature() const {
456
  // S2Loop has its own convention for empty and full loops.  For such loops,
457
  // we return the limit value as the area approaches 0 or 4*Pi respectively.
458
0
  if (is_empty_or_full()) {
459
0
    return contains_origin() ? (-2 * M_PI) : (2 * M_PI);
460
0
  }
461
0
  return S2::GetCurvature(vertices_span());
462
0
}
463
464
0
double S2Loop::GetCurvatureMaxError() const {
465
0
  return S2::GetCurvatureMaxError(vertices_span());
466
0
}
467
468
0
S2Cap S2Loop::GetCapBound() const {
469
0
  return bound_.GetCapBound();
470
0
}
471
472
0
void S2Loop::GetCellUnionBound(vector<S2CellId>* cell_ids) const {
473
0
  GetCapBound().GetCellUnionBound(cell_ids);
474
0
}
475
476
0
bool S2Loop::Contains(const S2Cell& target) const {
477
0
  MutableS2ShapeIndex::Iterator it(&index_);
478
0
  S2CellRelation relation = it.Locate(target.id());
479
480
  // If "target" is disjoint from all index cells, it is not contained.
481
  // Similarly, if "target" is subdivided into one or more index cells then it
482
  // is not contained, since index cells are subdivided only if they (nearly)
483
  // intersect a sufficient number of edges.  (But note that if "target" itself
484
  // is an index cell then it may be contained, since it could be a cell with
485
  // no edges in the loop interior.)
486
0
  if (relation != S2CellRelation::INDEXED) return false;
487
488
  // Otherwise check if any edges intersect "target".
489
0
  if (BoundaryApproxIntersects(it, target)) return false;
490
491
  // Otherwise check if the loop contains the center of "target".
492
0
  return Contains(it, target.GetCenter());
493
0
}
494
495
0
bool S2Loop::MayIntersect(const S2Cell& target) const {
496
0
  MutableS2ShapeIndex::Iterator it(&index_);
497
0
  S2CellRelation relation = it.Locate(target.id());
498
499
  // If "target" does not overlap any index cell, there is no intersection.
500
0
  if (relation == S2CellRelation::DISJOINT) return false;
501
502
  // If "target" is subdivided into one or more index cells, there is an
503
  // intersection to within the S2ShapeIndex error bound (see Contains).
504
0
  if (relation == S2CellRelation::SUBDIVIDED) return true;
505
506
  // If "target" is an index cell, there is an intersection because index cells
507
  // are created only if they have at least one edge or they are entirely
508
  // contained by the loop.
509
0
  if (it.id() == target.id()) return true;
510
511
  // Otherwise check if any edges intersect "target".
512
0
  if (BoundaryApproxIntersects(it, target)) return true;
513
514
  // Otherwise check if the loop contains the center of "target".
515
0
  return Contains(it, target.GetCenter());
516
0
}
517
518
bool S2Loop::BoundaryApproxIntersects(const MutableS2ShapeIndex::Iterator& it,
519
0
                                      const S2Cell& target) const {
520
0
  ABSL_DCHECK(it.id().contains(target.id()));
521
0
  const S2ClippedShape& a_clipped = it.cell().clipped(0);
522
0
  int a_num_edges = a_clipped.num_edges();
523
524
  // If there are no edges, there is no intersection.
525
0
  if (a_num_edges == 0) return false;
526
527
  // We can save some work if "target" is the index cell itself.
528
0
  if (it.id() == target.id()) return true;
529
530
  // Otherwise check whether any of the edges intersect "target".
531
0
  static const double kMaxError = (S2::kFaceClipErrorUVCoord +
532
0
                                   S2::kIntersectsRectErrorUVDist);
533
0
  R2Rect bound = target.GetBoundUV().Expanded(kMaxError);
534
0
  for (int i = 0; i < a_num_edges; ++i) {
535
0
    int ai = a_clipped.edge(i);
536
0
    R2Point v0, v1;
537
0
    if (S2::ClipToPaddedFace(vertex(ai), vertex(ai+1), target.face(),
538
0
                             kMaxError, &v0, &v1) &&
539
0
        S2::IntersectsRect(v0, v1, bound)) {
540
0
      return true;
541
0
    }
542
0
  }
543
0
  return false;
544
0
}
545
546
0
bool S2Loop::Contains(const S2Point& p) const {
547
  // NOTE(ericv): A bounds check slows down this function by about 50%.  It is
548
  // worthwhile only when it might allow us to delay building the index.
549
0
  if (!index_.is_fresh() && !bound_.Contains(p)) return false;
550
551
  // For small loops it is faster to just check all the crossings.  We also
552
  // use this method during loop initialization because InitOriginAndBound()
553
  // calls Contains() before InitIndex().  Otherwise, we keep track of the
554
  // number of calls to Contains() and only build the index when enough calls
555
  // have been made so that we think it is worth the effort.  Note that the
556
  // code below is structured so that if many calls are made in parallel only
557
  // one thread builds the index, while the rest continue using brute force
558
  // until the index is actually available.
559
  //
560
  // The constants below were tuned using the benchmarks.  It turns out that
561
  // building the index costs roughly 50x as much as Contains().  (The ratio
562
  // increases slowly from 46x with 64 points to 61x with 256k points.)  The
563
  // textbook approach to this problem would be to wait until the cumulative
564
  // time we would have saved with an index approximately equals the cost of
565
  // building the index, and then build it.  (This gives the optimal
566
  // competitive ratio of 2; look up "competitive algorithms" for details.)
567
  // We set the limit somewhat lower than this (20 rather than 50) because
568
  // building the index may be forced anyway by other API calls, and so we
569
  // want to err on the side of building it too early.
570
571
0
  static const int kMaxBruteForceVertices = 32;
572
0
  static const int kMaxUnindexedContainsCalls = 20;  // See notes above.
573
0
  if (index_.num_shape_ids() == 0 ||  // InitIndex() not called yet
574
0
      num_vertices() <= kMaxBruteForceVertices ||
575
0
      (!index_.is_fresh() &&
576
0
       ++unindexed_contains_calls_ != kMaxUnindexedContainsCalls)) {
577
0
    return BruteForceContains(p);
578
0
  }
579
  // Otherwise we look up the S2ShapeIndex cell containing this point.  Note
580
  // the index is built automatically the first time an iterator is created.
581
0
  MutableS2ShapeIndex::Iterator it(&index_);
582
0
  if (!it.Locate(p)) return false;
583
0
  return Contains(it, p);
584
0
}
585
586
0
bool S2Loop::BruteForceContains(const S2Point& p) const {
587
  // Empty and full loops don't need a special case, but invalid loops with
588
  // zero vertices do, so we might as well handle them all at once.
589
0
  if (num_vertices() < 3) return origin_inside_;
590
591
0
  S2Point origin = S2::Origin();
592
0
  S2EdgeCrosser crosser(&origin, &p, &vertex(0));
593
0
  bool inside = origin_inside_;
594
0
  for (int i = 1; i <= num_vertices(); ++i) {
595
0
    inside ^= crosser.EdgeOrVertexCrossing(&vertex(i));
596
0
  }
597
0
  return inside;
598
0
}
599
600
bool S2Loop::Contains(const MutableS2ShapeIndex::Iterator& it,
601
0
                      const S2Point& p) const {
602
  // Test containment by drawing a line segment from the cell center to the
603
  // given point and counting edge crossings.
604
0
  const S2ClippedShape& a_clipped = it.cell().clipped(0);
605
0
  bool inside = a_clipped.contains_center();
606
0
  int a_num_edges = a_clipped.num_edges();
607
0
  if (a_num_edges > 0) {
608
0
    S2Point center = it.id().ToPoint();
609
0
    S2EdgeCrosser crosser(&center, &p);
610
0
    int ai_prev = -2;
611
0
    for (int i = 0; i < a_num_edges; ++i) {
612
0
      int ai = a_clipped.edge(i);
613
0
      if (ai != ai_prev + 1) crosser.RestartAt(&vertex(ai));
614
0
      ai_prev = ai;
615
0
      inside ^= crosser.EdgeOrVertexCrossing(&vertex(ai+1));
616
0
    }
617
0
  }
618
0
  return inside;
619
0
}
620
621
0
void S2Loop::Encode(Encoder* const encoder) const {
622
0
  encoder->Ensure(num_vertices_ * sizeof(vertices_[0]) + 20);  // sufficient
623
624
0
  encoder->put8(kCurrentLosslessEncodingVersionNumber);
625
0
  encoder->put32(num_vertices_);
626
0
  encoder->putn(vertices_.get(), sizeof(vertices_[0]) * num_vertices_);
627
0
  encoder->put8(origin_inside_);
628
0
  encoder->put32(depth_);
629
0
  ABSL_DCHECK_GE(encoder->avail(), 0);
630
631
0
  bound_.Encode(encoder);
632
0
}
633
634
0
bool S2Loop::Decode(Decoder* const decoder) {
635
0
  if (decoder->avail() < sizeof(unsigned char)) return false;
636
0
  unsigned char version = decoder->get8();
637
0
  switch (version) {
638
0
    case kCurrentLosslessEncodingVersionNumber:
639
0
      return DecodeInternal(decoder);
640
0
  }
641
0
  return false;
642
0
}
643
644
0
bool S2Loop::DecodeInternal(Decoder* const decoder) {
645
  // Perform all checks before modifying vertex state. Empty loops are
646
  // explicitly allowed here: a newly created loop has zero vertices
647
  // and such loops encode and decode properly.
648
0
  if (decoder->avail() < sizeof(uint32_t)) return false;
649
0
  const uint32_t num_vertices = decoder->get32();
650
0
  if (num_vertices > static_cast<uint32_t>(absl::GetFlag(
651
0
                         FLAGS_s2polygon_decode_max_num_vertices))) {
652
0
    return false;
653
0
  }
654
0
  if (decoder->avail() < (num_vertices * sizeof(vertices_[0]) +
655
0
                          sizeof(uint8_t) + sizeof(uint32_t))) {
656
0
    return false;
657
0
  }
658
0
  ClearIndex();
659
0
  num_vertices_ = num_vertices;
660
661
0
  vertices_ = make_unique<S2Point[]>(num_vertices_);
662
0
  decoder->getn(vertices_.get(), num_vertices_ * sizeof(vertices_[0]));
663
0
  origin_inside_ = decoder->get8();
664
0
  depth_ = decoder->get32();
665
0
  if (!bound_.Decode(decoder)) return false;
666
0
  subregion_bound_ = S2LatLngRectBounder::ExpandForSubregions(bound_);
667
668
  // An initialized loop will have some non-zero count of vertices. A default
669
  // (uninitialized) has zero vertices. This code supports encoding and
670
  // decoding of uninitialized loops, but we only want to call InitIndex for
671
  // initialized loops. Otherwise we defer InitIndex until the call to Init().
672
0
  if (num_vertices > 0) {
673
0
    InitIndex();
674
0
  }
675
676
0
  return true;
677
0
}
678
679
// LoopRelation is an abstract class that defines a relationship between two
680
// loops (Contains, Intersects, or CompareBoundary).
681
class LoopRelation {
682
 public:
683
0
  LoopRelation() = default;
684
0
  virtual ~LoopRelation() = default;
685
686
  // Optionally, a_target() and b_target() can specify an early-exit condition
687
  // for the loop relation.  If any point P is found such that
688
  //
689
  //   A.Contains(P) == a_crossing_target() &&
690
  //   B.Contains(P) == b_crossing_target()
691
  //
692
  // then the loop relation is assumed to be the same as if a pair of crossing
693
  // edges were found.  For example, the Contains() relation has
694
  //
695
  //   a_crossing_target() == 0
696
  //   b_crossing_target() == 1
697
  //
698
  // because if A.Contains(P) == 0 (false) and B.Contains(P) == 1 (true) for
699
  // any point P, then it is equivalent to finding an edge crossing (i.e.,
700
  // since Contains() returns false in both cases).
701
  //
702
  // Loop relations that do not have an early-exit condition of this form
703
  // should return -1 for both crossing targets.
704
  virtual int a_crossing_target() const = 0;
705
  virtual int b_crossing_target() const = 0;
706
707
  // Given a vertex "ab1" that is shared between the two loops, return true if
708
  // the two associated wedges (a0, ab1, a2) and (b0, ab1, b2) are equivalent
709
  // to an edge crossing.  The loop relation is also allowed to maintain its
710
  // own internal state, and can return true if it observes any sequence of
711
  // wedges that are equivalent to an edge crossing.
712
  virtual bool WedgesCross(const S2Point& a0, const S2Point& ab1,
713
                           const S2Point& a2, const S2Point& b0,
714
                           const S2Point& b2) = 0;
715
};
716
717
// RangeIterator is a wrapper over MutableS2ShapeIndex::Iterator with extra
718
// methods that are useful for merging the contents of two or more
719
// S2ShapeIndexes.
720
class RangeIterator {
721
 public:
722
  // Construct a new RangeIterator positioned at the first cell of the index.
723
  explicit RangeIterator(const MutableS2ShapeIndex* index)
724
0
      : it_(index, S2ShapeIndex::BEGIN) {
725
0
    Refresh();
726
0
  }
727
728
  // The current S2CellId and cell contents.
729
0
  S2CellId id() const { return it_.id(); }
730
0
  const S2ShapeIndexCell& cell() const { return it_.cell(); }
731
732
  // The min and max leaf cell ids covered by the current cell.  If Done() is
733
  // true, these methods return a value larger than any valid cell id.
734
0
  S2CellId range_min() const { return range_min_; }
735
0
  S2CellId range_max() const { return range_max_; }
736
737
  // Various other convenience methods for the current cell.
738
0
  const S2ClippedShape& clipped() const { return cell().clipped(0); }
739
740
0
  int num_edges() const { return clipped().num_edges(); }
741
0
  bool contains_center() const { return clipped().contains_center(); }
742
743
0
  void Next() { it_.Next(); Refresh(); }
744
0
  bool Done() { return it_.done(); }
745
746
  // Position the iterator at the first cell that overlaps or follows
747
  // "target", i.e. such that range_max() >= target.range_min().
748
0
  void SeekTo(const RangeIterator& target) {
749
0
    it_.Seek(target.range_min());
750
    // If the current cell does not overlap "target", it is possible that the
751
    // previous cell is the one we are looking for.  This can only happen when
752
    // the previous cell contains "target" but has a smaller S2CellId.
753
0
    if (it_.done() || it_.id().range_min() > target.range_max()) {
754
0
      if (it_.Prev() && it_.id().range_max() < target.id()) it_.Next();
755
0
    }
756
0
    Refresh();
757
0
  }
758
759
  // Position the iterator at the first cell that follows "target", i.e. the
760
  // first cell such that range_min() > target.range_max().
761
0
  void SeekBeyond(const RangeIterator& target) {
762
0
    it_.Seek(target.range_max().next());
763
0
    if (!it_.done() && it_.id().range_min() <= target.range_max()) {
764
0
      it_.Next();
765
0
    }
766
0
    Refresh();
767
0
  }
768
769
 private:
770
  // Updates internal state after the iterator has been repositioned.
771
0
  void Refresh() {
772
0
    range_min_ = id().range_min();
773
0
    range_max_ = id().range_max();
774
0
  }
775
776
  MutableS2ShapeIndex::Iterator it_;
777
  S2CellId range_min_, range_max_;
778
};
779
780
// LoopCrosser is a helper class for determining whether two loops cross.
781
// It is instantiated twice for each pair of loops to be tested, once for the
782
// pair (A,B) and once for the pair (B,A), in order to be able to process
783
// edges in either loop nesting order.
784
class LoopCrosser {
785
 public:
786
  // If "swapped" is true, the loops A and B have been swapped.  This affects
787
  // how arguments are passed to the given loop relation, since for example
788
  // A.Contains(B) is not the same as B.Contains(A).
789
  LoopCrosser(const S2Loop& a, const S2Loop& b,
790
              LoopRelation* relation, bool swapped)
791
0
      : a_(a), b_(b), relation_(relation), swapped_(swapped),
792
0
        a_crossing_target_(relation->a_crossing_target()),
793
0
        b_crossing_target_(relation->b_crossing_target()),
794
0
        b_query_(&b.index_) {
795
0
    using std::swap;
796
0
    if (swapped) swap(a_crossing_target_, b_crossing_target_);
797
0
  }
798
799
  // Return the crossing targets for the loop relation, taking into account
800
  // whether the loops have been swapped.
801
0
  int a_crossing_target() const { return a_crossing_target_; }
802
0
  int b_crossing_target() const { return b_crossing_target_; }
803
804
  // Given two iterators positioned such that ai->id().Contains(bi->id()),
805
  // return true if there is a crossing relationship anywhere within ai->id().
806
  // Specifically, this method returns true if there is an edge crossing, a
807
  // wedge crossing, or a point P that matches both "crossing targets".
808
  // Advances both iterators past ai->id().
809
  bool HasCrossingRelation(RangeIterator* ai, RangeIterator* bi);
810
811
  // Given two index cells, return true if there are any edge crossings or
812
  // wedge crossings within those cells.
813
  bool CellCrossesCell(const S2ClippedShape& a_clipped,
814
                       const S2ClippedShape& b_clipped);
815
816
 private:
817
  // Given two iterators positioned such that ai->id().Contains(bi->id()),
818
  // return true if there is an edge crossing or wedge crossing anywhere
819
  // within ai->id().  Advances "bi" (only) past ai->id().
820
  bool HasCrossing(RangeIterator* ai, RangeIterator* bi);
821
822
  // Given an index cell of A, return true if there are any edge or wedge
823
  // crossings with any index cell of B contained within "b_id".
824
  bool CellCrossesAnySubcell(const S2ClippedShape& a_clipped, S2CellId b_id);
825
826
  // Prepare to check the given edge of loop A for crossings.
827
  void StartEdge(int aj);
828
829
  // Check the current edge of loop A for crossings with all edges of the
830
  // given index cell of loop B.
831
  bool EdgeCrossesCell(const S2ClippedShape& b_clipped);
832
833
  const S2Loop& a_;
834
  const S2Loop& b_;
835
  LoopRelation* const relation_;
836
  const bool swapped_;
837
  int a_crossing_target_, b_crossing_target_;
838
839
  // State maintained by StartEdge() and EdgeCrossesCell().
840
  S2EdgeCrosser crosser_;
841
  int aj_, bj_prev_;
842
843
  // Temporary data declared here to avoid repeated memory allocations.
844
  S2CrossingEdgeQuery b_query_;
845
  vector<const S2ShapeIndexCell*> b_cells_;
846
};
847
848
0
inline void LoopCrosser::StartEdge(int aj) {
849
  // Start testing the given edge of A for crossings.
850
0
  crosser_.Init(&a_.vertex(aj), &a_.vertex(aj+1));
851
0
  aj_ = aj;
852
0
  bj_prev_ = -2;
853
0
}
854
855
0
inline bool LoopCrosser::EdgeCrossesCell(const S2ClippedShape& b_clipped) {
856
  // Test the current edge of A against all edges of "b_clipped".
857
0
  int b_num_edges = b_clipped.num_edges();
858
0
  for (int j = 0; j < b_num_edges; ++j) {
859
0
    int bj = b_clipped.edge(j);
860
0
    if (bj != bj_prev_ + 1) crosser_.RestartAt(&b_.vertex(bj));
861
0
    bj_prev_ = bj;
862
0
    int crossing = crosser_.CrossingSign(&b_.vertex(bj + 1));
863
0
    if (crossing < 0) continue;
864
0
    if (crossing > 0) return true;
865
    // We only need to check each shared vertex once, so we only
866
    // consider the case where a_vertex(aj_+1) == b_.vertex(bj+1).
867
0
    if (a_.vertex(aj_+1) == b_.vertex(bj+1)) {
868
0
      if (swapped_ ?
869
0
          relation_->WedgesCross(
870
0
              b_.vertex(bj), b_.vertex(bj+1), b_.vertex(bj+2),
871
0
              a_.vertex(aj_), a_.vertex(aj_+2)) :
872
0
          relation_->WedgesCross(
873
0
              a_.vertex(aj_), a_.vertex(aj_+1), a_.vertex(aj_+2),
874
0
              b_.vertex(bj), b_.vertex(bj+2))) {
875
0
        return true;
876
0
      }
877
0
    }
878
0
  }
879
0
  return false;
880
0
}
881
882
bool LoopCrosser::CellCrossesCell(const S2ClippedShape& a_clipped,
883
0
                                  const S2ClippedShape& b_clipped) {
884
  // Test all edges of "a_clipped" against all edges of "b_clipped".
885
0
  int a_num_edges = a_clipped.num_edges();
886
0
  for (int i = 0; i < a_num_edges; ++i) {
887
0
    StartEdge(a_clipped.edge(i));
888
0
    if (EdgeCrossesCell(b_clipped)) return true;
889
0
  }
890
0
  return false;
891
0
}
892
893
bool LoopCrosser::CellCrossesAnySubcell(const S2ClippedShape& a_clipped,
894
0
                                        S2CellId b_id) {
895
  // Test all edges of "a_clipped" against all edges of B.  The relevant B
896
  // edges are guaranteed to be children of "b_id", which lets us find the
897
  // correct index cells more efficiently.
898
0
  S2PaddedCell b_root(b_id, 0);
899
0
  int a_num_edges = a_clipped.num_edges();
900
0
  for (int i = 0; i < a_num_edges; ++i) {
901
0
    int aj = a_clipped.edge(i);
902
    // Use an S2CrossingEdgeQuery starting at "b_root" to find the index cells
903
    // of B that might contain crossing edges.
904
0
    b_query_.GetCells(a_.vertex(aj), a_.vertex(aj+1), b_root, &b_cells_);
905
0
    if (b_cells_.empty()) continue;
906
0
    StartEdge(aj);
907
0
    for (const S2ShapeIndexCell* b_cell : b_cells_) {
908
0
      if (EdgeCrossesCell(b_cell->clipped(0))) return true;
909
0
    }
910
0
  }
911
0
  return false;
912
0
}
913
914
0
bool LoopCrosser::HasCrossing(RangeIterator* ai, RangeIterator* bi) {
915
0
  ABSL_DCHECK(ai->id().contains(bi->id()));
916
  // If ai->id() intersects many edges of B, then it is faster to use
917
  // S2CrossingEdgeQuery to narrow down the candidates.  But if it intersects
918
  // only a few edges, it is faster to check all the crossings directly.
919
  // We handle this by advancing "bi" and keeping track of how many edges we
920
  // would need to test.
921
922
0
  static const int kEdgeQueryMinEdges = 20;  // Tuned using benchmarks.
923
0
  int total_edges = 0;
924
0
  b_cells_.clear();
925
0
  do {
926
0
    if (bi->num_edges() > 0) {
927
0
      total_edges += bi->num_edges();
928
0
      if (total_edges >= kEdgeQueryMinEdges) {
929
        // There are too many edges to test them directly, so use
930
        // S2CrossingEdgeQuery.
931
0
        if (CellCrossesAnySubcell(ai->clipped(), ai->id())) return true;
932
0
        bi->SeekBeyond(*ai);
933
0
        return false;
934
0
      }
935
0
      b_cells_.push_back(&bi->cell());
936
0
    }
937
0
    bi->Next();
938
0
  } while (bi->id() <= ai->range_max());
939
940
  // Test all the edge crossings directly.
941
0
  for (const S2ShapeIndexCell* b_cell : b_cells_) {
942
0
    if (CellCrossesCell(ai->clipped(), b_cell->clipped(0))) {
943
0
      return true;
944
0
    }
945
0
  }
946
0
  return false;
947
0
}
948
949
0
bool LoopCrosser::HasCrossingRelation(RangeIterator* ai, RangeIterator* bi) {
950
0
  ABSL_DCHECK(ai->id().contains(bi->id()));
951
0
  if (ai->num_edges() == 0) {
952
0
    if (ai->contains_center() == a_crossing_target_) {
953
      // All points within ai->id() satisfy the crossing target for A, so it's
954
      // worth iterating through the cells of B to see whether any cell
955
      // centers also satisfy the crossing target for B.
956
0
      do {
957
0
        if (bi->contains_center() == b_crossing_target_) return true;
958
0
        bi->Next();
959
0
      } while (bi->id() <= ai->range_max());
960
0
    } else {
961
      // The crossing target for A is not satisfied, so we skip over the cells
962
      // of B using binary search.
963
0
      bi->SeekBeyond(*ai);
964
0
    }
965
0
  } else {
966
    // The current cell of A has at least one edge, so check for crossings.
967
0
    if (HasCrossing(ai, bi)) return true;
968
0
  }
969
0
  ai->Next();
970
0
  return false;
971
0
}
972
973
/*static*/ bool S2Loop::HasCrossingRelation(const S2Loop& a, const S2Loop& b,
974
0
                                            LoopRelation* relation) {
975
  // We look for S2CellId ranges where the indexes of A and B overlap, and
976
  // then test those edges for crossings.
977
0
  RangeIterator ai(&a.index_), bi(&b.index_);
978
0
  LoopCrosser ab(a, b, relation, false);  // Tests edges of A against B
979
0
  LoopCrosser ba(b, a, relation, true);   // Tests edges of B against A
980
0
  while (!ai.Done() || !bi.Done()) {
981
0
    if (ai.range_max() < bi.range_min()) {
982
      // The A and B cells don't overlap, and A precedes B.
983
0
      ai.SeekTo(bi);
984
0
    } else if (bi.range_max() < ai.range_min()) {
985
      // The A and B cells don't overlap, and B precedes A.
986
0
      bi.SeekTo(ai);
987
0
    } else {
988
      // One cell contains the other.  Determine which cell is larger.
989
0
      int64_t ab_relation = ai.id().lsb() - bi.id().lsb();
990
0
      if (ab_relation > 0) {
991
        // A's index cell is larger.
992
0
        if (ab.HasCrossingRelation(&ai, &bi)) return true;
993
0
      } else if (ab_relation < 0) {
994
        // B's index cell is larger.
995
0
        if (ba.HasCrossingRelation(&bi, &ai)) return true;
996
0
      } else {
997
        // The A and B cells are the same.  Since the two cells have the same
998
        // center point P, check whether P satisfies the crossing targets.
999
0
        if (ai.contains_center() == ab.a_crossing_target() &&
1000
0
            bi.contains_center() == ab.b_crossing_target()) {
1001
0
          return true;
1002
0
        }
1003
        // Otherwise test all the edge crossings directly.
1004
0
        if (ai.num_edges() > 0 && bi.num_edges() > 0 &&
1005
0
            ab.CellCrossesCell(ai.clipped(), bi.clipped())) {
1006
0
          return true;
1007
0
        }
1008
0
        ai.Next();
1009
0
        bi.Next();
1010
0
      }
1011
0
    }
1012
0
  }
1013
0
  return false;
1014
0
}
1015
1016
// Loop relation for Contains().
1017
class ContainsRelation : public LoopRelation {
1018
 public:
1019
0
  ContainsRelation() : found_shared_vertex_(false) {}
1020
0
  bool found_shared_vertex() const { return found_shared_vertex_; }
1021
1022
  // If A.Contains(P) == false && B.Contains(P) == true, it is equivalent to
1023
  // having an edge crossing (i.e., Contains returns false).
1024
0
  int a_crossing_target() const override { return false; }
1025
0
  int b_crossing_target() const override { return true; }
1026
1027
  bool WedgesCross(const S2Point& a0, const S2Point& ab1, const S2Point& a2,
1028
0
                   const S2Point& b0, const S2Point& b2) override {
1029
0
    found_shared_vertex_ = true;
1030
0
    return !S2::WedgeContains(a0, ab1, a2, b0, b2);
1031
0
  }
1032
1033
 private:
1034
  bool found_shared_vertex_;
1035
};
1036
1037
0
bool S2Loop::Contains(const S2Loop& b) const {
1038
  // For this loop A to contains the given loop B, all of the following must
1039
  // be true:
1040
  //
1041
  //  (1) There are no edge crossings between A and B except at vertices.
1042
  //
1043
  //  (2) At every vertex that is shared between A and B, the local edge
1044
  //      ordering implies that A contains B.
1045
  //
1046
  //  (3) If there are no shared vertices, then A must contain a vertex of B
1047
  //      and B must not contain a vertex of A.  (An arbitrary vertex may be
1048
  //      chosen in each case.)
1049
  //
1050
  // The second part of (3) is necessary to detect the case of two loops whose
1051
  // union is the entire sphere, i.e. two loops that contains each other's
1052
  // boundaries but not each other's interiors.
1053
0
  if (!subregion_bound_.Contains(b.bound_)) return false;
1054
1055
  // Special cases to handle either loop being empty or full.
1056
0
  if (is_empty_or_full() || b.is_empty_or_full()) {
1057
0
    return is_full() || b.is_empty();
1058
0
  }
1059
1060
  // Check whether there are any edge crossings, and also check the loop
1061
  // relationship at any shared vertices.
1062
0
  ContainsRelation relation;
1063
0
  if (HasCrossingRelation(*this, b, &relation)) return false;
1064
1065
  // There are no crossings, and if there are any shared vertices then A
1066
  // contains B locally at each shared vertex.
1067
0
  if (relation.found_shared_vertex()) return true;
1068
1069
  // Since there are no edge intersections or shared vertices, we just need to
1070
  // test condition (3) above.  We can skip this test if we discovered that A
1071
  // contains at least one point of B while checking for edge crossings.
1072
0
  if (!Contains(b.vertex(0))) return false;
1073
1074
  // We still need to check whether (A union B) is the entire sphere.
1075
  // Normally this check is very cheap due to the bounding box precondition.
1076
0
  if ((b.subregion_bound_.Contains(bound_) ||
1077
0
       b.bound_.Union(bound_).is_full()) &&
1078
0
      b.Contains(vertex(0))) {
1079
0
    return false;
1080
0
  }
1081
0
  return true;
1082
0
}
1083
1084
// Loop relation for Intersects().
1085
class IntersectsRelation : public LoopRelation {
1086
 public:
1087
0
  IntersectsRelation() : found_shared_vertex_(false) {}
1088
0
  bool found_shared_vertex() const { return found_shared_vertex_; }
1089
1090
  // If A.Contains(P) == true && B.Contains(P) == true, it is equivalent to
1091
  // having an edge crossing (i.e., Intersects returns true).
1092
0
  int a_crossing_target() const override { return true; }
1093
0
  int b_crossing_target() const override { return true; }
1094
1095
  bool WedgesCross(const S2Point& a0, const S2Point& ab1, const S2Point& a2,
1096
0
                   const S2Point& b0, const S2Point& b2) override {
1097
0
    found_shared_vertex_ = true;
1098
0
    return S2::WedgeIntersects(a0, ab1, a2, b0, b2);
1099
0
  }
1100
1101
 private:
1102
  bool found_shared_vertex_;
1103
};
1104
1105
0
bool S2Loop::Intersects(const S2Loop& b) const {
1106
  // a->Intersects(b) if and only if !a->Complement()->Contains(b).
1107
  // This code is similar to Contains(), but is optimized for the case
1108
  // where both loops enclose less than half of the sphere.
1109
0
  if (!bound_.Intersects(b.bound_)) return false;
1110
1111
  // Check whether there are any edge crossings, and also check the loop
1112
  // relationship at any shared vertices.
1113
0
  IntersectsRelation relation;
1114
0
  if (HasCrossingRelation(*this, b, &relation)) return true;
1115
0
  if (relation.found_shared_vertex()) return false;
1116
1117
  // Since there are no edge intersections or shared vertices, the loops
1118
  // intersect only if A contains B, B contains A, or the two loops contain
1119
  // each other's boundaries.  These checks are usually cheap because of the
1120
  // bounding box preconditions.  Note that neither loop is empty (because of
1121
  // the bounding box check above), so it is safe to access vertex(0).
1122
1123
  // Check whether A contains B, or A and B contain each other's boundaries.
1124
  // (Note that A contains all the vertices of B in either case.)
1125
0
  if (subregion_bound_.Contains(b.bound_) || bound_.Union(b.bound_).is_full()) {
1126
0
    if (Contains(b.vertex(0))) return true;
1127
0
  }
1128
  // Check whether B contains A.
1129
0
  if (b.subregion_bound_.Contains(bound_)) {
1130
0
    if (b.Contains(vertex(0))) return true;
1131
0
  }
1132
0
  return false;
1133
0
}
1134
1135
// Returns true if the wedge (a0, ab1, a2) contains the "semiwedge" defined as
1136
// any non-empty open set of rays immediately CCW from the edge (ab1, b2).  If
1137
// "reverse_b" is true, then substitute "clockwise" for "CCW"; this simulates
1138
// what would happen if the direction of loop B was reversed.
1139
inline static bool WedgeContainsSemiwedge(const S2Point& a0, const S2Point& ab1,
1140
                                          const S2Point& a2, const S2Point& b2,
1141
0
                                          bool reverse_b) {
1142
0
  if (b2 == a0 || b2 == a2) {
1143
    // We have a shared or reversed edge.
1144
0
    return (b2 == a0) == reverse_b;
1145
0
  } else {
1146
0
    return s2pred::OrderedCCW(a0, a2, b2, ab1);
1147
0
  }
1148
0
}
1149
1150
// Loop relation for CompareBoundary().
1151
class CompareBoundaryRelation : public LoopRelation {
1152
 public:
1153
  explicit CompareBoundaryRelation(bool reverse_b):
1154
0
      reverse_b_(reverse_b), found_shared_vertex_(false),
1155
0
      contains_edge_(false), excludes_edge_(false) {
1156
0
  }
1157
0
  bool found_shared_vertex() const { return found_shared_vertex_; }
1158
0
  bool contains_edge() const { return contains_edge_; }
1159
1160
  // The CompareBoundary relation does not have a useful early-exit condition,
1161
  // so we return -1 for both crossing targets.
1162
  //
1163
  // Aside: A possible early exit condition could be based on the following.
1164
  //   If A contains a point of both B and ~B, then A intersects Boundary(B).
1165
  //   If ~A contains a point of both B and ~B, then ~A intersects Boundary(B).
1166
  //   So if the intersections of {A, ~A} with {B, ~B} are all non-empty,
1167
  //   the return value is 0, i.e., Boundary(A) intersects Boundary(B).
1168
  // Unfortunately it isn't worth detecting this situation because by the
1169
  // time we have seen a point in all four intersection regions, we are also
1170
  // guaranteed to have seen at least one pair of crossing edges.
1171
0
  int a_crossing_target() const override { return -1; }
1172
0
  int b_crossing_target() const override { return -1; }
1173
1174
  bool WedgesCross(const S2Point& a0, const S2Point& ab1, const S2Point& a2,
1175
0
                   const S2Point& b0, const S2Point& b2) override {
1176
    // Because we don't care about the interior of B, only its boundary, it is
1177
    // sufficient to check whether A contains the semiwedge (ab1, b2).
1178
0
    found_shared_vertex_ = true;
1179
0
    if (WedgeContainsSemiwedge(a0, ab1, a2, b2, reverse_b_)) {
1180
0
      contains_edge_ = true;
1181
0
    } else {
1182
0
      excludes_edge_ = true;
1183
0
    }
1184
0
    return contains_edge_ & excludes_edge_;
1185
0
  }
1186
1187
 protected:
1188
  const bool reverse_b_;      // True if loop B should be reversed.
1189
  bool found_shared_vertex_;  // True if any wedge was processed.
1190
  bool contains_edge_;        // True if any edge of B is contained by A.
1191
  bool excludes_edge_;        // True if any edge of B is excluded by A.
1192
};
1193
1194
0
int S2Loop::CompareBoundary(const S2Loop& b) const {
1195
0
  ABSL_DCHECK(!is_empty() && !b.is_empty());
1196
0
  ABSL_DCHECK(!b.is_full() || !b.is_hole());
1197
1198
  // The bounds must intersect for containment or crossing.
1199
0
  if (!bound_.Intersects(b.bound_)) return -1;
1200
1201
  // Full loops are handled as though the loop surrounded the entire sphere.
1202
0
  if (is_full()) return 1;
1203
0
  if (b.is_full()) return -1;
1204
1205
  // Check whether there are any edge crossings, and also check the loop
1206
  // relationship at any shared vertices.
1207
0
  CompareBoundaryRelation relation(b.is_hole());
1208
0
  if (HasCrossingRelation(*this, b, &relation)) return 0;
1209
0
  if (relation.found_shared_vertex()) {
1210
0
    return relation.contains_edge() ? 1 : -1;
1211
0
  }
1212
1213
  // There are no edge intersections or shared vertices, so we can check
1214
  // whether A contains an arbitrary vertex of B.
1215
0
  return Contains(b.vertex(0)) ? 1 : -1;
1216
0
}
1217
1218
0
bool S2Loop::ContainsNested(const S2Loop& b) const {
1219
0
  if (!subregion_bound_.Contains(b.bound_)) return false;
1220
1221
  // Special cases to handle either loop being empty or full.  Also bail out
1222
  // when B has no vertices to avoid heap overflow on the vertex(1) call
1223
  // below.  (This method is called during polygon initialization before the
1224
  // client has an opportunity to call IsValid().)
1225
0
  if (is_empty_or_full() || b.num_vertices() < 2) {
1226
0
    return is_full() || b.is_empty();
1227
0
  }
1228
1229
  // We are given that A and B do not share any edges, and that either one
1230
  // loop contains the other or they do not intersect.
1231
0
  int m = FindVertex(b.vertex(1));
1232
0
  if (m < 0) {
1233
    // Since b.vertex(1) is not shared, we can check whether A contains it.
1234
0
    return Contains(b.vertex(1));
1235
0
  }
1236
  // Check whether the edge order around b.vertex(1) is compatible with
1237
  // A containing B.
1238
0
  return S2::WedgeContains(vertex(m - 1), vertex(m), vertex(m + 1), b.vertex(0),
1239
0
                           b.vertex(2));
1240
0
}
1241
1242
0
bool S2Loop::Equals(const S2Loop& b) const {
1243
0
  if (num_vertices() != b.num_vertices()) return false;
1244
0
  for (int i = 0; i < num_vertices(); ++i) {
1245
0
    if (vertex(i) != b.vertex(i)) return false;
1246
0
  }
1247
0
  return true;
1248
0
}
1249
1250
0
bool S2Loop::BoundaryEquals(const S2Loop& b) const {
1251
0
  if (num_vertices() != b.num_vertices()) return false;
1252
1253
  // Special case to handle empty or full loops.  Since they have the same
1254
  // number of vertices, if one loop is empty/full then so is the other.
1255
0
  if (is_empty_or_full()) return is_empty() == b.is_empty();
1256
1257
0
  for (int offset = 0; offset < num_vertices(); ++offset) {
1258
0
    if (vertex(offset) == b.vertex(0)) {
1259
      // There is at most one starting offset since loop vertices are unique.
1260
0
      for (int i = 0; i < num_vertices(); ++i) {
1261
0
        if (vertex(i + offset) != b.vertex(i)) return false;
1262
0
      }
1263
0
      return true;
1264
0
    }
1265
0
  }
1266
0
  return false;
1267
0
}
1268
1269
0
bool S2Loop::BoundaryApproxEquals(const S2Loop& b, S1Angle max_error) const {
1270
0
  if (num_vertices() != b.num_vertices()) return false;
1271
1272
  // Special case to handle empty or full loops.  Since they have the same
1273
  // number of vertices, if one loop is empty/full then so is the other.
1274
0
  if (is_empty_or_full()) return is_empty() == b.is_empty();
1275
1276
0
  for (int offset = 0; offset < num_vertices(); ++offset) {
1277
0
    if (S2::ApproxEquals(vertex(offset), b.vertex(0), max_error)) {
1278
0
      bool success = true;
1279
0
      for (int i = 0; i < num_vertices(); ++i) {
1280
0
        if (!S2::ApproxEquals(vertex(i + offset), b.vertex(i), max_error)) {
1281
0
          success = false;
1282
0
          break;
1283
0
        }
1284
0
      }
1285
0
      if (success) return true;
1286
      // Otherwise continue looping.  There may be more than one candidate
1287
      // starting offset since vertices are only matched approximately.
1288
0
    }
1289
0
  }
1290
0
  return false;
1291
0
}
1292
1293
static bool MatchBoundaries(const S2Loop& a, const S2Loop& b, int a_offset,
1294
0
                            S1Angle max_error) {
1295
  // The state consists of a pair (i,j).  A state transition consists of
1296
  // incrementing either "i" or "j".  "i" can be incremented only if
1297
  // a(i+1+a_offset) is near the edge from b(j) to b(j+1), and a similar rule
1298
  // applies to "j".  The function returns true iff we can proceed all the way
1299
  // around both loops in this way.
1300
  //
1301
  // Note that when "i" and "j" can both be incremented, sometimes only one
1302
  // choice leads to a solution.  We handle this using a stack and
1303
  // backtracking.  We also keep track of which states have already been
1304
  // explored to avoid duplicating work.
1305
1306
0
  vector<pair<int, int>> pending;
1307
0
  flat_hash_set<pair<int, int>> done;
1308
0
  pending.push_back(std::make_pair(0, 0));
1309
0
  while (!pending.empty()) {
1310
0
    int i = pending.back().first;
1311
0
    int j = pending.back().second;
1312
0
    pending.pop_back();
1313
0
    if (i == a.num_vertices() && j == b.num_vertices()) {
1314
0
      return true;
1315
0
    }
1316
0
    done.insert(std::make_pair(i, j));
1317
1318
    // If (i == na && offset == na-1) where na == a->num_vertices(), then
1319
    // then (i+1+offset) overflows the [0, 2*na-1] range allowed by vertex().
1320
    // So we reduce the range if necessary.
1321
0
    int io = i + a_offset;
1322
0
    if (io >= a.num_vertices()) io -= a.num_vertices();
1323
1324
0
    if (i < a.num_vertices() && done.count(std::make_pair(i + 1, j)) == 0 &&
1325
0
        S2::GetDistance(a.vertex(io + 1), b.vertex(j),
1326
0
                                b.vertex(j + 1)) <= max_error) {
1327
0
      pending.push_back(std::make_pair(i + 1, j));
1328
0
    }
1329
0
    if (j < b.num_vertices() && done.count(std::make_pair(i, j + 1)) == 0 &&
1330
0
        S2::GetDistance(b.vertex(j + 1), a.vertex(io),
1331
0
                                a.vertex(io + 1)) <= max_error) {
1332
0
      pending.push_back(std::make_pair(i, j + 1));
1333
0
    }
1334
0
  }
1335
0
  return false;
1336
0
}
1337
1338
0
bool S2Loop::BoundaryNear(const S2Loop& b, S1Angle max_error) const {
1339
  // Special case to handle empty or full loops.
1340
0
  if (is_empty_or_full() || b.is_empty_or_full()) {
1341
0
    return (is_empty() && b.is_empty()) || (is_full() && b.is_full());
1342
0
  }
1343
1344
0
  for (int a_offset = 0; a_offset < num_vertices(); ++a_offset) {
1345
0
    if (MatchBoundaries(*this, b, a_offset, max_error)) return true;
1346
0
  }
1347
0
  return false;
1348
0
}
1349
1350
0
void S2Loop::GetXYZFaceSiTiVertices(S2XYZFaceSiTi* vertices) const {
1351
0
  for (int i = 0; i < num_vertices(); ++i) {
1352
0
    vertices[i].xyz = vertex(i);
1353
0
    vertices[i].cell_level = S2::XYZtoFaceSiTi(vertices[i].xyz,
1354
0
        &vertices[i].face, &vertices[i].si, &vertices[i].ti);
1355
0
  }
1356
0
}
1357
1358
void S2Loop::EncodeCompressed(Encoder* encoder, const S2XYZFaceSiTi* vertices,
1359
0
                              int snap_level) const {
1360
  // Ensure enough for the data we write before S2EncodePointsCompressed.
1361
  // S2EncodePointsCompressed ensures its space.
1362
0
  encoder->Ensure(Encoder::kVarintMax32);
1363
0
  encoder->put_varint32(num_vertices_);
1364
1365
0
  S2EncodePointsCompressed(MakeSpan(vertices, num_vertices_),
1366
0
                           snap_level, encoder);
1367
1368
0
  std::bitset<kNumProperties> properties = GetCompressedEncodingProperties();
1369
1370
  // Ensure enough only for what we write.  Let the bound ensure its own
1371
  // space.
1372
0
  encoder->Ensure(2 * Encoder::kVarintMax32);
1373
0
  encoder->put_varint32(properties.to_ulong());
1374
0
  encoder->put_varint32(depth_);
1375
0
  if (properties.test(kBoundEncoded)) {
1376
0
    bound_.Encode(encoder);
1377
0
  }
1378
0
  ABSL_DCHECK_GE(encoder->avail(), 0);
1379
0
}
1380
1381
0
bool S2Loop::DecodeCompressed(Decoder* decoder, int snap_level) {
1382
  // get_varint32 takes a uint32_t*, but num_vertices_ is signed.
1383
  // Decode to a temporary variable to avoid reinterpret_cast.
1384
0
  uint32_t unsigned_num_vertices;
1385
0
  if (!decoder->get_varint32(&unsigned_num_vertices)) {
1386
0
    return false;
1387
0
  }
1388
0
  if (unsigned_num_vertices == 0 ||
1389
0
      unsigned_num_vertices > static_cast<uint32_t>(absl::GetFlag(
1390
0
                                  FLAGS_s2polygon_decode_max_num_vertices))) {
1391
0
    return false;
1392
0
  }
1393
0
  ClearIndex();
1394
0
  num_vertices_ = unsigned_num_vertices;
1395
0
  vertices_ = make_unique<S2Point[]>(num_vertices_);
1396
1397
0
  if (!S2DecodePointsCompressed(decoder, snap_level,
1398
0
                                MakeSpan(vertices_.get(), num_vertices_))) {
1399
0
    return false;
1400
0
  }
1401
0
  uint32_t properties_uint32;
1402
0
  if (!decoder->get_varint32(&properties_uint32)) {
1403
0
    return false;
1404
0
  }
1405
0
  const std::bitset<kNumProperties> properties(properties_uint32);
1406
0
  origin_inside_ = properties.test(kOriginInside);
1407
1408
0
  uint32_t unsigned_depth;
1409
0
  if (!decoder->get_varint32(&unsigned_depth)) {
1410
0
    return false;
1411
0
  }
1412
0
  depth_ = unsigned_depth;
1413
1414
0
  if (properties.test(kBoundEncoded)) {
1415
0
    if (!bound_.Decode(decoder)) {
1416
0
      return false;
1417
0
    }
1418
0
    subregion_bound_ = S2LatLngRectBounder::ExpandForSubregions(bound_);
1419
0
  } else {
1420
0
    InitBound();
1421
0
  }
1422
0
  InitIndex();
1423
0
  return true;
1424
0
}
1425
1426
0
std::bitset<kNumProperties> S2Loop::GetCompressedEncodingProperties() const {
1427
0
  std::bitset<kNumProperties> properties;
1428
0
  if (origin_inside_) {
1429
0
    properties.set(kOriginInside);
1430
0
  }
1431
1432
  // Write whether there is a bound so we can change the threshold later.
1433
  // Recomputing the bound multiplies the decode time taken per vertex
1434
  // by a factor of about 3.5.  Without recomputing the bound, decode
1435
  // takes approximately 125 ns / vertex.  A loop with 63 vertices
1436
  // encoded without the bound will take ~30us to decode, which is
1437
  // acceptable.  At ~3.5 bytes / vertex without the bound, adding
1438
  // the bound will increase the size by <15%, which is also acceptable.
1439
0
  static const int kMinVerticesForBound = 64;
1440
0
  if (num_vertices_ >= kMinVerticesForBound) {
1441
0
    properties.set(kBoundEncoded);
1442
0
  }
1443
0
  return properties;
1444
0
}
1445
1446
/* static */
1447
unique_ptr<S2Loop> S2Loop::MakeRegularLoop(const S2Point& center,
1448
0
                                           S1Angle radius, int num_vertices) {
1449
0
  return MakeRegularLoop(S2::GetFrame(center), radius, num_vertices);
1450
0
}
1451
1452
/* static */
1453
unique_ptr<S2Loop> S2Loop::MakeRegularLoop(const Matrix3x3_d& frame,
1454
0
                                           S1Angle radius, int num_vertices) {
1455
  // We construct the loop in the given frame coordinates, with the center at
1456
  // (0, 0, 1).  For a loop of radius "r", the loop vertices have the form
1457
  // (x, y, z) where x^2 + y^2 = sin(r) and z = cos(r).  The distance on the
1458
  // sphere (arc length) from each vertex to the center is acos(cos(r)) = r.
1459
0
  const S1Angle::SinCosPair r_and_z = radius.SinCos();
1460
0
  const double r = r_and_z.sin;
1461
0
  const double z = r_and_z.cos;
1462
0
  const double radian_step = 2 * M_PI / num_vertices;
1463
0
  vector<S2Point> vertices;
1464
0
  vertices.reserve(num_vertices);
1465
0
  for (int i = 0; i < num_vertices; ++i) {
1466
0
    const S1Angle angle = S1Angle::Radians(i * radian_step);
1467
0
    const S1Angle::SinCosPair a = angle.SinCos();
1468
0
    const S2Point p(r * a.cos, r * a.sin, z);
1469
0
    vertices.push_back(S2::FromFrame(frame, p).Normalize());
1470
0
  }
1471
0
  return make_unique<S2Loop>(vertices);
1472
0
}
1473
1474
0
size_t S2Loop::SpaceUsed() const {
1475
0
  size_t size = sizeof(*this);
1476
0
  size += num_vertices() * sizeof(S2Point);
1477
  // index_ itself is already included in sizeof(*this).
1478
0
  size += index_.SpaceUsed() - sizeof(index_);
1479
0
  return size;
1480
0
}
1481
1482
0
int S2Loop::Shape::num_chains() const {
1483
0
  return loop_->is_empty() ? 0 : 1;
1484
0
}
1485
1486
0
S2Shape::Chain S2Loop::Shape::chain(int i) const {
1487
0
  ABSL_DCHECK_EQ(i, 0);
1488
0
  return Chain(0, Shape::num_edges());  // Avoid virtual call.
1489
0
}