From df90a675a2afa014a3879cc411174c52441a2fd9 Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Wed, 23 Jun 2004 18:52:45 +0000 Subject: [PATCH] Replaced my orientation hack with a rigorous algorithm... Seems to work nicely (and is general). --- Graphics/Geom.cpp | 76 +++++++++++++++++++++++++++++++++++---------- Mesh/2D_Mesh.cpp | 67 ++++++++++++++++----------------------- Mesh/3D_Extrude.cpp | 3 +- Mesh/Mesh.h | 2 -- doc/VERSIONS | 6 ++-- 5 files changed, 91 insertions(+), 63 deletions(-) diff --git a/Graphics/Geom.cpp b/Graphics/Geom.cpp index 30c5cffdc8..b439ae5f8c 100644 --- a/Graphics/Geom.cpp +++ b/Graphics/Geom.cpp @@ -1,4 +1,4 @@ -// $Id: Geom.cpp,v 1.67 2004-06-23 03:57:43 geuzaine Exp $ +// $Id: Geom.cpp,v 1.68 2004-06-23 18:52:45 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -207,7 +207,7 @@ void Draw_Curve(void *a, void *b) // Surfaces -void put_Z(Vertex * v, Surface * s) +void putZ(Vertex * v, Surface * s) { Vertex V; V.Pos.X = s->a; @@ -255,6 +255,45 @@ int isPointOnPlanarSurface(Surface * S, double X, double Y, double Z, return 0; } +void getPlaneSurfaceNormal(Surface *s, double x, double y, double z, double n[3]) +{ + double t1[3], t2[3]; + Curve *c; + + for(int i = 0; i < 3; i++) + n[i] = 0.0; + + if(s->Typ != MSH_SURF_PLAN) + return; + + // We cannot use s->plan or InterpolateSurface here (they both rely + // on the mean plane, which borks the orientation). So we need to + // use this trick: + + if(List_Nbr(s->Generatrices) > 1){ + List_Read(s->Generatrices, 0, &c); + t1[0] = x - c->beg->Pos.X; + t1[1] = y - c->beg->Pos.Y; + t1[2] = z - c->beg->Pos.Z; + for(int i = 1; i < List_Nbr(s->Generatrices); i++){ + List_Read(s->Generatrices, i, &c); + t2[0] = x - c->beg->Pos.X; + t2[1] = y - c->beg->Pos.Y; + t2[2] = z - c->beg->Pos.Z; + prodve(t1, t2, n); + if(norme(n)) + break; + } + } + if(List_Nbr(s->Generatrices) < 2 || !norme(n)){ + Msg(WARNING, "Reverting to mean plane normal for surface %d", s->Num); + n[0] = s->a; + n[1] = s->b; + n[2] = s->c; + norme(n); + } +} + void Draw_Triangulated_Surface(Surface * s) { int k = 0; @@ -344,7 +383,7 @@ void Draw_Plane_Surface(Surface * s) for(i = 0; i < 4; i++) { V[i].Pos.Z = 0.0; - put_Z(&V[i], s); + putZ(&V[i], s); } n[0] = s->plan[2][0]; @@ -441,21 +480,17 @@ void Draw_Plane_Surface(Surface * s) if(CTX.geom.normals) { List_Read(s->Orientations, 0, &vv1); List_Read(s->Orientations, 1, &vv2); - // don't rely on MeanPlane: teh orientation is arbotrary - //n[0] = s->plan[2][0]; - //n[1] = s->plan[2][1]; - //n[2] = s->plan[2][2]; - //norme(n); - Get_SurfaceNormal(s, n); + double x = (vv1.Pos.X + vv2.Pos.X) / 2.; + double y = (vv1.Pos.Y + vv2.Pos.Y) / 2.; + double z = (vv1.Pos.Z + vv2.Pos.Z) / 2.; + getPlaneSurfaceNormal(s, x, y, z, n); n[0] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[0]; n[1] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[1]; n[2] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[2]; glColor4ubv((GLubyte *) & CTX.color.geom.normals); Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, - (vv2.Pos.X + vv1.Pos.X) / 2., (vv2.Pos.Y + vv1.Pos.Y) / 2., - (vv2.Pos.Z + vv1.Pos.Z) / 2., n[0], n[1], n[2], NULL, - CTX.geom.light); + x, y, z, n[0], n[1], n[2], NULL, CTX.geom.light); } } @@ -518,16 +553,25 @@ void Draw_NonPlane_Surface(Surface * s) } if(CTX.geom.normals) { - Vertex v = InterpolateSurface(s, 0.5, 0.5, 0, 0); - double n[3]; - Get_SurfaceNormal(s, n); + Vertex v1 = InterpolateSurface(s, 0.5, 0.5, 0, 0); + Vertex v2 = InterpolateSurface(s, 0.6, 0.5, 0, 0); + Vertex v3 = InterpolateSurface(s, 0.5, 0.6, 0, 0); + double t1[3], t2[3], n[3]; + t1[0] = v2.Pos.X - v1.Pos.X; + t1[1] = v2.Pos.Y - v1.Pos.Y; + t1[2] = v2.Pos.Z - v1.Pos.Z; + t2[0] = v3.Pos.X - v1.Pos.X; + t2[1] = v3.Pos.Y - v1.Pos.Y; + t2[2] = v3.Pos.Z - v1.Pos.Z; + prodve(t1, t2, n); + norme(n); n[0] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[0]; n[1] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[1]; n[2] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[2]; glColor4ubv((GLubyte *) & CTX.color.geom.normals); Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, - v.Pos.X, v.Pos.Y, v.Pos.Z, n[0], n[1], n[2], NULL, + v1.Pos.X, v1.Pos.Y, v1.Pos.Z, n[0], n[1], n[2], NULL, CTX.geom.light); } } diff --git a/Mesh/2D_Mesh.cpp b/Mesh/2D_Mesh.cpp index e42f166d3b..b47cc4483d 100644 --- a/Mesh/2D_Mesh.cpp +++ b/Mesh/2D_Mesh.cpp @@ -1,4 +1,4 @@ -// $Id: 2D_Mesh.cpp,v 1.64 2004-06-23 03:57:43 geuzaine Exp $ +// $Id: 2D_Mesh.cpp,v 1.65 2004-06-23 18:52:45 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -789,6 +789,8 @@ void ActionInvertQua(void *a, void *b) q->V[3] = tmp; } +int isPointOnPlanarSurface(Surface * S, double X, double Y, double Z, double n[3]); + int isMiddlePointOnPlanarSurface(Surface *s, Vertex *v1, Vertex *v2) { double n[3] = {s->a, s->b, s->c}; @@ -856,50 +858,36 @@ void Get_SurfaceNormal(Surface *s, double n[3]) } } -// Horrible (tm) hack to orient the elements correctly. This is -// *definitely* not the best way to do it, but I don't have time to -// look into the issue right now. +// A little routine to re-orient the surface meshe to match the +// geometrical orientation. It would be better to actually generate +// the meshes correctly in the first place (!), but this is handy +// since we use many different algorithms since the mean plane +// computation doesn't take the original orientation into account. void ReOrientSurfaceMesh(Surface *s) { - double t1[3], t2[3], n1[3], n2[3], res; - Simplex *simp; - Quadrangle *quad; - - Get_SurfaceNormal(s, n1); - - if(Tree_Right(s->Simplexes, &simp)){ - t1[0] = simp->V[1]->Pos.X - simp->V[0]->Pos.X; - t1[1] = simp->V[1]->Pos.Y - simp->V[0]->Pos.Y; - t1[2] = simp->V[1]->Pos.Z - simp->V[0]->Pos.Z; - t2[0] = simp->V[2]->Pos.X - simp->V[0]->Pos.X; - t2[1] = simp->V[2]->Pos.Y - simp->V[0]->Pos.Y; - t2[2] = simp->V[2]->Pos.Z - simp->V[0]->Pos.Z; - prodve(t1, t2, n2); - norme(n2); - prosca(n1, n2, &res); - if(res < 0.0){ - Msg(DEBUG, "Inverting triangles in %s surface %d (res = %g)", - (s->Typ == MSH_SURF_PLAN) ? "Plane" : "NonPlane", s->Num, res); + Curve *c; + List_Read(s->Generatrices, 0, &c); + Vertex *v1, *v2; + List_Read(c->Vertices, 0, &v1); + List_Read(c->Vertices, 1, &v2); + Edge edge; + edge.V[0] = v1; + edge.V[1] = v2; + + if(Tree_Nbr(s->Simplexes)){ + EdgesContainer edges; + edges.AddSimplexTree(s->Simplexes); + Edge *e = (Edge*)Tree_PQuery(edges.AllEdges, &edge); + if(e && e->V[0]->Num == v2->Num && e->V[1]->Num == v1->Num) Tree_Action(s->Simplexes, ActionInvertTri); - } } - - if(Tree_Right(s->Quadrangles, &quad)){ - t1[0] = quad->V[1]->Pos.X - quad->V[0]->Pos.X; - t1[1] = quad->V[1]->Pos.Y - quad->V[0]->Pos.Y; - t1[2] = quad->V[1]->Pos.Z - quad->V[0]->Pos.Z; - t2[0] = quad->V[2]->Pos.X - quad->V[0]->Pos.X; - t2[1] = quad->V[2]->Pos.Y - quad->V[0]->Pos.Y; - t2[2] = quad->V[2]->Pos.Z - quad->V[0]->Pos.Z; - prodve(t1, t2, n2); - norme(n2); - prosca(n1, n2, &res); - if(res < 0.0){ - Msg(DEBUG, "Inverting quads in %s surface %d (res = %g)", - (s->Typ == MSH_SURF_PLAN) ? "Plane" : "NonPlane", s->Num, res); + if(Tree_Nbr(s->Quadrangles)){ + EdgesContainer edges; + edges.AddQuadrangleTree(s->Quadrangles); + Edge *e = (Edge*)Tree_PQuery(edges.AllEdges, &edge); + if(e && e->V[0]->Num == v2->Num && e->V[1]->Num == v1->Num) Tree_Action(s->Quadrangles, ActionInvertQua); - } } } @@ -1006,7 +994,6 @@ void Maillage_Surface(void *data, void *dum) End_Surface(s->Support, 0); End_Surface(s, 0); - // FIXME: big hack ReOrientSurfaceMesh(s); } diff --git a/Mesh/3D_Extrude.cpp b/Mesh/3D_Extrude.cpp index f98b655dd7..c0ab9572f1 100644 --- a/Mesh/3D_Extrude.cpp +++ b/Mesh/3D_Extrude.cpp @@ -1,4 +1,4 @@ -// $Id: 3D_Extrude.cpp,v 1.81 2004-06-23 03:57:43 geuzaine Exp $ +// $Id: 3D_Extrude.cpp,v 1.82 2004-06-23 18:52:45 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -1046,7 +1046,6 @@ int Extrude_Mesh(Surface * s) Tree_Action(s->Simplexes, AddSimVertsInSurf); Tree_Action(s->Quadrangles, AddQuadVertsInSurf); - // FIXME: big hack ReOrientSurfaceMesh(s); return true; diff --git a/Mesh/Mesh.h b/Mesh/Mesh.h index 181cc9c19e..224bc57c86 100644 --- a/Mesh/Mesh.h +++ b/Mesh/Mesh.h @@ -476,8 +476,6 @@ void Projette_Plan_Moyen(void *a, void *b); void Projette_Inverse(void *a, void *b); void Freeze_Vertex(void *a, void *b); void deFreeze_Vertex(void *a, void *b); -int isPointOnPlanarSurface(Surface * S, double X, double Y, double Z, double n[3]); -void Get_SurfaceNormal(Surface *s, double n[3]); void ReOrientSurfaceMesh(Surface *s); double Lc_XYZ(double X, double Y, double Z, Mesh * m); diff --git a/doc/VERSIONS b/doc/VERSIONS index 3cf8fe1b3d..8552079b24 100644 --- a/doc/VERSIONS +++ b/doc/VERSIONS @@ -1,12 +1,12 @@ -$Id: VERSIONS,v 1.226 2004-06-23 04:02:38 geuzaine Exp $ +$Id: VERSIONS,v 1.227 2004-06-23 18:52:45 geuzaine Exp $ New since 1.53: fixed UNV output; make Layers' region numbering consistent between lines/surfaces/volumes; fixed home directory problem on Win98; new Plugin(CutParametric); the default project file is now created in the home directory if no current directory is defined (e.g. when double-clicking on the icon on Windows/MacOS); -(partial) fix of the geometry/mesh surface orientation discrepancies; -small bug fixes and cleanups. +fixed the discrepancy between the orientation of geometrical surfaces +and the associated surface meshes; small bug fixes and cleanups. New in 1.53: completed support for second order elements in the mesh module (lines, triangles, quadrangles, tetrahedra, hexahedra, prisms -- GitLab