Coverage Report

Created: 2023-09-25 06:27

/src/s2geometry/src/s2/s2point.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef S2_S2POINT_H_
19
#define S2_S2POINT_H_
20
21
#include <utility>
22
23
#include "absl/base/attributes.h"
24
#include "absl/hash/hash.h"
25
#include "s2/util/coding/coder.h"
26
#include "s2/_fp_contract_off.h"
27
#include "s2/s2coder.h"
28
#include "s2/s2error.h"
29
#include "s2/util/math/vector.h"  // IWYU pragma: export
30
31
// An S2Point represents a point on the unit sphere as a 3D vector.  Usually
32
// points are normalized to be unit length, but some methods do not require
33
// this.  See util/math/vector.h for the methods available.  Among other
34
// things, there are overloaded operators that make it convenient to write
35
// arithmetic expressions (e.g. (1-x)*p1 + x*p2).
36
class S2Point : public Vector3_d {
37
  using ValType = double;
38
39
 public:
40
  typedef s2coding::S2BasicCoder<S2Point> Coder;
41
42
  // Inherit base class constructors.
43
  using Base = Vector3_d;
44
  using Base::Base;
45
46
  // When S2Point was defined as a Vector3_d we could mix and match the two
47
  // names.  With inheritance upcasting to a Vector3_d is easy, but we need to
48
  // explicitly allow the other direction, even though there's no data to
49
  // modify.  These are not marked explicit because this translation wasn't
50
  // explicit before.
51
52
  // NOLINTNEXTLINE(google-explicit-constructor)
53
0
  S2Point(const Base& base) : Base(base) {}
54
55
  // NOLINTNEXTLINE(google-explicit-constructor)
56
0
  S2Point(Base&& base) : Base(std::move(base)) {}
57
58
  // Initialize S2Point from a Decoder instance.
59
0
  bool Init(Decoder* decoder, S2Error& error) {
60
0
    if (decoder->avail() < sizeof(S2Point)) {
61
0
      error.Init(S2Error::DATA_LOSS, "Not enough data to decode S2Point");
62
0
      return false;
63
0
    }
64
0
65
0
    x(decoder->getdouble());
66
0
    y(decoder->getdouble());
67
0
    z(decoder->getdouble());
68
0
    return true;
69
0
  }
70
71
0
  S2Point& operator=(const Base& base) {
72
0
    Base::operator=(base);
73
0
    return *this;
74
0
  }
75
76
0
  S2Point& operator=(Base&& base) {
77
0
    Base::operator=(std::move(base));
78
0
    return *this;
79
0
  }
80
81
  // We can freely convert between S2Point and Vector3_d with no cost, but there
82
  // are a few corner cases where returning a Vector3_d can cause problems.
83
  // Notably the type of a ternary operator is evaluated independently of the
84
  // type being assigned to, so something like:
85
  //
86
  //   S2Point pnt = (x < 0) ? start_pnt : start_pnt + step;
87
  // (where start_pnt and step are both S2Point)
88
  //
89
  // Would fail to compile because start_pnt is an S2Point but start_pnt + step
90
  // is a Vector3_d, which is likely surprising to people.  So add overloads for
91
  // functions that return a Vector3_d to force return types to be covariant.
92
0
  S2Point& operator+=(const S2Point& b) {
93
0
    Base::operator+=(b);
94
0
    return *this;
95
0
  }
96
0
  S2Point& operator-=(const S2Point& b) {
97
0
    Base::operator-=(b);
98
0
    return *this;
99
0
  }
100
0
  S2Point& operator*=(const ValType& v) {
101
0
    Base::operator*=(v);
102
0
    return *this;
103
0
  }
104
0
  S2Point& operator/=(const ValType& v) {
105
0
    Base::operator/=(v);
106
0
    return *this;
107
0
  }
108
109
0
  S2Point operator+(const S2Point& b) const { return Base::operator+(b); }
110
0
  S2Point operator-(const S2Point& b) const { return Base::operator-(b); }
111
0
  S2Point operator*(const ValType& v) const { return Base::operator*(v); }
112
0
  S2Point operator/(const ValType& v) const { return Base::operator/(v); }
113
114
0
  friend S2Point operator-(const S2Point& pnt) {
115
0
    return -static_cast<const Base&>(pnt);
116
0
  }
117
118
  template <typename T>
119
0
  static S2Point Cast(const Vector3<T>& b) {
120
0
    return Base::Cast(b);
121
0
  }
122
123
0
  S2Point MulComponents(const S2Point& b) const {
124
0
    return Base::MulComponents(b);
125
0
  }
126
0
  S2Point DivComponents(const S2Point& b) const {
127
0
    return Base::DivComponents(b);
128
0
  }
129
130
0
  friend S2Point Max(const S2Point& a, const S2Point& b) {
131
0
    return Max(static_cast<const Base&>(a), static_cast<const Base&>(b));
132
0
  }
133
134
0
  friend S2Point Min(const S2Point& a, const S2Point& b) {
135
0
    return Min(static_cast<const Base&>(a), static_cast<const Base&>(b));
136
0
  }
137
138
0
  S2Point Normalize() const { return Base::Normalize(); }
139
0
  S2Point Sqrt() const { return Base::Sqrt(); }
140
0
  S2Point Floor() const { return Base::Floor(); }
141
0
  S2Point Ceil() const { return Base::Ceil(); }
142
0
  S2Point FRound() const { return Base::FRound(); }
143
0
  static S2Point NaN() { return Base::NaN(); }
144
145
0
  void Encode(Encoder* encoder) const {
146
0
    encoder->Ensure(sizeof(S2Point));
147
0
    encoder->putn(Data(), sizeof(S2Point));
148
0
  }
149
};
150
151
// S2PointHash can be used with standard containers (e.g., unordered_set) or
152
// nonstandard extensions (e.g., hash_map).  It is defined such that if two
153
// S2Points compare equal to each other, they have the same hash.  (This
154
// requires that positive and negative zero hash to the same value.)
155
using S2PointHash = absl::Hash<S2Point>;
156
157
#endif  // S2_S2POINT_H_