GCC Code Coverage Report


Directory: ./
File: tests/test_orient_3d_SOS/main.cpp
Date: 2026-09-07 02:37:58
Exec Total Coverage
Lines: 132 177 74.6%
Functions: 10 17 58.8%
Branches: 153 310 49.4%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2026 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/common.h>
41 #include <geogram/basic/logger.h>
42 #include <geogram/basic/command_line.h>
43 #include <geogram/basic/command_line_args.h>
44 #include <geogram/basic/stopwatch.h>
45 #include <geogram/numerics/predicates.h>
46 #include <geogram/mesh/mesh_CSG_builder.h>
47 #include <geogram/mesh/mesh_io.h>
48
49 namespace {
50 using namespace GEO;
51
52 /**
53 * \brief Constructs a mesh that corresponds to a given box
54 * \param[in] B a reference to a CSGBuilder
55 * \param[in] box a box
56 * \return a shared pointer to the constructed mesh
57 */
58 4 std::shared_ptr<GEO::Mesh> make_box(CSGBuilder& B, const Box3d& box) {
59
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 vec3 lo = box.lo();
60
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 vec3 hi = box.hi();
61
2/4
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
8 return B.multmatrix(
62 4 {{1, 0, 0, lo.x},
63 4 {0, 1, 0, lo.y},
64
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 {0, 0, 1, lo.z},
65 {0, 0, 0, 1 }},
66 {
67 4 B.cube(hi-lo, false)
68 }
69
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 );
70
2/8
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
4 }
71
72 /**
73 * \brief Builds the Omega surface, that corresponds to a cube minus a corner
74 * \param[in] shape 1 for cube with one corner nibbled, 2 for cube with all
75 * corners nibbled.
76 */
77 2 std::shared_ptr<GEO::Mesh> build_Omega(int shape) {
78
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 CSGBuilder B;
79
80
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(shape == 1) {
81 return B.difference(
82
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 make_box(B, Box3d(0.0, 0.0, 0.0, 1.0, 1.0, 1.0)),
83
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 make_box(B, Box3d(0.0, 0.0, 0.0, 0.5, 0.5, 0.5))
84
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 );
85 }
86
87 if(shape == 2) {
88 return B.difference(
89 make_box(B, Box3d(0.0, 0.0, 0.0, 1.0, 1.0, 1.0 )),
90 make_box(B, Box3d(0.0, 0.0, 0.0, 0.25, 0.25, 0.25)),
91 make_box(B, Box3d(0.75, 0.0, 0.0, 1.0, 0.25, 0.25)),
92 make_box(B, Box3d(0.0, 0.75, 0.0, 0.25, 1.0, 0.25)),
93 make_box(B, Box3d(0.75, 0.75, 0.0, 1.0, 1.0, 0.25)),
94 make_box(B, Box3d(0.0, 0.0, 0.75, 0.25, 0.25, 1.0 )),
95 make_box(B, Box3d(0.75, 0.0, 0.75, 1.0, 0.25, 1.0 )),
96 make_box(B, Box3d(0.0, 0.75, 0.75, 0.25, 1.0, 1.0 )),
97 make_box(B, Box3d(0.75, 0.75, 0.75, 1.0, 1.0, 1.0 ))
98 );
99 }
100
101 Logger::err("test_orient3d_SOS") << "Invalid shape id: " << shape
102 << std::endl;
103 exit(-1);
104 2 }
105
106 enum Status {INSIDE=0, UNDETERMINED=1, ONBORDER=1, OUTSIDE=2};
107
108 /**
109 * \brief Computes where a point is relative to a 3D box
110 * \param[in] p the point
111 * \param[in] B the 3d box
112 * \retval one of INSIDE, ONBORDER or OUTSIDE
113 */
114 170128 Status where_is(const vec3& p, const Box3d& B) {
115 170128 if(
116
4/4
✓ Branch 0 taken 121520 times.
✓ Branch 1 taken 48608 times.
✓ Branch 2 taken 48608 times.
✓ Branch 3 taken 72912 times.
170128 p.x > B.xyz_min[0] && p.x < B.xyz_max[0] &&
117
4/4
✓ Branch 0 taken 34720 times.
✓ Branch 1 taken 13888 times.
✓ Branch 2 taken 17360 times.
✓ Branch 3 taken 17360 times.
48608 p.y > B.xyz_min[1] && p.y < B.xyz_max[1] &&
118
4/4
✓ Branch 0 taken 12400 times.
✓ Branch 1 taken 4960 times.
✓ Branch 2 taken 6944 times.
✓ Branch 3 taken 5456 times.
17360 p.z > B.xyz_min[2] && p.z < B.xyz_max[2]
119 ) {
120 6944 return INSIDE;
121 }
122
123 163184 if(
124
4/4
✓ Branch 0 taken 138880 times.
✓ Branch 1 taken 24304 times.
✓ Branch 2 taken 90272 times.
✓ Branch 3 taken 48608 times.
163184 p.x < B.xyz_min[0] || p.x > B.xyz_max[0] ||
125
4/4
✓ Branch 0 taken 76384 times.
✓ Branch 1 taken 13888 times.
✓ Branch 2 taken 52080 times.
✓ Branch 3 taken 24304 times.
90272 p.y < B.xyz_min[1] || p.y > B.xyz_max[1] ||
126
4/4
✓ Branch 0 taken 43648 times.
✓ Branch 1 taken 8432 times.
✓ Branch 2 taken 12896 times.
✓ Branch 3 taken 30752 times.
52080 p.z < B.xyz_min[2] || p.z > B.xyz_max[2]
127 ) {
128 132432 return OUTSIDE;
129 }
130
131 30752 return ONBORDER;
132 }
133
134 inline Status status_union(Status s1, Status s2) {
135 if(s1 == INSIDE || s2 == INSIDE) {
136 return INSIDE;
137 }
138 if(s1 == OUTSIDE && s2 == OUTSIDE) {
139 return OUTSIDE;
140 }
141 return ONBORDER;
142 }
143
144 template <typename...Types> inline
145 Status status_union(Status s1, Types... args) {
146 return status_union(s1, status_union(args...));
147 }
148
149 85064 inline Status status_intersection(Status s1, Status s2) {
150
4/4
✓ Branch 0 taken 6696 times.
✓ Branch 1 taken 78368 times.
✓ Branch 2 taken 4712 times.
✓ Branch 3 taken 1984 times.
85064 if(s1 == INSIDE && s2 == INSIDE) {
151 4712 return INSIDE;
152 }
153
4/4
✓ Branch 0 taken 26288 times.
✓ Branch 1 taken 54064 times.
✓ Branch 2 taken 248 times.
✓ Branch 3 taken 26040 times.
80352 if(s1 == OUTSIDE || s2 == OUTSIDE) {
154 54312 return OUTSIDE;
155 }
156 26040 return ONBORDER;
157 }
158
159 85064 inline Status status_invert(Status s) {
160
3/4
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 6448 times.
✓ Branch 2 taken 78368 times.
✗ Branch 3 not taken.
85064 switch(s) {
161 248 case INSIDE: return OUTSIDE;
162 6448 case ONBORDER: return ONBORDER;
163 78368 case OUTSIDE: return INSIDE;
164 }
165 geo_assert_not_reached;
166 }
167
168 85064 inline Status status_difference(Status s1, Status s2) {
169 85064 return status_intersection(s1, status_invert(s2));
170 }
171
172 /**
173 * \brief Tests where a point is realtive to Omega
174 * \details This version uses hardcoded tests (supposed to be correct).
175 * \param[in] p the 3d point to be tested
176 * \param[in] shape 1 for cube with one corner nibbled, 2 for cube with all
177 * corners nibbled.
178 * \retval INSIDE if \p p is inside Omega
179 * \retval ONBORDER if \p p is exactly on the boundary of Omega
180 * \retval OUTSIDE if \p p is outside Omega
181 */
182 85064 Status where_is(const vec3& p, int shape) {
183
1/2
✓ Branch 0 taken 85064 times.
✗ Branch 1 not taken.
85064 if(shape == 1) {
184 85064 Status s1 = where_is(p, Box3d{0.0, 0.0, 0.0, 1.0, 1.0, 1.0});
185 85064 Status s2 = where_is(p, Box3d{0.0, 0.0, 0.0, 0.5, 0.5, 0.5});
186 85064 return status_difference(s1,s2);
187 }
188
189 if(shape == 2) {
190 Status s0=where_is(p, Box3d{0.0, 0.0, 0.0, 1.0, 1.0, 1.0 });
191 Status s1=where_is(p, Box3d{0.0, 0.0, 0.0, 0.25, 0.25, 0.25});
192 Status s2=where_is(p, Box3d{0.75, 0.0, 0.0, 1.0, 0.25, 0.25});
193 Status s3=where_is(p, Box3d{0.0, 0.75, 0.0, 0.25, 1.0, 0.25});
194 Status s4=where_is(p, Box3d{0.75, 0.75, 0.0, 1.0, 1.0, 0.25});
195 Status s5=where_is(p, Box3d{0.0, 0.0, 0.75, 0.25, 0.25, 1.0 });
196 Status s6=where_is(p, Box3d{0.75, 0.0, 0.75, 1.0, 0.25, 1.0 });
197 Status s7=where_is(p, Box3d{0.0, 0.75, 0.75, 0.25, 1.0, 1.0 });
198 Status s8=where_is(p, Box3d{0.75, 0.75, 0.75, 1.0, 1.0, 1.0 });
199 return status_difference(
200 s0, status_union(s1,s2,s3,s4,s5,s6,s7,s8)
201 );
202 }
203
204 geo_assert_not_reached;
205 }
206
207 /**
208 * \brief Tests whether a segment intersects a triangle
209 * \param[in] q1 , q2 the two extremities of the segment
210 * \param[in] p1 , p2 , p3 the three verties of the triangle
211 * \retval true if the segment has an intersection with the
212 * interior of the triangle
213 * \retval false otherwise
214 * \details Degenerate configurations (segment passing through vertex,
215 * edge, or co-planar with triangle) are symbolically perturbed.
216 */
217 2041536 template <class POINT> bool segment_triangle_intersection_SOS(
218 const POINT& q1, const POINT& q2,
219 const POINT& p1, const POINT& p2, const POINT& p3
220 ) {
221 2041536 Sign o1 = PCK::orient_3d_SOS(q1,p1,p2,p3);
222 2041536 Sign o2 = PCK::orient_3d_SOS(q2,p1,p2,p3);
223
224 // There is no intersection if q1 and q2 are on the
225 // same side of the supporting plane of (p1,p2,p3)
226
2/2
✓ Branch 0 taken 1202910 times.
✓ Branch 1 taken 838626 times.
2041536 if(o1 == o2) {
227 1202910 return false;
228 }
229
230 // There is an intersection if the three tetrahedra
231 // formed by [q1,q2] and the three edges of the triangle
232 // have the same orientation
233 838626 Sign s1 = PCK::orient_3d_SOS(q1,q2,p1,p2);
234 838626 Sign s2 = PCK::orient_3d_SOS(q1,q2,p2,p3);
235
2/2
✓ Branch 0 taken 557196 times.
✓ Branch 1 taken 281430 times.
838626 if(s1*s2 < 0) {
236 557196 return false;
237 }
238 281430 Sign s3 = PCK::orient_3d_SOS(q1,q2,p3,p1);
239
3/4
✓ Branch 0 taken 47312 times.
✓ Branch 1 taken 234118 times.
✓ Branch 2 taken 47312 times.
✗ Branch 3 not taken.
281430 return(s2*s3 > 0 && s3*s1 > 0);
240 }
241
242 /**
243 * \brief Tests where a point is realtive to Omega
244 * \details This version uses orient_3d_SOS. One can use the other version
245 * of where_is() to test whether this one is correct.
246 * \param[in] q1 the 3d point to be tested
247 * \param[in] q2 the second extremity of a segment starting from \p q1 and
248 * going far far away
249 * \retval INSIDE if \p p is inside Omega
250 * \retval OUTSIDE if \p p is outside Omega
251 * \retval one of INSIDE or OUTSIDE if \p p is on the border of Omega
252 */
253 85064 Status where_is(const vec3& q1, const vec3& q2, const Mesh& Omega) {
254 85064 bool inside = false;
255
2/2
✓ Branch 5 taken 2041536 times.
✓ Branch 6 taken 85064 times.
2126600 for(index_t f: Omega.facets) {
256
1/2
✓ Branch 1 taken 2041536 times.
✗ Branch 2 not taken.
2041536 vec3 p1 = Omega.facets.point(f,0);
257
1/2
✓ Branch 1 taken 2041536 times.
✗ Branch 2 not taken.
2041536 vec3 p2 = Omega.facets.point(f,1);
258
1/2
✓ Branch 1 taken 2041536 times.
✗ Branch 2 not taken.
2041536 vec3 p3 = Omega.facets.point(f,2);
259
3/4
✓ Branch 1 taken 2041536 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 47312 times.
✓ Branch 4 taken 1994224 times.
2041536 if(segment_triangle_intersection_SOS(q1,q2,p1,p2,p3)) {
260 47312 inside = !inside;
261 }
262 }
263
2/2
✓ Branch 0 taken 12456 times.
✓ Branch 1 taken 72608 times.
85064 return inside ? INSIDE: OUTSIDE;
264 }
265 }
266
267 2 int main(int argc, char** argv) {
268
269 using namespace GEO;
270
271 2 GEO::initialize(GEO::GEOGRAM_INSTALL_ALL);
272 2 int result = 0;
273
274 try {
275
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 Stopwatch W("Total time");
276
277 2 std::vector<std::string> filenames;
278
279
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 CmdLine::import_arg_group("standard");
280
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 CmdLine::import_arg_group("algo");
281
282
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 CmdLine::declare_arg(
283
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 "shape", 1,
284
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
6 "1 for cube with one corner nibbled, 2 for all corners nibbled"
285 );
286
287
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 CmdLine::declare_arg(
288
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
10 "visual_debug", false, "save domain and points in file"
289 );
290
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 CmdLine::declare_arg(
291
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
10 "h", 0.25, "space between points (must be in the form of 1/2^n)"
292 );
293
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 CmdLine::declare_arg(
294
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
10 "dh", 1.0, "increment for directions (must be in the form of 1/2^n)"
295 );
296
297
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 CmdLine::declare_arg(
298
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
10 "lo", -0.25, "low bound for coordinates to be tested"
299 );
300
301
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 CmdLine::declare_arg(
302
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
10 "hi", 1.25, "high bound for coordinates to be tested"
303 );
304
305
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
4 if(!CmdLine::parse(argc, argv, filenames)) {
306 return 1;
307 }
308
309
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 int shape = CmdLine::get_arg_int("shape");
310
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 double h = CmdLine::get_arg_double("h");
311
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 double dh = CmdLine::get_arg_double("dh");
312
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 double lo = CmdLine::get_arg_double("lo");
313
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 double hi = CmdLine::get_arg_double("hi");
314
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 bool visual_debug = CmdLine::get_arg_bool("visual_debug");
315
316
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 std::shared_ptr<Mesh> Omega = build_Omega(shape);
317
318
319 // Some points are temporaries that are generated, so we
320 // need to activate lexicographic mode.
321 // (TODO: store them in "points mesh", and test both modes!)
322
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 PCK::set_SOS_mode(PCK::SOS_LEXICO);
323
324
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 Mesh P;
325 Attribute<index_t> attr_status(
326
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
6 P.vertices.attributes(), "status"
327
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 );
328 Attribute<index_t> attr_status_check(
329
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
6 P.vertices.attributes(), "status_check"
330
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 );
331
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 Attribute<bool> attr_sel(P.vertices.attributes(), "selection");
332
333
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for(double x=lo; x<=hi; x+=h) {
334
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 14 times.
112 for(double y=lo; y<=hi; y+=h) {
335
2/2
✓ Branch 0 taken 686 times.
✓ Branch 1 taken 98 times.
784 for(double z=lo; z<=hi; z+=h) {
336
1/2
✓ Branch 2 taken 686 times.
✗ Branch 3 not taken.
686 P.vertices.create_vertex(vec3(x,y,z));
337 }
338 }
339 }
340
341
342 2 index_t nb_OK = 0;
343 2 index_t nb_KO = 0;
344
345
2/2
✓ Branch 5 taken 686 times.
✓ Branch 6 taken 2 times.
688 for(index_t v: P.vertices) {
346
1/2
✓ Branch 1 taken 686 times.
✗ Branch 2 not taken.
686 vec3 q1 = P.vertices.point(v);
347
2/2
✓ Branch 0 taken 3430 times.
✓ Branch 1 taken 686 times.
4116 for(double dx=-1.0; dx<=1.0; dx+=dh) {
348
2/2
✓ Branch 0 taken 17150 times.
✓ Branch 1 taken 3430 times.
20580 for(double dy=-1.0; dy<=1.0; dy+=dh) {
349
2/2
✓ Branch 0 taken 85750 times.
✓ Branch 1 taken 17150 times.
102900 for(double dz=-1.0; dz<=1.0; dz+=dh) {
350
6/6
✓ Branch 0 taken 17150 times.
✓ Branch 1 taken 68600 times.
✓ Branch 2 taken 3430 times.
✓ Branch 3 taken 13720 times.
✓ Branch 4 taken 686 times.
✓ Branch 5 taken 2744 times.
85750 if(dx==0.0 && dy==0.0 && dz==0.0) {
351 686 continue;
352 }
353 85064 double S = 1024.0;
354 85064 vec3 q2(q1.x+S*dx,q1.y+S*dy,q1.z+S*dz);
355
356
1/2
✓ Branch 2 taken 85064 times.
✗ Branch 3 not taken.
85064 Status status = where_is(q1,q2,*Omega);
357
1/2
✓ Branch 1 taken 85064 times.
✗ Branch 2 not taken.
85064 Status check_status = where_is(q1,shape);
358
359
1/2
✓ Branch 1 taken 85064 times.
✗ Branch 2 not taken.
85064 attr_status[v] = status;
360
1/2
✓ Branch 1 taken 85064 times.
✗ Branch 2 not taken.
85064 attr_status_check[v] = check_status;
361
362
2/2
✓ Branch 0 taken 59024 times.
✓ Branch 1 taken 26040 times.
85064 if(
363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59024 times.
59024 check_status != UNDETERMINED &&
364 status != check_status
365 ) {
366 attr_sel[v] = true;
367 ++nb_KO;
368 } else {
369 85064 ++nb_OK;
370 }
371 }
372 }
373 }
374 }
375
376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(visual_debug) {
377 mesh_save(*Omega, "Omega.geogram");
378 mesh_save(P, "P.geogram");
379 }
380
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 Logger::out("test_orient_3d_SOS")
381
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 << " nb_OK:" << nb_OK
382
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 << " nb_KO:" << nb_KO
383
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 << std::endl;
384 2 result = int(nb_KO != 0);
385
2/4
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
2 }
386 catch(const std::exception& e) {
387 std::cerr << "Received an exception: " << e.what() << std::endl;
388 return 1;
389 }
390
391 2 return result;
392 }
393