Coverage Report

Created: 2026-11-12 07:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PROJ/src/sphere.h
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  PROJ
4
 * Purpose:  Spherical geometry helpers on 3D unit vectors —
5
 *           slerp, spherical triangle area, scalar triple/quadruple
6
 *           products for great-circle math.
7
 * Author:   Felix Palmer
8
 *
9
 ******************************************************************************
10
 * Derived from A5 (Apache-2.0).
11
 * https://github.com/felixpalmer/a5
12
 *
13
 * modules/utils/vector.ts
14
 *
15
 * Copyright (c) A5 contributors
16
 *
17
 * Licensed under the Apache License, Version 2.0 (the "License");
18
 * you may not use this file except in compliance with the License.
19
 * You may obtain a copy of the License at
20
 *
21
 *     http://www.apache.org/licenses/LICENSE-2.0
22
 *
23
 * Unless required by applicable law or agreed to in writing, software
24
 * distributed under the License is distributed on an "AS IS" BASIS,
25
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26
 * See the License for the specific language governing permissions and
27
 * limitations under the License.
28
 ****************************************************************************/
29
30
#ifndef SPHERE_H
31
#define SPHERE_H
32
33
#include "vec3.h"
34
35
#include <cmath>
36
37
// All routines in this header operate on *unit* vectors (points on the unit
38
// sphere); the identities they rely on assume |v| == 1 and results are
39
// undefined for non-normalized input.
40
41
// Numerically stable angular distance measure.
42
// Returns a value proportional to sin(angle/2) between a and b.
43
10.7k
inline double vector_difference(const Vec3 &a, const Vec3 &b) {
44
10.7k
    double D = vec3_length(vec3_subtract(a, b));
45
10.7k
    double S = vec3_length(vec3_add(a, b));
46
10.7k
    return D / std::hypot(D, S);
47
10.7k
}
48
49
263k
inline double triple_product(const Vec3 &a, const Vec3 &b, const Vec3 &c) {
50
263k
    return vec3_dot(a, vec3_cross(b, c));
51
263k
}
52
53
// Great-circle intersection helper.
54
// Returns dot(b,cross(c,d))*a - dot(a,cross(c,d))*b
55
inline Vec3 quadruple_product(const Vec3 &a, const Vec3 &b, const Vec3 &c,
56
5.35k
                              const Vec3 &d) {
57
5.35k
    Vec3 cross_cd = vec3_cross(c, d);
58
5.35k
    double tp_acd = vec3_dot(a, cross_cd);
59
5.35k
    double tp_bcd = vec3_dot(b, cross_cd);
60
5.35k
    return vec3_subtract(vec3_scale(b, tp_acd), vec3_scale(a, tp_bcd));
61
5.35k
}
62
63
0
inline Vec3 slerp(const Vec3 &a, const Vec3 &b, double t) {
64
0
    double gamma = vec3_angle(a, b);
65
0
    if (gamma == 0.0) {
66
0
        return vec3_lerp(a, b, t);
67
0
    }
68
0
    double sin_gamma = std::sin(gamma);
69
0
    double wa = std::sin((1.0 - t) * gamma) / sin_gamma;
70
0
    double wb = std::sin(t * gamma) / sin_gamma;
71
0
    return vec3_add(vec3_scale(a, wa), vec3_scale(b, wb));
72
0
}
73
74
// Signed spherical excess (area) of triangle (v1, v2, v3) of unit vectors,
75
// See: https://brsr.github.io/2021/05/01/vector-spherical-geometry.html
76
inline double spherical_triangle_area(const Vec3 &v1, const Vec3 &v2,
77
16.0k
                                      const Vec3 &v3) {
78
16.0k
    double num = triple_product(v1, v2, v3);
79
16.0k
    double den = 1.0 + vec3_dot(v1, v2) + vec3_dot(v2, v3) + vec3_dot(v3, v1);
80
16.0k
    return 2.0 * std::atan2(num, den);
81
16.0k
}
82
83
#endif // SPHERE_H