Interpolate growth vectors on surfaces

also:
- clean up delaunay2d code (Use Point<2>, remove comments)
- implement CalcWeights() used to interpolate data from boundary points
  to surface points
This commit is contained in:
mhochsteger@cerbsim.com 2022-02-25 16:50:26 +01:00
parent f6a7ffa4fe
commit dabb3b9dbf
5 changed files with 359 additions and 287 deletions

View File

@ -1184,6 +1184,8 @@ public:
: DelaunayTree(box.PMin(), box.PMax()) : DelaunayTree(box.PMin(), box.PMax())
{ } { }
double GetTolerance() { return tol; }
size_t GetNLeaves() size_t GetNLeaves()
{ {
return n_leaves; return n_leaves;

View File

@ -26,7 +26,7 @@ add_library(mesh ${NG_LIB_TYPE}
ruler2.cpp ruler3.cpp secondorder.cpp smoothing2.5.cpp ruler2.cpp ruler3.cpp secondorder.cpp smoothing2.5.cpp
smoothing2.cpp smoothing3.cpp specials.cpp smoothing2.cpp smoothing3.cpp specials.cpp
topology.cpp validate.cpp bcfunctions.cpp topology.cpp validate.cpp bcfunctions.cpp
parallelmesh.cpp paralleltop.cpp paralleltop.hpp basegeom.cpp parallelmesh.cpp paralleltop.cpp basegeom.cpp
python_mesh.cpp surfacegeom.cpp python_mesh.cpp surfacegeom.cpp
../../ng/onetcl.cpp ../../ng/onetcl.cpp
${rules_sources} ${rules_sources}
@ -53,6 +53,6 @@ install(FILES
localh.hpp meshclass.hpp meshfunc.hpp meshing2.hpp meshing3.hpp localh.hpp meshclass.hpp meshfunc.hpp meshing2.hpp meshing3.hpp
meshing.hpp meshtool.hpp meshtype.hpp msghandler.hpp paralleltop.hpp meshing.hpp meshtool.hpp meshtype.hpp msghandler.hpp paralleltop.hpp
ruler2.hpp ruler3.hpp specials.hpp topology.hpp validate.hpp ruler2.hpp ruler3.hpp specials.hpp topology.hpp validate.hpp
python_mesh.hpp surfacegeom.hpp python_mesh.hpp surfacegeom.hpp delaunay2d.hpp
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/meshing COMPONENT netgen_devel DESTINATION ${NG_INSTALL_DIR_INCLUDE}/meshing COMPONENT netgen_devel
) )

View File

@ -1,6 +1,7 @@
#include <mystdlib.h> #include <mystdlib.h>
#include "meshing.hpp" #include "meshing.hpp"
#include "meshing2.hpp" #include "meshing2.hpp"
#include "delaunay2d.hpp"
#include "global.hpp" #include "global.hpp"
#include "../geom2d/csg2d.hpp" #include "../geom2d/csg2d.hpp"
@ -262,6 +263,8 @@ namespace netgen
{ {
for(auto pi : sel.PNums()) for(auto pi : sel.PNums())
{ {
if(mesh[pi].Type() >= SURFACEPOINT)
continue;
auto & np = growthvectors[pi]; auto & np = growthvectors[pi];
if(np.Length() == 0) { np = n; continue; } if(np.Length() == 0) { np = n; continue; }
auto npn = np * n; auto npn = np * n;
@ -352,6 +355,8 @@ namespace netgen
for(auto i : Range(sel.PNums())) for(auto i : Range(sel.PNums()))
{ {
auto pi = sel.PNums()[i]; auto pi = sel.PNums()[i];
if(mesh[pi].Type() >= SURFACEPOINT)
continue;
if(growthvectors[pi].Length2() == 0.) if(growthvectors[pi].Length2() == 0.)
continue; continue;
auto next = sel.PNums()[(i+1)%sel.GetNV()]; auto next = sel.PNums()[(i+1)%sel.GetNV()];
@ -393,6 +398,73 @@ namespace netgen
} }
} }
Array<Point<2>, PointIndex> delaunay_points(mesh.GetNP());
Array<int, PointIndex> p2face(mesh.GetNP());
p2face = 0;
// interpolate growth vectors at inner surface points from surrounding edge points
Array<SurfaceElementIndex> surface_els;
Array<PointIndex> edge_points;
Array<PointIndex> surface_points;
for(auto facei : Range(1, fd_old+1))
{
if(!blp.surfid.Contains(facei))
continue;
p2face = 0;
edge_points.SetSize(0);
surface_points.SetSize(0);
surface_els.SetSize(0);
mesh.GetSurfaceElementsOfFace (facei, surface_els);
Box<2> bbox ( Box<2>::EMPTY_BOX );
for(auto sei : surface_els)
{
const auto & sel = mesh[sei];
for (auto i : Range(sel.GetNP()))
{
auto pi = sel[i];
if(p2face[pi] != 0)
continue;
p2face[pi] = facei;
if(mesh[pi].Type() <= EDGEPOINT)
edge_points.Append(pi);
else
surface_points.Append(pi);
auto & gi = sel.GeomInfo()[i];
// TODO: project to plane if u,v not available?
delaunay_points[pi] = {gi.u, gi.v};
bbox.Add(delaunay_points[pi]);
}
}
if(surface_points.Size()==0)
continue;
DelaunayMesh dmesh( delaunay_points, bbox );
for(auto pi : edge_points)
{
p2face[pi] = 0;
dmesh.AddPoint(pi);
}
std::map<PointIndex, double> weights;
for(auto pi : surface_points)
{
dmesh.AddPoint(pi, &weights);
auto & v = growthvectors[pi];
for(auto & [pi_other, weight] : weights)
v += weight * growthvectors[pi_other];
}
}
// insert new points // insert new points
for (PointIndex pi = 1; pi <= np; pi++) for (PointIndex pi = 1; pi <= np; pi++)
if (growthvectors[pi].Length2() != 0) if (growthvectors[pi].Length2() != 0)

View File

@ -1,265 +1,172 @@
#include <mystdlib.h> #include <mystdlib.h>
#include "meshing.hpp" #include "delaunay2d.hpp"
#include <geom2d/csg2d.hpp> #include <geom2d/csg2d.hpp>
// not yet working ....
namespace netgen namespace netgen
{ {
using ngcore::INT; using ngcore::INT;
extern void Optimize2d (Mesh & mesh, MeshingParameters & mp);
static inline Point<2> P2( Point<3> p )
void DelaunayTrig::CalcCenter (FlatArray<Point<2>, PointIndex> points)
{ {
return {p[0], p[1]}; Point<2> p1 = points[pnums[0]];
Point<2> p2 = points[pnums[1]];
Point<2> p3 = points[pnums[2]];
Vec<2> v1 = p2-p1;
Vec<2> v2 = p3-p1;
// without normal equation ...
Mat<2,2> mat, inv;
mat(0,0) = v1(0); mat(0,1) = v1(1);
mat(1,0) = v2(0); mat(1,1) = v2(1);
CalcInverse (mat, inv);
Vec<2> rhs, sol;
rhs(0) = 0.5 * v1*v1;
rhs(1) = 0.5 * v2*v2;
sol = inv * rhs;
c = p1 + sol;
rad2 = Dist2(c, p1);
r = sqrt(rad2);
} }
static inline Point<3> P3( Point<2> p ) int DelaunayMesh::GetNeighbour( int eli, int edge )
{ {
return {p[0], p[1], 0}; auto p0 = trigs[eli][(edge+1)%3];
auto p1 = trigs[eli][(edge+2)%3];
if(p1<p0)
Swap(p0,p1);
INT<2> hash = {p0,p1};
auto pos = edge_to_trig.Position(hash);
if (pos == -1) return -1;
auto i2 = edge_to_trig.GetData(pos);
return i2[0] == eli ? i2[1] : i2[0];
} }
void DelaunayMesh::SetNeighbour( int eli, int edge )
class DelaunayTrig
{ {
PointIndex pnums[3]; auto p0 = trigs[eli][(edge+1)%3];
Point<2> c; auto p1 = trigs[eli][(edge+2)%3];
public: if(p1<p0)
double r; Swap(p0,p1);
double rad2;
DelaunayTrig () = default;
DelaunayTrig (int p1, int p2, int p3)
{
pnums[0] = p1;
pnums[1] = p2;
pnums[2] = p3;
}
PointIndex & operator[] (int j) { return pnums[j]; } INT<2> hash = {p0,p1};
const PointIndex & operator[] (int j) const { return pnums[j]; } auto pos = edge_to_trig.Position(hash);
if (pos == -1)
void CalcCenter (Mesh & mesh) edge_to_trig[hash] = {eli, -1};
{ else
Point<2> p1 = P2(mesh[pnums[0]]);
Point<2> p2 = P2(mesh[pnums[1]]);
Point<2> p3 = P2(mesh[pnums[2]]);
Vec<2> v1 = p2-p1;
Vec<2> v2 = p3-p1;
/*
Mat<2,2> mat, inv;
mat(0,0) = v1*v1;
mat(0,1) = v1*v2;
mat(1,0) = v2*v1;
mat(1,1) = v2*v2;
Vec<2> rhs, sol;
rhs(0) = 0.5 * v1*v1;
rhs(1) = 0.5 * v2*v2;
CalcInverse (mat, inv);
sol = inv * rhs;
c = p1 + sol(0) * v1 + sol(1) * v2;
rad2 = Dist2(c, p1);
r = sqrt(rad2);
*/
// without normal equation ...
Mat<2,2> mat, inv;
mat(0,0) = v1(0); mat(0,1) = v1(1);
mat(1,0) = v2(0); mat(1,1) = v2(1);
CalcInverse (mat, inv);
Vec<2> rhs, sol;
rhs(0) = 0.5 * v1*v1;
rhs(1) = 0.5 * v2*v2;
sol = inv * rhs;
c = p1 + sol;
rad2 = Dist2(c, p1);
r = sqrt(rad2);
}
Point<2> Center() const { return c; }
double Radius2() const { return rad2; }
Box<2> BoundingBox() const { return Box<2> (c-Vec<2>(r,r), c+Vec<2>(r,r)); }
mutable PointIndex visited_pi = -1;
};
class DelaunayMesh
{
ngcore::ClosedHashTable<INT<2>, INT<2>> edge_to_trig;
Array<DelaunayTrig> trigs;
unique_ptr<DelaunayTree<2>> tree;
Mesh & mesh;
Array<int> closeels;
Array<int> intersecting;
Array<INT<2>> edges;
int GetNeighbour( int eli, int edge )
{
auto p0 = trigs[eli][(edge+1)%3];
auto p1 = trigs[eli][(edge+2)%3];
if(p1<p0)
Swap(p0,p1);
INT<2> hash = {p0,p1};
/*
if(!edge_to_trig.Used(hash))
return -1;
auto i2 = edge_to_trig.Get({p0,p1});
return i2[0] == eli ? i2[1] : i2[0];
*/
auto pos = edge_to_trig.Position(hash);
if (pos == -1) return -1;
auto i2 = edge_to_trig.GetData(pos);
return i2[0] == eli ? i2[1] : i2[0];
}
void SetNeighbour( int eli, int edge )
{
auto p0 = trigs[eli][(edge+1)%3];
auto p1 = trigs[eli][(edge+2)%3];
if(p1<p0)
Swap(p0,p1);
INT<2> hash = {p0,p1};
auto pos = edge_to_trig.Position(hash);
if (pos == -1)
edge_to_trig[hash] = {eli, -1};
else
{
auto i2 = edge_to_trig.GetData(pos);
if(i2[0]==-1)
i2[0] = eli;
else
{
if(i2[1]==-1)
i2[1] = eli;
}
edge_to_trig.SetData (pos, i2);
}
/*
if(!edge_to_trig.Used(hash))
edge_to_trig[hash] = {eli, -1};
else
{ {
auto i2 = edge_to_trig.GetData(pos);
auto i2 = edge_to_trig.Get({p0,p1});
if(i2[0]==-1) if(i2[0]==-1)
i2[0] = eli; i2[0] = eli;
else else
{ {
if(i2[1]==-1) if(i2[1]==-1)
i2[1] = eli; i2[1] = eli;
} }
edge_to_trig[hash] = i2;
}
*/
}
void UnsetNeighbours( int eli )
{
for(int edge : Range(3))
{
auto p0 = trigs[eli][(edge+1)%3];
auto p1 = trigs[eli][(edge+2)%3];
if(p1<p0)
Swap(p0,p1);
INT<2> hash = {p0,p1};
// auto i2 = edge_to_trig.Get({p0,p1});
auto pos = edge_to_trig.Position(hash);
auto i2 = edge_to_trig.GetData(pos);
if(i2[0]==eli)
i2[0] = i2[1];
i2[1] = -1;
// edge_to_trig[hash] = i2;
edge_to_trig.SetData (pos, i2); edge_to_trig.SetData (pos, i2);
} }
} }
void DelaunayMesh::UnsetNeighbours( int eli )
void AppendTrig( int pi0, int pi1, int pi2 ) {
for(int edge : Range(3))
{ {
DelaunayTrig el; auto p0 = trigs[eli][(edge+1)%3];
el[0] = pi0; auto p1 = trigs[eli][(edge+2)%3];
el[1] = pi1; if(p1<p0)
el[2] = pi2; Swap(p0,p1);
el.CalcCenter(mesh); INT<2> hash = {p0,p1};
auto pos = edge_to_trig.Position(hash);
auto i2 = edge_to_trig.GetData(pos);
trigs.Append(el); if(i2[0]==eli)
int ti = trigs.Size()-1; i2[0] = i2[1];
tree->Insert(el.BoundingBox(), ti); i2[1] = -1;
for(int i : Range(3)) edge_to_trig.SetData (pos, i2);
SetNeighbour(ti, i);
} }
}
public:
DelaunayMesh( Mesh & mesh_, Box<2> box )
: mesh(mesh_)
{
Vec<2> vdiag = box.PMax()-box.PMin();
double w = vdiag(0); void DelaunayMesh::AppendTrig( int pi0, int pi1, int pi2 )
double h = vdiag(1); {
DelaunayTrig el;
el[0] = pi0;
el[1] = pi1;
el[2] = pi2;
Point<2> p0 = box.PMin() + Vec<2> ( -3*h, -h); el.CalcCenter(points);
Point<2> p1 = box.PMin() + Vec<2> (w+3*h, -h);
Point<2> p2 = box.Center() + Vec<2> (0, 1.5*h+0.5*w);
box.Add( p0 ); trigs.Append(el);
box.Add( p1 ); int ti = trigs.Size()-1;
box.Add( p2 ); tree->Insert(el.BoundingBox(), ti);
tree = make_unique<DelaunayTree<2>>(box); for(int i : Range(3))
SetNeighbour(ti, i);
}
auto pi0 = mesh.AddPoint (P3(p0)); DelaunayMesh::DelaunayMesh( Array<Point<2>, PointIndex> & points_, Box<2> box )
auto pi1 = mesh.AddPoint (P3(p1)); : points(points_)
auto pi2 = mesh.AddPoint (P3(p2)); {
AppendTrig(pi0, pi1, pi2); Vec<2> vdiag = box.PMax()-box.PMin();
}
void AddPoint( PointIndex pi_new ) double w = vdiag(0);
{ double h = vdiag(1);
static Timer t("AddPoint"); RegionTimer reg(t);
Point<2> newp = P2(mesh[pi_new]);
intersecting.SetSize(0);
edges.SetSize(0);
int definitive_overlapping_trig = -1; Point<2> p0 = box.PMin() + Vec<2> ( -3*h, -h);
Point<2> p1 = box.PMin() + Vec<2> (w+3*h, -h);
Point<2> p2 = box.Center() + Vec<2> (0, 1.5*h+0.5*w);
double minquot{1e20}; box.Add( p0 );
tree->GetFirstIntersecting (newp, newp, [&] (const auto i_trig) box.Add( p1 );
{ box.Add( p2 );
const auto trig = trigs[i_trig];
double rad2 = trig.Radius2(); tree = make_unique<DelaunayTree<2>>(box);
double d2 = Dist2 (trig.Center(), newp);
if (d2 >= rad2) return false; auto pi0 = points.Append (p0);
auto pi1 = points.Append (p1);
if (d2 < 0.999 * rad2) auto pi2 = points.Append (p2);
{ AppendTrig(pi0, pi1, pi2);
definitive_overlapping_trig = i_trig; }
return true;
} void DelaunayMesh::CalcIntersecting( PointIndex pi_new )
{
if (definitive_overlapping_trig == -1 || d2 < 0.99*minquot*rad2) static Timer t("CalcIntersecting"); RegionTimer reg(t);
{
minquot = d2/rad2; Point<2> newp = points[pi_new];
definitive_overlapping_trig = i_trig; intersecting.SetSize(0);
} edges.SetSize(0);
return false;
}); int definitive_overlapping_trig = -1;
double minquot{1e20};
tree->GetFirstIntersecting (newp, newp, [&] (const auto i_trig)
{
const auto trig = trigs[i_trig];
double rad2 = trig.Radius2();
double d2 = Dist2 (trig.Center(), newp);
if (d2 >= rad2) return false;
if (d2 < 0.999 * rad2)
{
definitive_overlapping_trig = i_trig;
return true;
}
if (definitive_overlapping_trig == -1 || d2 < 0.99*minquot*rad2)
{
minquot = d2/rad2;
definitive_overlapping_trig = i_trig;
}
return false;
});
if(definitive_overlapping_trig==-1) if(definitive_overlapping_trig==-1)
{ {
@ -284,52 +191,63 @@ namespace netgen
} }
} }
// static Timer tvis("trig visited");
// tvis.Start();
// BitArray trig_visited(trigs.Size());
// trig_visited.Clear();
if(definitive_overlapping_trig==-1) if(definitive_overlapping_trig==-1)
{
Mesh m;
m.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0));
for(auto pi : points.Range())
m.AddPoint(P3(points[pi]));
for (DelaunayTrig & trig : trigs)
{
if (trig[0] < 0) continue;
Vec<3> n = Cross (P3(points[trig[1]])-P3(points[trig[0]]),
P3(points[trig[2]])-P3(points[trig[0]]));
if (n(2) < 0) Swap (trig[1], trig[2]);
Element2d el(trig[0], trig[1], trig[2]);
el.SetIndex (1);
m.AddSurfaceElement (el);
}
m.Compress();
m.AddPoint(P3(points[pi_new]));
m.Save("error.vol.gz");
throw Exception("point not in any circle "+ ToString(pi_new)); throw Exception("point not in any circle "+ ToString(pi_new));
// tvis.Stop(); }
// static Timer t2("addpoint - rest"); RegionTimer r2(t2);
Array<int> trigs_to_visit; Array<int> trigs_to_visit;
trigs_to_visit.Append(definitive_overlapping_trig); trigs_to_visit.Append(definitive_overlapping_trig);
intersecting.Append(definitive_overlapping_trig); intersecting.Append(definitive_overlapping_trig);
// trig_visited.SetBit(definitive_overlapping_trig);
trigs[definitive_overlapping_trig].visited_pi = pi_new; trigs[definitive_overlapping_trig].visited_pi = pi_new;
while(trigs_to_visit.Size()) while(trigs_to_visit.Size())
{ {
int ti = trigs_to_visit.Last(); int ti = trigs_to_visit.Last();
trigs_to_visit.DeleteLast(); trigs_to_visit.DeleteLast();
// trig_visited.SetBit(ti);
auto & trig = trigs[ti]; auto & trig = trigs[ti];
trig.visited_pi = pi_new; trig.visited_pi = pi_new;
for(auto ei : Range(3)) for(auto ei : Range(3))
{ {
auto nb = GetNeighbour(ti, ei); auto nb = GetNeighbour(ti, ei);
if(nb==-1) if(nb==-1)
continue; continue;
// if(trig_visited.Test(nb))
// continue;
const auto & trig_nb = trigs[nb]; const auto & trig_nb = trigs[nb];
if (trig_nb.visited_pi == pi_new) if (trig_nb.visited_pi == pi_new)
continue; continue;
// trig_visited.SetBit(nb);
trig_nb.visited_pi = pi_new; trig_nb.visited_pi = pi_new;
bool is_intersecting = Dist2(newp, trig_nb.Center()) < trig_nb.Radius2()*(1+1e-12); bool is_intersecting = Dist2(newp, trig_nb.Center()) < trig_nb.Radius2()*(1+1e-12);
if(!is_intersecting) if(!is_intersecting)
{ {
const Point<2> p0 = P2(mesh[PointIndex (trig[(ei+1)%3])]); const Point<2> p0 = points[PointIndex (trig[(ei+1)%3])];
const Point<2> p1 = P2(mesh[PointIndex (trig[(ei+2)%3])]); const Point<2> p1 = points[PointIndex (trig[(ei+2)%3])];
const Point<2> p2 = P2(mesh[PointIndex (trig[ei])]); const Point<2> p2 = points[PointIndex (trig[ei])];
auto v = p1-p0; auto v = p1-p0;
Vec<2> n = {-v[1], v[0]}; Vec<2> n = {-v[1], v[0]};
@ -365,7 +283,7 @@ namespace netgen
for (int l = 0; l < edges.Size(); l++) for (int l = 0; l < edges.Size(); l++)
if (edges[l] == edge) if (edges[l] == edge)
{ {
edges.RemoveElement(l); edges.RemoveElement(l);
found = true; found = true;
break; break;
} }
@ -373,47 +291,56 @@ namespace netgen
edges.Append (edge); edges.Append (edge);
} }
} }
}
for (int j : intersecting) void DelaunayMesh::CalcWeights( PointIndex pi_new, std::map<PointIndex, double> & weights )
{ {
UnsetNeighbours(j); double eps = tree->GetTolerance();
trigs[j][0] = -1; weights.clear();
trigs[j][1] = -1; double sum = 0.0;
trigs[j][2] = -1; auto p = points[pi_new];
} auto pi_last = *points.Range().end()-3;
for(auto edge : edges)
for (auto edge : edges)
AppendTrig( edge[0], edge[1], pi_new );
for (int j : intersecting)
tree->DeleteElement (j);
static int counter=0;
if(0)
{
Mesh m;
m = mesh;
m.ClearSurfaceElements();
for (DelaunayTrig & trig : trigs)
{ {
if (trig[0] < 0) continue; for(PointIndex pi : {edge[0], edge[1]})
{
Vec<3> n = Cross (mesh[trig[1]]-mesh[trig[0]], if(pi>=pi_last)
mesh[trig[2]]-mesh[trig[0]]); continue;
if (n(2) < 0) Swap (trig[1], trig[2]); if(weights.count(pi))
continue;
Element2d el(trig[0], trig[1], trig[2]); double weight = 1.0/(eps+Dist(p, points[pi]));
el.SetIndex (1); sum += weight;
m.AddSurfaceElement (el); weights[pi] = weight;
}
} }
m.Save("meshes/mesh_"+ToString(counter++)+".vol.gz"); double isum = 1.0/sum;
} for(auto & [pi, weight] : weights)
weight *= isum;
}
} void DelaunayMesh::AddPoint( PointIndex pi_new, std::map<PointIndex, double> * weights )
{
static Timer t("AddPoint"); RegionTimer reg(t);
Array<DelaunayTrig> & GetElements() { return trigs; } CalcIntersecting(pi_new);
}; if(weights)
CalcWeights(pi_new, *weights);
for (int j : intersecting)
{
UnsetNeighbours(j);
trigs[j][0] = -1;
trigs[j][1] = -1;
trigs[j][2] = -1;
}
for (auto edge : edges)
AppendTrig( edge[0], edge[1], pi_new );
for (int j : intersecting)
tree->DeleteElement (j);
}
ostream & operator<< (ostream & ost, DelaunayTrig trig) ostream & operator<< (ostream & ost, DelaunayTrig trig)
{ {
@ -699,26 +626,25 @@ namespace netgen
Array<PointIndex, PointIndex> compress; Array<PointIndex, PointIndex> compress;
Array<PointIndex, PointIndex> icompress(mesh.Points().Size()); Array<PointIndex, PointIndex> icompress(mesh.Points().Size());
/* Array<Point<2>, PointIndex> temp_points;
for(auto pi : mesh.Points().Range())
if(add_point.Test(pi))
*/
for (PointIndex pi : addpoints) for (PointIndex pi : addpoints)
{ {
icompress[pi] = tempmesh.AddPoint(mesh[pi]); icompress[pi] = tempmesh.AddPoint(mesh[pi]);
compress.Append(pi); compress.Append(pi);
temp_points.Append(P2(mesh[pi]));
} }
for (PointIndex pi : Range(first_point_blockfill, last_point_blockfill)) for (PointIndex pi : Range(first_point_blockfill, last_point_blockfill))
{ {
icompress[pi] = tempmesh.AddPoint(mesh[pi]); icompress[pi] = tempmesh.AddPoint(mesh[pi]);
compress.Append(pi); compress.Append(pi);
temp_points.Append(P2(mesh[pi]));
} }
t3.Stop(); t3.Stop();
// DelaunayMesh adds surrounding trig (don't add the last 3 points to delaunay AGAIN! // DelaunayMesh adds surrounding trig (don't add the last 3 points to delaunay AGAIN!
auto tempmesh_points = tempmesh.Points().Range(); auto points_range = temp_points.Range();
DelaunayMesh dmesh(tempmesh, bbox); DelaunayMesh dmesh(temp_points, bbox);
timer_addpoints.Start(); timer_addpoints.Start();
@ -736,7 +662,7 @@ namespace netgen
// for (PointIndex pi : old_points) // for (PointIndex pi : old_points)
// mixed[pi] = PointIndex ( (prim * pi) % old_points.Size() + PointIndex::BASE ); // mixed[pi] = PointIndex ( (prim * pi) % old_points.Size() + PointIndex::BASE );
for (auto pi : tempmesh_points) for (auto pi : points_range)
dmesh.AddPoint(pi); dmesh.AddPoint(pi);
timer_addpoints.Stop(); timer_addpoints.Stop();

View File

@ -0,0 +1,72 @@
#include "meshing.hpp"
namespace netgen
{
static inline Point<2> P2( Point<3> p )
{
return {p[0], p[1]};
}
static inline Point<3> P3( Point<2> p )
{
return {p[0], p[1], 0};
}
class DelaunayTrig
{
PointIndex pnums[3];
Point<2> c;
public:
double r;
double rad2;
DelaunayTrig () = default;
DelaunayTrig (int p1, int p2, int p3)
{
pnums[0] = p1;
pnums[1] = p2;
pnums[2] = p3;
}
PointIndex & operator[] (int j) { return pnums[j]; }
const PointIndex & operator[] (int j) const { return pnums[j]; }
void CalcCenter (FlatArray<Point<2>, PointIndex> points);
Point<2> Center() const { return c; }
double Radius2() const { return rad2; }
Box<2> BoundingBox() const { return Box<2> (c-Vec<2>(r,r), c+Vec<2>(r,r)); }
mutable PointIndex visited_pi = -1;
};
class DelaunayMesh
{
ngcore::ClosedHashTable<INT<2>, INT<2>> edge_to_trig;
Array<DelaunayTrig> trigs;
unique_ptr<DelaunayTree<2>> tree;
Array<Point<2>, PointIndex> & points;
Array<int> closeels;
Array<int> intersecting;
Array<INT<2>> edges;
int GetNeighbour( int eli, int edge );
void SetNeighbour( int eli, int edge );
void UnsetNeighbours( int eli );
void AppendTrig( int pi0, int pi1, int pi2 );
public:
DelaunayMesh( Array<Point<2>, PointIndex> & points_, Box<2> box );
void CalcIntersecting( PointIndex pi_new );
void CalcWeights( PointIndex pi_new, std::map<PointIndex, double> & weights );
void AddPoint( PointIndex pi_new, std::map<PointIndex, double> * weights = nullptr );
Array<DelaunayTrig> & GetElements() { return trigs; }
};
} // namespace netgen