Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
PRoctree_3d.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
37#include "libmmgtypes.h"
38#include "mmgcommon_private.h"
39#include "PRoctree_3d_private.h"
40#include <stdio.h>
41
49{
50 q->nbVer = 0;
51 q->depth = 0;
52 q->v = NULL;
53 q->branches = NULL;
54}
55
66{
67 MMG5_int i;
68
69 MMG5_ADD_MEM(mesh,sizeof(MMG3D_PROctree),"PROctree structure",
70 return 0);
71 MMG5_SAFE_MALLOC(*q,1, MMG3D_PROctree, return 0);
72
73
74 // set nv to the next power of 2
75 nv--;
76 nv |= nv >> 1;
77 nv |= nv >> 2;
78 nv |= nv >> 4;
79 nv |= nv >> 8;
80 nv |= nv >> 16;
81 nv++;
82 (*q)->nv = nv;
83
84 // Number maximum of cells listed for the zone search
85 (*q)->nc = MG_MAX(2048/nv,16);
86
87 MMG5_ADD_MEM(mesh,sizeof(MMG3D_PROctree_s),"initial PROctree cell",
88 return 0);
89
90 MMG5_SAFE_MALLOC((*q)->q0,1, MMG3D_PROctree_s, return 0);
91 MMG3D_initPROctree_s((*q)->q0);
92
93 for (i=1;i<=mesh->np; ++i)
94 {
95 if ( !MG_VOK(&mesh->point[i]) ) continue;
96 if (mesh->point[i].tag & MG_BDY) continue;
97
98 if(!MMG3D_addPROctree(mesh, (*q), i))
99 return 0;
100
101 }
102 return 1;
103}
104
114{
115 int nbBitsInt,depthMax,dim,i,sizBr,nvTemp;
116
117 dim = mesh->dim;
118 sizBr = 1<<dim;
119 nbBitsInt = sizeof(int64_t)*8;
120 depthMax = nbBitsInt/dim - 1;
121
122 if (q->nbVer>nv && q->depth < depthMax )
123 {
124 for ( i = 0; i<sizBr; i++)
125 {
126 MMG3D_freePROctree_s(mesh,&(q->branches[i]), nv);
127 }
129 q->branches = NULL;
130 }
131 else if (q->nbVer>0)
132 {
133 if ( q->nbVer<= nv )
134 {
135 nvTemp = q->nbVer;
136 nvTemp--;
137 nvTemp |= nvTemp >> 1;
138 nvTemp |= nvTemp >> 2;
139 nvTemp |= nvTemp >> 4;
140 nvTemp |= nvTemp >> 8;
141 nvTemp |= nvTemp >> 16;
142 nvTemp++;
143
144 MMG5_DEL_MEM(mesh,q->v);
145 q->v = NULL;
146 q->nbVer = 0;
147 }else
148 {
149 assert(q->v);
150 MMG5_DEL_MEM(mesh,q->v);
151 q->v = NULL;
152 q->nbVer = 0;
153 }
154 }
155}
156
165{
166 MMG3D_freePROctree_s(mesh,(*q)->q0, (*q)->nv);
167 MMG5_DEL_MEM(mesh,(*q)->q0);
168 (*q)->q0 = NULL;
169 MMG5_DEL_MEM(mesh,*q);
170 *q = NULL;
171}
172
173
183int64_t MMG3D_getPROctreeCoordinate(MMG3D_pPROctree q, double* ver, int dim)
184{
185 int64_t s = 1<<20;
186 double prec = 1./(1<<30);
187 int place = 0;
188 int ix = (int)floor((ver[0]-prec)*s);
189 int iy = (int)floor((ver[1]-prec)*s);
190 int iz = (int)floor((ver[2]-prec)*s);
191 ix = (ix > 0) ? ix:0;
192 iy = (iy > 0) ? iy:0;
193 iz = (iz > 0) ? iz:0;
194 int64_t i=0;
195 int j;
196 for(j=19; j>=0; j--)
197 {
198 s=s>>1;
199 i += ((ix & s) >> j)<<place;
200 place++;
201 i += ((iy & s) >> j)<<place;
202 place++;
203 i += ((iz & s) >> j)<<place;
204 place++;
205 }
206 return i;
207}
208
209
210
225int MMG3D_movePROctree(MMG5_pMesh mesh, MMG3D_pPROctree q, MMG5_int no, double* newVer, double* oldVer)
226{
227 int64_t oldCoor, newCoor;
228 double pt[3];
229 int dim;
230
231 dim = mesh->dim;
232
233 memcpy(&pt, oldVer ,dim*sizeof(double));
234 oldCoor = MMG3D_getPROctreeCoordinate(q, oldVer, dim);
235 memcpy(&pt, newVer ,dim*sizeof(double));
236 newCoor = MMG3D_getPROctreeCoordinate(q, mesh->point[no].c, dim);
237
238 if (newCoor == oldCoor) {
239 return 1;
240 }
241 else // it could be possible to combine delPROctree and addPROctree to keep it local...
242 {
243 /* delPROctree */
244 memcpy(&pt, oldVer ,dim*sizeof(double));
245 if (!MMG3D_delPROctreeRec(mesh, q->q0, pt , no, q->nv))
246 return 0;
247
248 /* addPROctree */
249 memcpy(&pt, newVer ,dim*sizeof(double));
250 if(!MMG3D_addPROctreeRec(mesh, q->q0, pt , no, q->nv))
251 return 0;
252 }
253 return 1;
254}
255
265int MMG3D_isCellIncluded(double* cellCenter, double l, double* zoneCenter, double l0)
266{
267 double x,y,z,r1;//r2,rmax;
268
269 x = cellCenter[0]-zoneCenter[0];
270 y = cellCenter[1]-zoneCenter[1];
271 z = cellCenter[2]-zoneCenter[2];
272
273 r1 = sqrt(x*x+y*y+z*z);
274
275 // to avoid sqrt :
276 //~ r1 = x*x+y*y+z*z;
277 //~ r2 = 3*l*l;
278 //~ rmax = MG_MAX(r1,r2);
279 //sqrt(3)=1.7320508...
280 //~ return (r1+r2+2*rmax<l0*l0);
281
282 return (r1+1.732051*l<l0);
283}
284
285
298void MMG3D_placeInListDouble(double* distList, double dist, int index, int size)
299{
300 memmove(&(distList[index+2]),&(distList[index+1]),(size-(index+1))*sizeof(double));
301 distList[index+1] = dist;
302}
303
316void MMG3D_placeInListPROctree(MMG3D_PROctree_s** qlist, MMG3D_PROctree_s* q, int index, int size)
317{
318 memmove(&(qlist[index+2]),&(qlist[index+1]),(size-(index+1))*sizeof(MMG3D_PROctree_s*));
319 #ifdef DEBUG
320 if (index+2+(size-(index+1))>61 || index+1<0)
321 fprintf(stderr, "\n ## Error: %s: index"
322 " too large %i > 61\n",__func__, index+2+(size-(index+1));
323 #endif
324 qlist[index+1] = q;
325}
326
337int MMG3D_seekIndex (double* distList, double dist, int indexMin, int indexMax)
338{
339 int indexMed;
340
341 if (indexMin > indexMax)
342 MMG3D_seekIndex(distList, dist, indexMax, indexMin);
343 else if (indexMax - indexMin <2)
344 {
345 #ifdef DEBUG
346 if (indexMin >= 60 || indexMax>=60)
347 fprintf(stderr,"\n ## Error: %s: index should not be that large %i %i.\n",
348 __func__,indexMin, indexMax);
349 #endif
350 if (dist > distList[indexMax])
351 return indexMax;
352 else
353 return indexMin;
354 }
355 else
356 {
357 indexMed = (indexMin + indexMax)/2;
358
359 #ifdef DEBUG
360 if (indexMed >= 60 || indexMed < 0)
361 fprintf(stderr,"\n ## Error: %s: index should not be that large %i.\n",
362 __func__,indexMed);
363 #endif
364
365 if (dist > distList[indexMed])
366 MMG3D_seekIndex(distList, dist, indexMed, indexMax);
367 else
368 MMG3D_seekIndex(distList, dist, indexMin, indexMed);
369 }
370 return 1;
371}
372
385int MMG3D_intersectRect(double *rectin, double *rectinout)
386{
387 double rect1Temp[6], rect2Temp[6];
388
389 rect1Temp[0] = rectin[0];
390 rect1Temp[1] = rectin[1];
391 rect1Temp[2] = rectin[2];
392 rect1Temp[3] = rectin[3]+rectin[0];
393 rect1Temp[4] = rectin[4]+rectin[1];
394 rect1Temp[5] = rectin[5]+rectin[2];
395
396 rect2Temp[0] = rectinout[0];
397 rect2Temp[1] = rectinout[1];
398 rect2Temp[2] = rectinout[2];
399 rect2Temp[3] = rectinout[3]+rectinout[0];
400 rect2Temp[4] = rectinout[4]+rectinout[1];
401 rect2Temp[5] = rectinout[5]+rectinout[2];
402
403 rectinout[0] = rect1Temp[0]>rect2Temp[0] ? rect1Temp[0]:rect2Temp[0];
404 rectinout[1] = rect1Temp[1]>rect2Temp[1] ? rect1Temp[1]:rect2Temp[1];
405 rectinout[2] = rect1Temp[2]>rect2Temp[2] ? rect1Temp[2]:rect2Temp[2];
406 rectinout[3] = rect1Temp[3]<rect2Temp[3] ? rect1Temp[3]:rect2Temp[3];
407 rectinout[4] = rect1Temp[4]<rect2Temp[4] ? rect1Temp[4]:rect2Temp[4];
408 rectinout[5] = rect1Temp[5]<rect2Temp[5] ? rect1Temp[5]:rect2Temp[5];
409
410 rectinout[3] = rectinout[3] - rectinout[0];
411 rectinout[4] = rectinout[4] - rectinout[1];
412 rectinout[5] = rectinout[5] - rectinout[2];
413
414 if ( rectinout[3]<=0 || rectinout[4]<=0 || rectinout[5]<=0 ) return 0;
415
416 return 1;
417}
418
443int MMG3D_getListSquareRec(MMG3D_PROctree_s* q, double* center, double* rect,
444 MMG3D_PROctree_s*** qlist, double* dist, double* ani,
445 double l0, int nc, int dim, int* index)
446{
447 double recttemp[6];
448 double centertemp[3];
449 int recCenter[6];
450 double l = 1./(1<<(q->depth+1));
451 double distTemp;
452 double x,y,z;
453 int indexTemp,i,j,k,nBranch;
454
455 // number max of PROctree cells listed for one search
456 if ((*index)>nc-4)
457 return 1;
458
459 // check if the current cell is included in the search zone, can avoid
460 // the loop over the vertices. Never occured in tests unless nc==4, in that
461 // case, there is no gain in computing time.
462 //~ if (q->nbVer>0 && MMG3D_isCellIncluded(center, l, &(dist[nc-3]), l0))
463 //~ {
464 //~ (*index)=nc-3;
465 //~ fprintf(stdout,"Included cell found\n");
466 //~ return;
467 //~ }
468
469 assert ( nc>= 3 );
470 if (q->branches==NULL && q->v != NULL)
471 {
472 // the vector dist is of size nc whereas qlist allows nc-3 inputs
473 // so the 3 last values can contain the coordinates of the center
474 // of the search volume.
475 x = dist[nc-3] - center[0];
476 y = dist[nc-2] - center[1];
477 z = dist[nc-1] - center[2];
478
479 // Should be replaced with distance in metric?
480 distTemp = x*x+y*y+z*z;
481
482 // Here the anisotropic distance not tested (not so important, this only
483 // reorders the cells)
484 //~ distTemp = ani[0]*x*x+ani[3]*y*y+ani[5]*z*z+
485 //~ 2*(ani[1]*x*y+ani[2]*x*z+ani[4]*y*z);
486 if (*index > 0)
487 {
488 indexTemp = MMG3D_seekIndex(dist,distTemp,0, *index-1);
489 if (indexTemp+1<*index)
490 {
491 MMG3D_placeInListDouble(dist, distTemp, indexTemp, *index);
492 MMG3D_placeInListPROctree((*qlist), q, indexTemp, *index);
493 }else
494 {
495 dist[*index]=distTemp;
496 (*qlist)[*index]=q;
497 }
498 }
499 else
500 {
501 dist[*index]=distTemp;
502 (*qlist)[*index]=q;
503 }
504
505 (*index)++;
506
507 }else if (q->branches!=NULL)
508 {
509
510 // check the position of the search zone in the current cell
511 for (i=0;i<3;i++)
512 {
513 recCenter[i] = (rect[i]>center[i]);
514 recCenter[i+3] = ((rect[i]+rect[i+3])>center[i]);
515 }
516
517 // three loop describing the 8 branches in binary (k,j,i):(0,0,0),(0,0,1)....(1,1,1)
518 for(i=0;i<2;i++)
519 {
520 for(j=0;j<2;j++)
521 {
522 for(k=0;k<2;k++)
523 {
524 // test if that branch intersects the rectangle
525 if (((i && recCenter[3]) || (!i && !recCenter[0])) &&
526 ((j && recCenter[4]) || (!j && !recCenter[1]))&&
527 ((k && recCenter[5]) || (!k && !recCenter[2])))
528 {
529 // set the branch number
530 nBranch = i+2*j+4*k;
531
532 // set recttemp to the cell size of the branch nBranch
533 recttemp[0] = center[0]-l*(1-i);
534 recttemp[1] = center[1]-l*(1-j);
535 recttemp[2] = center[2]-l*(1-k);
536 recttemp[3] = recttemp[4] = recttemp[5] = l;
537 // intersect the rectangle and the cell and store it in recttemp
538 if ( !MMG3D_intersectRect(rect,recttemp) ) return 0;
539
540 // set the new center
541 centertemp[0] = center[0]-l/2+i*l;
542 centertemp[1] = center[1]-l/2+j*l;
543 centertemp[2] = center[2]-l/2+k*l;
544
545 // recursive call in the branch
546 if ( !MMG3D_getListSquareRec(&(q->branches[nBranch]),
547 centertemp, recttemp, qlist, dist,
548 ani, l0, nc, dim, index) )
549 return 0;
550 }
551 }
552 }
553 }
554 }
555 return 1;
556}
557
574int MMG3D_getListSquare(MMG5_pMesh mesh, double* ani, MMG3D_pPROctree q, double* rect,
575 MMG3D_PROctree_s*** qlist)
576{
577 double rect2[6], center[3], *dist;
578 double l0;
579 int i,index,dim;
580
581 dim = mesh->dim;
582 index = 0;
583
584 memcpy(&rect2, rect, sizeof(double)*dim*2);
585
586 //instead of counting exactly the number of cells to be listed, the
587 //maximum size is set to nc-3 (so the list dist can have nc-3 values + 3 coordinates of
588 //the center of the rectangle)
589 assert(q->nc>=3);
590 index = q->nc-3;
591
592 MMG5_ADD_MEM(mesh,index*sizeof(MMG3D_PROctree_s*),"PROctree cell",return -1);
593 MMG5_SAFE_MALLOC(*qlist,index,MMG3D_PROctree_s*, return -1);
594
595 MMG5_ADD_MEM(mesh,q->nc*sizeof(double),"dist array",return -1);
596 MMG5_SAFE_MALLOC(dist,q->nc,double,return -1);
597
598 // Set the center of the zone search
599 dist[q->nc-3] = rect[0]+rect[3]/2;
600 dist[q->nc-2] = rect[1]+rect[4]/2;
601 dist[q->nc-1] = rect[2]+rect[5]/2;
602
603 // Set the radius of the zone search (used for cell inclusion test if activated)
604 l0 = rect[3]/2;
605
606 // Initialization of the PROctree cell list
607 for (i = 0; i<index; i++)
608 (*qlist)[i] = NULL;
609
610 index = 0;
611
612 // Set center of the first PROctree cell
613 for (i = 0; i < dim; ++i)
614 center[i] = 0.5;
615
616 // Avoid modification of input parameter rect
617 memcpy(&rect2, rect, sizeof(double)*dim*2);
618
619 if ( !MMG3D_getListSquareRec(q->q0, center, rect2, qlist, dist, ani, l0,
620 q->nc, dim, &index) ) {
621 MMG5_DEL_MEM(mesh,dist);
622 return 0;
623 }
624
625
626 if (index>q->nc-4)
627 {
628 MMG5_DEL_MEM(mesh,dist);
629 return 0;
630 }
631
632 MMG5_DEL_MEM(mesh,dist);
633
634 return index;
635}
636
651 const MMG5_int no, int nv)
652{
653 double pt[3],quadrant;
654 int dim, nbBitsInt,depthMax,i,j,k;
655 int sizBr;
656 int sizeRealloc;
657
658 nbBitsInt = sizeof(int64_t)*8;
659 dim = mesh->dim;
660 depthMax = nbBitsInt/dim - 1; // maximum depth is to allow integer coordinates
661 sizBr = 1<<dim;
662
663 if ( q->depth < depthMax ) // not at the maximum depth of the tree
664 {
665 if (q->nbVer < nv) // not at the maximum number of vertice in the cell
666 {
667
668 if(q->nbVer == 0) // first vertex list allocation
669 {
670 MMG5_ADD_MEM(mesh,sizeof(MMG5_int),"PROctree vertice table", return 0);
671 MMG5_SAFE_MALLOC(q->v,1,MMG5_int,return 0);
672 }
673 else if(!(q->nbVer & (q->nbVer - 1))) //is a power of 2 -> reallocation of the vertex list
674 {
675 sizeRealloc = q->nbVer;
676 sizeRealloc<<=1;
677 MMG5_ADD_MEM(mesh,(sizeRealloc-sizeRealloc/2)*sizeof(MMG5_int),"PROctree realloc",
678 return 0);
679 MMG5_SAFE_REALLOC(q->v,q->nbVer,sizeRealloc,MMG5_int,"PROctree",return 0);
680 }
681
682 q->v[q->nbVer] = no;
683 q->nbVer++;
684 return 1;
685 }
686 else if (q->nbVer == nv && q->branches==NULL) //vertex list at maximum -> cell subdivision
687 {
688 /* creation of sub-branch and relocation of vertices in the sub-branches */
689 MMG5_ADD_MEM(mesh,sizBr*sizeof(MMG3D_PROctree_s),"PROctree branches",
690 return 0);
691 MMG5_SAFE_MALLOC(q->branches,sizBr,MMG3D_PROctree_s,return 0);
692
693 for ( i = 0; i<sizBr; i++)
694 {
696 q->branches[i].depth = q->depth+1;
697 }
698 q->nbVer++;
699 for (i = 0; i<nv; i++)
700 {
701
702 memcpy(&pt, mesh->point[q->v[i]].c ,dim*sizeof(double));
703 for ( j =0; j < q->depth; j++)
704 {
705 for (k = 0; k<dim; k++)
706 {
707 pt[k] -= ((double) (pt[k]>0.5))*0.5;
708 pt[k] *= 2;
709 }
710 }
711 if (!MMG3D_addPROctreeRec(mesh, q, pt, q->v[i],nv))
712 return 0;
713 q->nbVer--;
714 }
715 if (!MMG3D_addPROctreeRec(mesh, q, ver, no, nv))
716 return 0;
717 q->nbVer--;
718 MMG5_DEL_MEM(mesh,q->v);
719
720 }else // Recursive call in the corresponding sub cell
721 {
722 quadrant = 0.;
723 for ( i = 0; i<dim; i++)
724 {
725 quadrant += ((double) (ver[i]>0.5))*(1<<i);
726 ver[i] -= ((double) (ver[i]>0.5))*0.5;
727 ver[i] *= 2;
728 }
729
730 q->nbVer++;
731 if (!MMG3D_addPROctreeRec(mesh, &(q->branches[(int)quadrant]), ver, no, nv))
732 return 0;
733 }
734 }else // maximum PROctree depth reached
735 {
736 if (q->nbVer < nv)
737 {
738 if(q->nbVer == 0) // first allocation
739 {
740 MMG5_ADD_MEM(mesh,sizeof(MMG5_int),"PROctree vertices table",
741 return 0);
742 MMG5_SAFE_MALLOC(q->v,1,MMG5_int,return 0);
743 }
744 else if(!(q->nbVer & (q->nbVer - 1))) //is a power of 2 -> normal reallocation
745 {
746 sizeRealloc = q->nbVer;
747 sizeRealloc <<= 1;
748 MMG5_ADD_MEM(mesh,(sizeRealloc-sizeRealloc/2)*sizeof(MMG5_int),"PROctree realloc",
749 return 0);
750 MMG5_SAFE_REALLOC(q->v,q->nbVer,sizeRealloc,MMG5_int,"PROctree",return 0);
751 }
752 }
753 else if (q->nbVer%nv == 0) // special reallocation of the vertex list because it is at maximum depth
754 {
755 MMG5_ADD_MEM(mesh,nv*sizeof(MMG5_int),"PROctree realloc",
756 return 0);
757 MMG5_SAFE_REALLOC(q->v,q->nbVer,q->nbVer+nv,MMG5_int,"PROctree",return 0);
758 }
759
760 q->v[q->nbVer] = no;
761 q->nbVer++;
762 }
763
764 return 1;
765}
766
776{
777 double pt[3];
778 int dim;
779
780 dim = mesh->dim;
781 assert(no<=mesh->np);
782 memcpy(&pt, mesh->point[no].c ,dim*sizeof(double));
783 if (!MMG3D_addPROctreeRec(mesh, q->q0, pt , no, q->nv))
784 {
785 return 0;
786 }
787
788 return 1;
789}
790
801{
802 MMG5_int* vTemp;
803 int i;
804
805 assert(q->v);
806 assert(q->nbVer>indNo);
807 for(i=0; i<q->nbVer; ++i)
808 assert(q->v[i]>0);
809 memmove(&q->v[indNo],&q->v[indNo+1], (q->nbVer-indNo-1)*sizeof(MMG5_int));
810 --(q->nbVer);
811 if (!(q->nbVer & (q->nbVer - 1)) && q->nbVer > 0) // is a power of 2
812 {
813 MMG5_ADD_MEM(mesh,q->nbVer*sizeof(MMG5_int),"PROctree index",
814 return 0);
815 MMG5_SAFE_MALLOC(vTemp,q->nbVer,MMG5_int,return 0);
816 memcpy(vTemp, q->v,q->nbVer*sizeof(MMG5_int));
817 MMG5_DEL_MEM(mesh,q->v);
818
819 q->v = vTemp;
820 }
821 return 1;
822}
823
835void MMG3D_mergeBranchesRec(MMG3D_PROctree_s* q0, MMG3D_PROctree_s* q, int dim, int nv, int* index)
836{
837 int i;
838
839 if (q->v != NULL)
840 {
841
842 assert(*index+q->nbVer<=nv);
843
844 memcpy(&(q0->v[*index]), q->v, q->nbVer*sizeof(MMG5_int));
845 (*index)+= q->nbVer;
846 for(i = 0; i<(*index); ++i)
847 assert(q0->v[i]>0);
848 }else if (q->branches != NULL)
849 {
850 for (i = 0; i<(1<<dim); ++i)
851 MMG3D_mergeBranchesRec(q0, &(q->branches[i]), dim, nv, index);
852 }
853}
854
865{
866 int index;
867 int i;
868
869 index = 0;
870 assert(q->v);
871 assert(q->branches);
872 assert(q->nbVer==nv);
873
874 for (i = 0; i<(1<<dim); ++i)
875 {
876 MMG3D_mergeBranchesRec(q, &(q->branches[i]), dim, nv, &index);
877 MMG3D_freePROctree_s(mesh,&(q->branches[i]), nv);
878 }
880}
881
896int MMG3D_delPROctreeRec(MMG5_pMesh mesh, MMG3D_PROctree_s* q, double* ver, const MMG5_int no, const int nv)
897{
898 double quadrant;
899 int i;
900 int dim = mesh->dim;
901 int nbVerTemp;
902
903 if (q->v)
904 {
905 for ( i = 0; i<q->nbVer; ++i)
906 {
907 if (q->v[i] == no)
908 {
909 if (!MMG3D_delPROctreeVertex(mesh, q, i))
910 return 0;
911 if ( q->nbVer == 0)
912 {
913 MMG5_DEL_MEM(mesh,q->v);
914 }
915 break;
916 }
917 }
918
919 }else if ( q->nbVer == nv+1)
920 {
921 quadrant = 0.;
922 for ( i = 0; i<dim; ++i)
923 {
924 quadrant += ((double) (ver[i]>0.5))*(1<<i);
925 ver[i] -= ((double) (ver[i]>0.5))*0.5;
926 ver[i] *= 2;
927 }
928 --q->nbVer;
929 nbVerTemp = q->branches[(int)quadrant].nbVer;
930
931 // warning: calling recursively here is not optimal
932 if(!MMG3D_delPROctreeRec(mesh, &(q->branches[(int)quadrant]), ver, no, nv))
933 return 0;
934
935 if (nbVerTemp > q->branches[(int)quadrant].nbVer)
936 {
937 MMG5_ADD_MEM(mesh,nv*sizeof(MMG5_int),"PROctree vertices table",
938 return 0);
939 MMG5_SAFE_MALLOC(q->v,nv,MMG5_int,return 0);
940 MMG3D_mergeBranches(mesh,q,dim,nv);
941 }else
942 {
943 ++q->nbVer;
944 }
945
946 }else if (q->branches != NULL)
947 {
948 quadrant = 0.;
949 for ( i = 0; i<dim; ++i)
950 {
951 quadrant += ((double) (ver[i]>0.5))*(1<<i);
952 ver[i] -= ((double) (ver[i]>0.5))*0.5;
953 ver[i] *= 2;
954 }
955
956 --q->nbVer;
957 nbVerTemp = q->branches[(int)quadrant].nbVer;
958 if(!MMG3D_delPROctreeRec(mesh, &(q->branches[(int)quadrant]), ver, no, nv))
959 return 0;
960 if (nbVerTemp <= q->branches[(int)quadrant].nbVer) // test if deletion worked
961 {
962 ++q->nbVer;
963 }
964 }
965 return 1;
966}
967
978{
979 double pt[3];
980 int dim;
981
982 dim = mesh->dim;
983
984 assert(MG_VOK(&mesh->point[no]));
985
986 memcpy(&pt, mesh->point[no].c ,dim*sizeof(double));
987 if(!MMG3D_delPROctreeRec(mesh, q->q0, pt , no, q->nv))
988 {
989 return 0;
990 }
991 return 1;
992}
993
994
1005void MMG3D_printArbreDepth(MMG3D_PROctree_s* q, int depth, int nv, int dim)
1006{
1007 int i;
1008 if ( q->depth < depth && q->nbVer > nv)
1009 {
1010
1011 for (i = 0; i < (1<<dim); i++)
1012 {
1013 MMG3D_printArbreDepth(&(q->branches[i]),depth, nv, dim);
1014 }
1015 }else if (q->depth == depth)
1016 {
1017 fprintf(stdout,"%i ",q->nbVer);
1018 }
1019}
1020
1030{
1031 int dim;
1032
1033 dim = 3;
1034 int i;
1035 for (i = 0; i<(int)sizeof(int)*8/dim; i++)
1036 {
1037 fprintf(stdout,"\n depth %i \n", i);
1038 MMG3D_printArbreDepth(q->q0, i, q->nv, dim);
1039
1040 }
1041 fprintf(stdout,"\n end \n");
1042}
1043
1054void MMG3D_printSubArbre(MMG3D_PROctree_s* q, int nv, int dim)
1055{
1056 int i;
1057 for (i = 0; i<(int)sizeof(int)*8/dim; i++)
1058 {
1059 fprintf(stdout,"\n depth %i \n", i);
1060 MMG3D_printArbreDepth(q, i, nv, dim);
1061
1062 }
1063 fprintf(stdout,"\n end \n");
1064}
1065
1066
1077void MMG3D_sizeArbreRec(MMG3D_PROctree_s* q, int nv, int dim,int* s1, int* s2)
1078{
1079 int i;
1080 int nVer;
1081 if (q->branches != NULL)
1082 {
1083 for (i= 0; i <(1<<dim); i++)
1084 {
1085 MMG3D_sizeArbreRec(&(q->branches[i]),nv,dim, s1, s2);
1086 (*s1) +=(int)( sizeof(MMG3D_PROctree_s)+(1<<dim)*sizeof(MMG3D_PROctree_s*));
1087 }
1088 }else if(q->v != NULL)
1089 {
1090 // rounding up to the next higher power of 2
1091 nVer = q->nbVer;
1092 nVer--;
1093 nVer |= nVer >> 1;
1094 nVer |= nVer >> 2;
1095 nVer |= nVer >> 4;
1096 nVer |= nVer >> 8;
1097 nVer |= nVer >> 16;
1098 nVer++;
1099 nVer = (nVer < nv) ? nVer : (int)(((q->nbVer-0.1)/nv+1)*nv);
1100 (*s2) += nVer*sizeof(MMG5_int);
1101 (*s1) += sizeof(MMG3D_PROctree_s);
1102 }else
1103 {
1104 (*s1) += sizeof(MMG3D_PROctree_s);
1105 }
1106}
1107
1120{
1121 int *s;
1122 MMG5_SAFE_MALLOC(s,2, int,return 0);
1123 s[0] = 0;
1124 s[1] = 0;
1125 MMG3D_sizeArbreRec(q->q0, q->nv, dim, &s[0], &s[1]);
1126 return s;
1127}
1128
1143int MMG3D_PROctreein_iso(MMG5_pMesh mesh,MMG5_pSol sol,MMG3D_pPROctree PROctree,MMG5_int ip,double lmax) {
1144 MMG5_pPoint ppt,pp1;
1145 MMG3D_PROctree_s **lococ;
1146 double d2,ux,uy,uz,hpi,hp1,hpi2,methalo[6];
1147 int i,j;
1148 MMG5_int ip1;
1149 int ncells;
1150 double ani[6];
1151 //double dmax;
1152
1153 ani[0] = sol->m[ip];
1154 ani[3] = sol->m[ip];
1155 ani[5] = sol->m[ip];
1156 ani[1] = 0;
1157 ani[2] = 0;
1158 ani[4] = 0;
1159
1160 lococ = NULL;
1161 ppt = &mesh->point[ip];
1162 // dmax = MG_MAX(0.1,2-lmax);
1163 //hpi = dmax*sol->m[ip];
1164 hpi = lmax*sol->m[ip];
1165 hp1 = hpi*hpi;
1166
1167 /* methalo is the box that we want to intersect with the PROctree, thus, the limit
1168 * of the filter. We give: the coordinates of one of the corner of the box and
1169 * the length of the box in each direction. */
1170 methalo[0] = ppt->c[0] - hpi;
1171 methalo[1] = ppt->c[1] - hpi;
1172 methalo[2] = ppt->c[2] - hpi;
1173 methalo[3] = methalo[4] = methalo[5] = 2.*hpi;
1174
1175 ncells = MMG3D_getListSquare(mesh, ani, PROctree, methalo, &lococ);
1176 if (ncells < 0)
1177 {
1178 if ( lococ )
1179 MMG5_DEL_MEM(mesh,lococ);
1180 return -1;
1181 }
1182 /* Check the PROctree cells */
1183 for ( i=0; i<ncells; ++i )
1184 {
1185 for (j=0; j<lococ[i]->nbVer; ++j)
1186 {
1187
1188 ip1 = lococ[i]->v[j];
1189 pp1 = &mesh->point[ip1];
1190
1191 hpi2 = lmax * sol->m[ip1];
1192 //hpi2 = dmax * sol->m[ip1];
1193
1194 ux = pp1->c[0] - ppt->c[0];
1195 uy = pp1->c[1] - ppt->c[1];
1196 uz = pp1->c[2] - ppt->c[2];
1197
1198 d2 = ux*ux + uy*uy + uz*uz;
1199
1200 if ( d2 < hp1 || d2 < hpi2*hpi2 )
1201 {
1202 MMG5_DEL_MEM(mesh,lococ);
1203 return 0;
1204 }
1205 }
1206 }
1207 MMG5_DEL_MEM(mesh,lococ);
1208 return 1;
1209}
1210
1225int MMG3D_PROctreein_ani(MMG5_pMesh mesh,MMG5_pSol sol,MMG3D_pPROctree PROctree,MMG5_int ip,double lmax) {
1226 MMG5_pPoint ppt,pp1;
1227 MMG3D_PROctree_s **lococ;
1228 double d2,ux,uy,uz,methalo[6];
1229 double det,dmi, *ma, *mb,m1,m2,m3,dx,dy,dz;
1230 int i,j;
1231 MMG5_int ip1,iadr;
1232 int ncells;
1233 // double dmax;
1234
1235 lococ = NULL;
1236 ppt = &mesh->point[ip];
1237
1238 iadr = ip*sol->size;
1239 ma = &sol->m[iadr];
1240 // dmax = MG_MAX(0.1,2-lmax);
1241 dmi =(lmax*lmax);
1242 //dmi =dmax*dmax;
1243
1244 // hpi = sol->m[ip]*dmax;
1245
1246 det = ma[0] * (ma[3]*ma[5] - ma[4]*ma[4])
1247 - ma[1] * (ma[1]*ma[5] - ma[2]*ma[4])
1248 + ma[2] * (ma[1]*ma[4] - ma[3]*ma[2]);
1249
1250 if ( det <= 0. ) return 1;
1251
1252 det = 1.0 / det;
1253 m1 = ma[3]*ma[5] - ma[4]*ma[4];
1254 m2 = ma[0]*ma[5] - ma[2]*ma[2];
1255 m3 = ma[0]*ma[3] - ma[1]*ma[1];
1256
1257 if ( m1<=0. || m2<=0. || m3<=0.) return 1;
1258
1259 dx = lmax * sqrt(m1 * det) ;
1260 dy = lmax * sqrt(m2 * det) ;
1261 dz = lmax * sqrt(m3 * det) ;
1262 /* dx = dmax * sqrt(m1 * det) ; */
1263 /* dy = dmax * sqrt(m2 * det) ; */
1264 /* dz = dmax * sqrt(m3 * det) ; */
1265
1266 /* methalo is the box that we want to intersect with the PROctree, thus, the limit
1267 * of the filter. We give: the coordinates of one of the corner of the box and
1268 * the length of the box in each direction. */
1269 methalo[0] = ppt->c[0] - dx;
1270 methalo[1] = ppt->c[1] - dy;
1271 methalo[2] = ppt->c[2] - dz;
1272 methalo[3] = 2*dx;
1273 methalo[4] = 2*dy;
1274 methalo[5] = 2*dz;
1275
1276 // this function allocates lococ, it has to be deleted after the call
1277 ncells = MMG3D_getListSquare(mesh,ma,PROctree, methalo, &lococ);
1278 if (ncells < 0)
1279 {
1280 MMG5_DEL_MEM(mesh,lococ);
1281 return -1;
1282 }
1283 /* Check the PROctree cells */
1284 for ( i=0; i<ncells; ++i )
1285 {
1286 for (j=0; j<lococ[i]->nbVer; ++j)
1287 {
1288 ip1 = lococ[i]->v[j];
1289 pp1 = &mesh->point[ip1];
1290
1291 ux = pp1->c[0] - ppt->c[0];
1292 uy = pp1->c[1] - ppt->c[1];
1293 uz = pp1->c[2] - ppt->c[2];
1294
1295 d2 = ma[0]*ux*ux + ma[3]*uy*uy + ma[5]*uz*uz
1296 + 2.0*(ma[1]*ux*uy + ma[2]*ux*uz + ma[4]*uy*uz);
1297 if ( d2 < dmi )
1298 {
1299 MMG5_DEL_MEM(mesh,lococ);
1300 return 0;
1301 }
1302 else
1303 {
1304 iadr = ip1*sol->size;
1305 mb = &sol->m[iadr];
1306 d2 = mb[0]*ux*ux + mb[3]*uy*uy + mb[5]*uz*uz
1307 + 2.0*(mb[1]*ux*uy + mb[2]*ux*uz + mb[4]*uy*uz);
1308 if ( d2 < dmi ) {
1309 MMG5_DEL_MEM(mesh,lococ);
1310 return 0;
1311 }
1312 }
1313 }
1314 }
1315
1316 MMG5_DEL_MEM(mesh,lococ);
1317 return 1;
1318}
MMG5_pMesh MMG5_pSol * sol
MMG5_pMesh * mesh
int MMG3D_getListSquareRec(MMG3D_PROctree_s *q, double *center, double *rect, MMG3D_PROctree_s ***qlist, double *dist, double *ani, double l0, int nc, int dim, int *index)
Definition: PRoctree_3d.c:443
int MMG3D_movePROctree(MMG5_pMesh mesh, MMG3D_pPROctree q, MMG5_int no, double *newVer, double *oldVer)
Definition: PRoctree_3d.c:225
void MMG3D_mergeBranchesRec(MMG3D_PROctree_s *q0, MMG3D_PROctree_s *q, int dim, int nv, int *index)
Definition: PRoctree_3d.c:835
int * MMG3D_sizeArbre(MMG3D_pPROctree q, int dim)
Definition: PRoctree_3d.c:1119
void MMG3D_mergeBranches(MMG5_pMesh mesh, MMG3D_PROctree_s *q, int dim, int nv)
Definition: PRoctree_3d.c:864
int MMG3D_seekIndex(double *distList, double dist, int indexMin, int indexMax)
Definition: PRoctree_3d.c:337
void MMG3D_printArbre(MMG3D_pPROctree q)
Definition: PRoctree_3d.c:1029
void MMG3D_freePROctree_s(MMG5_pMesh mesh, MMG3D_PROctree_s *q, int nv)
Definition: PRoctree_3d.c:113
int MMG3D_delPROctreeVertex(MMG5_pMesh mesh, MMG3D_PROctree_s *q, MMG5_int indNo)
Definition: PRoctree_3d.c:800
int MMG3D_intersectRect(double *rectin, double *rectinout)
Definition: PRoctree_3d.c:385
void MMG3D_freePROctree(MMG5_pMesh mesh, MMG3D_pPROctree *q)
Definition: PRoctree_3d.c:164
void MMG3D_initPROctree_s(MMG3D_PROctree_s *q)
Definition: PRoctree_3d.c:48
void MMG3D_printArbreDepth(MMG3D_PROctree_s *q, int depth, int nv, int dim)
Definition: PRoctree_3d.c:1005
int MMG3D_delPROctreeRec(MMG5_pMesh mesh, MMG3D_PROctree_s *q, double *ver, const MMG5_int no, const int nv)
Definition: PRoctree_3d.c:896
void MMG3D_placeInListPROctree(MMG3D_PROctree_s **qlist, MMG3D_PROctree_s *q, int index, int size)
Definition: PRoctree_3d.c:316
int MMG3D_PROctreein_iso(MMG5_pMesh mesh, MMG5_pSol sol, MMG3D_pPROctree PROctree, MMG5_int ip, double lmax)
Definition: PRoctree_3d.c:1143
int MMG3D_getListSquare(MMG5_pMesh mesh, double *ani, MMG3D_pPROctree q, double *rect, MMG3D_PROctree_s ***qlist)
Definition: PRoctree_3d.c:574
void MMG3D_sizeArbreRec(MMG3D_PROctree_s *q, int nv, int dim, int *s1, int *s2)
Definition: PRoctree_3d.c:1077
int MMG3D_isCellIncluded(double *cellCenter, double l, double *zoneCenter, double l0)
Definition: PRoctree_3d.c:265
int MMG3D_addPROctree(MMG5_pMesh mesh, MMG3D_pPROctree q, const MMG5_int no)
Definition: PRoctree_3d.c:775
void MMG3D_printSubArbre(MMG3D_PROctree_s *q, int nv, int dim)
Definition: PRoctree_3d.c:1054
int MMG3D_addPROctreeRec(MMG5_pMesh mesh, MMG3D_PROctree_s *q, double *ver, const MMG5_int no, int nv)
Definition: PRoctree_3d.c:650
int64_t MMG3D_getPROctreeCoordinate(MMG3D_pPROctree q, double *ver, int dim)
Definition: PRoctree_3d.c:183
int MMG3D_delPROctree(MMG5_pMesh mesh, MMG3D_pPROctree q, const int no)
Definition: PRoctree_3d.c:977
int MMG3D_initPROctree(MMG5_pMesh mesh, MMG3D_pPROctree *q, int nv)
Definition: PRoctree_3d.c:65
void MMG3D_placeInListDouble(double *distList, double dist, int index, int size)
Definition: PRoctree_3d.c:298
int MMG3D_PROctreein_ani(MMG5_pMesh mesh, MMG5_pSol sol, MMG3D_pPROctree PROctree, MMG5_int ip, double lmax)
Definition: PRoctree_3d.c:1225
#define MG_MAX(a, b)
#define MMG5_ADD_MEM(mesh, size, message, law)
#define MMG5_SAFE_REALLOC(ptr, prevSize, newSize, type, message, law)
#define MG_VOK(ppt)
#define MG_BDY
#define MMG5_SAFE_MALLOC(ptr, size, type, law)
#define MMG5_DEL_MEM(mesh, ptr)
struct MMG3D_PROctree_s * branches
MMG3D_PROctree_s * q0
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int np
Definition: libmmgtypes.h:612
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
int16_t tag
Definition: libmmgtypes.h:284
double c[3]
Definition: libmmgtypes.h:271