Path: blob/devel/ElmerGUI/netgen/libsrc/meshing/improve2.cpp
3206 views
#include <mystdlib.h>12#include "meshing.hpp"3#include <opti.hpp>45#ifndef SMALLLIB6//#ifndef NOTCL7//#include <visual.hpp>8//#endif9#endif1011namespace netgen12{1314class Neighbour15{16int nr[3];17int orient[3];1819public:20Neighbour () { nr[0] = nr[1] = nr[2] = -1; orient[0] = orient[1] = orient[2] = 0; }2122void SetNr (int side, int anr) { nr[side-1] = anr; }23int GetNr (int side) { return nr[side-1]; }2425void SetOrientation (int side, int aorient) { orient[side-1] = aorient; }26int GetOrientation (int side) { return orient[side-1]; }27};2829303132class trionedge33{34public:35int tnr;36int sidenr;3738trionedge () { tnr = 0; sidenr = 0; }39trionedge (int atnr, int asidenr)40{ tnr = atnr; sidenr = asidenr; }41};4243444546void MeshOptimize2d :: EdgeSwapping (Mesh & mesh, int usemetric)47{48// return;4950if (!faceindex)51{52if (usemetric)53PrintMessage (3, "Edgeswapping, metric");54else55PrintMessage (3, "Edgeswapping, topological");5657for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++)58{59EdgeSwapping (mesh, usemetric);6061if (multithread.terminate)62throw NgException ("Meshing stopped");63}6465faceindex = 0;66mesh.CalcSurfacesOfNode();67return;68}697071static int timer = NgProfiler::CreateTimer ("EdgeSwapping 2D");72NgProfiler::RegionTimer reg1 (timer);737475int i, i2, j, j2;76bool should;77PointIndex pi;7879ARRAY<SurfaceElementIndex> seia;80mesh.GetSurfaceElementsOfFace (faceindex, seia);8182for (i = 0; i < seia.Size(); i++)83if (mesh[seia[i]].GetNP() != 3)84{85GenericImprove (mesh);86return;87}8889int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr();9091ARRAY<Neighbour> neighbors(mesh.GetNSE());92INDEX_2_HASHTABLE<trionedge> other(seia.Size() + 2);939495ARRAY<char> swapped(mesh.GetNSE());96ARRAY<int,PointIndex::BASE> pdef(mesh.GetNP());97ARRAY<double,PointIndex::BASE> pangle(mesh.GetNP());9899SurfaceElementIndex t1, t2;100int o1, o2;101102PointIndex pi1, pi2, pi3, pi4;103PointGeomInfo gi1, gi2, gi3, gi4;104105106int nswaps = 0;107int e, done;108double d;109Vec3d nv1, nv2;110double horder;111double loch(-1);112static const double minangle[] = { 0, 1.481, 2.565, 3.627, 4.683, 5.736, 7, 9 };113114pangle = 0;115116for (i = 0; i < seia.Size(); i++)117{118const Element2d & sel = mesh[seia[i]];119for (j = 0; j < 3; j++)120{121POINTTYPE typ = mesh[sel[j]].Type();122if (typ == FIXEDPOINT || typ == EDGEPOINT)123{124pangle[sel[j]] +=125Angle (mesh[sel[(j+1)%3]] - mesh[sel[j]],126mesh[sel[(j+2)%3]] - mesh[sel[j]]);127}128}129}130131for (pi = PointIndex::BASE;132pi < mesh.GetNP()+PointIndex::BASE; pi++)133{134if (mesh[pi].Type() == INNERPOINT || mesh[pi].Type() == SURFACEPOINT)135pdef[pi] = -6;136else137for (j = 0; j < 8; j++)138if (pangle[pi] >= minangle[j])139pdef[pi] = -1-j;140}141142for (i = 0; i < seia.Size(); i++)143{144const Element2d & sel = mesh[seia[i]];145for (j = 0; j < 3; j++)146pdef[sel[j]]++;147}148149for (i = 0; i < seia.Size(); i++)150{151//const Element2d & sel = mesh[seia[i]];152for (j = 0; j < 3; j++)153{154neighbors[seia[i]].SetNr (j+1, -1);155neighbors[seia[i]].SetOrientation (j+1, 0);156}157}158159/*160ARRAY<Vec3d> normals(mesh.GetNP());161for (i = 1; i <= mesh.GetNSE(); i++)162{163Element2d & hel = mesh.SurfaceElement(i);164if (hel.GetIndex() == faceindex)165for (k = 1; k <= 3; k++)166{167int pi = hel.PNum(k);168SelectSurfaceOfPoint (mesh.Point(pi), hel.GeomInfoPi(k));169int surfi = mesh.GetFaceDescriptor(faceindex).SurfNr();170GetNormalVector (surfi, mesh.Point(pi), normals.Elem(pi));171normals.Elem(pi) /= normals.Elem(pi).Length();172}173}174*/175176177for (i = 0; i < seia.Size(); i++)178{179const Element2d & sel = mesh[seia[i]];180181for (j = 1; j <= 3; j++)182{183pi1 = sel.PNumMod(j+1);184pi2 = sel.PNumMod(j+2);185186loch = mesh.GetH(mesh[pi1]);187188INDEX_2 edge(pi1, pi2);189edge.Sort();190191if (mesh.IsSegment (pi1, pi2))192continue;193194/*195if (segments.Used (edge))196continue;197*/198INDEX_2 ii2 (pi1, pi2);199if (other.Used (ii2))200{201// INDEX_2 i2s(ii2);202// i2s.Sort();203204i2 = other.Get(ii2).tnr;205j2 = other.Get(ii2).sidenr;206207neighbors[seia[i]].SetNr (j, i2);208neighbors[seia[i]].SetOrientation (j, j2);209neighbors[i2].SetNr (j2, seia[i]);210neighbors[i2].SetOrientation (j2, j);211}212else213{214other.Set (INDEX_2 (pi2, pi1), trionedge (seia[i], j));215}216}217}218219for (i = 0; i < seia.Size(); i++)220swapped[seia[i]] = 0;221222223int t = 4;224done = 0;225while (!done && t >= 2)226{227for (i = 0; i < seia.Size(); i++)228{229t1 = seia[i];230231if (mesh[t1].IsDeleted())232continue;233234if (mesh[t1].GetIndex() != faceindex)235continue;236237if (multithread.terminate)238throw NgException ("Meshing stopped");239240for (o1 = 1; o1 <= 3; o1++)241{242t2 = neighbors[t1].GetNr (o1);243o2 = neighbors[t1].GetOrientation (o1);244245if (t2 == -1) continue;246if (swapped[t1] || swapped[t2]) continue;247248249pi1 = mesh[t1].PNumMod(o1+1);250pi2 = mesh[t1].PNumMod(o1+2);251pi3 = mesh[t1].PNumMod(o1);252pi4 = mesh[t2].PNumMod(o2);253254gi1 = mesh[t1].GeomInfoPiMod(o1+1);255gi2 = mesh[t1].GeomInfoPiMod(o1+2);256gi3 = mesh[t1].GeomInfoPiMod(o1);257gi4 = mesh[t2].GeomInfoPiMod(o2);258259bool allowswap = true;260261Vec3d auxvec1,auxvec2;262263auxvec1 = mesh.Point(pi3)-mesh.Point(pi4);264auxvec2 = mesh.Point(pi1)-mesh.Point(pi4);265allowswap = allowswap && fabs(1.-(auxvec1*auxvec2)/(auxvec1.Length()*auxvec2.Length())) > 1e-4;266267if(!allowswap)268continue;269270// normal of new271nv1 = Cross (auxvec1,272auxvec2);273274auxvec1 = mesh.Point(pi4)-mesh.Point(pi3);275auxvec2 = mesh.Point(pi2)-mesh.Point(pi3);276allowswap = allowswap && fabs(1.-(auxvec1*auxvec2)/(auxvec1.Length()*auxvec2.Length())) > 1e-4;277278279if(!allowswap)280continue;281282nv2 = Cross (auxvec1,283auxvec2);284285286// normals of original287Vec3d nv3, nv4;288nv3 = Cross (mesh.Point(pi1)-mesh.Point(pi4),289mesh.Point(pi2)-mesh.Point(pi4));290nv4 = Cross (mesh.Point(pi2)-mesh.Point(pi3),291mesh.Point(pi1)-mesh.Point(pi3));292293nv3 *= -1;294nv4 *= -1;295nv3.Normalize();296nv4.Normalize();297298nv1.Normalize();299nv2.Normalize();300301Vec<3> nvp3, nvp4;302SelectSurfaceOfPoint (mesh.Point(pi3), gi3);303GetNormalVector (surfnr, mesh.Point(pi3), gi3, nvp3);304305nvp3.Normalize();306307SelectSurfaceOfPoint (mesh.Point(pi4), gi4);308GetNormalVector (surfnr, mesh.Point(pi4), gi4, nvp4);309310nvp4.Normalize();311312313314double critval = cos (M_PI / 6); // 30 degree315allowswap = allowswap &&316(nv1 * nvp3 > critval) &&317(nv1 * nvp4 > critval) &&318(nv2 * nvp3 > critval) &&319(nv2 * nvp4 > critval) &&320(nvp3 * nv3 > critval) &&321(nvp4 * nv4 > critval);322323324horder = Dist (mesh.Point(pi1), mesh.Point(pi2));325326if ( // nv1 * nv2 >= 0 &&327nv1.Length() > 1e-3 * horder * horder &&328nv2.Length() > 1e-3 * horder * horder &&329allowswap )330{331if (!usemetric)332{333e = pdef[pi1] + pdef[pi2] - pdef[pi3] - pdef[pi4];334d =335Dist2 (mesh.Point(pi1), mesh.Point(pi2)) -336Dist2 (mesh.Point(pi3), mesh.Point(pi4));337338should = e >= t && (e > 2 || d > 0);339}340else341{342should =343CalcTriangleBadness (mesh.Point(pi4), mesh.Point(pi3), mesh.Point(pi1),344metricweight, loch) +345CalcTriangleBadness (mesh.Point(pi3), mesh.Point(pi4), mesh.Point(pi2),346metricweight, loch) <347CalcTriangleBadness (mesh.Point(pi1), mesh.Point(pi2), mesh.Point(pi3),348metricweight, loch) +349CalcTriangleBadness (mesh.Point(pi2), mesh.Point(pi1), mesh.Point(pi4),350metricweight, loch);351352}353354if (allowswap)355{356Element2d sw1 (pi4, pi3, pi1);357Element2d sw2 (pi3, pi4, pi2);358359int legal1 =360mesh.LegalTrig (mesh.SurfaceElement (t1)) +361mesh.LegalTrig (mesh.SurfaceElement (t2));362int legal2 =363mesh.LegalTrig (sw1) + mesh.LegalTrig (sw2);364365if (legal1 < legal2) should = 1;366if (legal2 < legal1) should = 0;367}368369if (should)370{371// do swapping !372373// cout << "swap " << endl;374375nswaps ++;376377// testout << "nv1 = " << nv1 << " nv2 = " << nv2 << endl;378379380done = 1;381382mesh[t1].PNum(1) = pi1;383mesh[t1].PNum(2) = pi4;384mesh[t1].PNum(3) = pi3;385386mesh[t2].PNum(1) = pi2;387mesh[t2].PNum(2) = pi3;388mesh[t2].PNum(3) = pi4;389390mesh[t1].GeomInfoPi(1) = gi1;391mesh[t1].GeomInfoPi(2) = gi4;392mesh[t1].GeomInfoPi(3) = gi3;393394mesh[t2].GeomInfoPi(1) = gi2;395mesh[t2].GeomInfoPi(2) = gi3;396mesh[t2].GeomInfoPi(3) = gi4;397398pdef[pi1]--;399pdef[pi2]--;400pdef[pi3]++;401pdef[pi4]++;402403swapped[t1] = 1;404swapped[t2] = 1;405}406}407}408}409t--;410}411412mesh.SetNextTimeStamp();413}414415416417418419420421422void MeshOptimize2d :: CombineImprove (Mesh & mesh)423{424if (!faceindex)425{426PrintMessage (3, "Combine improve");427428for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++)429{430CombineImprove (mesh);431432if (multithread.terminate)433throw NgException ("Meshing stopped");434}435faceindex = 0;436return;437}438439440static int timer = NgProfiler::CreateTimer ("Combineimprove 2D");441NgProfiler::RegionTimer reg (timer);442443444445int i, j, k, l;446PointIndex pi;447SurfaceElementIndex sei;448449450ARRAY<SurfaceElementIndex> seia;451mesh.GetSurfaceElementsOfFace (faceindex, seia);452453454for (i = 0; i < seia.Size(); i++)455if (mesh[seia[i]].GetNP() != 3)456return;457458459460int surfnr = 0;461if (faceindex)462surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr();463464465PointIndex pi1, pi2;466MeshPoint p1, p2, pnew;467double bad1, bad2;468Vec<3> nv;469470int np = mesh.GetNP();471//int nse = mesh.GetNSE();472473TABLE<SurfaceElementIndex,PointIndex::BASE> elementsonnode(np);474ARRAY<SurfaceElementIndex> hasonepi, hasbothpi;475476for (i = 0; i < seia.Size(); i++)477{478Element2d & el = mesh[seia[i]];479for (j = 0; j < el.GetNP(); j++)480{481elementsonnode.Add (el[j], seia[i]);482}483}484485486ARRAY<bool,PointIndex::BASE> fixed(np);487fixed = false;488489SegmentIndex si;490for (si = 0; si < mesh.GetNSeg(); si++)491{492INDEX_2 i2(mesh[si].p1, mesh[si].p2);493fixed[i2.I1()] = true;494fixed[i2.I2()] = true;495}496497for(i = 0; i<mesh.LockedPoints().Size(); i++)498fixed[mesh.LockedPoints()[i]] = true;499500501ARRAY<Vec<3>,PointIndex::BASE> normals(np);502503for (pi = PointIndex::BASE;504pi < np + PointIndex::BASE; pi++)505{506if (elementsonnode[pi].Size())507{508Element2d & hel = mesh[elementsonnode[pi][0]];509for (k = 0; k < 3; k++)510if (hel[k] == pi)511{512SelectSurfaceOfPoint (mesh[pi], hel.GeomInfoPi(k+1));513GetNormalVector (surfnr, mesh[pi], hel.GeomInfoPi(k+1), normals[pi]);514break;515}516if (k == 3)517{518cerr << "Neuer Fehler von Joachim, code 17121" << endl;519}520}521}522523524for (i = 0; i < seia.Size(); i++)525{526527sei = seia[i];528Element2d & elem = mesh[sei];529if (elem.IsDeleted()) continue;530531for (j = 0; j < 3; j++)532{533pi1 = elem[j];534pi2 = elem[(j+1) % 3];535536if (pi1 < PointIndex::BASE ||537pi2 < PointIndex::BASE)538continue;539540/*541INDEX_2 i2(pi1, pi2);542i2.Sort();543if (segmentht.Used(i2))544continue;545*/546547bool debugflag = 0;548549if (debugflag)550{551(*testout) << "Combineimprove, face = " << faceindex552<< "pi1 = " << pi1 << " pi2 = " << pi2 << endl;553}554555/*556// save version:557if (fixed.Get(pi1) || fixed.Get(pi2))558continue;559if (pi2 < pi1) swap (pi1, pi2);560*/561562// more general563if (fixed[pi2])564Swap (pi1, pi2);565566if (fixed[pi2])567continue;568569double loch = mesh.GetH (mesh[pi1]);570571INDEX_2 si2 (pi1, pi2);572si2.Sort();573574/*575if (edgetested.Used (si2))576continue;577edgetested.Set (si2, 1);578*/579580hasonepi.SetSize(0);581hasbothpi.SetSize(0);582583for (k = 0; k < elementsonnode[pi1].Size(); k++)584{585const Element2d & el2 = mesh[elementsonnode[pi1][k]];586587if (el2.IsDeleted()) continue;588589if (el2[0] == pi2 || el2[1] == pi2 || el2[2] == pi2)590{591hasbothpi.Append (elementsonnode[pi1][k]);592nv = Cross (Vec3d (mesh[el2[0]], mesh[el2[1]]),593Vec3d (mesh[el2[0]], mesh[el2[2]]));594}595else596{597hasonepi.Append (elementsonnode[pi1][k]);598}599}600601602Element2d & hel = mesh[hasbothpi[0]];603for (k = 0; k < 3; k++)604if (hel[k] == pi1)605{606SelectSurfaceOfPoint (mesh[pi1],607hel.GeomInfoPi(k+1));608GetNormalVector (surfnr, mesh[pi1], hel.GeomInfoPi(k+1), nv);609break;610}611if (k == 3)612{613cerr << "Neuer Fehler von Joachim, code 32434" << endl;614}615616617// nv = normals.Get(pi1);618619620621for (k = 0; k < elementsonnode[pi2].Size(); k++)622{623const Element2d & el2 = mesh[elementsonnode[pi2][k]];624if (el2.IsDeleted()) continue;625626if (el2[0] == pi1 || el2[1] == pi1 || el2[2] == pi1)627;628else629hasonepi.Append (elementsonnode[pi2][k]);630}631632bad1 = 0;633int illegal1 = 0, illegal2 = 0;634for (k = 0; k < hasonepi.Size(); k++)635{636const Element2d & el = mesh[hasonepi[k]];637bad1 += CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]],638nv, -1, loch);639illegal1 += 1-mesh.LegalTrig(el);640}641642for (k = 0; k < hasbothpi.Size(); k++)643{644const Element2d & el = mesh[hasbothpi[k]];645bad1 += CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]],646nv, -1, loch);647illegal1 += 1-mesh.LegalTrig(el);648}649bad1 /= (hasonepi.Size()+hasbothpi.Size());650651p1 = mesh[pi1];652p2 = mesh[pi2];653654pnew = p1;655mesh[pi1] = pnew;656mesh[pi2] = pnew;657658bad2 = 0;659for (k = 0; k < hasonepi.Size(); k++)660{661Element2d & el = mesh[hasonepi[k]];662double err =663CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]],664nv, -1, loch);665bad2 += err;666667Vec<3> hnv = Cross (Vec3d (mesh[el[0]],668mesh[el[1]]),669Vec3d (mesh[el[0]],670mesh[el[2]]));671if (hnv * nv < 0)672bad2 += 1e10;673674for (l = 0; l < 3; l++)675if ( (normals[el[l]] * nv) < 0.5)676bad2 += 1e10;677678illegal2 += 1-mesh.LegalTrig(el);679}680bad2 /= hasonepi.Size();681682mesh[pi1] = p1;683mesh[pi2] = p2;684685686if (debugflag)687{688(*testout) << "bad1 = " << bad1 << ", bad2 = " << bad2 << endl;689}690691692bool should = (bad2 < bad1 && bad2 < 1e4);693if (bad2 < 1e4)694{695if (illegal1 > illegal2) should = 1;696if (illegal2 > illegal1) should = 0;697}698699700if (should)701{702// (*testout) << "combine !" << endl;703// (*testout) << "bad1 = " << bad1 << ", bad2 = " << bad2 << endl;704705706mesh[pi1] = pnew;707PointGeomInfo gi;708bool gi_set(false);709710711Element2d *el1p(NULL);712l=0;713while(mesh[elementsonnode[pi1][l]].IsDeleted() && l<elementsonnode.EntrySize(pi1)) l++;714if(l<elementsonnode.EntrySize(pi1))715el1p = &mesh[elementsonnode[pi1][l]];716else717cerr << "OOPS!" << endl;718719for (l = 0; l < el1p->GetNP(); l++)720if ((*el1p)[l] == pi1)721{722gi = el1p->GeomInfoPi (l+1);723gi_set = true;724}725726// (*testout) << "Connect point " << pi2 << " to " << pi1 << "\n";727for (k = 0; k < elementsonnode[pi2].Size(); k++)728{729Element2d & el = mesh[elementsonnode[pi2][k]];730if(el.IsDeleted()) continue;731elementsonnode.Add (pi1, elementsonnode[pi2][k]);732733bool haspi1 = 0;734for (l = 0; l < el.GetNP(); l++)735if (el[l] == pi1)736haspi1 = 1;737if (haspi1) continue;738739for (l = 0; l < el.GetNP(); l++)740{741if (el[l] == pi2)742{743el[l] = pi1;744el.GeomInfoPi (l+1) = gi;745}746747fixed[el[l]] = true;748}749}750751/*752for (k = 0; k < hasbothpi.Size(); k++)753{754cout << mesh[hasbothpi[k]] << endl;755for (l = 0; l < 3; l++)756cout << mesh[mesh[hasbothpi[k]][l]] << " ";757cout << endl;758}759*/760761for (k = 0; k < hasbothpi.Size(); k++)762{763mesh[hasbothpi[k]].Delete();764/*765for (l = 0; l < 4; l++)766mesh[hasbothpi[k]][l] = PointIndex::BASE-1;767*/768}769770}771}772}773774// mesh.Compress();775mesh.SetNextTimeStamp();776}777778779void MeshOptimize2d :: CheckMeshApproximation (Mesh & mesh)780{781// Check angles between elements and normals at corners782/*783784int i, j;785int ne = mesh.GetNSE();786int surfnr;787788Vec3d n, ng;789ARRAY<Vec3d> ngs(3);790791(*mycout) << "Check Surface Approxiamtion" << endl;792(*testout) << "Check Surface Approxiamtion" << endl;793794for (i = 1; i <= ne; i++)795{796const Element2d & el = mesh.SurfaceElement(i);797surfnr = mesh.GetFaceDescriptor (el.GetIndex()).SurfNr();798Vec3d n = Cross (mesh.Point (el.PNum(1)) - mesh.Point (el.PNum(2)),799mesh.Point (el.PNum(1)) - mesh.Point (el.PNum(3)));800n /= n.Length();801802for (j = 1; j <= el.GetNP(); j++)803{804SelectSurfaceOfPoint (mesh.Point(el.PNum(j)), el.GeomInfoPi(j));805GetNormalVector (surfnr, mesh.Point(el.PNum(j)), ng);806ng /= ng.Length();807ngs.Elem(j) = ng;808809double angle = (180.0 / M_PI) * Angle (n, ng);810if (angle > 60)811{812(*testout) << "el " << i << " node " << el.PNum(j)813<< "has angle = " << angle << endl;814}815}816817for (j = 1; j <= 3; j++)818{819double angle = (180.0 / M_PI) * Angle (ngs.Get(j), ngs.Get(j%3+1));820if (angle > 60)821{822(*testout) << "el " << i << " node-node "823<< ngs.Get(j) << " - " << ngs.Get(j%3+1)824<< " has angle = " << angle << endl;825}826}827}828*/829}830}831832833