2010-03-23 17:52:07 +05:00
|
|
|
#include <mystdlib.h>
|
|
|
|
#include "meshing.hpp"
|
|
|
|
|
|
|
|
namespace netgen
|
|
|
|
{
|
|
|
|
|
2013-02-06 18:55:20 +06:00
|
|
|
DLL_HEADER GeometryRegisterArray geometryregister;
|
2019-07-09 13:39:16 +05:00
|
|
|
//DLL_HEADER NgArray<GeometryRegister*> geometryregister;
|
2011-01-11 01:18:01 +05:00
|
|
|
|
|
|
|
GeometryRegister :: ~GeometryRegister()
|
|
|
|
{ ; }
|
|
|
|
|
2019-10-28 23:58:35 +05:00
|
|
|
void GeometryFace :: RestrictHTrig(Mesh& mesh,
|
|
|
|
const PointGeomInfo& gi0,
|
|
|
|
const PointGeomInfo& gi1,
|
|
|
|
const PointGeomInfo& gi2,
|
|
|
|
const MeshingParameters& mparam,
|
|
|
|
int depth, double h) const
|
|
|
|
{
|
|
|
|
auto p0 = GetPoint(gi0);
|
|
|
|
auto p1 = GetPoint(gi1);
|
|
|
|
auto p2 = GetPoint(gi2);
|
|
|
|
auto longest = (p0-p1).Length();
|
|
|
|
int cutedge = 2;
|
|
|
|
if(auto len = (p0-p2).Length(); len > longest)
|
|
|
|
{
|
|
|
|
longest = len;
|
|
|
|
cutedge = 1;
|
|
|
|
}
|
|
|
|
if(auto len = (p1-p2).Length(); len > longest)
|
|
|
|
{
|
|
|
|
longest = len;
|
|
|
|
cutedge = 0;
|
|
|
|
}
|
|
|
|
PointGeomInfo gi_mid;
|
|
|
|
gi_mid.u = (gi0.u + gi1.u + gi2.u)/3;
|
|
|
|
gi_mid.v = (gi0.v + gi1.v + gi2.v)/3;
|
|
|
|
|
|
|
|
if(depth % 3 == 0)
|
|
|
|
{
|
|
|
|
double curvature = 0.;
|
2019-10-29 15:37:27 +05:00
|
|
|
curvature = max({curvature, GetCurvature(gi_mid),
|
|
|
|
GetCurvature(gi0), GetCurvature(gi1),
|
|
|
|
GetCurvature(gi2)});
|
2019-10-28 23:58:35 +05:00
|
|
|
if(curvature < 1e-3)
|
|
|
|
return;
|
|
|
|
double kappa = curvature * mparam.curvaturesafety;
|
|
|
|
h = mparam.maxh * kappa < 1 ? mparam.maxh : 1./kappa;
|
|
|
|
if(h < 1e-4 * longest)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(h < longest && depth < 10)
|
|
|
|
{
|
|
|
|
if(cutedge == 0)
|
|
|
|
{
|
|
|
|
PointGeomInfo gi_m;
|
|
|
|
gi_m.u = 0.5 * (gi1.u + gi2.u);
|
|
|
|
gi_m.v = 0.5 * (gi1.v + gi2.v);
|
|
|
|
RestrictHTrig(mesh, gi_m, gi2, gi0, mparam, depth+1, h);
|
|
|
|
RestrictHTrig(mesh, gi_m, gi0, gi1, mparam, depth+1, h);
|
|
|
|
}
|
|
|
|
else if(cutedge == 1)
|
|
|
|
{
|
|
|
|
PointGeomInfo gi_m;
|
|
|
|
gi_m.u = 0.5 * (gi0.u + gi2.u);
|
|
|
|
gi_m.v = 0.5 * (gi0.v + gi2.v);
|
|
|
|
RestrictHTrig(mesh, gi_m, gi1, gi2, mparam, depth+1, h);
|
|
|
|
RestrictHTrig(mesh, gi_m, gi0, gi1, mparam, depth+1, h);
|
|
|
|
}
|
|
|
|
else if(cutedge == 2)
|
|
|
|
{
|
|
|
|
PointGeomInfo gi_m;
|
|
|
|
gi_m.u = 0.5 * (gi0.u + gi1.u);
|
|
|
|
gi_m.v = 0.5 * (gi0.v + gi1.v);
|
|
|
|
RestrictHTrig(mesh, gi_m, gi1, gi2, mparam, depth+1, h);
|
|
|
|
RestrictHTrig(mesh, gi_m, gi2, gi0, mparam, depth+1, h);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto pmid = GetPoint(gi_mid);
|
|
|
|
for(const auto& p : {p0, p1, p2, pmid})
|
|
|
|
mesh.RestrictLocalH(p, h);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-24 16:17:00 +05:00
|
|
|
void NetgenGeometry :: Analyse(Mesh& mesh,
|
2019-10-28 18:41:31 +05:00
|
|
|
const MeshingParameters& mparam) const
|
2019-10-24 16:17:00 +05:00
|
|
|
{
|
|
|
|
static Timer t1("SetLocalMeshsize"); RegionTimer regt(t1);
|
|
|
|
mesh.SetGlobalH(mparam.maxh);
|
|
|
|
mesh.SetMinimalH(mparam.minh);
|
|
|
|
|
|
|
|
mesh.SetLocalH(bounding_box.PMin(), bounding_box.PMax(),
|
|
|
|
mparam.grading);
|
|
|
|
|
|
|
|
if(mparam.uselocalh)
|
2019-10-28 23:58:35 +05:00
|
|
|
{
|
|
|
|
double eps = 1e-12 * bounding_box.Diam();
|
2019-10-31 19:25:47 +05:00
|
|
|
const char* savetask = multithread.task;
|
|
|
|
multithread.task = "Analyse Edges";
|
2019-10-28 23:58:35 +05:00
|
|
|
|
|
|
|
// restrict meshsize on edges
|
2019-10-31 19:25:47 +05:00
|
|
|
for(auto i : Range(edges))
|
2019-10-28 23:58:35 +05:00
|
|
|
{
|
2019-10-31 19:25:47 +05:00
|
|
|
multithread.percent = 100. * i/edges.Size();
|
|
|
|
const auto & edge = edges[i];
|
2019-10-28 23:58:35 +05:00
|
|
|
auto length = edge->GetLength();
|
|
|
|
// skip very short edges
|
|
|
|
if(length < eps)
|
|
|
|
continue;
|
|
|
|
static constexpr int npts = 20;
|
|
|
|
// restrict mesh size based on edge length
|
|
|
|
for(auto i : Range(npts+1))
|
|
|
|
mesh.RestrictLocalH(edge->GetPoint(double(i)/npts), length/mparam.segmentsperedge);
|
|
|
|
|
|
|
|
// restrict mesh size based on edge curvature
|
|
|
|
double t = 0.;
|
|
|
|
auto p_old = edge->GetPoint(t);
|
|
|
|
while(t < 1.-eps)
|
|
|
|
{
|
|
|
|
t += edge->CalcStep(t, 1./mparam.curvaturesafety);
|
|
|
|
if(t < 1.)
|
|
|
|
{
|
|
|
|
auto p = edge->GetPoint(t);
|
|
|
|
auto dist = (p-p_old).Length();
|
|
|
|
mesh.RestrictLocalH(p, dist);
|
|
|
|
p_old = p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-31 19:25:47 +05:00
|
|
|
multithread.task = "Analyse Faces";
|
2019-10-28 23:58:35 +05:00
|
|
|
// restrict meshsize on faces
|
2019-10-31 19:25:47 +05:00
|
|
|
for(auto i : Range(faces))
|
|
|
|
{
|
|
|
|
multithread.percent = 100. * i/faces.Size();
|
|
|
|
const auto& face = faces[i];
|
|
|
|
face->RestrictH(mesh, mparam);
|
|
|
|
}
|
|
|
|
multithread.task = savetask;
|
2019-10-28 23:58:35 +05:00
|
|
|
}
|
2019-10-24 16:17:00 +05:00
|
|
|
mesh.LoadLocalMeshSize(mparam.meshsizefilename);
|
|
|
|
}
|
|
|
|
|
2019-10-28 18:41:31 +05:00
|
|
|
void NetgenGeometry :: FindEdges(Mesh& mesh,
|
|
|
|
const MeshingParameters& mparam) const
|
|
|
|
{
|
2019-10-28 21:14:55 +05:00
|
|
|
static Timer t1("MeshEdges"); RegionTimer regt(t1);
|
2019-10-29 15:37:27 +05:00
|
|
|
static Timer tdivide("Divide Edges");
|
|
|
|
static Timer tdivedgesections("Divide edge sections");
|
2019-10-31 17:34:40 +05:00
|
|
|
const char* savetask = multithread.task;
|
|
|
|
multithread.task = "Mesh Edges";
|
2019-10-28 21:14:55 +05:00
|
|
|
|
|
|
|
// create face descriptors and set bc names
|
|
|
|
mesh.SetNBCNames(faces.Size());
|
|
|
|
for(auto i : Range(faces.Size()))
|
|
|
|
{
|
|
|
|
mesh.SetBCName(i, faces[i]->GetName());
|
|
|
|
// todo find attached solids
|
|
|
|
FaceDescriptor fd(i+1, 1, 0, i+1);
|
|
|
|
fd.SetBCName(mesh.GetBCNamePtr(i));
|
|
|
|
mesh.AddFaceDescriptor(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::map<size_t, PointIndex> vert2meshpt;
|
|
|
|
for(auto i : Range(vertices))
|
|
|
|
{
|
|
|
|
const auto& vert = *vertices[i];
|
|
|
|
MeshPoint mp(vert.GetPoint());
|
|
|
|
vert2meshpt[vert.GetHash()] = mesh.AddPoint(mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t segnr = 0;
|
|
|
|
for(auto facenr : Range(faces.Size()))
|
|
|
|
{
|
|
|
|
const auto& face = *faces[facenr];
|
|
|
|
for(auto facebndnr : Range(face.GetNBoundaries()))
|
|
|
|
{
|
|
|
|
auto boundary = face.GetBoundary(facebndnr);
|
|
|
|
for(auto enr : Range(boundary))
|
|
|
|
{
|
2019-10-31 19:17:28 +05:00
|
|
|
multithread.percent = 100. * ((double(enr)/boundary.Size() + facebndnr)/face.GetNBoundaries() + facenr)/faces.Size();
|
2019-10-28 21:14:55 +05:00
|
|
|
const auto& oriented_edge = *boundary[enr];
|
|
|
|
auto edgenr = GetEdgeIndex(oriented_edge);
|
|
|
|
const auto& edge = edges[edgenr];
|
|
|
|
PointIndex startp, endp;
|
|
|
|
// throws if points are not found
|
|
|
|
startp = vert2meshpt.at(edge->GetStartVertex().GetHash());
|
|
|
|
endp = vert2meshpt.at(edge->GetEndVertex().GetHash());
|
|
|
|
|
|
|
|
// ignore collapsed edges
|
|
|
|
if(startp == endp && edge->GetLength() < 1e-10 * bounding_box.Diam())
|
|
|
|
continue;
|
|
|
|
Array<MeshPoint> mps;
|
|
|
|
Array<double> params;
|
|
|
|
// -------------------- DivideEdge -----------------
|
2019-10-29 15:37:27 +05:00
|
|
|
static constexpr size_t divide_edge_sections = 1000;
|
|
|
|
tdivide.Start();
|
2019-10-28 21:14:55 +05:00
|
|
|
double hvalue[divide_edge_sections+1];
|
|
|
|
hvalue[0] = 0;
|
|
|
|
|
2019-10-31 17:34:40 +05:00
|
|
|
Point<3> old_pt = edge->GetPoint(0.);
|
2019-10-28 21:14:55 +05:00
|
|
|
// calc local h for edge
|
2019-10-29 15:37:27 +05:00
|
|
|
tdivedgesections.Start();
|
2019-10-31 17:34:40 +05:00
|
|
|
for(auto i : Range(divide_edge_sections))
|
|
|
|
{
|
|
|
|
auto pt = edge->GetPoint(double(i+1)/divide_edge_sections);
|
|
|
|
hvalue[i+1] = hvalue[i] + 1./mesh.GetH(pt) * (pt-old_pt).Length();
|
|
|
|
old_pt = pt;
|
|
|
|
}
|
2019-10-28 21:14:55 +05:00
|
|
|
int nsubedges = max2(1, int(floor(hvalue[divide_edge_sections]+0.5)));
|
2019-10-29 15:37:27 +05:00
|
|
|
tdivedgesections.Stop();
|
2019-10-28 21:14:55 +05:00
|
|
|
mps.SetSize(nsubedges-1);
|
|
|
|
params.SetSize(nsubedges+1);
|
|
|
|
|
|
|
|
int i = 1;
|
|
|
|
int i1 = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (hvalue[i1]/hvalue[divide_edge_sections]*nsubedges >= i)
|
|
|
|
{
|
2019-10-29 15:37:27 +05:00
|
|
|
params[i] = (double(i1)/divide_edge_sections);
|
|
|
|
mps[i-1] = MeshPoint(edge->GetPoint(params[i]));
|
2019-10-28 21:14:55 +05:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
i1++;
|
|
|
|
if (i1 > divide_edge_sections)
|
|
|
|
{
|
|
|
|
nsubedges = i;
|
|
|
|
mps.SetSize(nsubedges-1);
|
|
|
|
params.SetSize(nsubedges+1);
|
|
|
|
cout << "divide edge: local h too small" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
} while(i < nsubedges);
|
|
|
|
|
|
|
|
params[0] = 0.;
|
|
|
|
params[nsubedges] = 1.;
|
|
|
|
|
|
|
|
if(params[nsubedges] <= params[nsubedges-1])
|
|
|
|
{
|
|
|
|
cout << "CORRECTED" << endl;
|
|
|
|
mps.SetSize (nsubedges-2);
|
|
|
|
params.SetSize (nsubedges);
|
2019-10-31 17:34:40 +05:00
|
|
|
params[nsubedges-1] = 1.;
|
2019-10-28 21:14:55 +05:00
|
|
|
}
|
2019-10-29 15:37:27 +05:00
|
|
|
tdivide.Stop();
|
2019-10-28 21:14:55 +05:00
|
|
|
// ----------- Add Points to mesh and create segments -----
|
|
|
|
Array<PointIndex> pnums(mps.Size() + 2);
|
|
|
|
pnums[0] = startp;
|
|
|
|
pnums[mps.Size()+1] = endp;
|
|
|
|
|
|
|
|
double eps = bounding_box.Diam() * 1e-8;
|
|
|
|
|
|
|
|
for(auto i : Range(mps))
|
|
|
|
{
|
|
|
|
bool exists = false;
|
|
|
|
for(auto pi : Range(mesh.Points()))
|
|
|
|
{
|
|
|
|
if((mesh[pi] - mps[i]).Length() < eps)
|
|
|
|
{
|
|
|
|
exists = true;
|
|
|
|
pnums[i+1] = pi;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!exists)
|
|
|
|
pnums[i+1] = mesh.AddPoint(mps[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(auto i : Range(pnums.Size()-1))
|
|
|
|
{
|
|
|
|
segnr++;
|
|
|
|
Segment seg;
|
|
|
|
seg[0] = pnums[i];
|
|
|
|
seg[1] = pnums[i+1];
|
|
|
|
seg.edgenr = segnr;
|
|
|
|
seg.epgeominfo[0].dist = params[i];
|
|
|
|
seg.epgeominfo[1].dist = params[i+1];
|
|
|
|
seg.epgeominfo[0].edgenr = edgenr;
|
|
|
|
seg.epgeominfo[1].edgenr = edgenr;
|
|
|
|
seg.si = facenr+1;
|
|
|
|
seg.surfnr1 = facenr+1;
|
|
|
|
|
|
|
|
// TODO: implement functionality to transfer edge parameter t to face parameters u,v
|
|
|
|
for(auto j : Range(2))
|
|
|
|
face.CalcEdgePointGI(*edge, params[i+j],
|
|
|
|
seg.epgeominfo[j]);
|
|
|
|
|
|
|
|
if(!oriented_edge.OrientedLikeGlobal())
|
|
|
|
{
|
|
|
|
swap (seg[0], seg[1]);
|
|
|
|
swap (seg.epgeominfo[0].dist, seg.epgeominfo[1].dist);
|
|
|
|
swap (seg.epgeominfo[0].u, seg.epgeominfo[1].u);
|
|
|
|
swap (seg.epgeominfo[0].v, seg.epgeominfo[1].v);
|
|
|
|
}
|
|
|
|
mesh.AddSegment(seg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-10-31 17:34:40 +05:00
|
|
|
mesh.CalcSurfacesOfNode();
|
|
|
|
multithread.task = savetask;
|
2019-10-28 18:41:31 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
void NetgenGeometry :: MeshSurface(Mesh& mesh,
|
|
|
|
const MeshingParameters& mparam) const
|
|
|
|
{
|
|
|
|
static Timer t1("Surface Meshing"); RegionTimer regt(t1);
|
2019-10-31 19:17:28 +05:00
|
|
|
const char* savetask = multithread.task;
|
|
|
|
multithread.task = "Mesh Surface";
|
2019-10-28 18:41:31 +05:00
|
|
|
|
|
|
|
Array<int, PointIndex> glob2loc(mesh.GetNP());
|
|
|
|
for(auto k : Range(faces))
|
|
|
|
{
|
2019-10-31 19:17:28 +05:00
|
|
|
multithread.percent = 100. * k/faces.Size();
|
2019-10-28 18:41:31 +05:00
|
|
|
const auto& face = *faces[k];
|
|
|
|
auto bb = face.GetBoundingBox();
|
|
|
|
bb.Increase(bb.Diam()/10);
|
|
|
|
Meshing2 meshing(*this, mparam, bb);
|
|
|
|
glob2loc = 0;
|
|
|
|
int cntp = 0;
|
|
|
|
|
|
|
|
for(auto& seg : mesh.LineSegments())
|
|
|
|
{
|
|
|
|
if(seg.si == k+1)
|
|
|
|
{
|
|
|
|
for(auto j : Range(2))
|
|
|
|
{
|
|
|
|
auto pi = seg[j];
|
|
|
|
if(glob2loc[pi] == 0)
|
|
|
|
{
|
|
|
|
meshing.AddPoint(mesh[pi], pi);
|
|
|
|
cntp++;
|
|
|
|
glob2loc[pi] = cntp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(auto & seg : mesh.LineSegments())
|
|
|
|
{
|
|
|
|
if(seg.si == k+1)
|
|
|
|
{
|
|
|
|
PointGeomInfo gi0, gi1;
|
|
|
|
gi0.trignum = gi1.trignum = k+1;
|
|
|
|
gi0.u = seg.epgeominfo[0].u;
|
|
|
|
gi0.v = seg.epgeominfo[0].v;
|
|
|
|
gi1.u = seg.epgeominfo[1].u;
|
|
|
|
gi1.v = seg.epgeominfo[1].v;
|
|
|
|
meshing.AddBoundaryElement(glob2loc[seg[0]],
|
|
|
|
glob2loc[seg[1]],
|
|
|
|
gi0, gi1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO Set max area 2* area of face
|
|
|
|
|
|
|
|
auto noldsurfels = mesh.GetNSE();
|
|
|
|
|
|
|
|
|
|
|
|
static Timer t("GenerateMesh"); RegionTimer reg(t);
|
|
|
|
MESHING2_RESULT res = meshing.GenerateMesh(mesh, mparam, mparam.maxh, k+1);
|
|
|
|
|
|
|
|
for(auto i : Range(noldsurfels, mesh.GetNSE()))
|
|
|
|
{
|
|
|
|
mesh.SurfaceElements()[i].SetIndex(k+1);
|
|
|
|
}
|
|
|
|
}
|
2019-10-31 19:17:28 +05:00
|
|
|
multithread.task = savetask;
|
2019-10-28 18:41:31 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
void NetgenGeometry :: OptimizeSurface(Mesh& mesh, const MeshingParameters& mparam) const
|
2019-10-02 21:14:38 +05:00
|
|
|
{
|
|
|
|
const auto savetask = multithread.task;
|
|
|
|
multithread.task = "Optimizing surface";
|
|
|
|
|
|
|
|
static Timer timer_opt2d("Optimization 2D");
|
|
|
|
RegionTimer reg(timer_opt2d);
|
2019-10-02 23:29:18 +05:00
|
|
|
auto meshopt = MeshOptimize2d(mesh);
|
2019-10-02 21:14:38 +05:00
|
|
|
for(auto i : Range(mparam.optsteps2d))
|
|
|
|
{
|
2019-10-31 19:17:28 +05:00
|
|
|
PrintMessage(3, "Optimization step ", i);
|
|
|
|
int innerstep = 0;
|
2019-10-02 21:14:38 +05:00
|
|
|
for(auto optstep : mparam.optimize2d)
|
|
|
|
{
|
2019-10-31 19:17:28 +05:00
|
|
|
multithread.percent = 100. * (double(innerstep++)/mparam.optimize2d.size() + i)/mparam.optsteps2d;
|
2019-10-02 21:14:38 +05:00
|
|
|
switch(optstep)
|
|
|
|
{
|
|
|
|
case 's':
|
2019-10-02 23:29:18 +05:00
|
|
|
meshopt.EdgeSwapping(0);
|
2019-10-02 21:14:38 +05:00
|
|
|
break;
|
|
|
|
case 'S':
|
2019-10-02 23:29:18 +05:00
|
|
|
meshopt.EdgeSwapping(1);
|
2019-10-02 21:14:38 +05:00
|
|
|
break;
|
2019-10-03 15:09:13 +05:00
|
|
|
case 'm':
|
2019-10-02 23:29:18 +05:00
|
|
|
meshopt.ImproveMesh(mparam);
|
2019-10-02 21:14:38 +05:00
|
|
|
break;
|
2019-10-03 15:09:13 +05:00
|
|
|
case 'c':
|
2019-10-02 23:29:18 +05:00
|
|
|
meshopt.CombineImprove();
|
2019-10-02 21:14:38 +05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mesh.CalcSurfacesOfNode();
|
|
|
|
mesh.Compress();
|
|
|
|
multithread.task = savetask;
|
|
|
|
}
|
2018-05-12 12:16:02 +05:00
|
|
|
|
|
|
|
shared_ptr<NetgenGeometry> GeometryRegisterArray :: LoadFromMeshFile (istream & ist) const
|
|
|
|
{
|
|
|
|
for (int i = 0; i < Size(); i++)
|
|
|
|
{
|
|
|
|
NetgenGeometry * hgeom = (*this)[i]->LoadFromMeshFile (ist);
|
|
|
|
if (hgeom)
|
|
|
|
return shared_ptr<NetgenGeometry>(hgeom);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
2011-01-11 01:18:01 +05:00
|
|
|
|
|
|
|
|
|
|
|
|
2010-03-23 17:52:07 +05:00
|
|
|
|
2016-12-05 17:50:21 +05:00
|
|
|
int NetgenGeometry :: GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam)
|
2010-03-23 17:52:07 +05:00
|
|
|
{
|
2019-10-02 20:20:13 +05:00
|
|
|
multithread.percent = 0;
|
2010-03-23 17:52:07 +05:00
|
|
|
|
2019-10-02 20:20:13 +05:00
|
|
|
if(mparam.perfstepsstart <= MESHCONST_ANALYSE)
|
2010-03-23 17:52:07 +05:00
|
|
|
{
|
2019-10-02 20:20:13 +05:00
|
|
|
if(!mesh)
|
|
|
|
mesh = make_shared<Mesh>();
|
|
|
|
mesh->geomtype = GetGeomType();
|
|
|
|
Analyse(*mesh, mparam);
|
|
|
|
}
|
2010-03-23 17:52:07 +05:00
|
|
|
|
2019-10-02 20:20:13 +05:00
|
|
|
if(multithread.terminate || mparam.perfstepsend <= MESHCONST_ANALYSE)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if(mparam.perfstepsstart <= MESHCONST_MESHEDGES)
|
|
|
|
FindEdges(*mesh, mparam);
|
|
|
|
|
|
|
|
if(multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHEDGES)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (mparam.perfstepsstart <= MESHCONST_MESHSURFACE)
|
|
|
|
{
|
|
|
|
MeshSurface(*mesh, mparam);
|
|
|
|
mesh->CalcSurfacesOfNode();
|
2010-03-23 17:52:07 +05:00
|
|
|
}
|
2019-10-03 15:09:13 +05:00
|
|
|
|
2019-10-02 20:20:13 +05:00
|
|
|
if (multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHSURFACE)
|
|
|
|
return 0;
|
2019-10-03 15:09:13 +05:00
|
|
|
|
2019-10-02 20:20:13 +05:00
|
|
|
if (mparam.perfstepsstart <= MESHCONST_OPTSURFACE)
|
|
|
|
OptimizeSurface(*mesh, mparam);
|
|
|
|
|
|
|
|
if (multithread.terminate || mparam.perfstepsend <= MESHCONST_OPTSURFACE)
|
|
|
|
return 0;
|
2010-03-23 17:52:07 +05:00
|
|
|
|
2019-10-03 15:09:13 +05:00
|
|
|
|
2019-10-02 20:20:13 +05:00
|
|
|
if(mparam.perfstepsstart <= MESHCONST_MESHVOLUME)
|
|
|
|
{
|
|
|
|
multithread.task = "Volume meshing";
|
|
|
|
|
|
|
|
MESHING3_RESULT res = MeshVolume (mparam, *mesh);
|
|
|
|
|
|
|
|
if (res != MESHING3_OK) return 1;
|
|
|
|
if (multithread.terminate) return 0;
|
|
|
|
|
|
|
|
RemoveIllegalElements (*mesh);
|
|
|
|
if (multithread.terminate) return 0;
|
|
|
|
|
|
|
|
MeshQuality3d (*mesh);
|
|
|
|
}
|
|
|
|
|
2016-12-05 17:50:21 +05:00
|
|
|
if (multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHVOLUME)
|
2010-03-23 17:52:07 +05:00
|
|
|
return 0;
|
2019-10-03 15:09:13 +05:00
|
|
|
|
2010-03-23 17:52:07 +05:00
|
|
|
|
2016-12-05 17:50:21 +05:00
|
|
|
if (mparam.perfstepsstart <= MESHCONST_OPTVOLUME)
|
2010-03-23 17:52:07 +05:00
|
|
|
{
|
|
|
|
multithread.task = "Volume optimization";
|
2019-10-03 15:09:13 +05:00
|
|
|
|
2010-03-23 17:52:07 +05:00
|
|
|
OptimizeVolume (mparam, *mesh);
|
|
|
|
if (multithread.terminate) return 0;
|
|
|
|
}
|
2019-10-02 20:20:13 +05:00
|
|
|
FinalizeMesh(*mesh);
|
2010-03-23 17:52:07 +05:00
|
|
|
return 0;
|
2019-10-02 20:20:13 +05:00
|
|
|
}
|
2010-03-23 17:52:07 +05:00
|
|
|
|
2011-01-11 01:18:01 +05:00
|
|
|
void NetgenGeometry :: Save (string filename) const
|
|
|
|
{
|
|
|
|
throw NgException("Cannot save geometry - no geometry available");
|
|
|
|
}
|
|
|
|
|
2018-12-14 16:01:58 +05:00
|
|
|
static RegisterClassForArchive<NetgenGeometry> regnggeo;
|
2010-03-23 17:52:07 +05:00
|
|
|
}
|