Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
analys.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
36#include "mmgcommon_private.h"
37
38
47 MMG5_pTria pt;
48 MMG5_pPoint ppt,p0;
49 MMG5_pxPoint pxp;
50 double *tabl,n[3],*nptr,lm1,lm2,dd,nx,ny,nz,res0,res;
51 int i,it,nit,ilist;
52 MMG5_int k,nn,iel,list[MMG5_LMAX],tlist[MMG5_LMAX],*adja,iad;
53
54 /* assign seed to vertex */
55 for (k=1; k<=mesh->nt; k++) {
56 pt = &mesh->tria[k];
57 if ( !MG_EOK(pt) ) continue;
58 for (i=0; i<3; i++) {
59 ppt = &mesh->point[pt->v[i]];
60 if ( !ppt->s ) ppt->s = k;
61 }
62 }
63
64 /* allocate memory for normals */
65 MMG5_SAFE_CALLOC(tabl,3*mesh->np+1,double,return 0);
66
67 /* Pointer toward the suitable adjacency array for Mmgs and Mmg3d */
68 if ( mesh->adjt ) {
69 /* Mmg3d */
70 adja = mesh->adjt;
71 }
72 else {
73 /* Mmgs */
74 adja = mesh->adja;
75 }
76
77 it = 0;
78 nit = 10;
79 res0 = 0.0;
80 lm1 = 0.4;
81 lm2 = 0.399;
82 while ( it++ < nit ) {
83 /* step 1: laplacian */
84 for (k=1; k<=mesh->np; k++) {
85 ppt = &mesh->point[k];
86 if ( !MG_VOK(ppt) ) continue;
87 if ( ppt->tag & MG_CRN || ppt->tag & MG_NOM || MG_EDG(ppt->tag) ) continue;
88
89 iel = ppt->s;
90 if ( !iel ) continue; // Mmg3d
91
92 pt = &mesh->tria[iel];
93 i = 0;
94 if ( pt->v[1] == k ) i = 1;
95 else if ( pt->v[2] == k ) i = 2;
96
97 ilist = MMG5_boulep(mesh,iel,i,adja,list,tlist);
98
99 /* average normal */
100 nx = ny = nz = 0.0;
101 for (i=1; i<=ilist; i++) {
102 p0 = &mesh->point[list[i]];
103 if ( p0->tag & MG_CRN || p0->tag & MG_NOM || MG_EDG(p0->tag) ) continue;
104
105 if ( p0->xp ) {
106 /* Mmg3d */
107 pxp = &mesh->xpoint[p0->xp];
108 nptr = pxp->n1;
109 }
110 else {
111 /* Mmgs */
112 nptr = p0->n;
113 }
114
115 nx += nptr[0];
116 ny += nptr[1];
117 nz += nptr[2];
118 }
119
120 dd = nx*nx + ny*ny + nz*nz;
121 if ( dd > MMG5_EPSD2 ) {
122 dd = 1.0 / sqrt(dd);
123 nx *= dd;
124 ny *= dd;
125 nz *= dd;
126 }
127
128 /* Laplacian */
129 if ( ppt->xp ) {
130 /* Mmg3d */
131 pxp = &mesh->xpoint[ppt->xp];
132 nptr = pxp->n1;
133 }
134 else {
135 /* Mmgs */
136 nptr = ppt->n;
137 }
138
139 iad = 3*(k-1)+1;
140 tabl[iad+0] = nptr[0] + lm1 * (nx - nptr[0]);
141 tabl[iad+1] = nptr[1] + lm1 * (ny - nptr[1]);
142 tabl[iad+2] = nptr[2] + lm1 * (nz - nptr[2]);
143 }
144
145 /* step 2: anti-laplacian */
146 res = 0;
147 nn = 0;
148 for (k=1; k<=mesh->np; k++) {
149 ppt = &mesh->point[k];
150
151 if ( !MG_VOK(ppt) ) continue;
152 if ( ppt->tag & MG_CRN || ppt->tag & MG_NOM || MG_EDG(ppt->tag) ) continue;
153
154 iel = ppt->s;
155 if ( !iel ) continue; // Mmg3d
156
157 pt = &mesh->tria[iel];
158 i = 0;
159 if ( pt->v[1] == k ) i = 1;
160 else if ( pt->v[2] == k ) i = 2;
161
162 ilist = MMG5_boulep(mesh,iel,i,adja,list,tlist);
163
164 /* average normal */
165 nx = ny = nz = 0.0;
166 for (i=1; i<=ilist; i++) {
167 iad = 3*(list[i]-1) + 1;
168 nx += tabl[iad+0];
169 ny += tabl[iad+1];
170 nz += tabl[iad+2];
171 }
172 dd = nx*nx + ny*ny + nz*nz;
173 if ( dd > MMG5_EPSD2 ) {
174 dd = 1.0 / sqrt(dd);
175 nx *= dd;
176 ny *= dd;
177 nz *= dd;
178 }
179
180 /* antiLaplacian */
181 iad = 3*(k-1)+1;
182 n[0] = tabl[iad+0] - lm2 * (nx - tabl[iad+0]);
183 n[1] = tabl[iad+1] - lm2 * (ny - tabl[iad+1]);
184 n[2] = tabl[iad+2] - lm2 * (nz - tabl[iad+2]);
185 nn++;
186
187 if ( ppt->xp ) {
188 /* Mmg3d */
189 pxp = &mesh->xpoint[ppt->xp];
190 nptr = pxp->n1;
191 }
192 else {
193 /* Mmgs */
194 nptr = ppt->n;
195 }
196 res += (nptr[0]-n[0])*(nptr[0]*n[0]) + (nptr[1]-n[1])*(nptr[1]*n[1]) + (nptr[2]-n[2])*(nptr[2]*n[2]);
197
198 nptr[0] = n[0];
199 nptr[1] = n[1];
200 nptr[2] = n[2];
201
202 }
203
204 if ( it == 1 ) res0 = res;
205 if ( res0 > MMG5_EPSD ) res = res / res0;
206 if ( mesh->info.imprim < -1 || mesh->info.ddebug ) {
207 fprintf(stdout," iter %5d res %.3E\r",it,res);
208 fflush(stdout);
209 }
210 if ( it > 1 && res < MMG5_EPS ) break;
211 }
212
213 /* reset the ppt->s tag */
214 for (k=1; k<=mesh->np; ++k) {
215 mesh->point[k].s = 0;
216 }
217
218 if ( mesh->info.imprim < -1 || mesh->info.ddebug ) fprintf(stdout,"\n");
219
220 if ( abs(mesh->info.imprim) > 4 )
221 fprintf(stdout," %" MMG5_PRId " normals regularized: %.3e\n",nn,res);
222
223 MMG5_SAFE_FREE(tabl);
224 return 1;
225}
MMG5_pMesh * mesh
int MMG5_regnor(MMG5_pMesh mesh)
Definition: analys.c:46
int MMG5_boulep(MMG5_pMesh mesh, MMG5_int start, int ip, MMG5_int *adja, MMG5_int *list, MMG5_int *tlist)
Definition: boulep.c:52
#define MMG5_EPSD
#define MMG5_EPS
#define MMG5_SAFE_CALLOC(ptr, size, type, law)
#define MG_EOK(pt)
#define MG_EDG(tag)
#define MMG5_LMAX
#define MG_VOK(ppt)
#define MG_CRN
#define MG_NOM
#define MMG5_EPSD2
#define MMG5_SAFE_FREE(ptr)
int8_t ddebug
Definition: libmmgtypes.h:532
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int * adja
Definition: libmmgtypes.h:624
MMG5_pxPoint xpoint
Definition: libmmgtypes.h:642
MMG5_int nt
Definition: libmmgtypes.h:612
MMG5_pTria tria
Definition: libmmgtypes.h:647
MMG5_int np
Definition: libmmgtypes.h:612
MMG5_int * adjt
Definition: libmmgtypes.h:628
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
double n[3]
Definition: libmmgtypes.h:272
int16_t tag
Definition: libmmgtypes.h:284
MMG5_int xp
Definition: libmmgtypes.h:279
MMG5_int s
Definition: libmmgtypes.h:283
MMG5_int v[3]
Definition: libmmgtypes.h:334
Structure to store surface points of a MMG mesh.
Definition: libmmgtypes.h:294
double n1[3]
Definition: libmmgtypes.h:295