| 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 H_HEXDOM_ALGO_MESH_UTILS_H | ||
| 41 | #define H_HEXDOM_ALGO_MESH_UTILS_H | ||
| 42 | |||
| 43 | #include <exploragram/basic/common.h> | ||
| 44 | #include <exploragram/hexdom/basic.h> | ||
| 45 | #include <geogram/basic/attributes.h> | ||
| 46 | #include <geogram/mesh/mesh.h> | ||
| 47 | |||
| 48 | namespace GEO { | ||
| 49 | |||
| 50 | ✗ | inline index_t cell_facet_corner_id(Mesh* m, index_t c, index_t cf, index_t cfc) { | |
| 51 | ✗ | return m->cells.corner(c, m->cells.descriptor(c).facet_vertex[cf][cfc]); | |
| 52 | } | ||
| 53 | |||
| 54 | void EXPLORAGRAM_API compute_3D_edge_cot_w(Mesh* m, Attribute<index_t>& v2e, double anisoZ_cotW); | ||
| 55 | |||
| 56 | /** | ||
| 57 | * remove vertices that are not referenced in cells/facets/edges | ||
| 58 | */ | ||
| 59 | void EXPLORAGRAM_API kill_isolated_vertices(Mesh* m); | ||
| 60 | |||
| 61 | /** | ||
| 62 | * merges vertices that are close (see GEO::colocate for details about distance guaranty) | ||
| 63 | * update references to vertices in cells/facets/edges | ||
| 64 | */ | ||
| 65 | void EXPLORAGRAM_API merge_vertices(Mesh* m, double eps); | ||
| 66 | |||
| 67 | |||
| 68 | void EXPLORAGRAM_API facets_smooth_geom(Mesh* m, std::vector<bool>& lock_v, double fit_coeff = .95); | ||
| 69 | |||
| 70 | void EXPLORAGRAM_API cells_smooth_geom(Mesh* m, std::vector<bool>& lock_v, double fit_coeff = .95); | ||
| 71 | |||
| 72 | void EXPLORAGRAM_API facets_smooth_geom(Mesh* m, double fit_coeff = .95); | ||
| 73 | |||
| 74 | void EXPLORAGRAM_API cells_smooth_geom(Mesh* m, double fit_coeff = .95); | ||
| 75 | |||
| 76 | void EXPLORAGRAM_API create_non_manifold_facet_adjacence(Mesh* m); | ||
| 77 | |||
| 78 | |||
| 79 | ✗ | inline vec3* X(Mesh* m) { return (vec3*)m->vertices.point_ptr(0); } | |
| 80 | ✗ | inline vec3 cell_bary(Mesh* m, index_t c){ | |
| 81 | ✗ | vec3 ave(0, 0, 0); | |
| 82 | ✗ | FOR(lv, m->cells.nb_vertices(c)) ave += m->vertices.point(m->cells.vertex(c, lv)); | |
| 83 | ✗ | return ave / double(m->cells.nb_vertices(c)); | |
| 84 | } | ||
| 85 | |||
| 86 | inline vec3 cell_facet_bary(Mesh* m, index_t c, index_t lf){ | ||
| 87 | vec3 ave(0, 0, 0); | ||
| 88 | FOR(lv, m->cells.facet_nb_vertices(c, lf)) ave += m->vertices.point(m->cells.facet_vertex(c, lf, lv)); | ||
| 89 | return ave / double(m->cells.facet_nb_vertices(c, lf)); | ||
| 90 | } | ||
| 91 | |||
| 92 | ✗ | inline vec3 facet_bary(Mesh* m, index_t f){ | |
| 93 | ✗ | vec3 ave(0, 0, 0); | |
| 94 | ✗ | FOR(lv, m->facets.nb_vertices(f)) ave += m->vertices.point(m->facets.vertex(f, lv)); | |
| 95 | ✗ | return ave / double(m->facets.nb_vertices(f)); | |
| 96 | } | ||
| 97 | |||
| 98 | EXPLORAGRAM_API double get_cell_average_edge_size( Mesh* mesh); | ||
| 99 | EXPLORAGRAM_API double get_facet_average_edge_size( Mesh* mesh); | ||
| 100 | EXPLORAGRAM_API vec3 tet_facet_cross(Mesh* m, index_t c, index_t lf); | ||
| 101 | EXPLORAGRAM_API index_t next_cell_around_oriented_edge(Mesh* m, index_t cell_id, index_t v_org, index_t v_dest); | ||
| 102 | |||
| 103 | |||
| 104 | |||
| 105 | |||
| 106 | /* __ __ _ _ _______ _ | ||
| 107 | * | \/ | | | (_) |__ __| | | | ||
| 108 | * | \ / | __ _ _ __ ___| |__ _ _ __ __ _ | | ___| |_ ___ | ||
| 109 | * | |\/| |/ _` | '__/ __| '_ \| | '_ \ / _` | | |/ _ \ __/ __| | ||
| 110 | * | | | | (_| | | | (__| | | | | | | | (_| | | | __/ |_\__ \ | ||
| 111 | * |_| |_|\__,_|_| \___|_| |_|_|_| |_|\__, | |_|\___|\__|___/ | ||
| 112 | * __/ | | ||
| 113 | * |___/ | ||
| 114 | */ | ||
| 115 | |||
| 116 | extern EXPLORAGRAM_API const index_t tet_edge_vertices[6][2]; | ||
| 117 | extern EXPLORAGRAM_API const index_t MT[16][4]; | ||
| 118 | |||
| 119 | |||
| 120 | inline const index_t* MTcase(double iso, double v0, double v1, double v2, double v3){ | ||
| 121 | index_t triindex = 0; | ||
| 122 | if (v0 < iso) triindex |= 1; | ||
| 123 | if (v1 < iso) triindex |= 2; | ||
| 124 | if (v2 < iso) triindex |= 4; | ||
| 125 | if (v3 < iso) triindex |= 8; | ||
| 126 | return &(MT[triindex][0]); | ||
| 127 | } | ||
| 128 | |||
| 129 | |||
| 130 | /** | ||
| 131 | * uv is a pointer because it is an optional parameter (can be nullptr) | ||
| 132 | */ | ||
| 133 | inline index_t add_facet_to_mesh(Mesh* m, vector<vec3>& pts, Attribute<vec2>* uv = nullptr, vector<vec2>* lU = nullptr){ | ||
| 134 | index_t off = m->vertices.create_vertices(pts.size()); | ||
| 135 | vector<index_t> nv(pts.size()); | ||
| 136 | FOR(lv ,pts.size()) { | ||
| 137 | nv[lv] = off + lv; | ||
| 138 | m->vertices.point(nv[lv]) = pts[lv]; | ||
| 139 | } | ||
| 140 | index_t f = m->facets.create_polygon(nv); | ||
| 141 | if (uv != nullptr) FOR(lc,m->facets.nb_corners(f))//FOR_EACH_HALFEDGE_OF_FACET(m,h,f) | ||
| 142 | (*uv)[m->facets.corner(f,lc)] = (*lU)[lc]; | ||
| 143 | return f; | ||
| 144 | } | ||
| 145 | |||
| 146 | template <class T> inline void get_range(Attribute<T> &attr, double& v_min, double &v_max) { | ||
| 147 | v_min = 1e20; | ||
| 148 | v_max = -1e20; | ||
| 149 | FOR(i, attr.nb_elements()) { | ||
| 150 | v_min = std::min(v_min, attr[i]); | ||
| 151 | v_max = std::max(v_max, attr[i]); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | } | ||
| 156 | |||
| 157 | #endif | ||
| 158 |