GCC Code Coverage Report


Directory: ./
File: mesh/mesh.h
Date: 2026-09-27 03:12:47
Exec Total Coverage
Lines: 252 421 59.9%
Functions: 33 51 64.7%
Branches: 796 2350 33.9%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40 #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 12807 times.
✓ Branch 1 taken 204 times.
✓ Branch 2 taken 185 times.
✓ Branch 3 taken 76736 times.
✓ Branch 4 taken 77881 times.
✓ Branch 5 taken 226048 times.
✓ Branch 6 taken 3851898 times.
✓ Branch 7 taken 96022 times.
✓ Branch 8 taken 36 times.
✓ Branch 9 taken 196 times.
✓ Branch 10 taken 4390954 times.
✓ Branch 11 taken 4012 times.
✓ Branch 12 taken 4391034 times.
✓ Branch 13 taken 23776 times.
✓ Branch 14 taken 995309 times.
✓ Branch 15 taken 41 times.
✓ Branch 16 taken 97 times.
✓ Branch 17 taken 12156 times.
✓ Branch 18 taken 23 times.
✓ Branch 19 taken 15 times.
✓ Branch 20 taken 124849 times.
✓ Branch 21 taken 181 times.
✓ Branch 22 taken 38 times.
✓ Branch 23 taken 132 times.
✓ Branch 24 taken 33 times.
✓ Branch 25 taken 25 times.
✓ Branch 26 taken 112 times.
✓ Branch 27 taken 59 times.
✓ Branch 28 taken 60508 times.
✓ Branch 29 taken 241 times.
✓ Branch 30 taken 76 times.
✓ Branch 31 taken 20 times.
✓ Branch 32 taken 10 times.
✓ Branch 33 taken 61 times.
✓ Branch 34 taken 17 times.
✓ Branch 35 taken 303 times.
✓ Branch 36 taken 249 times.
✓ Branch 37 taken 382208 times.
✓ Branch 38 taken 91277 times.
✓ Branch 39 taken 40 times.
✓ Branch 40 taken 1 times.
✓ Branch 41 taken 61 times.
✓ Branch 42 taken 40 times.
✓ Branch 43 taken 203 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 267 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 254 times.
✓ Branch 53 taken 1 times.
✓ Branch 54 taken 921085 times.
✓ Branch 55 taken 254 times.
✓ Branch 56 taken 891456 times.
✓ Branch 57 taken 252 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 5 times.
✓ Branch 66 taken 5 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 727 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 931735 times.
✓ Branch 93 taken 211 times.
✓ Branch 94 taken 2820929 times.
✓ Branch 95 taken 213 times.
✓ Branch 96 taken 1 times.
✓ Branch 97 taken 64 times.
✓ Branch 98 taken 4 times.
✓ Branch 99 taken 17 times.
✗ Branch 100 not taken.
✓ Branch 101 taken 1 times.
✓ Branch 102 taken 4241 times.
✓ Branch 103 taken 435 times.
✓ Branch 104 taken 834264 times.
✓ Branch 105 taken 435 times.
✓ Branch 106 taken 12 times.
✓ Branch 107 taken 436 times.
✓ Branch 108 taken 20 times.
✓ Branch 109 taken 13 times.
✓ Branch 110 taken 400500 times.
✓ Branch 111 taken 13 times.
✓ Branch 112 taken 6145 times.
✓ Branch 113 taken 772422 times.
✓ Branch 114 taken 528 times.
✓ Branch 115 taken 170 times.
✓ Branch 116 taken 838122 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 3 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 450847 times.
✗ Branch 140 not taken.
✓ Branch 141 taken 150162 times.
✓ Branch 142 taken 57 times.
✓ Branch 143 taken 294839 times.
✓ Branch 144 taken 56 times.
✓ Branch 145 taken 294838 times.
✓ Branch 146 taken 52 times.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✓ Branch 150 taken 164 times.
✓ Branch 151 taken 56 times.
✓ Branch 152 taken 12093 times.
✓ Branch 153 taken 56 times.
✓ Branch 154 taken 12094 times.
✓ Branch 155 taken 6 times.
✓ Branch 156 taken 5 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.
23870037 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
58/689
✗ Branch 0 not taken.
✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21116 times.
✓ Branch 5 taken 1 times.
✗ 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 653 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 830 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 316 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 60 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 5 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 taken 140 times.
✗ 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 taken 20 times.
✗ 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 6 times.
✗ Branch 977 not taken.
✓ Branch 979 taken 1 times.
✗ Branch 980 not taken.
✓ Branch 982 taken 40 times.
✗ Branch 983 not taken.
✗ Branch 985 not taken.
✗ Branch 986 not taken.
✓ Branch 988 taken 36 times.
✗ Branch 989 not taken.
2522000 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 94582 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 1202 index_t create_sub_elements(index_t nb) {
169 1202 index_t result = nb_;
170
2/2
✓ Branch 0 taken 1143 times.
✓ Branch 1 taken 59 times.
1202 if(nb_ + nb > attributes_.size()) {
171 index_t new_capacity=nb_ + nb;
172
2/2
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 504 times.
1143 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 1143 attributes_.reserve(new_capacity);
179 }
180 1202 nb_ += nb;
181 1202 attributes_.resize(nb_);
182 1202 return result;
183 }
184
185 /**
186 * \brief Creates attributes for a sub-element
187 * \return the index of the created element
188 */
189 6693111 index_t create_sub_element() {
190 6693111 index_t result = nb_;
191
2/2
✓ Branch 0 taken 7049 times.
✓ Branch 1 taken 6686062 times.
6693111 ++nb_;
192
2/2
✓ Branch 0 taken 7049 times.
✓ Branch 1 taken 6686062 times.
6693111 if(attributes_.capacity() < nb_) {
193 index_t new_capacity =
194 7049 std::max(index_t(16),attributes_.capacity()*2);
195 7049 attributes_.reserve(new_capacity);
196 }
197 6693111 attributes_.resize(nb_);
198 6693111 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 364219 times.
✓ Branch 3 taken 81 times.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 330700 times.
✓ Branch 7 taken 307 times.
1390219 for(index_t i = 0; i < I.size(); i++) {
313
6/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 364008 times.
✓ Branch 3 taken 211 times.
✓ Branch 4 taken 38 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 330530 times.
✓ Branch 7 taken 170 times.
694960 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.
678789 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 120128 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 357131 times.
✓ Branch 1 taken 120128 times.
597387 for(index_t c=0; c<dimension(); ++c) {
374 357131 point_ptr(result)[c] = coords[c];
375 }
376 120128 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 8 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 28 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
395 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 706 times.
706 void set_dimension(index_t dim) {
463 if(single_precision()) {
464 ✗ point_fp32_.redim(dim);
465 } else {
466 706 point_.redim(dim);
467 }
468 706 }
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
94/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 taken 2 times.
✓ Branch 19 taken 1 times.
✗ 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 taken 3 times.
✓ Branch 27 taken 2 times.
✗ 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 1348 times.
✓ Branch 51 taken 6120 times.
✓ Branch 52 taken 75853 times.
✓ Branch 53 taken 57760 times.
✓ Branch 54 taken 77192 times.
✓ Branch 55 taken 57760 times.
✓ Branch 56 taken 6338 times.
✓ Branch 57 taken 5767 times.
✓ Branch 58 taken 2874 times.
✓ Branch 59 taken 3464 times.
✓ Branch 60 taken 2160 times.
✓ Branch 61 taken 3607 times.
✗ Branch 62 not taken.
✓ Branch 63 taken 3 times.
✗ 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 taken 1 times.
✗ 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 8263 times.
✓ Branch 137 taken 6120 times.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✓ Branch 140 taken 1378 times.
✓ Branch 141 taken 6381 times.
✓ Branch 142 taken 131905 times.
✓ Branch 143 taken 79536 times.
✓ Branch 144 taken 103591 times.
✓ Branch 145 taken 79536 times.
✓ Branch 146 taken 6348 times.
✓ Branch 147 taken 6106 times.
✓ Branch 148 taken 2776 times.
✓ Branch 149 taken 3572 times.
✓ Branch 150 taken 2251 times.
✓ Branch 151 taken 3855 times.
✓ Branch 152 taken 1317 times.
✓ Branch 153 taken 6192 times.
✓ Branch 154 taken 133050 times.
✓ Branch 155 taken 82259 times.
✓ Branch 156 taken 111701 times.
✓ Branch 157 taken 82259 times.
✓ Branch 158 taken 6525 times.
✓ Branch 159 taken 6145 times.
✓ Branch 160 taken 2815 times.
✓ Branch 161 taken 3710 times.
✓ Branch 162 taken 2279 times.
✓ Branch 163 taken 3866 times.
✓ Branch 164 taken 1137 times.
✓ Branch 165 taken 8018 times.
✓ Branch 166 taken 111906 times.
✓ Branch 167 taken 87144 times.
✓ Branch 168 taken 118544 times.
✓ Branch 169 taken 87144 times.
✓ Branch 170 taken 5072 times.
✓ Branch 171 taken 7119 times.
✓ Branch 172 taken 1698 times.
✓ Branch 173 taken 3374 times.
✓ Branch 174 taken 2164 times.
✓ Branch 175 taken 4955 times.
✓ Branch 176 taken 1196 times.
✓ Branch 177 taken 8277 times.
✓ Branch 178 taken 85084 times.
✓ Branch 179 taken 82117 times.
✓ Branch 180 taken 101362 times.
✓ Branch 181 taken 82117 times.
✓ Branch 182 taken 5127 times.
✓ Branch 183 taken 6991 times.
✓ Branch 184 taken 1726 times.
✓ Branch 185 taken 3401 times.
✓ Branch 186 taken 2068 times.
✓ Branch 187 taken 4923 times.
✓ Branch 188 taken 1299 times.
✓ Branch 189 taken 6106 times.
✓ Branch 190 taken 141492 times.
✓ Branch 191 taken 95167 times.
✓ Branch 192 taken 143897 times.
✓ Branch 193 taken 95167 times.
✓ Branch 194 taken 6493 times.
✓ Branch 195 taken 6088 times.
✓ Branch 196 taken 2887 times.
✓ Branch 197 taken 3606 times.
✓ Branch 198 taken 2234 times.
✓ Branch 199 taken 3854 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 8226 times.
✓ Branch 221 taken 6381 times.
✓ Branch 222 taken 1 times.
✗ Branch 223 not taken.
✓ Branch 224 taken 7999 times.
✓ Branch 225 taken 6192 times.
✓ Branch 226 taken 2 times.
✓ Branch 227 taken 2 times.
✓ Branch 228 taken 6113 times.
✓ Branch 229 taken 8018 times.
✗ Branch 230 not taken.
✗ Branch 231 not taken.
✓ Branch 232 taken 6124 times.
✓ Branch 233 taken 8277 times.
✗ Branch 234 not taken.
✗ Branch 235 not taken.
✓ Branch 236 taken 8362 times.
✓ Branch 237 taken 6106 times.
✓ Branch 238 taken 2 times.
✗ Branch 239 not taken.
151578727 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 176204 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 31794 times.
✗ Branch 8 not taken.
2520929 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 263 times.
✓ Branch 1 taken 1855690 times.
✓ Branch 2 taken 5512 times.
✓ Branch 3 taken 19197 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 55 times.
✓ Branch 6 taken 488744 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 1233 times.
✓ Branch 15 taken 64521 times.
✗ Branch 16 not taken.
219369276 &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 883115 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 20000 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 25000 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.
1418194 &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 14495192 times.
✓ Branch 1 taken 248823 times.
✓ Branch 2 taken 27079593 times.
✓ Branch 3 taken 36317 times.
✓ Branch 4 taken 16299492 times.
✓ Branch 5 taken 10276675 times.
✓ Branch 6 taken 5760818 times.
✓ Branch 7 taken 217186 times.
✓ Branch 8 taken 1581486 times.
✓ Branch 9 taken 13151 times.
✓ Branch 10 taken 5507748 times.
✓ Branch 11 taken 301 times.
✓ Branch 12 taken 1811671 times.
✓ Branch 13 taken 355923 times.
✓ Branch 14 taken 3284782 times.
✓ Branch 15 taken 355917 times.
✓ Branch 16 taken 1466766 times.
✓ Branch 17 taken 355917 times.
✓ Branch 18 taken 818041 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 685836 times.
✓ Branch 25 taken 194042 times.
✓ Branch 26 taken 1430318 times.
✓ Branch 27 taken 25842 times.
✓ Branch 28 taken 1950068 times.
✓ Branch 29 taken 5100 times.
✓ Branch 30 taken 519424 times.
✓ Branch 31 taken 5120 times.
✓ Branch 32 taken 951126 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 246314 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 2380688 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 921085 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 921085 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 18087483 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 18087483 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 921337 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 402761 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 462030 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 1087418 times.
✗ Branch 59 not taken.
201273501 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 14856443 times.
✓ Branch 1 taken 233895 times.
✓ Branch 2 taken 31296281 times.
✓ Branch 3 taken 252786 times.
✓ Branch 4 taken 15382769 times.
✓ Branch 5 taken 56982 times.
✓ Branch 6 taken 4688908 times.
✓ Branch 7 taken 520 times.
✓ Branch 8 taken 2002125 times.
✓ Branch 9 taken 1786876 times.
✓ Branch 10 taken 10930928 times.
✓ Branch 11 taken 1786870 times.
✓ Branch 12 taken 6983202 times.
✓ Branch 13 taken 1786870 times.
✓ Branch 14 taken 1156267 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 131 times.
✓ Branch 17 taken 1504115 times.
✓ Branch 18 taken 2112572 times.
✓ Branch 19 taken 128928 times.
✓ Branch 20 taken 3254164 times.
✓ Branch 21 taken 128928 times.
✓ Branch 22 taken 3970153 times.
✓ Branch 23 taken 549587 times.
✓ Branch 24 taken 182847 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1134864 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 245680 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1777598 times.
✓ Branch 31 taken 5120 times.
✓ Branch 32 taken 19783992 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 19743796 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 40196 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 2764011 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 3180886 times.
✗ Branch 41 not taken.
178643494 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 94449 times.
✓ Branch 1 taken 13593887 times.
✓ Branch 2 taken 95780 times.
✓ Branch 3 taken 12479295 times.
✓ Branch 4 taken 18608 times.
✓ Branch 5 taken 12367658 times.
✓ Branch 6 taken 5100 times.
✓ Branch 7 taken 921631 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 921085 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 921357 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1087438 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 20 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 294838 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 294838 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.
42187524 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 424810 times.
✓ Branch 1 taken 78111 times.
✓ Branch 2 taken 122101 times.
✓ Branch 3 taken 648057 times.
✓ Branch 4 taken 140603 times.
✓ Branch 5 taken 20460 times.
✓ Branch 6 taken 202156 times.
✓ Branch 7 taken 1100 times.
✓ Branch 8 taken 1233 times.
✓ Branch 9 taken 61420 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 309400 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1268940 times.
✓ Branch 14 taken 61420 times.
✓ Branch 15 taken 1268940 times.
✓ Branch 16 taken 61420 times.
✓ Branch 17 taken 776520 times.
✓ Branch 18 taken 920534 times.
✓ Branch 19 taken 956291 times.
✓ Branch 20 taken 77152 times.
✓ Branch 21 taken 566570 times.
✓ Branch 22 taken 389721 times.
✓ Branch 23 taken 9790125 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 5069945 times.
✓ Branch 26 taken 5173918 times.
✓ Branch 27 taken 200533 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 200533 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 200533 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 200533 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 675222 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 32485 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 5127 times.
✓ Branch 41 taken 27358 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 64521 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.
41123053 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 335 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 209 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 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 3 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 5 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.
950 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 1415848 index_t create_sub_element() {
942
2/2
✓ Branch 0 taken 335412 times.
✓ Branch 1 taken 1080436 times.
1415848 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 1415848 return MeshSubElementsStore::create_sub_element();
946 }
947
948 352 index_t create_sub_elements(index_t nb) {
949
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 341 times.
352 if(!is_simplicial_) {
950
2/2
✓ Branch 0 taken 21733 times.
✓ Branch 1 taken 11 times.
21744 for(index_t i=0; i<nb; ++i) {
951
2/2
✓ Branch 0 taken 21688 times.
✓ Branch 1 taken 45 times.
21733 facet_ptr_.push_back(NO_CORNER);
952 }
953 }
954 352 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 524313 times.
✓ Branch 1 taken 1682383 times.
✓ Branch 2 taken 3013236 times.
✓ Branch 3 taken 4035313 times.
✓ Branch 4 taken 8084742 times.
✓ Branch 5 taken 5067357 times.
✓ Branch 6 taken 1708728 times.
✓ Branch 7 taken 188906 times.
✓ Branch 8 taken 6723673 times.
✓ Branch 9 taken 360768 times.
✓ Branch 10 taken 39667399 times.
✓ Branch 11 taken 5975668 times.
✓ Branch 12 taken 46540 times.
✓ Branch 13 taken 10242630 times.
✓ Branch 14 taken 191404 times.
✓ Branch 15 taken 303021 times.
✓ Branch 16 taken 942130 times.
✓ Branch 17 taken 370482 times.
✓ Branch 18 taken 891240 times.
✓ Branch 19 taken 856573 times.
✓ Branch 20 taken 4280033 times.
✓ Branch 21 taken 15917501 times.
✓ Branch 22 taken 1357661 times.
✓ Branch 23 taken 2058693 times.
✓ Branch 24 taken 3465044 times.
✓ Branch 25 taken 1455073 times.
✓ Branch 26 taken 1427686 times.
✓ Branch 27 taken 204581 times.
✓ Branch 28 taken 9790125 times.
✓ Branch 29 taken 20460 times.
✓ Branch 30 taken 4616207 times.
✓ Branch 31 taken 5193918 times.
✓ Branch 32 taken 384793 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 261953 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 200533 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 32485 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 5127 times.
✓ Branch 41 taken 27358 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 25000 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✓ Branch 47 taken 1007421 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 64521 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.
296477294 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 4413330 times.
✓ Branch 1 taken 3860714 times.
✓ Branch 2 taken 12396291 times.
✓ Branch 3 taken 10885206 times.
✓ Branch 4 taken 6916798 times.
✓ Branch 5 taken 2821139 times.
✓ Branch 6 taken 22095377 times.
✓ Branch 7 taken 2984247 times.
✓ Branch 8 taken 6274019 times.
✓ Branch 9 taken 227486 times.
✓ Branch 10 taken 3400672 times.
✓ Branch 11 taken 222296 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 1339992 times.
✓ Branch 23 taken 1327560 times.
81742971 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 322634 times.
✓ Branch 1 taken 19735 times.
✓ Branch 2 taken 322634 times.
✓ Branch 3 taken 19735 times.
✓ Branch 4 taken 118980 times.
✓ Branch 5 taken 240728 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.
12117337 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 2205811 times.
✓ Branch 1 taken 450860 times.
✓ Branch 2 taken 10881 times.
✗ Branch 3 not taken.
2667552 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 1446540 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.
20835582 corner_adjacent_facet_[c] = f;
1063 4591598 }
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 1760451 times.
1784796 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 4590248 index_t create_sub_element(index_t v, index_t f = NO_FACET) {
1133
2/2
✓ Branch 0 taken 4585372 times.
✓ Branch 1 taken 4876 times.
4590248 corner_vertex_.push_back(v);
1134
2/2
✓ Branch 0 taken 4585372 times.
✓ Branch 1 taken 4876 times.
4590248 corner_adjacent_facet_.push_back(f);
1135 4590248 return MeshSubElementsStore::create_sub_element();
1136 }
1137
1138 352 index_t create_sub_elements(index_t nb) {
1139
2/2
✓ Branch 0 taken 2071723 times.
✓ Branch 1 taken 352 times.
2072075 for(index_t i=0; i<nb; ++i) {
1140
2/2
✓ Branch 0 taken 2070031 times.
✓ Branch 1 taken 1692 times.
2071723 corner_vertex_.push_back(NO_VERTEX);
1141 }
1142
2/2
✓ Branch 0 taken 2071723 times.
✓ Branch 1 taken 352 times.
2072075 for(index_t i=0; i<nb; ++i) {
1143
2/2
✓ Branch 0 taken 2070031 times.
✓ Branch 1 taken 1692 times.
2071723 corner_adjacent_facet_.push_back(NO_FACET);
1144 }
1145 352 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 830 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 2734263 times.
✓ Branch 1 taken 15360 times.
✓ Branch 2 taken 1439696 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 627597 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 853 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 36 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1203198 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 281690 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 10037053 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 820239 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 402967 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 186047 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1029076 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 153230 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 154557 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 162728 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 513856 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 493856 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 516860 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 621036 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1500937 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
24936671 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 2559795 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2560321 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 225074 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 118536 times.
✗ Branch 9 not taken.
520654 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 1186037 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 772410 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 123 times.
✓ Branch 13 taken 52 times.
✓ Branch 14 taken 408546 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 160 times.
✓ Branch 18 taken 476691 times.
✓ Branch 19 taken 163652 times.
3350134 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 802404 times.
✓ Branch 1 taken 589416 times.
✓ Branch 2 taken 740964 times.
✓ Branch 3 taken 527976 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 675222 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
3335982 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 2287363 times.
✓ Branch 1 taken 789064 times.
✓ Branch 2 taken 1701216 times.
✓ Branch 3 taken 3305944 times.
✓ Branch 4 taken 2421074 times.
✓ Branch 5 taken 2851608 times.
✓ Branch 6 taken 1959808 times.
✓ Branch 7 taken 1283144 times.
✓ Branch 8 taken 171846 times.
✓ Branch 9 taken 1185808 times.
✓ Branch 10 taken 10100673 times.
✓ Branch 11 taken 28104 times.
✓ Branch 12 taken 2708074 times.
✓ Branch 13 taken 7597997 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 402761 times.
✓ Branch 21 taken 518576 times.
✓ Branch 22 taken 462030 times.
✓ Branch 23 taken 924060 times.
40712293 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 49941461 times.
✓ Branch 1 taken 2260096 times.
52201557 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 12124960 times.
✓ Branch 1 taken 40076597 times.
64326517 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 370482 times.
✗ Branch 1 not taken.
370482 index_t find_edge(index_t f, index_t v1, index_t v2) const {
1347
1/2
✓ Branch 0 taken 740964 times.
✗ Branch 1 not taken.
1111446 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 370482 times.
✓ Branch 1 taken 370482 times.
✓ Branch 2 taken 370482 times.
✗ Branch 3 not taken.
740964 facet_corners_.vertex(c1) == v1 &&
1351 facet_corners_.vertex(c2) == v2
1352 ) {
1353 370482 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 352 index_t create_facets(
1378 index_t nb_facets, index_t nb_vertices_per_polygon
1379 ) {
1380
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 341 times.
352 if(nb_vertices_per_polygon != 3) {
1381 11 is_not_simplicial();
1382 }
1383
1384 index_t first_facet = nb();
1385 352 index_t co = facet_corners_.nb();
1386 352 facet_corners_.create_sub_elements(
1387 nb_facets*nb_vertices_per_polygon
1388 );
1389 352 index_t result = create_sub_elements(nb_facets);
1390
1391
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 341 times.
352 if(!is_simplicial_) {
1392
2/2
✓ Branch 0 taken 21744 times.
✓ Branch 1 taken 11 times.
21755 for(index_t f=first_facet; f<=first_facet+nb_facets; ++f) {
1393 21744 facet_ptr_[f] = co;
1394 21744 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 352 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.
341 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 7 times.
✗ Branch 2 not taken.
11 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 663939 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 663939 facet_corners_.create_sub_element(v1);
1440 663939 facet_corners_.create_sub_element(v2);
1441 663939 facet_corners_.create_sub_element(v3);
1442 663939 index_t result = create_sub_element();
1443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 663939 times.
663939 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 663939 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 751801 index_t create_polygon(index_t nb_vertices) {
1475
2/2
✓ Branch 0 taken 248743 times.
✓ Branch 1 taken 503058 times.
751801 if(nb_vertices != 3) {
1476 248743 is_not_simplicial();
1477 }
1478
2/2
✓ Branch 0 taken 2597999 times.
✓ Branch 1 taken 751801 times.
3349800 for(index_t i=0; i<nb_vertices; ++i) {
1479 2597999 facet_corners_.create_sub_element(NO_VERTEX);
1480 }
1481 751801 index_t result = create_sub_element();
1482
2/2
✓ Branch 0 taken 335304 times.
✓ Branch 1 taken 416497 times.
751801 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 751801 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 Flips all facets
1551 */
1552 void flip() {
1553 ✗ for(index_t f: *this) {
1554 ✗ flip(f);
1555 }
1556 }
1557
1558 /**
1559 * \brief Replaces the edges of this mesh
1560 * with the borders of the surfacic part.
1561 */
1562 void compute_borders();
1563
1564 /**
1565 * \brief Copies a triangle mesh into this Mesh.
1566 * \details Facet adjacence are not computed.
1567 * Facet and corner attributes are zeroed.
1568 * \param[in] dim dimension of the vertices
1569 * \param[in] vertices coordinates of the vertices
1570 * \param[in] triangles facet to vertex links
1571 * \param[in] steal_args if set, vertices and triangles
1572 * are 'stolen' from the arguments
1573 * (using vector::swap).
1574 */
1575 void assign_triangle_mesh(
1576 coord_index_t dim,
1577 vector<double>& vertices,
1578 vector<index_t>& triangles,
1579 bool steal_args
1580 );
1581
1582 /*
1583 * \brief Copies a triangle mesh into this Mesh.
1584 * \details Facet adjacence are not computed.
1585 * Facet and corner attributes are zeroed.
1586 * \param[in] triangles facet to vertex links
1587 * \param[in] steal_args if set, vertices and triangles
1588 * are 'stolen' from the arguments
1589 * (using vector::swap).
1590 */
1591 void assign_triangle_mesh(
1592 vector<index_t>& triangles,
1593 bool steal_args
1594 );
1595
1596 void pop() override;
1597
1598 /**
1599 * \brief Gets the corners of a facet.
1600 * \param[in] f the index of the facet.
1601 * \return a range with all the corners of the facet.
1602 */
1603 index_range corners(index_t f) const {
1604 geo_debug_assert(f < nb());
1605 return index_range(
1606 index_as_iterator(corners_begin(f)),
1607 index_as_iterator(corners_end(f))
1608 );
1609 }
1610
1611 #ifndef MESH_NO_SYNTAXIC_SUGAR
1612
1613 /**
1614 * \brief Gets the vertices of a facet.
1615 * \param[in] f the index of the facet.
1616 * \return a range with all the vertices indices of the facet.
1617 */
1618
1/2
✓ Branch 0 taken 4174 times.
✗ Branch 1 not taken.
4174 auto vertices(index_t f) const {
1619 geo_debug_assert(f < nb());
1620 return transform_range(
1621 corners(f), [this](index_t c)->index_t {
1622
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12522 return facet_corners_.vertex(c);
1623 }
1624 4174 );
1625 }
1626
1627 /**
1628 * \brief Gets the facets adjacent to a given facet.
1629 * \param[in] f the index of the facet.
1630 * \return a range with all the indices of the facets adjacent to this
1631 * facet. It will output exactly one item per edge of the facet. Edges
1632 * on the border will output NO_INDEX (no adjacent facet).
1633 */
1634
2/2
✓ Branch 0 taken 2692249 times.
✓ Branch 1 taken 232546 times.
2924795 auto adjacent(index_t f) const {
1635 geo_debug_assert(f < nb());
1636 return transform_range(
1637 corners(f), [this](index_t c)->index_t {
1638
5/6
✓ Branch 0 taken 2899626 times.
✓ Branch 1 taken 166392 times.
✓ Branch 2 taken 5923019 times.
✓ Branch 3 taken 29836 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 555 times.
9019428 return facet_corners_.adjacent_facet(c);
1639 }
1640 2924795 );
1641 }
1642
1643 /**
1644 * \brief Gets the points associated with the vertices of a facet.
1645 * \param[in] f the index of the facet.
1646 * \return a range with the points that correspond to the vertices of
1647 * the facet, returned as const references.
1648 */
1649 template <index_t DIM=3> auto points(index_t f) const {
1650 geo_debug_assert(f < nb());
1651 typedef vecng<DIM,double> vecn;
1652 return transform_range_ref(
1653 corners(f), [this](index_t c)->const vecn& {
1654 index_t v = facet_corners_.vertex(c);
1655 return vertices_.point<DIM>(v);
1656 }
1657 );
1658 }
1659
1660 /**
1661 * \brief Gets the points associated with the vertices of a facet.
1662 * \param[in] f the index of the facet.
1663 * \return a range with the points that correspond to the vertices of
1664 * the facet, returned as modifiable references.
1665 */
1666
2/2
✓ Branch 0 taken 339419 times.
✓ Branch 1 taken 1233 times.
681304 template <index_t DIM=3> auto points(index_t f) {
1667 geo_debug_assert(f < nb());
1668 typedef vecng<DIM,double> vecn;
1669 return transform_range_ref(
1670 corners(f), [this](index_t c)->vecn& {
1671 1023189 index_t v = facet_corners_.vertex(c);
1672 1023189 return vertices_.point<DIM>(v);
1673 }
1674 681304 );
1675 }
1676
1677 /**
1678 * \brief Decomposes a facet into triangles
1679 * \param[in] f the index of the facet.
1680 * \return a range with a decomposition of the facet into triangles,
1681 * returned as std::tuple<index_t, index_t, index_t>
1682 */
1683 4529856 auto triangles(index_t f) const {
1684 geo_debug_assert(f < nb());
1685
2/2
✓ Branch 0 taken 4513259 times.
✓ Branch 1 taken 16597 times.
4529856 index_t v0 = facet_corners_.vertex(corners_begin(f));
1686 return transform_range(
1687 index_range(
1688 4529856 index_as_iterator(corners_begin(f)+1),
1689 4529856 index_as_iterator(corners_end(f)-1)
1690 ),
1691 [this,v0](index_t c)->std::tuple<index_t, index_t, index_t> {
1692 return std::make_tuple(
1693 v0,
1694 facet_corners_.vertex(c),
1695 1891781 facet_corners_.vertex(c+1)
1696 );
1697 }
1698 4529856 );
1699 }
1700
1701 /**
1702 * \brief Decomposes a facet into triangles
1703 * \param[in] f the index of the facet.
1704 * \return a range with a decomposition of the facet into triangles,
1705 * returned as std::tuple<const vecn&, const vecn&, const vecn&>
1706 * where vecn can be vec2, vec3, vec4 ... depending on the DIM
1707 * template argument
1708 */
1709 template <index_t DIM=3> auto triangle_points(index_t f) const {
1710 geo_debug_assert(f < nb());
1711 typedef vecng<DIM,double> vecn;
1712 return transform_range(
1713 3926150 triangles(f),
1714 [this](std::tuple<index_t, index_t, index_t> T)
1715 ->std::tuple<const vecn&, const vecn&, const vecn&> {
1716 return std::tuple<const vecn&, const vecn&, const vecn&>(
1717 vertices_.point<DIM>(std::get<0>(T)),
1718 vertices_.point<DIM>(std::get<1>(T)),
1719 3941510 vertices_.point<DIM>(std::get<2>(T))
1720 3941510 );
1721 }
1722 );
1723 }
1724
1725 /**
1726 * \brief Decomposes a facet into triangles
1727 * \param[in] f the index of the facet.
1728 * \return a range with a decomposition of the facet into triangles,
1729 * returned as std::tuple<vecn&, vecn&, vecn&>
1730 * where vecn can be vec2, vec3, vec4 ... depending on the DIM
1731 * template argument
1732 */
1733 template <index_t DIM=3> auto triangle_points(index_t f) {
1734 geo_debug_assert(f < nb());
1735 typedef vecng<DIM,double> vecn;
1736 return transform_range(
1737 48572 triangles(f),
1738 [this](std::tuple<index_t, index_t, index_t> T)
1739 ->std::tuple<vecn&, vecn&, vecn&> {
1740 return std::tuple<vecn&, vecn&, vecn&>(
1741 vertices_.point(std::get<0>(T)),
1742 vertices_.point(std::get<1>(T)),
1743 48572 vertices_.point(std::get<2>(T))
1744 48572 );
1745 }
1746 );
1747 }
1748
1749 #endif
1750
1751 protected:
1752
1753 /**
1754 * \brief Indicates that the stored elements are only triangles.
1755 */
1756 void is_simplicial() {
1757
4/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 532 times.
589 if(!is_simplicial_) {
1758 43 is_simplicial_ = true;
1759
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
43 facet_ptr_.resize(1);
1760 43 facet_ptr_[0] = 0;
1761 }
1762 }
1763
1764 /**
1765 * \brief Indicates that the stored elements are no
1766 * longer only triangles.
1767 * \details Creates the facet pointers for the pre-existing
1768 * triangles if any.
1769 */
1770 248862 void is_not_simplicial() {
1771
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 248719 times.
248862 if(is_simplicial_) {
1772 143 is_simplicial_ = false;
1773 143 facet_ptr_.resize(nb()+1);
1774
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 143 times.
473 for(index_t f=0; f<facet_ptr_.size(); ++f) {
1775 187 facet_ptr_[f] = 3*f;
1776 }
1777 }
1778 248862 }
1779
1780 protected:
1781 MeshVertices& vertices_;
1782 MeshFacetCornersStore& facet_corners_;
1783 friend class Mesh;
1784 friend class GeogramIOHandler;
1785 friend void GEOGRAM_API tessellate_facets(
1786 Mesh& M, index_t max_nb_vertices
1787 );
1788 };
1789
1790 /*************************************************************************/
1791
1792 enum MeshCellType {
1793 MESH_TET = 0,
1794 MESH_HEX = 1,
1795 MESH_PRISM = 2,
1796 MESH_PYRAMID = 3,
1797 MESH_CONNECTOR = 4,
1798 MESH_NB_CELL_TYPES = 5
1799 };
1800
1801 /**
1802 * \brief Lookup tables that describe the combinatorics
1803 * of each cell type.
1804 * \relates MeshCells
1805 */
1806 struct CellDescriptor {
1807 /** Number of vertices */
1808 index_t nb_vertices;
1809
1810 /** Number of facets */
1811 index_t nb_facets;
1812
1813 /** Number of vertices in each facet */
1814 index_t nb_vertices_in_facet[6];
1815
1816 /**
1817 * Cell vertex index by (facet index,facet vertex index).
1818 */
1819 index_t facet_vertex[6][4];
1820
1821 /**
1822 * Number of edges */
1823 index_t nb_edges;
1824
1825 /**
1826 * Cell vertex index by (edge index, edge vertex index).
1827 */
1828 index_t edge_vertex[12][2];
1829
1830 /**
1831 * Cell facet index by (edge index, adjacent facet index).
1832 */
1833 index_t edge_adjacent_facet[12][2];
1834 };
1835
1836
1837 /**
1838 * \brief Gathers declarations of global cell descriptors.
1839 * \details Cannot be declared as static variables in
1840 * MeshCellsStore, since visual C++ does not allows
1841 * exporting class static variables from a DLL.
1842 */
1843 namespace MeshCellDescriptors {
1844 /**
1845 * \brief Maps a cell type to the associated cell descriptor.
1846 */
1847 GEOGRAM_API extern CellDescriptor*
1848 cell_type_to_cell_descriptor[GEO::MESH_NB_CELL_TYPES];
1849
1850 GEOGRAM_API extern CellDescriptor tet_descriptor;
1851 GEOGRAM_API extern CellDescriptor hex_descriptor;
1852 GEOGRAM_API extern CellDescriptor prism_descriptor;
1853 GEOGRAM_API extern CellDescriptor pyramid_descriptor;
1854 GEOGRAM_API extern CellDescriptor connector_descriptor;
1855 }
1856
1857 /**
1858 * \brief Stores the cells of a mesh (low-level store)
1859 * \relates MeshCells
1860 */
1861 class GEOGRAM_API MeshCellsStore : public MeshSubElementsStore {
1862 public:
1863 MeshCellsStore(Mesh& mesh);
1864
1865 /**
1866 * \brief Tests whether all the cells are tetrahedra
1867 * \details Storage and access are optimized when all the
1868 * cells are tetrahedra
1869 * \retval true if all the cells are tetrahedra
1870 * \retval false otherwise
1871 */
1872 bool are_simplices() const {
1873
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_;
1874 }
1875
1876 /**
1877 * \brief Gets the type of a cell
1878 * \param[in] c the cell, in 0..nb()-1
1879 * \return one of
1880 * MESH_TET, MESH_HEX, MESH_PRISM, MESH_PYRAMID, MESH_CONNECTOR.
1881 */
1882 MeshCellType type(index_t c) const {
1883 geo_debug_assert(c < nb());
1884
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]);
1885 }
1886
1887 /**
1888 * \brief Gets the descriptor of a cell
1889 * \details The descriptor of a cell is a set of static
1890 * arrays that facilitate some accesses (most client
1891 * code do not need to use this function)
1892 * \param[in] c a cell, in 0..nb()-1
1893 * \return the descriptor of cell \p c
1894 */
1895 const CellDescriptor& descriptor(index_t c) const;
1896
1897 /**
1898 * \brief Gets a descriptor by cell type
1899 * \details The descriptor of a cell is a set of static
1900 * arrays that facilitate some accesses (most client
1901 * code do not need to use this function)
1902 * \param[in] t one of
1903 * MESH_TET, MESH_HEX, MESH_PRISM, MESH_PYRAMID, MESH_CONNECTOR
1904 * \return the descriptor of cell \p c
1905 */
1906 static const CellDescriptor& cell_type_to_cell_descriptor(
1907 MeshCellType t
1908 );
1909
1910 /**
1911 * \brief Gets the number of corners of a cell
1912 * \param[in] c a cell, in 0..nb()-1
1913 * \return the number of corners of cell \p c
1914 */
1915 index_t nb_corners(index_t c) const {
1916 geo_debug_assert(c < nb());
1917 ✗ return descriptor(c).nb_vertices;
1918 }
1919
1920 /**
1921 * \brief Gets the first element for iterating over
1922 * the corners of a cell
1923 * \param[in] c the cell, in 0..nb()-1
1924 * \return the first corner of the cell
1925 */
1926 index_t corners_begin(index_t c) const {
1927 geo_debug_assert(c < nb());
1928
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];
1929 }
1930
1931 /**
1932 * \brief Gets the upper limit for iterating over the
1933 * corners of a cell
1934 * \param[in] c the cell, in 0..nb()-1
1935 * \return one position past the last corner of the cell
1936 */
1937 ✗ index_t corners_end(index_t c) const {
1938 geo_debug_assert(c < nb());
1939 ✗ return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_corners(c);
1940 }
1941
1942 /**
1943 * \brief Gets a corner of a cell by local vertex index
1944 * \param[in] c the cell, in 0..nb()-1
1945 * \param[in] lv the local vertex index, in 0..nb_corners(c)-1
1946 * \return the corner incident to vertex \p lv in cell \p c
1947 */
1948 index_t corner(index_t c, index_t lv) const {
1949 geo_debug_assert(c < nb());
1950 // There seems to be a linkage problem under MSVC for the
1951 // following assertion check...
1952 #ifndef GEO_OS_WINDOWS
1953 geo_debug_assert(lv < nb_corners(c));
1954 #endif
1955
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;
1956 }
1957
1958 /**
1959 * \brief Gets the number of facets of a cell
1960 * \param[in] c the cell, in 0..nb()-1
1961 * \return the number of facets of cell \p c
1962 */
1963 index_t nb_facets(index_t c) const {
1964 geo_debug_assert(c < nb());
1965 ✗ return descriptor(c).nb_facets;
1966 }
1967
1968 /**
1969 * \brief Gets the first element for iterating over
1970 * the facets of a cell
1971 * \param[in] c the cell, in 0..nb()-1
1972 * \return the first facet of the cell
1973 */
1974 index_t facets_begin(index_t c) const {
1975 geo_debug_assert(c < nb());
1976
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];
1977 }
1978
1979 /**
1980 * \brief Gets the upper limit for iterating over the
1981 * facets of a cell
1982 * \param[in] c the cell, in 0..nb()-1
1983 * \return one position past the last facet of the facet
1984 */
1985 index_t facets_end(index_t c) const {
1986 geo_debug_assert(c < nb());
1987 return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_facets(c);
1988 }
1989
1990 /**
1991 * \brief Gets a facet of a cell by local facet index
1992 * \param[in] c the cell, in 0..nb()-1
1993 * \param[in] lf the local facet index, in 0..nb_facets(c)-1
1994 * \return the facet \p lf in cell \p c
1995 */
1996 index_t facet(index_t c, index_t lf) const {
1997 geo_debug_assert(c < nb());
1998 geo_debug_assert(lf < nb_facets(c));
1999
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;
2000 }
2001
2002 /**
2003 * \brief Gets the number of edges in a cell
2004 * \param[in] c the cell, in 0..nb()-1
2005 * \return the number of edges in cell \p c
2006 */
2007 index_t nb_edges(index_t c) const {
2008 return descriptor(c).nb_edges;
2009 }
2010
2011 /**
2012 * \brief Gets a pointer to a cell pointer index by cell index
2013 * \param[in] c cell index
2014 * \return a pointer to the cell pointer index
2015 * \note Normal uses do not call this function
2016 */
2017 index_t* cell_ptr_ptr(index_t c) {
2018 geo_debug_assert(!is_simplicial_);
2019 return &cell_ptr_[c];
2020 }
2021
2022 /**
2023 * \brief Gets a pointer to a cell pointer index by cell index
2024 * \param[in] c cell index
2025 * \return a pointer to the cell pointer index
2026 * \note Normal uses do not call this function
2027 */
2028 const index_t* cell_ptr_ptr(index_t c) const {
2029 geo_debug_assert(!is_simplicial_);
2030 return &cell_ptr_[c];
2031 }
2032
2033 /**
2034 * \brief Gets a pointer to a cell type by cell index
2035 * \param[in] c cell index
2036 * \return a pointer to the cell type
2037 * \note Normal uses do not call this function
2038 */
2039 Numeric::uint8* cell_type_ptr(index_t c) {
2040 geo_debug_assert(!is_simplicial_);
2041 return &cell_type_[c];
2042 }
2043
2044 /**
2045 * \brief Gets a pointer to a cell type by cell index
2046 * \param[in] c cell index
2047 * \return a const pointer to the cell type
2048 * \note Normal uses do not call this function
2049 */
2050 const Numeric::uint8* cell_type_ptr(index_t c) const {
2051 geo_debug_assert(!is_simplicial_);
2052 return &cell_type_[c];
2053 }
2054
2055
2056 protected:
2057 void clear_store(
2058 bool keep_attributes, bool keep_memory = false
2059 ) override;
2060
2061 void resize_store(index_t new_size) override;
2062
2063 ✗ index_t create_sub_element(MeshCellType type) {
2064 ✗ if(!is_simplicial_) {
2065 ✗ cell_ptr_.push_back(NO_CORNER);
2066 ✗ cell_type_.push_back(Numeric::uint8(type));
2067 }
2068 ✗ return MeshSubElementsStore::create_sub_element();
2069 }
2070
2071 5 index_t create_sub_elements(index_t nb, MeshCellType type) {
2072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(!is_simplicial_) {
2073 ✗ for(index_t i=0; i<nb; ++i) {
2074 ✗ cell_ptr_.push_back(NO_CORNER);
2075 ✗ cell_type_.push_back(Numeric::uint8(type));
2076 }
2077 }
2078 5 return MeshSubElementsStore::create_sub_elements(nb);
2079 }
2080
2081 61 void copy(
2082 const MeshCellsStore& rhs, bool copy_attributes=true
2083 ) {
2084 61 MeshSubElementsStore::copy(rhs, copy_attributes);
2085 61 is_simplicial_ = rhs.is_simplicial_;
2086 cell_type_ = rhs.cell_type_;
2087 cell_ptr_ = rhs.cell_ptr_;
2088 61 }
2089
2090 protected:
2091 bool is_simplicial_;
2092 vector<Numeric::uint8> cell_type_;
2093 vector<index_t> cell_ptr_;
2094
2095 protected:
2096 friend class Mesh;
2097 friend class GeogramIOHandler;
2098 };
2099
2100 /*************************************************************************/
2101
2102 /**
2103 * \brief Stores the cell corners of a mesh (low-level store)
2104 * \relates MeshCells
2105 */
2106 class GEOGRAM_API MeshCellCornersStore : public MeshSubElementsStore {
2107 public:
2108 MeshCellCornersStore(Mesh& mesh);
2109
2110 /**
2111 * \brief Gets the vertex that a corner is incident to
2112 * \param[in] c the corner, in 0..nb()-1
2113 * \return the vertex that corner \p c is incident to
2114 */
2115 index_t vertex(index_t c) const {
2116 geo_debug_assert(c < nb());
2117
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];
2118 }
2119
2120 /**
2121 * \brief Sets the vertex that a corner is incident to
2122 * \param[in] c the corner, in 0..nb()-1
2123 * \param[in] v specifies the vertex that corner \p c is incident to
2124 */
2125 void set_vertex(index_t c, index_t v) {
2126 geo_debug_assert(c < nb());
2127 geo_debug_assert(v < vertices_.nb());
2128
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;
2129 6144 }
2130
2131 /**
2132 * \brief Gets a pointer to the vertex that a corner is incident to
2133 * \param[in] c the corner
2134 * \return a pointer to the index of the vertex that this corner
2135 * is incident to
2136 * \note Normal uses do not call this function
2137 */
2138 index_t* vertex_index_ptr(index_t c) {
2139 geo_debug_assert(c < nb());
2140 return &(corner_vertex_[c]);
2141 }
2142
2143 /**
2144 * \brief Gets a pointer to the vertex that a corner is incident to
2145 * \param[in] c the corner
2146 * \return a const pointer to the index of the vertex that this corner
2147 * is incident to
2148 * \note Normal uses do not call this function
2149 */
2150 const index_t* vertex_index_ptr(index_t c) const {
2151 geo_debug_assert(c < nb());
2152 return &(corner_vertex_[c]);
2153 }
2154
2155 /**
2156 * \brief Gets the point associated with a corner
2157 * \param[in] c the corner
2158 * \return a reference to the DIM-d point associated with the corner
2159 * \pre vertices.dimension() >= DIM
2160 */
2161 template <index_t DIM=3> vecng<DIM,double>& point(index_t c) {
2162 geo_debug_assert(c < nb());
2163 return vertices_.point<DIM>(vertex(c));
2164 }
2165
2166 /**
2167 * \brief Gets the point associated with a corner
2168 * \param[in] c the corner
2169 * \return const a reference to the DIM-d point associated with
2170 * the corner
2171 * \pre vertices.dimension() >= DIM
2172 */
2173 template <index_t DIM=3> const vecng<DIM,double>& point(
2174 index_t c
2175 ) const {
2176 geo_debug_assert(c < nb());
2177 return vertices_.point(vertex(c));
2178 }
2179
2180 protected:
2181 void clear_store(
2182 bool keep_attributes, bool keep_memory = false
2183 ) override;
2184
2185 void resize_store(index_t new_size) override;
2186
2187 ✗ index_t create_sub_element(index_t v) {
2188 ✗ corner_vertex_.push_back(v);
2189 ✗ return MeshSubElementsStore::create_sub_element();
2190 }
2191
2192 5 index_t create_sub_elements(index_t nb) {
2193
2/2
✓ Branch 0 taken 48284 times.
✓ Branch 1 taken 5 times.
48289 for(index_t i=0; i<nb; ++i) {
2194
2/2
✓ Branch 0 taken 48219 times.
✓ Branch 1 taken 65 times.
48284 corner_vertex_.push_back(NO_VERTEX);
2195 }
2196 5 return MeshSubElementsStore::create_sub_elements(nb);
2197 }
2198
2199 void copy(
2200 const MeshCellCornersStore& rhs, bool copy_attributes=true
2201 ) {
2202 61 MeshSubElementsStore::copy(rhs, copy_attributes);
2203 corner_vertex_ = rhs.corner_vertex_;
2204 }
2205
2206 protected:
2207 MeshVertices& vertices_;
2208 vector<index_t> corner_vertex_;
2209
2210 friend class MeshCells;
2211 friend class Mesh;
2212 friend class GeogramIOHandler;
2213 };
2214
2215 /*************************************************************************/
2216
2217 /**
2218 * \brief Stores the cell facets of a mesh (low-level store)
2219 * \relates MeshCells
2220 */
2221 class GEOGRAM_API MeshCellFacetsStore : public MeshSubElementsStore {
2222 public:
2223 /**
2224 * \brief MeshCellFacetsStore constructor
2225 * \param[in] mesh the mesh that this MeshCellFacetsStore is attached to
2226 */
2227 MeshCellFacetsStore(Mesh& mesh);
2228
2229 /**
2230 * \brief Gets a cell adjacent to a facet
2231 * \param[in] f the facet, in 0..nb()-1
2232 * \return the cell adjacent to facet \p f, or NO_FACET if \p f
2233 * is on the border
2234 */
2235 index_t adjacent_cell(index_t f) const {
2236 geo_debug_assert(f < nb());
2237
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];
2238 }
2239
2240 /**
2241 * \brief Sets a cell adjacent to a facet
2242 * \param[in] f the facet, in 0..nb()-1
2243 * \param[in] c specifies the cell adjacent
2244 * to facet \p f, or is set to NO_FACET
2245 * if \p f is on the border
2246 */
2247 void set_adjacent_cell(index_t f, index_t c) {
2248 geo_debug_assert(f < nb());
2249 geo_debug_assert(c == NO_CELL || c < cells_.nb());
2250
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;
2251 }
2252
2253 /**
2254 * \brief Gets a const pointer to a cell adjacent to a facet
2255 * \param[in] f the facet, in 0..nb()-1
2256 * \return a const pointer to the cell adjacent to facet \p f,
2257 * or NO_FACET if \p f is on the border
2258 */
2259 const index_t* adjacent_cell_ptr(index_t f) const {
2260 geo_debug_assert(f < nb());
2261 return &adjacent_cell_[f];
2262 }
2263
2264 /**
2265 * \brief Gets a pointer to a cell adjacent to a facet
2266 * \param[in] f the facet, in 0..nb()-1
2267 * \return a pointer to the cell adjacent to facet \p f,
2268 * or NO_FACET if \p f is on the border
2269 */
2270 index_t* adjacent_cell_ptr(index_t f) {
2271 geo_debug_assert(f < nb());
2272 return &adjacent_cell_[f];
2273 }
2274
2275 protected:
2276 void clear_store(
2277 bool keep_attributes, bool keep_memory = false
2278 ) override;
2279
2280 void resize_store(index_t new_size) override;
2281
2282 ✗ index_t create_sub_element(index_t c = NO_CELL) {
2283 ✗ adjacent_cell_.push_back(c);
2284 ✗ return MeshSubElementsStore::create_sub_element();
2285 }
2286
2287 5 index_t create_sub_elements(index_t nb) {
2288
2/2
✓ Branch 0 taken 48284 times.
✓ Branch 1 taken 5 times.
48289 for(index_t i=0; i<nb; ++i) {
2289
2/2
✓ Branch 0 taken 48219 times.
✓ Branch 1 taken 65 times.
48284 adjacent_cell_.push_back(NO_CELL);
2290 }
2291 5 return MeshSubElementsStore::create_sub_elements(nb);
2292 }
2293
2294 void copy(
2295 const MeshCellFacetsStore& rhs, bool copy_attributes=true
2296 ) {
2297 61 MeshSubElementsStore::copy(rhs, copy_attributes);
2298 adjacent_cell_ = rhs.adjacent_cell_;
2299 61 }
2300
2301 protected:
2302 MeshVertices& vertices_;
2303 MeshCellsStore& cells_;
2304 vector<index_t> adjacent_cell_;
2305
2306 friend class MeshCells;
2307 friend class Mesh;
2308 friend class GeogramIOHandler;
2309 };
2310
2311 /*************************************************************************/
2312
2313 /**
2314 * \brief The cells of a mesh.
2315 * \relates Mesh
2316 */
2317 830 class GEOGRAM_API MeshCells : public MeshCellsStore, public MeshElements {
2318 public:
2319 /**
2320 * \brief MeshCells constructor
2321 * \param[in] mesh the mesh this MeshCells is attached to
2322 */
2323 MeshCells(Mesh& mesh);
2324
2325 /**
2326 * \brief Gets the number of vertices of a cell
2327 * \param[in] c a cell, in 0..nb()-1
2328 * \return the number of vertices of cell \p c
2329 */
2330 index_t nb_vertices(index_t c) const {
2331 ✗ return nb_corners(c);
2332 }
2333
2334 /**
2335 * \brief Gets a vertex of a cell by local vertex index
2336 * \param[in] c the cell, in 0..nb()-1
2337 * \param[in] lv local vertex index, in 0..nb_vertices(c)-1
2338 * \return the vertex \p lv of cell \p c
2339 */
2340 index_t vertex(index_t c, index_t lv) const {
2341
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));
2342 }
2343
2344 /**
2345 * \brief Sets a vertex of a cell by local vertex index
2346 * \param[in] c the cell, in 0..nb()-1
2347 * \param[in] lv local vertex index, in 0..nb_vertices(c)-1
2348 * \param[in] v specifies the vertex \p lv of cell \p c
2349 */
2350 void set_vertex(index_t c, index_t lv, index_t v) {
2351
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);
2352 }
2353
2354 /**
2355 * \brief Gets a point by cell and local vertex index
2356 * \param[in] c the cell
2357 * \param[in] lv the local vertex index in \p c
2358 * \return a const reference to the point corresponding to
2359 * the \p lv%th vertex of cell \p c
2360 * \pre lv < nb_vertices(c)
2361 */
2362 template <index_t DIM=3> const vecng<DIM,double>& point(
2363 index_t c, index_t lv
2364 ) const {
2365
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));
2366 }
2367
2368 /**
2369 * \brief Gets a point by cell and local vertex index
2370 * \param[in] c the cell
2371 * \param[in] lv the local vertex index in \p c
2372 * \return a reference to the point corresponding to
2373 * the \p lv%th vertex of cell \p c
2374 * \pre lv < nb_vertices(c)
2375 */
2376 template <index_t DIM=3> vecng<DIM,double>& point(
2377 index_t c, index_t lv
2378 ) {
2379 return vertices_.point<DIM>(vertex(c,lv));
2380 }
2381
2382 /**
2383 * \brief Gets a cell adjacent to another one by local facet index
2384 * \param[in] c the cell, in 0..nb()-1
2385 * \param[in] lf local facet index, in 0..nb_facets(c)-1
2386 * \return the cell adjacent to \p c along facet \p lf or NO_CELL
2387 * if no such cell exists
2388 */
2389 index_t adjacent(index_t c, index_t lf) const {
2390
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));
2391 }
2392
2393 /**
2394 * \brief Sets a cell adjacent to another one by local facet index
2395 * \param[in] c the cell, in 0..nb()-1
2396 * \param[in] lf local facet index, in 0..nb_facets(c)-1
2397 * \param[in] c2 specifies the cell adjacent to \p c along
2398 * facet \p lf or NO_CELL if no such cell exists
2399 */
2400 void set_adjacent(index_t c, index_t lf, index_t c2) {
2401
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);
2402 40828 }
2403
2404 /**
2405 * \brief Gets the number of vertices in a cell facet
2406 * \param[in] c the cell, in 0..nb()-1
2407 * \param[in] lf the local facet index, in 0..nb_facets(c)-1
2408 * \return the number of vertices of facet \p lf in cell \p c
2409 */
2410 index_t facet_nb_vertices(index_t c, index_t lf) const {
2411 geo_debug_assert(lf < nb_facets(c));
2412 ✗ return descriptor(c).nb_vertices_in_facet[lf];
2413 }
2414
2415 /**
2416 * \brief Gets a vertex of a cell by local facet index and
2417 * local vertex index in the facet
2418 * \param[in] c the cell, in 0..nb()-1
2419 * \param[in] lf the local facet index, in 0..nb_facets(c)-1
2420 * \param[in] lv the local vertex index, in 0..facet_nb_vertices(c,lf)-1
2421 * \return vertex \p lv of facet \p lf in cell \p c
2422 */
2423 148788 index_t facet_vertex(index_t c, index_t lf, index_t lv) const {
2424 geo_debug_assert(lv < facet_nb_vertices(c, lf));
2425 148788 return cell_corners_.vertex(
2426
1/2
✓ Branch 1 taken 148788 times.
✗ Branch 2 not taken.
148788 corner(c, descriptor(c).facet_vertex[lf][lv])
2427 148788 );
2428 }
2429 /**
2430 * \brief Gets a corner of a cell by local facet index and
2431 * local corner index in the facet
2432 * \param[in] c the cell, in 0..nb()-1
2433 * \param[in] lf the local facet index, in 0..nb_facets(c)-1
2434 * \param[in] lc the local corner index, in 0..facet_nb_vertices(c,lf)-1
2435 * \return corner \p lc of facet \p lf in cell \p c
2436 */
2437 index_t facet_corner(index_t c, index_t lf, index_t lc) const {
2438 geo_debug_assert(lc < facet_nb_vertices(c, lf));
2439 return corner(c, descriptor(c).facet_vertex[lf][lc]);
2440 }
2441
2442 /**
2443 * \brief Gets a cell vertex by local edge index and local
2444 * vertex index in the edge
2445 * \param[in] c the cell, in 0..nb()-1
2446 * \param[in] le the local edge index, in 0..nb_edges(c)-1
2447 * \param[in] lv the local index in the edge, one of 0,1
2448 * \return vertex \p lv of edge \p le in cell \p c
2449 */
2450 index_t edge_vertex(index_t c, index_t le, index_t lv) const {
2451 geo_debug_assert(le < nb_edges(c));
2452 geo_debug_assert(lv < 2);
2453 return cell_corners_.vertex(
2454 corner(c,descriptor(c).edge_vertex[le][lv])
2455 );
2456 }
2457
2458 /**
2459 * \brief Gets a cell local facet index by local edge index and local
2460 * facet index in the edge
2461 * \param[in] c the cell, in 0..nb()-1
2462 * \param[in] le the local edge index, in 0..nb_edges(c)-1
2463 * \param[in] lf the local index in the edge, one of 0,1
2464 * \return the local facet index of the facet adjacent to the edge.
2465 * - If \p lf=0, it gets the facet on the left of the oriented edge.
2466 * - If \p lf=1, it gets the facet on the right of the oriented edge.
2467 */
2468 index_t edge_adjacent_facet(index_t c, index_t le, index_t lf) const {
2469 geo_debug_assert(le < nb_edges(c));
2470 geo_debug_assert(lf < 2);
2471 return descriptor(c).edge_adjacent_facet[le][lf];
2472 }
2473
2474 /**
2475 * \brief Gets the corners of a cell.
2476 * \param[in] c the index of the cell.
2477 * \return a range with all the corners of the facet.
2478 */
2479 ✗ index_range corners(index_t c) const {
2480 geo_debug_assert(c < nb());
2481 return index_range(
2482 index_as_iterator(corners_begin(c)),
2483 ✗ index_as_iterator(corners_end(c))
2484 ✗ );
2485 }
2486
2487 /**
2488 * \brief Gets the facets of a cell.
2489 * \param[in] c the index of the cell.
2490 * \return a range with all the global indices of the cell facets.
2491 */
2492 index_range facets(index_t c) const {
2493 geo_debug_assert(c < nb());
2494 return index_range(
2495 index_as_iterator(facets_begin(c)),
2496 index_as_iterator(facets_end(c))
2497 );
2498 }
2499
2500 #ifndef MESH_NO_SYNTAXIC_SUGAR
2501
2502 /**
2503 * \brief Gets the points associated with the vertices of a cell.
2504 * \param[in] cell the index of the cell.
2505 * \return a range with the points that correspond to the vertices of
2506 * the cell, returned as const references.
2507 */
2508 template <index_t DIM=3> auto points(index_t cell) const {
2509 geo_debug_assert(cell < nb());
2510 typedef vecng<DIM,double> vecn;
2511 return transform_range_ref(
2512 ✗ corners(cell), [this](index_t c)->const vecn& {
2513 ✗ index_t v = cell_corners_.vertex(c);
2514 ✗ return vertices_.point<DIM>(v);
2515 }
2516 );
2517 }
2518
2519 /**
2520 * \brief Gets the points associated with the vertices of a cell.
2521 * \param[in] cell the index of the cell.
2522 * \return a range with the points that correspond to the vertices of
2523 * the cell, returned as modifiable references.
2524 */
2525 template <index_t DIM=3> auto points(index_t cell) {
2526 geo_debug_assert(cell < nb());
2527 typedef vecng<DIM,double> vecn;
2528 return transform_range_ref(
2529 ✗ corners(cell), [this](index_t c)->vecn& {
2530 ✗ index_t v = cell_corners_.vertex(c);
2531 ✗ return vertices_.point<DIM>(v);
2532 }
2533 );
2534 }
2535
2536 /**
2537 * \brief Gets the cells adjacent to a given cell.
2538 * \param[in] c the index of the cell.
2539 * \return a range with all the indices of the cels adjacent to this
2540 * cell. It will output exactly one item per facet of the cell. Facets
2541 * on the border will output NO_INDEX (no adjacent cell).
2542 */
2543 auto adjacent(index_t c) const {
2544 geo_debug_assert(c < nb());
2545 return transform_range(
2546 facets(c), [this](index_t f)->index_t {
2547 return cell_facets_.adjacent_cell(f);
2548 }
2549 );
2550 }
2551
2552 #endif
2553
2554 void clear(
2555 bool keep_attributes=true, bool keep_memory=false
2556 ) override;
2557
2558 void delete_elements(
2559 vector<index_t>& to_delete,
2560 bool remove_isolated_vertices=true
2561 ) override;
2562
2563 void permute_elements(vector<index_t>& permutation) override;
2564
2565 /**
2566 * \brief Creates a contiguous chunk of cells of the
2567 * same type
2568 * \param[in] nb_cells number of cells to create
2569 * \param[in] type type of the cells to create, one of
2570 * MESH_TET, MESH_HEX, MESH_PRISM, MESH_PYRAMID, MESH_CONNECTOR.
2571 * \return the first created cell
2572 */
2573 5 index_t create_cells(index_t nb_cells, MeshCellType type) {
2574
2575
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if(nb_cells == 0) {
2576 return NO_CELL;
2577 }
2578
2579
2580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(type != MESH_TET) {
2581 ✗ is_not_simplicial();
2582 }
2583
2584 5 const CellDescriptor& desc = cell_type_to_cell_descriptor(type);
2585
2586 // Note: there is padding, the same number of corners and
2587 // faces is created for each cell, so that a single cell
2588 // pointer is used for both.
2589
2590 index_t cell_size = std::max(desc.nb_vertices, desc.nb_facets);
2591 index_t first_cell = nb();
2592 5 index_t co = cell_corners_.nb();
2593
2594 5 cell_corners_.create_sub_elements(
2595 nb_cells*cell_size
2596 );
2597
2598 5 cell_facets_.create_sub_elements(
2599 nb_cells*cell_size
2600 );
2601
2602 5 index_t result = create_sub_elements(nb_cells, type);
2603
2604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(!is_simplicial_) {
2605 ✗ for(index_t c=first_cell; c<=first_cell+nb_cells; ++c) {
2606 ✗ cell_ptr_[c] = co;
2607 ✗ co += cell_size;
2608 }
2609
2610 geo_debug_assert(cell_ptr_.size() == nb()+1);
2611 geo_debug_assert(cell_ptr_[nb()] == cell_corners_.nb());
2612 geo_debug_assert(cell_ptr_[nb()] == cell_facets_.nb());
2613 }
2614
2615 return result;
2616 }
2617
2618 /**
2619 * \brief Creates a contiguous chunk of tetrahedra
2620 * \param[in] nb_tets number of tetrahedra to create
2621 * \return the first created tetrahedron
2622 */
2623 index_t create_tets(index_t nb_tets) {
2624
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);
2625 }
2626
2627 /**
2628 * \brief Creates a contiguous chunk of hexahedra
2629 * \param[in] nb_hexes number of hexahedra to create
2630 * \return the first created hexahedron
2631 */
2632 index_t create_hexes(index_t nb_hexes) {
2633 ✗ return create_cells(nb_hexes, MESH_HEX);
2634 }
2635
2636 /**
2637 * \brief Creates a contiguous chunk of prisms
2638 * \param[in] nb_prisms number of prisms to create
2639 * \return the first created prism
2640 */
2641 index_t create_prisms(index_t nb_prisms) {
2642 ✗ return create_cells(nb_prisms, MESH_PRISM);
2643 }
2644
2645 /**
2646 * \brief Creates a contiguous chunk of pyramids
2647 * \param[in] nb_pyramids number of pyramids to create
2648 * \return the first created pyramid
2649 */
2650 index_t create_pyramids(index_t nb_pyramids) {
2651 ✗ return create_cells(nb_pyramids, MESH_PYRAMID);
2652 }
2653
2654 /**
2655 * \brief Creates a tetrahedron
2656 * \param[in] v1 , v2 , v3 , v4 the vertices of the tetrahedron,
2657 * all in 0 .. mesh.vertices.nb()-1
2658 * \param[in] adj1 , adj2 , adj3 , adj4
2659 * adjacent cells, or NO_CELL if unspecified / on border
2660 * \return the created tetrahedron
2661 */
2662 ✗ index_t create_tet(
2663 index_t v1, index_t v2, index_t v3, index_t v4,
2664 index_t adj1 = NO_CELL,
2665 index_t adj2 = NO_CELL,
2666 index_t adj3 = NO_CELL,
2667 index_t adj4 = NO_CELL
2668 ) {
2669 ✗ cell_corners_.create_sub_element(v1);
2670 ✗ cell_corners_.create_sub_element(v2);
2671 ✗ cell_corners_.create_sub_element(v3);
2672 ✗ cell_corners_.create_sub_element(v4);
2673 ✗ cell_facets_.create_sub_element(adj1);
2674 ✗ cell_facets_.create_sub_element(adj2);
2675 ✗ cell_facets_.create_sub_element(adj3);
2676 ✗ cell_facets_.create_sub_element(adj4);
2677 ✗ index_t result = create_sub_element(MESH_TET);
2678 ✗ if(!is_simplicial_) {
2679 ✗ cell_ptr_[nb()] = cell_corners_.nb();
2680 }
2681 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2682 ✗ return result;
2683 }
2684
2685 /**
2686 * \brief Creates an hexahedron
2687 * \param[in] v1 , v2 , v3 , v4 , v5 , v6 , v7 , v8
2688 * the vertices of the hexahedron,
2689 * all in 0 .. mesh.vertices.nb()-1
2690 * \param[in] adj1 , adj2 , adj3 , adj4 , adj5 , adj6
2691 * adjacent cells, or NO_CELL if unspecified / on border
2692 * \return the created hexahedron
2693 */
2694 ✗ index_t create_hex(
2695 index_t v1, index_t v2, index_t v3, index_t v4,
2696 index_t v5, index_t v6, index_t v7, index_t v8,
2697 index_t adj1 = NO_CELL,
2698 index_t adj2 = NO_CELL,
2699 index_t adj3 = NO_CELL,
2700 index_t adj4 = NO_CELL,
2701 index_t adj5 = NO_CELL,
2702 index_t adj6 = NO_CELL
2703 ) {
2704 ✗ is_not_simplicial();
2705 ✗ cell_corners_.create_sub_element(v1);
2706 ✗ cell_corners_.create_sub_element(v2);
2707 ✗ cell_corners_.create_sub_element(v3);
2708 ✗ cell_corners_.create_sub_element(v4);
2709 ✗ cell_corners_.create_sub_element(v5);
2710 ✗ cell_corners_.create_sub_element(v6);
2711 ✗ cell_corners_.create_sub_element(v7);
2712 ✗ cell_corners_.create_sub_element(v8);
2713 ✗ cell_facets_.create_sub_element(adj1);
2714 ✗ cell_facets_.create_sub_element(adj2);
2715 ✗ cell_facets_.create_sub_element(adj3);
2716 ✗ cell_facets_.create_sub_element(adj4);
2717 ✗ cell_facets_.create_sub_element(adj5);
2718 ✗ cell_facets_.create_sub_element(adj6);
2719 ✗ cell_facets_.create_sub_element(NO_CELL); // padding
2720 ✗ cell_facets_.create_sub_element(NO_CELL); // padding
2721 ✗ index_t result = create_sub_element(MESH_HEX);
2722 ✗ cell_ptr_[nb()] = cell_corners_.nb();
2723 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2724 ✗ return result;
2725 }
2726
2727 /**
2728 * \brief Creates a prism
2729 * \param[in] v1 , v2 , v3 , v4 , v5 , v6
2730 * the vertices of the prism
2731 * all in 0 .. mesh.vertices.nb()-1
2732 * \param[in] adj1 , adj2 , adj3 , adj4 , adj5
2733 * adjacent cells, or NO_CELL if unspecified / on border
2734 * \return the created prism
2735 */
2736 ✗ index_t create_prism(
2737 index_t v1, index_t v2,
2738 index_t v3, index_t v4,
2739 index_t v5, index_t v6,
2740 index_t adj1 = NO_CELL,
2741 index_t adj2 = NO_CELL,
2742 index_t adj3 = NO_CELL,
2743 index_t adj4 = NO_CELL,
2744 index_t adj5 = NO_CELL
2745 ) {
2746 ✗ is_not_simplicial();
2747 ✗ cell_corners_.create_sub_element(v1);
2748 ✗ cell_corners_.create_sub_element(v2);
2749 ✗ cell_corners_.create_sub_element(v3);
2750 ✗ cell_corners_.create_sub_element(v4);
2751 ✗ cell_corners_.create_sub_element(v5);
2752 ✗ cell_corners_.create_sub_element(v6);
2753 ✗ cell_facets_.create_sub_element(adj1);
2754 ✗ cell_facets_.create_sub_element(adj2);
2755 ✗ cell_facets_.create_sub_element(adj3);
2756 ✗ cell_facets_.create_sub_element(adj4);
2757 ✗ cell_facets_.create_sub_element(adj5);
2758 ✗ cell_facets_.create_sub_element(NO_CELL); // padding
2759 ✗ index_t result = create_sub_element(MESH_PRISM);
2760 ✗ cell_ptr_[nb()] = cell_corners_.nb();
2761 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2762 ✗ return result;
2763 }
2764
2765 /**
2766 * \brief Creates a pyramid
2767 * \param[in] v1 , v2 , v3 , v4 , v5
2768 * the vertices of the pyramid
2769 * all in 0 .. mesh.vertices.nb()-1
2770 * \param[in] adj1 , adj2 , adj3 , adj4 , adj5
2771 * adjacent cells, or NO_CELL if unspecified / on border
2772 * \return the created pyramid
2773 */
2774 ✗ index_t create_pyramid(
2775 index_t v1, index_t v2, index_t v3, index_t v4, index_t v5,
2776 index_t adj1 = NO_CELL,
2777 index_t adj2 = NO_CELL,
2778 index_t adj3 = NO_CELL,
2779 index_t adj4 = NO_CELL,
2780 index_t adj5 = NO_CELL
2781 ) {
2782 ✗ is_not_simplicial();
2783 ✗ cell_corners_.create_sub_element(v1);
2784 ✗ cell_corners_.create_sub_element(v2);
2785 ✗ cell_corners_.create_sub_element(v3);
2786 ✗ cell_corners_.create_sub_element(v4);
2787 ✗ cell_corners_.create_sub_element(v5);
2788 ✗ cell_facets_.create_sub_element(adj1);
2789 ✗ cell_facets_.create_sub_element(adj2);
2790 ✗ cell_facets_.create_sub_element(adj3);
2791 ✗ cell_facets_.create_sub_element(adj4);
2792 ✗ cell_facets_.create_sub_element(adj5);
2793 ✗ index_t result = create_sub_element(MESH_PYRAMID);
2794 ✗ cell_ptr_[nb()] = cell_corners_.nb();
2795 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2796 ✗ return result;
2797 }
2798
2799 /**
2800 * \brief Creates a connector
2801 * \details Connector are automatically
2802 * created by connect() (most client codes
2803 * do not use this function)
2804 * \param[in] v1 , v2 , v3 , v4
2805 * the vertices of the connector
2806 * all in 0 .. mesh.vertices.nb()-1
2807 * \param[in] adj1 , adj2 , adj3
2808 * adjacent cells, or NO_CELL if unspecified / on border
2809 * \return the created connector
2810 */
2811 ✗ index_t create_connector(
2812 index_t v1, index_t v2, index_t v3, index_t v4,
2813 index_t adj1 = NO_CELL,
2814 index_t adj2 = NO_CELL,
2815 index_t adj3 = NO_CELL
2816 ) {
2817 ✗ is_not_simplicial();
2818 ✗ cell_corners_.create_sub_element(v1);
2819 ✗ cell_corners_.create_sub_element(v2);
2820 ✗ cell_corners_.create_sub_element(v3);
2821 ✗ cell_corners_.create_sub_element(v4);
2822 ✗ cell_facets_.create_sub_element(adj1);
2823 ✗ cell_facets_.create_sub_element(adj2);
2824 ✗ cell_facets_.create_sub_element(adj3);
2825 ✗ cell_facets_.create_sub_element(NO_CELL); // padding
2826 ✗ index_t result = create_sub_element(MESH_CONNECTOR);
2827 ✗ cell_ptr_[nb()] = cell_corners_.nb();
2828 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2829 ✗ return result;
2830 }
2831
2832 /**
2833 * \brief Connects the cells.
2834 * \details This creates as needed the connectors that represent
2835 * non-conformal connections between a quadrilateral facet and
2836 * two triangular facets.
2837 * \param[in] remove_trivial_slivers if set, this removes the
2838 * slivers that are adjacent to a quadrilateral facet.
2839 * \param[in] verbose_if_OK if set, says OK if no bad connector
2840 * configuration was detected.
2841 */
2842 void connect(
2843 bool remove_trivial_slivers = true, bool verbose_if_OK=false
2844 );
2845
2846 /**
2847 * \brief Replaces the surfacic part of this mesh
2848 * with the borders of the volumetric part.
2849 */
2850 void compute_borders();
2851
2852 /**
2853 * \brief Replaces the surfacic part of this mesh
2854 * with the borders of the volumetric part.
2855 * \param[out] facet_cell on exit, stores the
2856 * index of the cell adjacent to the facet
2857 * on the border.
2858 */
2859 void compute_borders(Attribute<index_t>& facet_cell);
2860
2861 /**
2862 * \brief Copies a tetrahedron mesh into this Mesh.
2863 * \details Tetrahedron adjacences are not computed.
2864 * \param[in] dim dimension of the vertices
2865 * \param[in] vertices coordinates of the vertices
2866 * \param[in] tets tetrahedron to vertex links
2867 * \param[in] steal_args if set, vertices and tets
2868 * are 'stolen' from the arguments
2869 * (using vector::swap).
2870 */
2871 void assign_tet_mesh(
2872 coord_index_t dim,
2873 vector<double>& vertices,
2874 vector<index_t>& tets,
2875 bool steal_args
2876 );
2877
2878 /**
2879 * \brief Copies a tetrahedron mesh into this Mesh.
2880 * \details Tetrahedron adjacences are not computed.
2881 * \param[in] tets tetrahedron to vertex links
2882 * \param[in] steal_args if set, vertices and tets
2883 * are 'stolen' from the arguments
2884 * (using vector::swap).
2885 */
2886 void assign_tet_mesh(
2887 vector<index_t>& tets,
2888 bool steal_args
2889 );
2890
2891 void pop() override;
2892
2893 index_t tet_adjacent(index_t t, index_t lf) const {
2894 geo_debug_assert(is_simplicial_);
2895 geo_debug_assert(t < nb());
2896 geo_debug_assert(lf < 4);
2897
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];
2898 }
2899
2900 index_t find_tet_adjacent(index_t t, index_t t2) const {
2901 geo_debug_assert(is_simplicial_);
2902 geo_debug_assert(t < nb());
2903 geo_debug_assert(t2 < nb());
2904
1/2
✓ Branch 0 taken 88782 times.
✗ Branch 1 not taken.
88782 for(index_t lf=0; lf<4; ++lf) {
2905
2/2
✓ Branch 0 taken 53184 times.
✓ Branch 1 taken 35598 times.
88782 if(cell_facets_.adjacent_cell_[4*t+lf] == t2) {
2906 return lf;
2907 }
2908 }
2909 return NO_FACET;
2910 }
2911
2912 index_t tet_vertex(index_t t, index_t lv) const {
2913 geo_debug_assert(is_simplicial_);
2914 geo_debug_assert(t < nb());
2915 geo_debug_assert(lv < 4);
2916
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
860035 return cell_corners_.corner_vertex_[4*t+lv];
2917 }
2918
2919 index_t find_tet_vertex(index_t t, index_t v) const {
2920 geo_debug_assert(is_simplicial_);
2921 geo_debug_assert(t < nb());
2922 geo_debug_assert(v < vertices_.nb());
2923 for(index_t lv=0; lv<4; ++lv) {
2924 if(cell_corners_.corner_vertex_[4*t+lv] == v) {
2925 return lv;
2926 }
2927 }
2928 return NO_VERTEX;
2929 }
2930
2931 /**
2932 * \brief Gets a vertex of a tetrahedron by local facet
2933 * index and local vertex index in facet.
2934 * \param[in] t global index of the tetrahedron
2935 * \param[in] lf local facet index (0,1,2 or 3)
2936 * \param[in] lv local vertex index in facet (0,1 or 2)
2937 * \return the global index of vertex \p lv in facet \p lf of
2938 * tetrahedron \p t
2939 * \pre are_simplices()
2940 */
2941 index_t tet_facet_vertex(
2942 index_t t, index_t lf, index_t lv
2943 ) const {
2944 geo_debug_assert(is_simplicial_);
2945 geo_debug_assert(t < nb());
2946 geo_debug_assert(lf < 4);
2947 geo_debug_assert(lv < 3);
2948 1536916 return cell_corners_.vertex(
2949 1536916 4 * t + local_tet_facet_vertex_index(lf,lv)
2950 );
2951 }
2952
2953 /**
2954 * \brief Finds the local index of a facet in a tetrahedron
2955 * by the global indices of its vertices.
2956 * \param[in] t index of the tetrahedron
2957 * \param[in] v1 global index of the first vertex
2958 * \param[in] v2 global index of the second vertex
2959 * \param[in] v3 global index of the third vertex
2960 * \return the local index (0,1,2 or 3) of the facet of
2961 * \p t that has \p v1, \p v2, \p v3 as vertices modulo a
2962 * circular permutation, or NO_FACET if such a facet does not
2963 * exist in \p t.
2964 * \pre are_simplices()
2965 */
2966 399168 index_t find_tet_facet(
2967 index_t t, index_t v1, index_t v2, index_t v3
2968 ) const {
2969 geo_debug_assert(is_simplicial_);
2970
2/2
✓ Branch 0 taken 1532148 times.
✓ Branch 1 taken 358340 times.
1890488 for(index_t lf = 0; lf < 4; ++lf) {
2971 index_t w1 = tet_facet_vertex(t, lf, 0);
2972 index_t w2 = tet_facet_vertex(t, lf, 1);
2973 index_t w3 = tet_facet_vertex(t, lf, 2);
2974 1532148 if(
2975
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) ||
2976
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) ||
2977
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)
2978 ) {
2979 return lf;
2980 }
2981 }
2982 return NO_FACET;
2983 }
2984
2985 /**
2986 * \brief Gives the local index of a vertex in a
2987 * tetrahedron from its facet and vertex local indices.
2988 * \param[in] lf local facet index (0,1,2 or 3)
2989 * \param[in] lv local vertex index in \p lf (0,1 or 2)
2990 * \return the local vertex index (0,1,2 or 3) of the
2991 * \p lv%th vertex in facet \p lf
2992 */
2993 static index_t local_tet_facet_vertex_index(index_t lf, index_t lv) {
2994 geo_debug_assert(lf < 4);
2995 geo_debug_assert(lv < 3);
2996
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];
2997 }
2998
2999 protected:
3000
3001 /**
3002 * \brief Indicates that the stored elements are no
3003 * longer only tetrahedra.
3004 * \details Creates the cell pointers and cell types
3005 * for the pre-existing cells if any.
3006 */
3007 ✗ void is_not_simplicial() {
3008 ✗ if(is_simplicial_) {
3009 ✗ is_simplicial_ = false;
3010 ✗ cell_ptr_.resize(nb()+1);
3011 ✗ cell_type_.assign(nb(), MESH_TET);
3012 ✗ for(index_t c=0; c<cell_ptr_.size(); ++c) {
3013 ✗ cell_ptr_[c] = 4*c;
3014 }
3015 }
3016 ✗ }
3017
3018 /**
3019 * \brief Tests whether two cell facets can be connected.
3020 * \details Two cell facets can be connected if they have the
3021 * same vertices in reverse order.
3022 * \param[in] c1 index of the first cell
3023 * \param[in] f1 index of the first facet in \p c1
3024 * \param[in] c2 index of the second cell
3025 * \param[in] f2 index of the second facet in \p c2
3026 * \retval true if \p c1 and \p c2 can be connected by \p f1 and \p f2
3027 * \retval false otherwise
3028 */
3029 bool facets_match(
3030 index_t c1, index_t f1, index_t c2, index_t f2
3031 ) const;
3032
3033 /**
3034 * \brief Finds the local index of a vertex in a cell.
3035 * \param[in] c index of the cell
3036 * \param[in] v global index of the vertex
3037 * \return the local index
3038 * (in 0..cell_nb_vertices(c)-1) of the vertex in
3039 * cell \p c or NO_VERTEX if \p c is not incident to \p v
3040 */
3041 ✗ index_t find_cell_vertex(index_t c, index_t v) const {
3042 geo_debug_assert(c < nb());
3043 geo_debug_assert(v < vertices_.nb());
3044 ✗ for(index_t lv=0; lv<nb_vertices(c); ++lv) {
3045 ✗ if(vertex(c,lv) == v) {
3046 return lv;
3047 }
3048 }
3049 return NO_VERTEX;
3050 }
3051
3052 /**
3053 * \brief Finds the local index of a facet in a cell
3054 * that can be connected to a facet of another cell
3055 * \param[in] c1 index of the cell
3056 * \param[in] c2 index of the other cell
3057 * \param[in] f2 facet of the other cell
3058 * \return the local index (in 0 .. cell_nb_facets(c1)) of the facet of
3059 * \p c1 that has the same vertices as \p f2 in \p c2 in reverse order,
3060 * modulo a circular permutation, or NO_FACET if such a facet does not
3061 * exist in \p c1.
3062 */
3063 ✗ index_t find_cell_facet(
3064 index_t c1, index_t c2, index_t f2
3065 ) const {
3066 ✗ for(index_t f1=0; f1<nb_facets(c1); ++f1) {
3067 ✗ if(facets_match(c1,f1,c2,f2)) {
3068 return f1;
3069 }
3070 }
3071 return NO_FACET;
3072 }
3073
3074 /**
3075 * \brief Tests whether a triangular facet matches a quad facet.
3076 * \details Used to detect non-conformal configurations that should
3077 * be resolved by a connector.
3078 * \param[in] c1 index of the first cell
3079 * \param[in] lf1 index of a triangular facet in \p c1
3080 * \param[in] c2 index of the second cell
3081 * \param[in] lf2 index of a quadrangular facet in \p c2
3082 * \retval true if the three vertices of \p f1 appear in \p f2
3083 * in reverse order
3084 * \retval false otherwise
3085 */
3086 bool triangular_facet_matches_quad_facet(
3087 index_t c1, index_t lf1,
3088 index_t c2, index_t lf2
3089 ) const;
3090
3091
3092 /**
3093 * \brief Tests whether two triangular cell facets have a common edge.
3094 * \param[in] c1 index of the first cell
3095 * \param[in] f1 index of a triangular facet of \p c1
3096 * \param[in] c2 index of the second cell
3097 * \param[in] f2 index of a triangular facet of \p c2
3098 * \param[out] e1 index of the common edge in \p f1
3099 * or NO_EDGE if no such edge exists
3100 * \param[out] e2 index of the common edge in \p f2
3101 * or NO_EDGE if no such edge exists
3102 * \retval true if \p f1 and \p f2 have a common edge
3103 * \retval false otherwise
3104 */
3105 bool triangular_facets_have_common_edge(
3106 index_t c1, index_t f1,
3107 index_t c2, index_t f2,
3108 index_t& e1, index_t& e2
3109 ) const;
3110
3111 /**
3112 * \brief Creates a connector between a quadrandular facet and two
3113 * triangular facets.
3114 * \details This function is used by connect_cells()
3115 * \param[in] c1 index of the cell that has the quadrangular facet
3116 * \param[in] lf1 index of the quadrangular facet in \p c1
3117 * \param[in] matches a const reference to a vector of
3118 * (cell index, facet index) pairs that are candidate triangles to be
3119 * connected to the quadrangular facet. Each of them
3120 * has three vertices in common with the quadrangular facet.
3121 * It may contain more than two (cell,facet) index pairs.
3122 * In this case, among them we select the pair of triangular facets
3123 * that have an edge in common.
3124 * \retval true if a connector was created. A connector is created if
3125 * among the candidate triangular facets there are exactly two facets
3126 * on the border with an edge in common.
3127 * \retval false otherwise
3128 */
3129 bool create_connector(
3130 index_t c1, index_t lf1,
3131 const std::vector< std::pair<index_t, index_t> >& matches
3132 );
3133
3134 /**
3135 * \brief Optimized implementation of connect() used
3136 * when the mesh is simplicial.
3137 */
3138 void connect_tets();
3139
3140 protected:
3141 MeshVertices& vertices_;
3142 MeshCellCornersStore& cell_corners_;
3143 MeshCellFacetsStore& cell_facets_;
3144 friend class Mesh;
3145 friend class GeogramIOHandler;
3146 };
3147
3148 /*************************************************************************/
3149
3150 /**
3151 * \brief Indicates the mesh elements (vertices, facets or cells)
3152 * present in a mesh.
3153 * \details The set of elements present in a mesh is represented
3154 * by a bitwise-or combination of the constants.
3155 * \relates Mesh
3156 */
3157 enum MeshElementsFlags {
3158 MESH_NONE = 0,
3159 MESH_VERTICES = 1,
3160 MESH_FACETS = 2,
3161 MESH_EDGES = 4,
3162 MESH_CELLS = 8,
3163 MESH_ALL_ELEMENTS = 15,
3164 MESH_FACET_CORNERS = 16,
3165 MESH_CELL_CORNERS = 32,
3166 MESH_CELL_FACETS = 64,
3167 MESH_ALL_SUBELEMENTS = 65
3168 };
3169
3170 /*************************************************************************/
3171
3172 /**
3173 * \brief Represents a mesh.
3174 * \details A mesh can have vertices, optionally facets and
3175 * optionally volumetric cells. Attributes can be attached
3176 * to all elements and sub-elements.
3177 */
3178 class GEOGRAM_API Mesh {
3179 public:
3180 MeshVertices vertices;
3181 MeshEdges edges;
3182 MeshFacets facets;
3183 MeshFacetCornersStore facet_corners;
3184 MeshCells cells;
3185 MeshCellCornersStore cell_corners;
3186 MeshCellFacetsStore cell_facets;
3187
3188 /**
3189 * \brief Mesh constructor
3190 * \param[in] dimension dimension of the vertices
3191 * \param[in] single_precision if true, vertices are
3192 * stored in single precision (float), else they are
3193 * stored as double precision (double).
3194 */
3195 Mesh(index_t dimension=3, bool single_precision=false);
3196
3197 /**
3198 * \brief Mesh destructor.
3199 */
3200 virtual ~Mesh();
3201
3202 /**
3203 * \brief Removes all the elements and attributes of
3204 * this mesh.
3205 * \param[in] keep_attributes if true, then all the
3206 * existing attribute names / bindings are kept (but
3207 * they are cleared). If false, they are destroyed.
3208 * \param[in] keep_memory if true, then memory is
3209 * kept and can be reused by subsequent mesh
3210 * element creations.
3211 */
3212 void clear(bool keep_attributes=true, bool keep_memory=false);
3213
3214 /**
3215 * \brief Displays number of vertices, facets and borders.
3216 */
3217
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;
3218
3219
3220 /**
3221 * \brief Does some validity checks.
3222 * \details Used for debugging. If the
3223 * validity checks are not satisfied,
3224 * then it crashes with an assertion
3225 * failure.
3226 */
3227 void assert_is_valid();
3228
3229
3230 /**
3231 * \brief Copies a mesh onto this one
3232 * \details All attributes of this mesh are deleted, and
3233 * Attribute instances connected to this mesh are unbound.
3234 * \param[in] rhs a const reference to the mesh to be copied
3235 * \param[in] copy_attributes if true, all the attributes are
3236 * copied.
3237 * \param[in] what a combination of MESH_VERTICES, MESH_EDGES,
3238 * MESH_FACETS, MESH_CELLS flags. Set to MESH_ALL_ELEMENTS
3239 * to copy everything (default). If MESH_VERTICES is not set,
3240 * then the mesh is cleared.
3241 */
3242 void copy(
3243 const Mesh& rhs,
3244 bool copy_attributes=true,
3245 MeshElementsFlags what=MESH_ALL_ELEMENTS
3246 );
3247
3248 /**
3249 * \brief Loads this mesh from a file.
3250 * \details The file format is deduced from the extension. Supported
3251 * formats are those registered in the mesh I/O handlers
3252 * (.obj, .off, .ply, .stl, .mesh/.meshb, .geogram, ...).
3253 * Equivalent to mesh_load(filename, *this); implemented in
3254 * mesh_io.cpp.
3255 * \param[in] filename the name of the file
3256 * \retval true on success
3257 */
3258 bool load(const std::string& filename);
3259
3260 /**
3261 * \brief Saves this mesh to a file.
3262 * \details The file format is deduced from the extension.
3263 * Equivalent to mesh_save(*this, filename).
3264 * \param[in] filename the name of the file
3265 * \retval true on success
3266 */
3267 bool save(const std::string& filename) const;
3268
3269 /**
3270 * \brief Gets the list of all attributes.
3271 * \return a ';'-separated list of all attributes.
3272 */
3273 std::string get_attributes() const;
3274
3275 /**
3276 * \brief Gets the list of all scalar attributes.
3277 * \return a ';'-separated list of all scalar attributes.
3278 * \details Whenever there is a vector attribute v of dim d,
3279 * it appends v[0];v[1];...v[d-1] to the list.
3280 */
3281 std::string get_scalar_attributes() const;
3282
3283 /**
3284 * \brief Gets the list of all vector attributes.
3285 * \param[in] max_dim if non-zero, only vector attributes of
3286 * dimension lower than \p max_dim are returned.
3287 * \return a ';'-separated list of all vector attributes.
3288 */
3289 std::string get_vector_attributes(index_t max_dim = 0) const;
3290
3291 /**
3292 * \brief Gets the number of subelements types.
3293 * \return the number of subelements types.
3294 */
3295 index_t nb_subelements_types() const;
3296
3297 /**
3298 * \brief Gets a MeshSubElementsStore by index.
3299 * \param[in] i index of the subelements
3300 * \return a reference to the corresponding MeshSubElementsStore
3301 * \pre i < nb_subelements_types()
3302 */
3303 MeshSubElementsStore& get_subelements_by_index(index_t i);
3304
3305 /**
3306 * \brief Gets a MeshSubElementsStore by index.
3307 * \param[in] i index of the subelements
3308 * \return a const reference to the corresponding MeshSubElementsStore
3309 * \pre i < nb_subelements_types()
3310 */
3311 const MeshSubElementsStore& get_subelements_by_index(index_t i) const;
3312
3313
3314 /**
3315 * \brief Gets a MeshSubElementsStore by subelements type.
3316 * \param[in] what one of MESH_VERTICES, MESH_EDGES, MESH_FACETS,
3317 * MESH_FACET_CORNERS, MESH_CELLS, MESH_CELL_CORNERS, MESH_CELL_FACETS
3318 * \return a reference to the corresponding MeshSubElementsStore
3319 */
3320 MeshSubElementsStore& get_subelements_by_type(MeshElementsFlags what);
3321
3322 /**
3323 * \brief Gets a MeshSubElementsStore by subelements type.
3324 * \param[in] what one of MESH_VERTICES, MESH_EDGES, MESH_FACETS,
3325 * MESH_FACET_CORNERS, MESH_CELLS, MESH_CELL_CORNERS, MESH_CELL_FACETS
3326 * \return a const reference to the corresponding MeshSubElementsStore
3327 */
3328 const MeshSubElementsStore& get_subelements_by_type(
3329 MeshElementsFlags what
3330 ) const;
3331
3332 /**
3333 * \brief Gets a subelement name by subelement type.
3334 * \param[in] what one of MESH_VERTICES, MESH_EDGES, MESH_FACETS,
3335 * MESH_FACET_CORNERS, MESH_CELLS, MESH_CELL_CORNERS, MESH_CELL_FACETS
3336 * \return a string with the name of the subelement.
3337 */
3338 static std::string subelements_type_to_name(MeshElementsFlags what);
3339
3340 /**
3341 * \brief Gets a subelement type by subelement name.
3342 * \param[in] name the name of the subelement as a string
3343 * \return one of MESH_VERTICES, MESH_EDGES, MESH_FACETS,
3344 * MESH_FACET_CORNERS, MESH_CELLS, MESH_CELL_CORNERS, MESH_CELL_FACETS
3345 * or MESH_NONE if the name is invalid
3346 */
3347 static MeshElementsFlags name_to_subelements_type(
3348 const std::string& name
3349 );
3350
3351 /**
3352 * \brief Extracts localisation, name and optional component from
3353 * an attribute name.
3354 * \param[in] full_attribute_name for instance, facets.density, or
3355 * vertices.normal[0]
3356 * \param[out] where one of MESH_VERTICES, MESH_EDGES, MESH_FACETS,
3357 * MESH_FACET_CORNERS, MESH_CELLS, MESH_CELL_FACETS, MESH_CELL_CORNERS
3358 * \param[out] attribute_name the name of the attribute, without the
3359 * localisation and without the component
3360 * \param[out] component the component (between square brackets in
3361 * \p full_attribute_name) or 0 if no component was specified
3362 * \retval true if the attribute name could be parsed
3363 * \retval false if the attribute name has invalid syntax
3364 */
3365 static bool parse_attribute_name(
3366 const std::string& full_attribute_name,
3367 MeshElementsFlags& where,
3368 std::string& attribute_name,
3369 index_t& component
3370 );
3371
3372 protected:
3373 /**
3374 * \brief Displays the list of attributes to the Logger.
3375 * \param[in] tag the tag to be sent to the Logger
3376 * \param[in] subelement_name the name of the subelement
3377 * (vertices, facets, facet_corners ...)
3378 * \param[in] subelements a const reference to the MeshSubElementsStore
3379 */
3380 void display_attributes(
3381 const std::string& tag, const std::string& subelement_name,
3382 const MeshSubElementsStore& subelements
3383 ) const;
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 Mesh(const Mesh& rhs) = delete;
3393
3394 /**
3395 * \brief Forbids copy.
3396 * \details This is to make sure that client code does
3397 * not unintentionlly copies a Mesh (for
3398 * instance by passing it by-value to a function).
3399 * Use copy() instead.
3400 */
3401 const Mesh& operator=(const Mesh& rhs) = delete;
3402 };
3403
3404 /*************************************************************************/
3405 }
3406
3407 #endif
3408