mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-26 22:00:33 +05:00
1168 lines
28 KiB
C++
1168 lines
28 KiB
C++
#include <mystdlib.h>
|
|
#include <myadt.hpp>
|
|
|
|
#include <linalg.hpp>
|
|
#include <gprim.hpp>
|
|
|
|
#include <meshing.hpp>
|
|
|
|
|
|
#include "stlgeom.hpp"
|
|
|
|
|
|
namespace netgen
|
|
{
|
|
|
|
static void STLFindEdges (STLGeometry & geom,
|
|
class Mesh & mesh)
|
|
{
|
|
double h = mparam.maxh;
|
|
|
|
// mark edge points:
|
|
//int ngp = geom.GetNP();
|
|
|
|
geom.RestrictLocalH(mesh, h);
|
|
|
|
PushStatusF("Mesh Lines");
|
|
|
|
Array<STLLine*> meshlines;
|
|
Array<Point3d> meshpoints;
|
|
|
|
PrintMessage(3,"Mesh Lines");
|
|
|
|
/*
|
|
cout << geom.GetNLines() << " lines" << endl;
|
|
double totnp = 0;
|
|
for (int i = 1; i <= geom.GetNLines(); i++)
|
|
totnp += geom.GetLine(i)->NP();
|
|
cout << "avg np per line " << totnp/geom.GetNLines() << endl;
|
|
*/
|
|
|
|
for (int i = 1; i <= geom.GetNLines(); i++)
|
|
{
|
|
meshlines.Append(geom.GetLine(i)->Mesh(geom.GetPoints(), meshpoints, h, mesh));
|
|
SetThreadPercent(100.0 * (double)i/(double)geom.GetNLines());
|
|
}
|
|
|
|
geom.meshpoints.SetSize(0); //testing
|
|
geom.meshlines.SetSize(0); //testing
|
|
for (int i = 1; i <= meshpoints.Size(); i++)
|
|
{
|
|
geom.meshpoints.Append(meshpoints.Get(i)); //testing
|
|
mesh.AddPoint(meshpoints.Get(i));
|
|
}
|
|
//(++++++++++++++testing
|
|
for (int i = 1; i <= geom.GetNLines(); i++)
|
|
{
|
|
geom.meshlines.Append(meshlines.Get(i));
|
|
}
|
|
//++++++++++++++testing)
|
|
|
|
PrintMessage(7,"feed with edges");
|
|
|
|
for (int i = 1; i <= meshlines.Size(); i++)
|
|
{
|
|
STLLine* line = meshlines.Get(i);
|
|
(*testout) << "store line " << i << endl;
|
|
for (int j = 1; j <= line->GetNS(); j++)
|
|
{
|
|
int p1, p2;
|
|
|
|
line->GetSeg(j, p1, p2);
|
|
int trig1, trig2, trig1b, trig2b;
|
|
|
|
if (p1 == p2)
|
|
cout << "Add Segment, p1 == p2 == " << p1 << endl;
|
|
|
|
// Test auf geschlossener Rand mit 2 Segmenten
|
|
|
|
if ((j == 2) && (line->GetNS() == 2))
|
|
{
|
|
int oldp1, oldp2;
|
|
line->GetSeg (1, oldp1, oldp2);
|
|
if (oldp1 == p2 && oldp2 == p1)
|
|
{
|
|
PrintMessage(7,"MESSAGE: don't use second segment");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
//mesh point number
|
|
//p1 = geom2meshnum.Get(p1); // for unmeshed lines!!!
|
|
//p2 = geom2meshnum.Get(p2); // for unmeshed lines!!!
|
|
|
|
//left and right trigs
|
|
trig1 = line->GetLeftTrig(j);
|
|
trig2 = line->GetRightTrig(j);
|
|
trig1b = line->GetLeftTrig(j+1);
|
|
trig2b = line->GetRightTrig(j+1);
|
|
|
|
(*testout) << "j = " << j << ", p1 = " << p1 << ", p2 = " << p2 << endl;
|
|
(*testout) << "segm-trigs: "
|
|
<< "trig1 = " << trig1
|
|
<< ", trig1b = " << trig1b
|
|
<< ", trig2 = " << trig2
|
|
<< ", trig2b = " << trig2b << endl;
|
|
|
|
if (trig1 <= 0 || trig2 <= 0 || trig1b <= 0 || trig2b <= 0)
|
|
{
|
|
cout << "negative trigs, "
|
|
<< ", trig1 = " << trig1
|
|
<< ", trig1b = " << trig1b
|
|
<< ", trig2 = " << trig2
|
|
<< ", trig2b = " << trig2b << endl;
|
|
}
|
|
/*
|
|
(*testout) << " trigs p1: " << trig1 << " - " << trig2 << endl;
|
|
(*testout) << " trigs p2: " << trig1b << " - " << trig2b << endl;
|
|
(*testout) << " charts p1: " << geom.GetChartNr(trig1) << " - " << geom.GetChartNr(trig2) << endl;
|
|
(*testout) << " charts p2: " << geom.GetChartNr(trig1b) << " - " << geom.GetChartNr(trig2b) << endl;
|
|
*/
|
|
Point3d hp, hp2;
|
|
Segment seg;
|
|
seg[0] = p1 + PointIndex::BASE-1;
|
|
seg[1] = p2 + PointIndex::BASE-1;
|
|
seg.si = geom.GetTriangle(trig1).GetFaceNum();
|
|
seg.edgenr = i;
|
|
|
|
seg.epgeominfo[0].edgenr = i;
|
|
seg.epgeominfo[0].dist = line->GetDist(j);
|
|
seg.epgeominfo[1].edgenr = i;
|
|
seg.epgeominfo[1].dist = line->GetDist(j+1);
|
|
/*
|
|
(*testout) << "seg = "
|
|
<< "edgenr " << seg.epgeominfo[0].edgenr
|
|
<< " dist " << seg.epgeominfo[0].dist
|
|
<< " edgenr " << seg.epgeominfo[1].edgenr
|
|
<< " dist " << seg.epgeominfo[1].dist << endl;
|
|
*/
|
|
|
|
seg.geominfo[0].trignum = trig1;
|
|
seg.geominfo[1].trignum = trig1b;
|
|
|
|
/*
|
|
geom.SelectChartOfTriangle (trig1);
|
|
hp = hp2 = mesh.Point (seg[0]);
|
|
seg.geominfo[0].trignum = geom.Project (hp);
|
|
|
|
(*testout) << "hp = " << hp2 << ", hp proj = " << hp << ", trignum = " << seg.geominfo[0].trignum << endl;
|
|
if (Dist (hp, hp2) > 1e-5 || seg.geominfo[0].trignum == 0)
|
|
{
|
|
(*testout) << "PROBLEM" << endl;
|
|
}
|
|
|
|
geom.SelectChartOfTriangle (trig1b);
|
|
hp = hp2 = mesh.Point (seg[1]);
|
|
seg.geominfo[1].trignum = geom.Project (hp);
|
|
|
|
(*testout) << "hp = " << hp2 << ", hp proj = " << hp << ", trignum = " << seg.geominfo[1].trignum << endl;
|
|
if (Dist (hp, hp2) > 1e-5 || seg.geominfo[1].trignum == 0)
|
|
{
|
|
(*testout) << "PROBLEM" << endl;
|
|
}
|
|
*/
|
|
|
|
|
|
if (Dist (mesh.Point(seg[0]), mesh.Point(seg[1])) < 1e-10)
|
|
{
|
|
(*testout) << "ERROR: Line segment of length 0" << endl;
|
|
(*testout) << "pi1, 2 = " << seg[0] << ", " << seg[1] << endl;
|
|
(*testout) << "p1, 2 = " << mesh.Point(seg[0])
|
|
<< ", " << mesh.Point(seg[1]) << endl;
|
|
throw NgException ("Line segment of length 0");
|
|
}
|
|
|
|
mesh.AddSegment (seg);
|
|
|
|
|
|
Segment seg2;
|
|
seg2[0] = p2 + PointIndex::BASE-1;;
|
|
seg2[1] = p1 + PointIndex::BASE-1;;
|
|
seg2.si = geom.GetTriangle(trig2).GetFaceNum();
|
|
seg2.edgenr = i;
|
|
|
|
seg2.epgeominfo[0].edgenr = i;
|
|
seg2.epgeominfo[0].dist = line->GetDist(j+1);
|
|
seg2.epgeominfo[1].edgenr = i;
|
|
seg2.epgeominfo[1].dist = line->GetDist(j);
|
|
/*
|
|
(*testout) << "seg = "
|
|
<< "edgenr " << seg2.epgeominfo[0].edgenr
|
|
<< " dist " << seg2.epgeominfo[0].dist
|
|
<< " edgenr " << seg2.epgeominfo[1].edgenr
|
|
<< " dist " << seg2.epgeominfo[1].dist << endl;
|
|
*/
|
|
|
|
seg2.geominfo[0].trignum = trig2b;
|
|
seg2.geominfo[1].trignum = trig2;
|
|
|
|
/*
|
|
geom.SelectChartOfTriangle (trig2);
|
|
hp = hp2 = mesh.Point (seg[0]);
|
|
seg2.geominfo[0].trignum = geom.Project (hp);
|
|
|
|
(*testout) << "hp = " << hp2 << ", hp proj = " << hp << ", trignum = " << seg.geominfo[0].trignum << endl;
|
|
if (Dist (hp, hp2) > 1e-5 || seg2.geominfo[0].trignum == 0)
|
|
{
|
|
(*testout) << "Get GeomInfo PROBLEM" << endl;
|
|
}
|
|
|
|
|
|
geom.SelectChartOfTriangle (trig2b);
|
|
hp = hp2 = mesh.Point (seg[1]);
|
|
seg2.geominfo[1].trignum = geom.Project (hp);
|
|
(*testout) << "hp = " << hp2 << ", hp proj = " << hp << ", trignum = " << seg.geominfo[1].trignum << endl;
|
|
if (Dist (hp, hp2) > 1e-5 || seg2.geominfo[1].trignum == 0)
|
|
{
|
|
(*testout) << "Get GeomInfo PROBLEM" << endl;
|
|
}
|
|
*/
|
|
|
|
mesh.AddSegment (seg2);
|
|
}
|
|
}
|
|
|
|
PopStatus();
|
|
}
|
|
|
|
|
|
|
|
|
|
void STLSurfaceMeshing1 (STLGeometry & geom, class Mesh & mesh,
|
|
int retrynr);
|
|
|
|
|
|
int STLSurfaceMeshing (STLGeometry & geom, class Mesh & mesh)
|
|
{
|
|
PrintFnStart("Do Surface Meshing");
|
|
|
|
geom.PrepareSurfaceMeshing();
|
|
|
|
if (mesh.GetNSeg() == 0)
|
|
STLFindEdges (geom, mesh);
|
|
|
|
int nopen;
|
|
int outercnt = 20;
|
|
|
|
for (int i = 1; i <= mesh.GetNSeg(); i++)
|
|
{
|
|
const Segment & seg = mesh.LineSegment (i);
|
|
if (seg.geominfo[0].trignum <= 0 || seg.geominfo[1].trignum <= 0)
|
|
(*testout) << "Problem with segment " << i << ": " << seg << endl;
|
|
}
|
|
|
|
|
|
do
|
|
{
|
|
outercnt--;
|
|
if (outercnt <= 0)
|
|
return MESHING3_OUTERSTEPSEXCEEDED;
|
|
|
|
if (multithread.terminate) return MESHING3_TERMINATE;
|
|
|
|
mesh.FindOpenSegments();
|
|
nopen = mesh.GetNOpenSegments();
|
|
|
|
if (nopen)
|
|
{
|
|
int trialcnt = 0;
|
|
while (nopen && trialcnt <= 5)
|
|
{
|
|
if (multithread.terminate) { return MESHING3_TERMINATE; }
|
|
|
|
trialcnt++;
|
|
STLSurfaceMeshing1 (geom, mesh, trialcnt);
|
|
|
|
mesh.FindOpenSegments();
|
|
nopen = mesh.GetNOpenSegments();
|
|
|
|
if (nopen)
|
|
{
|
|
geom.ClearMarkedSegs();
|
|
for (int i = 1; i <= nopen; i++)
|
|
{
|
|
const Segment & seg = mesh.GetOpenSegment (i);
|
|
geom.AddMarkedSeg(mesh.Point(seg[0]),mesh.Point(seg[1]));
|
|
}
|
|
|
|
geom.InitMarkedTrigs();
|
|
for (int i = 1; i <= nopen; i++)
|
|
{
|
|
const Segment & seg = mesh.GetOpenSegment (i);
|
|
geom.SetMarkedTrig(seg.geominfo[0].trignum,1);
|
|
geom.SetMarkedTrig(seg.geominfo[1].trignum,1);
|
|
}
|
|
|
|
MeshOptimizeSTLSurface optmesh(geom);
|
|
optmesh.SetFaceIndex (0);
|
|
optmesh.SetImproveEdges (0);
|
|
optmesh.SetMetricWeight (0);
|
|
|
|
mesh.CalcSurfacesOfNode();
|
|
optmesh.EdgeSwapping (mesh, 0);
|
|
mesh.CalcSurfacesOfNode();
|
|
optmesh.ImproveMesh (mesh, mparam);
|
|
}
|
|
|
|
mesh.Compress();
|
|
mesh.FindOpenSegments();
|
|
nopen = mesh.GetNOpenSegments();
|
|
|
|
if (trialcnt <= 5 && nopen)
|
|
{
|
|
mesh.RemoveOneLayerSurfaceElements();
|
|
|
|
if (trialcnt >= 4)
|
|
{
|
|
mesh.FindOpenSegments();
|
|
mesh.RemoveOneLayerSurfaceElements();
|
|
|
|
mesh.FindOpenSegments ();
|
|
nopen = mesh.GetNOpenSegments();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (multithread.terminate)
|
|
return MESHING3_TERMINATE;
|
|
|
|
if (nopen)
|
|
{
|
|
|
|
PrintMessage(3,"Meshing failed, trying to refine");
|
|
|
|
mesh.FindOpenSegments ();
|
|
nopen = mesh.GetNOpenSegments();
|
|
|
|
mesh.FindOpenSegments ();
|
|
mesh.RemoveOneLayerSurfaceElements();
|
|
mesh.FindOpenSegments ();
|
|
mesh.RemoveOneLayerSurfaceElements();
|
|
|
|
// Open edge-segments will be refined !
|
|
INDEX_2_HASHTABLE<int> openseght (nopen+1);
|
|
for (int i = 1; i <= mesh.GetNOpenSegments(); i++)
|
|
{
|
|
const Segment & seg = mesh.GetOpenSegment (i);
|
|
INDEX_2 i2(seg[0], seg[1]);
|
|
i2.Sort();
|
|
openseght.Set (i2, 1);
|
|
}
|
|
|
|
|
|
mesh.FindOpenSegments ();
|
|
mesh.RemoveOneLayerSurfaceElements();
|
|
mesh.FindOpenSegments ();
|
|
mesh.RemoveOneLayerSurfaceElements();
|
|
|
|
|
|
INDEX_2_HASHTABLE<int> newpht(100);
|
|
|
|
int nsegold = mesh.GetNSeg();
|
|
for (int i = 1; i <= nsegold; i++)
|
|
{
|
|
Segment seg = mesh.LineSegment(i);
|
|
INDEX_2 i2(seg[0], seg[1]);
|
|
i2.Sort();
|
|
if (openseght.Used (i2))
|
|
{
|
|
// segment will be split
|
|
PrintMessage(7,"Split segment ", int(seg[0]), "-", int(seg[1]));
|
|
|
|
Segment nseg1, nseg2;
|
|
EdgePointGeomInfo newgi;
|
|
|
|
const EdgePointGeomInfo & gi1 = seg.epgeominfo[0];
|
|
const EdgePointGeomInfo & gi2 = seg.epgeominfo[1];
|
|
|
|
newgi.dist = 0.5 * (gi1.dist + gi2.dist);
|
|
newgi.edgenr = gi1.edgenr;
|
|
|
|
int hi;
|
|
|
|
Point3d newp;
|
|
int newpi;
|
|
|
|
if (!newpht.Used (i2))
|
|
{
|
|
newp = geom.GetLine (gi1.edgenr)->
|
|
GetPointInDist (geom.GetPoints(), newgi.dist, hi);
|
|
newpi = mesh.AddPoint (newp);
|
|
newpht.Set (i2, newpi);
|
|
}
|
|
else
|
|
{
|
|
newpi = newpht.Get (i2);
|
|
newp = mesh.Point (newpi);
|
|
}
|
|
|
|
nseg1 = seg;
|
|
nseg2 = seg;
|
|
nseg1[1] = newpi;
|
|
nseg1.epgeominfo[1] = newgi;
|
|
|
|
nseg2[0] = newpi;
|
|
nseg2.epgeominfo[0] = newgi;
|
|
|
|
mesh.LineSegment(i) = nseg1;
|
|
mesh.AddSegment (nseg2);
|
|
|
|
mesh.RestrictLocalH (Center (mesh.Point(nseg1[0]),
|
|
mesh.Point(nseg1[1])),
|
|
Dist (mesh.Point(nseg1[0]),
|
|
mesh.Point(nseg1[1])));
|
|
mesh.RestrictLocalH (Center (mesh.Point(nseg2[0]),
|
|
mesh.Point(nseg2[1])),
|
|
Dist (mesh.Point(nseg2[0]),
|
|
mesh.Point(nseg2[1])));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
nopen = -1;
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
PrintMessage(5,"mesh is closed, verifying ...");
|
|
|
|
// no open elements, check wrong elemetns (intersecting..)
|
|
|
|
|
|
|
|
PrintMessage(5,"check overlapping");
|
|
// mesh.FindOpenElements(); // would leed to locked points
|
|
if(mesh.CheckOverlappingBoundary())
|
|
return MESHING3_BADSURFACEMESH;
|
|
|
|
geom.InitMarkedTrigs();
|
|
|
|
for (int i = 1; i <= mesh.GetNSE(); i++)
|
|
if (mesh.SurfaceElement(i).BadElement())
|
|
{
|
|
int trig = mesh.SurfaceElement(i).PNum(1);
|
|
geom.SetMarkedTrig(trig,1);
|
|
PrintMessage(7, "overlapping element, will be removed");
|
|
}
|
|
|
|
|
|
|
|
Array<Point3d> refpts;
|
|
Array<double> refh;
|
|
|
|
// was commented:
|
|
|
|
for (int i = 1; i <= mesh.GetNSE(); i++)
|
|
if (mesh.SurfaceElement(i).BadElement())
|
|
{
|
|
for (int j = 1; j <= 3; j++)
|
|
{
|
|
refpts.Append (mesh.Point (mesh.SurfaceElement(i).PNum(j)));
|
|
refh.Append (mesh.GetH (refpts.Last()) / 2);
|
|
}
|
|
mesh.DeleteSurfaceElement(i);
|
|
}
|
|
|
|
// delete wrong oriented element
|
|
for (int i = 1; i <= mesh.GetNSE(); i++)
|
|
{
|
|
const Element2d & el = mesh.SurfaceElement(i);
|
|
if (!el.PNum(1))
|
|
continue;
|
|
|
|
Vec3d n = Cross (Vec3d (mesh.Point(el.PNum(1)),
|
|
mesh.Point(el.PNum(2))),
|
|
Vec3d (mesh.Point(el.PNum(1)),
|
|
mesh.Point(el.PNum(3))));
|
|
Vec3d ng = geom.GetTriangle(el.GeomInfoPi(1).trignum).Normal();
|
|
if (n * ng < 0)
|
|
{
|
|
refpts.Append (mesh.Point (mesh.SurfaceElement(i).PNum(1)));
|
|
refh.Append (mesh.GetH (refpts.Last()) / 2);
|
|
mesh.DeleteSurfaceElement(i);
|
|
}
|
|
}
|
|
// end comments
|
|
|
|
for (int i = 1; i <= refpts.Size(); i++)
|
|
mesh.RestrictLocalH (refpts.Get(i), refh.Get(i));
|
|
|
|
mesh.RemoveOneLayerSurfaceElements();
|
|
|
|
mesh.Compress();
|
|
|
|
mesh.FindOpenSegments ();
|
|
nopen = mesh.GetNOpenSegments();
|
|
|
|
/*
|
|
if (!nopen)
|
|
{
|
|
// mesh is still ok
|
|
|
|
void STLSurfaceOptimization (STLGeometry & geom,
|
|
class Mesh & mesh,
|
|
MeshingParameters & mparam)
|
|
|
|
}
|
|
*/
|
|
}
|
|
|
|
}
|
|
while (nopen);
|
|
|
|
mesh.Compress();
|
|
mesh.CalcSurfacesOfNode();
|
|
|
|
return MESHING3_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void STLSurfaceMeshing1 (STLGeometry & geom,
|
|
class Mesh & mesh,
|
|
int retrynr)
|
|
{
|
|
static int timer1 = NgProfiler::CreateTimer ("STL surface meshing1");
|
|
static int timer1a = NgProfiler::CreateTimer ("STL surface meshing1a");
|
|
static int timer1b = NgProfiler::CreateTimer ("STL surface meshing1b");
|
|
static int timer1c = NgProfiler::CreateTimer ("STL surface meshing1c");
|
|
static int timer1d = NgProfiler::CreateTimer ("STL surface meshing1d");
|
|
|
|
double h = mparam.maxh;
|
|
|
|
mesh.FindOpenSegments();
|
|
|
|
Array<int> spiralps(0);
|
|
spiralps.SetSize(0);
|
|
for (int i = 1; i <= geom.GetNP(); i++)
|
|
if (geom.GetSpiralPoint(i))
|
|
spiralps.Append(i);
|
|
|
|
PrintMessage(7,"NO spiralpoints = ", spiralps.Size());
|
|
//int spfound;
|
|
|
|
/*
|
|
Array<int> meshsp(mesh.GetNP());
|
|
meshsp = 0;
|
|
for (int i = 1; i <= mesh.GetNP(); i++)
|
|
for (int j = 1; j <= spiralps.Size(); j++)
|
|
if (Dist2(geom.GetPoint(spiralps.Get(j)), mesh.Point(i)) < 1e-20)
|
|
meshsp.Elem(i) = spiralps.Get(j);
|
|
Array<PointIndex> imeshsp;
|
|
for (int i = 1; i <= meshsp.Size(); i++)
|
|
if (meshsp.Elem(i)) imeshsp.Append(i);
|
|
*/
|
|
Array<PointIndex> imeshsp;
|
|
Array<int> ispiral_point;
|
|
for (int i = 1; i <= mesh.GetNP(); i++)
|
|
{
|
|
for (int j = 1; j <= spiralps.Size(); j++)
|
|
if (Dist2(geom.GetPoint(spiralps.Get(j)), mesh.Point(i)) < 1e-20)
|
|
{
|
|
imeshsp.Append(i);
|
|
ispiral_point.Append(spiralps.Get(j));
|
|
break;
|
|
}
|
|
}
|
|
|
|
double starttime = GetTime ();
|
|
mesh.SurfaceArea().ReCalc();
|
|
|
|
// int oldnp = mesh.GetNP();
|
|
|
|
Array<int,PointIndex::BASE> compress(mesh.GetNP());
|
|
compress = 0;
|
|
Array<PointIndex> icompress;
|
|
|
|
Array<int, 1> opensegsperface(mesh.GetNFD());
|
|
opensegsperface = 0;
|
|
for (int i = 1; i <= mesh.GetNOpenSegments(); i++)
|
|
opensegsperface[mesh.GetOpenSegment(i).si]++;
|
|
|
|
TABLE<int, 1> opensegments(mesh.GetNFD());
|
|
for (int i = 1; i <= mesh.GetNOpenSegments(); i++)
|
|
{
|
|
const Segment & seg = mesh.GetOpenSegment (i);
|
|
if (seg.si < 1 || seg.si > mesh.GetNFD())
|
|
cerr << "segment index " << seg.si << " out of range [1, " << mesh.GetNFD() << "]" << endl;
|
|
opensegments.Add (seg.si, i);
|
|
}
|
|
|
|
|
|
for (int fnr = 1; fnr <= mesh.GetNFD(); fnr++)
|
|
{
|
|
if (fnr == 100) NgProfiler::ClearTimers();
|
|
if (!opensegsperface[fnr]) continue;
|
|
if (multithread.terminate) return;
|
|
|
|
NgProfiler::StartTimer (timer1);
|
|
NgProfiler::StartTimer (timer1a);
|
|
|
|
|
|
PrintMessage(5,"Meshing surface ", fnr, "/", mesh.GetNFD());
|
|
MeshingSTLSurface meshing (geom, mparam);
|
|
meshing.SetStartTime (starttime);
|
|
|
|
// compress = 0;
|
|
icompress.SetSize(0);
|
|
int cntused = 0;
|
|
|
|
for (int i = 0; i < imeshsp.Size(); i++)
|
|
{
|
|
compress[imeshsp[i]] = ++cntused;
|
|
icompress.Append(imeshsp[i]);
|
|
}
|
|
|
|
NgProfiler::StopTimer (timer1a);
|
|
NgProfiler::StartTimer (timer1b);
|
|
|
|
|
|
|
|
/*
|
|
for (int i = 1; i <= mesh.GetNOpenSegments(); i++)
|
|
{
|
|
const Segment & seg = mesh.GetOpenSegment (i);
|
|
if (seg.si == fnr)
|
|
for (int j = 0; j < 2; j++)
|
|
if (compress[seg[j]] == 0)
|
|
{
|
|
compress[seg[j]] = ++cntused;
|
|
icompress.Append(seg[j]);
|
|
}
|
|
}
|
|
*/
|
|
FlatArray<int> segs = opensegments[fnr];
|
|
for (int hi = 0; hi < segs.Size(); hi++)
|
|
{
|
|
int i = segs[hi];
|
|
const Segment & seg = mesh.GetOpenSegment (i);
|
|
for (int j = 0; j < 2; j++)
|
|
if (compress[seg[j]] == 0)
|
|
{
|
|
compress[seg[j]] = ++cntused;
|
|
icompress.Append(seg[j]);
|
|
}
|
|
}
|
|
|
|
NgProfiler::StopTimer (timer1b);
|
|
NgProfiler::StartTimer (timer1c);
|
|
|
|
|
|
for (int hi = 0; hi < icompress.Size(); hi++)
|
|
{
|
|
PointIndex pi = icompress[hi];
|
|
|
|
/*
|
|
// int sppointnum = meshsp.Get(i);
|
|
int sppointnum = 0;
|
|
if (hi < ispiral_point.Size())
|
|
sppointnum = ispiral_point[hi];
|
|
|
|
if (sppointnum)
|
|
{
|
|
*/
|
|
if (hi < ispiral_point.Size())
|
|
{
|
|
int sppointnum = ispiral_point[hi];
|
|
|
|
MultiPointGeomInfo mgi;
|
|
|
|
int ntrigs = geom.NOTrigsPerPoint(sppointnum);
|
|
for (int j = 0; j < ntrigs; j++)
|
|
{
|
|
PointGeomInfo gi;
|
|
gi.trignum = geom.TrigPerPoint(sppointnum, j+1);
|
|
mgi.AddPointGeomInfo (gi);
|
|
}
|
|
|
|
// Einfuegen von ConePoint: Point bekommt alle
|
|
// Dreiecke (werden dann intern kopiert)
|
|
// Ein Segment zum ConePoint muss vorhanden sein !!!
|
|
|
|
// meshing.AddPoint (mesh.Point(i), i, &mgi);
|
|
meshing.AddPoint (mesh[pi], pi, &mgi);
|
|
}
|
|
else
|
|
meshing.AddPoint (mesh[pi], pi);
|
|
}
|
|
|
|
NgProfiler::StopTimer (timer1c);
|
|
NgProfiler::StartTimer (timer1d);
|
|
|
|
/*
|
|
for (int i = 1; i <= mesh.GetNOpenSegments(); i++)
|
|
{
|
|
const Segment & seg = mesh.GetOpenSegment (i);
|
|
if (seg.si == fnr)
|
|
meshing.AddBoundaryElement (compress[seg[0]], compress[seg[1]],
|
|
seg.geominfo[0], seg.geominfo[1]);
|
|
}
|
|
*/
|
|
|
|
|
|
// FlatArray<int> segs = opensegments[fnr];
|
|
for (int hi = 0; hi < segs.Size(); hi++)
|
|
{
|
|
int i = segs[hi];
|
|
const Segment & seg = mesh.GetOpenSegment (i);
|
|
meshing.AddBoundaryElement (compress[seg[0]], compress[seg[1]],
|
|
seg.geominfo[0], seg.geominfo[1]);
|
|
}
|
|
|
|
|
|
|
|
NgProfiler::StopTimer (timer1d);
|
|
|
|
NgProfiler::StopTimer (timer1);
|
|
|
|
PrintMessage(3,"start meshing, trialcnt = ", retrynr);
|
|
|
|
meshing.GenerateMesh (mesh, mparam, h, fnr);
|
|
|
|
for (int i = 0; i < icompress.Size(); i++)
|
|
compress[icompress[i]] = 0;
|
|
|
|
|
|
mparam.Render();
|
|
}
|
|
|
|
// NgProfiler::Print(stdout);
|
|
|
|
mesh.CalcSurfacesOfNode();
|
|
}
|
|
|
|
|
|
|
|
void STLSurfaceOptimization (STLGeometry & geom,
|
|
class Mesh & mesh,
|
|
MeshingParameters & meshparam)
|
|
{
|
|
PrintFnStart("optimize STL Surface");
|
|
|
|
MeshOptimizeSTLSurface optmesh(geom);
|
|
|
|
optmesh.SetFaceIndex (0);
|
|
optmesh.SetImproveEdges (0);
|
|
optmesh.SetMetricWeight (meshparam.elsizeweight);
|
|
|
|
PrintMessage(5,"optimize string = ", meshparam.optimize2d, " elsizew = ", meshparam.elsizeweight);
|
|
|
|
for (int i = 1; i <= meshparam.optsteps2d; i++)
|
|
for (size_t j = 1; j <= meshparam.optimize2d.length(); j++)
|
|
{
|
|
if (multithread.terminate)
|
|
break;
|
|
|
|
//(*testout) << "optimize, before, step = " << meshparam.optimize2d[j-1] << mesh.Point (3679) << endl;
|
|
|
|
mesh.CalcSurfacesOfNode();
|
|
switch (meshparam.optimize2d[j-1])
|
|
{
|
|
case 's':
|
|
{
|
|
optmesh.EdgeSwapping (mesh, 0);
|
|
break;
|
|
}
|
|
case 'S':
|
|
{
|
|
optmesh.EdgeSwapping (mesh, 1);
|
|
break;
|
|
}
|
|
case 'm':
|
|
{
|
|
optmesh.ImproveMesh(mesh, mparam);
|
|
break;
|
|
}
|
|
case 'c':
|
|
{
|
|
optmesh.CombineImprove (mesh);
|
|
break;
|
|
}
|
|
}
|
|
//(*testout) << "optimize, after, step = " << meshparam.optimize2d[j-1] << mesh.Point (3679) << endl;
|
|
}
|
|
|
|
geom.surfaceoptimized = 1;
|
|
|
|
mesh.Compress();
|
|
mesh.CalcSurfacesOfNode();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
MeshingSTLSurface :: MeshingSTLSurface (STLGeometry & ageom,
|
|
const MeshingParameters & mp)
|
|
: Meshing2(mp, ageom.GetBoundingBox()), geom(ageom)
|
|
{
|
|
;
|
|
}
|
|
|
|
void MeshingSTLSurface :: DefineTransformation (const Point3d & p1, const Point3d & p2,
|
|
const PointGeomInfo * geominfo,
|
|
const PointGeomInfo * geominfo2)
|
|
{
|
|
transformationtrig = geominfo[0].trignum;
|
|
|
|
geom.DefineTangentialPlane(p1, p2, transformationtrig);
|
|
}
|
|
|
|
void MeshingSTLSurface :: TransformToPlain (const Point3d & locpoint, const MultiPointGeomInfo & gi,
|
|
Point2d & plainpoint, double h, int & zone)
|
|
{
|
|
int trigs[10000];
|
|
|
|
if (gi.GetNPGI() >= 9999)
|
|
{
|
|
PrintError("In Transform to plane: increase size of trigs!!!");
|
|
}
|
|
|
|
for (int i = 1; i <= gi.GetNPGI(); i++)
|
|
trigs[i-1] = gi.GetPGI(i).trignum;
|
|
trigs[gi.GetNPGI()] = 0;
|
|
|
|
// int trig = gi.trignum;
|
|
// (*testout) << "locpoint = " << locpoint;
|
|
|
|
Point<2> hp2d;
|
|
geom.ToPlane (locpoint, trigs, hp2d, h, zone, 1);
|
|
plainpoint = hp2d;
|
|
|
|
// geom.ToPlane (locpoint, NULL, plainpoint, h, zone, 1);
|
|
/*
|
|
(*testout) << " plainpoint = " << plainpoint
|
|
<< " h = " << h
|
|
<< endl;
|
|
*/
|
|
}
|
|
|
|
/*
|
|
int MeshingSTLSurface :: ComputeLineGeoInfo (const Point3d & p1, const Point3d & p2,
|
|
int & geoinfosize, void *& geoinfo)
|
|
{
|
|
static int geomtrig[2] = { 0, 0 };
|
|
|
|
Point3d hp;
|
|
hp = p1;
|
|
geomtrig[0] = geom.Project (hp);
|
|
|
|
hp = p2;
|
|
geomtrig[1] = geom.Project (hp);
|
|
|
|
geoinfosize = sizeof (geomtrig);
|
|
geoinfo = &geomtrig;
|
|
|
|
if (geomtrig[0] == 0)
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
*/
|
|
|
|
|
|
int MeshingSTLSurface :: ComputePointGeomInfo (const Point3d & p, PointGeomInfo & gi)
|
|
{
|
|
// compute triangle of point,
|
|
// if non-unique: 0
|
|
|
|
Point<3> hp = p;
|
|
gi.trignum = geom.Project (hp);
|
|
|
|
if (!gi.trignum)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int MeshingSTLSurface ::
|
|
ChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi,
|
|
PointGeomInfo & pgi)
|
|
{
|
|
for (int i = 1; i <= mpgi.GetNPGI(); i++)
|
|
if (geom.TrigIsInOC (mpgi.GetPGI(i).trignum, geom.meshchart))
|
|
{
|
|
pgi = mpgi.GetPGI(i);
|
|
return 0;
|
|
}
|
|
/*
|
|
for (i = 0; i < mpgi.cnt; i++)
|
|
{
|
|
// (*testout) << "d" << endl;
|
|
if (geom.TrigIsInOC (mpgi.mgi[i].trignum, geom.meshchart))
|
|
{
|
|
pgi = mpgi.mgi[i];
|
|
return 0;
|
|
}
|
|
}
|
|
*/
|
|
PrintMessage(7,"INFORM: no gi on chart");
|
|
pgi.trignum = 1;
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
int MeshingSTLSurface ::
|
|
IsLineVertexOnChart (const Point3d & p1, const Point3d & p2,
|
|
int endpoint, const PointGeomInfo & gi)
|
|
{
|
|
int lineendtrig = gi.trignum;
|
|
return geom.TrigIsInOC (lineendtrig, geom.meshchart);
|
|
|
|
// Vec3d baselinenormal = geom.meshtrignv;
|
|
// Vec3d linenormal = geom.GetTriangleNormal (lineendtrig);
|
|
// return ( (baselinenormal * linenormal) > cos (30 * (M_PI/180)) );
|
|
}
|
|
|
|
void MeshingSTLSurface ::
|
|
GetChartBoundary (Array<Point2d > & points,
|
|
Array<Point3d > & points3d,
|
|
Array<INDEX_2> & lines, double h) const
|
|
{
|
|
points.SetSize (0);
|
|
points3d.SetSize (0);
|
|
lines.SetSize (0);
|
|
geom.GetMeshChartBoundary (points, points3d, lines, h);
|
|
}
|
|
|
|
|
|
|
|
|
|
int MeshingSTLSurface :: TransformFromPlain (Point2d & plainpoint,
|
|
Point3d & locpoint,
|
|
PointGeomInfo & gi,
|
|
double h)
|
|
{
|
|
//return 0, wenn alles OK
|
|
Point<3> hp3d;
|
|
int res = geom.FromPlane (plainpoint, hp3d, h);
|
|
locpoint = hp3d;
|
|
ComputePointGeomInfo (locpoint, gi);
|
|
return res;
|
|
}
|
|
|
|
|
|
int MeshingSTLSurface ::
|
|
BelongsToActiveChart (const Point3d & p,
|
|
const PointGeomInfo & gi)
|
|
{
|
|
return (geom.TrigIsInOC(gi.trignum, geom.meshchart) != 0);
|
|
}
|
|
|
|
|
|
|
|
double MeshingSTLSurface :: CalcLocalH (const Point3d & p, double gh) const
|
|
{
|
|
return gh;
|
|
}
|
|
|
|
double MeshingSTLSurface :: Area () const
|
|
{
|
|
return geom.Area();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MeshOptimizeSTLSurface :: MeshOptimizeSTLSurface (STLGeometry & ageom)
|
|
: MeshOptimize2d(), geom(ageom)
|
|
{
|
|
;
|
|
}
|
|
|
|
|
|
void MeshOptimizeSTLSurface :: SelectSurfaceOfPoint (const Point<3> & p,
|
|
const PointGeomInfo & gi)
|
|
{
|
|
// (*testout) << "sel char: " << gi.trignum << endl;
|
|
|
|
geom.SelectChartOfTriangle (gi.trignum);
|
|
// geom.SelectChartOfPoint (p);
|
|
}
|
|
|
|
|
|
void MeshOptimizeSTLSurface :: ProjectPoint (INDEX surfind, Point<3> & p) const
|
|
{
|
|
if (!geom.Project (p))
|
|
{
|
|
PrintMessage(7,"project failed");
|
|
|
|
if (!geom.ProjectOnWholeSurface(p))
|
|
{
|
|
PrintMessage(7, "project on whole surface failed");
|
|
}
|
|
}
|
|
|
|
// geometry.GetSurface(surfind)->Project (p);
|
|
}
|
|
|
|
void MeshOptimizeSTLSurface :: ProjectPoint2 (INDEX surfind, INDEX surfind2, Point<3> & p) const
|
|
{
|
|
/*
|
|
ProjectToEdge ( geometry.GetSurface(surfind),
|
|
geometry.GetSurface(surfind2), p);
|
|
*/
|
|
}
|
|
|
|
int MeshOptimizeSTLSurface :: CalcPointGeomInfo(PointGeomInfo& gi, const Point<3> & p3) const
|
|
{
|
|
Point<3> hp = p3;
|
|
gi.trignum = geom.Project (hp);
|
|
|
|
if (gi.trignum) return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void MeshOptimizeSTLSurface :: GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const
|
|
{
|
|
n = geom.GetChartNormalVector();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RefinementSTLGeometry :: RefinementSTLGeometry (const STLGeometry & ageom)
|
|
: Refinement(), geom(ageom)
|
|
{
|
|
;
|
|
}
|
|
|
|
RefinementSTLGeometry :: ~RefinementSTLGeometry ()
|
|
{
|
|
;
|
|
}
|
|
|
|
void RefinementSTLGeometry ::
|
|
PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint,
|
|
int surfi,
|
|
const PointGeomInfo & gi1,
|
|
const PointGeomInfo & gi2,
|
|
Point<3> & newp, PointGeomInfo & newgi) const
|
|
{
|
|
newp = p1+secpoint*(p2-p1);
|
|
|
|
/*
|
|
(*testout) << "surf-between: p1 = " << p1 << ", p2 = " << p2
|
|
<< ", gi = " << gi1 << " - " << gi2 << endl;
|
|
*/
|
|
|
|
if (gi1.trignum > 0)
|
|
{
|
|
// ((STLGeometry&)geom).SelectChartOfTriangle (gi1.trignum);
|
|
|
|
Point<3> np1 = newp;
|
|
Point<3> np2 = newp;
|
|
((STLGeometry&)geom).SelectChartOfTriangle (gi1.trignum);
|
|
int tn1 = geom.Project (np1);
|
|
|
|
((STLGeometry&)geom).SelectChartOfTriangle (gi2.trignum);
|
|
int tn2 = geom.Project (np2);
|
|
|
|
newgi.trignum = tn1; //urspruengliche version
|
|
newp = np1; //urspruengliche version
|
|
|
|
if (!newgi.trignum)
|
|
{ newgi.trignum = tn2; newp = np2; }
|
|
if (!newgi.trignum) newgi.trignum = gi1.trignum;
|
|
|
|
/*
|
|
if (tn1 != 0 && tn2 != 0 && ((STLGeometry&)geom).GetAngle(tn1,tn2) < M_PI*0.05) {
|
|
newgi.trignum = tn1;
|
|
newp = np1;
|
|
}
|
|
else
|
|
{
|
|
newp = ((STLGeometry&)geom).PointBetween(p1, gi1.trignum, p2, gi2.trignum);
|
|
tn1 = ((STLGeometry&)geom).Project(newp);
|
|
newgi.trignum = tn1;
|
|
|
|
if (!tn1)
|
|
{
|
|
newp = Center (p1, p2);
|
|
newgi.trignum = 0;
|
|
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
// (*testout) << "WARNING: PointBetween got geominfo = 0" << endl;
|
|
newp = p1+secpoint*(p2-p1);
|
|
newgi.trignum = 0;
|
|
}
|
|
|
|
// (*testout) << "newp = " << newp << ", ngi = " << newgi << endl;
|
|
}
|
|
|
|
void RefinementSTLGeometry ::
|
|
PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint,
|
|
int surfi1, int surfi2,
|
|
const EdgePointGeomInfo & gi1,
|
|
const EdgePointGeomInfo & gi2,
|
|
Point<3> & newp, EdgePointGeomInfo & newgi) const
|
|
{
|
|
/*
|
|
(*testout) << "edge-between: p1 = " << p1 << ", p2 = " << p2
|
|
<< ", gi1,2 = " << gi1 << ", " << gi2 << endl;
|
|
*/
|
|
/*
|
|
newp = Center (p1, p2);
|
|
((STLGeometry&)geom).SelectChartOfTriangle (gi1.trignum);
|
|
newgi.trignum = geom.Project (newp);
|
|
*/
|
|
int hi;
|
|
newgi.dist = (1.0-secpoint) * gi1.dist + secpoint*gi2.dist;
|
|
newgi.edgenr = gi1.edgenr;
|
|
|
|
/*
|
|
(*testout) << "p1 = " << p1 << ", p2 = " << p2 << endl;
|
|
(*testout) << "refedge: " << gi1.edgenr
|
|
<< " d1 = " << gi1.dist << ", d2 = " << gi2.dist << endl;
|
|
*/
|
|
newp = geom.GetLine (gi1.edgenr)->GetPointInDist (geom.GetPoints(), newgi.dist, hi);
|
|
|
|
// (*testout) << "newp = " << newp << endl;
|
|
}
|
|
|
|
|
|
void RefinementSTLGeometry :: ProjectToSurface (Point<3> & p, int surfi) const
|
|
{
|
|
cout << "RefinementSTLGeometry :: ProjectToSurface not implemented!" << endl;
|
|
};
|
|
|
|
|
|
void RefinementSTLGeometry :: ProjectToSurface (Point<3> & p, int surfi,
|
|
PointGeomInfo & gi) const
|
|
{
|
|
((STLGeometry&)geom).SelectChartOfTriangle (gi.trignum);
|
|
gi.trignum = geom.Project (p);
|
|
// if (!gi.trignum)
|
|
// cout << "projectSTL failed" << endl;
|
|
};
|
|
|
|
|
|
}
|