mirror of
https://github.com/NGSolve/netgen.git
synced 2024-11-15 18:38:33 +05:00
more
This commit is contained in:
parent
96488d0626
commit
d6a3d875cc
@ -47,42 +47,62 @@ struct GrowthVectorLimiter {
|
|||||||
Face GetMappedFace( SurfaceElementIndex sei );
|
Face GetMappedFace( SurfaceElementIndex sei );
|
||||||
Face GetMappedFace( SurfaceElementIndex sei, int face );
|
Face GetMappedFace( SurfaceElementIndex sei, int face );
|
||||||
|
|
||||||
auto GetSeg(PointIndex pi) {
|
auto GetSeg(PointIndex pi, double shift=1.) {
|
||||||
return std::array<Point<3>, 2>{mesh[pi], mesh[pi]+height*limits[pi]*growthvectors[pi]};
|
return std::array<Point<3>, 2>{mesh[pi], mesh[pi]+shift*height*limits[pi]*growthvectors[pi]};
|
||||||
}
|
}
|
||||||
auto GetTrig(SurfaceElementIndex sei, bool shift = false) {
|
auto GetTrig(SurfaceElementIndex sei, double shift = 0.0) {
|
||||||
auto sel = mesh[sei];
|
auto sel = mesh[sei];
|
||||||
auto trig = std::array<Point<3>, 3> { mesh[sel[0]], mesh[sel[1]], mesh[sel[2]] };
|
auto trig = std::array<Point<3>, 3> { mesh[sel[0]], mesh[sel[1]], mesh[sel[2]] };
|
||||||
if(shift)
|
if(shift)
|
||||||
for (auto i : Range(3))
|
for (auto i : Range(3))
|
||||||
trig[i] += height * limits[sel[i]] * growthvectors[sel[i]];
|
trig[i] += height * shift * limits[sel[i]] * growthvectors[sel[i]];
|
||||||
|
return trig;
|
||||||
|
}
|
||||||
|
auto GetSideTrig(SurfaceElementIndex sei, int index, double shift = 0.0) {
|
||||||
|
auto trig = GetTrig(sei, shift);
|
||||||
|
auto sel = mesh[sei];
|
||||||
|
auto index1 = (index+1)%3;
|
||||||
|
trig[index] = trig[index1];
|
||||||
|
trig[index] += height * shift * limits[sel[index1]] * growthvectors[sel[index1]];
|
||||||
return trig;
|
return trig;
|
||||||
}
|
}
|
||||||
|
|
||||||
string DebugPoint(PointIndex pi, string col, bool shift=false ) {
|
string DebugPoint(PointIndex pi, string col, bool shift=false ) {
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
|
stringstream pos;
|
||||||
auto p = mesh[pi];
|
auto p = mesh[pi];
|
||||||
auto p1 = mesh[pi]+height*growthvectors[pi];
|
auto p1 = mesh[pi]+height*growthvectors[pi];
|
||||||
// auto type = shift ? "lines" : "points";
|
pos << "\"position\": [" << p[0] << "," << p[1] << "," << p[2];
|
||||||
string type = "points";
|
|
||||||
ss << "{\"name\": \"line\", \"color\": \"" << col << "\", \"type\": \"" << type << "\", \"position\": [";
|
|
||||||
ss << p[0] << "," << p[1] << "," << p[2];
|
|
||||||
if(shift)
|
if(shift)
|
||||||
ss << "," << p1[0] << "," << p1[1] << "," << p1[2];
|
pos << "," << p1[0] << "," << p1[1] << "," << p1[2];
|
||||||
ss << "]}";
|
pos << "]}";
|
||||||
|
|
||||||
|
ss << R"({"name": "point", "color": ")" + col + R"(", "type": "points", )";
|
||||||
|
ss << pos.str();
|
||||||
|
if(shift) {
|
||||||
|
ss << R"(, {"name": "line", "color": ")" + col + R"(", "type": "lines", )";
|
||||||
|
ss << pos.str();
|
||||||
|
}
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugOut(PointIndex pi, SurfaceElementIndex sei) {
|
||||||
|
auto sel = mesh[sei];
|
||||||
|
auto trig = GetTrig(sei, 1.0);
|
||||||
|
debug << "[";
|
||||||
|
for(auto i : Range(3))
|
||||||
|
if(pi!=sel[i])
|
||||||
|
debug << DebugPoint(sel[i], "blue", true) << ',';
|
||||||
|
debug << DebugPoint(pi, "red", true);
|
||||||
|
debug << "]" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr double INTERSECTION_SAFETY = .99;
|
static constexpr double INTERSECTION_SAFETY = .99;
|
||||||
void LimitGrowthVector(PointIndex pi, SurfaceElementIndex sei, bool shift = false) {
|
void LimitGrowthVector(PointIndex pi, SurfaceElementIndex sei, double trig_shift, double seg_shift) {
|
||||||
auto intersection = isIntersectingTrig(pi, sei, shift);
|
if(trig_shift > 0) {
|
||||||
auto lam = intersection.lam0;
|
auto intersection = isIntersectingTrig(pi, sei, trig_shift);
|
||||||
|
if(!intersection) return;
|
||||||
if(!intersection) return;
|
double dshift = trig_shift;
|
||||||
|
|
||||||
if(shift) {
|
|
||||||
double dshift = 1.0;
|
|
||||||
while(intersection && dshift > 0.01 && dshift > intersection.lam0) {
|
while(intersection && dshift > 0.01 && dshift > intersection.lam0) {
|
||||||
dshift *= 0.9;
|
dshift *= 0.9;
|
||||||
intersection = isIntersectingTrig(pi, sei, dshift);
|
intersection = isIntersectingTrig(pi, sei, dshift);
|
||||||
@ -97,59 +117,148 @@ struct GrowthVectorLimiter {
|
|||||||
limits[sel[i]] *= dshift;
|
limits[sel[i]] *= dshift;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(intersection && lam > 0 && lam < 1.0/INTERSECTION_SAFETY) {
|
auto seg = GetSeg(pi, seg_shift);
|
||||||
|
auto trig = GetTrig(sei, 0.0);
|
||||||
|
// cout << mesh[sei] << " " << pi << endl;
|
||||||
|
auto intersection = isIntersectingTrig(seg, trig);
|
||||||
|
auto lam = intersection.lam0;
|
||||||
|
// cout << "lam " << intersection.is_intersecting <<"\t" << lam << endl;
|
||||||
|
if(intersection) {
|
||||||
// check with original surface elements
|
// check with original surface elements
|
||||||
limits[pi] = min(limits[pi], INTERSECTION_SAFETY*intersection.lam0);
|
limits[pi] = min(limits[pi], seg_shift*0.45*INTERSECTION_SAFETY*lam);
|
||||||
cout << "set limit " << pi << '\t' << limits[pi] << endl;
|
// cout << "set limit " << pi << '\t' << limits[pi] << endl;
|
||||||
auto sel = mesh[sei];
|
if(limits[pi] < 0.1) DebugOut(pi, sei);
|
||||||
debug << "[";
|
|
||||||
for(auto i : Range(3))
|
|
||||||
debug << DebugPoint(sel[i], "black", false) << ',';
|
|
||||||
debug << DebugPoint(pi, "red", true);
|
|
||||||
debug << "]" << endl;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// cout << "lam " << lam << endl;
|
||||||
|
// if (lam > 0 && lam < 2./INTERSECTION_SAFETY) {
|
||||||
|
// limits[pi] = min(limits[pi], 0.45*INTERSECTION_SAFETY*lam);
|
||||||
|
// cout << "limit by 2 safety " << limits[pi] << endl;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// check with shifted surface elements using growthvectors
|
// check with shifted surface elements using growthvectors
|
||||||
return;
|
// return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LimitSelfIntersection () {
|
||||||
|
// check for self-intersection within new elements (prisms/hexes)
|
||||||
|
auto isIntersecting = [&](SurfaceElementIndex sei, double shift) {
|
||||||
|
const auto sel = mesh[sei];
|
||||||
|
auto np = sel.GetNP();
|
||||||
|
for(auto i : Range(np)) {
|
||||||
|
auto seg = GetSeg(sel[i], shift);
|
||||||
|
for(auto fi : Range(np-2)) {
|
||||||
|
auto trig = GetSideTrig(sei, i+fi, 1.0);
|
||||||
|
if(isIntersectingPlane(seg, trig)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto equalizeLimits = [&](SurfaceElementIndex sei) {
|
||||||
|
const auto sel = mesh[sei];
|
||||||
|
auto np = sel.GetNP();
|
||||||
|
double max_limit = 0;
|
||||||
|
double min_limit = 1e99;
|
||||||
|
for(auto i : Range(np)) {
|
||||||
|
max_limit = max(max_limit, limits[sel[i]]);
|
||||||
|
min_limit = min(min_limit, limits[sel[i]]);
|
||||||
|
}
|
||||||
|
// equalize
|
||||||
|
if(max_limit/min_limit > 1.2) {
|
||||||
|
max_limit = min_limit * 1.2;
|
||||||
|
for(auto i : Range(np))
|
||||||
|
limits[sel[i]] = min(limits[sel[i]], max_limit);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for(SurfaceElementIndex sei : mesh.SurfaceElements().Range()) {
|
||||||
|
auto sel = mesh[sei];
|
||||||
|
const auto& fd = mesh.GetFaceDescriptor(sel.GetIndex());
|
||||||
|
if(!changed_domains.Test(fd.DomainIn()) &&
|
||||||
|
!changed_domains.Test(fd.DomainOut()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ArrayMem<double, 4> ori_limits;
|
||||||
|
ori_limits.SetSize(3);
|
||||||
|
auto np = sel.GetNP();
|
||||||
|
for(auto i : Range(np))
|
||||||
|
ori_limits[i] = limits[sel[i]];
|
||||||
|
|
||||||
|
equalizeLimits(sei);
|
||||||
|
|
||||||
|
double shift = 1.0;
|
||||||
|
double safety = 1.1;
|
||||||
|
while(shift>0.01 && isIntersecting(sei, shift*safety)) {
|
||||||
|
double max_limit = 0;
|
||||||
|
for(auto i : Range(np))
|
||||||
|
max_limit = max(max_limit, limits[sel[i]]);
|
||||||
|
for(auto i : Range(np))
|
||||||
|
if(max_limit == limits[sel[i]])
|
||||||
|
limits[sel[i]] *= 0.9;
|
||||||
|
if(max_limit < 0.01) {
|
||||||
|
cout << "self intersection" << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(shift < 1) {
|
||||||
|
if(shift < 0.3) {
|
||||||
|
cout << "self intersection " << sel << "\t" << shift << endl;
|
||||||
|
cout << "\t" << limits[sel[0]] << '\t' << limits[sel[1]] << '\t' << limits[sel[2]] << endl;
|
||||||
|
}
|
||||||
|
for(auto pi : sel.PNums())
|
||||||
|
limits[pi] *= INTERSECTION_SAFETY*shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cout <<
|
||||||
|
// auto np = sel.GetNP();
|
||||||
|
// // check if a new edge intesects the plane of any opposing face
|
||||||
|
// for(auto i : Range(np)) {
|
||||||
|
// auto seg = GetSeg(sel[i]);
|
||||||
|
// for(auto fi : Range(np-2)) {
|
||||||
|
// auto trig = GetSideTrig(sei, i+fi, 1.0);
|
||||||
|
// auto intersection = isIntersectingPlane(seg, trig);
|
||||||
|
// if(intersection) {
|
||||||
|
// if(intersection.lam0 < 0.2) {
|
||||||
|
// DebugOut(sel[i], sei);
|
||||||
|
// }
|
||||||
|
// limits[sel[i]] *= INTERSECTION_SAFETY*intersection.lam0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks if a segment is intersecting a plane, spanned by three points, lam will be set s.t. p_intersect = seg[0] + lam * (seg[1]-seg[0])
|
// checks if a segment is intersecting a plane, spanned by three points, lam will be set s.t. p_intersect = seg[0] + lam * (seg[1]-seg[0])
|
||||||
Intersection_ isIntersectingPlane ( PointIndex pi, SurfaceElementIndex sei, double shift = 0.0 )
|
Intersection_ isIntersectingPlane ( std::array<Point<3>, 2> seg, std::array<Point<3>, 3> trig )
|
||||||
{
|
{
|
||||||
auto sel = mesh[sei];
|
|
||||||
// TODO: quads
|
|
||||||
|
|
||||||
auto seg = GetSeg(pi);
|
|
||||||
auto trig = GetTrig(sei, shift);
|
|
||||||
auto t1 = trig[1]-trig[0];
|
auto t1 = trig[1]-trig[0];
|
||||||
auto t2 = trig[2]-trig[0];
|
auto t2 = trig[2]-trig[0];
|
||||||
auto n = Cross(trig[1]-trig[0], trig[2]-trig[0]);
|
auto n = Cross(trig[1]-trig[0], trig[2]-trig[0]);
|
||||||
auto v0n = (seg[0]-trig[0])*n;
|
auto v0n = (seg[0]-trig[0])*n;
|
||||||
auto v1n = (seg[1]-trig[0])*n;
|
auto v1n = (seg[1]-trig[0])*n;
|
||||||
if(v0n * v1n >= 0)
|
|
||||||
return {false};
|
|
||||||
|
|
||||||
Intersection_ intersection;
|
Intersection_ intersection;
|
||||||
intersection.lam0 = -v0n/(v1n-v0n);
|
intersection.lam0 = -v0n/(v1n-v0n);
|
||||||
if(intersection.lam0 < -1e-8 || intersection.lam0>1+1e-8)
|
// cout << "lam0 " << intersection.lam0 << ", " << v0n << ", " << v1n << endl;
|
||||||
return intersection;
|
|
||||||
|
|
||||||
intersection.is_intersecting = true;
|
|
||||||
intersection.p = seg[0] + intersection.lam0*(seg[1]-seg[0]);
|
intersection.p = seg[0] + intersection.lam0*(seg[1]-seg[0]);
|
||||||
|
intersection.is_intersecting = (v0n * v1n < 0) && (intersection.lam0 > -1e-8) && (intersection.lam0<1+1e-8);
|
||||||
|
|
||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intersection_ isIntersectingTrig ( PointIndex pi, SurfaceElementIndex sei, double shift=0.0)
|
Intersection_ isIntersectingPlane ( PointIndex pi, SurfaceElementIndex sei, double shift = 0.0 )
|
||||||
{
|
{
|
||||||
auto intersection = isIntersectingPlane(pi, sei, shift);
|
return isIntersectingPlane(GetSeg(pi), GetTrig(sei, shift));
|
||||||
|
}
|
||||||
|
|
||||||
|
Intersection_ isIntersectingTrig ( std::array<Point<3>, 2> seg, std::array<Point<3>, 3> trig )
|
||||||
|
{
|
||||||
|
auto intersection = isIntersectingPlane(seg, trig);
|
||||||
if(!intersection)
|
if(!intersection)
|
||||||
return intersection;
|
return intersection;
|
||||||
|
|
||||||
auto seg = GetSeg(pi);
|
|
||||||
auto trig = GetTrig(sei, shift);
|
|
||||||
auto p = seg[0] + intersection.lam0*(seg[1]-seg[0]) - trig[0];
|
auto p = seg[0] + intersection.lam0*(seg[1]-seg[0]) - trig[0];
|
||||||
|
|
||||||
Vec3d col1 = trig[1]-trig[0];
|
Vec3d col1 = trig[1]-trig[0];
|
||||||
@ -175,12 +284,17 @@ struct GrowthVectorLimiter {
|
|||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildSearchTree(bool shift) {
|
Intersection_ isIntersectingTrig ( PointIndex pi, SurfaceElementIndex sei, double shift=0.0)
|
||||||
|
{
|
||||||
|
return isIntersectingTrig(GetSeg(pi), GetTrig(sei, shift));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildSearchTree(double trig_shift) {
|
||||||
Box<3> bbox(Box<3>::EMPTY_BOX);
|
Box<3> bbox(Box<3>::EMPTY_BOX);
|
||||||
for(auto pi : mesh.Points().Range())
|
for(auto pi : mesh.Points().Range())
|
||||||
{
|
{
|
||||||
bbox.Add(mesh[pi]);
|
bbox.Add(mesh[pi]);
|
||||||
bbox.Add(mesh[pi]+limits[pi]*height*growthvectors[pi]);
|
bbox.Add(mesh[pi]+max(trig_shift, 1.)*limits[pi]*height*growthvectors[pi]);
|
||||||
}
|
}
|
||||||
|
|
||||||
tree = make_unique<BoxTree<3>>(bbox);
|
tree = make_unique<BoxTree<3>>(bbox);
|
||||||
@ -196,23 +310,23 @@ struct GrowthVectorLimiter {
|
|||||||
for(auto pi : sel.PNums())
|
for(auto pi : sel.PNums())
|
||||||
box.Add(mesh[pi]);
|
box.Add(mesh[pi]);
|
||||||
// also add moved points to bounding box
|
// also add moved points to bounding box
|
||||||
if(shift && params.surfid.Contains(sel.GetIndex()))
|
if(trig_shift >0 && params.surfid.Contains(sel.GetIndex()))
|
||||||
for(auto pi : sel.PNums())
|
for(auto pi : sel.PNums())
|
||||||
box.Add(mesh[pi]+limits[pi]*height*growthvectors[pi]);
|
box.Add(mesh[pi]+trig_shift*limits[pi]*height*growthvectors[pi]);
|
||||||
tree->Insert(box, sei);
|
tree->Insert(box, sei);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TFunc>
|
template<typename TFunc>
|
||||||
void FindTreeIntersections( bool shift, TFunc f ) {
|
void FindTreeIntersections( double trig_shift, double seg_shift, TFunc f) {
|
||||||
BuildSearchTree(shift);
|
BuildSearchTree(trig_shift);
|
||||||
for(auto pi : mesh.Points().Range()) {
|
for(auto pi : mesh.Points().Range()) {
|
||||||
if(mesh[pi].Type() == INNERPOINT)
|
if(mesh[pi].Type() == INNERPOINT)
|
||||||
continue;
|
continue;
|
||||||
if(growthvectors[pi].Length2() == 0.0)
|
if(growthvectors[pi].Length2() == 0.0)
|
||||||
continue;
|
continue;
|
||||||
Box<3> box(Box<3>::EMPTY_BOX);
|
Box<3> box(Box<3>::EMPTY_BOX);
|
||||||
auto seg = GetSeg(pi);
|
auto seg = GetSeg(pi, seg_shift);
|
||||||
box.Add(seg[0]);
|
box.Add(seg[0]);
|
||||||
box.Add(seg[1]);
|
box.Add(seg[1]);
|
||||||
tree->GetFirstIntersecting(box.PMin(), box.PMax(), [&](SurfaceElementIndex sei) {
|
tree->GetFirstIntersecting(box.PMin(), box.PMax(), [&](SurfaceElementIndex sei) {
|
||||||
@ -276,21 +390,26 @@ struct GrowthVectorLimiter {
|
|||||||
GrowthVectorLimiter limiter(mesh, params, limits, growthvectors, height);
|
GrowthVectorLimiter limiter(mesh, params, limits, growthvectors, height);
|
||||||
|
|
||||||
// limit to not intersect with other surface elements
|
// limit to not intersect with other surface elements
|
||||||
bool shift = false;
|
double trig_shift = 0;
|
||||||
limiter.FindTreeIntersections(shift, [&] (PointIndex pi, SurfaceElementIndex sei) {
|
double seg_shift = 2.1;
|
||||||
limiter.LimitGrowthVector(pi, sei, shift);
|
limiter.FindTreeIntersections(trig_shift, seg_shift, [&] (PointIndex pi, SurfaceElementIndex sei) {
|
||||||
|
limiter.LimitGrowthVector(pi, sei, trig_shift, seg_shift);
|
||||||
});
|
});
|
||||||
|
|
||||||
for(auto i : Range(growthvectors))
|
limiter.LimitSelfIntersection();
|
||||||
growthvectors[i] *= limits[i];
|
// for(auto i : Range(growthvectors))
|
||||||
limits = 1.0;
|
// growthvectors[i] *= limits[i];
|
||||||
|
// limits = 1.0;
|
||||||
|
|
||||||
// now limit again with shifted surace elements
|
// now limit again with shifted surace elements
|
||||||
shift = true;
|
trig_shift = 1.0
|
||||||
limiter.FindTreeIntersections(shift, [&] (PointIndex pi, SurfaceElementIndex sei) {
|
seg_shift = 1.0
|
||||||
limiter.LimitGrowthVector(pi, sei, shift);
|
limiter.FindTreeIntersections(trig_shift, seg_shift, [&] (PointIndex pi, SurfaceElementIndex sei) {
|
||||||
|
limiter.LimitGrowthVector(pi, sei, trig_shift, seg_shift);
|
||||||
});
|
});
|
||||||
cout << limits << endl;
|
// for (auto i : Range(limits))
|
||||||
|
// if(limits[i] < 1.0)
|
||||||
|
// cout << i << ": " << limits[i] << endl;
|
||||||
|
|
||||||
for(auto i : Range(growthvectors))
|
for(auto i : Range(growthvectors))
|
||||||
growthvectors[i] *= limits[i];
|
growthvectors[i] *= limits[i];
|
||||||
@ -1676,7 +1795,7 @@ struct GrowthVectorLimiter {
|
|||||||
|
|
||||||
auto in_surface_direction = ProjectGrowthVectorsOnSurface();
|
auto in_surface_direction = ProjectGrowthVectorsOnSurface();
|
||||||
|
|
||||||
// InterpolateGrowthVectors();
|
InterpolateGrowthVectors();
|
||||||
|
|
||||||
auto fout = ofstream("growthvectors.txt");
|
auto fout = ofstream("growthvectors.txt");
|
||||||
for (auto pi : Range(mesh.Points()))
|
for (auto pi : Range(mesh.Points()))
|
||||||
|
Loading…
Reference in New Issue
Block a user