Forked from
gmsh / gmsh
17871 commits behind the upstream repository.
-
Christophe Geuzaine authored
remove obsolete BGM structure
Christophe Geuzaine authoredremove obsolete BGM structure
2D_Mesh_Aniso.cpp 28.97 KiB
// $Id: 2D_Mesh_Aniso.cpp,v 1.48 2006-01-29 22:53:41 geuzaine Exp $
//
// Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems to <gmsh@geuz.org>.
// Anisotropic Delaunay mesh generator
#include "Gmsh.h"
#include "Numeric.h"
#include "Geo.h"
#include "CAD.h"
#include "Mesh.h"
#include "Interpolation.h"
#include "Create.h"
#include "Context.h"
extern Context_T CTX;
extern double LC2D;
inline void cgsmpl(Simplex * s, double &x, double &y)
{
x = (1. / 3.) * (s->V[0]->Pos.X + s->V[1]->Pos.X + s->V[2]->Pos.X);
y = (1. / 3.) * (s->V[0]->Pos.Y + s->V[1]->Pos.Y + s->V[2]->Pos.Y);
}
extern Simplex MyNewBoundary;
extern Mesh *THEM;
extern double MAXIMUM_LC_FOR_SURFACE;
extern int Alerte_Point_Scabreux;
extern PointRecord *gPointArray;
extern Surface *PARAMETRIC;
static Tree_T *Tsd, *Sim_Sur_Le_Bord;
static List_T *Simplexes_Destroyed, *Simplexes_New, *Suppress;
static Simplex *THES;
static Vertex *THEV;
static Surface *SURF;
static Tree_T *FacesTree;
static int ZONEELIMINEE, Methode = 0;
static double volume;
static List_T *coquille;
static Edge *THEEDGE;
double Interpole_lcTriangle(Simplex * s, Vertex * vv)
{
double Xp, Yp, X[3], Y[3], det, u, v, q1, q2, q3;
if(THEM->BackgroundMeshType == ONFILE){
Vertex *v2 = Create_Vertex(-1, vv->Pos.X, vv->Pos.Y, 0.0, 0.0, 0.0);
Vertex *dum;
Calcule_Z_Plan(&v2, &dum);
Projette_Inverse(&v2, &dum);
double val = BGMXYZ(v2->Pos.X, v2->Pos.Y, v2->Pos.Z);
Free_Vertex(&v2, 0);
return val;
}
Xp = vv->Pos.X;
Yp = vv->Pos.Y;
X[0] = s->V[0]->Pos.X;
X[1] = s->V[1]->Pos.X;
X[2] = s->V[2]->Pos.X;
Y[0] = s->V[0]->Pos.Y;
Y[1] = s->V[1]->Pos.Y;
Y[2] = s->V[2]->Pos.Y;
q1 = s->V[0]->lc;
q2 = s->V[1]->lc;
q3 = s->V[2]->lc;
det = (X[2] - X[0]) * (Y[1] - Y[0]) - (Y[2] - Y[0]) * (X[1] - X[0]);
if(det != 0.0) {
u = ((Xp - X[0]) * (Y[1] - Y[0]) - (Yp - Y[0]) * (X[1] - X[0])) / det;
v = ((X[2] - X[0]) * (Yp - Y[0]) - (Y[2] - Y[0]) * (Xp - X[0])) / det;
}
else {
u = v = 0.0;
}
return (q1 * (1. - u - v) + q2 * v + q3 * u);
}
/* Au sens Riemannien, trouver le centre de l'ellipse
triangle de sommets (x1,x2,x3)
T T
(x-x1) M (x-x1) = (x-x2) M (x-x2)
T T
(x-x1) M (x-x1) = (x-x3) M (x-x3)
*/
void matXmat(int n, double mat1[3][3], double mat2[3][3], double Res[3][3])
{
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
Res[i][j] = 0.0;
for(int k = 0; k < n; k++)
Res[i][j] += mat1[i][k] * mat2[k][j];
}
}
}
void TmatXmat(int n, double mat1[3][3], double mat2[3][3], double Res[3][3])
{
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
Res[i][j] = 0.0;
for(int k = 0; k < n; k++)
Res[i][j] += mat1[k][i] * mat2[k][j];
}
}
}
Simplex *Create_Simplex_For2dmesh(Vertex * v1, Vertex * v2, Vertex * v3,
Vertex * v4)
{
Simplex *s;
double p12, p23, p13;
double srf = ((v2->Pos.X - v1->Pos.X) *
(v3->Pos.Y - v2->Pos.Y) -
(v3->Pos.X - v2->Pos.X) * (v2->Pos.Y - v1->Pos.Y));
if(srf > 0)
s = Create_Simplex(v3, v2, v1, v4);
else
s = Create_Simplex(v1, v2, v3, v4);
THEM->Metric->setSimplexQuality(s, PARAMETRIC);
if(PARAMETRIC) {
if((!v2->ListCurves && !v3->ListCurves && !v3->ListCurves)) {
prosca(v1->us, v2->us, &p12);
p12 = fabs(p12);
prosca(v1->us, v3->us, &p13);
p13 = fabs(p13);
prosca(v2->us, v3->us, &p23);
p23 = fabs(p23);
if(s->Quality < CONV_VALUE &&
(p12 < THEM->Metric->min_cos || p13 < THEM->Metric->min_cos ||
p23 < THEM->Metric->min_cos))
s->Quality = 1.0;
}
}
return s;
}
/*En l'honneur de ma femme Stephanie... */
void VSIM_2D(void *a, void *b)
{
Simplex *S;
S = *(Simplex **) a;
if(S->V[2])
volume += fabs(S->Volume_Simplexe2D());
}
void Box_2_Triangles(List_T * P, Surface * s)
{
#define FACT 1.1
#define LOIN 0.2
int i, j;
static int pts[4][2] = { {0, 0},
{1, 0},
{1, 1},
{0, 1} };
static int tri[2][3] = { {1, 4, 2},
{2, 4, 3} };
double Xm = 0., Ym = 0., XM = 0., YM = 0., Xc = 0., Yc = 0.;
Simplex *S, *ps;
Vertex *V, *v, *pv;
List_T *smp;
smp = List_Create(2, 1, sizeof(Simplex *));
V = (Vertex *) Malloc(4 * sizeof(Vertex));
for(i = 0; i < List_Nbr(P); i++) {
List_Read(P, i, &v);
if(!i) {
Xm = XM = v->Pos.X;
Ym = YM = v->Pos.Y;
}
else {
Xm = DMIN(Xm, v->Pos.X);
XM = DMAX(XM, v->Pos.X);
Ym = DMIN(Ym, v->Pos.Y);
YM = DMAX(YM, v->Pos.Y);
}
}
if(Xm == XM)
XM = Xm + 1.;
if(Ym == YM)
YM = Ym + 1.;
Xc = XM - Xm;
Yc = YM - Ym;
/* Longueur Caracteristique */
LC2D = sqrt(Xc * Xc + Yc * Yc);
for(i = 0; i < 4; i++) {
if(pts[i][0])
V[i].Freeze.X = V[i].Pos.X = Xm - LOIN * Xc;
else
V[i].Freeze.X = V[i].Pos.X = XM + LOIN * Xc;
if(pts[i][1])
V[i].Freeze.Y = V[i].Pos.Y = Ym - LOIN * Yc;
else
V[i].Freeze.Y = V[i].Pos.Y = YM + LOIN * Yc;
V[i].Freeze.Z = V[i].Pos.Z = 0.0;
V[i].Num = -(++THEM->MaxPointNum);
V[i].ListSurf = NULL;
pv = &V[i];
pv->lc = 1.0;
pv->Mov = NULL;
Tree_Replace(s->Vertices, &pv);
}
/* 2 Triangles forment le maillage de la boite */
for(i = 0; i < 2; i++) {
S = Create_Simplex_For2dmesh(&V[tri[i][0] - 1], &V[tri[i][1] - 1],
&V[tri[i][2] - 1], NULL);
List_Add(smp, &S);
S->iEnt = s->Num;
}
Link_Simplexes(smp, NULL);
for(i = 0; i < List_Nbr(smp); i++) {
List_Read(smp, i, &ps);
for(j = 0; j < 3; j++)
if(ps->S[j] == NULL)
ps->S[j] = &MyNewBoundary;
Tree_Replace(s->Simplexes, &ps);
}
List_Delete(smp);
}
int Intersect_Edges_2d(Edge * a, Edge * b)
{
double mat[2][2];
double rhs[2], x[2];
mat[0][0] = (a->V[1]->Pos.X - a->V[0]->Pos.X);
mat[0][1] = -(b->V[1]->Pos.X - b->V[0]->Pos.X);
mat[1][0] = (a->V[1]->Pos.Y - a->V[0]->Pos.Y);
mat[1][1] = -(b->V[1]->Pos.Y - b->V[0]->Pos.Y);
rhs[0] = b->V[0]->Pos.X - a->V[0]->Pos.X;
rhs[1] = b->V[0]->Pos.Y - a->V[0]->Pos.Y;
if(!sys2x2(mat, rhs, x))
return 0;
if(x[0] > 0.0 && x[0] < 1.0 && x[1] > 0.0 && x[1] < 1.0)
return 1;
return 0;
}
void putaindecoquille_2D(void *a, void *b)
{
Edge *e = (Edge *) a;
if(!compareVertex(&e->V[0], &THEEDGE->V[0]) ||
!compareVertex(&e->V[0], &THEEDGE->V[1]) ||
!compareVertex(&e->V[1], &THEEDGE->V[0]) ||
!compareVertex(&e->V[1], &THEEDGE->V[1])) {
return;
}
if(Intersect_Edges_2d(e, THEEDGE))
List_Add(coquille, &e);
}
void Recover_Edge(Surface * s, Edge * e, EdgesContainer & Edges)
{
THEEDGE = e;
int i;
Edge *me, E;
Vertex *v[2];
coquille = List_Create(3, 3, sizeof(Edge *));
/*On cherche la coquille */
Tree_Action(Edges.AllEdges, putaindecoquille_2D);
Msg(INFO, "Edge %d->%d, %d intersections",
e->V[0]->Num, e->V[1]->Num, List_Nbr(coquille));
if(List_Nbr(coquille) == 1) {
Msg(WARNING, "Unable to swap edge");
List_Delete(coquille);
return;
}
/*on swappe au hasard jusqu'a ce qu l'arete soit recuperee */
while(List_Nbr(coquille)) {
i = (int)(List_Nbr(coquille) * rand() / (RAND_MAX + 1.0));
//i = rand () % List_Nbr (coquille);
List_Read(coquille, i, &me);
v[0] = me->V[0];
v[1] = me->V[1];
List_Suppress(coquille, &me, compareEdgePtr);
Edges.SwapEdge(v);
if(Edges.Search(e->V[0], e->V[1]))
break;
E.V[0] = v[0];
E.V[1] = v[1];
me = (Edge *) Tree_PQuery(Edges.AllEdges, &E);
putaindecoquille_2D(me, NULL);
}
List_Delete(coquille);
Msg(INFO, "Edge recovered");
/*On swappe */
}
void constraint_the_edge(int isurf, int iv1, int iv2)
{
Vertex *v1 = FindVertex(iv1, THEM);
Vertex *v2 = FindVertex(iv2, THEM);
Surface *s = FindSurface(isurf, THEM);
Edge e;
if(!v1 || !v2)
return;
EdgesContainer EdgesOnSurface(s->Simplexes);
e.V[0] = v1;
e.V[1] = v2;
if(!EdgesOnSurface.Search(v1, v2)) {
Recover_Edge(s, &e, EdgesOnSurface);
}
}
void missing_edges_2d(Surface * s)
{
int i, j;
Curve *c;
Vertex *v1, *v2;
Edge e;
EdgesContainer EdgesOnSurface(s->Simplexes);
for(i = 0; i < List_Nbr(s->Generatrices); i++) {
List_Read(s->Generatrices, i, &c);
for(j = 1; j < List_Nbr(c->Vertices); j++) {
List_Read(c->Vertices, j - 1, &v1);
List_Read(c->Vertices, j, &v2);
e.V[0] = v1;
e.V[1] = v2;
if(!EdgesOnSurface.Search(v1, v2)) {
Msg(INFO, "Missing edge %d->%d", v1->Num, v2->Num);
Recover_Edge(s, &e, EdgesOnSurface);
}
}
}
}
int Restore_Boundary(Surface * s)
{
missing_edges_2d(s);
return 1;
}
int Maillage_Edge(Vertex * v1, Vertex * v2, List_T * Points)
{
int i;
static int qq = 1;
Simplex S, *s;
s = &S;
s->F[0].V[0] = v1;
s->F[0].V[1] = v2;
if(Tree_Search(FacesTree, &s))
return 0;
s = Create_Simplex_For2dmesh(v1, v2, NULL, NULL);
Tree_Add(FacesTree, &s);
Curve *c = Create_Curve(qq++, MSH_SEGM_LINE, 1, NULL, NULL, -1, -1, 0, 1);
Vertex *v;
c->Control_Points = List_Create(2, 1, sizeof(Vertex *));
List_Add(c->Control_Points, &v1);
List_Add(c->Control_Points, &v2);
c->beg = v1;
c->end = v2;
Maillage_Curve(&c, NULL);
for(i = 1; i < List_Nbr(c->Vertices) - 1; i++) {
List_Read(c->Vertices, i, &v);
List_Delete(v->ListCurves);
v->ListCurves = NULL;
List_Add(Points, &v);
}
List_Delete(c->Vertices);
List_Delete(c->Control_Points);
Free_Curve(&c, 0);
return 1;
}
void Action_First_Simplexes_2D(void *a, void *b)
{
Simplex *q;
if(!THES) {
q = *(Simplex **) a;
if(q->Pt_In_Ellipse(THEV, THEM->Metric->m)) {
THES = q;
}
}
}
void Fill_Sim_Des_2D(void *a, void *b)
{
Simplex *S;
S = *(Simplex **) a;
if(S->Pt_In_Ellipse(THEV, THEM->Metric->m))
List_Add(Simplexes_Destroyed, a);
}
void TStoLS_2D(void *a, void *b)
{
List_Add(Simplexes_Destroyed, a);
}
void TAtoLA_2D(void *a, void *b)
{
List_Add(Simplexes_New, a);
}
void CrSi_2D(void *a, void *b)
{
SxF *S;
Simplex *s;
S = (SxF *) a;
if(S->NumFaceSimpl == 1) {
s = Create_Simplex_For2dmesh(THEV, S->F.V[0], S->F.V[1], NULL);
s->iEnt = ZONEELIMINEE;
List_Add(Simplexes_New, &s);
}
else if(S->NumFaceSimpl != 2) {
Msg(GERROR, "Panic in CrSi_2D...");
}
}
void NewSimplexes_2D(Surface * s, List_T * Sim, List_T * news)
{
int i, j;
Tree_T *SimXFac;
Simplex *S;
SxF SXF, *pSXF;
SimXFac = Tree_Create(sizeof(SxF), compareSxF);
for(i = 0; i < List_Nbr(Sim); i++) {
List_Read(Sim, i, &S);
if(!i)
ZONEELIMINEE = S->iEnt;
else {
if(S->iEnt != ZONEELIMINEE) {
Msg(WARNING, "Huh! The elimination failed %d %d",
S->iEnt, ZONEELIMINEE);
}
}
for(j = 0; j < 3; j++) {
SXF.F = S->F[j];
if((pSXF = (SxF *) Tree_PQuery(SimXFac, &SXF))) {
(pSXF->NumFaceSimpl)++;
}
else {
SXF.NumFaceSimpl = 1;
Tree_Add(SimXFac, &SXF);
}
}
}
/* Les faces non communes sont obligatoirement a la frontiere ...
-> Nouveaux simplexes */
Tree_Action(SimXFac, CrSi_2D);
Tree_Delete(SimXFac);
}
int recur_bowyer_2D(Simplex * s)
{
int i;
Tree_Insert(Tsd, &s);
for(i = 0; i < 3; i++) {
if(s->S[i] && s->S[i] != &MyNewBoundary && !Tree_Query(Tsd, &s->S[i])) {
if(s->S[i]->Pt_In_Ellipse(THEV, THEM->Metric->m)
&& (s->iEnt == s->S[i]->iEnt)) {
recur_bowyer_2D(s->S[i]);
}
else {
if(s->iEnt != s->S[i]->iEnt) {
Alerte_Point_Scabreux = 1;
}
Tree_Insert(Sim_Sur_Le_Bord, &s->S[i]);
}
}
}
return 1;
}
bool draw_simplex2d(Surface * sur, Simplex * s, bool nouv)
{
Vertex v1, v2, v3;
if(!CTX.mesh.interactive)
return false;
if(s == &MyNewBoundary || !s || !s->iEnt)
return false;
v1 = InterpolateSurface(sur->Support, s->V[0]->Pos.X, s->V[0]->Pos.Y, 0, 0);
v2 = InterpolateSurface(sur->Support, s->V[1]->Pos.X, s->V[1]->Pos.Y, 0, 0);
v3 = InterpolateSurface(sur->Support, s->V[2]->Pos.X, s->V[2]->Pos.Y, 0, 0);
#if defined(HAVE_FLTK)
double x[3], y[3], z[3];
x[0] = v1.Pos.X;
x[1] = v2.Pos.X;
x[2] = v3.Pos.X;
y[0] = v1.Pos.Y;
y[1] = v2.Pos.Y;
y[2] = v3.Pos.Y;
z[0] = v1.Pos.Z;
z[1] = v2.Pos.Z;
z[2] = v3.Pos.Z;
void draw_polygon_2d(double r, double g, double b, int n,
double *x, double *y, double *z);
if(nouv)
draw_polygon_2d(1., 0., 0., 3, x, y, z);
else
draw_polygon_2d(0., 0., 0., 3, x, y, z);
#endif
return true;
}
bool Bowyer_Watson_2D(Surface * sur, Vertex * v, Simplex * S, int force)
{
int i;
Simplex *s;
static int init = 1;
double volumeold, volumenew;
THEV = v;
double x = (S->V[0]->Pos.X + S->V[1]->Pos.X + S->V[2]->Pos.X) / 3.;
double y = (S->V[0]->Pos.Y + S->V[1]->Pos.Y + S->V[2]->Pos.Y) / 3.;
if(force)
THEM->Metric->setMetricMin(x, y, sur->Support);
else
THEM->Metric->setMetric(x, y, sur->Support);
Tsd = Tree_Create(sizeof(Simplex *), compareSimplex);
Sim_Sur_Le_Bord = Tree_Create(sizeof(Simplex *), compareSimplex);
if(init) {
Simplexes_New = List_Create(10, 10, sizeof(Simplex *));
Simplexes_Destroyed = List_Create(10, 10, sizeof(Simplex *));
init = 0;
}
if(Methode) {
Tree_Action(sur->Simplexes, Fill_Sim_Des_2D);
S = NULL;
}
else {
recur_bowyer_2D(S);
}
Tree_Action(Tsd, TStoLS_2D);
NewSimplexes_2D(sur, Simplexes_Destroyed, Simplexes_New);
/* calcul des volumes des simplexes crees */
if(Alerte_Point_Scabreux || !CTX.mesh.speed_max) {
volume = 0.0;
for(i = 0; i < List_Nbr(Simplexes_Destroyed); i++) {
VSIM_2D(List_Pointer(Simplexes_Destroyed, i), NULL);
}
volumeold = volume;
volume = 0.0;
for(i = 0; i < List_Nbr(Simplexes_New); i++) {
VSIM_2D(List_Pointer(Simplexes_New, i), NULL);
}
volumenew = volume;
if(volumeold + volumenew == 0.0)
volumenew = 1.0;
}
else {
volumeold = 1.0;
volumenew = 1.0;
}
/* critere du volume */
if((fabs(volumeold - volumenew) / (volumeold + volumenew)) > 1.e-8) {
if(S) {
Tree_Suppress(sur->Simplexes, &S);
S->Quality /= 2.;
Tree_Add(sur->Simplexes, &S);
}
if(force) {
List_Reset(Simplexes_New);
List_Reset(Simplexes_Destroyed);
Tree_Delete(Sim_Sur_Le_Bord);
Tree_Delete(Tsd);
return false;
}
}
else {
Tree_Add(sur->Vertices, &THEV);
/* Suppression des simplexes elimines */
for(i = 0; i < List_Nbr(Simplexes_Destroyed); i++) {
List_Read(Simplexes_Destroyed, i, &s);
draw_simplex2d(sur, s, 0);
if(!Tree_Suppress(sur->Simplexes, &s)) {
Msg(WARNING, "Failed to suppress simplex %d", s->Num);
}
Free_Simplex(&s, 0);
}
for(i = 0; i < List_Nbr(Simplexes_New); i++) {
List_Read(Simplexes_New, i, &s);
if(0 || !force) {
double xc = s->Center.X;
double yc = s->Center.Y;
double rd = s->Radius;
cgsmpl(s, x, y);
THEM->Metric->setMetric(x, y, sur->Support);
THEM->Metric->setSimplexQuality(s, sur->Support);
s->Center.X = xc;
s->Center.Y = yc;
s->Radius = rd;
if(force)
THEM->Metric->Identity();
}
draw_simplex2d(sur, s, 1);
Tree_Add(sur->Simplexes, &s);
}
/* Creation des liens entre nouveaux simplexes */
Tree_Action(Sim_Sur_Le_Bord, TAtoLA_2D);
Link_Simplexes(Simplexes_New, sur->Simplexes);
}
List_Reset(Simplexes_New);
List_Reset(Simplexes_Destroyed);
Tree_Delete(Sim_Sur_Le_Bord);
Tree_Delete(Tsd);
return true;
}
void Convex_Hull_Mesh_2D(List_T * Points, Surface * s)
{
int i, N;
N = List_Nbr(Points);
Box_2_Triangles(Points, s);
for(i = 0; i < N; i++) {
THES = NULL;
List_Read(Points, i, &THEV);
Tree_Action(s->Simplexes, Action_First_Simplexes_2D);
/*
if(i%n == n-1){
volume = 0.0;
Tree_Action(s->Simplexes,VSIM_2D);
Msg(STATUS3, %d->%d Nodes, %d Elements",i+1,N,Tree_Nbr(s->Simplexes));
}
*/
if(!THES) {
Msg(GERROR, "Vertex (%g,%g,%g) in no simplex", THEV->Pos.X, THEV->Pos.Y,
THEV->Pos.Z);
THEV->Pos.X +=
CTX.mesh.rand_factor * LC2D * (1. -
(double)rand() / (double)RAND_MAX);
THEV->Pos.Y +=
CTX.mesh.rand_factor * LC2D * (1. -
(double)rand() / (double)RAND_MAX);
THEV->Pos.Z +=
CTX.mesh.rand_factor * LC2D * (1. -
(double)rand() / (double)RAND_MAX);
Tree_Action(s->Simplexes, Action_First_Simplexes_2D);
}
bool ca_marche = Bowyer_Watson_2D(s, THEV, THES, 1);
while(!ca_marche) {
double dx =
CTX.mesh.rand_factor * LC2D * (1. -
(double)rand() / (double)RAND_MAX);
double dy =
CTX.mesh.rand_factor * LC2D * (1. -
(double)rand() / (double)RAND_MAX);
THEV->Pos.X += dx;
THEV->Pos.Y += dy;
ca_marche = Bowyer_Watson_2D(s, THEV, THES, 1);
THEV->Pos.X -= dx;
THEV->Pos.Y -= dy;
}
}
}
/* recuperation de la surface */
static List_T *ListCurves, *ListAllCurves;
static Tree_T *keep;
static Simplex *SIMP;
static int iSurface;
void attribueSurface(void *a, void *b)
{
Simplex *s;
s = *(Simplex **) a;
s->iEnt = iSurface;
}
void Trouve_Simplex_2D(void *a, void *b)
{
Simplex *s;
if(SIMP != NULL)
return;
s = *(Simplex **) a;
if(s->iEnt < 0)
SIMP = s;
}
void Trouve_Simplex_Bord_2D(void *a, void *b)
{
Simplex *s;
if(SIMP != NULL)
return;
s = *(Simplex **) a;
if(s->V[0]->Num < 0 || s->V[1]->Num < 0 || s->V[2]->Num < 0)
SIMP = s;
}
void CourbesDansSurface(Surface * s, List_T * ListAllCurves)
{
int i, iseg;
Curve *c;
for(i = 0; i < List_Nbr(s->Generatrices); i++) {
List_Read(s->Generatrices, i, &c);
iseg = abs(c->Num);
List_Replace(ListAllCurves, &iseg, fcmp_int);
}
}
int isListaSurface(List_T * ListSurf, Surface * s)
{
int NN, j, srf;
bool found;
Curve *c;
NN = 0;
found = true;
for(j = 0; j < List_Nbr(s->Generatrices); j++) {
List_Read(s->Generatrices, j, &c);
srf = abs(c->Num);
if(!List_Search(ListSurf, &srf, fcmp_int)) {
found = false;
}
else
NN++;
}
if(found && NN == List_Nbr(ListSurf))
return s->Num;
return 0;
}
static List_T *StackSimp;
#define MAX_DEPTH 500
void recur_trouve_surface(Simplex * s, int *Depth)
{
int i, j;
Simplex *pS, S;
if(s->iEnt != -1)
return;
if((*Depth) > MAX_DEPTH) {
List_Add(StackSimp, &s);
return;
}
(*Depth)++;
s->iEnt = -2;
Tree_Add(keep, &s);
for(i = 0; i < 3; i++) {
pS = &S;
pS->F[0] = s->F[i];
if(Tree_Query(FacesTree, &pS)
&& List_Search(ListAllCurves, &pS->iEnt, fcmp_int)) {
j = abs(pS->iEnt);
List_Replace(ListCurves, &j, fcmp_int);
}
else if(s->S[i] && s->S[i] != &MyNewBoundary) {
recur_trouve_surface(s->S[i], Depth);
}
}
(*Depth)--;
}
extern int compareSimpSurf(const void *a, const void *b);
void Restore_Surface(Surface * s)
{
int N;
int i, depth;
StackSimp = List_Create(100, 100, sizeof(Simplex *));
ListCurves = List_Create(2, 2, sizeof(int));
iSurface = -1;
Tree_Action(s->Simplexes, attribueSurface);
/* Les simplexes sur le bord exterieur sont elimines */
ListAllCurves = List_Create(10, 3, sizeof(int));
CourbesDansSurface(s, ListAllCurves);
SIMP = NULL;
Tree_Action(s->Simplexes, Trouve_Simplex_Bord_2D);
if(SIMP) {
List_Add(StackSimp, &SIMP);
keep = Tree_Create(sizeof(Simplex *), compareQuality);
depth = 0;
i = 0;
do {
List_Read(StackSimp, i, &SIMP);
recur_trouve_surface(SIMP, &depth);
}
while(++i < List_Nbr(StackSimp));
List_Reset(StackSimp);
N = Tree_Nbr(keep);
iSurface = 0;
Tree_Action(keep, attribueSurface);
Tree_Delete(keep);
List_Reset(ListCurves);
}
while(1) {
SIMP = NULL;
keep = Tree_Create(sizeof(Simplex *), compareQuality);
Tree_Action(s->Simplexes, Trouve_Simplex_2D);
if(!SIMP)
break;
List_Add(StackSimp, &SIMP);
depth = 0;
i = 0;
do {
List_Read(StackSimp, i, &SIMP);
recur_trouve_surface(SIMP, &depth);
} while(++i < List_Nbr(StackSimp));
iSurface = isListaSurface(ListCurves, s);
N = Tree_Nbr(keep);
Msg(INFO,
"Initial mesh of Surface %d: %d simplices, %d/%d curves, %d faces",
iSurface, N, List_Nbr(ListCurves), List_Nbr(ListAllCurves),
Tree_Nbr(FacesTree));
Tree_Action(keep, attribueSurface);
Tree_Delete(keep);
List_Reset(ListCurves);
List_Reset(StackSimp);
}
// MEMORY LEAK (JF)
List_Delete(StackSimp);
List_Delete(ListCurves);
List_Delete(ListAllCurves);
}
void suppress_simplex_2D(void *data, void *dum)
{
Simplex **pv;
pv = (Simplex **) data;
if((*pv)->iEnt == 0)
List_Add(Suppress, pv);
}
Vertex *NewVertex_2D(Simplex * s)
{
Vertex *v = NULL;
double lc;
lc = (s->V[0]->lc + s->V[1]->lc + s->V[2]->lc) / 3.;
//lc = DMIN(MAXIMUM_LC_FOR_SURFACE,lc);
/*v = Create_Vertex( ++THEM->MaxPointNum,
(s->V[0]->Pos.X + s->V[1]->Pos.X + s->V[2]->Pos.X)/3.,
(s->V[0]->Pos.Y + s->V[1]->Pos.Y + s->V[2]->Pos.Y)/3.,
0.0, lc, 0.0);
*/
if(1){ // INSERTION_CENTROID
v = Create_Vertex(++THEM->MaxPointNum, s->Center.X, s->Center.Y, 0.0, lc, 0.0);
}
else{ // INSERTION_EDGE
Vertex *vv[2];
double l = THEM->Metric->getWorstEdge(s, PARAMETRIC, vv);
double f = 0.5;
if(vv[0]->lc <= vv[1]->lc)
f = vv[0]->lc / l;
else
f = 1. - (vv[1]->lc / l);
if(f >= 1)
v =
Create_Vertex(++THEM->MaxPointNum, s->Center.X, s->Center.Y, 0.0, lc,
0.0);
else
v = Create_Vertex(++THEM->MaxPointNum,
f * vv[0]->Pos.X + (1. - f) * vv[1]->Pos.X,
f * vv[0]->Pos.Y + (1. - f) * vv[1]->Pos.Y, 0.0, lc,
0.0);
}
v->lc = Interpole_lcTriangle(s, v);
if(PARAMETRIC) {
if(!v->ListCurves)
Normal2Surface(PARAMETRIC->Support, v->Pos.X, v->Pos.Y, v->us);
else {
v->us[0] = v->us[1] = v->us[2] = 0.0;
}
}
return (v);
}
void TRIE_MON_GARS(void *a, void *b)
{
Simplex *s = *(Simplex **) a;
s->Fourre_Simplexe(s->V[0], s->V[1], s->V[2], s->V[3]);
s->iEnt = SURF->Num;
s->S[0] = s->S[1] = s->S[2] = NULL;
THEM->Metric->setSimplexQuality(s, PARAMETRIC);
//SURF->Num;
//qsort(s->F[0].V,3,sizeof(Vertex*),compareVertex);
}
void RandomSwapEdges2d(Surface * s)
{
int i, j = 1, k;
List_T *AllTrg = Tree2List(s->Simplexes);
Simplex *t;
for(i = 0; i < List_Nbr(AllTrg); i++) {
k = rand() % List_Nbr(AllTrg);
List_Read(AllTrg, k, &t);
j = rand() % 3;
if(draw_simplex2d(s, t, false))
draw_simplex2d(s, t->S[j], false);
t->SwapEdge(j);
if(draw_simplex2d(s, t, true))
draw_simplex2d(s, t->S[j], true);
}
}
void IntelligentSwapEdges(Surface * s, GMSHMetric * m)
{
int i, j, k;
List_T *AllTrg = Tree2List(s->Simplexes);
Vertex *p[4], *q[4];
Simplex *t;
for(i = 0; i < List_Nbr(AllTrg); i++) {
k = rand() % List_Nbr(AllTrg);
List_Read(AllTrg, k, &t);
j = rand() % 3;
if(t->ExtractOppositeEdges(j, p, q)) {
double qp = 2. * m->EdgeLengthOnSurface(s, p, 1)
/ (RacineDeTrois * (p[0]->lc + p[1]->lc));
double qq = 2. * m->EdgeLengthOnSurface(s, q, 1)
/ (RacineDeTrois * (q[0]->lc + q[1]->lc));
if(fabs(qp) > fabs(qq)) {
if(draw_simplex2d(s, t, false))
draw_simplex2d(s, t->S[j], false);
t->SwapEdge(j);
if(draw_simplex2d(s, t, true))
draw_simplex2d(s, t->S[j], true);
}
}
}
List_Delete(AllTrg);
}
int AlgorithmeMaillage2DAnisotropeModeJF(Surface * s)
{
List_T *Points = List_Create(100, 100, sizeof(Vertex *));
int j, i, N, n;
List_T *c;
Curve *cur, *curinv;
extern int FACE_DIMENSION;
Simplex *simp;
Vertex *newv;
static int COUNT = 0;
FACE_DIMENSION = 1;
SURF = s;
if(s->Typ == MSH_SURF_PLAN || s->Typ == MSH_SURF_REGL
|| s->Typ == MSH_SURF_TRIC)
PARAMETRIC = NULL;
ZONEELIMINEE = s->Num;
for(i = 0; i < List_Nbr(s->Contours); i++) {
List_Read(s->Contours, i, &c);
for(j = 0; j < List_Nbr(c); j++) {
Vertex *pv;
List_Read(c, j, &pv);
List_Add(Points, &pv);
}
}
N = List_Nbr(Points);
n = N + 100;
Msg(STATUS2, "Mesh 2D... (initial)");
Convex_Hull_Mesh_2D(Points, s);
List_Reset(Points);
Link_Simplexes(NULL, s->Simplexes);
//return 1;
if(!Restore_Boundary(s)) {
//s->Simplexes = Tree_Create(sizeof(Simplex*),compareSimplex);
FACE_DIMENSION = 2;
Tree_Action(s->Simplexes, TRIE_MON_GARS);
return 1;
}
Tree_Action(s->Simplexes, TRIE_MON_GARS);
Link_Simplexes(NULL, s->Simplexes);
List_T *List = Tree2List(s->Simplexes);
Tree_Delete(s->Simplexes);
s->Simplexes = Tree_Create(sizeof(Simplex *), compareQuality);
for(i = 0; i < List_Nbr(List); i++)
Tree_Add(s->Simplexes, List_Pointer(List, i));
List_Delete(List);
// return 1;
FacesTree = Tree_Create(sizeof(Simplex *), compareSimpSurf);
for(i = 0; i < List_Nbr(s->Generatrices); i++) {
List_Read(s->Generatrices, i, &cur);
curinv = FindCurve(abs(cur->Num), THEM);
List_T *temp = Tree2List(curinv->Simplexes);
for(j = 0; j < List_Nbr(temp); j++) {
Tree_Add(FacesTree, List_Pointer(temp, j));
}
List_Delete(temp);
}
Restore_Surface(s);
// MEMORY LEAK (JF)
Tree_Delete(FacesTree);
Suppress = List_Create(10, 10, sizeof(Simplex *));
Tree_Action(s->Simplexes, suppress_simplex_2D);
for(i = 0; i < List_Nbr(Suppress); i++) {
Tree_Suppress(s->Simplexes, List_Pointer(Suppress, i));
}
Msg(STATUS2, "Mesh 2D... (final)");
if(!Tree_Right(s->Simplexes, &simp))
Msg(WARNING, "No simplex left");
else {
i = 0;
while(simp->Quality > CONV_VALUE) {
newv = NewVertex_2D(simp);
while(!simp->Pt_In_Simplex_2D(newv) &&
(simp->S[0] == &MyNewBoundary
|| !simp->S[0]->Pt_In_Simplex_2D(newv))
&& (simp->S[1] == &MyNewBoundary
|| !simp->S[1]->Pt_In_Simplex_2D(newv))
&& (simp->S[2] == &MyNewBoundary
|| !simp->S[2]->Pt_In_Simplex_2D(newv))) {
/*
Msg(INFO,"pt : %12.5E %12.5E",newv->Pos.X,newv->Pos.Y);
Msg(INFO,"not in : (%12.5E %12.5E) (%12.5E %12.5E) (%12.5E %12.5E)",
simp->V[0]->Pos.X,simp->V[0]->Pos.Y,simp->V[1]->Pos.X,
simp->V[1]->Pos.Y,simp->V[2]->Pos.X,simp->V[2]->Pos.Y);
*/
Tree_Suppress(s->Simplexes, &simp);
simp->Quality /= 2.;
Tree_Insert(s->Simplexes, &simp);
Tree_Right(s->Simplexes, &simp);
if(simp->Quality < CONV_VALUE)
break;
newv = NewVertex_2D(simp);
}
if(simp->Quality < CONV_VALUE)
break;
i++;
if(i % n == n - 1) {
volume = 0.0;
Tree_Action(s->Simplexes, VSIM_2D);
Msg(STATUS3, "Nod=%d Elm=%d",
Tree_Nbr(s->Vertices), Tree_Nbr(s->Simplexes));
Msg(STATUS1, "Vol(%g) Conv(%g->%g)", volume, simp->Quality,
CONV_VALUE);
}
Bowyer_Watson_2D(s, newv, simp, 0);
Tree_Right(s->Simplexes, &simp);
//if(i>COUNT)break;
}
}
//for(i=0;i<3;i++)RandomSwapEdges2d(s);
//for(i=0;i<2;i++)IntelligentSwapEdges(s,THEM->Metric);
List_Reset(Points);
FACE_DIMENSION = 2;
COUNT++;
Tree_Action(s->Simplexes, TRIE_MON_GARS);
Link_Simplexes(NULL, s->Simplexes);
List = Tree2List(s->Simplexes);
Tree_Delete(s->Simplexes);
s->Simplexes = Tree_Create(sizeof(Simplex *), compareSimplex);
for(i = 0; i < List_Nbr(List); i++)
Tree_Add(s->Simplexes, List_Pointer(List, i));
List_Delete(List);
/*suppression des points de la boite */
List = Tree2List(s->Vertices);
for(i = 0; i < List_Nbr(List); i++) {
List_Read(List, i, &THEV);
if(THEV->Num < 0) {
Tree_Suppress(s->Vertices, &THEV);
// BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
// MEMORY LEAK (JF) BUT THIS CAUSES PROBLEMS AFTER !!
// Free(THEV);
// BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
}
}
List_Delete(List);
if(!Tree_Nbr(s->Simplexes))
Msg(GERROR, "No triangles in surface %d", s->Num);
/*
RandomSwapEdges2d(s);
for(i=0;i<1;i++)IntelligentSwapEdges(s,THEM->Metric);
*/
//IntelligentSwapEdges(s,THEM->Metric);
List_Delete(Points);
// WAS A MEMORY LEAK
for(i = 0; i < List_Nbr(Suppress); i++) {
Free_Simplex(List_Pointer(Suppress, i), 0);
}
List_Delete(Suppress);
return 1;
}