Path: blob/devel/ElmerGUI/netgen/libsrc/stlgeom/stlgeommesh.cpp
3206 views
//20.11.1999 second part of stlgeom.cc, mainly mesh functions12#include <mystdlib.h>34#include <myadt.hpp>5#include <linalg.hpp>6#include <gprim.hpp>78#include <meshing.hpp>910#include "stlgeom.hpp"1112namespace netgen13{14int EdgeUsed(int p1, int p2, ARRAY<INDEX_2>& edges, INDEX_2_HASHTABLE<int>& hashtab)15{16if (p1 > p2) {swap (p1,p2);}1718if (hashtab.Used(INDEX_2(p1,p2)))19{return hashtab.Get(INDEX_2(p1,p2));}2021return 0;22}2324Point<3> STLGeometry :: PointBetween(const Point<3> & ap1, int t1,25const Point<3> & ap2, int t2)26{27//funktioniert nicht in allen F�llen!2829PrintWarning("Point between");303132ClearMarkedSegs();3334InitMarkedTrigs();35SetMarkedTrig(t1,1);36SetMarkedTrig(t2,1);3738TABLE<Point3d> edgepoints;39TABLE<double> edgepointdists;40TABLE<int> edgepointorigines;41TABLE<int> edgepointoriginps;4243ARRAY<int> edgetrigs;44ARRAY<INDEX_2> edgepointnums;45ARRAY<int> edgetriglocinds;4647int size = 3*GetNT();48INDEX_2_HASHTABLE<int> hashtab(size);4950int divisions = 10;5152edgepoints.SetSize(size);53edgepointdists.SetSize(size);54edgepointorigines.SetSize(size);55edgepointoriginps.SetSize(size);5657edgetrigs.SetSize(size);58edgepointnums.SetSize(size);59edgetriglocinds.SetSize(size);6061ARRAY<int> edgelist1;62ARRAY<int> edgelist2;6364edgelist1.SetSize(0);65edgelist2.SetSize(0);666768int i, j, k, l, m;69int edgecnt = 0;7071//first triangle:72for (i = 1; i <= 3; i++)73{74int ptn1 = GetTriangle(t1).PNum(i);75int ptn2 = GetTriangle(t1).PNumMod(i+1);7677if (ptn1 > ptn2) {swap(ptn1,ptn2);}7879Point3d pt1 = GetPoint(ptn1);80Point3d pt2 = GetPoint(ptn2);8182edgecnt++;83edgetrigs.Elem(edgecnt) = t1;84edgepointnums.Elem(edgecnt) = INDEX_2(ptn1,ptn2);85hashtab.Set(edgepointnums.Get(edgecnt),edgecnt);8687edgetriglocinds.Elem(edgecnt) = i;88edgelist1.Append(edgecnt);8990for (j = 1; j <= divisions; j++)91{92double lfact = (double)j/(double)divisions;93Point3d pbtw(lfact*pt1.X()+(1.-lfact)*pt2.X(),94lfact*pt1.Y()+(1.-lfact)*pt2.Y(),95lfact*pt1.Z()+(1.-lfact)*pt2.Z());9697//AddMarkedSeg(ap1,pbtw);9899edgepoints.Add1(edgecnt,pbtw);100edgepointdists.Add1(edgecnt,Dist(pbtw,ap1));101edgepointorigines.Add1(edgecnt,0);102edgepointoriginps.Add1(edgecnt,0);103}104}105106int finished = 0;107int endpointorigine = 0;108int endpointoriginp = 0;109double endpointmindist = 1E50;110111int maxsize = 0;112while (!finished)113{114finished = 1;115116if (edgelist1.Size() > maxsize) {maxsize = edgelist1.Size();}117118for (i = 1; i <= edgelist1.Size(); i++)119{120int en = edgelist1.Get(i);121int trig = edgetrigs.Get(en);122int edgenum = edgetriglocinds.Get(en);123int tn = NeighbourTrigSorted(trig,edgenum);124125if (tn != t2)126{127for (k = 1; k <= 3; k++)128{129int pnt1 = GetTriangle(tn).PNum(k);130int pnt2 = GetTriangle(tn).PNumMod(k+1);131132if (pnt1 > pnt2) {swap(pnt1,pnt2);}133134Point3d pt1 = GetPoint(pnt1);135Point3d pt2 = GetPoint(pnt2);136137//AddMarkedSeg(pt1,pt2);138139//if (!(pnt1 == ep1 && pnt2 == ep2))140// {141int edgeused = 0;142edgenum = EdgeUsed(pnt1, pnt2, edgepointnums, hashtab);143if (edgenum != en)144{145if (edgenum != 0)146{edgeused = 1;}147else148{149edgecnt++;150edgenum = edgecnt;151152edgetrigs.Elem(edgenum) = tn;153edgepointnums.Elem(edgenum) = INDEX_2(pnt1,pnt2);154hashtab.Set(edgepointnums.Get(edgenum),edgenum);155edgetriglocinds.Elem(edgenum) = k;156}157158if (edgenum > size || edgenum == 0) {PrintSysError("edgenum = ", edgenum);}159160double minofmindist = 1E50;161int changed = 0;162163for (l = 1; l <= divisions; l++)164{165double lfact = (double)l/(double)divisions;166Point3d pbtw(lfact*pt1.X()+(1.-lfact)*pt2.X(),167lfact*pt1.Y()+(1.-lfact)*pt2.Y(),168lfact*pt1.Z()+(1.-lfact)*pt2.Z());169170double mindist = 1E50;171int index=0;172173for (m = 1; m <= divisions; m++)174{175const Point3d& p = edgepoints.Get(en,m);176if (Dist(pbtw,p) + edgepointdists.Get(en,m) < mindist)177{mindist = Dist(pbtw,p) + edgepointdists.Get(en,m); index = m;}178}179180//if (mindist < endpointmindist) {finished = 0;}181if (mindist < minofmindist) {minofmindist = mindist;}182183184if (!edgeused)185{186//AddMarkedSeg(pbtw,edgepoints.Get(en,index));187188edgepoints.Add1(edgenum,pbtw);189edgepointdists.Add1(edgenum,mindist);190edgepointorigines.Add1(edgenum,en);191edgepointoriginps.Add1(edgenum,index);192changed = 1;193}194else195{196if (mindist < edgepointdists.Get(edgenum,l))197{198edgepointdists.Set(edgenum,l,mindist);199edgepointorigines.Set(edgenum,l,en);200edgepointoriginps.Set(edgenum,l,index);201changed = 1;202}203}204}205if (minofmindist < endpointmindist-1E-10 && changed)206{207finished = 0;208edgelist2.Append(edgenum);209}210}211}212}213else214{215double mindist = 1E50;216int index(0);217for (m = 1; m <= divisions; m++)218{219const Point3d& p = edgepoints.Get(en,m);220if (Dist(ap2,p) + edgepointdists.Get(en,m) < mindist)221{mindist = Dist(ap2,p) + edgepointdists.Get(en,m); index = m;}222}223if (mindist < endpointmindist)224{225endpointorigine = en;226endpointoriginp = index;227endpointmindist = mindist;228}229}230}231edgelist1.SetSize(0);232for (i = 1; i <= edgelist2.Size(); i++)233{234edgelist1.Append(edgelist2.Get(i));235}236}237238if (!endpointorigine) {PrintSysError("No connection found!");}239240ARRAY<Point3d> plist;241242plist.Append(ap2);243int laste = endpointorigine;244int lastp = endpointoriginp;245int lle, llp;246247248while (laste)249{250plist.Append(edgepoints.Get(laste,lastp));251252lle = laste;253llp = lastp;254laste = edgepointorigines.Get(lle,llp);255lastp = edgepointoriginps.Get(lle,llp);256}257258plist.Append(ap1);259260for (i = 1; i <= plist.Size()-1; i++)261{262AddMarkedSeg(plist.Get(i),plist.Get(i+1));263}264265PrintMessage(5,"PointBetween: complexity=", maxsize);266267268Point3d pm;269double dist = 0;270int found = 0;271272for (i = 1; i <= plist.Size()-1; i++)273{274dist += Dist(plist.Get(i),plist.Get(i+1));275if (dist > endpointmindist*0.5)276{277double segl = Dist(plist.Get(i), plist.Get(i+1));278double d = dist - endpointmindist * 0.5;279pm = Point3d(d/segl*plist.Get(i).X() + (1.-d/segl)*plist.Get(i+1).X(),280d/segl*plist.Get(i).Y() + (1.-d/segl)*plist.Get(i+1).Y(),281d/segl*plist.Get(i).Z() + (1.-d/segl)*plist.Get(i+1).Z());282found = 1;283break;284}285}286if (!found) {PrintWarning("Problem in PointBetween"); pm = Center(ap1,ap2);}287288AddMarkedSeg(pm, Point3d(0.,0.,0.));289290return pm;291292}293294295void STLGeometry :: PrepareSurfaceMeshing()296{297meshchart = -1; //clear no old chart298meshcharttrigs.SetSize(GetNT());299int i;300for (i = 1; i <= GetNT(); i++)301{meshcharttrigs.Elem(i) = 0;}302}303304void STLGeometry::GetMeshChartBoundary (ARRAY<Point2d > & apoints,305ARRAY<Point3d > & points3d,306ARRAY<INDEX_2> & alines, double h)307{308int i, j;309twoint seg, newseg;310int zone;311Point<2> p2;312313const STLChart& chart = GetChart(meshchart);314315316for (i = 1; i <= chart.GetNOLimit(); i++)317{318seg = chart.GetOLimit(i);319INDEX_2 i2;320for (j = 1; j <= 2; j++)321{322int pi = (j == 1) ? seg.i1 : seg.i2;323int lpi;324if (ha_points.Get(pi) == 0)325{326const Point<3> & p3d = GetPoint (pi);327Point<2> p2d;328329points3d.Append (p3d);330ToPlane(p3d, 0, p2d, h, zone, 0);331apoints.Append (p2d);332333lpi = apoints.Size();334ha_points.Elem(pi) = lpi;335}336else337lpi = ha_points.Get(pi);338339i2.I(j) = lpi;340}341alines.Append (i2);342343/*344seg = chart.GetOLimit(i);345psize = points.Size();346347newseg.i1 = psize+1;348newseg.i2 = psize+2;349350ToPlane(GetPoint(seg.i1), 0, p2, h, zone, 0);351points.Append(p2);352points3d.Append (GetPoint(seg.i1));353ToPlane(GetPoint(seg.i2), 0, p2, h, zone, 0);354points.Append(p2);355points3d.Append (GetPoint(seg.i2));356lines.Append (INDEX_2 (points.Size()-1, points.Size()));357*/358}359360for (i = 1; i <= chart.GetNOLimit(); i++)361{362seg = chart.GetOLimit(i);363ha_points.Elem(seg.i1) = 0;364ha_points.Elem(seg.i2) = 0;365}366}367368void STLGeometry :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2, int trig)369{370p1 = ap1; //save for ToPlane, in data of STLGeometry class371Point<3> p2 = ap2; //only locally used372373meshchart = GetChartNr(trig);374375if (usechartnormal)376meshtrignv = GetChart(meshchart).GetNormal();377else378meshtrignv = GetTriangle(trig).Normal();379380//meshtrignv = GetTriangle(trig).Normal(points);381382meshtrignv /= meshtrignv.Length();383384GetTriangle(trig).ProjectInPlain(points, meshtrignv, p2);385386387ez = meshtrignv;388ez /= ez.Length();389ex = p2 - p1;390ex -= (ex * ez) * ez;391ex /= ex.Length();392ey = Cross (ez, ex);393394}395396397void STLGeometry :: SelectChartOfTriangle (int trignum)398{399meshchart = GetChartNr(trignum);400meshtrignv = GetTriangle(trignum).Normal();401}402403404void STLGeometry :: SelectChartOfPoint (const Point<3> & p)405{406int i, ii;407408ARRAY<int> trigsinbox;409410Box<3> box(p,p);411box.Increase (1e-6);412GetTrianglesInBox (box, trigsinbox);413414415// for (i = 1; i <= GetNT(); i++)416for (ii = 1; ii <= trigsinbox.Size(); ii++)417{418i = trigsinbox.Get(ii);419Point<3> hp = p;420if (GetTriangle(i).GetNearestPoint(points, hp) <= 1E-8)421{422SelectChartOfTriangle (i);423break;424}425}426return;427}428429430431void STLGeometry :: ToPlane (const Point<3> & locpoint, int * trigs,432Point<2> & plainpoint, double h, int& zone,433int checkchart)434{435if (checkchart)436{437438//check if locpoint lies on actual chart:439zone = 0;440441442// Point3d p;443int i = 1;444const STLChart& chart = GetChart(meshchart);445int foundinchart = 0;446const double range = 1e-6; //1e-4 old447448449450451if (trigs)452{453int * htrigs = trigs;454while (*htrigs)455{456if (TrigIsInOC (*htrigs, meshchart))457{458foundinchart = 1;459break;460}461htrigs++;462}463}464465else466{467ARRAY<int> trigsinbox;468469if (!geomsearchtreeon)470{471//alter chart-tree472Box<3> box(locpoint, locpoint);473box.Increase (range);474chart.GetTrianglesInBox (box.PMin(), box.PMax(), trigsinbox);475}476else477{478ARRAY<int> trigsinbox2;479Box<3> box(locpoint, locpoint);480box.Increase (range);481GetTrianglesInBox (box, trigsinbox2);482for (i = 1; i <= trigsinbox2.Size(); i++)483{484if (TrigIsInOC(trigsinbox2.Get(i),meshchart)) {trigsinbox.Append(trigsinbox2.Get(i));}485}486487}488489490for (i = 1; i <= trigsinbox.Size(); i++)491{492Point<3> p = locpoint;493if (GetTriangle(trigsinbox.Get(i)).GetNearestPoint(points, p)494<= 1E-8)495{496foundinchart = 1;497break;498}499500}501}502503//do not use this point (but do correct projection (joachim)504if (!foundinchart)505{506zone = -1; // plainpoint.X() = 11111; plainpoint.Y() = 11111; return;507}508}509510else511{512zone = 0;513}514515//transform in plane516Vec<3> p1p = locpoint - p1;517plainpoint(0) = (p1p * ex) / h;518plainpoint(1) = (p1p * ey) / h;519520}521522int STLGeometry :: FromPlane (const Point<2> & plainpoint,523Point<3> & locpoint, double h)524{525Point2d plainpoint2 (plainpoint);526527plainpoint2.X() *= h;528plainpoint2.Y() *= h;529Vec3d p1p = plainpoint2.X() * ex + plainpoint2.Y() * ey;530locpoint = p1 + p1p;531532533int rv = Project(locpoint);534if (!rv) {return 1;} //project nicht gegangen535return 0;536}537538int lasttrig;539int STLGeometry :: LastTrig() const {return lasttrig;};540541//project normal to tangential plane542int STLGeometry :: Project(Point<3> & p3d) const543{544Point<3> p, pf;545546int i, j;547int fi = 0;548int cnt = 0;549int different = 0;550const double lamtol = 1e-6;551552const STLChart& chart = GetChart(meshchart);553554int nt = chart.GetNT();555556QuadraticFunction3d quadfun(p3d, meshtrignv);557558/*559Vec3d hv = meshtrignv;560hv /= hv.Length();561Vec3d t1, t2;562hv.GetNormal (t1);563Cross (hv, t1, t2);564*/565566for (j = 1; j <= nt; j++)567{568i = chart.GetTrig(j);569570const Point<3> & c = GetTriangle(i).center;571/*572double d1 = t1 * (c-p3d);573double d2 = t2 * (c-p3d);574*/575/*576if (d1 * d1 + d2 * d2 > sqr (GetTriangle(i).rad))577continue;578*/579if (quadfun.Eval(c) > sqr (GetTriangle(i).rad))580continue;581582p = p3d;583Vec<3> lam;584int err = GetTriangle(i).ProjectInPlain(points, meshtrignv, p, lam);585int inside = (err == 0 && lam(0) > -lamtol &&586lam(1) > -lamtol && (1-lam(0)-lam(1)) > -lamtol);587588589/*590p = p3d;591GetTriangle(i).ProjectInPlain(points, meshtrignv, p);592if (GetTriangle(i).PointInside(points, p))593*/594if (inside)595{596if (cnt != 0)597{598if (Dist2(p,pf)>=1E-16)599{600// (*testout) << "ERROR: found two points to project which are different" << endl;601//(*testout) << "p=" << p << ", pf=" << pf << endl;602different = 1;603}604}605pf = p; fi = i; cnt++;606}607608if (inside)609break;610611}612613// if (cnt == 2) {(*testout) << "WARNING: found 2 triangles to project" << endl;}614//if (cnt == 3) {(*testout) << "WARNING: found 3 triangles to project" << endl;}615//if (cnt > 3) {(*testout) << "WARNING: found more than 3 triangles to project" << endl;}616617if (fi != 0) {lasttrig = fi;}618if (fi != 0 && !different) {p3d = pf; return fi;}619620// (*testout) << "WARNING: Project failed" << endl;621return 0;622623}624625//project normal to tangential plane626int STLGeometry :: ProjectOnWholeSurface(Point<3> & p3d) const627{628Point<3> p, pf;629630int i;631int fi = 0;632int cnt = 0;633int different = 0;634const double lamtol = 1e-6;635636for (i = 1; i <= GetNT(); i++)637{638p = p3d;639Vec<3> lam;640int err =641GetTriangle(i).ProjectInPlain(points, meshtrignv, p, lam);642int inside = (err == 0 && lam(0) > -lamtol &&643lam(1) > -lamtol && (1-lam(0)-lam(1)) > -lamtol);644645/*646p = p3d;647GetTriangle(i).ProjectInPlain(points, meshtrignv, p);648if (GetTriangle(i).PointInside(points, p))649*/650if (inside)651{652if (cnt != 0)653{654if (Dist2(p,pf)>=1E-16)655{656// (*testout) << "ERROR: found two points to project which are different" << endl;657// (*testout) << "p=" << p << ", pf=" << pf << endl;658different = 1;659}660}661pf = p; fi = i; cnt++;662}663}664/*665if (cnt == 2) {(*testout) << "WARNING: found 2 triangles to project" << endl;}666if (cnt == 3) {(*testout) << "WARNING: found 3 triangles to project" << endl;}667if (cnt > 3) {(*testout) << "WARNING: found more than 3 triangles to project" << endl;}668*/669if (fi != 0) {lasttrig = fi;}670if (fi != 0 && !different) {p3d = pf; return fi;}671672// (*testout) << "WARNING: Project failed" << endl;673return 0;674675}676677678int STLGeometry :: ProjectNearest(Point<3> & p3d) const679{680Point<3> p, pf;681682//set new chart683const STLChart& chart = GetChart(meshchart);684int i;685double nearest = 1E50;686double dist;687int ft = 0;688689for (i = 1; i <= chart.GetNT(); i++)690{691p = p3d;692dist = GetTriangle(chart.GetTrig(i)).GetNearestPoint(points, p);693if (dist < nearest)694{695pf = p;696nearest = dist;697ft = chart.GetTrig(i);698}699}700p3d = pf;701//if (!ft) {(*testout) << "ERROR: ProjectNearest failed" << endl;}702703return ft;704}705706707708709//Restrict local h due to curvature for make atlas710void STLGeometry :: RestrictLocalHCurv(class Mesh & mesh, double gh)711{712PushStatusF("Restrict H due to surface curvature");713714//bei jedem Dreieck alle Nachbardreiecke vergleichen, und, fallskein Kante dazwischen,715//die Meshsize auf ein bestimmtes Mass limitieren716int i,j;717718int ap1,ap2,p3,p4;719Point<3> p1p, p2p, p3p, p4p;720Vec<3> n, ntn;721double rzyl, localh;722723// double localhfact = 0.5;724// double geometryignorelength = 1E-4;725double minlocalh = stlparam.atlasminh;726727Box<3> bb = GetBoundingBox();728// mesh.SetLocalH(bb.PMin() - Vec3d(10, 10, 10),bb.PMax() + Vec3d(10, 10, 10),729// mparam.grading);730731// mesh.SetGlobalH(gh);732733double mincalch = 1E10;734double maxcalch = -1E10;735736double objectsize = bb.Diam();737double geometryignoreedgelength = objectsize * 1e-5;738739740if (stlparam.resthatlasenable)741{742ARRAY<double> minh; //minimales h pro punkt743minh.SetSize(GetNP());744for (i = 1; i <= GetNP(); i++)745{746minh.Elem(i) = gh;747}748749for (i = 1; i <= GetNT(); i++)750{751SetThreadPercent((double)i/(double)GetNT()*100.);752753if (multithread.terminate)754{PopStatus(); return;}755756const STLTriangle& trig = GetTriangle(i);757n = GetTriangle(i).Normal();758for (j = 1; j <= 3; j++)759{760const STLTriangle& nt = GetTriangle(NeighbourTrig(i,j));761762trig.GetNeighbourPointsAndOpposite(nt,ap1,ap2,p3);763764//checken, ob ap1-ap2 eine Kante sind765if (IsEdge(ap1,ap2)) continue;766767p4 = trig.PNum(1) + trig.PNum(2) + trig.PNum(3) - ap1 - ap2;768769p1p = GetPoint(ap1); p2p = GetPoint(ap2);770p3p = GetPoint(p3); p4p = GetPoint(p4);771772double h1 = GetDistFromInfiniteLine(p1p,p2p, p4p);773double h2 = GetDistFromInfiniteLine(p1p,p2p, p3p);774double diaglen = Dist (p1p, p2p);775776if (diaglen < geometryignoreedgelength)777continue;778rzyl = ComputeCylinderRadius779(n, GetTriangle(NeighbourTrig(i,j)).Normal(),780h1, h2);781782783if (h1 < 1e-3 * diaglen && h2 < 1e-3 * diaglen)784continue;785if (h1 < 1e-5 * objectsize && h2 < 1e-5 * objectsize)786continue;787788789// rzyl = mindist/(2*sinang);790localh = 10.*rzyl / stlparam.resthatlasfac;791if (localh < mincalch) {mincalch = localh;}792if (localh > maxcalch) {maxcalch = localh;}793794if (localh < minlocalh) {localh = minlocalh;}795if (localh < gh)796{797minh.Elem(ap1) = min2(minh.Elem(ap1),localh);798minh.Elem(ap2) = min2(minh.Elem(ap2),localh);799}800801mesh.RestrictLocalHLine(p1p, p2p, localh);802}803804}805}806PrintMessage(5, "done\nATLAS H: nmin local h=", mincalch);807PrintMessage(5, "ATLAS H: max local h=", maxcalch);808PrintMessage(5, "Local h tree has ", mesh.LocalHFunction().GetNBoxes(), " boxes of size ",809(int)sizeof(GradingBox));810811PopStatus();812813}814//restrict local h due to near edges and due to outer chart distance815void STLGeometry :: RestrictLocalH(class Mesh & mesh, double gh)816{817818//bei jedem Dreieck alle Nachbardreiecke vergleichen, und, fallskein Kante dazwischen,819//die Meshsize auf ein bestimmtes Mass limitieren820int i,j;821822int ap1,ap2,p3,p4;823Point3d p1p, p2p, p3p, p4p;824Vec3d n, ntn;825double rzyl, localh;826827// double localhfact = 0.5;828// double geometryignorelength = 1E-4;829830Box<3> bb = GetBoundingBox();831//mesh.SetLocalH(bb.PMin() - Vec3d(10, 10, 10),bb.PMax() + Vec3d(10, 10, 10),832// mparam.grading);833834//mesh.SetGlobalH(gh);835836double mincalch = 1E10;837double maxcalch = -1E10;838839double objectsize = bb.Diam();840double geometryignoreedgelength = objectsize * 1e-5;841842if (stlparam.resthsurfcurvenable)843{844PushStatusF("Restrict H due to surface curvature");845846ARRAY<double> minh; //minimales h pro punkt847minh.SetSize(GetNP());848for (i = 1; i <= GetNP(); i++)849{850minh.Elem(i) = gh;851}852853for (i = 1; i <= GetNT(); i++)854{855SetThreadPercent((double)i/(double)GetNT()*100.);856if (i%20000==19999) {PrintMessage(7, (double)i/(double)GetNT()*100. , "%");}857858if (multithread.terminate)859{PopStatus(); return;}860861const STLTriangle& trig = GetTriangle(i);862n = GetTriangle(i).Normal();863for (j = 1; j <= 3; j++)864{865const STLTriangle& nt = GetTriangle(NeighbourTrig(i,j));866867trig.GetNeighbourPointsAndOpposite(nt,ap1,ap2,p3);868869//checken, ob ap1-ap2 eine Kante sind870if (IsEdge(ap1,ap2)) continue;871872p4 = trig.PNum(1) + trig.PNum(2) + trig.PNum(3) - ap1 - ap2;873874p1p = GetPoint(ap1); p2p = GetPoint(ap2);875p3p = GetPoint(p3); p4p = GetPoint(p4);876877double h1 = GetDistFromInfiniteLine(p1p,p2p, p4p);878double h2 = GetDistFromInfiniteLine(p1p,p2p, p3p);879double diaglen = Dist (p1p, p2p);880881if (diaglen < geometryignoreedgelength)882continue;883rzyl = ComputeCylinderRadius884(n, GetTriangle (NeighbourTrig(i,j)).Normal(),885h1, h2);886887888if (h1 < 1e-3 * diaglen && h2 < 1e-3 * diaglen)889continue;890891if (h1 < 1e-5 * objectsize && h2 < 1e-5 * objectsize)892continue;893894895// rzyl = mindist/(2*sinang);896localh = rzyl / stlparam.resthsurfcurvfac;897if (localh < mincalch) {mincalch = localh;}898if (localh > maxcalch) {maxcalch = localh;}899if (localh < gh)900{901minh.Elem(ap1) = min2(minh.Elem(ap1),localh);902minh.Elem(ap2) = min2(minh.Elem(ap2),localh);903}904905//if (localh < 0.2) {localh = 0.2;}906907if(localh < objectsize)908mesh.RestrictLocalHLine(p1p, p2p, localh);909(*testout) << "restrict h along " << p1p << " - " << p2p << " to " << localh << endl;910911if (localh < 0.1)912{913localh = 0.1;914}915916}917}918PrintMessage(7, "done\nmin local h=", mincalch, "\nmax local h=", maxcalch);919PopStatus();920}921922if (stlparam.resthcloseedgeenable)923{924PushStatusF("Restrict H due to close edges");925//geht nicht f�r spiralen!!!!!!!!!!!!!!!!!!926927double disttohfact = sqr(10.0 / stlparam.resthcloseedgefac);928int k,l;929double h1, h2, dist;930int rc = 0;931Point3d p3p1;932double mindist = 1E50;933934PrintMessage(7,"build search tree...");935Box3dTree* lsearchtree = new Box3dTree (GetBoundingBox().PMin() - Vec3d(1,1,1),936GetBoundingBox().PMax() + Vec3d(1,1,1));937938ARRAY<Point3d> pmins(GetNLines());939ARRAY<Point3d> pmaxs(GetNLines());940941double maxhline;942for (i = 1; i <= GetNLines(); i++)943{944maxhline = 0;945STLLine* l1 = GetLine(i);946Point3d pmin(GetPoint(l1->StartP())), pmax(GetPoint(l1->StartP())), px;947948for (j = 2; j <= l1->NP(); j++)949{950px = GetPoint(l1->PNum(j));951maxhline = max2(maxhline,mesh.GetH(px));952pmin.SetToMin (px);953pmax.SetToMax (px);954}955Box3d box(pmin,pmax);956box.Increase(maxhline);957958lsearchtree->Insert (box.PMin(), box.PMax(), i);959pmins.Elem(i) = box.PMin();960pmaxs.Elem(i) = box.PMax();961}962963ARRAY<int> linenums;964int k2;965966for (i = 1; i <= GetNLines(); i++)967{968SetThreadPercent((double)i/(double)GetNLines()*100.);969if (multithread.terminate)970{PopStatus(); return;}971972linenums.SetSize(0);973lsearchtree->GetIntersecting(pmins.Get(i),pmaxs.Get(i),linenums);974975STLLine* l1 = GetLine(i);976for (j = 1; j <= l1->NP(); j++)977{978p3p1 = GetPoint(l1->PNum(j));979h1 = sqr(mesh.GetH(p3p1));980981for (k2 = 1; k2 <= linenums.Size(); k2++)982{983k = linenums.Get(k2);984if (k <= i) {continue;}985/*986//old, without searchtrees987for (k = i+1; k <= GetNLines(); k++)988{989*/990STLLine* l2 = GetLine(k);991for (l = 1; l <= l2->NP(); l++)992{993const Point3d& p3p2 = GetPoint(l2->PNum(l));994h2 = sqr(mesh.GetH(p3p2));995dist = Dist2(p3p1,p3p2)*disttohfact;996if (dist > 1E-12)997{998if (dist < h1)999{1000mesh.RestrictLocalH(p3p1,sqrt(dist));1001rc++;1002mindist = min2(mindist,sqrt(dist));1003}1004if (dist < h2)1005{1006mesh.RestrictLocalH(p3p2,sqrt(dist));1007rc++;1008mindist = min2(mindist,sqrt(dist));1009}1010}1011}1012}1013}1014}1015PrintMessage(5, "done\n Restricted h in ", rc, " points due to near edges!");1016PopStatus();1017}10181019if (stlparam.resthedgeangleenable)1020{1021PushStatusF("Restrict h due to close edges");10221023int lp1, lp2;1024Vec3d v1,v2;1025mincalch = 1E50;1026maxcalch = -1E50;10271028for (i = 1; i <= GetNP(); i++)1029{1030SetThreadPercent((double)i/(double)GetNP()*100.);1031if (multithread.terminate)1032{PopStatus(); return;}10331034if (GetNEPP(i) == 2 && !IsLineEndPoint(i))1035{1036if (GetEdge(GetEdgePP(i,1)).PNum(2) == GetEdge(GetEdgePP(i,2)).PNum(1) ||1037GetEdge(GetEdgePP(i,1)).PNum(1) == GetEdge(GetEdgePP(i,2)).PNum(2))1038{1039lp1 = 1; lp2 = 2;1040}1041else1042{1043lp1 = 2; lp2 = 1;1044}10451046v1 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,1)).PNum(1)),1047GetPoint(GetEdge(GetEdgePP(i,1)).PNum(2)));1048v2 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp1)),1049GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp2)));10501051rzyl = ComputeCylinderRadius(v1, v2, v1.Length(), v2.Length());10521053localh = rzyl / stlparam.resthedgeanglefac;1054if (localh < mincalch) {mincalch = localh;}1055if (localh > maxcalch) {maxcalch = localh;}10561057if (localh != 0)1058mesh.RestrictLocalH(GetPoint(i), localh);1059}1060}1061PrintMessage(7,"edge-angle min local h=", mincalch, "\nedge-angle max local h=", maxcalch);1062PopStatus();1063}10641065if (stlparam.resthchartdistenable)1066{1067PushStatusF("Restrict H due to outer chart distance");10681069// mesh.LocalHFunction().Delete();10701071//berechne minimale distanz von chart zu einem nicht-outerchart-punkt in jedem randpunkt einer chart10721073ARRAY<int> acttrigs; //outercharttrigs1074acttrigs.SetSize(GetNT());1075for (i = 1; i <= GetNT(); i++)1076{1077acttrigs.Elem(i) = 0;1078}1079for (i = 1; i <= GetNOCharts(); i++)1080{1081SetThreadPercent((double)i/(double)GetNOCharts()*100.);1082if (multithread.terminate)1083{PopStatus(); return;}10841085RestrictHChartDistOneChart(i, acttrigs, mesh, gh, 1., 0.);1086}10871088PopStatus();1089}10901091if (stlparam.resthlinelengthenable)1092{1093//restrict h due to short lines1094PushStatusF("Restrict H due to line-length");10951096double minhl = 1E50;1097double linefact = 1./stlparam.resthlinelengthfac;1098double l;1099for (i = 1; i <= GetNLines(); i++)1100{1101SetThreadPercent((double)i/(double)GetNLines()*100.);1102if (multithread.terminate)1103{PopStatus(); return;}11041105l = GetLine(i)->GetLength(points);11061107const Point3d& pp1 = GetPoint(GetLine(i)->StartP());1108const Point3d& pp2 = GetPoint(GetLine(i)->EndP());11091110if (l != 0)1111{1112minhl = min2(minhl,l*linefact);11131114mesh.RestrictLocalH(pp1, l*linefact);1115mesh.RestrictLocalH(pp2, l*linefact);1116}1117}1118PopStatus();1119PrintMessage(5, "minh due to line length=", minhl);1120}1121}11221123void STLGeometry :: RestrictHChartDistOneChart(int chartnum, ARRAY<int>& acttrigs,1124class Mesh & mesh, double gh, double fact, double minh)1125{1126int i = chartnum;1127int j;11281129double limessafety = stlparam.resthchartdistfac*fact; // original: 21130double localh;11311132double f1,f2;1133// mincalch = 1E10;1134//maxcalch = -1E10;1135ARRAY<int> limes1;1136ARRAY<int> limes2;11371138ARRAY<Point3d> plimes1;1139ARRAY<Point3d> plimes2;11401141ARRAY<int> plimes1trigs; //check from wich trig the points come1142ARRAY<int> plimes2trigs;11431144ARRAY<int> plimes1origin; //either the original pointnumber or zero, if new point11451146int divisions = 10;11471148int k, t, nt, np1, np2;1149Point3d p3p1, p3p2;1150STLTriangle tt;11511152limes1.SetSize(0);1153limes2.SetSize(0);1154plimes1.SetSize(0);1155plimes2.SetSize(0);1156plimes1trigs.SetSize(0);1157plimes2trigs.SetSize(0);1158plimes1origin.SetSize(0);11591160STLChart& chart = GetChart(i);1161chart.ClearOLimit();1162chart.ClearILimit();11631164for (j = 1; j <= chart.GetNChartT(); j++)1165{1166t = chart.GetChartTrig(j);1167tt = GetTriangle(t);1168for (k = 1; k <= 3; k++)1169{1170nt = NeighbourTrig(t,k);1171if (GetChartNr(nt) != i)1172{1173tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);1174if (!IsEdge(np1,np2) && !GetSpiralPoint(np1) && !GetSpiralPoint(np2))1175{1176p3p1 = GetPoint(np1);1177p3p2 = GetPoint(np2);1178if (AddIfNotExists(limes1,np1))1179{1180plimes1.Append(p3p1);1181plimes1trigs.Append(t);1182plimes1origin.Append(np1);1183}1184if (AddIfNotExists(limes1,np2))1185{1186plimes1.Append(p3p2);1187plimes1trigs.Append(t);1188plimes1origin.Append(np2);1189}1190chart.AddILimit(twoint(np1,np2));11911192for (int di = 1; di <= divisions; di++)1193{1194f1 = (double)di/(double)(divisions+1.);1195f2 = (divisions+1.-(double)di)/(double)(divisions+1.);11961197plimes1.Append(Point3d(p3p1.X()*f1+p3p2.X()*f2,1198p3p1.Y()*f1+p3p2.Y()*f2,1199p3p1.Z()*f1+p3p2.Z()*f2));1200plimes1trigs.Append(t);1201plimes1origin.Append(0);1202}1203}1204}1205}1206}120712081209for (j = 1; j <= chart.GetNT(); j++)1210{1211acttrigs.Elem(chart.GetTrig(j)) = i;1212}12131214for (j = 1; j <= chart.GetNOuterT(); j++)1215{1216t = chart.GetOuterTrig(j);1217tt = GetTriangle(t);1218for (k = 1; k <= 3; k++)1219{1220nt = NeighbourTrig(t,k);12211222if (acttrigs.Get(nt) != i)1223{1224tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);12251226if (!IsEdge(np1,np2))1227{1228p3p1 = GetPoint(np1);1229p3p2 = GetPoint(np2);12301231if (AddIfNotExists(limes2,np1)) {plimes2.Append(p3p1); plimes2trigs.Append(t);}1232if (AddIfNotExists(limes2,np2)) {plimes2.Append(p3p2); plimes2trigs.Append(t);}1233chart.AddOLimit(twoint(np1,np2));12341235for (int di = 1; di <= divisions; di++)1236{1237f1 = (double)di/(double)(divisions+1.);1238f2 = (divisions+1.-(double)di)/(double)(divisions+1.);12391240plimes2.Append(Point3d(p3p1.X()*f1+p3p2.X()*f2,1241p3p1.Y()*f1+p3p2.Y()*f2,1242p3p1.Z()*f1+p3p2.Z()*f2));1243plimes2trigs.Append(t);1244}1245}1246}1247}1248}124912501251double chartmindist = 1E50;12521253if (plimes2.Size())1254{1255Box3d bbox;1256bbox.SetPoint (plimes2.Get(1));1257for (j = 2; j <= plimes2.Size(); j++)1258bbox.AddPoint (plimes2.Get(j));1259Point3dTree stree(bbox.PMin(), bbox.PMax());1260for (j = 1; j <= plimes2.Size(); j++)1261stree.Insert (plimes2.Get(j), j);1262ARRAY<int> foundpts;12631264for (j = 1; j <= plimes1.Size(); j++)1265{1266double mindist = 1E50;1267double dist;12681269const Point3d & ap1 = plimes1.Get(j);1270double boxs = mesh.GetH (plimes1.Get(j)) * limessafety;12711272Point3d pmin = ap1 - Vec3d (boxs, boxs, boxs);1273Point3d pmax = ap1 + Vec3d (boxs, boxs, boxs);12741275stree.GetIntersecting (pmin, pmax, foundpts);127612771278for (int kk = 1; kk <= foundpts.Size(); kk++)1279{1280k = foundpts.Get(kk);1281dist = Dist2(plimes1.Get(j),plimes2.Get(k));1282if (dist < mindist)1283{1284mindist = dist;1285}1286}12871288/*1289const Point3d & ap1 = plimes1.Get(j);1290double his = mesh.GetH (plimes1.Get(j));12911292double xmin = ap1.X() - his * limessafety;1293double xmax = ap1.X() + his * limessafety;1294double ymin = ap1.Y() - his * limessafety;1295double ymax = ap1.Y() + his * limessafety;1296double zmin = ap1.Z() - his * limessafety;1297double zmax = ap1.Z() + his * limessafety;12981299for (k = 1; k <= plimes2.Size(); k++)1300{1301const Point3d & ap2 = plimes2.Get(k);1302if (ap2.X() >= xmin && ap2.X() <= xmax &&1303ap2.Y() >= ymin && ap2.Y() <= ymax &&1304ap2.Z() >= zmin && ap2.Z() <= zmax)1305{1306dist = Dist2(plimes1.Get(j),plimes2.Get(k));1307if (dist < mindist)1308{1309mindist = dist;1310}1311}1312}1313*/1314mindist = sqrt(mindist);1315localh = mindist/limessafety;13161317if (localh < minh && localh != 0) {localh = minh;} //minh is generally 0! (except make atlas)1318if (localh < gh && localh > 0)1319{1320mesh.RestrictLocalH(plimes1.Get(j), localh);1321// if (mindist < mincalch) {mincalch = mindist;}1322// if (mindist > maxcalch) {maxcalch = mindist;}1323if (mindist < chartmindist) {chartmindist = mindist;}1324}1325}1326}13271328}132913301331//void * STLMeshingDummy (void *)1332int STLMeshingDummy (STLGeometry* stlgeometry, Mesh*& mesh,1333int perfstepsstart, int perfstepsend, char* optstring)1334{1335if (perfstepsstart > perfstepsend) return 0;13361337multithread.terminate = 0;1338int success = 1;1339//int trialcntouter = 0;13401341if (perfstepsstart <= MESHCONST_MESHEDGES)1342{13431344mesh = new Mesh();1345mesh -> SetGlobalH (mparam.maxh);1346mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10),1347stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10),1348mparam.grading);1349mesh -> LoadLocalMeshSize (mparam.meshsizefilename);13501351success = 0;13521353//mesh->DeleteMesh();13541355STLMeshing (*stlgeometry, *mesh);13561357stlgeometry->edgesfound = 1;1358stlgeometry->surfacemeshed = 0;1359stlgeometry->surfaceoptimized = 0;1360stlgeometry->volumemeshed = 0;1361}13621363if (multithread.terminate)1364return 0;13651366if (perfstepsstart <= MESHCONST_MESHSURFACE &&1367perfstepsend >= MESHCONST_MESHSURFACE)1368{13691370if (!stlgeometry->edgesfound)1371{1372PrintUserError("You have to do 'analyse geometry' first!!!");1373return 0;1374}1375if (stlgeometry->surfacemeshed || stlgeometry->surfacemeshed)1376{1377PrintUserError("Already meshed. Please start again with 'Analyse Geometry'!!!");1378return 0;1379}13801381success = 0;1382int retval = STLSurfaceMeshing (*stlgeometry, *mesh);1383if (retval == MESHING3_OK)1384{1385PrintMessage(3,"Success !!!!");1386stlgeometry->surfacemeshed = 1;1387stlgeometry->surfaceoptimized = 0;1388stlgeometry->volumemeshed = 0;1389success = 1;1390}1391else if (retval == MESHING3_OUTERSTEPSEXCEEDED)1392{1393PrintError("Give up because of too many trials. Meshing aborted!");1394}1395else if (retval == MESHING3_TERMINATE)1396{1397PrintWarning("Meshing Stopped by user!");1398}1399else1400{1401PrintError("Surface meshing not successful. Meshing aborted!");1402}14031404#ifdef STAT_STREAM1405(*statout) << mesh->GetNSeg() << " & " << endl1406<< mesh->GetNSE() << " & " << endl1407<< GetTime() << " & ";1408#endif1409}1410if (multithread.terminate)1411return 0;14121413if (success)1414{1415if (perfstepsstart <= MESHCONST_OPTSURFACE &&1416perfstepsend >= MESHCONST_OPTSURFACE)1417{1418if (!stlgeometry->edgesfound)1419{1420PrintUserError("You have to do 'meshing->analyse geometry' first!!!");1421return 0;1422}1423if (!stlgeometry->surfacemeshed)1424{1425PrintUserError("You have to do 'meshing->mesh surface' first!!!");1426return 0;1427}1428if (stlgeometry->volumemeshed)1429{1430PrintWarning("Surface optimization with meshed volume is dangerous!!!");1431}14321433if (!optstring || strlen(optstring) == 0)1434{1435mparam.optimize2d = "smcm";1436}1437else1438{1439mparam.optimize2d = optstring;1440}14411442STLSurfaceOptimization (*stlgeometry, *mesh, mparam);14431444if (stlparam.recalc_h_opt)1445{1446mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10),1447stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10),1448mparam.grading);1449mesh -> LoadLocalMeshSize (mparam.meshsizefilename);1450mesh -> CalcLocalHFromSurfaceCurvature (stlparam.resthsurfmeshcurvfac);1451mparam.optimize2d = "cmsmSm";1452STLSurfaceOptimization (*stlgeometry, *mesh, mparam);1453#ifdef STAT_STREAM1454(*statout) << GetTime() << " & ";1455#endif14561457#ifdef OPENGL1458extern void Render();1459Render();1460#endif1461}1462stlgeometry->surfaceoptimized = 1;1463}1464if (multithread.terminate)1465return 0;14661467if (perfstepsstart <= MESHCONST_MESHVOLUME &&1468perfstepsend >= MESHCONST_MESHVOLUME)1469{1470if (stlgeometry->volumemeshed)1471{1472PrintUserError("Volume already meshed!"); return 0;1473}14741475if (!stlgeometry->edgesfound)1476{1477PrintUserError("You have to do 'meshing->analyse geometry' first!!!");1478return 0;1479}1480if (!stlgeometry->surfacemeshed)1481{1482PrintUserError("You have to do 'meshing->mesh surface' first!!!");1483return 0;1484}1485if (!stlgeometry->surfaceoptimized)1486{1487PrintWarning("You should do 'meshing->optimize surface' first!!!");1488}148914901491PrintMessage(5,"Check Overlapping boundary: ");1492mesh->FindOpenElements();1493mesh->CheckOverlappingBoundary();1494PrintMessage(5,"");149514961497if (stlparam.recalc_h_opt)1498{1499mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10),1500stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10),1501mparam.grading);1502mesh -> LoadLocalMeshSize (mparam.meshsizefilename);1503mesh -> CalcLocalH ();1504}150515061507PrintMessage(5,"Volume meshing");1508int retval = MeshVolume (mparam, *mesh);1509if (retval == MESHING3_OK)1510{1511RemoveIllegalElements(*mesh);1512stlgeometry->volumemeshed = 1;1513}1514else if (retval == MESHING3_OUTERSTEPSEXCEEDED)1515{1516PrintError("Give up because of too many trials. Meshing aborted!");1517return 0;1518}1519else if (retval == MESHING3_TERMINATE)1520{1521PrintWarning("Meshing Stopped by user!");1522}1523else1524{1525PrintError("Volume meshing not successful. Meshing aborted!");1526return 0;1527}15281529#ifdef STAT_STREAM1530(*statout) << GetTime() << " & " << endl;1531#endif1532MeshQuality3d (*mesh);1533}15341535if (multithread.terminate)1536return 0;15371538if (perfstepsstart <= MESHCONST_OPTVOLUME &&1539perfstepsend >= MESHCONST_OPTVOLUME)1540{1541if (!stlgeometry->edgesfound)1542{1543PrintUserError("You have to do 'meshing->analyse geometry' first!!!");1544return 0;1545}1546if (!stlgeometry->surfacemeshed)1547{1548PrintUserError("You have to do 'meshing->mesh surface' first!!!");1549return 0;1550}1551if (!stlgeometry->volumemeshed)1552{1553PrintUserError("You have to do 'meshing->mesh volume' first!!!");1554return 0;1555}15561557if (!optstring || strlen(optstring) == 0)1558{1559mparam.optimize3d = "cmdmstm";1560}1561else1562{1563mparam.optimize3d = optstring;1564}156515661567OptimizeVolume (mparam, *mesh);15681569#ifdef STAT_STREAM1570(*statout) << GetTime() << " & " << endl;1571(*statout) << mesh->GetNE() << " & " << endl1572<< mesh->GetNP() << " " << '\\' << '\\' << " \\" << "hline" << endl;1573#endif15741575#ifdef OPENGL1576extern void Render();1577Render();1578#endif15791580}1581}158215831584return 0;1585}1586158715881589}159015911592