Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
length_2d.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#include "libmmg2d_private.h"
25
26/* Compute isotropic edge length */
27double long_iso(double *ca,double *cb,double *ma,double *mb) {
28 double ha,hb,ux,uy,dd,rap,len;
29
30 ha = *ma;
31 hb = *mb;
32 ux = cb[0] - ca[0];
33 uy = cb[1] - ca[1];
34 dd = sqrt(ux*ux + uy*uy);
35
36 rap = (hb - ha) / ha;
37 if ( fabs(rap) < MMG2D_EPSD )
38 len = dd / ha;
39 else
40 len = dd * (1.0/ha + 1.0/hb + 8.0 / (ha+hb)) / 6.0;
41
42 return len;
43}
44
45
46/* compute aniso edge length */
47double long_ani(double *ca,double *cb,double *ma,double *mb) {
48 double ux,uy,dd1,dd2,len;
49 ux = cb[0] - ca[0];
50 uy = cb[1] - ca[1];
51
52 dd1 = ma[0]*ux*ux + ma[2]*uy*uy + 2.0*ma[1]*ux*uy;
53 if ( dd1 <= 0.0 ) dd1 = 0.0;
54 dd2 = mb[0]*ux*ux + mb[2]*uy*uy + 2.0*mb[1]*ux*uy;
55 if ( dd2 <= 0.0 ) dd2 = 0.0;
56
57 len = (sqrt(dd1)+sqrt(dd2)+4.0*sqrt(0.5*(dd1+dd2))) / 6.0;
58
59 return len;
60}
61
63double MMG2D_lencurv_iso(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int ip1,MMG5_int ip2) {
64 MMG5_pPoint p1,p2;
65 double h1,h2,len,l,r;
66
67 p1 = &mesh->point[ip1];
68 p2 = &mesh->point[ip2];
69
70 h1 = met->m[ip1];
71 h2 = met->m[ip2];
72
73 l = (p2->c[0]-p1->c[0])*(p2->c[0]-p1->c[0]) + (p2->c[1]-p1->c[1])*(p2->c[1]-p1->c[1]);
74 l = sqrt(l);
75 r = h2 / h1 - 1.0;
76 len = ( fabs(r) < MMG5_EPS ) ? ( l/h1 ) : ( l / (h2-h1) * log1p(r) );
77
78 return len;
79}
80
81/* Calculate length of a curve in the considered anisotropic metric by using a two-point quadrature formula */
82double MMG2D_lencurv_ani(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int ip1,MMG5_int ip2) {
83 MMG5_pPoint p1,p2;
84 double len,*m1,*m2,ux,uy,l1,l2;
85 static int8_t mmgWarn0=0,mmgWarn1=0;
86
87 p1 = &mesh->point[ip1];
88 p2 = &mesh->point[ip2];
89
90 m1 = &met->m[3*ip1];
91 m2 = &met->m[3*ip2];
92
93 ux = p2->c[0] - p1->c[0];
94 uy = p2->c[1] - p1->c[1];
95
96 l1 = m1[0]*ux*ux + 2.0*m1[1]*ux*uy + m1[2]*uy*uy;
97 l2 = m2[0]*ux*ux + 2.0*m2[1]*ux*uy + m2[2]*uy*uy;
98
99 if ( l1 < 0.0 ) {
100 if ( !mmgWarn0 ) {
101 mmgWarn0 = 1;
102 fprintf(stderr,"\n ## Error: %s: at least 1 negative edge length"
103 " (l1: %e).\n",__func__,l1);
104 }
105 return 0.;
106 }
107 if ( l2 < 0.0 ) {
108 if ( !mmgWarn1 ) {
109 mmgWarn1 = 1;
110 fprintf(stderr,"\n ## Error: %s: at least 1 negative edge length"
111 " (l2: %e)\n",__func__,l2);
112 }
113 return 0.;
114 }
115
116 l1 = sqrt(l1);
117 l2 = sqrt(l2);
118
119 len = 0.5*(l1+l2);
120
121 return len;
122}
123
124/* print histo of edge lengths */
126 MMG5_pTria pt;
127 double lavg,len,lmin,lmax;
128 int ia,ipa,ipb;
129 MMG5_int iamin,ibmin,iamax,ibmax,hl[9],nullEdge,navg;
130 static double bd[9] = {0.0, 0.3, 0.6, 0.7071, 0.9, 1.3, 1.4142, 2.0, 5.0};
131 MMG5_int k,l;
132
133 navg = 0;
134 lavg = 0.0;
135 lmin = 1.e20;
136 lmax = 0.0;
137 iamin = 0;
138 ibmin = 0;
139 iamax = 0;
140 ibmax = 0;
141 nullEdge = 0;
142
143 if ( (!sol) || (!sol->m) ) {
144 /* the functions that computes the edge length cannot be called without an
145 * allocated metric */
146 return 0;
147 }
148
149 if ( !mesh->nt ) {
150 return 0;
151 }
152
153 for (k=0; k<9; k++) hl[k] = 0;
154
155 for (k=1; k<=mesh->nt; k++) {
156 pt = &mesh->tria[k];
157 if ( !MG_EOK(pt) ) continue;
158
159 for (ia=0; ia<3; ia++) {
160 l = (&mesh->adja[3*(k-1)+1])[ia];
161 if ( l < 3*k ) continue;
162
163 ipa = MMG2D_iare[ia][0];
164 ipb = MMG2D_iare[ia][1];
165
166 if ( sol->m )
167 len = MMG2D_lencurv(mesh,sol,pt->v[ipa],pt->v[ipb]);
168 else
169 len = MMG2D_lencurv_iso(mesh,sol,pt->v[ipa],pt->v[ipb]);
170
171 navg++;
172 lavg += len;
173
174 /* find largest, smallest edge */
175 if (len < lmin) {
176 lmin = len;
177 iamin = pt->v[ipa];
178 ibmin = pt->v[ipb];
179 }
180 if (len > lmax) {
181 lmax = len;
182 iamax = pt->v[ipa];
183 ibmax = pt->v[ipb];
184 }
185
186 /* update histogram */
187 if (len < bd[3]) {
188 if (len > bd[2]) hl[2]++;
189 else if (len > bd[1]) hl[1]++;
190 else hl[0]++;
191 }
192 else if (len < bd[5]) {
193 if (len > bd[4]) hl[4]++;
194 else if (len > bd[3]) hl[3]++;
195 }
196 else if (len < bd[6]) hl[5]++;
197 else if (len < bd[7]) hl[6]++;
198 else if (len < bd[8]) hl[7]++;
199 else hl[8]++;
200 }
201 }
202 MMG5_displayLengthHisto(mesh, navg, &lavg, iamin, ibmin, lmin,
203 iamax, ibmax, lmax,nullEdge, &bd[0], &hl[0],0);
204
205
206 return 1;
207}
MMG5_pMesh MMG5_pSol * sol
MMG5_pMesh * mesh
#define MMG5_EPS
double MMG2D_lencurv_iso(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int ip1, MMG5_int ip2)
Definition: length_2d.c:63
double MMG2D_lencurv_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int ip1, MMG5_int ip2)
Definition: length_2d.c:82
double long_ani(double *ca, double *cb, double *ma, double *mb)
Definition: length_2d.c:47
int MMG2D_prilen(MMG5_pMesh mesh, MMG5_pSol sol)
Definition: length_2d.c:125
double long_iso(double *ca, double *cb, double *ma, double *mb)
Definition: length_2d.c:27
static const int MMG2D_iare[3][2]
#define MMG2D_EPSD
#define MG_EOK(pt)
void MMG5_displayLengthHisto(MMG5_pMesh, MMG5_int, double *, MMG5_int, MMG5_int, double, MMG5_int, MMG5_int, double, int, double *, MMG5_int *, int8_t)
Definition: quality.c:252
MMG mesh structure.
Definition: libmmgtypes.h:613
MMG5_pPoint point
Definition: libmmgtypes.h:649
MMG5_int * adja
Definition: libmmgtypes.h:632
MMG5_int nt
Definition: libmmgtypes.h:620
MMG5_pTria tria
Definition: libmmgtypes.h:655
Structure to store vertices of an MMG mesh.
Definition: libmmgtypes.h:276
double c[3]
Definition: libmmgtypes.h:277
double * m
Definition: libmmgtypes.h:680
Structure to store triangles of a MMG mesh.
Definition: libmmgtypes.h:338
MMG5_int v[3]
Definition: libmmgtypes.h:340