1use super::{ST_TO_UV, face_uv_to_xyz};
2use crate::geometry::{LonLat, S2CellId, xyz_to_face_st, xyz_to_face_uv};
3use core::{
4 cmp::Ordering,
5 fmt::Debug,
6 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
7};
8use libm::{atan2, fabs, sqrt};
9use s2json::{GetXY, GetZ, NewXY, NewXYZ, SetXY, SetZ, VectorPoint};
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize, Deserialize)]
45#[repr(C)]
46pub struct S2Point {
47 pub x: f64,
49 pub y: f64,
51 pub z: f64,
53}
54impl GetXY for S2Point {
55 fn x(&self) -> f64 {
56 self.x
57 }
58 fn y(&self) -> f64 {
59 self.y
60 }
61}
62impl GetZ for S2Point {
63 fn z(&self) -> Option<f64> {
64 Some(self.z)
65 }
66}
67impl NewXY for S2Point {
68 fn new_xy(x: f64, y: f64) -> Self {
69 S2Point { x, y, z: 0.0 }
70 }
71}
72impl NewXYZ for S2Point {
73 fn new_xyz(x: f64, y: f64, z: f64) -> Self {
74 S2Point { x, y, z }
75 }
76}
77impl SetXY for S2Point {
78 fn set_x(&mut self, x: f64) {
79 self.x = x;
80 }
81 fn set_y(&mut self, y: f64) {
82 self.y = y;
83 }
84}
85impl SetZ for S2Point {
86 fn set_z(&mut self, z: f64) {
87 self.z = z;
88 }
89}
90impl S2Point {
91 pub fn new(x: f64, y: f64, z: f64) -> Self {
93 S2Point { x, y, z }
94 }
95
96 pub fn is_empty(&self) -> bool {
98 let zero = f64::default();
99 self.x == zero && self.y == zero && self.z == zero
100 }
101
102 pub fn face(&self, f: u8) -> f64 {
104 if f == 0 {
105 self.x
106 } else if f == 1 {
107 self.y
108 } else {
109 self.z
110 }
111 }
112
113 pub fn angle(&self, b: &Self) -> f64 {
117 atan2(self.cross(b).norm(), self.dot(b))
118 }
119
120 pub fn cross(&self, b: &Self) -> Self {
122 Self::new(
123 self.y * b.z - self.z * b.y,
124 self.z * b.x - self.x * b.z,
125 self.x * b.y - self.y * b.x,
126 )
127 }
128
129 pub fn to_face_st(&self) -> (u8, f64, f64) {
131 xyz_to_face_st(self)
132 }
133
134 pub fn get_face(&self) -> u8 {
136 xyz_to_face_uv(self).0
137 }
138
139 pub fn dot(&self, b: &Self) -> f64 {
141 self.x * b.x + self.y * b.y + self.z * b.z
142 }
143
144 pub fn abs(&self) -> Self {
146 Self::new(fabs(self.x), fabs(self.y), fabs(self.z))
147 }
148
149 pub fn invert(&self) -> Self {
151 Self::new(-self.x, -self.y, -self.z)
152 }
153
154 pub fn len(&self) -> f64 {
156 self.norm()
157 }
158
159 pub fn norm(&self) -> f64 {
161 sqrt(self.norm2())
162 }
163
164 pub fn norm2(&self) -> f64 {
166 self.dot(self)
167 }
168
169 pub fn normalize(&mut self) {
171 let len = self.len();
172 if len > 0.0 {
173 self.x /= len;
174 self.y /= len;
175 self.z /= len;
176 }
177 }
178
179 pub fn distance(&self, b: &Self) -> f64 {
181 let d = *self - *b;
182 d.len()
183 }
184
185 pub fn largest_abs_component(&self) -> u8 {
187 let tmp = self.abs();
188 if tmp.x > tmp.y {
189 if tmp.x > tmp.z { 0 } else { 2 }
190 } else if tmp.y > tmp.z {
191 1
192 } else {
193 2
194 }
195 }
196
197 pub fn intermediate(&self, b: &Self, t: f64) -> Self {
199 Self::new(
200 self.x + ((b.x - self.x) * (1.0 - t)),
201 self.y + ((b.y - self.y) * (1.0 - t)),
202 self.z + ((b.z - self.z) * (1.0 - t)),
203 )
204 }
205
206 pub fn from_face_uv(face: u8, u: f64, v: f64) -> Self {
208 let mut p = face_uv_to_xyz(face, u, v);
209 p.normalize();
210 p
211 }
212
213 pub fn from_face_st(face: u8, s: f64, t: f64) -> Self {
215 let u = ST_TO_UV(s);
216 let v = ST_TO_UV(t);
217 Self::from_face_uv(face, u, v)
218 }
219}
220impl<M: Clone + Default> From<&LonLat<M>> for S2Point {
221 fn from(lonlat: &LonLat<M>) -> Self {
222 lonlat.to_point()
223 }
224}
225impl<M: Clone + Default> From<&VectorPoint<M>> for S2Point {
226 fn from(v: &VectorPoint<M>) -> Self {
227 Self { x: v.x, y: v.y, z: v.z.unwrap_or(0.0) }
228 }
229}
230impl<M: Clone + Default> From<&mut VectorPoint<M>> for S2Point {
231 fn from(v: &mut VectorPoint<M>) -> Self {
232 Self { x: v.x, y: v.y, z: v.z.unwrap_or(0.0) }
233 }
234}
235impl From<S2CellId> for S2Point {
236 fn from(cellid: S2CellId) -> Self {
237 cellid.to_point()
238 }
239}
240impl Add<S2Point> for S2Point {
242 type Output = Self;
243 fn add(self, other: Self) -> Self::Output {
244 S2Point { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z }
245 }
246}
247impl AddAssign<S2Point> for S2Point {
248 fn add_assign(&mut self, other: S2Point) {
249 self.x += other.x;
250 self.y += other.y;
251 self.z += other.z;
252 }
253}
254impl Add<f64> for S2Point {
255 type Output = Self;
256 fn add(self, other: f64) -> Self::Output {
257 S2Point { x: self.x + other, y: self.y + other, z: self.z + other }
258 }
259}
260impl AddAssign<f64> for S2Point {
261 fn add_assign(&mut self, other: f64) {
262 self.x += other;
263 self.y += other;
264 self.z += other;
265 }
266}
267impl Sub<S2Point> for S2Point {
269 type Output = Self;
270 fn sub(self, other: Self) -> Self::Output {
271 S2Point { x: self.x - other.x, y: self.y - other.y, z: self.z - other.z }
272 }
273}
274impl SubAssign<S2Point> for S2Point {
275 fn sub_assign(&mut self, other: S2Point) {
276 self.x -= other.x;
277 self.y -= other.y;
278 self.z -= other.z;
279 }
280}
281impl Sub<f64> for S2Point {
282 type Output = Self;
283 fn sub(self, other: f64) -> Self::Output {
284 S2Point { x: self.x - other, y: self.y - other, z: self.z - other }
285 }
286}
287impl SubAssign<f64> for S2Point {
288 fn sub_assign(&mut self, other: f64) {
289 self.x -= other;
290 self.y -= other;
291 self.z -= other;
292 }
293}
294impl Neg for S2Point {
296 type Output = Self;
297 fn neg(self) -> Self::Output {
298 S2Point { x: -self.x, y: -self.y, z: -self.z }
299 }
300}
301impl Div<S2Point> for S2Point {
303 type Output = Self;
304 fn div(self, other: Self) -> Self::Output {
305 S2Point { x: self.x / other.x, y: self.y / other.y, z: self.z / other.z }
306 }
307}
308impl DivAssign<S2Point> for S2Point {
309 fn div_assign(&mut self, other: S2Point) {
310 self.x /= other.x;
311 self.y /= other.y;
312 self.z /= other.z;
313 }
314}
315impl Div<f64> for S2Point {
316 type Output = Self;
317 fn div(self, other: f64) -> Self::Output {
318 S2Point { x: self.x / other, y: self.y / other, z: self.z / other }
319 }
320}
321impl DivAssign<f64> for S2Point {
322 fn div_assign(&mut self, other: f64) {
323 self.x /= other;
324 self.y /= other;
325 self.z /= other;
326 }
327}
328impl Mul<S2Point> for S2Point {
330 type Output = Self;
331 fn mul(self, other: Self) -> Self::Output {
332 S2Point { x: self.x * other.x, y: self.y * other.y, z: self.z * other.z }
333 }
334}
335impl MulAssign<S2Point> for S2Point {
336 fn mul_assign(&mut self, other: S2Point) {
337 self.x *= other.x;
338 self.y *= other.y;
339 self.z *= other.z;
340 }
341}
342impl Mul<f64> for S2Point {
343 type Output = Self;
344 fn mul(self, other: f64) -> Self::Output {
345 S2Point { x: self.x * other, y: self.y * other, z: self.z * other }
346 }
347}
348impl MulAssign<f64> for S2Point {
349 fn mul_assign(&mut self, other: f64) {
350 self.x *= other;
351 self.y *= other;
352 self.z *= other;
353 }
354}
355impl Rem<f64> for S2Point {
356 type Output = Self;
357 fn rem(self, other: f64) -> Self::Output {
358 S2Point { x: self.x % other, y: self.y % other, z: self.z % other }
359 }
360}
361impl RemAssign<f64> for S2Point {
362 fn rem_assign(&mut self, other: f64) {
363 self.x %= other;
364 self.y %= other;
365 self.z %= other;
366 }
367}
368impl Eq for S2Point {}
369impl Ord for S2Point {
370 fn cmp(&self, other: &Self) -> Ordering {
371 match self.x.partial_cmp(&other.x) {
372 Some(Ordering::Equal) => {}
373 other => return other.unwrap(), }
375 match self.y.partial_cmp(&other.y) {
376 Some(Ordering::Equal) => {}
377 other => return other.unwrap(), }
379 match self.z.partial_cmp(&other.z) {
380 Some(order) => order,
381 None => Ordering::Equal, }
383 }
384}
385impl PartialOrd for S2Point {
386 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
387 Some(self.cmp(other))
388 }
389}