Coverage Report

Created: 2026-11-10 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/s2geometry/src/s2/s2shapeutil_edge_wrap.cc
Line
Count
Source
1
// Copyright 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
#include "s2/s2shapeutil_edge_wrap.h"
17
18
#include "absl/log/absl_check.h"
19
#include "s2/s2point.h"
20
#include "s2/s2shape.h"
21
22
namespace s2shapeutil {
23
24
0
int NextEdgeWrap(const S2Shape& shape, int edge_id) {
25
0
  ABSL_DCHECK_GE(edge_id, 0);
26
0
  ABSL_DCHECK_LT(edge_id, shape.num_edges());
27
28
0
  S2Shape::ChainPosition chainpos = shape.chain_position(edge_id);
29
0
  S2Shape::Chain chaininfo = shape.chain(chainpos.chain_id);
30
31
  // Polygon chains wrap around, point and polylines don't.
32
0
  int offset = chainpos.offset;
33
0
  switch (shape.dimension()) {
34
0
    case 2:
35
      // Polygon chains always wrap around.
36
0
      offset = (offset + 1) % chaininfo.length;
37
0
      break;
38
39
0
    case 1:
40
      // If we're at the end of a polyline, wrap around if it's closed.
41
0
      if (offset == chaininfo.length - 1) {
42
0
        const S2Shape::Edge& curr = shape.chain_edge(chainpos.chain_id, offset);
43
0
        const S2Shape::Edge& next = shape.chain_edge(chainpos.chain_id, 0);
44
45
0
        if (curr.v1 == next.v0) {
46
0
          offset = 0;
47
0
        } else {
48
0
          return -1;
49
0
        }
50
0
      } else {
51
0
        ++offset;
52
0
      }
53
0
      break;
54
55
0
    default:
56
      // Points are one per chain.
57
0
      return -1;
58
0
  }
59
60
0
  return chaininfo.start + offset;
61
0
}
62
63
0
int PrevEdgeWrap(const S2Shape& shape, int edge_id) {
64
0
  ABSL_DCHECK_GE(edge_id, 0);
65
0
  ABSL_DCHECK_LT(edge_id, shape.num_edges());
66
67
0
  S2Shape::ChainPosition chainpos = shape.chain_position(edge_id);
68
0
  S2Shape::Chain chaininfo = shape.chain(chainpos.chain_id);
69
70
0
  int offset = chainpos.offset;
71
0
  switch (shape.dimension()) {
72
0
    case 2:
73
      // Polygons always wrap around.
74
0
      --offset;
75
0
      if (offset < 0) {
76
0
        offset += chaininfo.length;
77
0
      }
78
0
      break;
79
80
0
    case 1:
81
0
      if (offset == 0) {
82
0
        int end = chaininfo.length - 1;
83
0
        const S2Shape::Edge& curr = shape.chain_edge(chainpos.chain_id, 0);
84
0
        const S2Shape::Edge& prev = shape.chain_edge(chainpos.chain_id, end);
85
86
0
        if (prev.v1 == curr.v0) {
87
0
          offset = end;
88
0
        } else {
89
0
          return -1;
90
0
        }
91
0
      } else {
92
0
        --offset;
93
0
      }
94
0
      break;
95
96
0
    default:
97
      // Points are one per chain.
98
0
      return -1;
99
0
  }
100
101
0
  return chaininfo.start + offset;
102
0
}
103
104
}  //  namespace s2shapeutil