Skip to content

Commit b86f826

Browse files
committed
new area calculation for triangular faces to avoid numeric instability
for 180° edges (can happen for quad-face calculations when splitting)
1 parent 8b346d7 commit b86f826

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

geom_utils.cxx

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ angleBetweenVecs(const double vecA[3], const double vecB[3],
180180
}
181181

182182
static double
183-
triArea(const double coords[][3], const GMGW_int v0, const GMGW_int v1,
183+
triArea_old(const double coords[][3], const GMGW_int v0, const GMGW_int v1,
184184
const GMGW_int v2)
185185
{
186186
double e0 = distance(coords[v0], coords[v1]);
@@ -201,6 +201,7 @@ triArea(const double coords[][3], const GMGW_int v0, const GMGW_int v1,
201201
}
202202
assert(e0 >= e1);
203203
assert(e1 >= e2);
204+
assert(e2 >= (e0-e1)); // astonishingly numerically possible for 180° inner edge angle (jww)
204205
// The parentheses enforce a numerically stable order of operations.
205206
double Area = 0.25
206207
* sqrt(
@@ -209,6 +210,49 @@ triArea(const double coords[][3], const GMGW_int v0, const GMGW_int v1,
209210
return Area;
210211
}
211212

213+
static double // replaces previous edge-length based version (jww)
214+
triArea(const double coords[][3], const GMGW_int v0, const GMGW_int v1,
215+
const GMGW_int v2)
216+
{
217+
// the following is unneeded computational overshoot - only for the assertion below
218+
// would be sufficient to calculate pv1, pv2, nv1 and Area (jww)
219+
220+
double pv1[3], pv2[3], pv3[3], nv1[3], nv2[3], nv3[3];
221+
pv1[0] = coords[v1][0] - coords[v0][0];
222+
pv1[1] = coords[v1][1] - coords[v0][1];
223+
pv1[2] = coords[v1][2] - coords[v0][2];
224+
225+
pv2[0] = coords[v2][0] - coords[v1][0];
226+
pv2[1] = coords[v2][1] - coords[v1][1];
227+
pv2[2] = coords[v2][2] - coords[v1][2];
228+
229+
pv2[0] = coords[v0][0] - coords[v2][0];
230+
pv2[1] = coords[v0][1] - coords[v2][1];
231+
pv2[2] = coords[v0][2] - coords[v2][2];
232+
233+
nv1[0] = pv1[1]*pv2[2] - pv1[2]*pv2[1];
234+
nv1[1] = pv1[2]*pv2[0] - pv1[0]*pv2[2];
235+
nv1[2] = pv1[0]*pv2[1] - pv1[1]*pv2[0];
236+
237+
nv2[0] = pv2[1]*pv3[2] - pv2[2]*pv3[1];
238+
nv2[1] = pv2[2]*pv3[0] - pv2[0]*pv3[2];
239+
nv2[2] = pv2[0]*pv3[1] - pv2[1]*pv3[0];
240+
241+
nv3[0] = pv3[1]*pv1[2] - pv3[2]*pv1[1];
242+
nv3[1] = pv3[2]*pv1[0] - pv3[0]*pv1[2];
243+
nv3[2] = pv3[0]*pv1[1] - pv3[1]*pv1[0];
244+
245+
double Area = 0.5* sqrt(nv1[0]*nv1[0]+nv1[1]*nv1[1]+nv1[2]*nv1[2]);
246+
247+
double Area2 = 0.5* sqrt(nv2[0]*nv2[0]+nv2[1]*nv2[1]+nv2[2]*nv2[2]);
248+
double Area3 = 0.5* sqrt(nv3[0]*nv3[0]+nv3[1]*nv3[1]+nv3[2]*nv3[2]);
249+
double Area_mean = (Area + Area2 + Area3) / 3.;
250+
assert ( Area != Area_mean); // didn't occur in my cases also the '!=' is a very strong assertion criterion (jww)
251+
252+
return Area;
253+
}
254+
255+
212256
void
213257
findOnWallSpacing(const double coords[][3], const GMGW_int nConn,
214258
const GMGW_int connect[], const GMGW_int newIndex[],

0 commit comments

Comments
 (0)