GCC Code Coverage Report


Directory: ./
File: lib/geogram/basic/geometry.cpp
Date: 2026-09-07 02:36:43
Exec Total Coverage
Lines: 22 57 38.6%
Functions: 1 6 16.7%
Branches: 7 26 26.9%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40 #include <geogram/basic/geometry.h>
41
42 namespace {
43
44 using namespace GEO;
45 using namespace Geom;
46
47 /**
48 * \brief Computes a vector orthogonal to a segment
49 * and the barycenter of the segment
50 * \param[in] p1 first extremity of the segment
51 * \param[in] p2 second extremity of the segment
52 * \param[out] p barycenter of [ \p p1, \p p2 ].
53 * \param[out] v a vector orthogonal to [ \p p1, \p p2 ].
54 */
55 inline void perp(
56 const vec2& p1, const vec2& p2, vec2& p, vec2& v
57 ) {
58 v = p2 - p1;
59 v = vec2(-v.y, v.x);
60 p = barycenter(p1, p2);
61 }
62
63 /**
64 * \brief Computes a parameter that determines the intersection
65 * between two 2d lines.
66 * \param[in] p1 origin of the first line
67 * \param[in] v1 direction of the first line
68 * \param[in] p2 origin of the second line
69 * \param[in] v2 direction of the second line
70 * \return the parameter t such that p1 + t * v1 is the intersection
71 * between the two 2d lines (p1, v1) and (p2, v2).
72 */
73 inline double segments_intersection_parameter(
74 const vec2& p1, const vec2& v1,
75 const vec2& p2, const vec2& v2
76 ) {
77 double delta = v1.x * v2.y - v1.y * v2.x;
78 double t1 = (v2.y * (p2.x - p1.x) - v2.x * (p2.y - p1.y)) / delta;
79 return t1;
80 }
81
82 /**
83 * \brief Computes the intersection between two 2d lines
84 * specified by origin and vector.
85 * \param[in] p1 origin of the first line
86 * \param[in] v1 direction of the first line
87 * \param[in] p2 origin of the second line
88 * \param[in] v2 direction of the second line
89 * \return the intersection between the two 2d lines (p1, v1) and (p2, v2)
90 */
91 inline vec2 segments_intersection_pv(
92 const vec2& p1, const vec2& v1,
93 const vec2& p2, const vec2& v2
94 ) {
95 double t1 = segments_intersection_parameter(p1, v1, p2, v2);
96 return p1 + t1 * v1;
97 }
98
99 #ifdef REMOVE_ME
100 /**
101 * \brief Computes the intersection between the supporting lines
102 * of 2d segments specified by their extremities.
103 * \param[in] p1 first extremity of the first segment
104 * \param[in] p2 second extremity of the first segment
105 * \param[in] p3 first extremity of the second segment
106 * \param[in] p4 second extremity of the second segment
107 * \return the intersection between the two supporting lines of
108 * segments [ \p p1, \p p2] and [ \p p3, \p p4].
109 * \note The intersection may be outside of the two segments.
110 */
111 inline vec2 segments_intersection_pp(
112 const vec2& p1, const vec2& p2,
113 const vec2& p3, const vec2& p4
114 ) {
115 return segments_intersection_pv(
116 p1, (p2 - p1), p3, (p4 - p3)
117 );
118 }
119
120 /**
121 * \brief Computes the determinant of a 3x3 matrix given
122 * by coefficients.
123 */
124 inline double det3x3(
125 double a00, double a01, double a02,
126 double a10, double a11, double a12,
127 double a20, double a21, double a22
128 ) {
129 double m01 = a00 * a11 - a10 * a01;
130 double m02 = a00 * a21 - a20 * a01;
131 double m12 = a10 * a21 - a20 * a11;
132 return m01 * a22 - m02 * a12 + m12 * a02;
133 }
134 #endif
135
136 }
137
138 /****************************************************************************/
139
140 namespace GEO {
141
142 namespace Geom {
143
144 vec2 triangle_circumcenter(
145 const vec2& q1, const vec2& q2, const vec2& q3
146 ) {
147 vec2 p1, p2;
148 vec2 v1, v2;
149 perp(q1, q2, p1, v1);
150 perp(q1, q3, p2, v2);
151 return segments_intersection_pv(p1, v1, p2, v2);
152 }
153
154 63524 vec3 perpendicular(const vec3& V) {
155 63524 int min_index = 0;
156 63524 double c = ::fabs(V[0]);
157 63524 double cur = ::fabs(V[1]);
158
2/2
✓ Branch 0 taken 46355 times.
✓ Branch 1 taken 17169 times.
63524 if(cur < c) {
159 46355 min_index = 1;
160 46355 c = cur;
161 }
162 63524 cur = ::fabs(V[2]);
163
2/2
✓ Branch 0 taken 7311 times.
✓ Branch 1 taken 56213 times.
63524 if(cur < c) {
164 7311 min_index = 2;
165 }
166 63524 vec3 result;
167
3/4
✓ Branch 0 taken 14220 times.
✓ Branch 1 taken 41993 times.
✓ Branch 2 taken 7311 times.
✗ Branch 3 not taken.
63524 switch(min_index) {
168 14220 case 0:
169 14220 result = vec3(0, -V.z, V.y);
170 14220 break;
171 41993 case 1:
172 41993 result = vec3(V.z, 0, -V.x);
173 41993 break;
174 7311 case 2:
175 7311 result = vec3(-V.y, V.x, 0);
176 7311 break;
177 }
178 63524 return result;
179 }
180
181 vec3 tetra_circum_center(
182 const vec3& p, const vec3& q,
183 const vec3& r, const vec3& s
184 ) {
185 vec3 qp = q - p;
186 double qp2 = length2(qp);
187 vec3 rp = r - p;
188 double rp2 = length2(rp);
189 vec3 sp = s - p;
190 double sp2 = length2(sp);
191
192 double num_x = det3x3(
193 qp.y, qp.z, qp2,
194 rp.y, rp.z, rp2,
195 sp.y, sp.z, sp2
196 );
197
198 double num_y = det3x3(
199 qp.x, qp.z, qp2,
200 rp.x, rp.z, rp2,
201 sp.x, sp.z, sp2
202 );
203
204 double num_z = det3x3(
205 qp.x, qp.y, qp2,
206 rp.x, rp.y, rp2,
207 sp.x, sp.y, sp2
208 );
209
210 double den = det3x3(
211 qp.x, qp.y, qp.z,
212 rp.x, rp.y, rp.z,
213 sp.x, sp.y, sp.z
214 );
215
216 geo_assert(::fabs(den) > 1e-30);
217
218 den *= 2.0;
219
220 return vec3(
221 p.x + num_x / den,
222 p.y - num_y / den,
223 p.z + num_z / den
224 );
225 }
226 }
227 }
228