GCC Code Coverage Report


Directory: ./
File: lib/geogram/mesh/mesh.h
Date: 2026-09-07 02:28:19
Exec Total Coverage
Lines: 252 419 60.1%
Functions: 33 51 64.7%
Branches: 783 2346 33.4%

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 #ifndef GEOGRAM_MESH_MESH
41 #define GEOGRAM_MESH_MESH
42
43 #include <geogram/basic/common.h>
44 #include <geogram/basic/range.h>
45 #include <geogram/basic/attributes.h>
46 #include <geogram/basic/vector_attribute.h>
47 #include <geogram/basic/geometry.h>
48 #include <tuple>
49
50 // GOMGEN (Graphite's pre-processor) does not understand
51 // modern C++ (but it is not a big drama since it is just
52 // used to generate the GUI).
53 #ifdef GOMGEN
54 #define MESH_NO_SYNTAXIC_SUGAR
55 #endif
56
57 /**
58 * \file geogram/mesh/mesh.h
59 * \brief The class that represents a mesh.
60 */
61
62 namespace GEO {
63
64 class Mesh;
65
66 static constexpr index_t NO_VERTEX = NO_INDEX;
67 static constexpr index_t NO_EDGE = NO_INDEX;
68 static constexpr index_t NO_FACET = NO_INDEX;
69 static constexpr index_t NO_CELL = NO_INDEX;
70 static constexpr index_t NO_CORNER = NO_INDEX;
71
72 /**
73 * \brief Base class for mesh sub-element storage.
74 * \details Sub-elements are those that cannot exist
75 * independently (such as MeshFacetCorner, MeshCellCorner
76 * and MeshCellFacet).
77 * \relates Mesh
78 */
79 class GEOGRAM_API MeshSubElementsStore {
80 public:
81
82 /**
83 * \brief Constructs a new MeshSubElementStore.
84 * \param[in] mesh a reference to the mesh
85 * this MeshElementStore belongs to.
86 */
87 MeshSubElementsStore(Mesh& mesh);
88
89 /**
90 * \brief MeshElementStore destructor.
91 */
92 virtual ~MeshSubElementsStore();
93
94 /**
95 * \brief Gets the number of (sub-)elements.
96 * \return the number of (sub-)elements in this store
97 */
98 index_t nb() const {
99
134/205
✓ Branch 0 taken 12797 times.
✓ Branch 1 taken 199 times.
✓ Branch 2 taken 182 times.
✓ Branch 3 taken 76729 times.
✓ Branch 4 taken 77876 times.
✓ Branch 5 taken 226048 times.
✓ Branch 6 taken 3414843 times.
✓ Branch 7 taken 96014 times.
✓ Branch 8 taken 36 times.
✓ Branch 9 taken 192 times.
✓ Branch 10 taken 121172 times.
✓ Branch 11 taken 4012 times.
✓ Branch 12 taken 121247 times.
✓ Branch 13 taken 23771 times.
✓ Branch 14 taken 941727 times.
✓ Branch 15 taken 40 times.
✓ Branch 16 taken 92 times.
✓ Branch 17 taken 12155 times.
✓ Branch 18 taken 20 times.
✓ Branch 19 taken 14 times.
✓ Branch 20 taken 124849 times.
✓ Branch 21 taken 177 times.
✓ Branch 22 taken 36 times.
✓ Branch 23 taken 129 times.
✓ Branch 24 taken 33 times.
✓ Branch 25 taken 25 times.
✓ Branch 26 taken 109 times.
✓ Branch 27 taken 59 times.
✓ Branch 28 taken 60508 times.
✓ Branch 29 taken 237 times.
✓ Branch 30 taken 74 times.
✓ Branch 31 taken 19 times.
✓ Branch 32 taken 9 times.
✓ Branch 33 taken 61 times.
✓ Branch 34 taken 17 times.
✓ Branch 35 taken 299 times.
✓ Branch 36 taken 244 times.
✓ Branch 37 taken 380232 times.
✓ Branch 38 taken 91253 times.
✓ Branch 39 taken 40 times.
✓ Branch 40 taken 1 times.
✓ Branch 41 taken 61 times.
✓ Branch 42 taken 40 times.
✓ Branch 43 taken 199 times.
✓ Branch 44 taken 22635 times.
✓ Branch 45 taken 42 times.
✓ Branch 46 taken 22606 times.
✓ Branch 47 taken 67 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 46 times.
✓ Branch 50 taken 265 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 252 times.
✓ Branch 53 taken 1 times.
✓ Branch 54 taken 848687 times.
✓ Branch 55 taken 252 times.
✓ Branch 56 taken 819056 times.
✓ Branch 57 taken 250 times.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✓ Branch 61 taken 1 times.
✓ Branch 62 taken 1 times.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✓ Branch 65 taken 4 times.
✓ Branch 66 taken 4 times.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✓ Branch 70 taken 4167 times.
✓ Branch 71 taken 144 times.
✓ Branch 72 taken 13151 times.
✓ Branch 73 taken 19 times.
✓ Branch 74 taken 13151 times.
✓ Branch 75 taken 19 times.
✓ Branch 76 taken 722 times.
✗ Branch 77 not taken.
✓ Branch 78 taken 1 times.
✓ Branch 79 taken 1 times.
✓ Branch 80 taken 4 times.
✗ Branch 81 not taken.
✓ Branch 82 taken 4352 times.
✓ Branch 83 taken 4 times.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✓ Branch 90 taken 116 times.
✗ Branch 91 not taken.
✓ Branch 92 taken 931714 times.
✓ Branch 93 taken 211 times.
✓ Branch 94 taken 2820866 times.
✓ Branch 95 taken 213 times.
✓ Branch 96 taken 1 times.
✓ Branch 97 taken 64 times.
✓ Branch 98 taken 4 times.
✓ Branch 99 taken 16 times.
✗ Branch 100 not taken.
✓ Branch 101 taken 1 times.
✓ Branch 102 taken 4241 times.
✓ Branch 103 taken 433 times.
✓ Branch 104 taken 761854 times.
✓ Branch 105 taken 433 times.
✓ Branch 106 taken 12 times.
✓ Branch 107 taken 434 times.
✓ Branch 108 taken 20 times.
✓ Branch 109 taken 11 times.
✓ Branch 110 taken 25698 times.
✓ Branch 111 taken 11 times.
✓ Branch 112 taken 6145 times.
✓ Branch 113 taken 394942 times.
✓ Branch 114 taken 528 times.
✓ Branch 115 taken 170 times.
✓ Branch 116 taken 838104 times.
✓ Branch 117 taken 171 times.
✗ Branch 118 not taken.
✓ Branch 119 taken 190 times.
✓ Branch 120 taken 1 times.
✓ Branch 121 taken 12 times.
✓ Branch 122 taken 1 times.
✓ Branch 123 taken 20 times.
✓ Branch 124 taken 1 times.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✓ Branch 130 taken 175 times.
✓ Branch 131 taken 1 times.
✓ Branch 132 taken 2 times.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✓ Branch 135 taken 44 times.
✗ Branch 136 not taken.
✓ Branch 137 taken 1 times.
✓ Branch 138 taken 1 times.
✓ Branch 139 taken 421060 times.
✗ Branch 140 not taken.
✓ Branch 141 taken 145160 times.
✓ Branch 142 taken 56 times.
✓ Branch 143 taken 284906 times.
✓ Branch 144 taken 55 times.
✓ Branch 145 taken 284905 times.
✓ Branch 146 taken 51 times.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✓ Branch 150 taken 164 times.
✓ Branch 151 taken 55 times.
✓ Branch 152 taken 12093 times.
✓ Branch 153 taken 55 times.
✓ Branch 154 taken 12094 times.
✓ Branch 155 taken 6 times.
✓ Branch 156 taken 4 times.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 160 not taken.
✗ Branch 161 not taken.
✓ Branch 162 taken 304048 times.
✓ Branch 163 taken 59 times.
✗ Branch 164 not taken.
✓ Branch 165 taken 1 times.
✓ Branch 166 taken 1 times.
✓ Branch 167 taken 1 times.
✓ Branch 168 taken 1 times.
✗ Branch 169 not taken.
✓ Branch 170 taken 1708 times.
✗ Branch 171 not taken.
✓ Branch 172 taken 640344 times.
✓ Branch 173 taken 1 times.
✗ Branch 174 not taken.
✗ Branch 175 not taken.
✗ Branch 176 not taken.
✗ Branch 177 not taken.
✓ Branch 178 taken 1 times.
✗ Branch 179 not taken.
✗ Branch 180 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 183 not taken.
✗ Branch 184 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 188 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 192 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 195 not taken.
✗ Branch 196 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 203 not taken.
✗ Branch 204 not taken.
17943694 return nb_;
100 }
101
102 /**
103 * \brief Gets the attributes manager.
104 * \details The returned reference is not a const one,
105 * so that attributes can be bound / unbound / accessed
106 * even if the mesh is const.
107 * \return a modifiable reference to the attributes manager.
108 */
109 AttributesManager& attributes() const {
110
55/689
✗ Branch 0 not taken.
✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21114 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 469 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 416 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 331 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 17 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 53 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 66 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 30 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 30 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 30 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 30 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 5 times.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 58 times.
✓ Branch 47 taken 35 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 58 times.
✓ Branch 50 taken 32 times.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✓ Branch 53 taken 34 times.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✓ Branch 56 taken 34 times.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✓ Branch 61 taken 58 times.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✓ Branch 64 taken 647 times.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✓ Branch 74 taken 1 times.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✓ Branch 83 taken 226 times.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✓ Branch 86 taken 226 times.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✓ Branch 89 taken 115 times.
✗ Branch 90 not taken.
✓ Branch 91 taken 61 times.
✗ Branch 92 not taken.
✓ Branch 94 taken 65 times.
✗ Branch 95 not taken.
✓ Branch 97 taken 226 times.
✗ Branch 98 not taken.
✓ Branch 100 taken 177 times.
✗ Branch 101 not taken.
✗ Branch 103 not taken.
✓ Branch 104 taken 58 times.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✓ Branch 107 taken 823 times.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✓ Branch 142 taken 1 times.
✗ Branch 143 not taken.
✓ Branch 145 taken 36 times.
✗ Branch 146 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 160 not taken.
✗ Branch 161 not taken.
✗ Branch 163 not taken.
✗ Branch 164 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✓ Branch 172 taken 2 times.
✗ Branch 173 not taken.
✗ Branch 175 not taken.
✗ Branch 176 not taken.
✗ Branch 178 not taken.
✗ Branch 179 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 184 not taken.
✗ Branch 185 not taken.
✗ Branch 187 not taken.
✗ Branch 188 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 196 not taken.
✗ Branch 197 not taken.
✓ Branch 199 taken 136 times.
✗ Branch 200 not taken.
✗ Branch 202 not taken.
✗ Branch 203 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 208 not taken.
✗ Branch 209 not taken.
✗ Branch 211 not taken.
✗ Branch 212 not taken.
✗ Branch 214 not taken.
✗ Branch 215 not taken.
✓ Branch 217 taken 264 times.
✗ Branch 218 not taken.
✗ Branch 220 not taken.
✗ Branch 221 not taken.
✗ Branch 223 not taken.
✗ Branch 224 not taken.
✗ Branch 226 not taken.
✗ Branch 227 not taken.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 232 not taken.
✗ Branch 233 not taken.
✓ Branch 235 taken 20 times.
✗ Branch 236 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✗ Branch 241 not taken.
✗ Branch 242 not taken.
✗ Branch 244 not taken.
✗ Branch 245 not taken.
✗ Branch 247 not taken.
✗ Branch 248 not taken.
✗ Branch 250 not taken.
✗ Branch 251 not taken.
✓ Branch 253 taken 40 times.
✗ Branch 254 not taken.
✗ Branch 256 not taken.
✗ Branch 257 not taken.
✗ Branch 259 not taken.
✗ Branch 260 not taken.
✗ Branch 262 not taken.
✗ Branch 263 not taken.
✗ Branch 265 not taken.
✗ Branch 266 not taken.
✗ Branch 268 not taken.
✗ Branch 269 not taken.
✗ Branch 271 not taken.
✗ Branch 272 not taken.
✓ Branch 274 taken 1 times.
✗ Branch 275 not taken.
✗ Branch 277 not taken.
✗ Branch 278 not taken.
✗ Branch 280 not taken.
✗ Branch 281 not taken.
✗ Branch 283 not taken.
✗ Branch 284 not taken.
✗ Branch 286 not taken.
✗ Branch 287 not taken.
✗ Branch 289 not taken.
✗ Branch 290 not taken.
✗ Branch 292 not taken.
✗ Branch 293 not taken.
✗ Branch 295 not taken.
✗ Branch 296 not taken.
✗ Branch 298 not taken.
✗ Branch 299 not taken.
✗ Branch 301 not taken.
✗ Branch 302 not taken.
✗ Branch 304 not taken.
✗ Branch 305 not taken.
✗ Branch 307 not taken.
✗ Branch 308 not taken.
✗ Branch 310 not taken.
✗ Branch 311 not taken.
✗ Branch 313 not taken.
✗ Branch 314 not taken.
✗ Branch 316 not taken.
✗ Branch 317 not taken.
✗ Branch 319 not taken.
✗ Branch 320 not taken.
✗ Branch 322 not taken.
✗ Branch 323 not taken.
✗ Branch 325 not taken.
✗ Branch 326 not taken.
✗ Branch 328 not taken.
✗ Branch 329 not taken.
✓ Branch 331 taken 148 times.
✗ Branch 332 not taken.
✗ Branch 334 not taken.
✗ Branch 335 not taken.
✗ Branch 337 not taken.
✗ Branch 338 not taken.
✗ Branch 340 not taken.
✗ Branch 341 not taken.
✗ Branch 343 not taken.
✗ Branch 344 not taken.
✗ Branch 346 not taken.
✗ Branch 347 not taken.
✗ Branch 349 not taken.
✗ Branch 350 not taken.
✗ Branch 352 not taken.
✗ Branch 353 not taken.
✗ Branch 355 not taken.
✗ Branch 356 not taken.
✗ Branch 358 not taken.
✗ Branch 359 not taken.
✗ Branch 361 not taken.
✗ Branch 362 not taken.
✗ Branch 364 not taken.
✗ Branch 365 not taken.
✓ Branch 367 taken 20 times.
✗ Branch 368 not taken.
✗ Branch 370 not taken.
✗ Branch 371 not taken.
✗ Branch 373 not taken.
✗ Branch 374 not taken.
✗ Branch 376 not taken.
✗ Branch 377 not taken.
✗ Branch 379 not taken.
✗ Branch 380 not taken.
✗ Branch 382 not taken.
✗ Branch 383 not taken.
✗ Branch 385 not taken.
✗ Branch 386 not taken.
✗ Branch 388 not taken.
✗ Branch 389 not taken.
✗ Branch 391 not taken.
✗ Branch 392 not taken.
✗ Branch 394 not taken.
✗ Branch 395 not taken.
✗ Branch 397 not taken.
✗ Branch 398 not taken.
✗ Branch 400 not taken.
✗ Branch 401 not taken.
✗ Branch 403 not taken.
✗ Branch 404 not taken.
✓ Branch 406 taken 1 times.
✗ Branch 407 not taken.
✗ Branch 409 not taken.
✗ Branch 410 not taken.
✗ Branch 412 not taken.
✗ Branch 413 not taken.
✗ Branch 415 not taken.
✗ Branch 416 not taken.
✗ Branch 418 not taken.
✗ Branch 419 not taken.
✗ Branch 421 not taken.
✗ Branch 422 not taken.
✗ Branch 424 not taken.
✗ Branch 425 not taken.
✗ Branch 427 not taken.
✗ Branch 428 not taken.
✗ Branch 430 not taken.
✗ Branch 431 not taken.
✗ Branch 433 not taken.
✗ Branch 434 not taken.
✓ Branch 436 taken 4 times.
✗ Branch 437 not taken.
✗ Branch 439 not taken.
✗ Branch 440 not taken.
✗ Branch 442 not taken.
✗ Branch 443 not taken.
✗ Branch 445 not taken.
✗ Branch 446 not taken.
✗ Branch 448 not taken.
✗ Branch 449 not taken.
✗ Branch 451 not taken.
✗ Branch 452 not taken.
✗ Branch 454 not taken.
✗ Branch 455 not taken.
✗ Branch 457 not taken.
✗ Branch 458 not taken.
✗ Branch 460 not taken.
✗ Branch 461 not taken.
✓ Branch 463 taken 132 times.
✗ Branch 464 not taken.
✗ Branch 466 not taken.
✗ Branch 467 not taken.
✗ Branch 469 not taken.
✗ Branch 470 not taken.
✗ Branch 472 not taken.
✗ Branch 473 not taken.
✗ Branch 475 not taken.
✗ Branch 476 not taken.
✗ Branch 478 not taken.
✗ Branch 479 not taken.
✓ Branch 481 taken 528 times.
✗ Branch 482 not taken.
✗ Branch 484 not taken.
✗ Branch 485 not taken.
✗ Branch 487 not taken.
✗ Branch 488 not taken.
✗ Branch 490 not taken.
✗ Branch 491 not taken.
✗ Branch 493 not taken.
✗ Branch 494 not taken.
✗ Branch 496 not taken.
✗ Branch 497 not taken.
✓ Branch 499 taken 20 times.
✗ Branch 500 not taken.
✗ Branch 502 not taken.
✗ Branch 503 not taken.
✗ Branch 505 not taken.
✗ Branch 506 not taken.
✗ Branch 508 not taken.
✗ Branch 509 not taken.
✗ Branch 511 not taken.
✗ Branch 512 not taken.
✗ Branch 514 not taken.
✗ Branch 515 not taken.
✓ Branch 517 taken 80 times.
✗ Branch 518 not taken.
✗ Branch 520 not taken.
✗ Branch 521 not taken.
✗ Branch 523 not taken.
✗ Branch 524 not taken.
✗ Branch 526 not taken.
✗ Branch 527 not taken.
✗ Branch 529 not taken.
✗ Branch 530 not taken.
✗ Branch 532 not taken.
✗ Branch 533 not taken.
✗ Branch 535 not taken.
✗ Branch 536 not taken.
✓ Branch 538 taken 1 times.
✗ Branch 539 not taken.
✗ Branch 541 not taken.
✗ Branch 542 not taken.
✗ Branch 544 not taken.
✗ Branch 545 not taken.
✗ Branch 547 not taken.
✗ Branch 548 not taken.
✗ Branch 550 not taken.
✗ Branch 551 not taken.
✗ Branch 553 not taken.
✗ Branch 554 not taken.
✗ Branch 556 not taken.
✗ Branch 557 not taken.
✗ Branch 559 not taken.
✗ Branch 560 not taken.
✗ Branch 562 not taken.
✗ Branch 563 not taken.
✗ Branch 565 not taken.
✗ Branch 566 not taken.
✗ Branch 568 not taken.
✗ Branch 569 not taken.
✗ Branch 571 not taken.
✗ Branch 572 not taken.
✗ Branch 574 not taken.
✗ Branch 575 not taken.
✗ Branch 577 not taken.
✗ Branch 578 not taken.
✗ Branch 580 not taken.
✗ Branch 581 not taken.
✗ Branch 583 not taken.
✗ Branch 584 not taken.
✗ Branch 586 not taken.
✗ Branch 587 not taken.
✗ Branch 589 not taken.
✗ Branch 590 not taken.
✗ Branch 592 not taken.
✗ Branch 593 not taken.
✓ Branch 595 taken 132 times.
✗ Branch 596 not taken.
✗ Branch 598 not taken.
✗ Branch 599 not taken.
✗ Branch 601 not taken.
✗ Branch 602 not taken.
✗ Branch 604 not taken.
✗ Branch 605 not taken.
✗ Branch 607 not taken.
✗ Branch 608 not taken.
✗ Branch 610 not taken.
✗ Branch 611 not taken.
✗ Branch 613 not taken.
✗ Branch 614 not taken.
✗ Branch 616 not taken.
✗ Branch 617 not taken.
✗ Branch 619 not taken.
✗ Branch 620 not taken.
✗ Branch 622 not taken.
✗ Branch 623 not taken.
✗ Branch 625 not taken.
✗ Branch 626 not taken.
✗ Branch 628 not taken.
✗ Branch 629 not taken.
✓ Branch 631 taken 20 times.
✗ Branch 632 not taken.
✗ Branch 634 not taken.
✗ Branch 635 not taken.
✗ Branch 637 not taken.
✗ Branch 638 not taken.
✗ Branch 640 not taken.
✗ Branch 641 not taken.
✗ Branch 643 not taken.
✗ Branch 644 not taken.
✗ Branch 646 not taken.
✗ Branch 647 not taken.
✗ Branch 649 not taken.
✗ Branch 650 not taken.
✗ Branch 652 not taken.
✗ Branch 653 not taken.
✗ Branch 655 not taken.
✗ Branch 656 not taken.
✗ Branch 658 not taken.
✗ Branch 659 not taken.
✗ Branch 661 not taken.
✗ Branch 662 not taken.
✗ Branch 664 not taken.
✗ Branch 665 not taken.
✗ Branch 667 not taken.
✗ Branch 668 not taken.
✗ Branch 670 not taken.
✗ Branch 671 not taken.
✗ Branch 673 not taken.
✗ Branch 674 not taken.
✗ Branch 676 not taken.
✗ Branch 677 not taken.
✗ Branch 679 not taken.
✗ Branch 680 not taken.
✗ Branch 682 not taken.
✗ Branch 683 not taken.
✗ Branch 685 not taken.
✗ Branch 686 not taken.
✗ Branch 688 not taken.
✗ Branch 689 not taken.
✗ Branch 691 not taken.
✗ Branch 692 not taken.
✗ Branch 694 not taken.
✗ Branch 695 not taken.
✗ Branch 697 not taken.
✗ Branch 698 not taken.
✗ Branch 700 not taken.
✗ Branch 701 not taken.
✗ Branch 703 not taken.
✗ Branch 704 not taken.
✗ Branch 706 not taken.
✗ Branch 707 not taken.
✗ Branch 709 not taken.
✗ Branch 710 not taken.
✗ Branch 712 not taken.
✗ Branch 713 not taken.
✗ Branch 715 not taken.
✗ Branch 716 not taken.
✗ Branch 718 not taken.
✗ Branch 719 not taken.
✗ Branch 721 not taken.
✗ Branch 722 not taken.
✗ Branch 724 not taken.
✗ Branch 725 not taken.
✗ Branch 727 not taken.
✗ Branch 728 not taken.
✗ Branch 730 not taken.
✗ Branch 731 not taken.
✗ Branch 733 not taken.
✗ Branch 734 not taken.
✗ Branch 736 not taken.
✗ Branch 737 not taken.
✗ Branch 739 not taken.
✗ Branch 740 not taken.
✗ Branch 742 not taken.
✗ Branch 743 not taken.
✗ Branch 745 not taken.
✗ Branch 746 not taken.
✗ Branch 748 not taken.
✗ Branch 749 not taken.
✗ Branch 751 not taken.
✗ Branch 752 not taken.
✗ Branch 754 not taken.
✗ Branch 755 not taken.
✗ Branch 757 not taken.
✗ Branch 758 not taken.
✗ Branch 760 not taken.
✗ Branch 761 not taken.
✗ Branch 763 not taken.
✗ Branch 764 not taken.
✗ Branch 766 not taken.
✗ Branch 767 not taken.
✗ Branch 769 not taken.
✗ Branch 770 not taken.
✗ Branch 772 not taken.
✗ Branch 773 not taken.
✗ Branch 775 not taken.
✗ Branch 776 not taken.
✗ Branch 778 not taken.
✗ Branch 779 not taken.
✗ Branch 781 not taken.
✗ Branch 782 not taken.
✗ Branch 784 not taken.
✗ Branch 785 not taken.
✗ Branch 787 not taken.
✗ Branch 788 not taken.
✗ Branch 790 not taken.
✗ Branch 791 not taken.
✗ Branch 793 not taken.
✗ Branch 794 not taken.
✗ Branch 796 not taken.
✗ Branch 797 not taken.
✗ Branch 799 not taken.
✗ Branch 800 not taken.
✗ Branch 802 not taken.
✗ Branch 803 not taken.
✗ Branch 805 not taken.
✗ Branch 806 not taken.
✗ Branch 808 not taken.
✗ Branch 809 not taken.
✗ Branch 811 not taken.
✗ Branch 812 not taken.
✗ Branch 814 not taken.
✗ Branch 815 not taken.
✗ Branch 817 not taken.
✗ Branch 818 not taken.
✗ Branch 820 not taken.
✗ Branch 821 not taken.
✗ Branch 823 not taken.
✗ Branch 824 not taken.
✗ Branch 826 not taken.
✗ Branch 827 not taken.
✗ Branch 829 not taken.
✗ Branch 830 not taken.
✗ Branch 832 not taken.
✗ Branch 833 not taken.
✗ Branch 835 not taken.
✗ Branch 836 not taken.
✗ Branch 838 not taken.
✗ Branch 839 not taken.
✗ Branch 841 not taken.
✗ Branch 842 not taken.
✗ Branch 844 not taken.
✗ Branch 845 not taken.
✗ Branch 847 not taken.
✗ Branch 848 not taken.
✗ Branch 850 not taken.
✗ Branch 851 not taken.
✗ Branch 853 not taken.
✗ Branch 854 not taken.
✗ Branch 856 not taken.
✗ Branch 857 not taken.
✗ Branch 859 not taken.
✗ Branch 860 not taken.
✗ Branch 862 not taken.
✗ Branch 863 not taken.
✗ Branch 865 not taken.
✗ Branch 866 not taken.
✗ Branch 868 not taken.
✗ Branch 869 not taken.
✗ Branch 871 not taken.
✗ Branch 872 not taken.
✗ Branch 874 not taken.
✗ Branch 875 not taken.
✗ Branch 877 not taken.
✗ Branch 878 not taken.
✗ Branch 880 not taken.
✗ Branch 881 not taken.
✗ Branch 883 not taken.
✗ Branch 884 not taken.
✗ Branch 886 not taken.
✗ Branch 887 not taken.
✗ Branch 889 not taken.
✗ Branch 890 not taken.
✗ Branch 892 not taken.
✗ Branch 893 not taken.
✗ Branch 895 not taken.
✗ Branch 896 not taken.
✗ Branch 898 not taken.
✗ Branch 899 not taken.
✗ Branch 901 not taken.
✗ Branch 902 not taken.
✗ Branch 904 not taken.
✗ Branch 905 not taken.
✗ Branch 907 not taken.
✗ Branch 908 not taken.
✗ Branch 910 not taken.
✗ Branch 911 not taken.
✗ Branch 913 not taken.
✗ Branch 914 not taken.
✗ Branch 916 not taken.
✗ Branch 917 not taken.
✗ Branch 919 not taken.
✗ Branch 920 not taken.
✗ Branch 922 not taken.
✗ Branch 923 not taken.
✗ Branch 925 not taken.
✗ Branch 926 not taken.
✗ Branch 928 not taken.
✗ Branch 929 not taken.
✗ Branch 931 not taken.
✗ Branch 932 not taken.
✗ Branch 934 not taken.
✗ Branch 935 not taken.
✗ Branch 937 not taken.
✗ Branch 938 not taken.
✗ Branch 940 not taken.
✗ Branch 941 not taken.
✗ Branch 943 not taken.
✗ Branch 944 not taken.
✗ Branch 946 not taken.
✗ Branch 947 not taken.
✗ Branch 949 not taken.
✗ Branch 950 not taken.
✗ Branch 952 not taken.
✗ Branch 953 not taken.
✗ Branch 955 not taken.
✗ Branch 956 not taken.
✗ Branch 958 not taken.
✗ Branch 959 not taken.
✗ Branch 961 not taken.
✗ Branch 962 not taken.
✗ Branch 964 not taken.
✗ Branch 965 not taken.
✗ Branch 967 not taken.
✗ Branch 968 not taken.
✗ Branch 970 not taken.
✗ Branch 971 not taken.
✓ Branch 973 taken 1 times.
✗ Branch 974 not taken.
✓ Branch 976 taken 5 times.
✗ Branch 977 not taken.
✓ Branch 979 taken 1 times.
✗ Branch 980 not taken.
✓ Branch 982 taken 39 times.
✗ Branch 983 not taken.
✗ Branch 985 not taken.
✗ Branch 986 not taken.
✓ Branch 988 taken 36 times.
✗ Branch 989 not taken.
2385149 return attributes_;
111 }
112
113 /**
114 * \brief Used by range-based for.
115 * \return The index of the first position.
116 */
117 index_as_iterator begin() const {
118 return index_as_iterator(0);
119 }
120
121 /**
122 * \brief Used by range-based for.
123 * \return The index of one position past the last position.
124 */
125 index_as_iterator end() const {
126 94441 return index_as_iterator(nb());
127 }
128
129 protected:
130
131 /**
132 * \brief Removes all the elements and attributes.
133 * \param[in] keep_attributes if true, then all the
134 * existing attribute names / bindings are kept (but
135 * they are cleared). If false, they are destroyed.
136 * \param[in] keep_memory if true, then memory is
137 * kept and can be reused by subsequent mesh
138 * element creations.
139 */
140 virtual void clear_store(
141 bool keep_attributes, bool keep_memory = false
142 );
143
144 /**
145 * \brief Resizes this MeshSubElementsStore.
146 * \details On exit, nb() == new_size, elements are
147 * created or destroyed if needed.
148 * \param[in] new_size the desired size
149 */
150 virtual void resize_store(index_t new_size);
151
152
153 /**
154 * \brief Reserves space for new elements
155 * \param[in] nb_to_reserve the number of subelements to reserve
156 */
157 void reserve_store(index_t nb_to_reserve) {
158 index_t nb = this->nb();
159 114 resize_store(nb + nb_to_reserve);
160 114 resize_store(nb);
161 }
162
163 /**
164 * \brief Creates a contiguous chunk of attributes for sub-elements.
165 * \param[in] nb number of sub-elements to create
166 * \return the index of the first created sub-element
167 */
168 1191 index_t create_sub_elements(index_t nb) {
169 1191 index_t result = nb_;
170
2/2
✓ Branch 0 taken 1132 times.
✓ Branch 1 taken 59 times.
1191 if(nb_ + nb > attributes_.size()) {
171 index_t new_capacity=nb_ + nb;
172
2/2
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 493 times.
1132 if(nb < 128) {
173 new_capacity = std::max(index_t(16),attributes_.capacity());
174
2/2
✓ Branch 0 taken 528 times.
✓ Branch 1 taken 639 times.
1167 while(new_capacity < nb_ + nb) {
175 528 new_capacity *= 2;
176 }
177 }
178 1132 attributes_.reserve(new_capacity);
179 }
180 1191 nb_ += nb;
181 1191 attributes_.resize(nb_);
182 1191 return result;
183 }
184
185 /**
186 * \brief Creates attributes for a sub-element
187 * \return the index of the created element
188 */
189 6189778 index_t create_sub_element() {
190 6189778 index_t result = nb_;
191
2/2
✓ Branch 0 taken 6965 times.
✓ Branch 1 taken 6182813 times.
6189778 ++nb_;
192
2/2
✓ Branch 0 taken 6965 times.
✓ Branch 1 taken 6182813 times.
6189778 if(attributes_.capacity() < nb_) {
193 index_t new_capacity =
194 6965 std::max(index_t(16),attributes_.capacity()*2);
195 6965 attributes_.reserve(new_capacity);
196 }
197 6189778 attributes_.resize(nb_);
198 6189778 return result;
199 }
200
201 /**
202 * \brief Makes the size of the store tightly match
203 * the number of the elements.
204 * \details When elements are created one by one, the
205 * system may allocate more memory than necessary, to
206 * amortize the cost of container reallocation. Once
207 * the object is constructed, this function may be called
208 * to release the memory that was not used.
209 */
210 void adjust_store() {
211 attributes_.resize(nb_);
212 }
213
214 /**
215 * \brief Copies a MeshSubElementsStore into
216 * this one.
217 * \param[in] rhs a const reference to the
218 * MeshSubElementsStore to be copied.
219 * \param[in] copy_attributes if true, copies
220 * also the attributes, else attributes are
221 * cleared.
222 */
223 427 void copy(
224 const MeshSubElementsStore& rhs,
225 bool copy_attributes = true
226 ) {
227 427 nb_ = rhs.nb();
228
1/2
✓ Branch 0 taken 427 times.
✗ Branch 1 not taken.
427 if(copy_attributes) {
229 427 attributes_.copy(rhs.attributes_);
230 } else {
231 attributes_.clear(false,false);
232 attributes_.resize(rhs.attributes_.size());
233 }
234 427 }
235
236 protected:
237 Mesh& mesh_;
238 mutable AttributesManager attributes_;
239 index_t nb_;
240 };
241
242
243 /**************************************************************************/
244
245 /**
246 * \brief Base class for mesh elements.
247 * \details Mesh elements can be created / manipulated independantly,
248 * in contrast with sub-elements that cannot. Mesh elements are
249 * vertices, facets and cells.
250 * \relates Mesh
251 */
252 class GEOGRAM_API MeshElements {
253 public:
254 MeshElements();
255 virtual ~MeshElements();
256
257 /**
258 * \brief Deletes a set of elements.
259 * \param[in] to_delete a vector of size nb(). If to_delete[e]
260 * is different from 0, then element e will be destroyed, else
261 * it will be kept. On exit, to_delete is modified (it is used
262 * for internal bookkeeping).
263 * \param[in] remove_isolated_vertices if true, then the vertices
264 * that are no longer incident to any element are deleted.
265 */
266 virtual void delete_elements(
267 vector<index_t>& to_delete,
268 bool remove_isolated_vertices=true
269 ) = 0;
270
271 /**
272 * \brief Applies a permutation to the elements and their attributes.
273 * \details On exit, permutation is modified (used for internal
274 * bookkeeping). Applying a permutation \p permutation is equivalent
275 * to:
276 * \code
277 * for(i=0; i<permutation.size(); i++) {
278 * data2[i] = data[permutation[i]]
279 * }
280 * data = data2 ;
281 * \endcode
282 */
283 virtual void permute_elements(vector<index_t>& permutation) = 0;
284
285 /**
286 * \brief Removes all the elements and attributes.
287 * \param[in] keep_attributes if true, then all the
288 * existing attribute names / bindings are kept (but
289 * they are cleared). If false, they are destroyed.
290 * \param[in] keep_memory if true, then memory is
291 * kept and can be reused by subsequent mesh
292 * element creations.
293 */
294 virtual void clear(
295 bool keep_attributes=true, bool keep_memory=false
296 ) = 0;
297
298 /**
299 * \brief Removes the last element.
300 */
301 virtual void pop() = 0;
302
303 protected:
304 /**
305 * \brief Tests whether a vector contains a non-zero value.
306 * \details This function is used internally by delete_elements()
307 * \param[in] I a vector of signed integers
308 * \retval true if \p I contains at least a non-zero value
309 * \retval false otherwise
310 */
311 static bool has_non_zero(const GEO::vector<index_t>& I) {
312
5/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 291882 times.
✓ Branch 3 taken 79 times.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 293928 times.
✓ Branch 7 taken 305 times.
1171995 for(index_t i = 0; i < I.size(); i++) {
313
6/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 291671 times.
✓ Branch 3 taken 211 times.
✓ Branch 4 taken 38 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 293758 times.
✓ Branch 7 taken 170 times.
585851 if(I[i] != 0) {
314 return true;
315 }
316 }
317 return false;
318 }
319 };
320
321 /**************************************************************************/
322
323 class MeshEdges;
324 class MeshFacetCornersStore;
325 class MeshCellCornersStore;
326
327 /**
328 * \brief The vertices of a mesh.
329 * \relates Mesh
330 */
331 class GEOGRAM_API MeshVertices :
332 public MeshSubElementsStore, public MeshElements {
333 public:
334 MeshVertices(Mesh& mesh);
335 ~MeshVertices() override;
336
337 /**
338 * \brief Removes the vertices that have no mesh element
339 * incident to them.
340 */
341 void remove_isolated();
342
343 void delete_elements(
344 vector<index_t>& to_delete, bool remove_isolated_vertices=true
345 ) override;
346
347 void permute_elements(vector<index_t>& permutation) override;
348
349 /**
350 * \brief Creates a new vertex
351 * \return the index of the created vertex
352 */
353 index_t create_vertex() {
354
2/10
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 192 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 345173 times.
✗ Branch 14 not taken.
678788 return MeshSubElementsStore::create_sub_element();
355 }
356
357 /**
358 * \brief Creates a new vertex
359 * \param[in] coords a pointer to dimension() coordinates
360 * \return the index of the created vertex
361 */
362 120127 index_t create_vertex(const double* coords) {
363 // Sanity check:
364 // It is not correct to call create_vertex(point_ptr(v)) since
365 // create_vertex may realloc the points coordinates vector, thus
366 // invalidate point_ptr(v).
367 geo_debug_assert(
368 nb() == 0 ||
369 coords < point_ptr(0) ||
370 coords >= point_ptr(0) + nb() * dimension()
371 );
372 index_t result = create_vertex();
373
2/2
✓ Branch 0 taken 357128 times.
✓ Branch 1 taken 120127 times.
597382 for(index_t c=0; c<dimension(); ++c) {
374 357128 point_ptr(result)[c] = coords[c];
375 }
376 120127 return result;
377 }
378
379 /**
380 * \brief Creates a vertex from a 3d point
381 * \param[in] p a const reference to the 3d point
382 * \return the index of the created vertex
383 * \pre dimension() == 3
384 */
385 template <index_t DIM> index_t create_vertex(
386 const vecng<DIM,double>& p
387 ) {
388 geo_debug_assert(dimension() == DIM);
389
14/28
✓ Branch 1 taken 767 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 51 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 51 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 51 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 51 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 51 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 51 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 51 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 51 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 2916 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 22 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 22 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 22 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 22 times.
✗ Branch 41 not taken.
3756 return create_vertex(p.data());
390 }
391
392 /**
393 * \brief Creates a contiguous chunk of vertices.
394 * \param[in] nb number of sub-elements to create
395 * \return the index of the first created vertex
396 */
397 index_t create_vertices(index_t nb) {
398
6/15
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 88 times.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 17 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 11 taken 25 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 24 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
388 return MeshSubElementsStore::create_sub_elements(nb);
399 }
400
401 void clear(
402 bool keep_attributes=true, bool keep_memory=false
403 ) override;
404
405 /**
406 * \brief Sets single precision mode.
407 * \details Single-precision mode is used for instance
408 * by Vorpaview, to make it more memory efficient.
409 * Existing point coordinates are copied and converted to
410 * single precision.
411 */
412 void set_single_precision();
413
414 /**
415 * \brief Sets double precision mode.
416 * \details Double precision mode is the default.
417 * Single-precision mode is used for instance
418 * by Vorpaview, to make it more memory efficient.
419 * Existing point coordinates are copied and converted to
420 * double precision.
421 */
422 void set_double_precision();
423
424 /**
425 * \brief Tests whether vertices are stored in
426 * single-precision mode.
427 * \details Single-precision mode is used for instance
428 * by Vorpaview, to make it more memory efficient.
429 */
430 bool single_precision() const {
431 return point_fp32_.is_bound();
432 }
433
434 /**
435 * \brief Tests whether vertices are stored in
436 * double-precision mode.
437 * \details Double precision mode is the default.
438 * Single-precision mode is used for instance
439 * by Vorpaview, to make it more memory efficient.
440 */
441 bool double_precision() const {
442 return point_.is_bound();
443 }
444
445 /**
446 * \brief Gets the dimension of the vertices.
447 * \return the number of coordinates in each vertex
448 */
449 index_t dimension() const {
450 return
451 single_precision() ?
452 point_fp32_.dimension() :
453 point_.dimension() ;
454 }
455
456 /**
457 * \brief Sets the dimension of the vertices
458 * \details Existing coordinates are kept, newly created
459 * coordinates are initialized to zero.
460 * \param[in] dim new dimension
461 */
462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 701 times.
701 void set_dimension(index_t dim) {
463 if(single_precision()) {
464 point_fp32_.redim(dim);
465 } else {
466 701 point_.redim(dim);
467 }
468 701 }
469
470 /**
471 * \brief Gets a point
472 * \param[in] v the index of the vertex
473 * \return a const pointer to the coordinates of the point
474 * that correspond to the vertex
475 * \pre !single_precision()
476 */
477 const double* point_ptr(index_t v) const {
478 geo_debug_assert(v < nb());
479 geo_debug_assert(!single_precision());
480
84/240
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 80 times.
✓ Branch 51 taken 444 times.
✓ Branch 52 taken 2045 times.
✓ Branch 53 taken 2050 times.
✓ Branch 54 taken 2121 times.
✓ Branch 55 taken 2050 times.
✓ Branch 56 taken 356 times.
✓ Branch 57 taken 320 times.
✓ Branch 58 taken 159 times.
✓ Branch 59 taken 197 times.
✓ Branch 60 taken 102 times.
✓ Branch 61 taken 218 times.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✓ Branch 136 taken 518 times.
✓ Branch 137 taken 444 times.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✓ Branch 140 taken 108 times.
✓ Branch 141 taken 528 times.
✓ Branch 142 taken 5713 times.
✓ Branch 143 taken 3929 times.
✓ Branch 144 taken 4692 times.
✓ Branch 145 taken 3929 times.
✓ Branch 146 taken 392 times.
✓ Branch 147 taken 429 times.
✓ Branch 148 taken 165 times.
✓ Branch 149 taken 227 times.
✓ Branch 150 taken 124 times.
✓ Branch 151 taken 305 times.
✓ Branch 152 taken 93 times.
✓ Branch 153 taken 501 times.
✓ Branch 154 taken 4730 times.
✓ Branch 155 taken 3792 times.
✓ Branch 156 taken 4400 times.
✓ Branch 157 taken 3792 times.
✓ Branch 158 taken 378 times.
✓ Branch 159 taken 427 times.
✓ Branch 160 taken 135 times.
✓ Branch 161 taken 243 times.
✓ Branch 162 taken 156 times.
✓ Branch 163 taken 271 times.
✓ Branch 164 taken 93 times.
✓ Branch 165 taken 462 times.
✓ Branch 166 taken 3783 times.
✓ Branch 167 taken 3949 times.
✓ Branch 168 taken 4965 times.
✓ Branch 169 taken 3949 times.
✓ Branch 170 taken 358 times.
✓ Branch 171 taken 409 times.
✓ Branch 172 taken 130 times.
✓ Branch 173 taken 228 times.
✓ Branch 174 taken 135 times.
✓ Branch 175 taken 274 times.
✓ Branch 176 taken 85 times.
✓ Branch 177 taken 468 times.
✓ Branch 178 taken 4331 times.
✓ Branch 179 taken 3886 times.
✓ Branch 180 taken 4432 times.
✓ Branch 181 taken 3886 times.
✓ Branch 182 taken 338 times.
✓ Branch 183 taken 407 times.
✓ Branch 184 taken 141 times.
✓ Branch 185 taken 197 times.
✓ Branch 186 taken 126 times.
✓ Branch 187 taken 281 times.
✓ Branch 188 taken 89 times.
✓ Branch 189 taken 508 times.
✓ Branch 190 taken 6464 times.
✓ Branch 191 taken 5264 times.
✓ Branch 192 taken 6826 times.
✓ Branch 193 taken 5264 times.
✓ Branch 194 taken 376 times.
✓ Branch 195 taken 471 times.
✓ Branch 196 taken 143 times.
✓ Branch 197 taken 233 times.
✓ Branch 198 taken 154 times.
✓ Branch 199 taken 317 times.
✗ Branch 200 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 203 not taken.
✗ Branch 204 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 207 not taken.
✗ Branch 208 not taken.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 211 not taken.
✗ Branch 212 not taken.
✗ Branch 213 not taken.
✗ Branch 214 not taken.
✗ Branch 215 not taken.
✗ Branch 216 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 219 not taken.
✓ Branch 220 taken 521 times.
✓ Branch 221 taken 528 times.
✗ Branch 222 not taken.
✗ Branch 223 not taken.
✓ Branch 224 taken 470 times.
✓ Branch 225 taken 501 times.
✗ Branch 226 not taken.
✗ Branch 227 not taken.
✓ Branch 228 taken 518 times.
✓ Branch 229 taken 462 times.
✗ Branch 230 not taken.
✗ Branch 231 not taken.
✓ Branch 232 taken 540 times.
✓ Branch 233 taken 468 times.
✗ Branch 234 not taken.
✗ Branch 235 not taken.
✓ Branch 236 taken 540 times.
✓ Branch 237 taken 508 times.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
70720371 return &point_[v*point_.dimension()];
481 }
482
483 /**
484 * \brief Gets a point
485 * \param[in] v the vertex, in 0..nb()-1
486 * \return a pointer to the coordinates of the point
487 * that correspond to the vertex
488 * \pre !single_precision()
489 */
490 double* point_ptr(index_t v) {
491 geo_debug_assert(v < nb());
492 geo_debug_assert(!single_precision());
493
6/8
✓ Branch 0 taken 6452 times.
✓ Branch 1 taken 161204 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 32 times.
✗ Branch 8 not taken.
2122142 return &point_[v*point_.dimension()];
494 }
495
496
497 /**
498 * \brief Gets a point
499 * \param[in] v the vertex, in 0..nb()-1
500 * \return a modifiable reference to the point
501 * that corresponds to the vertex
502 * \pre !single_precision()
503 */
504 template<index_t DIM=3> vecng<DIM,double>& point(index_t v) {
505 geo_debug_assert(v < nb());
506 geo_debug_assert(!single_precision());
507 geo_debug_assert(dimension() >= DIM);
508 return Memory::pointer_as_reference<vecng<DIM,double>>(
509
12/15
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 138327 times.
✓ Branch 2 taken 5512 times.
✓ Branch 3 taken 19128 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 55 times.
✓ Branch 6 taken 484044 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 4599 times.
✓ Branch 9 taken 1618 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 178 times.
✓ Branch 15 taken 64410 times.
✗ Branch 16 not taken.
217036799 &point_[v*point_.dimension()]
510 );
511 }
512
513 /**
514 * \brief Gets a point
515 * \param[in] v the vertex, in 0..nb()-1
516 * \return a const reference to the point
517 * that corresponds to the vertex
518 * \pre !single_precision()
519 */
520 template <index_t DIM=3> const vecng<DIM,double>& point(
521 index_t v
522 ) const {
523 geo_debug_assert(v < nb());
524 geo_debug_assert(!single_precision());
525 geo_debug_assert(dimension() >= DIM);
526 return Memory::pointer_as_reference<vecng<DIM,double>>(
527
7/38
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 3 taken 866296 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 20 taken 300 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 10000 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 300 times.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✓ Branch 32 taken 300 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 20000 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 300 times.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
1114649 &point_[v*point_.dimension()]
528 );
529 }
530
531 /**
532 * \brief Gets a (single-precision) point
533 * \param[in] v the index of the vertex
534 * \return a const pointer to the coordinates
535 * of the point that corresponds to the vertex
536 * \pre single_precision()
537 */
538 const float* single_precision_point_ptr(index_t v) const {
539 geo_debug_assert(v < nb());
540 geo_debug_assert(single_precision());
541 return &point_fp32_[v*point_fp32_.dimension()];
542 }
543
544 /**
545 * \brief Gets a (single-precision) point
546 * \param[in] v the index of the vertex
547 * \return a pointer to the coordinates of the point
548 * that corresponds to the vertex
549 * \pre single_precision()
550 */
551 float* single_precision_point_ptr(index_t v) {
552 geo_debug_assert(v < nb());
553 geo_debug_assert(single_precision());
554 return &point_fp32_[v*point_fp32_.dimension()];
555 }
556
557 /**
558 * \brief Gets the coordinates of all the points as a single vector.
559 * \details The vector contains nb() * dimension() coordinates
560 * [x0, y0, z0, x1, y1, z1, ...]. It is forbidden to change the
561 * size of the returned vector; the reference is invalidated by
562 * create_vertices() (same lifetime rule as point_ptr()).
563 * \return a const reference to the vector of all point coordinates.
564 * \pre !single_precision()
565 */
566 const vector<double>& point_coordinates() const {
567 geo_debug_assert(!single_precision());
568 return point_.get_vector();
569 }
570
571 /**
572 * \brief Gets the coordinates of all the points as a single vector.
573 * \return a modifiable reference to the vector of all point
574 * coordinates (see the const overload for the contract).
575 * \pre !single_precision()
576 */
577 vector<double>& point_coordinates() {
578 geo_debug_assert(!single_precision());
579 return point_.get_vector();
580 }
581
582
583 /**
584 * \brief Assigns all the points.
585 * \param[in] points a vector that contains all the coordinates
586 * of the points
587 * \param[in] dim the dimension of the points, i.e. number of
588 * coordinates per point
589 * \param[in] steal_arg if true, memory is stolen from \p points,
590 * using std::vector::swap (no memory copy).
591 */
592 void assign_points(
593 vector<double>& points, index_t dim, bool steal_arg
594 );
595
596 /**
597 * \brief Assigns all the points.
598 * \param[in] points a const pointer to the (\p dim * \p nb_pts)
599 * coordinates of al the points
600 * \param[in] dim the dimension of the points, i.e. number of
601 * coordinates per point
602 * \param[in] nb_pts number of points
603 */
604 void assign_points(
605 const double* points, index_t dim, index_t nb_pts
606 );
607
608 void pop() override;
609
610 #ifndef MESH_NO_SYNTAXIC_SUGAR
611
612 /**
613 * \brief Gets the 3D points of the mesh as an iterable sequence
614 * \details Each point is returned as a const reference
615 */
616 template <index_t DIM = 3> auto points() const {
617 typedef vecng<DIM,double> vecn;
618 return transform_range_ref(
619 index_range(0, nb()),
620 [this](index_t v)->const vecn& {
621 // for MSVC that cannot chose among const/non-const versions
622 return Memory::pointer_as_reference<vecn>(point_ptr(v));
623 // return point<DIM>(v); // MSVC does not understand this one
624 }
625 );
626 }
627
628 /**
629 * \brief Gets the 3D points of the mesh as an iterable sequence
630 * \details Each point is returned as a modifiable reference
631 */
632 template <index_t DIM = 3> auto points() {
633 typedef vecng<DIM,double> vecn;
634 return transform_range_ref(
635 index_range(0, nb()),
636 [this](index_t v)->vecn& {
637 // for MSVC that cannot chose among const/non-const versions
638 return Memory::pointer_as_reference<vecn>(point_ptr(v));
639 // return point<DIM>(v); //MSVC does not understand this one
640 }
641 );
642 }
643
644 #endif
645
646 protected:
647
648 void clear_store(
649 bool keep_attributes, bool keep_memory = false
650 ) override;
651
652 void resize_store(index_t new_size) override;
653
654 void bind_point_attribute(index_t dim, bool single_precision=false);
655
656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 void copy(const MeshVertices& rhs, bool copy_attributes=true) {
657 index_t dim = rhs.dimension();
658 if(point_fp32_.is_bound()) {
659 point_fp32_.destroy();
660 }
661 if(point_.is_bound()) {
662 61 point_.destroy();
663 }
664 61 MeshSubElementsStore::copy(rhs, copy_attributes);
665 if(rhs.single_precision()) {
666 point_fp32_.bind_if_is_defined(attributes(),"point_fp32");
667 if(!point_fp32_.is_bound()) {
668 point_fp32_.create_vector_attribute(
669 attributes(), "point_fp32", dim
670 );
671 }
672 } else {
673
2/4
✓ Branch 2 taken 61 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
122 point_.bind_if_is_defined(attributes(),"point");
674 if(!point_.is_bound()) {
675 point_.create_vector_attribute(
676 attributes(), "point", dim
677 );
678 }
679 }
680 // Even if we do not copy the attributes, we need at least
681 // to copy the coordinates of the points !!
682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if(!copy_attributes) {
683 if(rhs.single_precision()) {
684 Memory::copy(
685 single_precision_point_ptr(0),
686 rhs.single_precision_point_ptr(0),
687 rhs.dimension()*rhs.nb()*sizeof(float)
688 );
689 } else {
690 Memory::copy(
691 point_ptr(0),
692 rhs.point_ptr(0),
693 rhs.dimension()*rhs.nb()*sizeof(double)
694 );
695 }
696 }
697 61 }
698
699 MeshEdges& edges_;
700 MeshFacetCornersStore& facet_corners_;
701 MeshCellCornersStore& cell_corners_;
702 Attribute<double> point_;
703 Attribute<float> point_fp32_;
704
705 friend class Mesh;
706 friend class GeogramIOHandler;
707 };
708
709 /*************************************************************************/
710
711 /**
712 * \brief The edges of a mesh.
713 * \relates Mesh
714 */
715 class GEOGRAM_API MeshEdges :
716 public MeshSubElementsStore, public MeshElements {
717 public:
718 MeshEdges(Mesh& mesh);
719 ~MeshEdges() override;
720
721 /**
722 * \brief Gets the index of an edge vertex
723 * \param[in] e index of the edge
724 * \param[in] lv local index of the vertex, in {0,1}
725 * \return the global index of vertex \p lv in edge \p e
726 */
727 index_t vertex(index_t e, index_t lv) const {
728 geo_debug_assert(e < nb());
729 geo_debug_assert(lv < 2);
730
6/21
✓ Branch 0 taken 768 times.
✓ Branch 1 taken 7673 times.
✓ Branch 2 taken 18934 times.
✓ Branch 3 taken 1314 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✓ Branch 6 taken 55 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
38485 return edge_vertex_[2*e+lv];
731 }
732
733 /**
734 * \brief Sets a vertex of an edge
735 * \param[in] e index of the edge
736 * \param[in] lv local index of the vertex, in {0,1}
737 * \param[in] v global index of the vertex
738 */
739 void set_vertex(index_t e, index_t lv, index_t v) {
740 geo_debug_assert(e < nb());
741 geo_debug_assert(lv < 2);
742
1/6
✓ Branch 0 taken 1314 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2370 edge_vertex_[2*e+lv] = v;
743 }
744
745
746 /**
747 * \brief Gets a pointer to a vertex index by corner index
748 * \param[in] c corner index (2 * edge index + 0 or 1)
749 * \return a pointer to the index of the vertex.
750 * \note Normal uses do not call this function
751 */
752 index_t* vertex_index_ptr(index_t c) {
753 geo_debug_assert(c < 2*nb());
754 return &(edge_vertex_[c]);
755 }
756
757 /**
758 * \brief Gets a pointer to a vertex index by corner index
759 * \param[in] c corner index (2 * edge index + 0 or 1)
760 * \return a pointer to the index of the vertex.
761 * \note Normal uses do not call this function
762 */
763 const index_t* vertex_index_ptr(index_t c) const {
764 geo_debug_assert(c < 2*nb());
765 return &(edge_vertex_[c]);
766 }
767
768 /**
769 * \brief Creates a new edge
770 * \return the index of the created edge
771 */
772 index_t create_edge() {
773
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
5013 return create_sub_element();
774 }
775
776 /**
777 * \brief Creates a batch of edges
778 * \param[in] nb number of edges to create
779 * \return the index of the first created edge
780 */
781 index_t create_edges(index_t nb) {
782
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 return create_sub_elements(nb);
783 }
784
785 /**
786 * \brief Creates a new edge
787 * \param[in] v1 , v2 global indices of the vertices of the edge
788 * \return the index of the created edge
789 */
790 8226 index_t create_edge(index_t v1, index_t v2) {
791 index_t result = create_edge();
792 set_vertex(result,0,v1);
793 set_vertex(result,1,v2);
794 8226 return result;
795 }
796
797 void delete_elements(
798 vector<index_t>& to_delete, bool remove_isolated_vertices=true
799 ) override;
800
801 void permute_elements(vector<index_t>& permutation) override;
802
803 void clear(
804 bool keep_attributes=true, bool keep_memory=false
805 ) override;
806
807 void pop() override;
808
809 /**
810 * \brief Swaps both extremities of an edge
811 * \param[in] e the edge
812 */
813 void flip(index_t e);
814
815 protected:
816 void clear_store(
817 bool keep_attributes, bool keep_memory = false
818 ) override;
819
820 void resize_store(index_t new_size) override;
821
822 8226 index_t create_sub_element() {
823
2/2
✓ Branch 0 taken 7043 times.
✓ Branch 1 taken 1183 times.
8226 edge_vertex_.push_back(NO_VERTEX);
824 edge_vertex_.push_back(NO_VERTEX);
825 8226 return MeshSubElementsStore::create_sub_element();
826 }
827
828 88 index_t create_sub_elements(index_t nb_in) {
829 88 edge_vertex_.resize(2*(nb()+nb_in),NO_VERTEX);
830 88 return MeshSubElementsStore::create_sub_elements(nb_in);
831 }
832
833 void copy(const MeshEdges& rhs, bool copy_attributes=true) {
834 61 MeshSubElementsStore::copy(rhs, copy_attributes);
835 edge_vertex_ = rhs.edge_vertex_;
836 61 }
837
838 vector<index_t> edge_vertex_;
839 friend class Mesh;
840 friend class GeogramIOHandler;
841 };
842
843 /**************************************************************************/
844
845 /**
846 * \brief Stores the facets of a mesh (low-level store)
847 * \relates MeshFacets
848 */
849 class GEOGRAM_API MeshFacetsStore : public MeshSubElementsStore {
850 public:
851 MeshFacetsStore(Mesh& mesh);
852
853 /**
854 * \brief Gets the first element for iterating over
855 * the corners of a facet
856 * \param[in] f the facet
857 * \return the first corner of the facet
858 */
859 index_t corners_begin(index_t f) const {
860 geo_debug_assert(f < nb());
861
43/60
✓ Branch 0 taken 6843438 times.
✓ Branch 1 taken 233725 times.
✓ Branch 2 taken 15909942 times.
✓ Branch 3 taken 4092 times.
✓ Branch 4 taken 6221254 times.
✓ Branch 5 taken 10260409 times.
✓ Branch 6 taken 4869824 times.
✓ Branch 7 taken 217186 times.
✓ Branch 8 taken 1374214 times.
✓ Branch 9 taken 13151 times.
✓ Branch 10 taken 4342050 times.
✓ Branch 11 taken 301 times.
✓ Branch 12 taken 1522087 times.
✓ Branch 13 taken 355923 times.
✓ Branch 14 taken 2941768 times.
✓ Branch 15 taken 355917 times.
✓ Branch 16 taken 1331007 times.
✓ Branch 17 taken 355917 times.
✓ Branch 18 taken 747606 times.
✓ Branch 19 taken 155068 times.
✓ Branch 20 taken 9675 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 4613 times.
✓ Branch 23 taken 298422 times.
✓ Branch 24 taken 685822 times.
✓ Branch 25 taken 194042 times.
✓ Branch 26 taken 1279794 times.
✓ Branch 27 taken 25842 times.
✓ Branch 28 taken 1734004 times.
✓ Branch 29 taken 5100 times.
✓ Branch 30 taken 452929 times.
✓ Branch 31 taken 5120 times.
✓ Branch 32 taken 806334 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 202429 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 2065009 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 61594 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✓ Branch 44 taken 848687 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 848687 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 16089472 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 16089472 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 848937 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 378988 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 426082 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 942622 times.
✗ Branch 59 not taken.
153572722 return (is_simplicial_ ? 3*f : facet_ptr_[f]);
862 }
863
864 /**
865 * \brief Gets the upper limit for iterating over the
866 * corners of a facet
867 * \param[in] f the facet
868 * \return one position past the last corner of the facet
869 */
870 index_t corners_end(index_t f) const {
871 geo_debug_assert(f < nb());
872
33/42
✓ Branch 0 taken 6891888 times.
✓ Branch 1 taken 218797 times.
✓ Branch 2 taken 6732876 times.
✓ Branch 3 taken 221616 times.
✓ Branch 4 taken 5888096 times.
✓ Branch 5 taken 40716 times.
✓ Branch 6 taken 2219337 times.
✓ Branch 7 taken 520 times.
✓ Branch 8 taken 1650074 times.
✓ Branch 9 taken 1786876 times.
✓ Branch 10 taken 9824896 times.
✓ Branch 11 taken 1786870 times.
✓ Branch 12 taken 6295374 times.
✓ Branch 13 taken 1786870 times.
✓ Branch 14 taken 1011479 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 131 times.
✓ Branch 17 taken 1504115 times.
✓ Branch 18 taken 2112516 times.
✓ Branch 19 taken 128928 times.
✓ Branch 20 taken 2964524 times.
✓ Branch 21 taken 128928 times.
✓ Branch 22 taken 3610642 times.
✓ Branch 23 taken 549587 times.
✓ Branch 24 taken 182847 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 990072 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 245680 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1650133 times.
✓ Branch 31 taken 5120 times.
✓ Branch 32 taken 17690441 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 17650196 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 40245 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 2546811 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 2739667 times.
✗ Branch 41 not taken.
119228721 return (is_simplicial_ ? 3*(f+1): facet_ptr_[f+1]);
873 }
874
875 /**
876 * \brief Gets the number of corners in a facet
877 * \param[in] f the facet
878 * \return the number of corners in facet \p f
879 */
880 index_t nb_corners(index_t f) const {
881 geo_debug_assert(f < nb());
882
14/64
✓ Branch 0 taken 79351 times.
✓ Branch 1 taken 6159493 times.
✓ Branch 2 taken 64610 times.
✓ Branch 3 taken 5110374 times.
✓ Branch 4 taken 2204 times.
✓ Branch 5 taken 5064024 times.
✓ Branch 6 taken 5100 times.
✓ Branch 7 taken 849095 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 848687 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 848957 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 942642 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 20 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 284905 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 284905 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
19708443 return (is_simplicial_ ? 3 : facet_ptr_[f+1] - facet_ptr_[f]);
883 }
884
885 /**
886 * \brief Gets a corner by facet and local vertex index
887 * \param[in] f the facet
888 * \param[in] lv the local index of the vertex in facet \p f
889 * \return the \p lv%th corner of facet \p f
890 * \pre lv < nb_corners(f)
891 */
892 index_t corner(index_t f, index_t lv) const {
893 geo_debug_assert(f < nb());
894 geo_debug_assert(lv < nb_corners(f));
895
33/51
✓ Branch 0 taken 404946 times.
✓ Branch 1 taken 68184 times.
✓ Branch 2 taken 122101 times.
✓ Branch 3 taken 558696 times.
✓ Branch 4 taken 140603 times.
✓ Branch 5 taken 20460 times.
✓ Branch 6 taken 201101 times.
✓ Branch 7 taken 1100 times.
✓ Branch 8 taken 178 times.
✓ Branch 9 taken 61420 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 309390 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1268928 times.
✓ Branch 14 taken 61420 times.
✓ Branch 15 taken 1268928 times.
✓ Branch 16 taken 61420 times.
✓ Branch 17 taken 776602 times.
✓ Branch 18 taken 920408 times.
✓ Branch 19 taken 956284 times.
✓ Branch 20 taken 77141 times.
✓ Branch 21 taken 566560 times.
✓ Branch 22 taken 389724 times.
✓ Branch 23 taken 9892308 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 5060975 times.
✓ Branch 26 taken 5285371 times.
✓ Branch 27 taken 200529 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 200529 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 200529 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 200529 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 675198 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 32430 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 5281 times.
✓ Branch 41 taken 27149 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 64410 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
40701075 return corners_begin(f)+lv;
896 }
897
898 /**
899 * \brief Tests whether all the facets are triangles
900 * \details When all the facets are triangles, storage
901 * and access is optimized.
902 * \retval true if all the facets are triangles
903 * \retval false otherwise
904 */
905 bool are_simplices() const {
906
6/28
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 204 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 4 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
931 return is_simplicial_;
907 }
908
909 /**
910 * \brief Gets a pointer to the first element for iterating over
911 * the corners of a facet
912 * \param[in] f the facet
913 * \return a pointer to the first corner of the facet
914 */
915 index_t* corners_begin_ptr(index_t f) {
916 geo_debug_assert(!is_simplicial_);
917 geo_debug_assert(f < nb());
918 return &facet_ptr_[f];
919 }
920
921 /**
922 * \brief Gets a pointer to the first element for iterating over
923 * the corners of a facet
924 * \param[in] f the facet
925 * \return a const pointer to the first corner of the facet
926 */
927 const index_t* corners_begin_ptr(index_t f) const {
928 geo_debug_assert(!is_simplicial_);
929 geo_debug_assert(f < nb());
930 return &facet_ptr_[f];
931 }
932
933
934 protected:
935 void clear_store(
936 bool keep_attributes, bool keep_memory = false
937 ) override;
938
939 void resize_store(index_t new_size) override;
940
941 1290015 index_t create_sub_element() {
942
2/2
✓ Branch 0 taken 335412 times.
✓ Branch 1 taken 954603 times.
1290015 if(!is_simplicial_) {
943
2/2
✓ Branch 0 taken 334407 times.
✓ Branch 1 taken 1005 times.
335412 facet_ptr_.push_back(NO_CORNER);
944 }
945 1290015 return MeshSubElementsStore::create_sub_element();
946 }
947
948 350 index_t create_sub_elements(index_t nb) {
949
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 340 times.
350 if(!is_simplicial_) {
950
2/2
✓ Branch 0 taken 20678 times.
✓ Branch 1 taken 10 times.
20688 for(index_t i=0; i<nb; ++i) {
951
2/2
✓ Branch 0 taken 20644 times.
✓ Branch 1 taken 34 times.
20678 facet_ptr_.push_back(NO_CORNER);
952 }
953 }
954 350 return MeshSubElementsStore::create_sub_elements(nb);
955 }
956
957 void copy(const MeshFacetsStore& rhs, bool copy_attributes=true) {
958 61 MeshSubElementsStore::copy(rhs,copy_attributes);
959 61 is_simplicial_ = rhs.is_simplicial_;
960 facet_ptr_ = rhs.facet_ptr_;
961 }
962
963 protected:
964 bool is_simplicial_;
965 vector<index_t> facet_ptr_;
966 friend class Mesh;
967 friend class GeogramIOHandler;
968 };
969
970 /*************************************************************************/
971
972 /**
973 * \brief Stores the facet corners of a mesh (low-level store)
974 * \relates MeshFacets
975 */
976 class GEOGRAM_API MeshFacetCornersStore : public MeshSubElementsStore {
977 public:
978 MeshFacetCornersStore(Mesh& mesh);
979
980 /**
981 * \brief Gets the vertex that a corner is incident to
982 * \param[in] c the corner
983 * \return the vertex that corner \p c is incident to
984 */
985 index_t vertex(index_t c) const {
986 geo_debug_assert(c < nb());
987
41/59
✓ Branch 0 taken 473538 times.
✓ Branch 1 taken 1260834 times.
✓ Branch 2 taken 173860 times.
✓ Branch 3 taken 1862998 times.
✓ Branch 4 taken 4964948 times.
✓ Branch 5 taken 2053468 times.
✓ Branch 6 taken 1491007 times.
✓ Branch 7 taken 188464 times.
✓ Branch 8 taken 4590186 times.
✓ Branch 9 taken 353030 times.
✓ Branch 10 taken 34028321 times.
✓ Branch 11 taken 5083784 times.
✓ Branch 12 taken 40453 times.
✓ Branch 13 taken 4962204 times.
✓ Branch 14 taken 191422 times.
✓ Branch 15 taken 303115 times.
✓ Branch 16 taken 942016 times.
✓ Branch 17 taken 370476 times.
✓ Branch 18 taken 818842 times.
✓ Branch 19 taken 801506 times.
✓ Branch 20 taken 3823127 times.
✓ Branch 21 taken 14281107 times.
✓ Branch 22 taken 1287022 times.
✓ Branch 23 taken 1984502 times.
✓ Branch 24 taken 3357193 times.
✓ Branch 25 taken 1345706 times.
✓ Branch 26 taken 1282883 times.
✓ Branch 27 taken 204587 times.
✓ Branch 28 taken 9892308 times.
✓ Branch 29 taken 20460 times.
✓ Branch 30 taken 4606937 times.
✓ Branch 31 taken 5295371 times.
✓ Branch 32 taken 384789 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 261949 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 200529 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 32430 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 5281 times.
✓ Branch 41 taken 27149 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 20000 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✓ Branch 47 taken 1007411 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 64410 times.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
201115413 return corner_vertex_[c];
988 }
989
990 /**
991 * \brief Gets the facet that a corner is adjacent to
992 * \param[in] c the corner
993 * \return the facet that corner \p is adjacent to or
994 * NO_FACET if \p c is on the border
995 */
996 index_t adjacent_facet(index_t c) const {
997 geo_debug_assert(c < nb());
998
18/24
✓ Branch 0 taken 3738206 times.
✓ Branch 1 taken 3325344 times.
✓ Branch 2 taken 2230554 times.
✓ Branch 3 taken 5224754 times.
✓ Branch 4 taken 6453669 times.
✓ Branch 5 taken 261534 times.
✓ Branch 6 taken 19341535 times.
✓ Branch 7 taken 2746429 times.
✓ Branch 8 taken 5641762 times.
✓ Branch 9 taken 37316 times.
✓ Branch 10 taken 2967501 times.
✓ Branch 11 taken 33702 times.
✓ Branch 12 taken 16591 times.
✓ Branch 13 taken 92130 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 92130 times.
✓ Branch 16 taken 90717 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 1121680 times.
✓ Branch 23 taken 1111496 times.
56688430 return corner_adjacent_facet_[c];
999 }
1000
1001 /**
1002 * \brief Gets a pointer to the the facet index
1003 * that a corner is adjacent to
1004 * \param[in] c the corner
1005 * \return a pointer to the the facet index
1006 * that corner \p is adjacent to.
1007 */
1008 const index_t* adjacent_facet_ptr(index_t c) const {
1009 geo_debug_assert(c < nb());
1010 return &corner_adjacent_facet_[c];
1011 }
1012
1013
1014 /**
1015 * \brief Gets a pointer to the the facet index
1016 * that a corner is adjacent to
1017 * \param[in] c the corner
1018 * \return a pointer to the the facet index
1019 * that corner \p is adjacent to.
1020 */
1021 index_t* adjacent_facet_ptr(index_t c) {
1022 geo_debug_assert(c < nb());
1023 return &corner_adjacent_facet_[c];
1024 }
1025
1026 /**
1027 * \brief Sets the vertex that a corner is incident to
1028 * \param[in] c the corner
1029 * \param[in] v the vertex that corner \p c is incident to
1030 * \pre v < mesh.vertices.nb()
1031 */
1032 void set_vertex(index_t c, index_t v) {
1033 geo_debug_assert(c < nb());
1034 geo_debug_assert(v < vertices_.nb());
1035
19/32
✓ Branch 0 taken 322630 times.
✓ Branch 1 taken 18680 times.
✓ Branch 2 taken 322630 times.
✓ Branch 3 taken 18680 times.
✓ Branch 4 taken 118980 times.
✓ Branch 5 taken 239669 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 20460 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 20460 times.
✓ Branch 10 taken 61420 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 61420 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 61420 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 61420 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 61420 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 61420 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 61420 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 61420 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 61420 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 61420 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 61420 times.
✗ Branch 34 not taken.
10988909 corner_vertex_[c] = v;
1036 }
1037
1038 /**
1039 * \brief Sets the vertex that a corner is incident to
1040 * \details Does not check whether \p v is a valid vertex
1041 * index. This function is useful for some algorithms that
1042 * need to create/update the facets before creating the
1043 * vertices.
1044 * \param[in] c the corner
1045 * \param[in] v the vertex that corner \p c is incident to
1046 * \note Normal uses do not call this function
1047 */
1048 void set_vertex_no_check(index_t c, index_t v) {
1049 geo_debug_assert(c < nb());
1050
3/4
✓ Branch 0 taken 1845823 times.
✓ Branch 1 taken 377336 times.
✓ Branch 2 taken 10017 times.
✗ Branch 3 not taken.
2233176 corner_vertex_[c] = v;
1051 }
1052
1053 /**
1054 * \brief Sets the facet that a corner is adjacent to
1055 * \param[in] c the corner
1056 * \param[in] f the facet that corner \p is adjacent to or
1057 * NO_FACET if \p c is on the border
1058 */
1059 void set_adjacent_facet(index_t c, index_t f) {
1060 geo_debug_assert(c < nb());
1061 geo_debug_assert(f == NO_FACET || f < facets_.nb());
1062
4/8
✓ Branch 0 taken 1230476 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 118980 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 117880 times.
✓ Branch 5 taken 1100 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
19045783 corner_adjacent_facet_[c] = f;
1063 4172985 }
1064
1065 /**
1066 * \brief Gets a pointer to the vertex that a corner is incident to
1067 * \param[in] c the corner
1068 * \return a pointer to the index of the vertex that this corner
1069 * is incident to
1070 * \note Normal uses do not call this function
1071 */
1072 index_t* vertex_index_ptr(index_t c) {
1073 geo_debug_assert(c < nb());
1074 return &(corner_vertex_[c]);
1075 }
1076
1077 /**
1078 * \brief Gets a pointer to the vertex that a corner is incident to
1079 * \param[in] c the corner
1080 * \return a pointer to the index of the vertex that this corner
1081 * is incident to
1082 * \note Normal uses do not call this function
1083 */
1084 const index_t* vertex_index_ptr(index_t c) const {
1085 geo_debug_assert(c < nb());
1086 return &(corner_vertex_[c]);
1087 }
1088
1089 /**
1090 * \brief Gets the vertex indices of all corners as a single vector.
1091 * \details On a triangulated mesh, this is the triangle list
1092 * (3 vertex indices per facet). It is forbidden to change the
1093 * size of the returned vector.
1094 * \return a const reference to the corner-to-vertex table.
1095 */
1096 const vector<index_t>& vertex_indices() const {
1097 return corner_vertex_;
1098 }
1099
1100 /**
1101 * \brief Gets the point associated with a corner
1102 * \param[in] c the corner
1103 * \return a reference to the DIM-d point associated with the corner
1104 * \pre vertices.dimension() >= DIM
1105 */
1106 template <index_t DIM=3> vecng<DIM,double>& point(index_t c) {
1107 geo_debug_assert(c < nb());
1108 return vertices_.point<DIM>(vertex(c));
1109 }
1110
1111 /**
1112 * \brief Gets the point associated with a corner
1113 * \param[in] c the corner
1114 * \return const a reference to the DIM-d point associated with
1115 * the corner
1116 * \pre vertices.dimension() >= DIM
1117 */
1118 template <index_t DIM=3> const vecng<DIM,double>& point(
1119 index_t c
1120 ) const {
1121 geo_debug_assert(c < nb());
1122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48019 times.
51003 return vertices_.point(vertex(c));
1123 }
1124
1125 protected:
1126 void clear_store(
1127 bool keep_attributes, bool keep_memory = false
1128 ) override;
1129
1130 void resize_store(index_t new_size) override;
1131
1132 4212749 index_t create_sub_element(index_t v, index_t f = NO_FACET) {
1133
2/2
✓ Branch 0 taken 4207935 times.
✓ Branch 1 taken 4814 times.
4212749 corner_vertex_.push_back(v);
1134
2/2
✓ Branch 0 taken 4207935 times.
✓ Branch 1 taken 4814 times.
4212749 corner_adjacent_facet_.push_back(f);
1135 4212749 return MeshSubElementsStore::create_sub_element();
1136 }
1137
1138 350 index_t create_sub_elements(index_t nb) {
1139
2/2
✓ Branch 0 taken 2037704 times.
✓ Branch 1 taken 350 times.
2038054 for(index_t i=0; i<nb; ++i) {
1140
2/2
✓ Branch 0 taken 2036042 times.
✓ Branch 1 taken 1662 times.
2037704 corner_vertex_.push_back(NO_VERTEX);
1141 }
1142
2/2
✓ Branch 0 taken 2037704 times.
✓ Branch 1 taken 350 times.
2038054 for(index_t i=0; i<nb; ++i) {
1143
2/2
✓ Branch 0 taken 2036042 times.
✓ Branch 1 taken 1662 times.
2037704 corner_adjacent_facet_.push_back(NO_FACET);
1144 }
1145 350 return MeshSubElementsStore::create_sub_elements(nb);
1146 }
1147
1148 61 void copy(
1149 const MeshFacetCornersStore& rhs, bool copy_attributes=true
1150 ) {
1151 61 MeshSubElementsStore::copy(rhs, copy_attributes);
1152 corner_vertex_ = rhs.corner_vertex_;
1153 corner_adjacent_facet_ = rhs.corner_adjacent_facet_;
1154 61 }
1155
1156 protected:
1157 MeshVertices& vertices_;
1158 MeshFacetsStore& facets_;
1159 vector<index_t> corner_vertex_;
1160 vector<index_t> corner_adjacent_facet_;
1161
1162 friend class MeshFacets;
1163 friend class Mesh;
1164 friend class GeogramIOHandler;
1165 };
1166
1167 /*************************************************************************/
1168
1169 /**
1170 * \brief The facets of a mesh
1171 * \relates Mesh
1172 */
1173 823 class GEOGRAM_API MeshFacets : public MeshFacetsStore, public MeshElements {
1174 public:
1175
1176 /**
1177 * \brief MeshFacets constructor
1178 * \param[in] mesh a reference to the mesh
1179 * this MeshFacets is attached to
1180 */
1181 MeshFacets(Mesh& mesh);
1182
1183 /**
1184 * \brief Gets the number of vertices of a facet
1185 * \param[in] f the facet
1186 * \return the number of vertices of facet \p f
1187 */
1188 index_t nb_vertices(index_t f) const {
1189 return nb_corners(f);
1190 }
1191
1192 /**
1193 * \brief Gets a vertex by facet and local vertex index
1194 * \param[in] f the facet
1195 * \param[in] lv the local vertex index in \p f
1196 * \return the \p lv%th vertex of facet \p f
1197 * \pre lv < nb_vertices(f)
1198 */
1199 index_t vertex(index_t f, index_t lv) const {
1200
21/42
✓ Branch 0 taken 2631028 times.
✓ Branch 1 taken 15360 times.
✓ Branch 2 taken 1383025 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 538236 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 612 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 36 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1203174 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 281685 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 10139226 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 695281 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 402906 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 61195 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1029066 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 153329 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 154550 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 162720 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 503836 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 493836 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 511795 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 620972 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1500857 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
24524261 return facet_corners_.vertex(corner(f,lv));
1201 }
1202
1203
1204 /**
1205 * \brief Gets a point by facet and local vertex index
1206 * \param[in] f the facet
1207 * \param[in] lv the local vertex index in \p f
1208 * \return a const reference to the point corresponding to
1209 * the \p lv%th vertex of facet \p f
1210 * \pre lv < nb_vertices(f)
1211 */
1212 template <index_t DIM=3> const vecng<DIM,double>& point(
1213 index_t f, index_t lv
1214 ) const {
1215
1/6
✓ Branch 0 taken 2559984 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2560372 return vertices_.point<DIM>(vertex(f,lv));
1216 }
1217
1218 /**
1219 * \brief Gets a point by facet and local vertex index
1220 * \param[in] f the facet
1221 * \param[in] lv the local vertex index in \p f
1222 * \return a reference to the point corresponding to
1223 * the \p lv%th vertex of facet \p f
1224 * \pre lv < nb_vertices(f)
1225 */
1226 template <index_t DIM=3> vecng<DIM,double>& point(
1227 index_t f, index_t lv
1228 ) {
1229
4/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1052 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 175992 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 225066 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 118536 times.
✗ Branch 9 not taken.
520646 return vertices_.point<DIM>(vertex(f,lv));
1230 }
1231
1232 /**
1233 * \brief Sets a vertex by facet and local vertex index
1234 * \param[in] f the facet
1235 * \param[in] lv the local vertex index in \p f
1236 * \param[in] v specifies the \p lv%th vertex of facet \p f
1237 * \pre lv < nb_vertices(f)
1238 */
1239 void set_vertex(index_t f, index_t lv, index_t v) {
1240
15/20
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 1184982 times.
✓ Branch 2 taken 118980 times.
✓ Branch 3 taken 20460 times.
✓ Branch 4 taken 61420 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 61420 times.
✓ Branch 7 taken 18502 times.
✓ Branch 8 taken 61612 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 394932 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 123 times.
✓ Branch 13 taken 52 times.
✓ Branch 14 taken 378759 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 160 times.
✓ Branch 18 taken 476691 times.
✓ Branch 19 taken 163652 times.
2941814 facet_corners_.set_vertex(corner(f,lv),v);
1241 }
1242
1243 /**
1244 * \brief Gets the local index of a vertex in a facet.
1245 * \param[in] f a facet
1246 * \param[in] v a vertex
1247 * \return lv such that vertex(f,lv) == v or NO_VERTE if f is
1248 * not incident to v
1249 */
1250 index_t find_vertex(index_t f, index_t v) const {
1251 for(index_t lv=0; lv<nb_vertices(f); ++lv) {
1252 if(vertex(f,lv) == v) {
1253 return lv;
1254 }
1255 }
1256 return NO_VERTEX;
1257 }
1258
1259 /**
1260 * \brief finds a common vertex shared by two facets
1261 * \param[in] f1 , f2 the two facets
1262 * \return the local index in \p f1 of a vertex present in \p f2,
1263 * or NO_VERTEX if there is no such vertex.
1264 */
1265 index_t find_common_vertex(index_t f1, index_t f2) const {
1266 for(index_t lv=0; lv<nb_vertices(f1); ++lv) {
1267 index_t v = vertex(f1,lv);
1268 if(find_vertex(f2,v) != NO_VERTEX) {
1269 return lv;
1270 }
1271 }
1272 return NO_VERTEX;
1273 }
1274
1275 /**
1276 * \brief Gets an adjacent facet by facet and local edge index
1277 * \param[in] f the facet
1278 * \param[in] le the local index of an edge in facet \p f
1279 * \return the facet incident to \p f along edge \p le or
1280 * NO_FACET if \p le is on the border
1281 */
1282 index_t adjacent(index_t f, index_t le) const {
1283
5/10
✓ Branch 0 taken 802392 times.
✓ Branch 1 taken 589416 times.
✓ Branch 2 taken 740952 times.
✓ Branch 3 taken 527976 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 675198 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
3335934 return facet_corners_.adjacent_facet(corner(f,le));
1284 }
1285
1286 /**
1287 * \brief Gets the local index of a facet adjacent to another one.
1288 * \param[in] f a facet
1289 * \param[in] f2 another facet
1290 * \return le such that adjacent(f,le) == f2 or NO_INDEX if f and f2
1291 * are not adjacent.
1292 */
1293 index_t find_adjacent(index_t f, index_t f2) const {
1294 for(index_t le=0; le<nb_vertices(f); ++le) {
1295 if(adjacent(f,le) == f2) {
1296 return le;
1297 }
1298 }
1299 return NO_INDEX;
1300 }
1301
1302 /**
1303 * \brief Sets an adjacent facet by facet and local edge index
1304 * \param[in] f the facet
1305 * \param[in] le the local index of an edge in facet \p f
1306 * \param[in] f2 specifies the facet incident to \p f along edge
1307 * \p le or NO_FACET if \p le is on the border
1308 */
1309 void set_adjacent(index_t f, index_t le, index_t f2) {
1310 facet_corners_.set_adjacent_facet(corner(f,le),f2);
1311 }
1312
1313 /**
1314 * \brief Gets the successor of a corner around a facet
1315 * \param[in] f the facet
1316 * \param[in] c the corner
1317 * \return the successor of corner \p c around facet \p f
1318 * \pre c >= corners_begin(f) && c < corners_end(f)
1319 */
1320 index_t next_corner_around_facet(index_t f, index_t c) const {
1321 geo_debug_assert(f < nb());
1322 geo_debug_assert(c >= corners_begin(f) && c < corners_end(f));
1323
20/24
✓ Branch 0 taken 1997764 times.
✓ Branch 1 taken 644206 times.
✓ Branch 2 taken 1552428 times.
✓ Branch 3 taken 3032747 times.
✓ Branch 4 taken 2353511 times.
✓ Branch 5 taken 2489254 times.
✓ Branch 6 taken 1741496 times.
✓ Branch 7 taken 1281034 times.
✓ Branch 8 taken 126906 times.
✓ Branch 9 taken 1011381 times.
✓ Branch 10 taken 4939019 times.
✓ Branch 11 taken 27049 times.
✓ Branch 12 taken 1987028 times.
✓ Branch 13 taken 3157389 times.
✓ Branch 14 taken 4573 times.
✓ Branch 15 taken 8570 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 378988 times.
✓ Branch 21 taken 469949 times.
✓ Branch 22 taken 426082 times.
✓ Branch 23 taken 852164 times.
28481538 return c + 1 == corners_end(f) ? corners_begin(f) : c + 1;
1324 }
1325
1326 /**
1327 * \brief Gets the predecessor of a corner around a facet
1328 * \param[in] f the facet
1329 * \param[in] c the corner
1330 * \return the predecessor of corner \p c around facet \p f
1331 * \pre c >= corners_begin(f) && c < corners_end(f)
1332 */
1333
2/2
✓ Branch 0 taken 39078777 times.
✓ Branch 1 taken 2260096 times.
41338873 index_t prev_corner_around_facet(index_t f, index_t c) const {
1334 geo_debug_assert(f < nb());
1335 geo_debug_assert(c >= corners_begin(f) && c < corners_end(f));
1336
2/2
✓ Branch 0 taken 7627972 times.
✓ Branch 1 taken 33710901 times.
48966845 return c == corners_begin(f) ? corners_end(f) - 1 : c - 1;
1337 }
1338
1339 /**
1340 * \brief Finds an edge by vertex indices
1341 * \param[in] f a facet
1342 * \param[in] v1 , v2 two vertex indices
1343 * \return the edge le such that vertex(f,le) = v1 and
1344 * vertex(f, (le+1)%nb_vertices(f)) == v2
1345 */
1346
1/2
✓ Branch 0 taken 370476 times.
✗ Branch 1 not taken.
370476 index_t find_edge(index_t f, index_t v1, index_t v2) const {
1347
1/2
✓ Branch 0 taken 740952 times.
✗ Branch 1 not taken.
1111428 for(index_t c1 = corners_begin(f); c1 != corners_end(f); ++c1) {
1348 index_t c2 = next_corner_around_facet(f,c1);
1349 if(
1350
3/4
✓ Branch 0 taken 370476 times.
✓ Branch 1 taken 370476 times.
✓ Branch 2 taken 370476 times.
✗ Branch 3 not taken.
740952 facet_corners_.vertex(c1) == v1 &&
1351 facet_corners_.vertex(c2) == v2
1352 ) {
1353 370476 return c1 - corners_begin(f);
1354 }
1355 }
1356 return NO_INDEX;
1357 }
1358
1359 void delete_elements(
1360 vector<index_t>& to_delete,
1361 bool remove_isolated_vertices=true
1362 ) override;
1363
1364 void permute_elements(vector<index_t>& permutation) override;
1365
1366 void clear(
1367 bool keep_attributes=true, bool keep_memory=false
1368 ) override;
1369
1370 /**
1371 * \brief Creates a contiguous chunk of facets
1372 * \param[in] nb_facets number of facets to create
1373 * \param[in] nb_vertices_per_polygon number of vertices
1374 * in each facet
1375 * \return the index of the first facet
1376 */
1377 350 index_t create_facets(
1378 index_t nb_facets, index_t nb_vertices_per_polygon
1379 ) {
1380
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 340 times.
350 if(nb_vertices_per_polygon != 3) {
1381 10 is_not_simplicial();
1382 }
1383
1384 index_t first_facet = nb();
1385 350 index_t co = facet_corners_.nb();
1386 350 facet_corners_.create_sub_elements(
1387 nb_facets*nb_vertices_per_polygon
1388 );
1389 350 index_t result = create_sub_elements(nb_facets);
1390
1391
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 340 times.
350 if(!is_simplicial_) {
1392
2/2
✓ Branch 0 taken 20688 times.
✓ Branch 1 taken 10 times.
20698 for(index_t f=first_facet; f<=first_facet+nb_facets; ++f) {
1393 20688 facet_ptr_[f] = co;
1394 20688 co += nb_vertices_per_polygon;
1395 }
1396 geo_debug_assert(facet_ptr_.size() == nb()+1);
1397 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1398 }
1399 350 return result;
1400 }
1401
1402 /**
1403 * \brief Reserves space for new facets
1404 * \param[in] nb_to_reserve the number of facets to reserve
1405 * \details Does not change size
1406 */
1407 57 void reserve(index_t nb_to_reserve) {
1408 57 facet_corners_.reserve_store(nb_to_reserve*3);
1409 57 this->reserve_store(nb_to_reserve);
1410 57 }
1411
1412 /**
1413 * \brief Creates a contiguous chunk of triangles
1414 * \param[in] nb_triangles number of triangles to create
1415 * \return the index of the first triangle
1416 */
1417 index_t create_triangles(index_t nb_triangles) {
1418
2/4
✓ Branch 1 taken 146 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
340 return create_facets(nb_triangles, 3);
1419 }
1420
1421 /**
1422 * \brief Creates a contiguous chunk of quads
1423 * \param[in] nb_quads number of quads to create
1424 * \return the index of the first quad
1425 */
1426 index_t create_quads(index_t nb_quads) {
1427
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
10 return create_facets(nb_quads, 4);
1428 }
1429
1430 /**
1431 * \brief Creates a triangle
1432 * \param[in] v1 , v2 , v3 the vertices of the triangle
1433 * \return the index of the created triangle
1434 */
1435 663932 index_t create_triangle(index_t v1, index_t v2, index_t v3) {
1436 geo_debug_assert(v1 != v2);
1437 geo_debug_assert(v2 != v3);
1438 geo_debug_assert(v3 != v1);
1439 663932 facet_corners_.create_sub_element(v1);
1440 663932 facet_corners_.create_sub_element(v2);
1441 663932 facet_corners_.create_sub_element(v3);
1442 663932 index_t result = create_sub_element();
1443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 663932 times.
663932 if(!is_simplicial_) {
1444 facet_ptr_[result+1] = facet_corners_.nb();
1445 geo_debug_assert(facet_ptr_.size() == nb()+1);
1446 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1447 }
1448 663932 return result;
1449 }
1450
1451 /**
1452 * \brief Creates a quad
1453 * \param[in] v1 , v2 , v3 , v4 the vertices of the quad
1454 * \return the index of the created quad
1455 */
1456 108 index_t create_quad(index_t v1, index_t v2, index_t v3, index_t v4) {
1457 108 is_not_simplicial();
1458 108 facet_corners_.create_sub_element(v1);
1459 108 facet_corners_.create_sub_element(v2);
1460 108 facet_corners_.create_sub_element(v3);
1461 108 facet_corners_.create_sub_element(v4);
1462 108 index_t result = create_sub_element();
1463 108 facet_ptr_[result+1] = facet_corners_.nb();
1464 geo_debug_assert(facet_ptr_.size() == nb()+1);
1465 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1466 108 return result;
1467 }
1468
1469 /**
1470 * \brief Creates a polygonal facet
1471 * \param[in] nb_vertices number of vertices of the facet
1472 * \return the index of the created facet
1473 */
1474 625975 index_t create_polygon(index_t nb_vertices) {
1475
2/2
✓ Branch 0 taken 248743 times.
✓ Branch 1 taken 377232 times.
625975 if(nb_vertices != 3) {
1476 248743 is_not_simplicial();
1477 }
1478
2/2
✓ Branch 0 taken 2220521 times.
✓ Branch 1 taken 625975 times.
2846496 for(index_t i=0; i<nb_vertices; ++i) {
1479 2220521 facet_corners_.create_sub_element(NO_VERTEX);
1480 }
1481 625975 index_t result = create_sub_element();
1482
2/2
✓ Branch 0 taken 335304 times.
✓ Branch 1 taken 290671 times.
625975 if(!is_simplicial_) {
1483 335304 facet_ptr_[result+1] = facet_corners_.nb();
1484 geo_debug_assert(facet_ptr_.size() == nb()+1);
1485 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1486 }
1487 625975 return result;
1488 }
1489
1490 /**
1491 * \brief Creates a polygonal facet
1492 * \param[in] nb_vertices number of vertices of the facet
1493 * \param[in] vertices a const pointer to the \p nb_vertices vertices
1494 * \return the index of the created facet
1495 */
1496 index_t create_polygon(index_t nb_vertices, const index_t* vertices) {
1497 if(nb_vertices != 3) {
1498 is_not_simplicial();
1499 }
1500 for(index_t i=0; i<nb_vertices; ++i) {
1501 facet_corners_.create_sub_element(vertices[i]);
1502 }
1503 index_t result = create_sub_element();
1504 if(!is_simplicial_) {
1505 facet_ptr_[result+1] = facet_corners_.nb();
1506 geo_debug_assert(facet_ptr_.size() == nb()+1);
1507 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1508 }
1509 return result;
1510 }
1511
1512 /**
1513 * \brief Creates a polygonal facet
1514 * \param[in] vertices a const reference to a vector that
1515 * contains the vertices
1516 * \return the index of the created facet
1517 */
1518 index_t create_polygon(const vector<index_t>& vertices) {
1519 return create_polygon(vertices.size(), vertices.data());
1520 }
1521
1522 /**
1523 * \brief Connects the facets
1524 * \details Finds the adjacent_facet() links based on vertex indices
1525 */
1526 void connect();
1527
1528 /**
1529 * \brief Connects a contiguous sequence of facets
1530 * \details Finds the adjacent_facet() links based on vertex indices
1531 * \param[in] facets_begin first facet to connect
1532 * \param[in] facets_end one position past the last facet to connect
1533 */
1534 void connect(index_t facets_begin, index_t facets_end);
1535
1536 /**
1537 * \brief Triangulates the facets
1538 * \note Attributes are zeroed
1539 */
1540 void triangulate();
1541
1542 /**
1543 * \brief Flips a facet
1544 * \details The order of the corners is reversed
1545 * \param[in] f the facet to be flipped
1546 */
1547 void flip(index_t f);
1548
1549 /**
1550 * \brief Replaces the edges of this mesh
1551 * with the borders of the surfacic part.
1552 */
1553 void compute_borders();
1554
1555 /**
1556 * \brief Copies a triangle mesh into this Mesh.
1557 * \details Facet adjacence are not computed.
1558 * Facet and corner attributes are zeroed.
1559 * \param[in] dim dimension of the vertices
1560 * \param[in] vertices coordinates of the vertices
1561 * \param[in] triangles facet to vertex links
1562 * \param[in] steal_args if set, vertices and triangles
1563 * are 'stolen' from the arguments
1564 * (using vector::swap).
1565 */
1566 void assign_triangle_mesh(
1567 coord_index_t dim,
1568 vector<double>& vertices,
1569 vector<index_t>& triangles,
1570 bool steal_args
1571 );
1572
1573 /*
1574 * \brief Copies a triangle mesh into this Mesh.
1575 * \details Facet adjacence are not computed.
1576 * Facet and corner attributes are zeroed.
1577 * \param[in] triangles facet to vertex links
1578 * \param[in] steal_args if set, vertices and triangles
1579 * are 'stolen' from the arguments
1580 * (using vector::swap).
1581 */
1582 void assign_triangle_mesh(
1583 vector<index_t>& triangles,
1584 bool steal_args
1585 );
1586
1587 void pop() override;
1588
1589 /**
1590 * \brief Gets the corners of a facet.
1591 * \param[in] f the index of the facet.
1592 * \return a range with all the corners of the facet.
1593 */
1594 index_range corners(index_t f) const {
1595 geo_debug_assert(f < nb());
1596 return index_range(
1597 index_as_iterator(corners_begin(f)),
1598 index_as_iterator(corners_end(f))
1599 );
1600 }
1601
1602 #ifndef MESH_NO_SYNTAXIC_SUGAR
1603
1604 /**
1605 * \brief Gets the vertices of a facet.
1606 * \param[in] f the index of the facet.
1607 * \return a range with all the vertices indices of the facet.
1608 */
1609
1/2
✓ Branch 0 taken 4174 times.
✗ Branch 1 not taken.
4174 auto vertices(index_t f) const {
1610 geo_debug_assert(f < nb());
1611 return transform_range(
1612 corners(f), [this](index_t c)->index_t {
1613
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12522 return facet_corners_.vertex(c);
1614 }
1615 4174 );
1616 }
1617
1618 /**
1619 * \brief Gets the facets adjacent to a given facet.
1620 * \param[in] f the index of the facet.
1621 * \return a range with all the indices of the facets adjacent to this
1622 * facet. It will output exactly one item per edge of the facet. Edges
1623 * on the border will output NO_INDEX (no adjacent facet).
1624 */
1625
2/2
✓ Branch 0 taken 2402645 times.
✓ Branch 1 taken 232546 times.
2635191 auto adjacent(index_t f) const {
1626 geo_debug_assert(f < nb());
1627 return transform_range(
1628 corners(f), [this](index_t c)->index_t {
1629
5/6
✓ Branch 0 taken 2899586 times.
✓ Branch 1 taken 166384 times.
✓ Branch 2 taken 5058751 times.
✓ Branch 3 taken 25340 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 555 times.
8150616 return facet_corners_.adjacent_facet(c);
1630 }
1631 2635191 );
1632 }
1633
1634 /**
1635 * \brief Gets the points associated with the vertices of a facet.
1636 * \param[in] f the index of the facet.
1637 * \return a range with the points that correspond to the vertices of
1638 * the facet, returned as const references.
1639 */
1640 template <index_t DIM=3> auto points(index_t f) const {
1641 geo_debug_assert(f < nb());
1642 typedef vecng<DIM,double> vecn;
1643 return transform_range_ref(
1644 corners(f), [this](index_t c)->const vecn& {
1645 index_t v = facet_corners_.vertex(c);
1646 return vertices_.point<DIM>(v);
1647 }
1648 );
1649 }
1650
1651 /**
1652 * \brief Gets the points associated with the vertices of a facet.
1653 * \param[in] f the index of the facet.
1654 * \return a range with the points that correspond to the vertices of
1655 * the facet, returned as modifiable references.
1656 */
1657
2/2
✓ Branch 0 taken 204556 times.
✓ Branch 1 taken 178 times.
409468 template <index_t DIM=3> auto points(index_t f) {
1658 geo_debug_assert(f < nb());
1659 typedef vecng<DIM,double> vecn;
1660 return transform_range_ref(
1661 corners(f), [this](index_t c)->vecn& {
1662 614380 index_t v = facet_corners_.vertex(c);
1663 614380 return vertices_.point<DIM>(v);
1664 }
1665 409468 );
1666 }
1667
1668 /**
1669 * \brief Decomposes a facet into triangles
1670 * \param[in] f the index of the facet.
1671 * \return a range with a decomposition of the facet into triangles,
1672 * returned as std::tuple<index_t, index_t, index_t>
1673 */
1674 3968424 auto triangles(index_t f) const {
1675 geo_debug_assert(f < nb());
1676
2/2
✓ Branch 0 taken 3952344 times.
✓ Branch 1 taken 16080 times.
3968424 index_t v0 = facet_corners_.vertex(corners_begin(f));
1677 return transform_range(
1678 index_range(
1679 3968424 index_as_iterator(corners_begin(f)+1),
1680 3968424 index_as_iterator(corners_end(f)-1)
1681 ),
1682 [this,v0](index_t c)->std::tuple<index_t, index_t, index_t> {
1683 return std::make_tuple(
1684 v0,
1685 facet_corners_.vertex(c),
1686 1466937 facet_corners_.vertex(c+1)
1687 );
1688 }
1689 3968424 );
1690 }
1691
1692 /**
1693 * \brief Decomposes a facet into triangles
1694 * \param[in] f the index of the facet.
1695 * \return a range with a decomposition of the facet into triangles,
1696 * returned as std::tuple<const vecn&, const vecn&, const vecn&>
1697 * where vecn can be vec2, vec3, vec4 ... depending on the DIM
1698 * template argument
1699 */
1700 template <index_t DIM=3> auto triangle_points(index_t f) const {
1701 geo_debug_assert(f < nb());
1702 typedef vecng<DIM,double> vecn;
1703 return transform_range(
1704 3429728 triangles(f),
1705 [this](std::tuple<index_t, index_t, index_t> T)
1706 ->std::tuple<const vecn&, const vecn&, const vecn&> {
1707 return std::tuple<const vecn&, const vecn&, const vecn&>(
1708 vertices_.point<DIM>(std::get<0>(T)),
1709 vertices_.point<DIM>(std::get<1>(T)),
1710 3445088 vertices_.point<DIM>(std::get<2>(T))
1711 3445088 );
1712 }
1713 );
1714 }
1715
1716 /**
1717 * \brief Decomposes a facet into triangles
1718 * \param[in] f the index of the facet.
1719 * \return a range with a decomposition of the facet into triangles,
1720 * returned as std::tuple<vecn&, vecn&, vecn&>
1721 * where vecn can be vec2, vec3, vec4 ... depending on the DIM
1722 * template argument
1723 */
1724 template <index_t DIM=3> auto triangle_points(index_t f) {
1725 geo_debug_assert(f < nb());
1726 typedef vecng<DIM,double> vecn;
1727 return transform_range(
1728 48568 triangles(f),
1729 [this](std::tuple<index_t, index_t, index_t> T)
1730 ->std::tuple<vecn&, vecn&, vecn&> {
1731 return std::tuple<vecn&, vecn&, vecn&>(
1732 vertices_.point(std::get<0>(T)),
1733 vertices_.point(std::get<1>(T)),
1734 48568 vertices_.point(std::get<2>(T))
1735 48568 );
1736 }
1737 );
1738 }
1739
1740 #endif
1741
1742 protected:
1743
1744 /**
1745 * \brief Indicates that the stored elements are only triangles.
1746 */
1747 void is_simplicial() {
1748
4/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 526 times.
582 if(!is_simplicial_) {
1749 43 is_simplicial_ = true;
1750
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
43 facet_ptr_.resize(1);
1751 43 facet_ptr_[0] = 0;
1752 }
1753 }
1754
1755 /**
1756 * \brief Indicates that the stored elements are no
1757 * longer only triangles.
1758 * \details Creates the facet pointers for the pre-existing
1759 * triangles if any.
1760 */
1761 248861 void is_not_simplicial() {
1762
2/2
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 248719 times.
248861 if(is_simplicial_) {
1763 142 is_simplicial_ = false;
1764 142 facet_ptr_.resize(nb()+1);
1765
2/2
✓ Branch 0 taken 186 times.
✓ Branch 1 taken 142 times.
470 for(index_t f=0; f<facet_ptr_.size(); ++f) {
1766 186 facet_ptr_[f] = 3*f;
1767 }
1768 }
1769 248861 }
1770
1771 protected:
1772 MeshVertices& vertices_;
1773 MeshFacetCornersStore& facet_corners_;
1774 friend class Mesh;
1775 friend class GeogramIOHandler;
1776 friend void GEOGRAM_API tessellate_facets(
1777 Mesh& M, index_t max_nb_vertices
1778 );
1779 };
1780
1781 /*************************************************************************/
1782
1783 enum MeshCellType {
1784 MESH_TET = 0,
1785 MESH_HEX = 1,
1786 MESH_PRISM = 2,
1787 MESH_PYRAMID = 3,
1788 MESH_CONNECTOR = 4,
1789 MESH_NB_CELL_TYPES = 5
1790 };
1791
1792 /**
1793 * \brief Lookup tables that describe the combinatorics
1794 * of each cell type.
1795 * \relates MeshCells
1796 */
1797 struct CellDescriptor {
1798 /** Number of vertices */
1799 index_t nb_vertices;
1800
1801 /** Number of facets */
1802 index_t nb_facets;
1803
1804 /** Number of vertices in each facet */
1805 index_t nb_vertices_in_facet[6];
1806
1807 /**
1808 * Cell vertex index by (facet index,facet vertex index).
1809 */
1810 index_t facet_vertex[6][4];
1811
1812 /**
1813 * Number of edges */
1814 index_t nb_edges;
1815
1816 /**
1817 * Cell vertex index by (edge index, edge vertex index).
1818 */
1819 index_t edge_vertex[12][2];
1820
1821 /**
1822 * Cell facet index by (edge index, adjacent facet index).
1823 */
1824 index_t edge_adjacent_facet[12][2];
1825 };
1826
1827
1828 /**
1829 * \brief Gathers declarations of global cell descriptors.
1830 * \details Cannot be declared as static variables in
1831 * MeshCellsStore, since visual C++ does not allows
1832 * exporting class static variables from a DLL.
1833 */
1834 namespace MeshCellDescriptors {
1835 /**
1836 * \brief Maps a cell type to the associated cell descriptor.
1837 */
1838 GEOGRAM_API extern CellDescriptor*
1839 cell_type_to_cell_descriptor[GEO::MESH_NB_CELL_TYPES];
1840
1841 GEOGRAM_API extern CellDescriptor tet_descriptor;
1842 GEOGRAM_API extern CellDescriptor hex_descriptor;
1843 GEOGRAM_API extern CellDescriptor prism_descriptor;
1844 GEOGRAM_API extern CellDescriptor pyramid_descriptor;
1845 GEOGRAM_API extern CellDescriptor connector_descriptor;
1846 }
1847
1848 /**
1849 * \brief Stores the cells of a mesh (low-level store)
1850 * \relates MeshCells
1851 */
1852 class GEOGRAM_API MeshCellsStore : public MeshSubElementsStore {
1853 public:
1854 MeshCellsStore(Mesh& mesh);
1855
1856 /**
1857 * \brief Tests whether all the cells are tetrahedra
1858 * \details Storage and access are optimized when all the
1859 * cells are tetrahedra
1860 * \retval true if all the cells are tetrahedra
1861 * \retval false otherwise
1862 */
1863 bool are_simplices() const {
1864
3/6
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
17 return is_simplicial_;
1865 }
1866
1867 /**
1868 * \brief Gets the type of a cell
1869 * \param[in] c the cell, in 0..nb()-1
1870 * \return one of
1871 * MESH_TET, MESH_HEX, MESH_PRISM, MESH_PYRAMID, MESH_CONNECTOR.
1872 */
1873 MeshCellType type(index_t c) const {
1874 geo_debug_assert(c < nb());
1875
2/47
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 12093 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 12093 times.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
24186 return is_simplicial_ ? MESH_TET : MeshCellType(cell_type_[c]);
1876 }
1877
1878 /**
1879 * \brief Gets the descriptor of a cell
1880 * \details The descriptor of a cell is a set of static
1881 * arrays that facilitate some accesses (most client
1882 * code do not need to use this function)
1883 * \param[in] c a cell, in 0..nb()-1
1884 * \return the descriptor of cell \p c
1885 */
1886 const CellDescriptor& descriptor(index_t c) const;
1887
1888 /**
1889 * \brief Gets a descriptor by cell type
1890 * \details The descriptor of a cell is a set of static
1891 * arrays that facilitate some accesses (most client
1892 * code do not need to use this function)
1893 * \param[in] t one of
1894 * MESH_TET, MESH_HEX, MESH_PRISM, MESH_PYRAMID, MESH_CONNECTOR
1895 * \return the descriptor of cell \p c
1896 */
1897 static const CellDescriptor& cell_type_to_cell_descriptor(
1898 MeshCellType t
1899 );
1900
1901 /**
1902 * \brief Gets the number of corners of a cell
1903 * \param[in] c a cell, in 0..nb()-1
1904 * \return the number of corners of cell \p c
1905 */
1906 index_t nb_corners(index_t c) const {
1907 geo_debug_assert(c < nb());
1908 return descriptor(c).nb_vertices;
1909 }
1910
1911 /**
1912 * \brief Gets the first element for iterating over
1913 * the corners of a cell
1914 * \param[in] c the cell, in 0..nb()-1
1915 * \return the first corner of the cell
1916 */
1917 index_t corners_begin(index_t c) const {
1918 geo_debug_assert(c < nb());
1919
0/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
575669 return is_simplicial_ ? 4*c : cell_ptr_[c];
1920 }
1921
1922 /**
1923 * \brief Gets the upper limit for iterating over the
1924 * corners of a cell
1925 * \param[in] c the cell, in 0..nb()-1
1926 * \return one position past the last corner of the cell
1927 */
1928 index_t corners_end(index_t c) const {
1929 geo_debug_assert(c < nb());
1930 return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_corners(c);
1931 }
1932
1933 /**
1934 * \brief Gets a corner of a cell by local vertex index
1935 * \param[in] c the cell, in 0..nb()-1
1936 * \param[in] lv the local vertex index, in 0..nb_corners(c)-1
1937 * \return the corner incident to vertex \p lv in cell \p c
1938 */
1939 index_t corner(index_t c, index_t lv) const {
1940 geo_debug_assert(c < nb());
1941 // There seems to be a linkage problem under MSVC for the
1942 // following assertion check...
1943 #ifndef GEO_OS_WINDOWS
1944 geo_debug_assert(lv < nb_corners(c));
1945 #endif
1946
0/20
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
424913 return corners_begin(c) + lv;
1947 }
1948
1949 /**
1950 * \brief Gets the number of facets of a cell
1951 * \param[in] c the cell, in 0..nb()-1
1952 * \return the number of facets of cell \p c
1953 */
1954 index_t nb_facets(index_t c) const {
1955 geo_debug_assert(c < nb());
1956 return descriptor(c).nb_facets;
1957 }
1958
1959 /**
1960 * \brief Gets the first element for iterating over
1961 * the facets of a cell
1962 * \param[in] c the cell, in 0..nb()-1
1963 * \return the first facet of the cell
1964 */
1965 index_t facets_begin(index_t c) const {
1966 geo_debug_assert(c < nb());
1967
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
220364 return is_simplicial_ ? 4*c : cell_ptr_[c];
1968 }
1969
1970 /**
1971 * \brief Gets the upper limit for iterating over the
1972 * facets of a cell
1973 * \param[in] c the cell, in 0..nb()-1
1974 * \return one position past the last facet of the facet
1975 */
1976 index_t facets_end(index_t c) const {
1977 geo_debug_assert(c < nb());
1978 return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_facets(c);
1979 }
1980
1981 /**
1982 * \brief Gets a facet of a cell by local facet index
1983 * \param[in] c the cell, in 0..nb()-1
1984 * \param[in] lf the local facet index, in 0..nb_facets(c)-1
1985 * \return the facet \p lf in cell \p c
1986 */
1987 index_t facet(index_t c, index_t lf) const {
1988 geo_debug_assert(c < nb());
1989 geo_debug_assert(lf < nb_facets(c));
1990
5/24
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 4768 times.
✓ Branch 3 taken 43516 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 49596 times.
✓ Branch 21 taken 40828 times.
✓ Branch 22 taken 40828 times.
✗ Branch 23 not taken.
220364 return facets_begin(c) + lf;
1991 }
1992
1993 /**
1994 * \brief Gets the number of edges in a cell
1995 * \param[in] c the cell, in 0..nb()-1
1996 * \return the number of edges in cell \p c
1997 */
1998 index_t nb_edges(index_t c) const {
1999 return descriptor(c).nb_edges;
2000 }
2001
2002 /**
2003 * \brief Gets a pointer to a cell pointer index by cell index
2004 * \param[in] c cell index
2005 * \return a pointer to the cell pointer index
2006 * \note Normal uses do not call this function
2007 */
2008 index_t* cell_ptr_ptr(index_t c) {
2009 geo_debug_assert(!is_simplicial_);
2010 return &cell_ptr_[c];
2011 }
2012
2013 /**
2014 * \brief Gets a pointer to a cell pointer index by cell index
2015 * \param[in] c cell index
2016 * \return a pointer to the cell pointer index
2017 * \note Normal uses do not call this function
2018 */
2019 const index_t* cell_ptr_ptr(index_t c) const {
2020 geo_debug_assert(!is_simplicial_);
2021 return &cell_ptr_[c];
2022 }
2023
2024 /**
2025 * \brief Gets a pointer to a cell type by cell index
2026 * \param[in] c cell index
2027 * \return a pointer to the cell type
2028 * \note Normal uses do not call this function
2029 */
2030 Numeric::uint8* cell_type_ptr(index_t c) {
2031 geo_debug_assert(!is_simplicial_);
2032 return &cell_type_[c];
2033 }
2034
2035 /**
2036 * \brief Gets a pointer to a cell type by cell index
2037 * \param[in] c cell index
2038 * \return a const pointer to the cell type
2039 * \note Normal uses do not call this function
2040 */
2041 const Numeric::uint8* cell_type_ptr(index_t c) const {
2042 geo_debug_assert(!is_simplicial_);
2043 return &cell_type_[c];
2044 }
2045
2046
2047 protected:
2048 void clear_store(
2049 bool keep_attributes, bool keep_memory = false
2050 ) override;
2051
2052 void resize_store(index_t new_size) override;
2053
2054 index_t create_sub_element(MeshCellType type) {
2055 if(!is_simplicial_) {
2056 cell_ptr_.push_back(NO_CORNER);
2057 cell_type_.push_back(Numeric::uint8(type));
2058 }
2059 return MeshSubElementsStore::create_sub_element();
2060 }
2061
2062 5 index_t create_sub_elements(index_t nb, MeshCellType type) {
2063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(!is_simplicial_) {
2064 for(index_t i=0; i<nb; ++i) {
2065 cell_ptr_.push_back(NO_CORNER);
2066 cell_type_.push_back(Numeric::uint8(type));
2067 }
2068 }
2069 5 return MeshSubElementsStore::create_sub_elements(nb);
2070 }
2071
2072 61 void copy(
2073 const MeshCellsStore& rhs, bool copy_attributes=true
2074 ) {
2075 61 MeshSubElementsStore::copy(rhs, copy_attributes);
2076 61 is_simplicial_ = rhs.is_simplicial_;
2077 cell_type_ = rhs.cell_type_;
2078 cell_ptr_ = rhs.cell_ptr_;
2079 61 }
2080
2081 protected:
2082 bool is_simplicial_;
2083 vector<Numeric::uint8> cell_type_;
2084 vector<index_t> cell_ptr_;
2085
2086 protected:
2087 friend class Mesh;
2088 friend class GeogramIOHandler;
2089 };
2090
2091 /*************************************************************************/
2092
2093 /**
2094 * \brief Stores the cell corners of a mesh (low-level store)
2095 * \relates MeshCells
2096 */
2097 class GEOGRAM_API MeshCellCornersStore : public MeshSubElementsStore {
2098 public:
2099 MeshCellCornersStore(Mesh& mesh);
2100
2101 /**
2102 * \brief Gets the vertex that a corner is incident to
2103 * \param[in] c the corner, in 0..nb()-1
2104 * \return the vertex that corner \p c is incident to
2105 */
2106 index_t vertex(index_t c) const {
2107 geo_debug_assert(c < nb());
2108
5/23
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6144 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 300 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 300 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 300 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 300 times.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
388741 return corner_vertex_[c];
2109 }
2110
2111 /**
2112 * \brief Sets the vertex that a corner is incident to
2113 * \param[in] c the corner, in 0..nb()-1
2114 * \param[in] v specifies the vertex that corner \p c is incident to
2115 */
2116 void set_vertex(index_t c, index_t v) {
2117 geo_debug_assert(c < nb());
2118 geo_debug_assert(v < vertices_.nb());
2119
0/14
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
54428 corner_vertex_[c] = v;
2120 6144 }
2121
2122 /**
2123 * \brief Gets a pointer to the vertex that a corner is incident to
2124 * \param[in] c the corner
2125 * \return a pointer to the index of the vertex that this corner
2126 * is incident to
2127 * \note Normal uses do not call this function
2128 */
2129 index_t* vertex_index_ptr(index_t c) {
2130 geo_debug_assert(c < nb());
2131 return &(corner_vertex_[c]);
2132 }
2133
2134 /**
2135 * \brief Gets a pointer to the vertex that a corner is incident to
2136 * \param[in] c the corner
2137 * \return a const pointer to the index of the vertex that this corner
2138 * is incident to
2139 * \note Normal uses do not call this function
2140 */
2141 const index_t* vertex_index_ptr(index_t c) const {
2142 geo_debug_assert(c < nb());
2143 return &(corner_vertex_[c]);
2144 }
2145
2146 /**
2147 * \brief Gets the point associated with a corner
2148 * \param[in] c the corner
2149 * \return a reference to the DIM-d point associated with the corner
2150 * \pre vertices.dimension() >= DIM
2151 */
2152 template <index_t DIM=3> vecng<DIM,double>& point(index_t c) {
2153 geo_debug_assert(c < nb());
2154 return vertices_.point<DIM>(vertex(c));
2155 }
2156
2157 /**
2158 * \brief Gets the point associated with a corner
2159 * \param[in] c the corner
2160 * \return const a reference to the DIM-d point associated with
2161 * the corner
2162 * \pre vertices.dimension() >= DIM
2163 */
2164 template <index_t DIM=3> const vecng<DIM,double>& point(
2165 index_t c
2166 ) const {
2167 geo_debug_assert(c < nb());
2168 return vertices_.point(vertex(c));
2169 }
2170
2171 protected:
2172 void clear_store(
2173 bool keep_attributes, bool keep_memory = false
2174 ) override;
2175
2176 void resize_store(index_t new_size) override;
2177
2178 index_t create_sub_element(index_t v) {
2179 corner_vertex_.push_back(v);
2180 return MeshSubElementsStore::create_sub_element();
2181 }
2182
2183 5 index_t create_sub_elements(index_t nb) {
2184
2/2
✓ Branch 0 taken 48284 times.
✓ Branch 1 taken 5 times.
48289 for(index_t i=0; i<nb; ++i) {
2185
2/2
✓ Branch 0 taken 48219 times.
✓ Branch 1 taken 65 times.
48284 corner_vertex_.push_back(NO_VERTEX);
2186 }
2187 5 return MeshSubElementsStore::create_sub_elements(nb);
2188 }
2189
2190 void copy(
2191 const MeshCellCornersStore& rhs, bool copy_attributes=true
2192 ) {
2193 61 MeshSubElementsStore::copy(rhs, copy_attributes);
2194 corner_vertex_ = rhs.corner_vertex_;
2195 }
2196
2197 protected:
2198 MeshVertices& vertices_;
2199 vector<index_t> corner_vertex_;
2200
2201 friend class MeshCells;
2202 friend class Mesh;
2203 friend class GeogramIOHandler;
2204 };
2205
2206 /*************************************************************************/
2207
2208 /**
2209 * \brief Stores the cell facets of a mesh (low-level store)
2210 * \relates MeshCells
2211 */
2212 class GEOGRAM_API MeshCellFacetsStore : public MeshSubElementsStore {
2213 public:
2214 /**
2215 * \brief MeshCellFacetsStore constructor
2216 * \param[in] mesh the mesh that this MeshCellFacetsStore is attached to
2217 */
2218 MeshCellFacetsStore(Mesh& mesh);
2219
2220 /**
2221 * \brief Gets a cell adjacent to a facet
2222 * \param[in] f the facet, in 0..nb()-1
2223 * \return the cell adjacent to facet \p f, or NO_FACET if \p f
2224 * is on the border
2225 */
2226 index_t adjacent_cell(index_t f) const {
2227 geo_debug_assert(f < nb());
2228
4/16
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 4768 times.
✓ Branch 3 taken 43516 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 49596 times.
✓ Branch 15 taken 40828 times.
138708 return adjacent_cell_[f];
2229 }
2230
2231 /**
2232 * \brief Sets a cell adjacent to a facet
2233 * \param[in] f the facet, in 0..nb()-1
2234 * \param[in] c specifies the cell adjacent
2235 * to facet \p f, or is set to NO_FACET
2236 * if \p f is on the border
2237 */
2238 void set_adjacent_cell(index_t f, index_t c) {
2239 geo_debug_assert(f < nb());
2240 geo_debug_assert(c == NO_CELL || c < cells_.nb());
2241
1/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 40828 times.
✗ Branch 7 not taken.
131252 adjacent_cell_[f] = c;
2242 }
2243
2244 /**
2245 * \brief Gets a const pointer to a cell adjacent to a facet
2246 * \param[in] f the facet, in 0..nb()-1
2247 * \return a const pointer to the cell adjacent to facet \p f,
2248 * or NO_FACET if \p f is on the border
2249 */
2250 const index_t* adjacent_cell_ptr(index_t f) const {
2251 geo_debug_assert(f < nb());
2252 return &adjacent_cell_[f];
2253 }
2254
2255 /**
2256 * \brief Gets a pointer to a cell adjacent to a facet
2257 * \param[in] f the facet, in 0..nb()-1
2258 * \return a pointer to the cell adjacent to facet \p f,
2259 * or NO_FACET if \p f is on the border
2260 */
2261 index_t* adjacent_cell_ptr(index_t f) {
2262 geo_debug_assert(f < nb());
2263 return &adjacent_cell_[f];
2264 }
2265
2266 protected:
2267 void clear_store(
2268 bool keep_attributes, bool keep_memory = false
2269 ) override;
2270
2271 void resize_store(index_t new_size) override;
2272
2273 index_t create_sub_element(index_t c = NO_CELL) {
2274 adjacent_cell_.push_back(c);
2275 return MeshSubElementsStore::create_sub_element();
2276 }
2277
2278 5 index_t create_sub_elements(index_t nb) {
2279
2/2
✓ Branch 0 taken 48284 times.
✓ Branch 1 taken 5 times.
48289 for(index_t i=0; i<nb; ++i) {
2280
2/2
✓ Branch 0 taken 48219 times.
✓ Branch 1 taken 65 times.
48284 adjacent_cell_.push_back(NO_CELL);
2281 }
2282 5 return MeshSubElementsStore::create_sub_elements(nb);
2283 }
2284
2285 void copy(
2286 const MeshCellFacetsStore& rhs, bool copy_attributes=true
2287 ) {
2288 61 MeshSubElementsStore::copy(rhs, copy_attributes);
2289 adjacent_cell_ = rhs.adjacent_cell_;
2290 61 }
2291
2292 protected:
2293 MeshVertices& vertices_;
2294 MeshCellsStore& cells_;
2295 vector<index_t> adjacent_cell_;
2296
2297 friend class MeshCells;
2298 friend class Mesh;
2299 friend class GeogramIOHandler;
2300 };
2301
2302 /*************************************************************************/
2303
2304 /**
2305 * \brief The cells of a mesh.
2306 * \relates Mesh
2307 */
2308 823 class GEOGRAM_API MeshCells : public MeshCellsStore, public MeshElements {
2309 public:
2310 /**
2311 * \brief MeshCells constructor
2312 * \param[in] mesh the mesh this MeshCells is attached to
2313 */
2314 MeshCells(Mesh& mesh);
2315
2316 /**
2317 * \brief Gets the number of vertices of a cell
2318 * \param[in] c a cell, in 0..nb()-1
2319 * \return the number of vertices of cell \p c
2320 */
2321 index_t nb_vertices(index_t c) const {
2322 return nb_corners(c);
2323 }
2324
2325 /**
2326 * \brief Gets a vertex of a cell by local vertex index
2327 * \param[in] c the cell, in 0..nb()-1
2328 * \param[in] lv local vertex index, in 0..nb_vertices(c)-1
2329 * \return the vertex \p lv of cell \p c
2330 */
2331 index_t vertex(index_t c, index_t lv) const {
2332
9/28
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 90424 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 93376 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 93216 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 85216 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 12093 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 300 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 300 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 300 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 300 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
375525 return cell_corners_.vertex(corner(c,lv));
2333 }
2334
2335 /**
2336 * \brief Sets a vertex of a cell by local vertex index
2337 * \param[in] c the cell, in 0..nb()-1
2338 * \param[in] lv local vertex index, in 0..nb_vertices(c)-1
2339 * \param[in] v specifies the vertex \p lv of cell \p c
2340 */
2341 void set_vertex(index_t c, index_t lv, index_t v) {
2342
2/18
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 6144 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 42140 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
48284 cell_corners_.set_vertex(corner(c,lv),v);
2343 }
2344
2345 /**
2346 * \brief Gets a point by cell and local vertex index
2347 * \param[in] c the cell
2348 * \param[in] lv the local vertex index in \p c
2349 * \return a const reference to the point corresponding to
2350 * the \p lv%th vertex of cell \p c
2351 * \pre lv < nb_vertices(c)
2352 */
2353 template <index_t DIM=3> const vecng<DIM,double>& point(
2354 index_t c, index_t lv
2355 ) const {
2356
4/14
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 768 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 768 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 768 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 768 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
3072 return vertices_.point<DIM>(vertex(c,lv));
2357 }
2358
2359 /**
2360 * \brief Gets a point by cell and local vertex index
2361 * \param[in] c the cell
2362 * \param[in] lv the local vertex index in \p c
2363 * \return a reference to the point corresponding to
2364 * the \p lv%th vertex of cell \p c
2365 * \pre lv < nb_vertices(c)
2366 */
2367 template <index_t DIM=3> vecng<DIM,double>& point(
2368 index_t c, index_t lv
2369 ) {
2370 return vertices_.point<DIM>(vertex(c,lv));
2371 }
2372
2373 /**
2374 * \brief Gets a cell adjacent to another one by local facet index
2375 * \param[in] c the cell, in 0..nb()-1
2376 * \param[in] lf local facet index, in 0..nb_facets(c)-1
2377 * \return the cell adjacent to \p c along facet \p lf or NO_CELL
2378 * if no such cell exists
2379 */
2380 index_t adjacent(index_t c, index_t lf) const {
2381
2/14
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 48284 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 90424 times.
✗ Branch 13 not taken.
138708 return cell_facets_.adjacent_cell(facet(c,lf));
2382 }
2383
2384 /**
2385 * \brief Sets a cell adjacent to another one by local facet index
2386 * \param[in] c the cell, in 0..nb()-1
2387 * \param[in] lf local facet index, in 0..nb_facets(c)-1
2388 * \param[in] c2 specifies the cell adjacent to \p c along
2389 * facet \p lf or NO_CELL if no such cell exists
2390 */
2391 void set_adjacent(index_t c, index_t lf, index_t c2) {
2392
1/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 40828 times.
✗ Branch 5 not taken.
40828 cell_facets_.set_adjacent_cell(facet(c,lf),c2);
2393 40828 }
2394
2395 /**
2396 * \brief Gets the number of vertices in a cell facet
2397 * \param[in] c the cell, in 0..nb()-1
2398 * \param[in] lf the local facet index, in 0..nb_facets(c)-1
2399 * \return the number of vertices of facet \p lf in cell \p c
2400 */
2401 index_t facet_nb_vertices(index_t c, index_t lf) const {
2402 geo_debug_assert(lf < nb_facets(c));
2403 return descriptor(c).nb_vertices_in_facet[lf];
2404 }
2405
2406 /**
2407 * \brief Gets a vertex of a cell by local facet index and
2408 * local vertex index in the facet
2409 * \param[in] c the cell, in 0..nb()-1
2410 * \param[in] lf the local facet index, in 0..nb_facets(c)-1
2411 * \param[in] lv the local vertex index, in 0..facet_nb_vertices(c,lf)-1
2412 * \return vertex \p lv of facet \p lf in cell \p c
2413 */
2414 148788 index_t facet_vertex(index_t c, index_t lf, index_t lv) const {
2415 geo_debug_assert(lv < facet_nb_vertices(c, lf));
2416 148788 return cell_corners_.vertex(
2417
1/2
✓ Branch 1 taken 148788 times.
✗ Branch 2 not taken.
148788 corner(c, descriptor(c).facet_vertex[lf][lv])
2418 148788 );
2419 }
2420 /**
2421 * \brief Gets a corner of a cell by local facet index and
2422 * local corner index in the facet
2423 * \param[in] c the cell, in 0..nb()-1
2424 * \param[in] lf the local facet index, in 0..nb_facets(c)-1
2425 * \param[in] lc the local corner index, in 0..facet_nb_vertices(c,lf)-1
2426 * \return corner \p lc of facet \p lf in cell \p c
2427 */
2428 index_t facet_corner(index_t c, index_t lf, index_t lc) const {
2429 geo_debug_assert(lc < facet_nb_vertices(c, lf));
2430 return corner(c, descriptor(c).facet_vertex[lf][lc]);
2431 }
2432
2433 /**
2434 * \brief Gets a cell vertex by local edge index and local
2435 * vertex index in the edge
2436 * \param[in] c the cell, in 0..nb()-1
2437 * \param[in] le the local edge index, in 0..nb_edges(c)-1
2438 * \param[in] lv the local index in the edge, one of 0,1
2439 * \return vertex \p lv of edge \p le in cell \p c
2440 */
2441 index_t edge_vertex(index_t c, index_t le, index_t lv) const {
2442 geo_debug_assert(le < nb_edges(c));
2443 geo_debug_assert(lv < 2);
2444 return cell_corners_.vertex(
2445 corner(c,descriptor(c).edge_vertex[le][lv])
2446 );
2447 }
2448
2449 /**
2450 * \brief Gets a cell local facet index by local edge index and local
2451 * facet index in the edge
2452 * \param[in] c the cell, in 0..nb()-1
2453 * \param[in] le the local edge index, in 0..nb_edges(c)-1
2454 * \param[in] lf the local index in the edge, one of 0,1
2455 * \return the local facet index of the facet adjacent to the edge.
2456 * - If \p lf=0, it gets the facet on the left of the oriented edge.
2457 * - If \p lf=1, it gets the facet on the right of the oriented edge.
2458 */
2459 index_t edge_adjacent_facet(index_t c, index_t le, index_t lf) const {
2460 geo_debug_assert(le < nb_edges(c));
2461 geo_debug_assert(lf < 2);
2462 return descriptor(c).edge_adjacent_facet[le][lf];
2463 }
2464
2465 /**
2466 * \brief Gets the corners of a cell.
2467 * \param[in] c the index of the cell.
2468 * \return a range with all the corners of the facet.
2469 */
2470 index_range corners(index_t c) const {
2471 geo_debug_assert(c < nb());
2472 return index_range(
2473 index_as_iterator(corners_begin(c)),
2474 index_as_iterator(corners_end(c))
2475 );
2476 }
2477
2478 /**
2479 * \brief Gets the facets of a cell.
2480 * \param[in] c the index of the cell.
2481 * \return a range with all the global indices of the cell facets.
2482 */
2483 index_range facets(index_t c) const {
2484 geo_debug_assert(c < nb());
2485 return index_range(
2486 index_as_iterator(facets_begin(c)),
2487 index_as_iterator(facets_end(c))
2488 );
2489 }
2490
2491 #ifndef MESH_NO_SYNTAXIC_SUGAR
2492
2493 /**
2494 * \brief Gets the points associated with the vertices of a cell.
2495 * \param[in] cell the index of the cell.
2496 * \return a range with the points that correspond to the vertices of
2497 * the cell, returned as const references.
2498 */
2499 template <index_t DIM=3> auto points(index_t cell) const {
2500 geo_debug_assert(cell < nb());
2501 typedef vecng<DIM,double> vecn;
2502 return transform_range_ref(
2503 corners(cell), [this](index_t c)->const vecn& {
2504 index_t v = cell_corners_.vertex(c);
2505 return vertices_.point<DIM>(v);
2506 }
2507 );
2508 }
2509
2510 /**
2511 * \brief Gets the points associated with the vertices of a cell.
2512 * \param[in] cell the index of the cell.
2513 * \return a range with the points that correspond to the vertices of
2514 * the cell, returned as modifiable references.
2515 */
2516 template <index_t DIM=3> auto points(index_t cell) {
2517 geo_debug_assert(cell < nb());
2518 typedef vecng<DIM,double> vecn;
2519 return transform_range_ref(
2520 corners(cell), [this](index_t c)->vecn& {
2521 index_t v = cell_corners_.vertex(c);
2522 return vertices_.point<DIM>(v);
2523 }
2524 );
2525 }
2526
2527 /**
2528 * \brief Gets the cells adjacent to a given cell.
2529 * \param[in] c the index of the cell.
2530 * \return a range with all the indices of the cels adjacent to this
2531 * cell. It will output exactly one item per facet of the cell. Facets
2532 * on the border will output NO_INDEX (no adjacent cell).
2533 */
2534 auto adjacent(index_t c) const {
2535 geo_debug_assert(c < nb());
2536 return transform_range(
2537 facets(c), [this](index_t f)->index_t {
2538 return cell_facets_.adjacent_cell(f);
2539 }
2540 );
2541 }
2542
2543 #endif
2544
2545 void clear(
2546 bool keep_attributes=true, bool keep_memory=false
2547 ) override;
2548
2549 void delete_elements(
2550 vector<index_t>& to_delete,
2551 bool remove_isolated_vertices=true
2552 ) override;
2553
2554 void permute_elements(vector<index_t>& permutation) override;
2555
2556 /**
2557 * \brief Creates a contiguous chunk of cells of the
2558 * same type
2559 * \param[in] nb_cells number of cells to create
2560 * \param[in] type type of the cells to create, one of
2561 * MESH_TET, MESH_HEX, MESH_PRISM, MESH_PYRAMID, MESH_CONNECTOR.
2562 * \return the first created cell
2563 */
2564 5 index_t create_cells(index_t nb_cells, MeshCellType type) {
2565
2566
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if(nb_cells == 0) {
2567 return NO_CELL;
2568 }
2569
2570
2571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(type != MESH_TET) {
2572 is_not_simplicial();
2573 }
2574
2575 5 const CellDescriptor& desc = cell_type_to_cell_descriptor(type);
2576
2577 // Note: there is padding, the same number of corners and
2578 // faces is created for each cell, so that a single cell
2579 // pointer is used for both.
2580
2581 index_t cell_size = std::max(desc.nb_vertices, desc.nb_facets);
2582 index_t first_cell = nb();
2583 5 index_t co = cell_corners_.nb();
2584
2585 5 cell_corners_.create_sub_elements(
2586 nb_cells*cell_size
2587 );
2588
2589 5 cell_facets_.create_sub_elements(
2590 nb_cells*cell_size
2591 );
2592
2593 5 index_t result = create_sub_elements(nb_cells, type);
2594
2595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(!is_simplicial_) {
2596 for(index_t c=first_cell; c<=first_cell+nb_cells; ++c) {
2597 cell_ptr_[c] = co;
2598 co += cell_size;
2599 }
2600
2601 geo_debug_assert(cell_ptr_.size() == nb()+1);
2602 geo_debug_assert(cell_ptr_[nb()] == cell_corners_.nb());
2603 geo_debug_assert(cell_ptr_[nb()] == cell_facets_.nb());
2604 }
2605
2606 return result;
2607 }
2608
2609 /**
2610 * \brief Creates a contiguous chunk of tetrahedra
2611 * \param[in] nb_tets number of tetrahedra to create
2612 * \return the first created tetrahedron
2613 */
2614 index_t create_tets(index_t nb_tets) {
2615
1/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
5 return create_cells(nb_tets, MESH_TET);
2616 }
2617
2618 /**
2619 * \brief Creates a contiguous chunk of hexahedra
2620 * \param[in] nb_hexes number of hexahedra to create
2621 * \return the first created hexahedron
2622 */
2623 index_t create_hexes(index_t nb_hexes) {
2624 return create_cells(nb_hexes, MESH_HEX);
2625 }
2626
2627 /**
2628 * \brief Creates a contiguous chunk of prisms
2629 * \param[in] nb_prisms number of prisms to create
2630 * \return the first created prism
2631 */
2632 index_t create_prisms(index_t nb_prisms) {
2633 return create_cells(nb_prisms, MESH_PRISM);
2634 }
2635
2636 /**
2637 * \brief Creates a contiguous chunk of pyramids
2638 * \param[in] nb_pyramids number of pyramids to create
2639 * \return the first created pyramid
2640 */
2641 index_t create_pyramids(index_t nb_pyramids) {
2642 return create_cells(nb_pyramids, MESH_PYRAMID);
2643 }
2644
2645 /**
2646 * \brief Creates a tetrahedron
2647 * \param[in] v1 , v2 , v3 , v4 the vertices of the tetrahedron,
2648 * all in 0 .. mesh.vertices.nb()-1
2649 * \param[in] adj1 , adj2 , adj3 , adj4
2650 * adjacent cells, or NO_CELL if unspecified / on border
2651 * \return the created tetrahedron
2652 */
2653 index_t create_tet(
2654 index_t v1, index_t v2, index_t v3, index_t v4,
2655 index_t adj1 = NO_CELL,
2656 index_t adj2 = NO_CELL,
2657 index_t adj3 = NO_CELL,
2658 index_t adj4 = NO_CELL
2659 ) {
2660 cell_corners_.create_sub_element(v1);
2661 cell_corners_.create_sub_element(v2);
2662 cell_corners_.create_sub_element(v3);
2663 cell_corners_.create_sub_element(v4);
2664 cell_facets_.create_sub_element(adj1);
2665 cell_facets_.create_sub_element(adj2);
2666 cell_facets_.create_sub_element(adj3);
2667 cell_facets_.create_sub_element(adj4);
2668 index_t result = create_sub_element(MESH_TET);
2669 if(!is_simplicial_) {
2670 cell_ptr_[nb()] = cell_corners_.nb();
2671 }
2672 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2673 return result;
2674 }
2675
2676 /**
2677 * \brief Creates an hexahedron
2678 * \param[in] v1 , v2 , v3 , v4 , v5 , v6 , v7 , v8
2679 * the vertices of the hexahedron,
2680 * all in 0 .. mesh.vertices.nb()-1
2681 * \param[in] adj1 , adj2 , adj3 , adj4 , adj5 , adj6
2682 * adjacent cells, or NO_CELL if unspecified / on border
2683 * \return the created hexahedron
2684 */
2685 index_t create_hex(
2686 index_t v1, index_t v2, index_t v3, index_t v4,
2687 index_t v5, index_t v6, index_t v7, index_t v8,
2688 index_t adj1 = NO_CELL,
2689 index_t adj2 = NO_CELL,
2690 index_t adj3 = NO_CELL,
2691 index_t adj4 = NO_CELL,
2692 index_t adj5 = NO_CELL,
2693 index_t adj6 = NO_CELL
2694 ) {
2695 is_not_simplicial();
2696 cell_corners_.create_sub_element(v1);
2697 cell_corners_.create_sub_element(v2);
2698 cell_corners_.create_sub_element(v3);
2699 cell_corners_.create_sub_element(v4);
2700 cell_corners_.create_sub_element(v5);
2701 cell_corners_.create_sub_element(v6);
2702 cell_corners_.create_sub_element(v7);
2703 cell_corners_.create_sub_element(v8);
2704 cell_facets_.create_sub_element(adj1);
2705 cell_facets_.create_sub_element(adj2);
2706 cell_facets_.create_sub_element(adj3);
2707 cell_facets_.create_sub_element(adj4);
2708 cell_facets_.create_sub_element(adj5);
2709 cell_facets_.create_sub_element(adj6);
2710 cell_facets_.create_sub_element(NO_CELL); // padding
2711 cell_facets_.create_sub_element(NO_CELL); // padding
2712 index_t result = create_sub_element(MESH_HEX);
2713 cell_ptr_[nb()] = cell_corners_.nb();
2714 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2715 return result;
2716 }
2717
2718 /**
2719 * \brief Creates a prism
2720 * \param[in] v1 , v2 , v3 , v4 , v5 , v6
2721 * the vertices of the prism
2722 * all in 0 .. mesh.vertices.nb()-1
2723 * \param[in] adj1 , adj2 , adj3 , adj4 , adj5
2724 * adjacent cells, or NO_CELL if unspecified / on border
2725 * \return the created prism
2726 */
2727 index_t create_prism(
2728 index_t v1, index_t v2,
2729 index_t v3, index_t v4,
2730 index_t v5, index_t v6,
2731 index_t adj1 = NO_CELL,
2732 index_t adj2 = NO_CELL,
2733 index_t adj3 = NO_CELL,
2734 index_t adj4 = NO_CELL,
2735 index_t adj5 = NO_CELL
2736 ) {
2737 is_not_simplicial();
2738 cell_corners_.create_sub_element(v1);
2739 cell_corners_.create_sub_element(v2);
2740 cell_corners_.create_sub_element(v3);
2741 cell_corners_.create_sub_element(v4);
2742 cell_corners_.create_sub_element(v5);
2743 cell_corners_.create_sub_element(v6);
2744 cell_facets_.create_sub_element(adj1);
2745 cell_facets_.create_sub_element(adj2);
2746 cell_facets_.create_sub_element(adj3);
2747 cell_facets_.create_sub_element(adj4);
2748 cell_facets_.create_sub_element(adj5);
2749 cell_facets_.create_sub_element(NO_CELL); // padding
2750 index_t result = create_sub_element(MESH_PRISM);
2751 cell_ptr_[nb()] = cell_corners_.nb();
2752 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2753 return result;
2754 }
2755
2756 /**
2757 * \brief Creates a pyramid
2758 * \param[in] v1 , v2 , v3 , v4 , v5
2759 * the vertices of the pyramid
2760 * all in 0 .. mesh.vertices.nb()-1
2761 * \param[in] adj1 , adj2 , adj3 , adj4 , adj5
2762 * adjacent cells, or NO_CELL if unspecified / on border
2763 * \return the created pyramid
2764 */
2765 index_t create_pyramid(
2766 index_t v1, index_t v2, index_t v3, index_t v4, index_t v5,
2767 index_t adj1 = NO_CELL,
2768 index_t adj2 = NO_CELL,
2769 index_t adj3 = NO_CELL,
2770 index_t adj4 = NO_CELL,
2771 index_t adj5 = NO_CELL
2772 ) {
2773 is_not_simplicial();
2774 cell_corners_.create_sub_element(v1);
2775 cell_corners_.create_sub_element(v2);
2776 cell_corners_.create_sub_element(v3);
2777 cell_corners_.create_sub_element(v4);
2778 cell_corners_.create_sub_element(v5);
2779 cell_facets_.create_sub_element(adj1);
2780 cell_facets_.create_sub_element(adj2);
2781 cell_facets_.create_sub_element(adj3);
2782 cell_facets_.create_sub_element(adj4);
2783 cell_facets_.create_sub_element(adj5);
2784 index_t result = create_sub_element(MESH_PYRAMID);
2785 cell_ptr_[nb()] = cell_corners_.nb();
2786 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2787 return result;
2788 }
2789
2790 /**
2791 * \brief Creates a connector
2792 * \details Connector are automatically
2793 * created by connect() (most client codes
2794 * do not use this function)
2795 * \param[in] v1 , v2 , v3 , v4
2796 * the vertices of the connector
2797 * all in 0 .. mesh.vertices.nb()-1
2798 * \param[in] adj1 , adj2 , adj3
2799 * adjacent cells, or NO_CELL if unspecified / on border
2800 * \return the created connector
2801 */
2802 index_t create_connector(
2803 index_t v1, index_t v2, index_t v3, index_t v4,
2804 index_t adj1 = NO_CELL,
2805 index_t adj2 = NO_CELL,
2806 index_t adj3 = NO_CELL
2807 ) {
2808 is_not_simplicial();
2809 cell_corners_.create_sub_element(v1);
2810 cell_corners_.create_sub_element(v2);
2811 cell_corners_.create_sub_element(v3);
2812 cell_corners_.create_sub_element(v4);
2813 cell_facets_.create_sub_element(adj1);
2814 cell_facets_.create_sub_element(adj2);
2815 cell_facets_.create_sub_element(adj3);
2816 cell_facets_.create_sub_element(NO_CELL); // padding
2817 index_t result = create_sub_element(MESH_CONNECTOR);
2818 cell_ptr_[nb()] = cell_corners_.nb();
2819 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2820 return result;
2821 }
2822
2823 /**
2824 * \brief Connects the cells.
2825 * \details This creates as needed the connectors that represent
2826 * non-conformal connections between a quadrilateral facet and
2827 * two triangular facets.
2828 * \param[in] remove_trivial_slivers if set, this removes the
2829 * slivers that are adjacent to a quadrilateral facet.
2830 * \param[in] verbose_if_OK if set, says OK if no bad connector
2831 * configuration was detected.
2832 */
2833 void connect(
2834 bool remove_trivial_slivers = true, bool verbose_if_OK=false
2835 );
2836
2837 /**
2838 * \brief Replaces the surfacic part of this mesh
2839 * with the borders of the volumetric part.
2840 */
2841 void compute_borders();
2842
2843 /**
2844 * \brief Replaces the surfacic part of this mesh
2845 * with the borders of the volumetric part.
2846 * \param[out] facet_cell on exit, stores the
2847 * index of the cell adjacent to the facet
2848 * on the border.
2849 */
2850 void compute_borders(Attribute<index_t>& facet_cell);
2851
2852 /**
2853 * \brief Copies a tetrahedron mesh into this Mesh.
2854 * \details Tetrahedron adjacences are not computed.
2855 * \param[in] dim dimension of the vertices
2856 * \param[in] vertices coordinates of the vertices
2857 * \param[in] tets tetrahedron to vertex links
2858 * \param[in] steal_args if set, vertices and tets
2859 * are 'stolen' from the arguments
2860 * (using vector::swap).
2861 */
2862 void assign_tet_mesh(
2863 coord_index_t dim,
2864 vector<double>& vertices,
2865 vector<index_t>& tets,
2866 bool steal_args
2867 );
2868
2869 /**
2870 * \brief Copies a tetrahedron mesh into this Mesh.
2871 * \details Tetrahedron adjacences are not computed.
2872 * \param[in] tets tetrahedron to vertex links
2873 * \param[in] steal_args if set, vertices and tets
2874 * are 'stolen' from the arguments
2875 * (using vector::swap).
2876 */
2877 void assign_tet_mesh(
2878 vector<index_t>& tets,
2879 bool steal_args
2880 );
2881
2882 void pop() override;
2883
2884 index_t tet_adjacent(index_t t, index_t lf) const {
2885 geo_debug_assert(is_simplicial_);
2886 geo_debug_assert(t < nb());
2887 geo_debug_assert(lf < 4);
2888
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 35598 times.
✓ Branch 2 taken 43070 times.
✗ Branch 3 not taken.
869898 return cell_facets_.adjacent_cell_[4*t+lf];
2889 }
2890
2891 index_t find_tet_adjacent(index_t t, index_t t2) const {
2892 geo_debug_assert(is_simplicial_);
2893 geo_debug_assert(t < nb());
2894 geo_debug_assert(t2 < nb());
2895
1/2
✓ Branch 0 taken 88782 times.
✗ Branch 1 not taken.
88782 for(index_t lf=0; lf<4; ++lf) {
2896
2/2
✓ Branch 0 taken 53184 times.
✓ Branch 1 taken 35598 times.
88782 if(cell_facets_.adjacent_cell_[4*t+lf] == t2) {
2897 return lf;
2898 }
2899 }
2900 return NO_FACET;
2901 }
2902
2903 index_t tet_vertex(index_t t, index_t lv) const {
2904 geo_debug_assert(is_simplicial_);
2905 geo_debug_assert(t < nb());
2906 geo_debug_assert(lv < 4);
2907
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
860035 return cell_corners_.corner_vertex_[4*t+lv];
2908 }
2909
2910 index_t find_tet_vertex(index_t t, index_t v) const {
2911 geo_debug_assert(is_simplicial_);
2912 geo_debug_assert(t < nb());
2913 geo_debug_assert(v < vertices_.nb());
2914 for(index_t lv=0; lv<4; ++lv) {
2915 if(cell_corners_.corner_vertex_[4*t+lv] == v) {
2916 return lv;
2917 }
2918 }
2919 return NO_VERTEX;
2920 }
2921
2922 /**
2923 * \brief Gets a vertex of a tetrahedron by local facet
2924 * index and local vertex index in facet.
2925 * \param[in] t global index of the tetrahedron
2926 * \param[in] lf local facet index (0,1,2 or 3)
2927 * \param[in] lv local vertex index in facet (0,1 or 2)
2928 * \return the global index of vertex \p lv in facet \p lf of
2929 * tetrahedron \p t
2930 * \pre are_simplices()
2931 */
2932 index_t tet_facet_vertex(
2933 index_t t, index_t lf, index_t lv
2934 ) const {
2935 geo_debug_assert(is_simplicial_);
2936 geo_debug_assert(t < nb());
2937 geo_debug_assert(lf < 4);
2938 geo_debug_assert(lv < 3);
2939 1536916 return cell_corners_.vertex(
2940 1536916 4 * t + local_tet_facet_vertex_index(lf,lv)
2941 );
2942 }
2943
2944 /**
2945 * \brief Finds the local index of a facet in a tetrahedron
2946 * by the global indices of its vertices.
2947 * \param[in] t index of the tetrahedron
2948 * \param[in] v1 global index of the first vertex
2949 * \param[in] v2 global index of the second vertex
2950 * \param[in] v3 global index of the third vertex
2951 * \return the local index (0,1,2 or 3) of the facet of
2952 * \p t that has \p v1, \p v2, \p v3 as vertices modulo a
2953 * circular permutation, or NO_FACET if such a facet does not
2954 * exist in \p t.
2955 * \pre are_simplices()
2956 */
2957 399168 index_t find_tet_facet(
2958 index_t t, index_t v1, index_t v2, index_t v3
2959 ) const {
2960 geo_debug_assert(is_simplicial_);
2961
2/2
✓ Branch 0 taken 1532148 times.
✓ Branch 1 taken 358340 times.
1890488 for(index_t lf = 0; lf < 4; ++lf) {
2962 index_t w1 = tet_facet_vertex(t, lf, 0);
2963 index_t w2 = tet_facet_vertex(t, lf, 1);
2964 index_t w3 = tet_facet_vertex(t, lf, 2);
2965 1532148 if(
2966
4/4
✓ Branch 0 taken 13414 times.
✓ Branch 1 taken 1518734 times.
✓ Branch 2 taken 3296 times.
✓ Branch 3 taken 10118 times.
1532148 (v1 == w1 && v2 == w2 && v3 == w3) ||
2967
4/4
✓ Branch 0 taken 16980 times.
✓ Branch 1 taken 1505050 times.
✓ Branch 2 taken 1162 times.
✓ Branch 3 taken 15818 times.
1522030 (v1 == w2 && v2 == w3 && v3 == w1) ||
2968
4/4
✓ Branch 0 taken 19202 times.
✓ Branch 1 taken 1487010 times.
✓ Branch 2 taken 4310 times.
✓ Branch 3 taken 14892 times.
1506212 (v1 == w3 && v2 == w1 && v3 == w2)
2969 ) {
2970 return lf;
2971 }
2972 }
2973 return NO_FACET;
2974 }
2975
2976 /**
2977 * \brief Gives the local index of a vertex in a
2978 * tetrahedron from its facet and vertex local indices.
2979 * \param[in] lf local facet index (0,1,2 or 3)
2980 * \param[in] lv local vertex index in \p lf (0,1 or 2)
2981 * \return the local vertex index (0,1,2 or 3) of the
2982 * \p lv%th vertex in facet \p lf
2983 */
2984 static index_t local_tet_facet_vertex_index(index_t lf, index_t lv) {
2985 geo_debug_assert(lf < 4);
2986 geo_debug_assert(lv < 3);
2987
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 13414 times.
✓ Branch 2 taken 1518734 times.
2114886 return MeshCellDescriptors::tet_descriptor.facet_vertex[lf][lv];
2988 }
2989
2990 protected:
2991
2992 /**
2993 * \brief Indicates that the stored elements are no
2994 * longer only tetrahedra.
2995 * \details Creates the cell pointers and cell types
2996 * for the pre-existing cells if any.
2997 */
2998 void is_not_simplicial() {
2999 if(is_simplicial_) {
3000 is_simplicial_ = false;
3001 cell_ptr_.resize(nb()+1);
3002 cell_type_.assign(nb(), MESH_TET);
3003 for(index_t c=0; c<cell_ptr_.size(); ++c) {
3004 cell_ptr_[c] = 4*c;
3005 }
3006 }
3007 }
3008
3009 /**
3010 * \brief Tests whether two cell facets can be connected.
3011 * \details Two cell facets can be connected if they have the
3012 * same vertices in reverse order.
3013 * \param[in] c1 index of the first cell
3014 * \param[in] f1 index of the first facet in \p c1
3015 * \param[in] c2 index of the second cell
3016 * \param[in] f2 index of the second facet in \p c2
3017 * \retval true if \p c1 and \p c2 can be connected by \p f1 and \p f2
3018 * \retval false otherwise
3019 */
3020 bool facets_match(
3021 index_t c1, index_t f1, index_t c2, index_t f2
3022 ) const;
3023
3024 /**
3025 * \brief Finds the local index of a vertex in a cell.
3026 * \param[in] c index of the cell
3027 * \param[in] v global index of the vertex
3028 * \return the local index
3029 * (in 0..cell_nb_vertices(c)-1) of the vertex in
3030 * cell \p c or NO_VERTEX if \p c is not incident to \p v
3031 */
3032 index_t find_cell_vertex(index_t c, index_t v) const {
3033 geo_debug_assert(c < nb());
3034 geo_debug_assert(v < vertices_.nb());
3035 for(index_t lv=0; lv<nb_vertices(c); ++lv) {
3036 if(vertex(c,lv) == v) {
3037 return lv;
3038 }
3039 }
3040 return NO_VERTEX;
3041 }
3042
3043 /**
3044 * \brief Finds the local index of a facet in a cell
3045 * that can be connected to a facet of another cell
3046 * \param[in] c1 index of the cell
3047 * \param[in] c2 index of the other cell
3048 * \param[in] f2 facet of the other cell
3049 * \return the local index (in 0 .. cell_nb_facets(c1)) of the facet of
3050 * \p c1 that has the same vertices as \p f2 in \p c2 in reverse order,
3051 * modulo a circular permutation, or NO_FACET if such a facet does not
3052 * exist in \p c1.
3053 */
3054 index_t find_cell_facet(
3055 index_t c1, index_t c2, index_t f2
3056 ) const {
3057 for(index_t f1=0; f1<nb_facets(c1); ++f1) {
3058 if(facets_match(c1,f1,c2,f2)) {
3059 return f1;
3060 }
3061 }
3062 return NO_FACET;
3063 }
3064
3065 /**
3066 * \brief Tests whether a triangular facet matches a quad facet.
3067 * \details Used to detect non-conformal configurations that should
3068 * be resolved by a connector.
3069 * \param[in] c1 index of the first cell
3070 * \param[in] lf1 index of a triangular facet in \p c1
3071 * \param[in] c2 index of the second cell
3072 * \param[in] lf2 index of a quadrangular facet in \p c2
3073 * \retval true if the three vertices of \p f1 appear in \p f2
3074 * in reverse order
3075 * \retval false otherwise
3076 */
3077 bool triangular_facet_matches_quad_facet(
3078 index_t c1, index_t lf1,
3079 index_t c2, index_t lf2
3080 ) const;
3081
3082
3083 /**
3084 * \brief Tests whether two triangular cell facets have a common edge.
3085 * \param[in] c1 index of the first cell
3086 * \param[in] f1 index of a triangular facet of \p c1
3087 * \param[in] c2 index of the second cell
3088 * \param[in] f2 index of a triangular facet of \p c2
3089 * \param[out] e1 index of the common edge in \p f1
3090 * or NO_EDGE if no such edge exists
3091 * \param[out] e2 index of the common edge in \p f2
3092 * or NO_EDGE if no such edge exists
3093 * \retval true if \p f1 and \p f2 have a common edge
3094 * \retval false otherwise
3095 */
3096 bool triangular_facets_have_common_edge(
3097 index_t c1, index_t f1,
3098 index_t c2, index_t f2,
3099 index_t& e1, index_t& e2
3100 ) const;
3101
3102 /**
3103 * \brief Creates a connector between a quadrandular facet and two
3104 * triangular facets.
3105 * \details This function is used by connect_cells()
3106 * \param[in] c1 index of the cell that has the quadrangular facet
3107 * \param[in] lf1 index of the quadrangular facet in \p c1
3108 * \param[in] matches a const reference to a vector of
3109 * (cell index, facet index) pairs that are candidate triangles to be
3110 * connected to the quadrangular facet. Each of them
3111 * has three vertices in common with the quadrangular facet.
3112 * It may contain more than two (cell,facet) index pairs.
3113 * In this case, among them we select the pair of triangular facets
3114 * that have an edge in common.
3115 * \retval true if a connector was created. A connector is created if
3116 * among the candidate triangular facets there are exactly two facets
3117 * on the border with an edge in common.
3118 * \retval false otherwise
3119 */
3120 bool create_connector(
3121 index_t c1, index_t lf1,
3122 const std::vector< std::pair<index_t, index_t> >& matches
3123 );
3124
3125 /**
3126 * \brief Optimized implementation of connect() used
3127 * when the mesh is simplicial.
3128 */
3129 void connect_tets();
3130
3131 protected:
3132 MeshVertices& vertices_;
3133 MeshCellCornersStore& cell_corners_;
3134 MeshCellFacetsStore& cell_facets_;
3135 friend class Mesh;
3136 friend class GeogramIOHandler;
3137 };
3138
3139 /*************************************************************************/
3140
3141 /**
3142 * \brief Indicates the mesh elements (vertices, facets or cells)
3143 * present in a mesh.
3144 * \details The set of elements present in a mesh is represented
3145 * by a bitwise-or combination of the constants.
3146 * \relates Mesh
3147 */
3148 enum MeshElementsFlags {
3149 MESH_NONE = 0,
3150 MESH_VERTICES = 1,
3151 MESH_FACETS = 2,
3152 MESH_EDGES = 4,
3153 MESH_CELLS = 8,
3154 MESH_ALL_ELEMENTS = 15,
3155 MESH_FACET_CORNERS = 16,
3156 MESH_CELL_CORNERS = 32,
3157 MESH_CELL_FACETS = 64,
3158 MESH_ALL_SUBELEMENTS = 65
3159 };
3160
3161 /*************************************************************************/
3162
3163 /**
3164 * \brief Represents a mesh.
3165 * \details A mesh can have vertices, optionally facets and
3166 * optionally volumetric cells. Attributes can be attached
3167 * to all elements and sub-elements.
3168 */
3169 class GEOGRAM_API Mesh {
3170 public:
3171 MeshVertices vertices;
3172 MeshEdges edges;
3173 MeshFacets facets;
3174 MeshFacetCornersStore facet_corners;
3175 MeshCells cells;
3176 MeshCellCornersStore cell_corners;
3177 MeshCellFacetsStore cell_facets;
3178
3179 /**
3180 * \brief Mesh constructor
3181 * \param[in] dimension dimension of the vertices
3182 * \param[in] single_precision if true, vertices are
3183 * stored in single precision (float), else they are
3184 * stored as double precision (double).
3185 */
3186 Mesh(index_t dimension=3, bool single_precision=false);
3187
3188 /**
3189 * \brief Mesh destructor.
3190 */
3191 virtual ~Mesh();
3192
3193 /**
3194 * \brief Removes all the elements and attributes of
3195 * this mesh.
3196 * \param[in] keep_attributes if true, then all the
3197 * existing attribute names / bindings are kept (but
3198 * they are cleared). If false, they are destroyed.
3199 * \param[in] keep_memory if true, then memory is
3200 * kept and can be reused by subsequent mesh
3201 * element creations.
3202 */
3203 void clear(bool keep_attributes=true, bool keep_memory=false);
3204
3205 /**
3206 * \brief Displays number of vertices, facets and borders.
3207 */
3208
2/6
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
18 void show_stats(const std::string& tag = "Mesh") const;
3209
3210
3211 /**
3212 * \brief Does some validity checks.
3213 * \details Used for debugging. If the
3214 * validity checks are not satisfied,
3215 * then it crashes with an assertion
3216 * failure.
3217 */
3218 void assert_is_valid();
3219
3220
3221 /**
3222 * \brief Copies a mesh onto this one
3223 * \details All attributes of this mesh are deleted, and
3224 * Attribute instances connected to this mesh are unbound.
3225 * \param[in] rhs a const reference to the mesh to be copied
3226 * \param[in] copy_attributes if true, all the attributes are
3227 * copied.
3228 * \param[in] what a combination of MESH_VERTICES, MESH_EDGES,
3229 * MESH_FACETS, MESH_CELLS flags. Set to MESH_ALL_ELEMENTS
3230 * to copy everything (default). If MESH_VERTICES is not set,
3231 * then the mesh is cleared.
3232 */
3233 void copy(
3234 const Mesh& rhs,
3235 bool copy_attributes=true,
3236 MeshElementsFlags what=MESH_ALL_ELEMENTS
3237 );
3238
3239 /**
3240 * \brief Loads this mesh from a file.
3241 * \details The file format is deduced from the extension. Supported
3242 * formats are those registered in the mesh I/O handlers
3243 * (.obj, .off, .ply, .stl, .mesh/.meshb, .geogram, ...).
3244 * Equivalent to mesh_load(filename, *this); implemented in
3245 * mesh_io.cpp.
3246 * \param[in] filename the name of the file
3247 * \retval true on success
3248 */
3249 bool load(const std::string& filename);
3250
3251 /**
3252 * \brief Saves this mesh to a file.
3253 * \details The file format is deduced from the extension.
3254 * Equivalent to mesh_save(*this, filename).
3255 * \param[in] filename the name of the file
3256 * \retval true on success
3257 */
3258 bool save(const std::string& filename) const;
3259
3260 /**
3261 * \brief Gets the list of all attributes.
3262 * \return a ';'-separated list of all attributes.
3263 */
3264 std::string get_attributes() const;
3265
3266 /**
3267 * \brief Gets the list of all scalar attributes.
3268 * \return a ';'-separated list of all scalar attributes.
3269 * \details Whenever there is a vector attribute v of dim d,
3270 * it appends v[0];v[1];...v[d-1] to the list.
3271 */
3272 std::string get_scalar_attributes() const;
3273
3274 /**
3275 * \brief Gets the list of all vector attributes.
3276 * \param[in] max_dim if non-zero, only vector attributes of
3277 * dimension lower than \p max_dim are returned.
3278 * \return a ';'-separated list of all vector attributes.
3279 */
3280 std::string get_vector_attributes(index_t max_dim = 0) const;
3281
3282 /**
3283 * \brief Gets the number of subelements types.
3284 * \return the number of subelements types.
3285 */
3286 index_t nb_subelements_types() const;
3287
3288 /**
3289 * \brief Gets a MeshSubElementsStore by index.
3290 * \param[in] i index of the subelements
3291 * \return a reference to the corresponding MeshSubElementsStore
3292 * \pre i < nb_subelements_types()
3293 */
3294 MeshSubElementsStore& get_subelements_by_index(index_t i);
3295
3296 /**
3297 * \brief Gets a MeshSubElementsStore by index.
3298 * \param[in] i index of the subelements
3299 * \return a const reference to the corresponding MeshSubElementsStore
3300 * \pre i < nb_subelements_types()
3301 */
3302 const MeshSubElementsStore& get_subelements_by_index(index_t i) const;
3303
3304
3305 /**
3306 * \brief Gets a MeshSubElementsStore by subelements type.
3307 * \param[in] what one of MESH_VERTICES, MESH_EDGES, MESH_FACETS,
3308 * MESH_FACET_CORNERS, MESH_CELLS, MESH_CELL_CORNERS, MESH_CELL_FACETS
3309 * \return a reference to the corresponding MeshSubElementsStore
3310 */
3311 MeshSubElementsStore& get_subelements_by_type(MeshElementsFlags what);
3312
3313 /**
3314 * \brief Gets a MeshSubElementsStore by subelements type.
3315 * \param[in] what one of MESH_VERTICES, MESH_EDGES, MESH_FACETS,
3316 * MESH_FACET_CORNERS, MESH_CELLS, MESH_CELL_CORNERS, MESH_CELL_FACETS
3317 * \return a const reference to the corresponding MeshSubElementsStore
3318 */
3319 const MeshSubElementsStore& get_subelements_by_type(
3320 MeshElementsFlags what
3321 ) const;
3322
3323 /**
3324 * \brief Gets a subelement name by subelement type.
3325 * \param[in] what one of MESH_VERTICES, MESH_EDGES, MESH_FACETS,
3326 * MESH_FACET_CORNERS, MESH_CELLS, MESH_CELL_CORNERS, MESH_CELL_FACETS
3327 * \return a string with the name of the subelement.
3328 */
3329 static std::string subelements_type_to_name(MeshElementsFlags what);
3330
3331 /**
3332 * \brief Gets a subelement type by subelement name.
3333 * \param[in] name the name of the subelement as a string
3334 * \return one of MESH_VERTICES, MESH_EDGES, MESH_FACETS,
3335 * MESH_FACET_CORNERS, MESH_CELLS, MESH_CELL_CORNERS, MESH_CELL_FACETS
3336 * or MESH_NONE if the name is invalid
3337 */
3338 static MeshElementsFlags name_to_subelements_type(
3339 const std::string& name
3340 );
3341
3342 /**
3343 * \brief Extracts localisation, name and optional component from
3344 * an attribute name.
3345 * \param[in] full_attribute_name for instance, facets.density, or
3346 * vertices.normal[0]
3347 * \param[out] where one of MESH_VERTICES, MESH_EDGES, MESH_FACETS,
3348 * MESH_FACET_CORNERS, MESH_CELLS, MESH_CELL_FACETS, MESH_CELL_CORNERS
3349 * \param[out] attribute_name the name of the attribute, without the
3350 * localisation and without the component
3351 * \param[out] component the component (between square brackets in
3352 * \p full_attribute_name) or 0 if no component was specified
3353 * \retval true if the attribute name could be parsed
3354 * \retval false if the attribute name has invalid syntax
3355 */
3356 static bool parse_attribute_name(
3357 const std::string& full_attribute_name,
3358 MeshElementsFlags& where,
3359 std::string& attribute_name,
3360 index_t& component
3361 );
3362
3363 protected:
3364 /**
3365 * \brief Displays the list of attributes to the Logger.
3366 * \param[in] tag the tag to be sent to the Logger
3367 * \param[in] subelement_name the name of the subelement
3368 * (vertices, facets, facet_corners ...)
3369 * \param[in] subelements a const reference to the MeshSubElementsStore
3370 */
3371 void display_attributes(
3372 const std::string& tag, const std::string& subelement_name,
3373 const MeshSubElementsStore& subelements
3374 ) const;
3375
3376 /**
3377 * \brief Forbids copy.
3378 * \details This is to make sure that client code does
3379 * not unintentionlly copies a Mesh (for
3380 * instance by passing it by-value to a function).
3381 * Use copy() instead.
3382 */
3383 Mesh(const Mesh& rhs) = delete;
3384
3385 /**
3386 * \brief Forbids copy.
3387 * \details This is to make sure that client code does
3388 * not unintentionlly copies a Mesh (for
3389 * instance by passing it by-value to a function).
3390 * Use copy() instead.
3391 */
3392 const Mesh& operator=(const Mesh& rhs) = delete;
3393 };
3394
3395 /*************************************************************************/
3396 }
3397
3398 #endif
3399