Path: blob/devel/ElmerGUI/netgen/libsrc/meshing/delaunay.cpp
3206 views
#include <mystdlib.h>1#include "meshing.hpp"2345namespace netgen6{789static const int deltetfaces[][3] =10{ { 1, 2, 3 },11{ 2, 0, 3 },12{ 0, 1, 3 },13{ 1, 0, 2 } };14151617181920class DelaunayTet21{22PointIndex pnums[4];23int nb[4];2425public:26DelaunayTet () { ; }2728DelaunayTet (const DelaunayTet & el)29{30for (int i = 0; i < 4; i++)31pnums[i] = el[i];32}3334DelaunayTet (const Element & el)35{36for (int i = 0; i < 4; i++)37pnums[i] = el[i];38}3940PointIndex & operator[] (int i) { return pnums[i]; }41PointIndex operator[] (int i) const { return pnums[i]; }4243int & NB1(int i) { return nb[i-1]; }44int NB1(int i) const { return nb[i-1]; }4546int & NB(int i) { return nb[i]; }47int NB(int i) const { return nb[i]; }484950int FaceNr (INDEX_3 & face) const // which face nr is it ?51{52for (int i = 0; i < 3; i++)53if (pnums[i] != face.I1() &&54pnums[i] != face.I2() &&55pnums[i] != face.I3())56return i;57return 3;58}5960void GetFace1 (int i, INDEX_3 & face) const61{62face.I(1) = pnums[deltetfaces[i-1][0]];63face.I(2) = pnums[deltetfaces[i-1][1]];64face.I(3) = pnums[deltetfaces[i-1][2]];65}6667void GetFace (int i, INDEX_3 & face) const68{69face.I(1) = pnums[deltetfaces[i][0]];70face.I(2) = pnums[deltetfaces[i][1]];71face.I(3) = pnums[deltetfaces[i][2]];72}7374INDEX_3 GetFace1 (int i) const75{76return INDEX_3 (pnums[deltetfaces[i-1][0]],77pnums[deltetfaces[i-1][1]],78pnums[deltetfaces[i-1][2]]);79}8081INDEX_3 GetFace (int i) const82{83return INDEX_3 (pnums[deltetfaces[i][0]],84pnums[deltetfaces[i][1]],85pnums[deltetfaces[i][2]]);86}8788void GetFace1 (int i, Element2d & face) const89{90// face.SetType(TRIG);91face[0] = pnums[deltetfaces[i-1][0]];92face[1] = pnums[deltetfaces[i-1][1]];93face[2] = pnums[deltetfaces[i-1][2]];94}95};96979899100101102103104105/*106Table to maintain neighbour elements107*/108class MeshNB109{110// face nodes -> one element111INDEX_3_CLOSED_HASHTABLE<int> faces;112113//114ARRAY<DelaunayTet> & tets;115116public:117118// estimated number of points119MeshNB (ARRAY<DelaunayTet> & atets, int np)120: faces(200), tets(atets)121{ ; }122123// add element with 4 nodes124void Add (int elnr);125126// delete element with 4 nodes127void Delete (int elnr)128{129DelaunayTet & el = tets.Elem(elnr);130for (int i = 0; i < 4; i++)131faces.Set (el.GetFace(i).Sort(), el.NB(i));132}133134// get neighbour of element elnr in direction fnr135int GetNB (int elnr, int fnr)136{137return tets.Get(elnr).NB1(fnr);138}139140//141void ResetFaceHT (int size)142{143faces.SetSize (size);144}145};146147148149void MeshNB :: Add (int elnr)150{151DelaunayTet & el = tets.Elem(elnr);152153for (int i = 0; i < 4; i++)154{155INDEX_3 i3 = INDEX_3::Sort (el.GetFace(i));156157int posnr;158159if (!faces.PositionCreate (i3, posnr))160{161// face already in use162int othertet = faces.GetData (posnr);163164el.NB(i) = othertet;165if (othertet)166{167int fnr = tets.Get(othertet).FaceNr (i3);168tets.Elem(othertet).NB(fnr) = elnr;169}170}171else172{173faces.SetData (posnr, elnr);174el.NB(i) = 0;175}176}177}178179180181182183184/*185connected lists of cosphereical elements186*/187class SphereList188{189ARRAY<int> links;190public:191SphereList ()192{ ; }193194void AddElement (int elnr)195{196if (elnr > links.Size())197links.Append (1);198links.Elem(elnr) = elnr;199}200201void DeleteElement (int elnr)202{203links.Elem(elnr) = 0;204}205206void ConnectElement (int eli, int toi)207{208links.Elem (eli) = links.Get (toi);209links.Elem (toi) = eli;210}211212void GetList (int eli, ARRAY<int> & linked) const;213};214215216void SphereList :: GetList (int eli, ARRAY<int> & linked) const217{218linked.SetSize (0);219int pi = eli;220221do222{223if (pi <= 0 || pi > links.Size())224{225cerr << "link, error " << endl;226cerr << "pi = " << pi << " linked.s = " << linked.Size() << endl;227exit(1);228}229if (linked.Size() > links.Size())230{231cerr << "links have loop" << endl;232exit(1);233}234235linked.Append (pi);236pi = links.Get(pi);237}238while (pi != eli);239}240241242243244245void AddDelaunayPoint (PointIndex newpi, const Point3d & newp,246ARRAY<DelaunayTet> & tempels,247Mesh & mesh,248Box3dTree & tettree,249MeshNB & meshnb,250ARRAY<Point<3> > & centers, ARRAY<double> & radi2,251ARRAY<int> & connected, ARRAY<int> & treesearch,252ARRAY<int> & freelist, SphereList & list,253IndexSet & insphere, IndexSet & closesphere)254{255/*256find any sphere, such that newp is contained in257*/258259DelaunayTet el;260int cfelind = -1;261262const Point<3> * pp[4];263Point<3> pc;264double r2;265Point3d tpmin, tpmax;266267tettree.GetIntersecting (newp, newp, treesearch);268269double quot,minquot(1e20);270271for (int j = 0; j < treesearch.Size(); j++)272{273int jjj = treesearch[j];274quot = Dist2 (centers.Get(jjj), newp) / radi2.Get(jjj);275276if((cfelind == -1 || quot < 0.99*minquot) && quot < 1)277{278minquot = quot;279el = tempels.Get(jjj);280cfelind = jjj;281if(minquot < 0.917632)282break;283}284}285286287/*288int i, j, k, l;289if (!felind)290{291cerr << "not in any sphere, 1" << endl;292// old, non tree search293294double mindist = 1e10;295for (j = 1; j <= tempels.Size(); j++)296{297if (tempels.Get(j).PNum(1))298{299double toofar =300Dist2 (centers.Get(j), newp) - radi2.Get(j);301if (toofar < mindist || toofar < 1e-7)302{303mindist = toofar;304cout << " dist2 = " << Dist2 (centers.Get(j), newp)305<< " radi2 = " << radi2.Get(j) << endl;306}307if (toofar < 0)308{309el = tempels.Get(j);310felind = j;311cout << "sphere found !" << endl;312break;313}314}315}316cout << "point is too far from sheres: " << mindist << endl;317}318*/319320if (cfelind == -1)321{322PrintWarning ("Delaunay, point not in any sphere");323return;324}325326327/*328insphere: point is in sphere -> delete element329closesphere: point is close to sphere -> considered for same center330*/331332// save overestimate333insphere.SetMaxIndex (2 * tempels.Size() + 5 * mesh.GetNP());334closesphere.SetMaxIndex (2 * tempels.Size() + 5 * mesh.GetNP());335336insphere.Clear();337closesphere.Clear();338339340insphere.Add (cfelind);341342int changed = 1;343int nstarti = 1, starti;344345346while (changed)347{348changed = 0;349starti = nstarti;350nstarti = insphere.Array().Size()+1;351352353// if point in sphere, then it is also closesphere354for (int j = starti; j < nstarti; j++)355{356int helind = insphere.Array().Get(j);357if (!closesphere.IsIn (helind))358closesphere.Add (helind);359}360361// add connected spheres to insphere - list362for (int j = starti; j < nstarti; j++)363{364list.GetList (insphere.Array().Get(j), connected);365for (int k = 0; k < connected.Size(); k++)366{367int celind = connected[k];368369if (tempels.Get(celind)[0] != -1 &&370!insphere.IsIn (celind))371{372changed = 1;373insphere.Add (celind);374}375}376}377378// check neighbour-tets379for (int j = starti; j < nstarti; j++)380for (int k = 1; k <= 4; k++)381{382int helind = insphere.Array().Get(j);383int nbind = meshnb.GetNB (helind, k);384385if (nbind && !insphere.IsIn (nbind) )386{387//changed388//int prec = testout->precision();389//testout->precision(12);390//(*testout) << "val1 " << Dist2 (centers.Get(nbind), newp)391// << " val2 " << radi2.Get(nbind) * (1+1e-8)392// << " val3 " << radi2.Get(nbind)393// << " val1 / val3 " << Dist2 (centers.Get(nbind), newp)/radi2.Get(nbind) << endl;394//testout->precision(prec);395if (Dist2 (centers.Get(nbind), newp)396< radi2.Get(nbind) * (1+1e-8) )397closesphere.Add (nbind);398399if (Dist2 (centers.Get(nbind), newp)400< radi2.Get(nbind) * (1 + 1e-12))401{402// point is in sphere -> remove tet403insphere.Add (nbind);404changed = 1;405}406else407{408/*409Element2d face;410tempels.Get(helind).GetFace (k, face);411412const Point3d & p1 = mesh.Point (face.PNum(1));413const Point3d & p2 = mesh.Point (face[1]);414const Point3d & p3 = mesh.Point (face[2]);415*/416417INDEX_3 i3 = tempels.Get(helind).GetFace (k-1);418419const Point3d & p1 = mesh.Point ( PointIndex (i3.I1()));420const Point3d & p2 = mesh.Point ( PointIndex (i3.I2()));421const Point3d & p3 = mesh.Point ( PointIndex (i3.I3()));422423424Vec3d v1(p1, p2);425Vec3d v2(p1, p3);426Vec3d n = Cross (v1, v2);427n /= n.Length();428429if (n * Vec3d (p1, mesh.Point (tempels.Get(helind)[k-1])) > 0)430n *= -1;431432double dist = n * Vec3d (p1, newp);433434435if (dist > -1e-10) // 1e-10436{437insphere.Add (nbind);438changed = 1;439}440441442}443}444}445} // while (changed)446447// (*testout) << "newels: " << endl;448ARRAY<Element> newels;449450Element2d face(TRIG);451452for (int j = 1; j <= insphere.Array().Size(); j++)453for (int k = 1; k <= 4; k++)454{455// int elind = insphere.Array().Get(j);456int celind = insphere.Array().Get(j);457int nbind = meshnb.GetNB (celind, k);458459if (!nbind || !insphere.IsIn (nbind))460{461tempels.Get (celind).GetFace1 (k, face);462463Element newel(TET);464for (int l = 0; l < 3; l++)465newel[l] = face[l];466newel[3] = newpi;467468newels.Append (newel);469470Vec<3> v1 = mesh[face[1]] - mesh[face[0]];471Vec<3> v2 = mesh[face[2]] - mesh[face[0]];472Vec<3> n = Cross (v1, v2);473474n.Normalize();475if (n * Vec3d(mesh.Point (face[0]),476mesh.Point (tempels.Get(insphere.Array().Get(j))[k-1]))477> 0)478n *= -1;479480double hval = n * ( newp - mesh[face[0]]);481482if (hval > -1e-12)483{484cerr << "vec to outer" << endl;485(*testout) << "vec to outer, hval = " << hval << endl;486(*testout) << "v1 x v2 = " << Cross (v1, v2) << endl;487(*testout) << "facep: "488<< mesh.Point (face[0]) << " "489<< mesh.Point (face[1]) << " "490<< mesh.Point (face[2]) << endl;491}492}493}494495meshnb.ResetFaceHT (10*insphere.Array().Size()+1);496497for (int j = 1; j <= insphere.Array().Size(); j++)498{499// int elind =500int celind = insphere.Array().Get(j);501502meshnb.Delete (celind);503list.DeleteElement (celind);504505for (int k = 0; k < 4; k++)506tempels.Elem(celind)[k] = -1;507508((ADTree6&)tettree.Tree()).DeleteElement (celind);509freelist.Append (celind);510}511512513int hasclose = 0;514for (int j = 1; j <= closesphere.Array().Size(); j++)515{516int ind = closesphere.Array().Get(j);517if (!insphere.IsIn(ind) &&518fabs (Dist2 (centers.Get (ind), newp) - radi2.Get(ind)) < 1e-8 )519hasclose = 1;520}521522for (int j = 1; j <= newels.Size(); j++)523{524int nelind;525526if (!freelist.Size())527{528tempels.Append (newels.Get(j));529nelind = tempels.Size();530}531else532{533nelind = freelist.Last();534freelist.DeleteLast();535536tempels.Elem(nelind) = newels.Get(j);537}538539meshnb.Add (nelind);540list.AddElement (nelind);541542for (int k = 0; k < 4; k++)543pp[k] = &mesh.Point (newels.Get(j)[k]);544545if (CalcSphereCenter (&pp[0], pc) )546{547PrintSysError ("Delaunay: New tet is flat");548549(*testout) << "new tet is flat" << endl;550for (int k = 1; k <= 4; k++)551(*testout) << newels.Get(j).PNum(k) << " ";552(*testout) << endl;553for (int k = 1; k <= 4; k++)554(*testout) << *pp[k-1] << " ";555(*testout) << endl;556}557558r2 = Dist2 (*pp[0], pc);559if (hasclose)560for (int k = 1; k <= closesphere.Array().Size(); k++)561{562int csameind = closesphere.Array().Get(k);563if (!insphere.IsIn(csameind) &&564fabs (r2 - radi2.Get(csameind)) < 1e-10 &&565Dist (pc, centers.Get(csameind)) < 1e-10)566{567pc = centers.Get(csameind);568r2 = radi2.Get(csameind);569list.ConnectElement (nelind, csameind);570break;571}572}573574if (centers.Size() < nelind)575{576centers.Append (pc);577radi2.Append (r2);578}579else580{581centers.Elem(nelind) = pc;582radi2.Elem(nelind) = r2;583}584585closesphere.Add (nelind);586587tpmax = tpmin = *pp[0];588for (int k = 1; k <= 3; k++)589{590tpmin.SetToMin (*pp[k]);591tpmax.SetToMax (*pp[k]);592}593tpmax = tpmax + 0.01 * (tpmax - tpmin);594tettree.Insert (tpmin, tpmax, nelind);595}596}597598599600601602603void Delaunay1 (Mesh & mesh, const MeshingParameters & mp, AdFront3 * adfront,604ARRAY<DelaunayTet> & tempels,605int oldnp, DelaunayTet & startel, Point3d & pmin, Point3d & pmax)606{607int i, j, k;608const Point<3> * pp[4];609610ARRAY<Point<3> > centers;611ARRAY<double> radi2;612613Point3d tpmin, tpmax;614615616// new: local box617mesh.GetBox (pmax, pmin); // lower bound for pmax, upper for pmin618for (i = 1; i <= adfront->GetNF(); i++)619{620const MiniElement2d & face = adfront->GetFace(i);621for (j = 0; j < face.GetNP(); j++)622{623pmin.SetToMin (mesh.Point (face[j]));624pmax.SetToMax (mesh.Point (face[j]));625}626}627628for (i = 0; i < mesh.LockedPoints().Size(); i++)629{630pmin.SetToMin (mesh.Point (mesh.LockedPoints()[i]));631pmax.SetToMax (mesh.Point (mesh.LockedPoints()[i]));632}633634635636Vec3d vdiag(pmin, pmax);637// double r1 = vdiag.Length();638double r1 = sqrt (3.0) * max3(vdiag.X(), vdiag.Y(), vdiag.Z());639vdiag = Vec3d (r1, r1, r1);640//double r2;641642Point3d pmin2 = pmin - 8 * vdiag;643Point3d pmax2 = pmax + 8 * vdiag;644645Point3d cp1(pmin2), cp2(pmax2), cp3(pmax2), cp4(pmax2);646cp2.X() = pmin2.X();647cp3.Y() = pmin2.Y();648cp4.Z() = pmin2.Z();649650651652653int np = mesh.GetNP();654655startel[0] = mesh.AddPoint (cp1);656startel[1] = mesh.AddPoint (cp2);657startel[2] = mesh.AddPoint (cp3);658startel[3] = mesh.AddPoint (cp4);659660// flag points to use for Delaunay:661BitArrayChar<PointIndex::BASE> usep(np);662usep.Clear();663for (i = 1; i <= adfront->GetNF(); i++)664{665const MiniElement2d & face = adfront->GetFace(i);666for (j = 0; j < face.GetNP(); j++)667usep.Set (face[j]);668}669670for (i = oldnp + PointIndex::BASE;671i < np + PointIndex::BASE; i++)672usep.Set (i);673674for (i = 0; i < mesh.LockedPoints().Size(); i++)675usep.Set (mesh.LockedPoints()[i]);676677678ARRAY<int> freelist;679680681int cntp = 0;682683MeshNB meshnb (tempels, mesh.GetNP() + 5);684SphereList list;685686pmin2 = pmin2 + 0.1 * (pmin2 - pmax2);687pmax2 = pmax2 + 0.1 * (pmax2 - pmin2);688689Box3dTree tettree(pmin2, pmax2);690691692tempels.Append (startel);693meshnb.Add (1);694list.AddElement (1);695ARRAY<int> connected, treesearch;696697698tpmin = tpmax = mesh.Point(startel[0]);699for (k = 1; k < 4; k++)700{701tpmin.SetToMin (mesh.Point (startel[k]));702tpmax.SetToMax (mesh.Point (startel[k]));703}704tpmax = tpmax + 0.01 * (tpmax - tpmin);705tettree.Insert (tpmin, tpmax, 1);706707708Point<3> pc;709710for (k = 0; k < 4; k++)711{712pp[k] = &mesh.Point (startel[k]);713}714715CalcSphereCenter (&pp[0], pc);716717centers.Append (pc);718radi2.Append (Dist2 (*pp[0], pc));719720721IndexSet insphere(mesh.GetNP());722IndexSet closesphere(mesh.GetNP());723724725726// "random" reordering of points (speeds a factor 3 - 5 !!!)727728ARRAY<int> mixed(np);729int prims[] = { 11, 13, 17, 19, 23, 29, 31, 37 };730int prim;731732i = 0;733while (np % prims[i] == 0) i++;734prim = prims[i];735736for (i = 1; i <= np; i++)737mixed.Elem(i) = (prim * i) % np + PointIndex::BASE;738739for (i = 1; i <= np; i++)740{741if (i % 1000 == 0)742{743if (i % 10000 == 0)744PrintDot ('+');745else746PrintDot ('.');747}748749multithread.percent = 100.0 * i / np;750if (multithread.terminate)751break;752753PointIndex newpi = mixed.Get(i);754755if (!usep.Test(newpi))756continue;757758cntp++;759760const Point3d & newp = mesh.Point(newpi);761762AddDelaunayPoint (newpi, newp, tempels, mesh,763tettree, meshnb, centers, radi2,764connected, treesearch, freelist, list, insphere, closesphere);765}766767for (i = tempels.Size(); i >= 1; i--)768if (tempels.Get(i)[0] <= 0)769tempels.DeleteElement (i);770771PrintDot ('\n');772773PrintMessage (3, "Points: ", cntp);774PrintMessage (3, "Elements: ", tempels.Size());775// (*mycout) << cntp << " / " << tempels.Size() << " points/elements" << endl;776777/*778cout << "tempels: ";779tempels.PrintMemInfo(cout);780cout << "Searchtree: ";781tettree.Tree().PrintMemInfo(cout);782cout << "MeshNB: ";783meshnb.PrintMemInfo(cout);784*/785}786787788789790791792void Meshing3 :: Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp)793{794int np, ne;795796PrintMessage (1, "Delaunay meshing");797PrintMessage (3, "number of points: ", mesh.GetNP());798PushStatus ("Delaunay meshing");799800801ARRAY<DelaunayTet> tempels;802Point3d pmin, pmax;803804DelaunayTet startel;805806int oldnp = mesh.GetNP();807if (mp.blockfill)808{809BlockFillLocalH (mesh, mp);810PrintMessage (3, "number of points: ", mesh.GetNP());811}812813np = mesh.GetNP();814815Delaunay1 (mesh, mp, adfront, tempels, oldnp, startel, pmin, pmax);816817{818// improve delaunay - mesh by swapping !!!!819820Mesh tempmesh;821for (PointIndex pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++)822tempmesh.AddPoint (mesh[pi]);823824for (int i = 1; i <= tempels.Size(); i++)825{826Element el(4);827for (int j = 0; j < 4; j++)828el[j] = tempels.Elem(i)[j];829830el.SetIndex (1);831832const Point3d & lp1 = mesh.Point (el[0]);833const Point3d & lp2 = mesh.Point (el[1]);834const Point3d & lp3 = mesh.Point (el[2]);835const Point3d & lp4 = mesh.Point (el[3]);836Vec3d v1(lp1, lp2);837Vec3d v2(lp1, lp3);838Vec3d v3(lp1, lp4);839840Vec3d n = Cross (v1, v2);841double vol = n * v3;842if (vol > 0) swap (el[2], el[3]);843844tempmesh.AddVolumeElement (el);845}846847848MeshQuality3d (tempmesh);849850tempmesh.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0));851tempmesh.AddFaceDescriptor (FaceDescriptor (2, 1, 0, 0));852853854855for (int i = 1; i <= mesh.GetNOpenElements(); i++)856{857Element2d sel = mesh.OpenElement(i);858sel.SetIndex(1);859tempmesh.AddSurfaceElement (sel);860swap (sel[1], sel[2]);861tempmesh.AddSurfaceElement (sel);862}863864865for (int i = 1; i <= 4; i++)866{867Element2d self(TRIG);868self.SetIndex (1);869startel.GetFace1 (i, self);870tempmesh.AddSurfaceElement (self);871}872873874// for (i = mesh.GetNP() - 3; i <= mesh.GetNP(); i++)875// tempmesh.AddLockedPoint (i);876for (PointIndex pi = PointIndex::BASE;877pi < tempmesh.GetNP() + PointIndex::BASE; pi++)878tempmesh.AddLockedPoint (pi);879880// tempmesh.PrintMemInfo(cout);881// tempmesh.Save ("tempmesh.vol");882883for (int i = 1; i <= 2; i++)884{885tempmesh.FindOpenElements ();886887PrintMessage (5, "Num open: ", tempmesh.GetNOpenElements());888tempmesh.CalcSurfacesOfNode ();889890tempmesh.FreeOpenElementsEnvironment (1);891892MeshOptimize3d meshopt;893// tempmesh.CalcSurfacesOfNode();894meshopt.SwapImprove(tempmesh, OPT_CONFORM);895}896897MeshQuality3d (tempmesh);898899tempels.SetSize(0);900for (int i = 1; i <= tempmesh.GetNE(); i++)901tempels.Append (tempmesh.VolumeElement(i));902}903904905906// remove degenerated907908BitArray badnode(mesh.GetNP());909badnode.Clear();910int ndeg = 0;911for (int i = 1; i <= tempels.Size(); i++)912{913Element el(4);914for (int j = 0; j < 4; j++)915el[j] = tempels.Elem(i)[j];916// Element & el = tempels.Elem(i);917const Point3d & lp1 = mesh.Point (el[0]);918const Point3d & lp2 = mesh.Point (el[1]);919const Point3d & lp3 = mesh.Point (el[2]);920const Point3d & lp4 = mesh.Point (el[3]);921Vec3d v1(lp1, lp2);922Vec3d v2(lp1, lp3);923Vec3d v3(lp1, lp4);924Vec3d n = Cross (v1, v2);925double vol = n * v3;926927double h = v1.Length() + v2.Length() + v3.Length();928if (fabs (vol) < 1e-8 * (h * h * h) &&929(el[0] <= np && el[1] <= np &&930el[2] <= np && el[3] <= np) ) // old: 1e-12931{932badnode.Set(el[0]);933badnode.Set(el[1]);934badnode.Set(el[2]);935badnode.Set(el[3]);936ndeg++;937(*testout) << "vol = " << vol << " h = " << h << endl;938}939940if (vol > 0)941Swap (el[2], el[3]);942}943944ne = tempels.Size();945for (int i = ne; i >= 1; i--)946{947const DelaunayTet & el = tempels.Get(i);948if (badnode.Test(el[0]) ||949badnode.Test(el[1]) ||950badnode.Test(el[2]) ||951badnode.Test(el[3]) )952tempels.DeleteElement(i);953}954955956PrintMessage (3, ndeg, " degenerated elements removed");957958// find surface triangles which are no face of any tet959960INDEX_3_HASHTABLE<int> openeltab(mesh.GetNOpenElements()+3);961ARRAY<int> openels;962for (int i = 1; i <= mesh.GetNOpenElements(); i++)963{964const Element2d & tri = mesh.OpenElement(i);965INDEX_3 i3(tri[0], tri[1], tri[2]);966i3.Sort();967openeltab.Set (i3, i);968}969970for (int i = 1; i <= tempels.Size(); i++)971{972for (int j = 0; j < 4; j++)973{974INDEX_3 i3 = tempels.Get(i).GetFace (j);975i3.Sort();976if (openeltab.Used(i3))977openeltab.Set (i3, 0);978}979}980981// and store them in openels982for (int i = 1; i <= openeltab.GetNBags(); i++)983for (int j = 1; j <= openeltab.GetBagSize(i); j++)984{985INDEX_3 i3;986int fnr;987openeltab.GetData (i, j, i3, fnr);988if (fnr)989openels.Append (fnr);990}991992993994995996// find open triangle with close edge (from halfening of surface squares)997998INDEX_2_HASHTABLE<INDEX_2> twotrias(mesh.GetNOpenElements()+5);999// for (i = 1; i <= mesh.GetNOpenElements(); i++)1000for (int ii = 1; ii <= openels.Size(); ii++)1001{1002int i = openels.Get(ii);1003const Element2d & el = mesh.OpenElement(i);1004for (int j = 1; j <= 3; j++)1005{1006INDEX_2 hi2 (el.PNumMod (j), el.PNumMod(j+1));1007hi2.Sort();1008if (twotrias.Used(hi2))1009{1010INDEX_2 hi3;1011hi3 = twotrias.Get (hi2);1012hi3.I2() = el.PNumMod (j+2);1013twotrias.Set (hi2, hi3);1014}1015else1016{1017INDEX_2 hi3(el.PNumMod (j+2), 0);1018twotrias.Set (hi2, hi3);1019}1020}1021}10221023INDEX_2_HASHTABLE<int> tetedges(tempels.Size() + 5);1024for (int i = 1; i <= tempels.Size(); i++)1025{1026const DelaunayTet & el = tempels.Get(i);1027INDEX_2 i2;1028for (int j = 1; j <= 6; j++)1029{1030switch (j)1031{1032case 1: i2.I1()=el[0]; i2.I2()=el[1]; break;1033case 2: i2.I1()=el[0]; i2.I2()=el[2]; break;1034case 3: i2.I1()=el[0]; i2.I2()=el[3]; break;1035case 4: i2.I1()=el[1]; i2.I2()=el[2]; break;1036case 5: i2.I1()=el[1]; i2.I2()=el[3]; break;1037case 6: i2.I1()=el[2]; i2.I2()=el[3]; break;1038default: i2.I1()=i2.I2()=0; break;1039}1040i2.Sort();1041tetedges.Set (i2, 1);1042}1043}1044// cout << "tetedges:";1045// tetedges.PrintMemInfo (cout);104610471048for (INDEX_2_HASHTABLE<INDEX_2>::Iterator it = twotrias.Begin();1049it != twotrias.End(); it++)1050{1051INDEX_2 hi2, hi3;1052twotrias.GetData (it, hi2, hi3);1053hi3.Sort();1054if (tetedges.Used (hi3))1055{1056const Point3d & p1 = mesh.Point ( PointIndex (hi2.I1()));1057const Point3d & p2 = mesh.Point ( PointIndex (hi2.I2()));1058const Point3d & p3 = mesh.Point ( PointIndex (hi3.I1()));1059const Point3d & p4 = mesh.Point ( PointIndex (hi3.I2()));1060Vec3d v1(p1, p2);1061Vec3d v2(p1, p3);1062Vec3d v3(p1, p4);1063Vec3d n = Cross (v1, v2);1064double vol = n * v3;10651066double h = v1.Length() + v2.Length() + v3.Length();1067if (fabs (vol) < 1e-4 * (h * h * h)) // old: 1e-121068{1069badnode.Set(hi3.I1());1070badnode.Set(hi3.I2());1071}1072}1073}10741075/*1076for (i = 1; i <= twotrias.GetNBags(); i++)1077for (j = 1; j <= twotrias.GetBagSize (i); j++)1078{1079INDEX_2 hi2, hi3;1080twotrias.GetData (i, j, hi2, hi3);1081hi3.Sort();1082if (tetedges.Used (hi3))1083{1084const Point3d & p1 = mesh.Point (hi2.I1());1085const Point3d & p2 = mesh.Point (hi2.I2());1086const Point3d & p3 = mesh.Point (hi3.I1());1087const Point3d & p4 = mesh.Point (hi3.I2());1088Vec3d v1(p1, p2);1089Vec3d v2(p1, p3);1090Vec3d v3(p1, p4);1091Vec3d n = Cross (v1, v2);1092double vol = n * v3;10931094double h = v1.Length() + v2.Length() + v3.Length();1095if (fabs (vol) < 1e-4 * (h * h * h)) // old: 1e-121096{1097badnode.Set(hi3.I1());1098badnode.Set(hi3.I2());1099}1100}1101}1102*/11031104ne = tempels.Size();1105for (int i = ne; i >= 1; i--)1106{1107const DelaunayTet & el = tempels.Get(i);1108if (badnode.Test(el[0]) ||1109badnode.Test(el[1]) ||1110badnode.Test(el[2]) ||1111badnode.Test(el[3]) )1112tempels.DeleteElement(i);1113}11141115111611171118// find intersecting:1119PrintMessage (3, "Remove intersecting");1120if (openels.Size())1121{1122Box3dTree setree(pmin, pmax);11231124/*1125cout << "open elements in search tree: " << openels.Size() << endl;1126cout << "pmin, pmax = " << pmin << " - " << pmax << endl;1127*/11281129for (int i = 1; i <= openels.Size(); i++)1130{1131int fnr;1132fnr = openels.Get(i);1133if (fnr)1134{1135const Element2d & tri = mesh.OpenElement(fnr);11361137Point3d ltpmin (mesh.Point(tri[0]));1138Point3d ltpmax (ltpmin);11391140for (int k = 2; k <= 3; k++)1141{1142ltpmin.SetToMin (mesh.Point (tri.PNum(k)));1143ltpmax.SetToMax (mesh.Point (tri.PNum(k)));1144}1145setree.Insert (ltpmin, ltpmax, fnr);1146}1147}11481149ARRAY<int> neartrias;1150for (int i = 1; i <= tempels.Size(); i++)1151{1152const Point<3> *pp[4];1153int tetpi[4];1154DelaunayTet & el = tempels.Elem(i);11551156int intersect = 0;11571158for (int j = 0; j < 4; j++)1159{1160pp[j] = &mesh.Point(el[j]);1161tetpi[j] = el[j];1162}11631164Point3d tetpmin(*pp[0]);1165Point3d tetpmax(tetpmin);1166for (int j = 1; j < 4; j++)1167{1168tetpmin.SetToMin (*pp[j]);1169tetpmax.SetToMax (*pp[j]);1170}1171tetpmin = tetpmin + 0.01 * (tetpmin - tetpmax);1172tetpmax = tetpmax + 0.01 * (tetpmax - tetpmin);11731174setree.GetIntersecting (tetpmin, tetpmax, neartrias);117511761177// for (j = 1; j <= mesh.GetNSE(); j++)1178// {1179for (int jj = 1; jj <= neartrias.Size(); jj++)1180{1181int j = neartrias.Get(jj);11821183const Element2d & tri = mesh.OpenElement(j);1184const Point<3> *tripp[3];1185int tripi[3];11861187for (int k = 1; k <= 3; k++)1188{1189tripp[k-1] = &mesh.Point (tri.PNum(k));1190tripi[k-1] = tri.PNum(k);1191}11921193if (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi))1194{1195/*1196int il1, il2;1197(*testout) << "intersect !" << endl;1198(*testout) << "triind: ";1199for (il1 = 0; il1 < 3; il1++)1200(*testout) << " " << tripi[il1];1201(*testout) << endl;1202(*testout) << "tetind: ";1203for (il2 = 0; il2 < 4; il2++)1204(*testout) << " " << tetpi[il2];1205(*testout) << endl;12061207(*testout) << "trip: ";1208for (il1 = 0; il1 < 3; il1++)1209(*testout) << " " << *tripp[il1];1210(*testout) << endl;1211(*testout) << "tetp: ";1212for (il2 = 0; il2 < 4; il2++)1213(*testout) << " " << *pp[il2];1214(*testout) << endl;1215*/121612171218intersect = 1;1219break;1220}1221}122212231224if (intersect)1225{1226tempels.DeleteElement(i);1227i--;1228}1229}1230}12311232123312341235PrintMessage (3, "Remove outer");12361237// find connected tets (with no face between, and no hole due1238// to removed intersecting tets.1239// INDEX_3_HASHTABLE<INDEX_2> innerfaces(np);124012411242INDEX_3_HASHTABLE<int> boundaryfaces(mesh.GetNOpenElements()/3+1);1243for (int i = 1; i <= mesh.GetNOpenElements(); i++)1244{1245const Element2d & tri = mesh.OpenElement(i);1246INDEX_3 i3 (tri[0], tri[1], tri[2]);1247i3.Sort();1248boundaryfaces.PrepareSet (i3);1249}1250boundaryfaces.AllocateElements();1251for (int i = 1; i <= mesh.GetNOpenElements(); i++)1252{1253const Element2d & tri = mesh.OpenElement(i);1254INDEX_3 i3 (tri[0], tri[1], tri[2]);1255i3.Sort();1256boundaryfaces.Set (i3, 1);1257}12581259for (int i = 0; i < tempels.Size(); i++)1260for (int j = 0; j < 4; j++)1261tempels[i].NB(j) = 0;12621263TABLE<int,PointIndex::BASE> elsonpoint(mesh.GetNP());1264for (int i = 0; i < tempels.Size(); i++)1265{1266const DelaunayTet & el = tempels[i];1267INDEX_4 i4(el[0], el[1], el[2], el[3]);1268i4.Sort();1269elsonpoint.IncSizePrepare (i4.I1());1270elsonpoint.IncSizePrepare (i4.I2());1271}12721273elsonpoint.AllocateElementsOneBlock();12741275for (int i = 0; i < tempels.Size(); i++)1276{1277const DelaunayTet & el = tempels[i];1278INDEX_4 i4(el[0], el[1], el[2], el[3]);1279i4.Sort();1280elsonpoint.Add (i4.I1(), i+1);1281elsonpoint.Add (i4.I2(), i+1);1282}12831284// cout << "elsonpoint mem: ";1285// elsonpoint.PrintMemInfo(cout);12861287INDEX_3_CLOSED_HASHTABLE<INDEX_2> faceht(100);12881289Element2d hel(TRIG);1290for (PointIndex pi = PointIndex::BASE;1291pi < mesh.GetNP()+PointIndex::BASE; pi++)1292{1293faceht.SetSize (4 * elsonpoint[pi].Size());1294for (int ii = 0; ii < elsonpoint[pi].Size(); ii++)1295{1296int i = elsonpoint[pi][ii];1297const DelaunayTet & el = tempels.Get(i);12981299for (int j = 1; j <= 4; j++)1300{1301el.GetFace1 (j, hel);1302hel.Invert();1303hel.NormalizeNumbering();13041305if (hel[0] == pi)1306{1307INDEX_3 i3(hel[0], hel[1], hel[2]);13081309if (!boundaryfaces.Used (i3))1310{1311if (faceht.Used (i3))1312{1313INDEX_2 i2 = faceht.Get(i3);13141315tempels.Elem(i).NB1(j) = i2.I1();1316tempels.Elem(i2.I1()).NB1(i2.I2()) = i;1317}1318else1319{1320hel.Invert();1321hel.NormalizeNumbering();1322INDEX_3 i3i(hel[0], hel[1], hel[2]);1323INDEX_2 i2(i, j);1324faceht.Set (i3i, i2);1325}1326}1327}1328}1329}1330}13311332/*1333for (i = 1; i <= tempels.Size(); i++)1334{1335const DelaunayTet & el = tempels.Get(i);1336for (j = 1; j <= 4; j++)1337{1338INDEX_3 i3;1339Element2d face;1340el.GetFace1 (j, face);1341for (int kk = 1; kk <= 3; kk++)1342i3.I(kk) = face.PNum(kk);13431344i3.Sort();1345if (!boundaryfaces.Used (i3))1346{1347if (innerfaces.Used(i3))1348{1349INDEX_2 i2;1350i2 = innerfaces.Get(i3);1351i2.I2() = i;1352innerfaces.Set (i3, i2);1353}1354else1355{1356INDEX_2 i2;1357i2.I1() = i;1358i2.I2() = 0;1359innerfaces.Set (i3, i2);1360}1361}1362}1363}1364*/13651366/*1367(*testout) << "nb elements:" << endl;1368for (i = 1; i <= tempels.Size(); i++)1369{1370(*testout) << i << " ";1371for (j = 1; j <= 4; j++)1372(*testout) << tempels.Get(i).NB1(j) << " ";1373(*testout) << endl;1374}13751376(*testout) << "pairs:" << endl;1377for (i = 1; i <= innerfaces.GetNBags(); i++)1378for (j = 1; j <= innerfaces.GetBagSize(i); j++)1379{1380INDEX_3 i3;1381INDEX_2 i2;1382innerfaces.GetData (i, j, i3, i2);1383(*testout) << i2 << endl;1384}1385*/13861387138813891390139113921393/*1394cout << "innerfaces: ";1395innerfaces.PrintMemInfo (cout);1396*/13971398// cout << "boundaryfaces: ";1399// boundaryfaces.PrintMemInfo (cout);140014011402PrintMessage (5, "tables filled");140314041405ne = tempels.Size();1406BitArray inner(ne), outer(ne);1407inner.Clear();1408outer.Clear();1409ARRAY<int> elstack;14101411/*1412int starti = 0;1413for (i = 1; i <= ne; i++)1414{1415const Element & el = tempels.Get(i);1416for (j = 1; j <= 4; j++)1417for (k = 1; k <= 4; k++)1418if (el.PNum(j) == startel.PNum(k))1419{1420outer.Set(i);1421starti = i;1422}1423}1424*/14251426while (1)1427{1428int inside;1429bool done = 1;14301431int i;1432for (i = 1; i <= ne; i++)1433if (!inner.Test(i) && !outer.Test(i))1434{1435done = 0;1436break;1437}14381439if (done) break;14401441const DelaunayTet & el = tempels.Get(i);1442const Point3d & p1 = mesh.Point (el[0]);1443const Point3d & p2 = mesh.Point (el[1]);1444const Point3d & p3 = mesh.Point (el[2]);1445const Point3d & p4 = mesh.Point (el[3]);14461447Point3d ci = Center (p1, p2, p3, p4);14481449inside = adfront->Inside (ci);14501451/*1452cout << "startel: " << i << endl;1453cout << "inside = " << inside << endl;1454cout << "ins2 = " << adfront->Inside (Center (ci, p1)) << endl;1455cout << "ins3 = " << adfront->Inside (Center (ci, p2)) << endl;1456*/14571458elstack.SetSize(0);1459elstack.Append (i);14601461while (elstack.Size())1462{1463int ei = elstack.Last();1464elstack.DeleteLast();14651466if (!inner.Test(ei) && !outer.Test(ei))1467{1468if (inside)1469inner.Set(ei);1470else1471outer.Set(ei);147214731474for (int j = 1; j <= 4; j++)1475{1476INDEX_3 i3 = tempels.Get(ei).GetFace1(j);1477/*1478Element2d face;1479tempels.Get(ei).GetFace(j, face);1480for (int kk = 1; kk <= 3; kk++)1481i3.I(kk) = face.PNum(kk);1482*/1483i3.Sort();148414851486if (tempels.Get(ei).NB1(j))1487elstack.Append (tempels.Get(ei).NB1(j));14881489/*1490if (innerfaces.Used(i3))1491{1492INDEX_2 i2 = innerfaces.Get(i3);1493int other = i2.I1() + i2.I2() - ei;14941495if (other != tempels.Get(ei).NB1(j))1496cerr << "different1 !!" << endl;14971498if (other)1499{1500elstack.Append (other);1501}1502}1503else1504if (tempels.Get(ei).NB1(j))1505cerr << "different2 !!" << endl;1506*/15071508}1509}1510}1511}1512151315141515// check outer elements1516if (debugparam.slowchecks)1517{1518for (int i = 1; i <= ne; i++)1519{1520const DelaunayTet & el = tempels.Get(i);1521const Point3d & p1 = mesh.Point (el[0]);1522const Point3d & p2 = mesh.Point (el[1]);1523const Point3d & p3 = mesh.Point (el[2]);1524const Point3d & p4 = mesh.Point (el[3]);15251526Point3d ci = Center (p1, p2, p3, p4);15271528// if (adfront->Inside (ci) != adfront->Inside (Center (ci, p1)))1529// cout << "ERROR: outer test unclear !!!" << endl;15301531if (inner.Test(i) != adfront->Inside (ci))1532{1533/*1534cout << "ERROR: outer test wrong !!!"1535<< "inner = " << int(inner.Test(i))1536<< "outer = " << int(outer.Test(i))1537<< endl;15381539cout << "Vol = " << Determinant(Vec3d(p1, p2),1540Vec3d(p1, p3),1541Vec3d(p1, p4)) << endl;15421543*/1544for (int j = 1; j <= 4; j++)1545{1546Point3d hp;1547switch (j)1548{1549case 1: hp = Center (ci, p1); break;1550case 2: hp = Center (ci, p2); break;1551case 3: hp = Center (ci, p3); break;1552case 4: hp = Center (ci, p4); break;1553}1554// cout << "inside(" << hp << ") = " << adfront->Inside(hp) << endl;1555}15561557}15581559if (adfront->Inside(ci))1560outer.Clear(i);1561else1562outer.Set(i);1563}1564}156515661567/*15681569// find bug in innerfaces15701571tempmesh.DeleteVolumeElements();15721573for (i = 1; i <= innerfaces.GetNBags(); i++)1574for (j = 1; j <= innerfaces.GetBagSize(i); j++)1575{1576INDEX_3 i3;1577INDEX_2 i2;1578innerfaces.GetData (i, j, i3, i2);1579if (i2.I2())1580{1581if (outer.Test(i2.I1()) != outer.Test(i2.I2()))1582{1583tempmesh.AddVolumeElement (tempels.Get(i2.I1()));1584tempmesh.AddVolumeElement (tempels.Get(i2.I2()));1585cerr << "outer flag different for connected els" << endl;1586}1587}1588}158915901591cout << "Check intersectiong once more" << endl;15921593for (i = 1; i <= openels.Size(); i++)1594{1595tempmesh.SurfaceElement(2*openels.Get(i)).SetIndex(2);1596tempmesh.SurfaceElement(2*openels.Get(i)-1).SetIndex(2);1597}15981599// for (i = 1; i <= tempmesh.GetNE(); i++)1600// for (j = 1; j <= tempmesh.GetNSE(); j++)1601i = 6; j = 403;1602if (i <= tempmesh.GetNE() && j <= tempmesh.GetNSE())1603if (tempmesh.SurfaceElement(j).GetIndex()==2)1604{1605const Element & el = tempmesh.VolumeElement(i);1606const Element2d & sel = tempmesh.SurfaceElement(j);16071608const Point3d *tripp[3];1609const Point3d *pp[4];1610int tetpi[4], tripi[3];16111612for (k = 1; k <= 4; k++)1613{1614pp[k-1] = &tempmesh.Point(el.PNum(k));1615tetpi[k-1] = el.PNum(k);1616}16171618for (k = 1; k <= 3; k++)1619{1620tripp[k-1] = &tempmesh.Point (sel.PNum(k));1621tripi[k-1] = sel.PNum(k);1622}16231624(*testout) << "Check Triangle " << j << ":";1625for (k = 1; k <= 3; k++)1626(*testout) << " " << sel.PNum(k);1627for (k = 1; k <= 3; k++)1628(*testout) << " " << tempmesh.Point(sel.PNum(k));1629(*testout) << endl;16301631(*testout) << "Check Tet " << i << ":";1632for (k = 1; k <= 4; k++)1633(*testout) << " " << el.PNum(k);1634for (k = 1; k <= 4; k++)1635(*testout) << " " << tempmesh.Point(el.PNum(k));1636(*testout) << endl;16371638if (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi))1639{1640cout << "Intesection detected !!" << endl;1641}1642}16431644tempmesh.Save ("temp.vol");16451646// end bug search1647*/164816491650for (int i = ne; i >= 1; i--)1651{1652if (outer.Test(i))1653tempels.DeleteElement(i);1654}165516561657// mesh.points.SetSize(mesh.points.Size()-4);16581659for (int i = 0; i < tempels.Size(); i++)1660{1661Element el(4);1662for (int j = 0; j < 4; j++)1663el[j] = tempels[i][j];1664mesh.AddVolumeElement (el);1665}16661667PrintMessage (5, "outer removed");16681669mesh.FindOpenElements(domainnr);16701671mesh.Compress();16721673PopStatus ();1674}1675}167616771678