mirror of
https://github.com/NGSolve/netgen.git
synced 2024-11-12 00:59:16 +05:00
1992 lines
46 KiB
C++
1992 lines
46 KiB
C++
#include <mystdlib.h>
|
|
#include "meshing.hpp"
|
|
|
|
namespace netgen
|
|
{
|
|
static void glrender (int wait);
|
|
|
|
|
|
// global variable for visualization
|
|
// static NgArray<Point3d> locpoints;
|
|
// static NgArray<int> legalpoints;
|
|
// static NgArray<Point2d> plainpoints;
|
|
// static NgArray<int> plainzones;
|
|
// static NgArray<INDEX_2> loclines;
|
|
// // static int geomtrig;
|
|
// //static const char * rname;
|
|
// static int cntelem, trials, nfaces;
|
|
// static int oldnl;
|
|
// static int qualclass;
|
|
|
|
|
|
static Array<unique_ptr<netrule>> global_trig_rules;
|
|
static Array<unique_ptr<netrule>> global_quad_rules;
|
|
|
|
|
|
Meshing2 :: Meshing2 (const MeshingParameters & mp, const Box<3> & aboundingbox)
|
|
: adfront(aboundingbox), boundingbox(aboundingbox)
|
|
{
|
|
static Timer t("Mesing2::Meshing2"); RegionTimer r(t);
|
|
|
|
auto & globalrules = mp.quad ? global_quad_rules : global_trig_rules;
|
|
if (!globalrules.Size())
|
|
{
|
|
LoadRules (NULL, mp.quad);
|
|
for (auto * rule : rules)
|
|
globalrules.Append (unique_ptr<netrule>(rule));
|
|
}
|
|
else
|
|
{
|
|
for (auto i : globalrules.Range())
|
|
rules.Append (globalrules[i].get());
|
|
}
|
|
// LoadRules ("rules/quad.rls");
|
|
// LoadRules ("rules/triangle.rls");
|
|
|
|
|
|
|
|
// adfront = new AdFront2(boundingbox);
|
|
starttime = GetTime();
|
|
|
|
maxarea = -1;
|
|
}
|
|
|
|
|
|
Meshing2 :: ~Meshing2 ()
|
|
{ ; }
|
|
|
|
void Meshing2 :: AddPoint (const Point3d & p, PointIndex globind,
|
|
MultiPointGeomInfo * mgi,
|
|
bool pointonsurface)
|
|
{
|
|
//(*testout) << "add point " << globind << endl;
|
|
adfront.AddPoint (p, globind, mgi, pointonsurface);
|
|
}
|
|
|
|
void Meshing2 :: AddBoundaryElement (int i1, int i2,
|
|
const PointGeomInfo & gi1, const PointGeomInfo & gi2)
|
|
{
|
|
// (*testout) << "add line " << i1 << " - " << i2 << endl;
|
|
if (!gi1.trignum || !gi2.trignum)
|
|
{
|
|
PrintSysError ("addboundaryelement: illegal geominfo");
|
|
}
|
|
adfront.AddLine (i1-1, i2-1, gi1, gi2);
|
|
}
|
|
|
|
|
|
|
|
void Meshing2 :: StartMesh ()
|
|
{
|
|
foundmap.SetSize (rules.Size());
|
|
canuse.SetSize (rules.Size());
|
|
ruleused.SetSize (rules.Size());
|
|
|
|
foundmap = 0;
|
|
canuse = 0;
|
|
ruleused = 0;
|
|
|
|
// cntelem = 0;
|
|
// trials = 0;
|
|
}
|
|
|
|
void Meshing2 :: EndMesh ()
|
|
{
|
|
for (int i = 0; i < ruleused.Size(); i++)
|
|
(*testout) << setw(4) << ruleused[i]
|
|
<< " times used rule " << rules[i] -> Name() << endl;
|
|
}
|
|
|
|
void Meshing2 :: SetStartTime (double astarttime)
|
|
{
|
|
starttime = astarttime;
|
|
}
|
|
|
|
|
|
void Meshing2 :: SetMaxArea (double amaxarea)
|
|
{
|
|
maxarea = amaxarea;
|
|
}
|
|
|
|
|
|
double Meshing2 :: CalcLocalH (const Point3d & /* p */, double gh) const
|
|
{
|
|
return gh;
|
|
}
|
|
|
|
// should be class variables !!(?)
|
|
// static Vec3d ex, ey;
|
|
// static Point3d globp1;
|
|
|
|
void Meshing2 :: DefineTransformation (const Point3d & p1, const Point3d & p2,
|
|
const PointGeomInfo * geominfo1,
|
|
const PointGeomInfo * geominfo2)
|
|
{
|
|
globp1 = p1;
|
|
ex = p2 - p1;
|
|
ex /= ex.Length();
|
|
ey.X() = -ex.Y();
|
|
ey.Y() = ex.X();
|
|
ey.Z() = 0;
|
|
}
|
|
|
|
void Meshing2 :: TransformToPlain (const Point3d & locpoint,
|
|
const MultiPointGeomInfo & geominf,
|
|
Point2d & plainpoint, double h, int & zone)
|
|
{
|
|
Vec3d p1p (globp1, locpoint);
|
|
|
|
// p1p = locpoint - globp1;
|
|
p1p /= h;
|
|
plainpoint.X() = p1p * ex;
|
|
plainpoint.Y() = p1p * ey;
|
|
zone = 0;
|
|
}
|
|
|
|
int Meshing2 :: TransformFromPlain (Point2d & plainpoint,
|
|
Point3d & locpoint,
|
|
PointGeomInfo & gi,
|
|
double h)
|
|
{
|
|
Vec3d p1p;
|
|
gi.trignum = 1;
|
|
|
|
p1p = plainpoint.X() * ex + plainpoint.Y() * ey;
|
|
p1p *= h;
|
|
locpoint = globp1 + p1p;
|
|
return 0;
|
|
}
|
|
|
|
|
|
int Meshing2 :: BelongsToActiveChart (const Point3d & p,
|
|
const PointGeomInfo & gi)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
|
|
int Meshing2 :: ComputePointGeomInfo (const Point3d & p, PointGeomInfo & gi)
|
|
{
|
|
gi.trignum = 1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
int Meshing2 :: ChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi,
|
|
PointGeomInfo & pgi)
|
|
{
|
|
pgi = mpgi.GetPGI(1);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int Meshing2 ::
|
|
IsLineVertexOnChart (const Point3d & p1, const Point3d & p2,
|
|
int endpoint, const PointGeomInfo & geominfo)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
void Meshing2 ::
|
|
GetChartBoundary (NgArray<Point2d> & points,
|
|
NgArray<Point3d> & points3d,
|
|
NgArray<INDEX_2> & lines, double h) const
|
|
{
|
|
points.SetSize (0);
|
|
points3d.SetSize (0);
|
|
lines.SetSize (0);
|
|
}
|
|
|
|
double Meshing2 :: Area () const
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MESHING2_RESULT Meshing2 :: GenerateMesh (Mesh & mesh, const MeshingParameters & mp, double gh, int facenr)
|
|
{
|
|
static Timer timer("surface meshing"); RegionTimer reg(timer);
|
|
|
|
static int timer1 = NgProfiler::CreateTimer ("surface meshing1");
|
|
static int timer2 = NgProfiler::CreateTimer ("surface meshing2");
|
|
static int timer3 = NgProfiler::CreateTimer ("surface meshing3");
|
|
|
|
static int ts1 = NgProfiler::CreateTimer ("surface meshing start 1");
|
|
static int ts2 = NgProfiler::CreateTimer ("surface meshing start 2");
|
|
static int ts3 = NgProfiler::CreateTimer ("surface meshing start 3");
|
|
|
|
|
|
NgProfiler::StartTimer (ts1);
|
|
|
|
NgArray<int> pindex, lindex;
|
|
NgArray<int> delpoints, dellines;
|
|
|
|
NgArray<PointGeomInfo> upgeominfo; // unique info
|
|
NgArray<MultiPointGeomInfo> mpgeominfo; // multiple info
|
|
|
|
NgArray<Element2d> locelements;
|
|
|
|
int z1, z2, oldnp(-1);
|
|
bool found;
|
|
int rulenr(-1);
|
|
|
|
const PointGeomInfo * blgeominfo1;
|
|
const PointGeomInfo * blgeominfo2;
|
|
|
|
bool morerisc;
|
|
bool debugflag;
|
|
|
|
// double h;
|
|
|
|
NgArray<Point3d> locpoints;
|
|
NgArray<int> legalpoints;
|
|
NgArray<Point2d> plainpoints;
|
|
NgArray<int> plainzones;
|
|
NgArray<INDEX_2> loclines;
|
|
int cntelem = 0, trials = 0, nfaces = 0;
|
|
int oldnl = 0;
|
|
int qualclass;
|
|
|
|
|
|
|
|
// test for 3d overlaps
|
|
BoxTree<3> surfeltree (boundingbox.PMin(),
|
|
boundingbox.PMax());
|
|
|
|
NgArray<int> intersecttrias;
|
|
NgArray<Point3d> critpoints;
|
|
|
|
// test for doubled edges
|
|
//INDEX_2_HASHTABLE<int> doubleedge(300000);
|
|
|
|
|
|
testmode = 0;
|
|
|
|
StartMesh();
|
|
|
|
NgArray<Point2d> chartboundpoints;
|
|
NgArray<Point3d> chartboundpoints3d;
|
|
NgArray<INDEX_2> chartboundlines;
|
|
|
|
// illegal points: points with more then 50 elements per node
|
|
int maxlegalpoint(-1), maxlegalline(-1);
|
|
NgArray<int,PointIndex::BASE> trigsonnode;
|
|
NgArray<int,PointIndex::BASE> illegalpoint;
|
|
|
|
trigsonnode.SetSize (mesh.GetNP());
|
|
illegalpoint.SetSize (mesh.GetNP());
|
|
|
|
trigsonnode = 0;
|
|
illegalpoint = 0;
|
|
|
|
double totalarea = Area ();
|
|
double meshedarea = 0;
|
|
|
|
|
|
// search tree for surface elements:
|
|
/*
|
|
for (sei = 0; sei < mesh.GetNSE(); sei++)
|
|
{
|
|
const Element2d & sel = mesh[sei];
|
|
|
|
if (sel.IsDeleted()) continue;
|
|
|
|
if (sel.GetIndex() == facenr)
|
|
{
|
|
Box<3> box;
|
|
box.Set ( mesh[sel[0]] );
|
|
box.Add ( mesh[sel[1]] );
|
|
box.Add ( mesh[sel[2]] );
|
|
surfeltree.Insert (box, sei);
|
|
}
|
|
}
|
|
*/
|
|
NgArray<SurfaceElementIndex> seia;
|
|
mesh.GetSurfaceElementsOfFace (facenr, seia);
|
|
for (int i = 0; i < seia.Size(); i++)
|
|
{
|
|
const Element2d & sel = mesh[seia[i]];
|
|
|
|
if (sel.IsDeleted()) continue;
|
|
|
|
Box<3> box;
|
|
box.Set ( mesh[sel[0]] );
|
|
box.Add ( mesh[sel[1]] );
|
|
box.Add ( mesh[sel[2]] );
|
|
surfeltree.Insert (box, seia[i]);
|
|
}
|
|
|
|
NgProfiler::StopTimer (ts1);
|
|
NgProfiler::StartTimer (ts2);
|
|
|
|
if (totalarea > 0 || maxarea > 0)
|
|
meshedarea = mesh.SurfaceArea();
|
|
/*
|
|
for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
|
|
{
|
|
const Element2d & sel = mesh[sei];
|
|
if (sel.IsDeleted()) continue;
|
|
|
|
double trigarea = Cross ( mesh[sel[1]]-mesh[sel[0]],
|
|
mesh[sel[2]]-mesh[sel[0]] ).Length() / 2;
|
|
|
|
|
|
if (sel.GetNP() == 4)
|
|
trigarea += Cross (Vec3d (mesh.Point (sel.PNum(1)),
|
|
mesh.Point (sel.PNum(3))),
|
|
Vec3d (mesh.Point (sel.PNum(1)),
|
|
mesh.Point (sel.PNum(4)))).Length() / 2;;
|
|
meshedarea += trigarea;
|
|
}
|
|
*/
|
|
// cout << "meshedarea = " << meshedarea << " =?= "
|
|
// << mesh.SurfaceArea() << endl;
|
|
|
|
NgProfiler::StopTimer (ts2);
|
|
NgProfiler::StartTimer (ts3);
|
|
|
|
const char * savetask = multithread.task;
|
|
multithread.task = "Surface meshing";
|
|
|
|
adfront.SetStartFront ();
|
|
|
|
|
|
int plotnexttrial = 999;
|
|
|
|
double meshedarea_before = meshedarea;
|
|
|
|
NgProfiler::StopTimer (ts3);
|
|
|
|
static Timer tloop("surfacemeshing mainloop");
|
|
// static Timer tgetlocals("surfacemeshing getlocals");
|
|
{
|
|
RegionTimer rloop(tloop);
|
|
while (!adfront.Empty() && !multithread.terminate)
|
|
{
|
|
NgProfiler::RegionTimer reg1 (timer1);
|
|
|
|
if (multithread.terminate)
|
|
throw NgException ("Meshing stopped");
|
|
|
|
// known for STL meshing
|
|
if (totalarea > 0)
|
|
multithread.percent = 100 * meshedarea / totalarea;
|
|
/*
|
|
else
|
|
multithread.percent = 0;
|
|
*/
|
|
|
|
locpoints.SetSize0();
|
|
loclines.SetSize0();
|
|
pindex.SetSize0();
|
|
lindex.SetSize0();
|
|
delpoints.SetSize0();
|
|
dellines.SetSize0();
|
|
locelements.SetSize0();
|
|
|
|
|
|
|
|
// plot statistics
|
|
if (trials > plotnexttrial)
|
|
{
|
|
PrintMessage (5,
|
|
"faces = ", nfaces,
|
|
" trials = ", trials,
|
|
" elements = ", mesh.GetNSE(),
|
|
" els/sec = ",
|
|
(mesh.GetNSE() / (GetTime() - starttime + 0.0001)));
|
|
plotnexttrial += 1000;
|
|
}
|
|
|
|
|
|
// unique-pgi, multi-pgi
|
|
upgeominfo.SetSize0();
|
|
mpgeominfo.SetSize0();
|
|
|
|
|
|
nfaces = adfront.GetNFL();
|
|
trials ++;
|
|
|
|
|
|
if (trials % 1000 == 0)
|
|
{
|
|
(*testout) << "\n";
|
|
for (int i = 1; i <= canuse.Size(); i++)
|
|
{
|
|
(*testout) << foundmap.Get(i) << "/"
|
|
<< canuse.Get(i) << "/"
|
|
<< ruleused.Get(i) << " map/can/use rule " << rules.Get(i)->Name() << "\n";
|
|
}
|
|
(*testout) << "\n";
|
|
}
|
|
|
|
Point<3> p1, p2;
|
|
int baselineindex = adfront.SelectBaseLine (p1, p2, blgeominfo1, blgeominfo2, qualclass);
|
|
|
|
found = 1;
|
|
|
|
double his = Dist (p1, p2);
|
|
|
|
Point<3> pmid = Center (p1, p2);
|
|
double hshould = CalcLocalH (pmid, mesh.GetH (pmid));
|
|
if (gh < hshould) hshould = gh;
|
|
|
|
mesh.RestrictLocalH (pmid, hshould);
|
|
|
|
double h = hshould;
|
|
|
|
double hinner = (3 + qualclass) * max2 (his, hshould);
|
|
|
|
// tgetlocals.Start();
|
|
adfront.GetLocals (baselineindex, locpoints, mpgeominfo, loclines,
|
|
pindex, lindex, 2*hinner);
|
|
// tgetlocals.Stop();
|
|
|
|
NgProfiler::RegionTimer reg2 (timer2);
|
|
|
|
//(*testout) << "h for locals: " << 2*hinner << endl;
|
|
|
|
|
|
//(*testout) << "locpoints " << locpoints << endl;
|
|
|
|
if (qualclass > mp.giveuptol2d)
|
|
{
|
|
PrintMessage (3, "give up with qualclass ", qualclass);
|
|
PrintMessage (3, "number of frontlines = ", adfront.GetNFL());
|
|
// throw NgException ("Give up 2d meshing");
|
|
break;
|
|
}
|
|
|
|
/*
|
|
if (found && qualclass > 60)
|
|
{
|
|
found = 0;
|
|
}
|
|
*/
|
|
// morerisc = ((qualclass > 20) && (qualclass % 2 == 1));
|
|
// morerisc = 1;
|
|
morerisc = 0;
|
|
|
|
|
|
PointIndex gpi1 = adfront.GetGlobalIndex (pindex.Get(loclines[0].I1()));
|
|
PointIndex gpi2 = adfront.GetGlobalIndex (pindex.Get(loclines[0].I2()));
|
|
|
|
|
|
debugflag =
|
|
(
|
|
debugparam.haltsegment &&
|
|
( ((debugparam.haltsegmentp1 == gpi1) && (debugparam.haltsegmentp2 == gpi2)) ||
|
|
((debugparam.haltsegmentp1 == gpi2) && (debugparam.haltsegmentp2 == gpi1)))
|
|
)
|
|
||
|
|
(
|
|
debugparam.haltnode &&
|
|
( (debugparam.haltsegmentp1 == gpi1) || (debugparam.haltsegmentp2 == gpi1))
|
|
);
|
|
|
|
|
|
if (debugparam.haltface && debugparam.haltfacenr == facenr)
|
|
{
|
|
debugflag = 1;
|
|
cout << "set debugflag" << endl;
|
|
}
|
|
|
|
if (debugparam.haltlargequalclass && qualclass > 50)
|
|
debugflag = 1;
|
|
|
|
// problem recognition !
|
|
if (found &&
|
|
(gpi1 < illegalpoint.Size()+PointIndex::BASE) &&
|
|
(gpi2 < illegalpoint.Size()+PointIndex::BASE) )
|
|
{
|
|
if (illegalpoint[gpi1] || illegalpoint[gpi2])
|
|
found = 0;
|
|
}
|
|
|
|
|
|
Point2d p12d, p22d;
|
|
|
|
if (found)
|
|
{
|
|
oldnp = locpoints.Size();
|
|
oldnl = loclines.Size();
|
|
|
|
if (debugflag)
|
|
(*testout) << "define new transformation" << endl;
|
|
|
|
DefineTransformation (p1, p2, blgeominfo1, blgeominfo2);
|
|
|
|
plainpoints.SetSize (locpoints.Size());
|
|
plainzones.SetSize (locpoints.Size());
|
|
|
|
// (*testout) << endl;
|
|
|
|
if (debugflag)
|
|
{
|
|
*testout << "3d->2d transformation" << endl;
|
|
*testout << "3d points: " << endl << locpoints << endl;
|
|
}
|
|
|
|
|
|
for (size_t i = 0; i < locpoints.Size(); i++)
|
|
TransformToPlain (locpoints[i], mpgeominfo[i],
|
|
plainpoints[i], h, plainzones[i]);
|
|
|
|
/*
|
|
for (int i = 1; i <= locpoints.Size(); i++)
|
|
{
|
|
// (*testout) << "pindex(i) = " << pindex[i-1] << endl;
|
|
TransformToPlain (locpoints.Get(i),
|
|
mpgeominfo.Get(i),
|
|
plainpoints.Elem(i), h, plainzones.Elem(i));
|
|
// (*testout) << mpgeominfo.Get(i).GetPGI(1).u << " " << mpgeominfo.Get(i).GetPGI(1).v << " ";
|
|
// (*testout) << plainpoints.Get(i).X() << " " << plainpoints.Get(i).Y() << endl;
|
|
//(*testout) << "transform " << locpoints.Get(i) << " to " << plainpoints.Get(i).X() << " " << plainpoints.Get(i).Y() << endl;
|
|
}
|
|
*/
|
|
// (*testout) << endl << endl << endl;
|
|
|
|
|
|
if (debugflag)
|
|
*testout << "2d points: " << endl << plainpoints << endl;
|
|
|
|
|
|
p12d = plainpoints.Get(1);
|
|
p22d = plainpoints.Get(2);
|
|
|
|
/*
|
|
// last idea on friday
|
|
plainzones.Elem(1) = 0;
|
|
plainzones.Elem(2) = 0;
|
|
*/
|
|
|
|
|
|
/*
|
|
// old netgen:
|
|
for (i = 2; i <= loclines.Size(); i++) // don't remove first line
|
|
{
|
|
z1 = plainzones.Get(loclines.Get(i).I1());
|
|
z2 = plainzones.Get(loclines.Get(i).I2());
|
|
|
|
if (z1 && z2 && (z1 != z2) || (z1 == -1) || (z2 == -1) )
|
|
{
|
|
loclines.DeleteElement(i);
|
|
lindex.DeleteElement(i);
|
|
oldnl--;
|
|
i--;
|
|
}
|
|
}
|
|
|
|
// for (i = 1; i <= plainpoints.Size(); i++)
|
|
// if (plainzones.Elem(i) == -1)
|
|
// plainpoints.Elem(i) = Point2d (1e4, 1e4);
|
|
*/
|
|
|
|
|
|
|
|
for (int i = 2; i <= loclines.Size(); i++) // don't remove first line
|
|
{
|
|
// (*testout) << "loclines(i) = " << loclines.Get(i).I1() << " - " << loclines.Get(i).I2() << endl;
|
|
z1 = plainzones.Get(loclines.Get(i).I1());
|
|
z2 = plainzones.Get(loclines.Get(i).I2());
|
|
|
|
|
|
// one inner point, one outer
|
|
if ( (z1 >= 0) != (z2 >= 0))
|
|
{
|
|
int innerp = (z1 >= 0) ? 1 : 2;
|
|
if (IsLineVertexOnChart (locpoints.Get(loclines.Get(i).I1()),
|
|
locpoints.Get(loclines.Get(i).I2()),
|
|
innerp,
|
|
adfront.GetLineGeomInfo (lindex.Get(i), innerp)))
|
|
// pgeominfo.Get(loclines.Get(i).I(innerp))))
|
|
{
|
|
|
|
if (!morerisc)
|
|
{
|
|
// use one end of line
|
|
int pini, pouti;
|
|
Vec2d v;
|
|
|
|
pini = loclines.Get(i).I(innerp);
|
|
pouti = loclines.Get(i).I(3-innerp);
|
|
|
|
Point2d pin (plainpoints.Get(pini));
|
|
Point2d pout (plainpoints.Get(pouti));
|
|
v = pout - pin;
|
|
double len = v.Length();
|
|
if (len <= 1e-6)
|
|
(*testout) << "WARNING(js): inner-outer: short vector" << endl;
|
|
else
|
|
v /= len;
|
|
|
|
/*
|
|
// don't elongate line towards base-line !!
|
|
if (Vec2d (pin, p12d) * v > 0 &&
|
|
Vec2d (pin, p22d) * v > 0)
|
|
v *= -1;
|
|
*/
|
|
|
|
Point2d newpout = pin + 1000 * v;
|
|
newpout = pout;
|
|
|
|
|
|
plainpoints.Append (newpout);
|
|
Point3d pout3d = locpoints.Get(pouti);
|
|
locpoints.Append (pout3d);
|
|
|
|
plainzones.Append (0);
|
|
pindex.Append (-1);
|
|
oldnp++;
|
|
loclines.Elem(i).I(3-innerp) = oldnp;
|
|
}
|
|
else
|
|
plainzones.Elem(loclines.Get(i).I(3-innerp)) = 0;
|
|
|
|
|
|
// (*testout) << "inner - outer correction" << endl;
|
|
}
|
|
else
|
|
{
|
|
// remove line
|
|
loclines.DeleteElement(i);
|
|
lindex.DeleteElement(i);
|
|
oldnl--;
|
|
i--;
|
|
}
|
|
}
|
|
|
|
else if ( (z1 > 0 && z2 > 0 && (z1 != z2)) || ((z1 < 0) && (z2 < 0)) )
|
|
{
|
|
loclines.DeleteElement(i);
|
|
lindex.DeleteElement(i);
|
|
oldnl--;
|
|
i--;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
legalpoints.SetSize(plainpoints.Size());
|
|
legalpoints = 1;
|
|
/*
|
|
for (int i = 1; i <= legalpoints.Size(); i++)
|
|
legalpoints.Elem(i) = 1;
|
|
*/
|
|
|
|
double avy = 0;
|
|
for (size_t i = 0; i < plainpoints.Size(); i++)
|
|
avy += plainpoints[i].Y();
|
|
avy *= 1./plainpoints.Size();
|
|
|
|
|
|
for (auto i : Range(plainpoints))
|
|
{
|
|
if (plainzones[i] < 0)
|
|
{
|
|
plainpoints[i] = Point2d (1e4, 1e4);
|
|
legalpoints[i] = 0;
|
|
}
|
|
if (pindex[i] == -1)
|
|
{
|
|
legalpoints[i] = 0;
|
|
}
|
|
|
|
|
|
if (plainpoints[i].Y() < -1e-10*avy) // changed
|
|
{
|
|
legalpoints[i] = 0;
|
|
}
|
|
}
|
|
/*
|
|
for (i = 3; i <= plainpoints.Size(); i++)
|
|
if (sqr (plainpoints.Get(i).X()) + sqr (plainpoints.Get(i).Y())
|
|
> sqr (2 + 0.2 * qualclass))
|
|
legalpoints.Elem(i) = 0;
|
|
*/
|
|
|
|
/*
|
|
int clp = 0;
|
|
for (i = 1; i <= plainpoints.Size(); i++)
|
|
if (legalpoints.Get(i))
|
|
clp++;
|
|
(*testout) << "legalpts: " << clp << "/" << plainpoints.Size() << endl;
|
|
|
|
// sort legal/illegal lines
|
|
int lastleg = 2;
|
|
int firstilleg = oldnl;
|
|
|
|
while (lastleg < firstilleg)
|
|
{
|
|
while (legalpoints.Get(loclines.Get(lastleg).I1()) &&
|
|
legalpoints.Get(loclines.Get(lastleg).I2()) &&
|
|
lastleg < firstilleg)
|
|
lastleg++;
|
|
while ( ( !legalpoints.Get(loclines.Get(firstilleg).I1()) ||
|
|
!legalpoints.Get(loclines.Get(firstilleg).I2())) &&
|
|
lastleg < firstilleg)
|
|
firstilleg--;
|
|
|
|
if (lastleg < firstilleg)
|
|
{
|
|
swap (loclines.Elem(lastleg), loclines.Elem(firstilleg));
|
|
swap (lindex.Elem(lastleg), lindex.Elem(firstilleg));
|
|
}
|
|
}
|
|
|
|
(*testout) << "leglines " << lastleg << "/" << oldnl << endl;
|
|
*/
|
|
|
|
|
|
GetChartBoundary (chartboundpoints,
|
|
chartboundpoints3d,
|
|
chartboundlines, h);
|
|
|
|
oldnp = plainpoints.Size();
|
|
|
|
maxlegalpoint = locpoints.Size();
|
|
maxlegalline = loclines.Size();
|
|
|
|
|
|
|
|
if (mp.checkchartboundary)
|
|
{
|
|
for (int i = 1; i <= chartboundpoints.Size(); i++)
|
|
{
|
|
plainpoints.Append (chartboundpoints.Get(i));
|
|
locpoints.Append (chartboundpoints3d.Get(i));
|
|
legalpoints.Append (0);
|
|
}
|
|
|
|
|
|
for (int i = 1; i <= chartboundlines.Size(); i++)
|
|
{
|
|
INDEX_2 line (chartboundlines.Get(i).I1()+oldnp,
|
|
chartboundlines.Get(i).I2()+oldnp);
|
|
loclines.Append (line);
|
|
// (*testout) << "line: " << line.I1() << "-" << line.I2() << endl;
|
|
}
|
|
}
|
|
|
|
oldnl = loclines.Size();
|
|
oldnp = plainpoints.Size();
|
|
}
|
|
|
|
|
|
/*
|
|
if (qualclass > 100)
|
|
{
|
|
multithread.drawing = 1;
|
|
glrender(1);
|
|
cout << "qualclass 100, nfl = " << adfront.GetNFL() << endl;
|
|
}
|
|
*/
|
|
|
|
if (found)
|
|
{
|
|
// static Timer t("ApplyRules");
|
|
// RegionTimer r(t);
|
|
rulenr = ApplyRules (plainpoints, legalpoints, maxlegalpoint,
|
|
loclines, maxlegalline, locelements,
|
|
dellines, qualclass, mp);
|
|
|
|
// (*testout) << "Rule Nr = " << rulenr << endl;
|
|
if (!rulenr)
|
|
{
|
|
found = 0;
|
|
if ( debugflag || debugparam.haltnosuccess )
|
|
PrintWarning ("no rule found");
|
|
}
|
|
}
|
|
|
|
NgProfiler::RegionTimer reg3 (timer3);
|
|
|
|
|
|
for (int i = 1; i <= locelements.Size() && found; i++)
|
|
{
|
|
const Element2d & el = locelements.Get(i);
|
|
|
|
for (int j = 1; j <= el.GetNP(); j++)
|
|
if (el.PNum(j) <= oldnp && pindex.Get(el.PNum(j)) == -1)
|
|
{
|
|
found = 0;
|
|
PrintSysError ("meshing2, index missing");
|
|
}
|
|
}
|
|
|
|
|
|
if (found)
|
|
{
|
|
locpoints.SetSize (plainpoints.Size());
|
|
upgeominfo.SetSize(locpoints.Size());
|
|
|
|
for (int i = oldnp+1; i <= plainpoints.Size(); i++)
|
|
{
|
|
int err =
|
|
TransformFromPlain (plainpoints.Elem(i), locpoints.Elem(i),
|
|
upgeominfo.Elem(i), h);
|
|
|
|
if (err)
|
|
{
|
|
found = 0;
|
|
|
|
if ( debugflag || debugparam.haltnosuccess )
|
|
PrintSysError ("meshing2, Backtransformation failed");
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// for (i = 1; i <= oldnl; i++)
|
|
// adfront.ResetClass (lindex[i]);
|
|
|
|
|
|
/*
|
|
double violateminh;
|
|
if (qualclass <= 10)
|
|
violateminh = 3;
|
|
else
|
|
violateminh = 3 * qualclass;
|
|
|
|
if (uselocalh && found) // && qualclass <= 10)
|
|
{
|
|
for (i = 1; i <= locelements.Size(); i++)
|
|
{
|
|
Point3d pmin = locpoints.Get(locelements.Get(i).PNum(1));
|
|
Point3d pmax = pmin;
|
|
for (j = 2; j <= 3; j++)
|
|
{
|
|
const Point3d & hp =
|
|
locpoints.Get(locelements.Get(i).PNum(j));
|
|
pmin.SetToMin (hp);
|
|
pmax.SetToMax (hp);
|
|
}
|
|
double minh = mesh.GetMinH (pmin, pmax);
|
|
if (h > violateminh * minh)
|
|
{
|
|
found = 0;
|
|
loclines.SetSize (oldnl);
|
|
locpoints.SetSize (oldnp);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
if (found)
|
|
{
|
|
double violateminh = 3 + 0.1 * sqr (qualclass);
|
|
double minh = 1e8;
|
|
double newedgemaxh = 0;
|
|
for (int i = oldnl+1; i <= loclines.Size(); i++)
|
|
{
|
|
double eh = Dist (locpoints.Get(loclines.Get(i).I1()),
|
|
locpoints.Get(loclines.Get(i).I2()));
|
|
|
|
// Markus (brute force method to avoid bad elements on geometries like \_/ )
|
|
//if(eh > 4.*mesh.GetH(locpoints.Get(loclines.Get(i).I1()))) found = 0;
|
|
//if(eh > 4.*mesh.GetH(locpoints.Get(loclines.Get(i).I2()))) found = 0;
|
|
// Markus end
|
|
|
|
if (eh > newedgemaxh)
|
|
newedgemaxh = eh;
|
|
}
|
|
|
|
for (int i = 1; i <= locelements.Size(); i++)
|
|
{
|
|
Point3d pmin = locpoints.Get(locelements.Get(i).PNum(1));
|
|
Point3d pmax = pmin;
|
|
for (int j = 2; j <= locelements.Get(i).GetNP(); j++)
|
|
{
|
|
const Point3d & hp =
|
|
locpoints.Get(locelements.Get(i).PNum(j));
|
|
pmin.SetToMin (hp);
|
|
pmax.SetToMax (hp);
|
|
}
|
|
double eh = mesh.GetMinH (pmin, pmax);
|
|
if (eh < minh)
|
|
minh = eh;
|
|
}
|
|
|
|
for (int i = 1; i <= locelements.Size(); i++)
|
|
for (int j = 1; j <= locelements.Get(i).GetNP(); j++)
|
|
if (Dist2 (locpoints.Get(locelements.Get(i).PNum(j)), pmid) > hinner*hinner)
|
|
found = 0;
|
|
|
|
// cout << "violate = " << newedgemaxh / minh << endl;
|
|
static double maxviolate = 0;
|
|
if (newedgemaxh / minh > maxviolate)
|
|
{
|
|
maxviolate = newedgemaxh / minh;
|
|
// cout << "max minhviolate = " << maxviolate << endl;
|
|
}
|
|
|
|
|
|
if (newedgemaxh > violateminh * minh)
|
|
{
|
|
found = 0;
|
|
loclines.SetSize (oldnl);
|
|
locpoints.SetSize (oldnp);
|
|
|
|
if ( debugflag || debugparam.haltnosuccess )
|
|
PrintSysError ("meshing2, maxh too large");
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
// test good ComputeLineGeoInfo
|
|
if (found)
|
|
{
|
|
// is line on chart ?
|
|
for (i = oldnl+1; i <= loclines.Size(); i++)
|
|
{
|
|
int gisize;
|
|
void *geominfo;
|
|
|
|
if (ComputeLineGeoInfo (locpoints.Get(loclines.Get(i).I1()),
|
|
locpoints.Get(loclines.Get(i).I2()),
|
|
gisize, geominfo))
|
|
found = 0;
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
// changed for OCC meshing
|
|
if (found)
|
|
{
|
|
// take geominfo from dellines
|
|
// upgeominfo.SetSize(locpoints.Size());
|
|
|
|
/*
|
|
for (i = 1; i <= dellines.Size(); i++)
|
|
for (j = 1; j <= 2; j++)
|
|
{
|
|
upgeominfo.Elem(loclines.Get(dellines.Get(i)).I(j)) =
|
|
adfront.GetLineGeomInfo (lindex.Get(dellines.Get(i)), j);
|
|
}
|
|
*/
|
|
|
|
|
|
for (int i = 1; i <= locelements.Size(); i++)
|
|
for (int j = 1; j <= locelements.Get(i).GetNP(); j++)
|
|
{
|
|
int pi = locelements.Get(i).PNum(j);
|
|
if (pi <= oldnp)
|
|
{
|
|
|
|
if (ChooseChartPointGeomInfo (mpgeominfo.Get(pi), upgeominfo.Elem(pi)))
|
|
{
|
|
// cannot select, compute new one
|
|
PrintWarning ("calc point geominfo instead of using");
|
|
if (ComputePointGeomInfo (locpoints.Get(pi), upgeominfo.Elem(pi)))
|
|
{
|
|
found = 0;
|
|
PrintSysError ("meshing2d, geominfo failed");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
// use upgeominfo from ProjectFromPlane
|
|
for (i = oldnp+1; i <= locpoints.Size(); i++)
|
|
{
|
|
if (ComputePointGeomInfo (locpoints.Get(i), upgeominfo.Elem(i)))
|
|
{
|
|
found = 0;
|
|
if ( debugflag || debugparam.haltnosuccess )
|
|
PrintSysError ("meshing2d, compute geominfo failed");
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
if (found && mp.checkoverlap)
|
|
{
|
|
// cout << "checkoverlap" << endl;
|
|
// test for overlaps
|
|
|
|
Point3d hullmin(1e10, 1e10, 1e10);
|
|
Point3d hullmax(-1e10, -1e10, -1e10);
|
|
|
|
for (int i = 1; i <= locelements.Size(); i++)
|
|
for (int j = 1; j <= locelements.Get(i).GetNP(); j++)
|
|
{
|
|
const Point3d & p = locpoints.Get(locelements.Get(i).PNum(j));
|
|
hullmin.SetToMin (p);
|
|
hullmax.SetToMax (p);
|
|
}
|
|
hullmin += Vec3d (-his, -his, -his);
|
|
hullmax += Vec3d ( his, his, his);
|
|
|
|
surfeltree.GetIntersecting (hullmin, hullmax, intersecttrias);
|
|
|
|
critpoints.SetSize (0);
|
|
for (int i = oldnp+1; i <= locpoints.Size(); i++)
|
|
critpoints.Append (locpoints.Get(i));
|
|
|
|
for (int i = 1; i <= locelements.Size(); i++)
|
|
{
|
|
const Element2d & tri = locelements.Get(i);
|
|
if (tri.GetNP() == 3)
|
|
{
|
|
const Point3d & tp1 = locpoints.Get(tri.PNum(1));
|
|
const Point3d & tp2 = locpoints.Get(tri.PNum(2));
|
|
const Point3d & tp3 = locpoints.Get(tri.PNum(3));
|
|
|
|
Vec3d tv1 (tp1, tp2);
|
|
Vec3d tv2 (tp1, tp3);
|
|
|
|
double lam1, lam2;
|
|
for (lam1 = 0.2; lam1 <= 0.8; lam1 += 0.2)
|
|
for (lam2 = 0.2; lam2 + lam1 <= 0.8; lam2 += 0.2)
|
|
{
|
|
Point3d hp = tp1 + lam1 * tv1 + lam2 * tv2;
|
|
critpoints.Append (hp);
|
|
}
|
|
}
|
|
else if (tri.GetNP() == 4)
|
|
{
|
|
const Point3d & tp1 = locpoints.Get(tri.PNum(1));
|
|
const Point3d & tp2 = locpoints.Get(tri.PNum(2));
|
|
const Point3d & tp3 = locpoints.Get(tri.PNum(3));
|
|
const Point3d & tp4 = locpoints.Get(tri.PNum(4));
|
|
|
|
double l1, l2;
|
|
for (l1 = 0.1; l1 <= 0.9; l1 += 0.1)
|
|
for (l2 = 0.1; l2 <= 0.9; l2 += 0.1)
|
|
{
|
|
Point3d hp;
|
|
hp.X() =
|
|
(1-l1)*(1-l2) * tp1.X() +
|
|
l1*(1-l2) * tp2.X() +
|
|
l1*l2 * tp3.X() +
|
|
(1-l1)*l2 * tp4.X();
|
|
hp.Y() =
|
|
(1-l1)*(1-l2) * tp1.Y() +
|
|
l1*(1-l2) * tp2.Y() +
|
|
l1*l2 * tp3.Y() +
|
|
(1-l1)*l2 * tp4.Y();
|
|
hp.Z() =
|
|
(1-l1)*(1-l2) * tp1.Z() +
|
|
l1*(1-l2) * tp2.Z() +
|
|
l1*l2 * tp3.Z() +
|
|
(1-l1)*l2 * tp4.Z();
|
|
|
|
|
|
critpoints.Append (hp);
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
for (i = oldnl+1; i <= loclines.Size(); i++)
|
|
{
|
|
Point3d hp = locpoints.Get(loclines.Get(i).I1());
|
|
Vec3d hv(hp, locpoints.Get(loclines.Get(i).I2()));
|
|
int ncp = 2;
|
|
for (j = 1; j <= ncp; j++)
|
|
critpoints.Append ( hp + (double(j)/(ncp+1)) * hv);
|
|
}
|
|
*/
|
|
|
|
|
|
/*
|
|
for (i = oldnp+1; i <= locpoints.Size(); i++)
|
|
{
|
|
const Point3d & p = locpoints.Get(i);
|
|
*/
|
|
|
|
|
|
for (int i = 1; i <= critpoints.Size(); i++)
|
|
{
|
|
const Point3d & p = critpoints.Get(i);
|
|
|
|
for (int jj = 0; jj < intersecttrias.Size(); jj++)
|
|
{
|
|
// int j = intersecttrias.Get(jj);
|
|
// const Element2d & el = mesh.SurfaceElement(j);
|
|
|
|
SurfaceElementIndex j = intersecttrias[jj];
|
|
const Element2d & el = mesh[j];
|
|
|
|
int ntrig = (el.GetNP() == 3) ? 1 : 2;
|
|
|
|
int jl;
|
|
for (jl = 1; jl <= ntrig; jl++)
|
|
{
|
|
Point3d tp1, tp2, tp3;
|
|
|
|
if (jl == 1)
|
|
{
|
|
tp1 = mesh.Point(el.PNum(1));
|
|
tp2 = mesh.Point(el.PNum(2));
|
|
tp3 = mesh.Point(el.PNum(3));
|
|
}
|
|
else
|
|
{
|
|
tp1 = mesh.Point(el.PNum(1));
|
|
tp2 = mesh.Point(el.PNum(3));
|
|
tp3 = mesh.Point(el.PNum(4));
|
|
}
|
|
|
|
int onchart = 0;
|
|
for (int k = 1; k <= el.GetNP(); k++)
|
|
if (BelongsToActiveChart (mesh.Point(el.PNum(k)),
|
|
el.GeomInfoPi(k)))
|
|
onchart = 1;
|
|
if (!onchart)
|
|
continue;
|
|
|
|
Vec3d e1(tp1, tp2);
|
|
Vec3d e2(tp1, tp3);
|
|
Vec3d n = Cross (e1, e2);
|
|
n /= n.Length();
|
|
double lam1, lam2, lam3;
|
|
lam3 = n * Vec3d (tp1, p);
|
|
LocalCoordinates (e1, e2, Vec3d (tp1, p), lam1, lam2);
|
|
|
|
if (fabs (lam3) < 0.1 * hshould &&
|
|
lam1 > 0 && lam2 > 0 && (lam1 + lam2) < 1)
|
|
{
|
|
#ifdef DEVELOP
|
|
cout << "overlap" << endl;
|
|
(*testout) << "overlap:" << endl
|
|
<< "tri = " << tp1 << "-" << tp2 << "-" << tp3 << endl
|
|
<< "point = " << p << endl
|
|
<< "lam1, 2 = " << lam1 << ", " << lam2 << endl
|
|
<< "lam3 = " << lam3 << endl;
|
|
|
|
// cout << "overlap !!!" << endl;
|
|
#endif
|
|
for (int k = 1; k <= 5; k++)
|
|
adfront.IncrementClass (lindex.Get(1));
|
|
|
|
found = 0;
|
|
|
|
if ( debugflag || debugparam.haltnosuccess )
|
|
PrintWarning ("overlapping");
|
|
|
|
|
|
if (debugparam.haltoverlap)
|
|
{
|
|
debugflag = 1;
|
|
}
|
|
|
|
/*
|
|
multithread.drawing = 1;
|
|
glrender(1);
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (found)
|
|
{
|
|
// check, whether new front line already exists
|
|
|
|
for (int i = oldnl+1; i <= loclines.Size(); i++)
|
|
{
|
|
int nlgpi1 = loclines.Get(i).I1();
|
|
int nlgpi2 = loclines.Get(i).I2();
|
|
if (nlgpi1 <= pindex.Size() && nlgpi2 <= pindex.Size())
|
|
{
|
|
nlgpi1 = adfront.GetGlobalIndex (pindex.Get(nlgpi1));
|
|
nlgpi2 = adfront.GetGlobalIndex (pindex.Get(nlgpi2));
|
|
|
|
int exval = adfront.ExistsLine (nlgpi1, nlgpi2);
|
|
if (exval)
|
|
{
|
|
cout << "ERROR: new line exits, val = " << exval << endl;
|
|
(*testout) << "ERROR: new line exits, val = " << exval << endl;
|
|
found = 0;
|
|
|
|
|
|
if (debugparam.haltexistingline)
|
|
debugflag = 1;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
if (found)
|
|
{
|
|
// check, whether new triangles insert edges twice
|
|
for (i = 1; i <= locelements.Size(); i++)
|
|
for (j = 1; j <= 3; j++)
|
|
{
|
|
int tpi1 = locelements.Get(i).PNumMod (j);
|
|
int tpi2 = locelements.Get(i).PNumMod (j+1);
|
|
if (tpi1 <= pindex.Size() && tpi2 <= pindex.Size())
|
|
{
|
|
tpi1 = adfront.GetGlobalIndex (pindex.Get(tpi1));
|
|
tpi2 = adfront.GetGlobalIndex (pindex.Get(tpi2));
|
|
|
|
if (doubleedge.Used (INDEX_2(tpi1, tpi2)))
|
|
{
|
|
if (debugparam.haltexistingline)
|
|
debugflag = 1;
|
|
cerr << "ERROR Insert edge "
|
|
<< tpi1 << " - " << tpi2 << " twice !!!" << endl;
|
|
found = 0;
|
|
}
|
|
doubleedge.Set (INDEX_2(tpi1, tpi2), 1);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
if (found)
|
|
{
|
|
// everything is ok, perform mesh update
|
|
|
|
ruleused.Elem(rulenr)++;
|
|
|
|
|
|
pindex.SetSize(locpoints.Size());
|
|
|
|
for (int i = oldnp+1; i <= locpoints.Size(); i++)
|
|
{
|
|
PointIndex globind = mesh.AddPoint (locpoints.Get(i));
|
|
pindex.Elem(i) = adfront.AddPoint (locpoints.Get(i), globind);
|
|
}
|
|
|
|
for (int i = oldnl+1; i <= loclines.Size(); i++)
|
|
{
|
|
/*
|
|
for (j = 1; j <= locpoints.Size(); j++)
|
|
{
|
|
(*testout) << j << ": " << locpoints.Get(j) << endl;
|
|
}
|
|
*/
|
|
|
|
/*
|
|
ComputeLineGeoInfo (locpoints.Get(loclines.Get(i).I1()),
|
|
locpoints.Get(loclines.Get(i).I2()),
|
|
gisize, geominfo);
|
|
*/
|
|
|
|
if (pindex.Get(loclines.Get(i).I1()) == -1 ||
|
|
pindex.Get(loclines.Get(i).I2()) == -1)
|
|
{
|
|
(*testout) << "pindex is 0" << endl;
|
|
}
|
|
|
|
if (!upgeominfo.Get(loclines.Get(i).I1()).trignum ||
|
|
!upgeominfo.Get(loclines.Get(i).I2()).trignum)
|
|
{
|
|
cout << "new el: illegal geominfo" << endl;
|
|
}
|
|
|
|
adfront.AddLine (pindex.Get(loclines.Get(i).I1()),
|
|
pindex.Get(loclines.Get(i).I2()),
|
|
upgeominfo.Get(loclines.Get(i).I1()),
|
|
upgeominfo.Get(loclines.Get(i).I2()));
|
|
}
|
|
for (int i = 1; i <= locelements.Size(); i++)
|
|
{
|
|
Element2d mtri(locelements.Get(i).GetNP());
|
|
mtri = locelements.Get(i);
|
|
mtri.SetIndex (facenr);
|
|
|
|
|
|
// compute triangle geominfo:
|
|
// (*testout) << "triggeominfo: ";
|
|
for (int j = 1; j <= locelements.Get(i).GetNP(); j++)
|
|
{
|
|
mtri.GeomInfoPi(j) = upgeominfo.Get(locelements.Get(i).PNum(j));
|
|
// (*testout) << mtri.GeomInfoPi(j).trignum << " ";
|
|
}
|
|
// (*testout) << endl;
|
|
|
|
for (int j = 1; j <= locelements.Get(i).GetNP(); j++)
|
|
{
|
|
mtri.PNum(j) =
|
|
locelements.Elem(i).PNum(j) =
|
|
adfront.GetGlobalIndex (pindex.Get(locelements.Get(i).PNum(j)));
|
|
}
|
|
|
|
|
|
|
|
|
|
mesh.AddSurfaceElement (mtri);
|
|
cntelem++;
|
|
// cout << "elements: " << cntelem << endl;
|
|
|
|
|
|
|
|
Box<3> box;
|
|
box.Set (mesh[mtri[0]]);
|
|
box.Add (mesh[mtri[1]]);
|
|
box.Add (mesh[mtri[2]]);
|
|
surfeltree.Insert (box, mesh.GetNSE()-1);
|
|
|
|
const Point3d & sep1 = mesh.Point (mtri.PNum(1));
|
|
const Point3d & sep2 = mesh.Point (mtri.PNum(2));
|
|
const Point3d & sep3 = mesh.Point (mtri.PNum(3));
|
|
|
|
double trigarea = Cross (Vec3d (sep1, sep2),
|
|
Vec3d (sep1, sep3)).Length() / 2;
|
|
|
|
if (mtri.GetNP() == 4)
|
|
{
|
|
const Point3d & sep4 = mesh.Point (mtri.PNum(4));
|
|
trigarea += Cross (Vec3d (sep1, sep3),
|
|
Vec3d (sep1, sep4)).Length() / 2;
|
|
}
|
|
|
|
meshedarea += trigarea;
|
|
|
|
if(maxarea > 0 && meshedarea-meshedarea_before > maxarea)
|
|
{
|
|
cerr << "meshed area = " << meshedarea-meshedarea_before << endl
|
|
<< "maximal area = " << maxarea << endl
|
|
<< "GIVING UP" << endl;
|
|
return MESHING2_GIVEUP;
|
|
}
|
|
|
|
|
|
|
|
for (int j = 1; j <= locelements.Get(i).GetNP(); j++)
|
|
{
|
|
int gpi = locelements.Get(i).PNum(j);
|
|
|
|
int oldts = trigsonnode.Size();
|
|
if (gpi >= oldts+PointIndex::BASE)
|
|
{
|
|
trigsonnode.SetSize (gpi+1-PointIndex::BASE);
|
|
illegalpoint.SetSize (gpi+1-PointIndex::BASE);
|
|
for (int k = oldts+PointIndex::BASE;
|
|
k <= gpi; k++)
|
|
{
|
|
trigsonnode[k] = 0;
|
|
illegalpoint[k] = 0;
|
|
}
|
|
}
|
|
|
|
trigsonnode[gpi]++;
|
|
|
|
if (trigsonnode[gpi] > 20)
|
|
{
|
|
illegalpoint[gpi] = 1;
|
|
// cout << "illegal point: " << gpi << endl;
|
|
(*testout) << "illegal point: " << gpi << endl;
|
|
}
|
|
|
|
static int mtonnode = 0;
|
|
if (trigsonnode[gpi] > mtonnode)
|
|
mtonnode = trigsonnode[gpi];
|
|
}
|
|
// cout << "els = " << cntelem << " trials = " << trials << endl;
|
|
// if (trials > 100) return;
|
|
}
|
|
|
|
for (int i = 1; i <= dellines.Size(); i++)
|
|
adfront.DeleteLine (lindex.Get(dellines.Get(i)));
|
|
|
|
// rname = rules.Get(rulenr)->Name();
|
|
#ifdef MYGRAPH
|
|
if (silentflag<3)
|
|
{
|
|
plotsurf.DrawPnL(locpoints, loclines);
|
|
plotsurf.Plot(testmode, testmode);
|
|
}
|
|
#endif
|
|
|
|
if (morerisc)
|
|
{
|
|
cout << "generated due to morerisc" << endl;
|
|
// multithread.drawing = 1;
|
|
// glrender(1);
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( debugparam.haltsuccess || debugflag )
|
|
{
|
|
// adfront.PrintOpenSegments (*testout);
|
|
cout << "success of rule" << rules.Get(rulenr)->Name() << endl;
|
|
multithread.drawing = 1;
|
|
multithread.testmode = 1;
|
|
multithread.pause = 1;
|
|
|
|
|
|
/*
|
|
extern STLGeometry * stlgeometry;
|
|
stlgeometry->ClearMarkedSegs();
|
|
for (i = 1; i <= loclines.Size(); i++)
|
|
{
|
|
stlgeometry->AddMarkedSeg(locpoints.Get(loclines.Get(i).I1()),
|
|
locpoints.Get(loclines.Get(i).I2()));
|
|
}
|
|
*/
|
|
|
|
(*testout) << "success of rule" << rules.Get(rulenr)->Name() << endl;
|
|
(*testout) << "trials = " << trials << endl;
|
|
|
|
(*testout) << "locpoints " << endl;
|
|
for (int i = 1; i <= pindex.Size(); i++)
|
|
(*testout) << adfront.GetGlobalIndex (pindex.Get(i)) << endl;
|
|
|
|
(*testout) << "old number of lines = " << oldnl << endl;
|
|
for (int i = 1; i <= loclines.Size(); i++)
|
|
{
|
|
(*testout) << "line ";
|
|
for (int j = 1; j <= 2; j++)
|
|
{
|
|
int hi = 0;
|
|
if (loclines.Get(i).I(j) >= 1 &&
|
|
loclines.Get(i).I(j) <= pindex.Size())
|
|
hi = adfront.GetGlobalIndex (pindex.Get(loclines.Get(i).I(j)));
|
|
|
|
(*testout) << hi << " ";
|
|
}
|
|
(*testout) << " : "
|
|
<< plainpoints.Get(loclines.Get(i).I1()) << " - "
|
|
<< plainpoints.Get(loclines.Get(i).I2()) << " 3d: "
|
|
<< locpoints.Get(loclines.Get(i).I1()) << " - "
|
|
<< locpoints.Get(loclines.Get(i).I2())
|
|
<< endl;
|
|
}
|
|
|
|
|
|
|
|
glrender(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
adfront.IncrementClass (lindex.Get(1));
|
|
|
|
if ( debugparam.haltnosuccess || debugflag )
|
|
{
|
|
cout << "Problem with seg " << gpi1 << " - " << gpi2
|
|
<< ", class = " << qualclass << endl;
|
|
|
|
(*testout) << "Problem with seg " << gpi1 << " - " << gpi2
|
|
<< ", class = " << qualclass << endl;
|
|
|
|
multithread.drawing = 1;
|
|
multithread.testmode = 1;
|
|
multithread.pause = 1;
|
|
|
|
|
|
/*
|
|
extern STLGeometry * stlgeometry;
|
|
stlgeometry->ClearMarkedSegs();
|
|
for (i = 1; i <= loclines.Size(); i++)
|
|
{
|
|
stlgeometry->AddMarkedSeg(locpoints.Get(loclines.Get(i).I1()),
|
|
locpoints.Get(loclines.Get(i).I2()));
|
|
}
|
|
*/
|
|
|
|
for (int i = 1; i <= loclines.Size(); i++)
|
|
{
|
|
(*testout) << "line ";
|
|
for (int j = 1; j <= 2; j++)
|
|
{
|
|
int hi = 0;
|
|
if (loclines.Get(i).I(j) >= 1 &&
|
|
loclines.Get(i).I(j) <= pindex.Size())
|
|
hi = adfront.GetGlobalIndex (pindex.Get(loclines.Get(i).I(j)));
|
|
|
|
(*testout) << hi << " ";
|
|
}
|
|
(*testout) << " : "
|
|
<< plainpoints.Get(loclines.Get(i).I1()) << " - "
|
|
<< plainpoints.Get(loclines.Get(i).I2()) << " 3d: "
|
|
<< locpoints.Get(loclines.Get(i).I1()) << " - "
|
|
<< locpoints.Get(loclines.Get(i).I2())
|
|
<< endl;
|
|
}
|
|
|
|
|
|
/*
|
|
cout << "p1gi = " << blgeominfo[0].trignum
|
|
<< ", p2gi = " << blgeominfo[1].trignum << endl;
|
|
*/
|
|
|
|
glrender(1);
|
|
}
|
|
|
|
|
|
#ifdef MYGRAPH
|
|
if (silentflag<3)
|
|
{
|
|
if (testmode || trials%2 == 0)
|
|
{
|
|
plotsurf.DrawPnL(locpoints, loclines);
|
|
plotsurf.Plot(testmode, testmode);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
}
|
|
}
|
|
PrintMessage (3, "Surface meshing done");
|
|
|
|
|
|
adfront.PrintOpenSegments (*testout);
|
|
|
|
multithread.task = savetask;
|
|
|
|
|
|
EndMesh ();
|
|
|
|
|
|
if (!adfront.Empty())
|
|
return MESHING2_GIVEUP;
|
|
|
|
return MESHING2_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// #define OPENGL
|
|
#ifdef OPENGLxx
|
|
|
|
/* *********************** Draw Surface Meshing **************** */
|
|
|
|
|
|
#include <visual.hpp>
|
|
#include <stlgeom.hpp>
|
|
|
|
namespace netgen
|
|
{
|
|
|
|
extern STLGeometry * stlgeometry;
|
|
extern Mesh * mesh;
|
|
VisualSceneSurfaceMeshing vssurfacemeshing;
|
|
|
|
|
|
|
|
void glrender (int wait)
|
|
{
|
|
// cout << "plot adfront" << endl;
|
|
|
|
if (multithread.drawing)
|
|
{
|
|
// vssurfacemeshing.Render();
|
|
Render ();
|
|
|
|
if (wait || multithread.testmode)
|
|
{
|
|
multithread.pause = 1;
|
|
}
|
|
while (multithread.pause);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VisualSceneSurfaceMeshing :: VisualSceneSurfaceMeshing ()
|
|
: VisualScene()
|
|
{
|
|
;
|
|
}
|
|
|
|
VisualSceneSurfaceMeshing :: ~VisualSceneSurfaceMeshing ()
|
|
{
|
|
;
|
|
}
|
|
|
|
void VisualSceneSurfaceMeshing :: DrawScene ()
|
|
{
|
|
int i, j, k;
|
|
|
|
if (loclines.Size() != changeval)
|
|
{
|
|
center = Point<3>(0,0,-5);
|
|
rad = 0.1;
|
|
|
|
CalcTransformationMatrices();
|
|
changeval = loclines.Size();
|
|
}
|
|
|
|
glClearColor(backcolor, backcolor, backcolor, 1.0);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
SetLight();
|
|
|
|
// glEnable (GL_COLOR_MATERIAL);
|
|
|
|
// glDisable (GL_SHADING);
|
|
// glColor3f (0.0f, 1.0f, 1.0f);
|
|
// glLineWidth (1.0f);
|
|
// glShadeModel (GL_SMOOTH);
|
|
|
|
// glCallList (linelists.Get(1));
|
|
|
|
// SetLight();
|
|
|
|
glPushMatrix();
|
|
glMultMatrixf (transformationmat);
|
|
|
|
glShadeModel (GL_SMOOTH);
|
|
// glDisable (GL_COLOR_MATERIAL);
|
|
glEnable (GL_COLOR_MATERIAL);
|
|
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
glEnable (GL_BLEND);
|
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
// glEnable (GL_LIGHTING);
|
|
|
|
double shine = vispar.shininess;
|
|
double transp = vispar.transp;
|
|
|
|
glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine);
|
|
glLogicOp (GL_COPY);
|
|
|
|
|
|
|
|
/*
|
|
|
|
float mat_col[] = { 0.2, 0.2, 0.8, 1 };
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);
|
|
|
|
glPolygonOffset (1, 1);
|
|
glEnable (GL_POLYGON_OFFSET_FILL);
|
|
|
|
float mat_colbl[] = { 0.8, 0.2, 0.2, 1 };
|
|
float mat_cololdl[] = { 0.2, 0.8, 0.2, 1 };
|
|
float mat_colnewl[] = { 0.8, 0.8, 0.2, 1 };
|
|
|
|
|
|
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
|
glPolygonOffset (1, -1);
|
|
glLineWidth (3);
|
|
|
|
for (i = 1; i <= loclines.Size(); i++)
|
|
{
|
|
if (i == 1)
|
|
{
|
|
glEnable (GL_POLYGON_OFFSET_FILL);
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbl);
|
|
}
|
|
else if (i <= oldnl)
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_cololdl);
|
|
else
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colnewl);
|
|
|
|
int pi1 = loclines.Get(i).I1();
|
|
int pi2 = loclines.Get(i).I2();
|
|
|
|
if (pi1 >= 1 && pi2 >= 1)
|
|
{
|
|
Point3d p1 = locpoints.Get(pi1);
|
|
Point3d p2 = locpoints.Get(pi2);
|
|
|
|
glBegin (GL_LINES);
|
|
glVertex3f (p1.X(), p1.Y(), p1.Z());
|
|
glVertex3f (p2.X(), p2.Y(), p2.Z());
|
|
glEnd();
|
|
}
|
|
|
|
glDisable (GL_POLYGON_OFFSET_FILL);
|
|
}
|
|
|
|
|
|
glLineWidth (1);
|
|
|
|
|
|
glPointSize (5);
|
|
float mat_colp[] = { 1, 0, 0, 1 };
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp);
|
|
glBegin (GL_POINTS);
|
|
for (i = 1; i <= locpoints.Size(); i++)
|
|
{
|
|
Point3d p = locpoints.Get(i);
|
|
glVertex3f (p.X(), p.Y(), p.Z());
|
|
}
|
|
glEnd();
|
|
|
|
|
|
glPopMatrix();
|
|
*/
|
|
|
|
float mat_colp[] = { 1, 0, 0, 1 };
|
|
|
|
float mat_col2d1[] = { 1, 0.5, 0.5, 1 };
|
|
float mat_col2d[] = { 1, 1, 1, 1 };
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d);
|
|
|
|
double scalex = 0.1, scaley = 0.1;
|
|
|
|
glBegin (GL_LINES);
|
|
for (i = 1; i <= loclines.Size(); i++)
|
|
{
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d);
|
|
if (i == 1)
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d1);
|
|
|
|
int pi1 = loclines.Get(i).I1();
|
|
int pi2 = loclines.Get(i).I2();
|
|
|
|
if (pi1 >= 1 && pi2 >= 1)
|
|
{
|
|
Point2d p1 = plainpoints.Get(pi1);
|
|
Point2d p2 = plainpoints.Get(pi2);
|
|
|
|
glBegin (GL_LINES);
|
|
glVertex3f (scalex * p1.X(), scaley * p1.Y(), -5);
|
|
glVertex3f (scalex * p2.X(), scaley * p2.Y(), -5);
|
|
glEnd();
|
|
}
|
|
}
|
|
glEnd ();
|
|
|
|
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp);
|
|
glBegin (GL_POINTS);
|
|
for (i = 1; i <= plainpoints.Size(); i++)
|
|
{
|
|
Point2d p = plainpoints.Get(i);
|
|
glVertex3f (scalex * p.X(), scaley * p.Y(), -5);
|
|
}
|
|
glEnd();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glDisable (GL_POLYGON_OFFSET_FILL);
|
|
|
|
glPopMatrix();
|
|
DrawCoordinateCross ();
|
|
DrawNetgenLogo ();
|
|
glFinish();
|
|
|
|
/*
|
|
glDisable (GL_POLYGON_OFFSET_FILL);
|
|
|
|
// cout << "draw surfacemeshing" << endl;
|
|
//
|
|
// if (changeval != stlgeometry->GetNT())
|
|
// BuildScene();
|
|
// changeval = stlgeometry->GetNT();
|
|
|
|
|
|
glClearColor(backcolor, backcolor, backcolor, 1.0);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
SetLight();
|
|
|
|
glPushMatrix();
|
|
glLoadMatrixf (transmat);
|
|
glMultMatrixf (rotmat);
|
|
|
|
glShadeModel (GL_SMOOTH);
|
|
glDisable (GL_COLOR_MATERIAL);
|
|
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
glEnable (GL_BLEND);
|
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
float mat_spec_col[] = { 1, 1, 1, 1 };
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_spec_col);
|
|
|
|
double shine = vispar.shininess;
|
|
double transp = vispar.transp;
|
|
|
|
glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine);
|
|
glLogicOp (GL_COPY);
|
|
|
|
|
|
float mat_col[] = { 0.2, 0.2, 0.8, transp };
|
|
float mat_colrt[] = { 0.2, 0.8, 0.8, transp };
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);
|
|
|
|
glPolygonOffset (1, 1);
|
|
glEnable (GL_POLYGON_OFFSET_FILL);
|
|
|
|
glColor3f (1.0f, 1.0f, 1.0f);
|
|
|
|
glEnable (GL_NORMALIZE);
|
|
|
|
// glBegin (GL_TRIANGLES);
|
|
// for (j = 1; j <= stlgeometry -> GetNT(); j++)
|
|
// {
|
|
// glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);
|
|
// if (j == geomtrig)
|
|
// glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colrt);
|
|
|
|
|
|
// const STLReadTriangle & tria = stlgeometry -> GetReadTriangle(j);
|
|
// glNormal3f (tria.normal.X(),
|
|
// tria.normal.Y(),
|
|
// tria.normal.Z());
|
|
|
|
// for (k = 0; k < 3; k++)
|
|
// {
|
|
// glVertex3f (tria.pts[k].X(),
|
|
// tria.pts[k].Y(),
|
|
// tria.pts[k].Z());
|
|
// }
|
|
// }
|
|
// glEnd ();
|
|
|
|
|
|
|
|
glDisable (GL_POLYGON_OFFSET_FILL);
|
|
|
|
float mat_colbl[] = { 0.8, 0.2, 0.2, 1 };
|
|
float mat_cololdl[] = { 0.2, 0.8, 0.2, 1 };
|
|
float mat_colnewl[] = { 0.8, 0.8, 0.2, 1 };
|
|
|
|
|
|
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
|
glPolygonOffset (1, -1);
|
|
glLineWidth (3);
|
|
|
|
for (i = 1; i <= loclines.Size(); i++)
|
|
{
|
|
if (i == 1)
|
|
{
|
|
glEnable (GL_POLYGON_OFFSET_FILL);
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbl);
|
|
}
|
|
else if (i <= oldnl)
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_cololdl);
|
|
else
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colnewl);
|
|
|
|
int pi1 = loclines.Get(i).I1();
|
|
int pi2 = loclines.Get(i).I2();
|
|
|
|
if (pi1 >= 1 && pi2 >= 1)
|
|
{
|
|
Point3d p1 = locpoints.Get(pi1);
|
|
Point3d p2 = locpoints.Get(pi2);
|
|
|
|
glBegin (GL_LINES);
|
|
glVertex3f (p1.X(), p1.Y(), p1.Z());
|
|
glVertex3f (p2.X(), p2.Y(), p2.Z());
|
|
glEnd();
|
|
}
|
|
|
|
glDisable (GL_POLYGON_OFFSET_FILL);
|
|
}
|
|
|
|
|
|
glLineWidth (1);
|
|
|
|
|
|
glPointSize (5);
|
|
float mat_colp[] = { 1, 0, 0, 1 };
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp);
|
|
glBegin (GL_POINTS);
|
|
for (i = 1; i <= locpoints.Size(); i++)
|
|
{
|
|
Point3d p = locpoints.Get(i);
|
|
glVertex3f (p.X(), p.Y(), p.Z());
|
|
}
|
|
glEnd();
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
|
|
float mat_col2d1[] = { 1, 0.5, 0.5, 1 };
|
|
float mat_col2d[] = { 1, 1, 1, 1 };
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d);
|
|
|
|
double scalex = 0.1, scaley = 0.1;
|
|
|
|
glBegin (GL_LINES);
|
|
for (i = 1; i <= loclines.Size(); i++)
|
|
{
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d);
|
|
if (i == 1)
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d1);
|
|
|
|
int pi1 = loclines.Get(i).I1();
|
|
int pi2 = loclines.Get(i).I2();
|
|
|
|
if (pi1 >= 1 && pi2 >= 1)
|
|
{
|
|
Point2d p1 = plainpoints.Get(pi1);
|
|
Point2d p2 = plainpoints.Get(pi2);
|
|
|
|
glBegin (GL_LINES);
|
|
glVertex3f (scalex * p1.X(), scaley * p1.Y(), -5);
|
|
glVertex3f (scalex * p2.X(), scaley * p2.Y(), -5);
|
|
glEnd();
|
|
}
|
|
}
|
|
glEnd ();
|
|
|
|
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp);
|
|
glBegin (GL_POINTS);
|
|
for (i = 1; i <= plainpoints.Size(); i++)
|
|
{
|
|
Point2d p = plainpoints.Get(i);
|
|
glVertex3f (scalex * p.X(), scaley * p.Y(), -5);
|
|
}
|
|
glEnd();
|
|
|
|
glFinish();
|
|
*/
|
|
}
|
|
|
|
|
|
void VisualSceneSurfaceMeshing :: BuildScene (int zoomall)
|
|
{
|
|
int i, j, k;
|
|
/*
|
|
center = stlgeometry -> GetBoundingBox().Center();
|
|
rad = stlgeometry -> GetBoundingBox().Diam() / 2;
|
|
|
|
CalcTransformationMatrices();
|
|
*/
|
|
}
|
|
|
|
}
|
|
|
|
|
|
#else
|
|
namespace netgen
|
|
{
|
|
void glrender (int wait)
|
|
{ ; }
|
|
}
|
|
#endif
|