Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
hash.c
Go to the documentation of this file.
1/* =============================================================================
2** This file is part of the mmg software package for the tetrahedral
3** mesh modification.
4** Copyright (c) Bx INP/CNRS/Inria/UBordeaux/UPMC, 2004-
5**
6** mmg is free software: you can redistribute it and/or modify it
7** under the terms of the GNU Lesser General Public License as published
8** by the Free Software Foundation, either version 3 of the License, or
9** (at your option) any later version.
10**
11** mmg is distributed in the hope that it will be useful, but WITHOUT
12** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13** FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14** License for more details.
15**
16** You should have received a copy of the GNU Lesser General Public
17** License and of the GNU General Public License along with mmg (in
18** files COPYING.LESSER and COPYING). If not, see
19** <http://www.gnu.org/licenses/>. Please read their terms carefully and
20** use this copy of the mmg distribution only if you accept them.
21** =============================================================================
22*/
23
35#include "mmgcommon_private.h"
36
58int MMG5_mmgHashTria(MMG5_pMesh mesh, MMG5_int *adjt, MMG5_Hash *hash, int chkISO) {
59 MMG5_pTria pt,pt1,pt2;
60 MMG5_hedge *ph;
61 MMG5_int kk;
62 MMG5_int *adja,hmax,k,ia,ib,jel,lel,dup,nmf;
63 int8_t i,i1,i2,j,l;
64 MMG5_int key;
65
66 /* adjust hash table params */
67 hmax =(MMG5_int)(3.71*mesh->np);
68 hash->siz = mesh->np;
69 hash->max = hmax + 1;
70 hash->nxt = hash->siz;
71 MMG5_ADD_MEM(mesh,(hash->max+1)*sizeof(MMG5_hedge),"hash table",return 0);
72 MMG5_SAFE_CALLOC(hash->item,hash->max+1,MMG5_hedge,return 0);
73
74 for (k=hash->siz; k<hash->max; k++)
75 hash->item[k].nxt = k+1;
76
77 if ( mesh->info.ddebug ) fprintf(stdout," h- stage 1: init\n");
78
79 /* hash triangles */
80 ++mesh->base;
81 dup = nmf = 0;
82 for (k=1; k<=mesh->nt; k++) {
83 pt = &mesh->tria[k];
84 if ( !MG_EOK(pt) ) continue;
85
86 pt->flag = 0;
87 // base field of triangles has to be setted because it is used in setadj (mmgs
88 // and mmg3d) to detect moebius strip and to flip tria orientation
89 pt->base = mesh->base;
90
91 adja = &adjt[3*(k-1)+1];
92 for (i=0; i<3; i++) {
93
94 if ( !MG_EOK(pt) ) continue;
95
96 /* Skip parallel edges */
97 if( (pt->tag[i] & MG_PARBDY) && !(pt->tag[i] & MG_PARBDYBDY) ) continue;
98
99 i1 = MMG5_inxt2[i];
100 i2 = MMG5_iprv2[i];
101
102 /* compute key */
103 ia = MG_MIN(pt->v[i1],pt->v[i2]);
104 ib = MG_MAX(pt->v[i1],pt->v[i2]);
105 key = (MMG5_KA*(int64_t)ia + MMG5_KB*(int64_t)ib) % hash->siz;
106 ph = &hash->item[key];
107
108 /* store edge */
109 if ( ph->a == 0 ) {
110 ph->a = ia;
111 ph->b = ib;
112 ph->k = 3*k + i;
113 ph->nxt = 0;
114 ++ph->s;
115 continue;
116 }
117 /* update info about adjacent */
118#ifndef NDEBUG
119 int8_t ok = 0;
120#endif
121 while ( ph->a ) {
122 if ( ph->a == ia && ph->b == ib ) {
123 jel = ph->k / 3;
124 j = ph->k % 3;
125 pt1 = &mesh->tria[jel];
126 /* discard duplicate face */
127 if ( pt1->v[j] == pt->v[i] ) {
128 pt->v[0] = 0;
129 dup++;
130 }
131 /* update adjacent */
132 else if ( !adjt[3*(jel-1)+1+j] ) {
133 adja[i] = 3*jel + j;
134 adjt[3*(jel-1)+1+j] = 3*k + i;
135 ++ph->s;
136 }
137 /* non-manifold case */
138 else if ( adja[i] != 3*jel+j ) {
139 lel = adjt[3*(jel-1)+1+j]/3;
140 l = adjt[3*(jel-1)+1+j]%3;
141 pt2 = &mesh->tria[lel];
142
143 if ( chkISO && ( (pt->ref == mesh->info.isoref) || (pt->ref < 0)) ) {
144 adjt[3*(lel-1)+1+l] = 0;
145 adja[i] = 3*jel+j;
146 adjt[3*(jel-1)+1+j] = 3*k + i;
147 }
148 pt->tag[i] |= MG_NOM;
149 pt1->tag[j] |= MG_NOM;
150 pt2->tag[l] |= MG_NOM;
151 nmf++;
152 ++ph->s;
153 }
154#ifndef NDEBUG
155 ok = 1;
156#endif
157 break;
158 }
159 else if ( !ph->nxt ) {
160 ph->nxt = hash->nxt;
161 ph = &hash->item[ph->nxt];
162 assert(ph);
163
164 if ( hash->nxt >= hash->max-1 ) {
165 if ( mesh->info.ddebug ) {
166 fprintf(stderr,"\n ## Warning: %s: memory alloc problem (edge):"
167 " %" MMG5_PRId "\n",__func__,hash->max);
168 }
170 "MMG5_edge",
171 MMG5_DEL_MEM(mesh,hash->item);
172 return 0);
173
174 ph = &hash->item[hash->nxt];
175
176 for (kk=ph->nxt; kk<hash->max; kk++)
177 hash->item[kk].nxt = kk+1;
178 }
179
180 hash->nxt = ph->nxt;
181 ph->a = ia;
182 ph->b = ib;
183 ph->k = 3*k + i;
184 ph->nxt = 0;
185 ++ph->s;
186#ifndef NDEBUG
187 ok = 1;
188#endif
189 break;
190 }
191 else
192 ph = &hash->item[ph->nxt];
193 }
194 assert(ok);
195 }
196 }
197
198 /* Now loop on "only" parallel edges in order to add a MG_BDY tag on those
199 * that are found in the hash table and their adjacents (if manifold; in the
200 * non-manifold case the MG_NOM tag suffices).
201 *
202 * Rationale:
203 * - put MG_BDY tags on edges that are contact edges between a "true"
204 * geometrical boundary (!MG_PARBDY || (MG_PARBDY && MG_PARBDYBDY) and a
205 * purele parallel (non-geometrical) one (MG_PARBDY && !MG_PARBDYBDY);
206 * - add also a MG_PARBDYBDY tag on those edges (as it cannot be inherited
207 * from any triangle there) and their extremities.
208 */
209 for (k=1; k<=mesh->nt; k++) {
210 pt = &mesh->tria[k];
211 if ( !MG_EOK(pt) ) continue;
212 for (i=0; i<3; i++) {
213 if( !(pt->tag[i] & MG_PARBDY) || (pt->tag[i] & MG_PARBDYBDY) ) continue;
214 i1 = MMG5_inxt2[i];
215 i2 = MMG5_iprv2[i];
216
217 /* compute key */
218 ia = MG_MIN(pt->v[i1],pt->v[i2]);
219 ib = MG_MAX(pt->v[i1],pt->v[i2]);
220 key = (MMG5_KA*(int64_t)ia + MMG5_KB*(int64_t)ib) % hash->siz;
221 ph = &hash->item[key];
222
223 if ( ph->a == 0 ) continue;
224 while( ph->a ) {
225 if ( ph->a == ia && ph->b == ib ) {
226 jel = ph->k / 3;
227 j = ph->k % 3;
228 pt1 = &mesh->tria[jel];
229 pt1->tag[j] |= MG_BDY + MG_PARBDYBDY;
230 mesh->point[ia].tag |= MG_PARBDYBDY;
231 mesh->point[ib].tag |= MG_PARBDYBDY;
232 /* update adjacent */
233 lel = adjt[3*(jel-1)+1+j]/3;
234 l = adjt[3*(jel-1)+1+j]%3;
235 if( lel ) {
236 pt2 = &mesh->tria[lel];
237 pt2->tag[l] |= MG_BDY + MG_PARBDYBDY;
238 mesh->point[ia].tag |= MG_PARBDYBDY;
239 mesh->point[ib].tag |= MG_PARBDYBDY;
240 }
241 break;
242 } else if ( !ph->nxt ) {
243 break;
244 } else {
245 ph = &hash->item[ph->nxt];
246 }
247 }
248 }
249 }
250
251 /* set tag */
252 for (k=1; k<=mesh->nt; k++) {
253 pt = &mesh->tria[k];
254 for (i=0; i<3; i++) {
255 if ( pt->tag[i] & MG_NOM ) {
256 mesh->point[pt->v[MMG5_inxt2[i]]].tag |= MG_NOM;
257 mesh->point[pt->v[MMG5_iprv2[i]]].tag |= MG_NOM;
258 }
259 }
260 }
261
262 if ( abs(mesh->info.imprim) > 5 && dup+nmf > 0 ) {
263 fprintf(stdout," ## "); fflush(stdout);
264 if ( nmf > 0 ) fprintf(stdout,"[non-manifold model] ");
265 if ( dup > 0 ) fprintf(stdout," %" MMG5_PRId " duplicate removed",dup);
266 fprintf(stdout,"\n");
267 }
268 if ( mesh->info.ddebug ) fprintf(stdout," h- completed.\n");
269
270 return 1;
271}
272
286MMG5_int MMG5_hashFace(MMG5_pMesh mesh,MMG5_Hash *hash,MMG5_int ia,MMG5_int ib,MMG5_int ic,MMG5_int k) {
287 MMG5_hedge *ph;
288 MMG5_int key;
289 MMG5_int mins,maxs,sum,j;
290
291 mins = MG_MIN(ia,MG_MIN(ib,ic));
292 maxs = MG_MAX(ia,MG_MAX(ib,ic));
293
294 /* compute key */
295 sum = ia + ib + ic;
296 key = (MMG5_KA*(int64_t)mins + MMG5_KB*(int64_t)maxs) % hash->siz;
297 ph = &hash->item[key];
298
299 if ( ph->a ) {
300 if ( ph->a == mins && ph->b == maxs && ph->s == sum )
301 return ph->k;
302 else {
303 while ( ph->nxt && ph->nxt < hash->max ) {
304 ph = &hash->item[ph->nxt];
305 if ( ph->a == mins && ph->b == maxs && ph->s == sum ) return ph->k;
306 }
307 }
308 ph->nxt = hash->nxt;
309 ph = &hash->item[hash->nxt];
310 ph->a = mins;
311 ph->b = maxs;
312 ph->s = sum;
313 ph->k = k;
314 hash->nxt = ph->nxt;
315 ph->nxt = 0;
316
317 if ( hash->nxt >= hash->max ) {
318 MMG5_TAB_RECALLOC(mesh,hash->item,hash->max,MMG5_GAP,MMG5_hedge,"face",return 0;);
319 for (j=hash->nxt; j<hash->max; j++) hash->item[j].nxt = j+1;
320 }
321 return -1;
322 }
323
324 /* insert new face */
325 ph->a = mins;
326 ph->b = maxs;
327 ph->s = sum;
328 ph->k = k;
329 ph->nxt = 0;
330
331 return -1;
332}
333
346int MMG5_hashEdge(MMG5_pMesh mesh,MMG5_Hash *hash, MMG5_int a,MMG5_int b,MMG5_int k) {
347 MMG5_hedge *ph;
348 MMG5_int key;
349 MMG5_int ia,ib,j;
350
351 ia = MG_MIN(a,b);
352 ib = MG_MAX(a,b);
353 key = (MMG5_KA*(int64_t)ia + MMG5_KB*(int64_t)ib) % hash->siz;
354 ph = &hash->item[key];
355
356 if ( ph->a == ia && ph->b == ib )
357 return 1;
358 else if ( ph->a ) {
359 while ( ph->nxt && ph->nxt < hash->max ) {
360 ph = &hash->item[ph->nxt];
361 if ( ph->a == ia && ph->b == ib ) return 1;
362 }
363 ph->nxt = hash->nxt;
364 ph = &hash->item[hash->nxt];
365
366 if ( hash->nxt >= hash->max-1 ) {
367 if ( mesh->info.ddebug )
368 fprintf(stderr,"\n ## Warning: %s: memory alloc problem (edge):"
369 " %" MMG5_PRId "\n",__func__,hash->max);
370
372 "MMG5_edge",return 0);
373 /* ph pointer may be false after realloc */
374 ph = &hash->item[hash->nxt];
375
376 for (j=ph->nxt; j<hash->max; j++) hash->item[j].nxt = j+1;
377 }
378 hash->nxt = ph->nxt;
379 }
380
381 /* insert new edge */
382 ph->a = ia;
383 ph->b = ib;
384 ph->k = k;
385 ph->nxt = 0;
386
387 return 2;
388}
389
390
404int MMG5_hashUpdate(MMG5_Hash *hash, MMG5_int a,MMG5_int b,MMG5_int k) {
405 MMG5_hedge *ph;
406 MMG5_int key;
407 MMG5_int ia,ib;
408
409 ia = MG_MIN(a,b);
410 ib = MG_MAX(a,b);
411 key = (MMG5_KA*(int64_t)ia + MMG5_KB*(int64_t)ib) % hash->siz;
412 ph = &hash->item[key];
413
414 while ( ph->a ) {
415 if ( ph->a == ia && ph->b == ib ) {
416 ph->k = k;
417 return 1;
418 }
419
420 if ( !ph->nxt ) return 0;
421
422 ph = &hash->item[ph->nxt];
423
424 }
425
426 return 0;
427}
428
441int MMG5_hashEdgeTag(MMG5_pMesh mesh,MMG5_Hash *hash, MMG5_int a,MMG5_int b,uint16_t tag) {
442 MMG5_hedge *ph;
443 MMG5_int key;
444 MMG5_int ia,ib,j;
445
446 ia = MG_MIN(a,b);
447 ib = MG_MAX(a,b);
448 key = (MMG5_KA*(int64_t)ia + MMG5_KB*(int64_t)ib) % hash->siz;
449 ph = &hash->item[key];
450
451 if ( ph->a ) {
452 if ( ph->a == ia && ph->b == ib ) {
453 ph->k |= tag;
454 return ph->k;
455 }
456 else {
457 while ( ph->nxt && ph->nxt < hash->max ) {
458 ph = &hash->item[ph->nxt];
459 if ( ph->a == ia && ph->b == ib ) {
460 ph->k |= tag;
461 return ph->k;
462 }
463 }
464 }
465 ph->nxt = hash->nxt;
466 ph = &hash->item[hash->nxt];
467 ph->a = ia;
468 ph->b = ib;
469 ph->k = tag;
470 hash->nxt = ph->nxt;
471 ph->nxt = 0;
472
473 if ( hash->nxt >= hash->max ) {
475 "edge hash table",return 0);
476 for (j=hash->nxt; j<hash->max; j++) hash->item[j].nxt = j+1;
477 }
478 return tag;
479 }
480
481 /* insert new edge */
482 ph->a = ia;
483 ph->b = ib;
484 ph->k = tag;
485 ph->nxt = 0;
486
487 return tag;
488}
489
501MMG5_int MMG5_hashGet(MMG5_Hash *hash,MMG5_int a,MMG5_int b) {
502 MMG5_hedge *ph;
503 MMG5_int key;
504 MMG5_int ia,ib;
505
506 if ( !hash->item ) return 0;
507
508 ia = MG_MIN(a,b);
509 ib = MG_MAX(a,b);
510 key = (MMG5_KA*(int64_t)ia + MMG5_KB*(int64_t)ib) % hash->siz;
511 ph = &hash->item[key];
512
513 if ( !ph->a ) return 0;
514 if ( ph->a == ia && ph->b == ib ) return ph->k;
515 while ( ph->nxt ) {
516 ph = &hash->item[ph->nxt];
517 if ( ph->a == ia && ph->b == ib ) return ph->k;
518 }
519 return 0;
520}
521
532int MMG5_hashNew(MMG5_pMesh mesh,MMG5_Hash *hash,MMG5_int hsiz,MMG5_int hmax) {
533 MMG5_int k;
534
535 /* adjust hash table params */
536 hash->siz = hsiz+1;
537 hash->max = hmax + 2;
538 hash->nxt = hash->siz;
539
540 MMG5_ADD_MEM(mesh,(hash->max+1)*sizeof(MMG5_hedge),"hash table",
541 return 0);
542 MMG5_SAFE_CALLOC(hash->item,(hash->max+1),MMG5_hedge,return 0);
543
544 for (k=hash->siz; k<hash->max; k++)
545 hash->item[k].nxt = k+1;
546
547 return 1;
548}
if(!ier) exit(EXIT_FAILURE)
MMG5_pMesh * mesh
MMG5_int MMG5_hashFace(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int ia, MMG5_int ib, MMG5_int ic, MMG5_int k)
Definition: hash.c:286
int MMG5_mmgHashTria(MMG5_pMesh mesh, MMG5_int *adjt, MMG5_Hash *hash, int chkISO)
Definition: hash.c:58
int MMG5_hashEdgeTag(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int a, MMG5_int b, uint16_t tag)
Definition: hash.c:441
int MMG5_hashUpdate(MMG5_Hash *hash, MMG5_int a, MMG5_int b, MMG5_int k)
Definition: hash.c:404
int MMG5_hashNew(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int hsiz, MMG5_int hmax)
Definition: hash.c:532
MMG5_int MMG5_hashGet(MMG5_Hash *hash, MMG5_int a, MMG5_int b)
Definition: hash.c:501
int MMG5_hashEdge(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int a, MMG5_int b, MMG5_int k)
Definition: hash.c:346
#define MMG5_SAFE_CALLOC(ptr, size, type, law)
#define MG_EOK(pt)
#define MG_PARBDY
#define MG_MIN(a, b)
#define MG_MAX(a, b)
#define MMG5_GAP
#define MMG5_ADD_MEM(mesh, size, message, law)
static const uint8_t MMG5_iprv2[3]
#define MMG5_KB
#define MMG5_TAB_RECALLOC(mesh, ptr, initSize, wantedGap, type, message, law)
static const uint8_t MMG5_inxt2[6]
#define MG_BDY
#define MG_NOM
#define MMG5_KA
#define MG_PARBDYBDY
#define MMG5_DEL_MEM(mesh, ptr)
Identic as MMG5_HGeom but use MMG5_hedge to store edges instead of MMG5_hgeom (memory economy).
Definition: libmmgtypes.h:603
MMG5_int max
Definition: libmmgtypes.h:604
MMG5_int nxt
Definition: libmmgtypes.h:604
MMG5_hedge * item
Definition: libmmgtypes.h:605
MMG5_int siz
Definition: libmmgtypes.h:604
int8_t ddebug
Definition: libmmgtypes.h:539
MMG5_int isoref
Definition: libmmgtypes.h:528
MMG mesh structure.
Definition: libmmgtypes.h:613
MMG5_Info info
Definition: libmmgtypes.h:659
MMG5_pPoint point
Definition: libmmgtypes.h:649
double gap
Definition: libmmgtypes.h:616
MMG5_int base
Definition: libmmgtypes.h:624
MMG5_int nt
Definition: libmmgtypes.h:620
MMG5_pTria tria
Definition: libmmgtypes.h:655
MMG5_int np
Definition: libmmgtypes.h:620
uint16_t tag
Definition: libmmgtypes.h:290
Structure to store triangles of a MMG mesh.
Definition: libmmgtypes.h:338
MMG5_int ref
Definition: libmmgtypes.h:341
MMG5_int flag
Definition: libmmgtypes.h:347
uint16_t tag[3]
Definition: libmmgtypes.h:348
MMG5_int base
Definition: libmmgtypes.h:342
MMG5_int v[3]
Definition: libmmgtypes.h:340
Used to hash edges (memory economy compared to MMG5_hgeom).
Definition: libmmgtypes.h:592
MMG5_int s
Definition: libmmgtypes.h:595
MMG5_int b
Definition: libmmgtypes.h:593
MMG5_int a
Definition: libmmgtypes.h:593
MMG5_int k
Definition: libmmgtypes.h:594
MMG5_int nxt
Definition: libmmgtypes.h:593