Select Git revision
Advection1D.lua
Forked from
gmsh / gmsh
Source project has a limited visibility.
-
Emilie Marchandise authored
No commit message
Emilie Marchandise authoredNo commit message
3D_Extrude.cpp 31.58 KiB
// $Id: 3D_Extrude.cpp,v 1.88 2005-05-17 22:03:18 geuzaine Exp $
//
// Copyright (C) 1997-2005 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>.
#include "Gmsh.h"
#include "Numeric.h"
#include "Geo.h"
#include "CAD.h"
#include "Mesh.h"
#include "Context.h"
#include "Create.h"
extern Context_T CTX;
extern Mesh *THEM;
static int DIM, NUM; // current dimension of parent entity
static int BAD_TETS;
static Tree_T *Tree_Ares = NULL, *Tree_Swaps = NULL;
static Curve *THEC = NULL;
static Surface *THES = NULL;
static Volume *THEV = NULL;
static ExtrudeParams *ep;
// Point_Bound and Vertex_Bound contain the points and vertices on the
// "boundaries". We cannot check for duplicates in THEM->Points and
// THEM->Vertices directly since the comparison function for these
// trees are on the point/vertex numbers, not the position.
static Tree_T *Point_Bound = NULL, *Vertex_Bound = NULL;
typedef struct
{
int Dim, Num;
List_T *List;
}
nxl;
static int compnxl(const void *a, const void *b)
{
int val;
nxl *q = (nxl *) a, *w = (nxl *) b;
if((val = q->Dim - w->Dim) != 0)
return val;
return q->Num - w->Num;
}
List_T *getnxl(Vertex * v, Curve * c)
{
nxl NXL;
NXL.Dim = 1;
NXL.Num = abs(c->Num);
nxl *NXLP = (nxl *) List_PQuery(v->Extruded_Points, &NXL, compnxl);
if(NXLP)
return NXLP->List;
return NULL;
}
List_T *getnxl(Vertex * v, Surface * s)
{
nxl NXL;
NXL.Dim = 2;
NXL.Num = s->Num;
nxl *NXLP = (nxl *) List_PQuery(v->Extruded_Points, &NXL, compnxl);
if(NXLP)
return NXLP->List;
return NULL;
}
List_T *getnxl(Vertex * v, Volume * vol)
{
nxl NXL;
NXL.Dim = 3;
NXL.Num = vol->Num;
nxl *NXLP = (nxl *) List_PQuery(v->Extruded_Points, &NXL, compnxl);
if(NXLP)
return NXLP->List;
return NULL;
}
List_T *getnxl(Vertex * v, int dim)
{
int i, j;
Curve *c;
Surface *s;
List_T *list;
// the test on the source entity is in case we extrude a
// curve/surface resulting from the extrusion of a point/curve...
if(dim == 1) {
if((list = getnxl(v, THEC)))
return list;
}
else if(dim == 2) {
if((list = getnxl(v, THES)))
return list;
else {
for(i = 0; i < List_Nbr(THES->Generatrices); i++) {
if((abs(ep->geo.Source) != c->Num) && (list = getnxl(v, c)))
return list;
}
}
}
else if(dim == 3) {
if((list = getnxl(v, THEV)))
return list;
else {
for(i = 0; i < List_Nbr(THEV->Surfaces); i++) {
List_Read(THEV->Surfaces, i, &s);
if((ep->geo.Source != s->Num) && (list = getnxl(v, s)))
return list;
}
for(i = 0; i < List_Nbr(THEV->Surfaces); i++) {
List_Read(THEV->Surfaces, i, &s);
if(ep->geo.Source != s->Num) {
for(j = 0; j < List_Nbr(s->Generatrices); j++) {
List_Read(s->Generatrices, j, &c);
if((list = getnxl(v, c)))
return list;
}
}
}
}
}
Msg(GERROR, "Could not find extruded list for vertex %d", v->Num);
return NULL;
}
void Free_ExtrudedPoints(List_T * Extruded_Points)
{
nxl *NXL;
for(int i = 0; i < List_Nbr(Extruded_Points); i++) {
NXL = (nxl *) List_Pointer(Extruded_Points, i);
List_Delete(NXL->List);
}
List_Delete(Extruded_Points);
}
typedef struct
{
int a, b;
}
nxn;
static int compnxn(const void *a, const void *b)
{
nxn *q, *w;
q = (nxn *) a;
w = (nxn *) b;
if(q->a > w->a)
return 1;
if(q->a < w->a)
return -1;
if(q->b > w->b)
return 1;
if(q->b < w->b)
return -1;
return 0;
}
void InsertInVertexBound(void *a, void *b)
{
Tree_Insert(Vertex_Bound, a);
}
void InsertInPointBound(void *a, void *b)
{
Tree_Insert(Point_Bound, a);
}
void InitExtrude()
{
if(!Tree_Ares)
Tree_Ares = Tree_Create(sizeof(nxn), compnxn);
if(!Tree_Swaps)
Tree_Swaps = Tree_Create(sizeof(nxn), compnxn);
if(Point_Bound)
Tree_Delete(Point_Bound);
Point_Bound = Tree_Create(sizeof(Vertex *), comparePosition);
if(Vertex_Bound)
Tree_Delete(Vertex_Bound);
Vertex_Bound = Tree_Create(sizeof(Vertex *), comparePosition);
Tree_Action(THEM->Points, InsertInPointBound);
Tree_Action(THEM->Vertices, InsertInVertexBound);
}
void ExitExtrude()
{
if(Tree_Ares)
Tree_Delete(Tree_Ares);
if(Tree_Swaps)
Tree_Delete(Tree_Swaps);
if(Point_Bound)
Tree_Delete(Point_Bound);
if(Vertex_Bound)
Tree_Delete(Vertex_Bound);
Tree_Ares = Tree_Swaps = Point_Bound = Vertex_Bound = NULL;
}
int are_exist(Vertex * v1, Vertex * v2, Tree_T * t)
{
nxn n;
n.a = IMAX(v1->Num, v2->Num);
n.b = IMIN(v1->Num, v2->Num);
return Tree_Search(t, &n);
}
void are_cree(Vertex * v1, Vertex * v2, Tree_T * t)
{
nxn n;
n.a = IMAX(v1->Num, v2->Num);
n.b = IMIN(v1->Num, v2->Num);
Tree_Replace(t, &n);
}
void are_del(Vertex * v1, Vertex * v2, Tree_T * t)
{
nxn n;
n.a = IMAX(v1->Num, v2->Num);
n.b = IMIN(v1->Num, v2->Num);
Tree_Suppress(t, &n);
}
void Extrude_Simplex_Phase1(void *data, void *dum)
{
Vertex *v1, *v2, *v3, *v4, *v5, *v6;
Simplex *s = *(Simplex **) data;
List_T *L0 = getnxl(s->V[0], DIM);
List_T *L1 = getnxl(s->V[1], DIM);
List_T *L2 = getnxl(s->V[2], DIM);
if(!L0 || !L1 || !L2) return;
int k = 0;
for(int i = 0; i < ep->mesh.NbLayer; i++) {
for(int j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
List_Read(L0, k, &v1);
List_Read(L1, k, &v2);
List_Read(L2, k, &v3);
List_Read(L0, k + 1, &v4);
List_Read(L1, k + 1, &v5);
List_Read(L2, k + 1, &v6);
k++;
if(!are_exist(v1, v5, Tree_Ares))
are_cree(v2, v4, Tree_Ares);
if(!are_exist(v5, v3, Tree_Ares))
are_cree(v2, v6, Tree_Ares);
if(!are_exist(v4, v3, Tree_Ares))
are_cree(v1, v6, Tree_Ares);
}
}
}
void Extrude_Simplex_Phase2(void *data, void *dum)
{
Vertex *v1, *v2, *v3, *v4, *v5, *v6;
Simplex *s = *(Simplex **) data;
List_T *L0 = getnxl(s->V[0], DIM);
List_T *L1 = getnxl(s->V[1], DIM);
List_T *L2 = getnxl(s->V[2], DIM);
if(!L0 || !L1 || !L2) return;
int k = 0;
for(int i = 0; i < ep->mesh.NbLayer; i++) {
for(int j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
List_Read(L0, k, &v1);
List_Read(L1, k, &v2);
List_Read(L2, k, &v3);
List_Read(L0, k + 1, &v4);
List_Read(L1, k + 1, &v5);
List_Read(L2, k + 1, &v6);
k++;
if(are_exist(v4, v2, Tree_Ares) &&
are_exist(v5, v3, Tree_Ares) &&
are_exist(v1, v6, Tree_Ares)) {
BAD_TETS++;
if(!are_exist(v4, v2, Tree_Swaps)) {
are_del(v4, v2, Tree_Ares);
are_cree(v1, v5, Tree_Ares);
are_cree(v1, v5, Tree_Swaps);
are_cree(v4, v2, Tree_Swaps);
}
else if(!are_exist(v5, v3, Tree_Swaps)) {
are_del(v5, v3, Tree_Ares);
are_cree(v2, v6, Tree_Ares);
are_cree(v5, v3, Tree_Swaps);
are_cree(v2, v6, Tree_Swaps);
}
else if(!are_exist(v1, v6, Tree_Swaps)) {
are_del(v1, v6, Tree_Ares);
are_cree(v4, v3, Tree_Ares);
are_cree(v1, v6, Tree_Swaps);
are_cree(v4, v3, Tree_Swaps);
}
}
else if(are_exist(v1, v5, Tree_Ares) &&
are_exist(v2, v6, Tree_Ares) &&
are_exist(v4, v3, Tree_Ares)) {
BAD_TETS++;
if(!are_exist(v1, v5, Tree_Swaps)) {
are_del(v1, v5, Tree_Ares);
are_cree(v4, v2, Tree_Ares);
are_cree(v1, v5, Tree_Swaps);
are_cree(v4, v2, Tree_Swaps);
}
else if(!are_exist(v2, v6, Tree_Swaps)) {
are_del(v2, v6, Tree_Ares);
are_cree(v5, v3, Tree_Ares);
are_cree(v5, v3, Tree_Swaps);
are_cree(v2, v6, Tree_Swaps);
}
else if(!are_exist(v4, v3, Tree_Swaps)) {
are_del(v4, v3, Tree_Ares);
are_cree(v1, v6, Tree_Ares);
are_cree(v1, v6, Tree_Swaps);
are_cree(v4, v3, Tree_Swaps);
}
}
}
}
}
void Create_HexPri(int iEnt, Vertex * v[8])
{
int i, j = 0, dup[4];
Hexahedron *newh;
Prism *newp;
if(CTX.mesh.allow_degenerated_extrude) {
newh = Create_Hexahedron(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
newh->iEnt = (iEnt && ep->useZonLayer()) ? iEnt : THEV->Num;
Tree_Add(THEV->Hexahedra, &newh);
return;
}
for(i = 0; i < 4; i++)
if(v[i]->Num == v[i + 4]->Num)
dup[j++] = i;
if(j == 2) {
if(dup[0] == 0 && dup[1] == 1)
newp = Create_Prism(v[0], v[3], v[7], v[1], v[6], v[2]);
else if(dup[0] == 1 && dup[1] == 2)
newp = Create_Prism(v[0], v[1], v[4], v[3], v[2], v[7]);
else if(dup[0] == 2 && dup[1] == 3)
newp = Create_Prism(v[0], v[3], v[4], v[1], v[5], v[7]);
else if(dup[0] == 0 && dup[1] == 3)
newp = Create_Prism(v[0], v[1], v[5], v[3], v[2], v[6]);
else {
Msg(GERROR, "Uncoherent hexahedron (nodes %d %d %d %d %d %d %d %d)",
v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
return;
}
newp->iEnt = (iEnt && ep->useZonLayer()) ? iEnt : THEV->Num;
Tree_Add(THEV->Prisms, &newp);
}
else {
newh = Create_Hexahedron(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
newh->iEnt = (iEnt && ep->useZonLayer()) ? iEnt : THEV->Num;
Tree_Add(THEV->Hexahedra, &newh);
if(j)
Msg(GERROR, "Degenerated hexahedron %d (nodes %d %d %d %d %d %d %d %d)",
newh->Num, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
}
}
void Create_PriPyrTet(int iEnt, Vertex * v[6])
{
int i, j = 0, dup[3];
Prism *newp;
Pyramid *newpyr;
Simplex *news;
if(CTX.mesh.allow_degenerated_extrude) {
newp = Create_Prism(v[0], v[1], v[2], v[3], v[4], v[5]);
newp->iEnt = (iEnt && ep->useZonLayer()) ? iEnt : THEV->Num;
Tree_Add(THEV->Prisms, &newp);
return;
}
for(i = 0; i < 3; i++)
if(v[i]->Num == v[i + 3]->Num)
dup[j++] = i;
if(j == 2) {
if(dup[0] == 0 && dup[1] == 1)
news = Create_Simplex(v[0], v[1], v[2], v[5]);
else if(dup[0] == 1 && dup[1] == 2)
news = Create_Simplex(v[0], v[1], v[2], v[3]);
else
news = Create_Simplex(v[0], v[1], v[2], v[4]);
news->iEnt = (iEnt && ep->useZonLayer()) ? iEnt : THEV->Num;
Tree_Add(THEV->Simplexes, &news);
}
else if(j == 1) {
if(dup[0] == 0)
newpyr = Create_Pyramid(v[1], v[4], v[5], v[2], v[0]);
else if(dup[0] == 1)
newpyr = Create_Pyramid(v[0], v[2], v[5], v[3], v[1]);
else
newpyr = Create_Pyramid(v[0], v[1], v[4], v[3], v[2]);
newpyr->iEnt = (iEnt && ep->useZonLayer()) ? iEnt : THEV->Num;
Tree_Add(THEV->Pyramids, &newpyr);
}
else {
newp = Create_Prism(v[0], v[1], v[2], v[3], v[4], v[5]);
newp->iEnt = (iEnt && ep->useZonLayer()) ? iEnt : THEV->Num;
Tree_Add(THEV->Prisms, &newp);
if(j)
Msg(GERROR, "Degenerated prism %d (nodes %d %d %d %d %d %d)",
newp->Num, v[0], v[1], v[2], v[3], v[4], v[5]);
}
}
void Create_Sim(int iEnt, Vertex * v1, Vertex * v2, Vertex * v3, Vertex * v4)
{
Simplex *news;
if(CTX.mesh.allow_degenerated_extrude ||
(v1->Num != v2->Num && v1->Num != v3->Num && v1->Num != v4->Num &&
v2->Num != v3->Num && v2->Num != v4->Num && v3->Num != v4->Num)) {
news = Create_Simplex(v1, v2, v3, v4);
news->iEnt = (iEnt && ep->useZonLayer()) ? iEnt : THEV->Num;
Tree_Add(THEV->Simplexes, &news);
}
}
void Extrude_Simplex_Phase3(void *data, void *dum)
{
int i, j, k;
Vertex *v[8];
Simplex *s = *(Simplex **) data;
List_T *L0 = getnxl(s->V[0], DIM);
List_T *L1 = getnxl(s->V[1], DIM);
List_T *L2 = getnxl(s->V[2], DIM);
if(!L0 || !L1 || !L2) return;
k = 0;
for(i = 0; i < ep->mesh.NbLayer; i++) {
for(j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
List_Read(L0, k, &v[0]);
List_Read(L1, k, &v[1]);
List_Read(L2, k, &v[2]);
List_Read(L0, k + 1, &v[3]);
List_Read(L1, k + 1, &v[4]);
List_Read(L2, k + 1, &v[5]);
k++;
if(ep->mesh.Recombine) {
Create_PriPyrTet(ep->mesh.ZonLayer[i], v);
}
else {
if(are_exist(v[3], v[1], Tree_Ares) &&
are_exist(v[4], v[2], Tree_Ares) &&
are_exist(v[3], v[2], Tree_Ares)) {
Create_Sim(ep->mesh.ZonLayer[i], v[0], v[1], v[2], v[3]);
Create_Sim(ep->mesh.ZonLayer[i], v[3], v[4], v[5], v[2]);
Create_Sim(ep->mesh.ZonLayer[i], v[1], v[3], v[4], v[2]);
}
else if(are_exist(v[3], v[1], Tree_Ares) &&
are_exist(v[1], v[5], Tree_Ares) &&
are_exist(v[3], v[2], Tree_Ares)) {
Create_Sim(ep->mesh.ZonLayer[i], v[0], v[1], v[2], v[3]);
Create_Sim(ep->mesh.ZonLayer[i], v[3], v[4], v[5], v[1]);
Create_Sim(ep->mesh.ZonLayer[i], v[3], v[1], v[5], v[2]);
}
else if(are_exist(v[3], v[1], Tree_Ares) &&
are_exist(v[1], v[5], Tree_Ares) &&
are_exist(v[5], v[0], Tree_Ares)) {
Create_Sim(ep->mesh.ZonLayer[i], v[0], v[1], v[2], v[5]);
Create_Sim(ep->mesh.ZonLayer[i], v[3], v[4], v[5], v[1]);
Create_Sim(ep->mesh.ZonLayer[i], v[1], v[3], v[5], v[0]);
}
else if(are_exist(v[4], v[0], Tree_Ares) &&
are_exist(v[4], v[2], Tree_Ares) &&
are_exist(v[3], v[2], Tree_Ares)) {
Create_Sim(ep->mesh.ZonLayer[i], v[0], v[1], v[2], v[4]);
Create_Sim(ep->mesh.ZonLayer[i], v[3], v[4], v[5], v[2]);
Create_Sim(ep->mesh.ZonLayer[i], v[0], v[3], v[4], v[2]);
}
else if(are_exist(v[4], v[0], Tree_Ares) &&
are_exist(v[4], v[2], Tree_Ares) &&
are_exist(v[5], v[0], Tree_Ares)) {
Create_Sim(ep->mesh.ZonLayer[i], v[0], v[1], v[2], v[4]);
Create_Sim(ep->mesh.ZonLayer[i], v[3], v[4], v[5], v[0]);
Create_Sim(ep->mesh.ZonLayer[i], v[0], v[2], v[4], v[5]);
}
else if(are_exist(v[4], v[0], Tree_Ares) &&
are_exist(v[1], v[5], Tree_Ares) &&
are_exist(v[5], v[0], Tree_Ares)) {
Create_Sim(ep->mesh.ZonLayer[i], v[0], v[1], v[2], v[5]);
Create_Sim(ep->mesh.ZonLayer[i], v[3], v[4], v[5], v[0]);
Create_Sim(ep->mesh.ZonLayer[i], v[0], v[1], v[4], v[5]);
}
}
}
}
}
void Extrude_Quadrangle_Phase3(void *data, void *dum)
{
int i, j, k;
Vertex *v[8];
Quadrangle *q = *(Quadrangle **) data;
if(!ep->mesh.Recombine) {
Msg(GERROR, "You have to use 'Recombine' to extrude quadrangular meshes");
return;
}
List_T *L0 = getnxl(q->V[0], DIM);
List_T *L1 = getnxl(q->V[1], DIM);
List_T *L2 = getnxl(q->V[2], DIM);
List_T *L3 = getnxl(q->V[3], DIM);
if(!L0 || !L1 || !L2 || !L3) return;
k = 0;
for(i = 0; i < ep->mesh.NbLayer; i++) {
for(j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
List_Read(L0, k, &v[0]);
List_Read(L1, k, &v[1]);
List_Read(L2, k, &v[2]);
List_Read(L3, k, &v[3]);
List_Read(L0, k + 1, &v[4]);
List_Read(L1, k + 1, &v[5]);
List_Read(L2, k + 1, &v[6]);
List_Read(L3, k + 1, &v[7]);
k++;
Create_HexPri(ep->mesh.ZonLayer[i], v);
}
}
}
void Extrude_Vertex(void *data, void *dum)
{
Vertex **vexist, *v, *newv;
int i, j;
nxl NXL;
v = *((Vertex **) data);
if(!v->Extruded_Points)
v->Extruded_Points = List_Create(1, 1, sizeof(nxl));
NXL.Num = NUM;
NXL.Dim = DIM;
if(List_Search(v->Extruded_Points, &NXL, compnxl))
return;
else
NXL.List = List_Create(ep->mesh.NbLayer, 1, sizeof(Vertex *));
List_Add(NXL.List, &v);
for(i = 0; i < ep->mesh.NbLayer; i++) {
for(j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
newv = Create_Vertex(++THEM->MaxPointNum, v->Pos.X,
v->Pos.Y, v->Pos.Z, v->lc, v->u);
ep->Extrude(i, j + 1, newv->Pos.X, newv->Pos.Y, newv->Pos.Z);
if(Vertex_Bound && (vexist = (Vertex **) Tree_PQuery(Vertex_Bound, &newv))) {
Free_Vertex(&newv, 0);
List_Add(NXL.List, vexist);
}
else{
if(Point_Bound && (vexist = (Vertex **) Tree_PQuery(Point_Bound, &newv))) {
// keep the new one: we cannot have points and vertices
// pointing to the same memory location
newv->Num = (*vexist)->Num;
}
List_Add(NXL.List, &newv);
Tree_Add(THEM->Vertices, &newv);
Tree_Insert(Vertex_Bound, &newv);
}
}
}
List_Add(v->Extruded_Points, &NXL);
}
void Extrude_Surface1(Surface * s)
{
THES = s;
Tree_Action(s->Vertices, Extrude_Vertex);
if(!ep->mesh.Recombine){
Tree_Action(s->Simplexes, Extrude_Simplex_Phase1);
Tree_Action(s->SimplexesBase, Extrude_Simplex_Phase1);
}
}
void Extrude_Surface2(Surface * s)
{
THES = s;
Tree_Action(s->Simplexes, Extrude_Simplex_Phase2);
Tree_Action(s->SimplexesBase, Extrude_Simplex_Phase2);
}
void Extrude_Surface3(Surface * s)
{
THES = s;
Tree_Action(s->Simplexes, Extrude_Simplex_Phase3);
Tree_Action(s->SimplexesBase, Extrude_Simplex_Phase3);
Tree_Action(s->Quadrangles, Extrude_Quadrangle_Phase3);
}
void Create_Tri(int iEnt, Vertex * v1, Vertex * v2, Vertex * v3)
{
if(CTX.mesh.allow_degenerated_extrude ||
(v1->Num != v2->Num && v1->Num != v3->Num && v2->Num != v3->Num)) {
Simplex *s = Create_Simplex(v1, v2, v3, NULL);
s->iEnt = (iEnt && ep->useZonLayer()) ? iEnt : THES->Num;
s->Num = -s->Num; //Tag triangles to re-extrude
Tree_Add(THES->Simplexes, &s);
}
}
void Extrude_Seg(Vertex * V1, Vertex * V2)
{
Vertex *v1, *v2, *v3, *v4;
List_T *L1 = getnxl(V1, DIM);
List_T *L2 = getnxl(V2, DIM);
if(!L1 || !L2) return;
int k = 0;
for(int i = 0; i < ep->mesh.NbLayer; i++) {
for(int j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
List_Read(L1, k, &v1);
List_Read(L2, k, &v2);
List_Read(L1, k + 1, &v3);
List_Read(L2, k + 1, &v4);
if(ep->mesh.Recombine) {
if(CTX.mesh.allow_degenerated_extrude){
Quadrangle *q = Create_Quadrangle(v1, v2, v4, v3);
q->iEnt = (ep->mesh.ZonLayer[i] && ep->useZonLayer()) ?
ep->mesh.ZonLayer[i] : THES->Num;
q->Num = -q->Num; // Tag elt to re-extrude
Tree_Add(THES->Quadrangles, &q);
}
else if(v1->Num == v2->Num || v2->Num == v4->Num){
Simplex *s = Create_Simplex(v1, v4, v3, NULL);
s->iEnt = (ep->mesh.ZonLayer[i] && ep->useZonLayer()) ?
ep->mesh.ZonLayer[i] : THES->Num;
s->Num = -s->Num; // Tag elt to re-extrude
Tree_Add(THES->Simplexes, &s);
}
else if(v1->Num == v3->Num || v3->Num == v4->Num){
Simplex *s = Create_Simplex(v1, v2, v4, NULL);
s->iEnt = (ep->mesh.ZonLayer[i] && ep->useZonLayer()) ?
ep->mesh.ZonLayer[i] : THES->Num;
s->Num = -s->Num; // Tag elt to re-extrude
Tree_Add(THES->Simplexes, &s);
}
else if(v1->Num == v4->Num || v2->Num == v3->Num) {
Msg(GERROR, "Uncoherent quadrangle (nodes %d %d %d %d)",
v1->Num, v2->Num, v3->Num, v4->Num);
return;
}
else{
Quadrangle *q = Create_Quadrangle(v1, v2, v4, v3);
q->iEnt = (ep->mesh.ZonLayer[i] && ep->useZonLayer()) ?
ep->mesh.ZonLayer[i] : THES->Num;
q->Num = -q->Num; // Tag elt to re-extrude
Tree_Add(THES->Quadrangles, &q);
}
}
else {
if(are_exist(v3, v2, Tree_Ares)) {
Create_Tri(ep->mesh.ZonLayer[i], v3, v2, v1);
Create_Tri(ep->mesh.ZonLayer[i], v3, v4, v2);
}
else {
Create_Tri(ep->mesh.ZonLayer[i], v3, v4, v1);
Create_Tri(ep->mesh.ZonLayer[i], v1, v4, v2);
}
}
k++;
}
}
}
void Extrude_Curve(void *data, void *dum)
{
Vertex *v1, *v2;
Curve *c = *(Curve **) data;
//if (c->Num < 0) return;
for(int i = 0; i < List_Nbr(c->Vertices) - 1; i++) {
List_Read(c->Vertices, i, &v1);
List_Read(c->Vertices, i + 1, &v2);
Extrude_Seg(v1, v2);
}
}
void copy_mesh(Curve * from, Curve * to, int direction)
{
List_T *list = from->Vertices;
Vertex **vexist, *v, *newv;
int nb = List_Nbr(to->Vertices);
if(nb) {
if(nb != List_Nbr(from->Vertices))
Msg(GERROR, "Incompatible extrusion of curve %d into curve %d",
from->Num, to->Num);
return;
}
v = to->beg;
if((vexist = (Vertex **) Tree_PQuery(THEM->Vertices, &v))) {
(*vexist)->u = to->ubeg;
if((*vexist)->ListCurves)
List_Add((*vexist)->ListCurves, &to);
List_Add(to->Vertices, vexist);
}
else {
newv = Create_Vertex(v->Num, v->Pos.X, v->Pos.Y, v->Pos.Z, v->lc, to->ubeg);
Tree_Add(THEM->Vertices, &newv);
newv->ListCurves = List_Create(1, 1, sizeof(Curve *));
List_Add(newv->ListCurves, &to);
List_Add(to->Vertices, &newv);
}
for(int i = 1; i < List_Nbr(list) - 1; i++) {
if(direction < 0)
List_Read(list, List_Nbr(list) - 1 - i, &v);
else
List_Read(list, i, &v);
newv = Create_Vertex(++THEM->MaxPointNum, v->Pos.X,
v->Pos.Y, v->Pos.Z, v->lc,
(direction > 0) ? v->u : (1. - v->u));
ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1],
newv->Pos.X, newv->Pos.Y, newv->Pos.Z);
if(!comparePosition(&newv, &v)) {
Free_Vertex(&newv, 0);
newv = v;
}
else if(Vertex_Bound && (vexist = (Vertex **) Tree_PQuery(Vertex_Bound, &newv))) {
Free_Vertex(&newv, 0);
newv = *vexist;
}
else {
if(Point_Bound && (vexist = (Vertex **) Tree_PQuery(Point_Bound, &newv))) {
// keep the new one: we cannot have points and vertices
// pointing to the same memory location
newv->Num = (*vexist)->Num;
}
Tree_Add(THEM->Vertices, &newv);
Tree_Insert(Vertex_Bound, &newv);
}
if(!newv->ListCurves)
newv->ListCurves = List_Create(1, 1, sizeof(Curve *));
List_Add(newv->ListCurves, &to);
List_Add(to->Vertices, &newv);
}
v = to->end;
if((vexist = (Vertex **) Tree_PQuery(THEM->Vertices, &v))) {
(*vexist)->u = to->uend;
if((*vexist)->ListCurves)
List_Add((*vexist)->ListCurves, &to);
List_Add(to->Vertices, vexist);
}
else {
newv = Create_Vertex(v->Num, v->Pos.X, v->Pos.Y, v->Pos.Z, v->lc, to->uend);
Tree_Add(THEM->Vertices, &newv);
newv->ListCurves = List_Create(1, 1, sizeof(Curve *));
List_Add(newv->ListCurves, &to);
List_Add(to->Vertices, &newv);
}
for(int i = 0; i < List_Nbr(to->Vertices) - 1; i++) {
Vertex *v1, *v2;
List_Read(to->Vertices, i, &v1);
List_Read(to->Vertices, i + 1, &v2);
Simplex *s = Create_Simplex(v1, v2, NULL, NULL);
s->iEnt = to->Num;
Tree_Add(to->Simplexes, &s);
}
}
int Extrude_Mesh(Curve * c)
{
int i, j;
Vertex **vexist, *v, *newv, *v1, *v2;
List_T *L;
if(!c->Extrude || !c->Extrude->mesh.ExtrudeMesh)
return false;
InitExtrude();
THEC = c;
DIM = 1;
NUM = c->Num;
ep = c->Extrude;
if(ep->geo.Mode == EXTRUDED_ENTITY) {
Extrude_Vertex(&c->beg, NULL);
L = getnxl(c->beg, DIM);
if(!L) return false;
v = c->beg;
if((vexist = (Vertex **) Tree_PQuery(THEM->Vertices, &v))) {
(*vexist)->u = c->ubeg;
if((*vexist)->ListCurves)
List_Add((*vexist)->ListCurves, &c);
List_Add(c->Vertices, vexist);
}
else {
newv = Create_Vertex(v->Num, v->Pos.X, v->Pos.Y, v->Pos.Z, v->lc, c->ubeg);
newv->ListCurves = List_Create(1, 1, sizeof(Curve *));
List_Add(newv->ListCurves, &c);
Tree_Add(THEM->Vertices, &newv);
List_Add(c->Vertices, &newv);
}
for(i = 1; i < List_Nbr(L) - 1; i++) {
List_Read(L, i, &v);
if(!v->ListCurves)
v->ListCurves = List_Create(1, 1, sizeof(Curve *));
List_Add(v->ListCurves, &c);
Tree_Insert(THEM->Vertices, &v);
// This is not correct when we have multiple layers with
// different spacings. So we fill this in later.
//v->u = (double)i / (double)(List_Nbr(L)-1);
List_Add(c->Vertices, &v);
}
v = c->end;
if((vexist = (Vertex **) Tree_PQuery(THEM->Vertices, &v))) {
(*vexist)->u = c->uend;
if((*vexist)->ListCurves)
List_Add((*vexist)->ListCurves, &c);
List_Add(c->Vertices, vexist);
}
else {
newv = Create_Vertex(v->Num, v->Pos.X, v->Pos.Y, v->Pos.Z, v->lc, c->uend);
newv->ListCurves = List_Create(1, 1, sizeof(Curve *));
List_Add(newv->ListCurves, &c);
Tree_Add(THEM->Vertices, &newv);
List_Add(c->Vertices, &newv);
}
int k = 0;
for(i = 0; i < ep->mesh.NbLayer; i++) {
for(j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
if(k >= List_Nbr(c->Vertices) - 1){
Msg(GERROR, "Something wrong in number of elements in extruded curve %d",
c->Num);
return false;
}
List_Read(c->Vertices, k, &v1);
List_Read(c->Vertices, k + 1, &v2);
Simplex *s = Create_Simplex(v1, v2, NULL, NULL);
s->iEnt = (ep->mesh.ZonLayer[i] && ep->useZonLayer()) ?
ep->mesh.ZonLayer[i] : c->Num;
Tree_Add(c->Simplexes, &s);
// fill-in the data we didn't have above:
v1->u = ep->u(i, j);
k++;
}
}
}
else {
Curve *cc = FindCurve(abs(ep->geo.Source), THEM);
if(!cc)
return false;
copy_mesh(cc, c, sign(ep->geo.Source));
}
return true;
}
void copy_mesh(Surface * from, Surface * to)
{
List_T *list;
Simplex *s;
Quadrangle *q;
Vertex **vexist, *newv[4];
int nbs = Tree_Nbr(to->Simplexes);
if(nbs){
if(nbs != Tree_Nbr(from->Simplexes))
Msg(GERROR, "Incompatible extrusion of surface %d into surface %d",
from->Num, to->Num);
return;
}
int nbq = Tree_Nbr(to->Quadrangles);
if(nbq){
if(nbq != Tree_Nbr(from->Quadrangles))
Msg(GERROR, "Incompatible extrusion of surface %d into surface %d",
from->Num, to->Num);
return;
}
// triangles
list = Tree2List(from->Simplexes);
for(int i = 0; i < List_Nbr(list); i++) {
List_Read(list, i, &s);
for(int j = 0; j < 3; j++) {
newv[j] = Create_Vertex(++THEM->MaxPointNum, s->V[j]->Pos.X, s->V[j]->Pos.Y,
s->V[j]->Pos.Z, s->V[j]->lc, s->V[j]->u);
ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1],
newv[j]->Pos.X, newv[j]->Pos.Y, newv[j]->Pos.Z);
if(Vertex_Bound && (vexist = (Vertex **) Tree_PQuery(Vertex_Bound, &newv[j]))) {
Free_Vertex(&newv[j], 0);
newv[j] = *vexist;
}
else {
if(Point_Bound && (vexist = (Vertex **) Tree_PQuery(Point_Bound, &newv[j]))) {
// keep the new one: we cannot have points and vertices
// pointing to the same memory location
newv[j]->Num = (*vexist)->Num;
}
Tree_Add(THEM->Vertices, &newv[j]);
Tree_Insert(Vertex_Bound, &newv[j]);
}
}
Simplex *news = Create_Simplex(newv[0], newv[1], newv[2], NULL);
news->iEnt = to->Num;
Tree_Add(to->Simplexes, &news);
}
List_Delete(list);
// quadrangles
list = Tree2List(from->Quadrangles);
for(int i = 0; i < List_Nbr(list); i++) {
List_Read(list, i, &q);
for(int j = 0; j < 4; j++) {
newv[j] = Create_Vertex(++THEM->MaxPointNum, q->V[j]->Pos.X, q->V[j]->Pos.Y,
q->V[j]->Pos.Z, q->V[j]->lc, q->V[j]->u);
ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1],
newv[j]->Pos.X, newv[j]->Pos.Y, newv[j]->Pos.Z);
if(Vertex_Bound && (vexist = (Vertex **) Tree_PQuery(Vertex_Bound, &newv[j]))) {
Free_Vertex(&newv[j], 0);
newv[j] = *vexist;
}
else {
if(Point_Bound && (vexist = (Vertex **) Tree_PQuery(Point_Bound, &newv[j]))) {
// keep the new one: we cannot have points and vertices
// pointing to the same memory location
newv[j]->Num = (*vexist)->Num;
}
Tree_Add(THEM->Vertices, &newv[j]);
Tree_Insert(Vertex_Bound, &newv[j]);
}
}
Quadrangle *newq = Create_Quadrangle(newv[0], newv[1], newv[2], newv[3]);
newq->iEnt = to->Num;
Tree_Add(to->Quadrangles, &newq);
}
List_Delete(list);
}
void AddSimVertsInSurf(void *a, void *b)
{
Simplex *s = *(Simplex **) a;
for(int i = 0; i < 3; i++)
if(s->V[i])
Tree_Insert(THES->Vertices, &s->V[i]);
}
void AddQuadVertsInSurf(void *a, void *b)
{
Quadrangle *q = *(Quadrangle **) a;
for(int i = 0; i < 4; i++)
Tree_Insert(THES->Vertices, &q->V[i]);
}
int Extrude_Mesh(Surface * s)
{
int i;
Vertex *v1;
Curve *c;
extern int FACE_DIMENSION;
if(!s->Extrude || !s->Extrude->mesh.ExtrudeMesh)
return false;
InitExtrude();
THES = s;
DIM = 2;
NUM = s->Num;
ep = s->Extrude;
FACE_DIMENSION = 2;
if(ep->geo.Mode == EXTRUDED_ENTITY) {
c = FindCurve(abs(ep->geo.Source), THEM);
if(!c)
return false;
for(i = 0; i < List_Nbr(c->Vertices); i++) {
List_Read(c->Vertices, i, &v1);
Extrude_Vertex(&v1, NULL);
}
Extrude_Curve(&c, NULL);
}
else {
Surface *ss = FindSurface(ep->geo.Source, THEM);
if(!ss)
return false;
copy_mesh(ss, s);
}
Tree_Action(s->Simplexes, AddSimVertsInSurf);
Tree_Action(s->SimplexesBase, AddSimVertsInSurf);
Tree_Action(s->Quadrangles, AddQuadVertsInSurf);
ReOrientSurfaceMesh(s);
return true;
}
static Tree_T *tmp;
void Free_NegativeSimplex(void *a, void *b)
{
Simplex *s = *(Simplex **) a;
if(s) {
if(s->Num >= 0) {
Tree_Add(tmp, &s);
}
else {
delete s;
s = NULL;
}
}
}
int Extrude_Mesh(Volume * v)
{
ep = v->Extrude;
if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY)
return true;
else
return false;
}
int Extrude_Mesh(Tree_T * Volumes)
{
int i, j, extrude = 0;
Surface *s;
List_T *list;
InitExtrude();
DIM = 3;
List_T *vol = Tree2List(Volumes);
for(int ivol = 0; ivol < List_Nbr(vol); ivol++) {
List_Read(vol, ivol, &THEV);
ep = THEV->Extrude;
if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY)
extrude = 1;
}
if(!extrude)
return false;
Msg(STATUS2, "Mesh 3D... (initial)");
for(int ivol = 0; ivol < List_Nbr(vol); ivol++) {
List_Read(vol, ivol, &THEV);
ep = THEV->Extrude;
NUM = THEV->Num;
if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY) {
s = FindSurface(ep->geo.Source, THEM);
if(s) {
Msg(STATUS3, "Meshing volume %d", NUM);
Extrude_Surface1(s);
}
}
}
j = 0;
do {
BAD_TETS = 0;
for(int ivol = 0; ivol < List_Nbr(vol); ivol++) {
List_Read(vol, ivol, &THEV);
ep = THEV->Extrude;
NUM = THEV->Num;
if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY &&
!ep->mesh.Recombine) {
s = FindSurface(ep->geo.Source, THEM);
if(s)
Extrude_Surface2(s);
}
}
Msg(STATUS3, "Swapping %d", BAD_TETS);
if(BAD_TETS == j && j != 0) {
Msg(GERROR, "Unable to swap all edges (output mesh will be incorrect): use 'Recombine'");
break;
}
j = BAD_TETS;
} while(BAD_TETS);
Msg(STATUS2, "Mesh 3D... (Final)");
for(int ivol = 0; ivol < List_Nbr(vol); ivol++) {
List_Read(vol, ivol, &THEV);
ep = THEV->Extrude;
NUM = THEV->Num;
if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY) {
s = FindSurface(ep->geo.Source, THEM);
if(s) {
Msg(STATUS3, "Meshing volume %d", NUM);
Extrude_Surface3(s);
}
}
}
list = List_Create(100, 100, sizeof(Surface *));
for(int ivol = 0; ivol < List_Nbr(vol); ivol++) {
List_Read(vol, ivol, &THEV);
ep = THEV->Extrude;
if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY &&
!ep->mesh.Recombine) {
for(i = 0; i < List_Nbr(THEV->Surfaces); i++) {
List_Read(THEV->Surfaces, i, &s);
if(!List_Search(list, &s, compareSurface))
List_Add(list, &s);
}
}
}
for(i = 0; i < List_Nbr(list); i++) {
List_Read(list, i, &s);
tmp = Tree_Create(sizeof(Simplex *), compareQuality);
Tree_Action(s->Simplexes, Free_NegativeSimplex);
Tree_Delete(s->Simplexes);
s->Simplexes = tmp;
Msg(STATUS3, "Coherence surface %d", s->Num);
Extrude_Mesh(s);
}
List_Delete(list);
List_Delete(vol);
return true;
}