Path: blob/devel/ElmerGUI/netgen/libsrc/stlgeom/stlgeomchart.cpp
3206 views
//20.11.1999 third part of stlgeom.cc, functions with chart and atlas12#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{1415int chartdebug = 0;16171819void STLGeometry :: MakeAtlas(Mesh & mesh)20{2122double h, h2;2324h = mparam.maxh;252627PushStatusF("Make Atlas");2829int i,j,k,l;3031double atlasminh = 5e-3 * Dist (boundingbox.PMin(), boundingbox.PMax());32PrintMessage(5, "atlasminh = ", atlasminh);3334//speedup for make atlas35if (GetNT() > 50000)36{37mesh.SetGlobalH(0.05*Dist (boundingbox.PMin(), boundingbox.PMax()));38}394041atlas.SetSize(0);42ClearSpiralPoints();43BuildSmoothEdges();444546double chartangle = stlparam.chartangle;47double outerchartangle = stlparam.outerchartangle;4849chartangle = chartangle/180.*M_PI;50outerchartangle = outerchartangle/180.*M_PI;5152double coschartangle = cos(chartangle);53double cosouterchartangle = cos(outerchartangle);54double cosouterchartanglehalf = cos(0.5*outerchartangle);55double sinchartangle = sin(chartangle);56double sinouterchartangle = sin(outerchartangle);5758ARRAY<int> outermark(GetNT()); //marks all trigs form actual outer region59ARRAY<int> outertested(GetNT()); //marks tested trigs for outer region60ARRAY<int> pointstochart(GetNP()); //point in chart becomes chartnum61ARRAY<int> innerpointstochart(GetNP()); //point in chart becomes chartnum62ARRAY<int> chartpoints; //point in chart becomes chartnum63ARRAY<int> innerchartpoints;64ARRAY<int> dirtycharttrigs;65ARRAY<int> chartpointchecked;6667ARRAY<int> chartdistacttrigs; //outercharttrigs68chartdistacttrigs.SetSize(GetNT());69for (i = 1; i <= GetNT(); i++)70{71chartdistacttrigs.Elem(i) = 0;72}7374STLBoundary chartbound(this); //knows the actual chart boundary75//int chartboundarydivisions = 10;76markedsegs.SetSize(0); //for testing!!!7778chartpointchecked.SetSize(GetNP()); //for dirty-chart-trigs7980outermark.SetSize(GetNT());81outertested.SetSize(GetNT());82pointstochart.SetSize(GetNP());83innerpointstochart.SetSize(GetNP());84chartmark.SetSize(GetNT());8586for (i = 1; i <= GetNP(); i++)87{88innerpointstochart.Elem(i) = 0;89pointstochart.Elem(i) = 0;90chartpointchecked.Elem(i) = 0;91}9293double eps = 1e-12 * Dist (boundingbox.PMin(), boundingbox.PMax());9495int spiralcheckon = stldoctor.spiralcheck;96if (!spiralcheckon) {PrintWarning("++++++++++++\nspiral deactivated by user!!!!\n+++++++++++++++"); }9798for (i = 1; i <= GetNT(); i++)99{100chartmark.Elem(i) = 0;101}102103for (i = 1; i <= GetNT(); i++)104{105outermark.Elem(i) = 0;106outertested.Elem(i) = 0;107}108109int markedtrigcnt = 0;110int found = 1;111double atlasarea = Area();112double workedarea = 0;113double showinc = 100.*5000./(double)GetNT();114double nextshow = 0;115Point<3> startp;116int lastunmarked = 1;117int prelastunmarked;118119PrintMessage(5,"one dot per 5000 triangles: ");120121while(markedtrigcnt < GetNT() && found)122{123if (multithread.terminate)124{PopStatus();return;}125126if (workedarea / atlasarea*100. >= nextshow)127{PrintDot(); nextshow+=showinc;}128129SetThreadPercent(100.0 * workedarea / atlasarea);130131/*132for (j = 1; j <= GetNT(); j++)133{134outermark.Elem(j) = 0;135}136*/137STLChart * chart = new STLChart(this);138atlas.Append(chart);139140//find unmarked trig141prelastunmarked = lastunmarked;142j = lastunmarked;143found = 0;144while (!found && j <= GetNT())145{146if (!GetMarker(j)) {found = 1; lastunmarked = j;}147else {j++;}148}149150chartpoints.SetSize(0);151innerchartpoints.SetSize(0);152chartbound.Clear();153chartbound.SetChart(chart);154155if (!found) {PrintSysError("Make Atlas, no starttrig found"); return;}156157//find surrounding trigs158int starttrig = j;159160double tdist;161startp = GetPoint(GetTriangle(starttrig).PNum(1));162163int accepted;164int chartnum = GetNOCharts();165166Vec<3> sn = GetTriangle(starttrig).Normal();167chart->SetNormal (startp, sn);168169170SetMarker(starttrig, chartnum);171markedtrigcnt++;172chart->AddChartTrig(starttrig);173chartbound.AddTriangle(GetTriangle(starttrig));174175workedarea += GetTriangle(starttrig).Area(points);176177for (i = 1; i <= 3; i++)178{179innerpointstochart.Elem(GetTriangle(starttrig).PNum(i)) = chartnum;180pointstochart.Elem(GetTriangle(starttrig).PNum(i)) = chartnum;181chartpoints.Append(GetTriangle(starttrig).PNum(i));182innerchartpoints.Append(GetTriangle(starttrig).PNum(i));183}184185Vec<3> n2, n3;186int changed = 1;187int nt;188int ic;189int oldstartic = 1;190int oldstartic2;191int np1, np2;192193while (changed)194{195changed = 0;196oldstartic2 = oldstartic;197oldstartic = chart->GetNT();198// for (ic = oldstartic2; ic <= chart->GetNT(); ic++)199for (ic = oldstartic2; ic <= oldstartic; ic++)200{201i = chart->GetTrig(ic);202if (GetMarker(i) == chartnum)203{204for (j = 1; j <= NONeighbourTrigs(i); j++)205{206nt = NeighbourTrig(i,j);207GetTriangle(i).GetNeighbourPoints(GetTriangle(nt),np1,np2);208if (GetMarker(nt) == 0 && !IsEdge(np1,np2))209{210n2 = GetTriangle(nt).Normal();211if ( (n2 * sn) >= coschartangle )212{213214accepted = 1;215/*216//alter spiralentest, schnell, aber ungenau217for (k = 1; k <= 3; k++)218{219//find overlapping charts:220Point3d pt = GetPoint(GetTriangle(nt).PNum(k));221if (innerpointstochart.Get(GetTriangle(nt).PNum(k)) != chartnum)222{223for (l = 1; l <= chartpoints.Size(); l++)224{225Vec3d vptpl(GetPoint(chartpoints.Get(l)), pt);226double vlen = vptpl.Length();227if (vlen > 0)228{229vptpl /= vlen;230if ( fabs( vptpl * sn) > sinchartangle )231{232accepted = 0;233break;234}235}236}237238}239}240*/241242int nnp1, nnp2;243int nnt;244//find overlapping charts exacter:245for (k = 1; k <= 3; k++)246{247nnt = NeighbourTrig(nt,k);248if (GetMarker(nnt) != chartnum)249{250GetTriangle(nt).GetNeighbourPoints(GetTriangle(nnt),nnp1,nnp2);251252accepted = chartbound.TestSeg(GetPoint(nnp1),253GetPoint(nnp2),254sn,sinchartangle,1 /*chartboundarydivisions*/ ,points, eps);255256257n3 = GetTriangle(nnt).Normal();258if ( (n3 * sn) >= coschartangle &&259IsSmoothEdge (nnp1, nnp2) )260accepted = 1;261}262if (!accepted) {break;}263}264265/*266mindist = 1E50;267for (int ii = 1; ii <= 3; ii++)268{269tdist = Dist(GetPoint(GetTriangle(nt).PNum(ii)),startp);270if (tdist < mindist) {mindist = tdist;}271}272if (mindist > maxdist1) {accepted = 0;}273*/274275if (accepted)276{277SetMarker(nt, chartnum);278changed = 1;279markedtrigcnt++;280workedarea += GetTriangle(nt).Area(points);281chart->AddChartTrig(nt);282283chartbound.AddTriangle(GetTriangle(nt));284285for (k = 1; k <= 3; k++)286{287if (innerpointstochart.Get(GetTriangle(nt).PNum(k))288!= chartnum)289{290innerpointstochart.Elem(GetTriangle(nt).PNum(k)) = chartnum;291pointstochart.Elem(GetTriangle(nt).PNum(k)) = chartnum;292chartpoints.Append(GetTriangle(nt).PNum(k));293innerchartpoints.Append(GetTriangle(nt).PNum(k));294}295}296}297}298}299}300}301}302}303304305//find outertrigs306307// chartbound.Clear();308// warum, ic-bound auf edge macht Probleme js ???309310311outermark.Elem(starttrig) = chartnum;312//chart->AddOuterTrig(starttrig);313changed = 1;314oldstartic = 1;315while (changed)316{317changed = 0;318oldstartic2 = oldstartic;319oldstartic = chart->GetNT();320//for (ic = oldstartic2; ic <= chart->GetNT(); ic++)321for (ic = oldstartic2; ic <= oldstartic; ic++)322{323i = chart->GetTrig(ic);324325if (outermark.Get(i) == chartnum)326{327for (j = 1; j <= NONeighbourTrigs(i); j++)328{329nt = NeighbourTrig(i,j);330if (outermark.Get(nt) == chartnum)331continue;332333const STLTriangle & ntrig = GetTriangle(nt);334GetTriangle(i).GetNeighbourPoints(GetTriangle(nt),np1,np2);335336if (IsEdge (np1, np2))337continue;338339340/*341if (outertested.Get(nt) == chartnum)342continue;343*/344outertested.Elem(nt) = chartnum;345346347n2 = GetTriangle(nt).Normal();348/*349double ang;350ang = Angle(n2,sn);351if (ang < -M_PI*0.5) {ang += 2*M_PI;}352353(*testout) << "ang < ocharang = " << (fabs(ang) <= outerchartangle);354(*testout) << " = " << ( (n2 * sn) >= cosouterchartangle) << endl;355356// if (fabs(ang) <= outerchartangle)357*/358//abfragen, ob noch im tolerierten Winkel359if ( (n2 * sn) >= cosouterchartangle )360{361accepted = 1;362363int isdirtytrig = 0;364Vec<3> gn = GetTriangle(nt).GeomNormal(points);365double gnlen = gn.Length();366367if (n2 * gn <= cosouterchartanglehalf * gnlen)368{isdirtytrig = 1;}369370//zurueckweisen, falls eine Spiralartige outerchart entsteht371int nnp1, nnp2;372int nnt;373//find overlapping charts exacter:374//do not check dirty trigs!375376377if (spiralcheckon && !isdirtytrig)378for (k = 1; k <= 3; k++)379{380nnt = NeighbourTrig(nt,k);381382if (outermark.Elem(nnt) != chartnum)383{384GetTriangle(nt).GetNeighbourPoints(GetTriangle(nnt),nnp1,nnp2);385386accepted =387chartbound.TestSeg(GetPoint(nnp1),GetPoint(nnp2),388sn,sinouterchartangle, 0 /*chartboundarydivisions*/ ,points, eps);389390391n3 = GetTriangle(nnt).Normal();392if ( (n3 * sn) >= cosouterchartangle &&393IsSmoothEdge (nnp1, nnp2) )394accepted = 1;395}396if (!accepted) {break;}397}398399//}400401402// outer chart is only small environment of403// inner chart:404if (accepted)405{406accepted = 0;407408for (k = 1; k <= 3; k++)409{410if (innerpointstochart.Get(ntrig.PNum(k)) == chartnum)411{412accepted = 1;413break;414}415}416417if (!accepted)418for (k = 1; k <= 3; k++)419{420Point<3> pt = GetPoint(ntrig.PNum(k));421h2 = sqr(mesh.GetH(pt));422423for (l = 1; l <= innerchartpoints.Size(); l++)424{425tdist = Dist2(pt, GetPoint (innerchartpoints.Get(l)));426if (tdist < 4 * h2)427{428accepted = 1;429break;430}431}432if (accepted) {break;}433}434}435436437if (accepted)438{439changed = 1;440outermark.Elem(nt) = chartnum;441442if (GetMarker(nt) != chartnum)443{444chartbound.AddTriangle(GetTriangle(nt));445chart->AddOuterTrig(nt);446for (k = 1; k <= 3; k++)447{448if (pointstochart.Get(GetTriangle(nt).PNum(k))449!= chartnum)450{451pointstochart.Elem(GetTriangle(nt).PNum(k)) = chartnum;452chartpoints.Append(GetTriangle(nt).PNum(k));453}454}455}456}457}458}459}460}461}462//end of while loop for outer chart463GetDirtyChartTrigs(chartnum, *chart, outermark, chartpointchecked, dirtycharttrigs);464//dirtycharttrigs are local (chart) point numbers!!!!!!!!!!!!!!!!465466if (dirtycharttrigs.Size() != 0 &&467(dirtycharttrigs.Size() != chart->GetNChartT() || dirtycharttrigs.Size() != 1))468{469if (dirtycharttrigs.Size() == chart->GetNChartT() && dirtycharttrigs.Size() != 1)470{471//if all trigs would be eliminated -> leave 1 trig!472dirtycharttrigs.SetSize(dirtycharttrigs.Size() - 1);473}474for (k = 1; k <= dirtycharttrigs.Size(); k++)475{476int tn = chart->GetChartTrig(dirtycharttrigs.Get(k));477outermark.Elem(tn) = 0; //not necessary, for later use478SetMarker(tn, 0);479markedtrigcnt--;480workedarea -= GetTriangle(tn).Area(points);481}482chart->MoveToOuterChart(dirtycharttrigs);483lastunmarked = 1;484lastunmarked = prelastunmarked;485}486487//calculate an estimate meshsize, not to produce to large outercharts, with factor 2 larger!488RestrictHChartDistOneChart(chartnum, chartdistacttrigs, mesh, h, 0.5, atlasminh);489}490491PrintMessage(5,"");492PrintMessage(5,"NO charts=", atlas.Size());493494int cnttrias = 0;495//int found2;496outerchartspertrig.SetSize(GetNT());497498for (i = 1; i <= atlas.Size(); i++)499{500//found2 = 1;501for (j = 1; j <= GetChart(i).GetNT(); j++)502{503int tn = GetChart(i).GetTrig(j);504AddOCPT(tn,i);505506}507508cnttrias += GetChart(i).GetNT();509}510PrintMessage(5, "NO outer chart trias=", cnttrias);511512//sort outerchartspertrig513for (i = 1; i <= GetNT(); i++)514{515int swap;516for (k = 1; k < GetNOCPT(i); k++)517{518519for (j = 1; j < GetNOCPT(i); j++)520{521swap = GetOCPT(i,j);522if (GetOCPT(i,j+1) < swap)523{524SetOCPT(i,j,GetOCPT(i,j+1));525SetOCPT(i,j+1,swap);526}527}528}529530// check make atlas531if (GetChartNr(i) <= 0 || GetChartNr(i) > GetNOCharts())532{533PrintSysError("Make Atlas: chartnr(", i, ")=0!!");534};535}536537mesh.SetGlobalH(mparam.maxh);538mesh.SetMinimalH(mparam.minh);539540541AddConeAndSpiralEdges();542543PrintMessage(5,"Make Atlas finished");544545PopStatus();546}547548549int STLGeometry::TrigIsInOC(int tn, int ocn) const550{551if (tn < 1 || tn > GetNT())552{553// assert (1);554abort ();555PrintSysError("STLGeometry::TrigIsInOC illegal tn: ", tn);556557return 0;558}559560/*561int firstval = 0;562int i;563for (i = 1; i <= GetNOCPT(tn); i++)564{565if (GetOCPT(tn, i) == ocn) {firstval = 1;}566}567*/568569int found = 0;570571int inc = 1;572while (inc <= GetNOCPT(tn)) {inc *= 2;}573inc /= 2;574575int start = inc;576577while (!found && inc > 0)578{579if (GetOCPT(tn,start) > ocn) {inc = inc/2; start -= inc;}580else if (GetOCPT(tn,start) < ocn) {inc = inc/2; if (start+inc <= GetNOCPT(tn)) {start += inc;}}581else {found = 1;}582}583584return GetOCPT(tn, start) == ocn;585}586587int STLGeometry :: GetChartNr(int i) const588{589if (i > chartmark.Size())590{591PrintSysError("GetChartNr(", i, ") not possible!!!");592i = 1;593}594return chartmark.Get(i);595}596/*597int STLGeometry :: GetMarker(int i) const598{599return chartmark.Get(i);600}601*/602void STLGeometry :: SetMarker(int nr, int m)603{604chartmark.Elem(nr) = m;605}606int STLGeometry :: GetNOCharts() const607{608return atlas.Size();609}610const STLChart& STLGeometry :: GetChart(int nr) const611{612if (nr > atlas.Size())613{614PrintSysError("GetChart(", nr, ") not possible!!!");615nr = 1;616}617return *(atlas.Get(nr));618}619620int STLGeometry :: AtlasMade() const621{622return chartmark.Size() != 0;623}624625626//return 1 if not exists627int AddIfNotExists(ARRAY<int>& list, int x)628{629int i;630for (i = 1; i <= list.Size(); i++)631{632if (list.Get(i) == x) {return 0;}633}634list.Append(x);635return 1;636}637638void STLGeometry :: GetInnerChartLimes(ARRAY<twoint>& limes, int chartnum)639{640int j, k;641642int t, nt, np1, np2;643644limes.SetSize(0);645646STLChart& chart = GetChart(chartnum);647648for (j = 1; j <= chart.GetNChartT(); j++)649{650t = chart.GetChartTrig(j);651const STLTriangle& tt = GetTriangle(t);652for (k = 1; k <= 3; k++)653{654nt = NeighbourTrig(t,k);655if (GetChartNr(nt) != chartnum)656{657tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);658if (!IsEdge(np1,np2))659{660limes.Append(twoint(np1,np2));661/*662p3p1 = GetPoint(np1);663p3p2 = GetPoint(np2);664if (AddIfNotExists(limes,np1))665{666plimes1.Append(p3p1);667//plimes1trigs.Append(t);668//plimes1origin.Append(np1);669}670if (AddIfNotExists(limes1,np2))671{672plimes1.Append(p3p2);673//plimes1trigs.Append(t);674//plimes1origin.Append(np2);675}676//chart.AddILimit(twoint(np1,np2));677678for (int di = 1; di <= divisions; di++)679{680double f1 = (double)di/(double)(divisions+1.);681double f2 = (divisions+1.-(double)di)/(double)(divisions+1.);682683plimes1.Append(Point3d(p3p1.X()*f1+p3p2.X()*f2,684p3p1.Y()*f1+p3p2.Y()*f2,685p3p1.Z()*f1+p3p2.Z()*f2));686//plimes1trigs.Append(t);687//plimes1origin.Append(0);688}689*/690}691}692}693}694}695696697698void STLGeometry :: GetDirtyChartTrigs(int chartnum, STLChart& chart,699const ARRAY<int>& outercharttrigs,700ARRAY<int>& chartpointchecked,701ARRAY<int>& dirtytrigs)702{703dirtytrigs.SetSize(0);704int j,k,n;705706int np1, np2, nt;707int cnt = 0;708709for (j = 1; j <= chart.GetNChartT(); j++)710{711int t = chart.GetChartTrig(j);712const STLTriangle& tt = GetTriangle(t);713714for (k = 1; k <= 3; k++)715{716nt = NeighbourTrig(t,k);717if (GetChartNr(nt) != chartnum && outercharttrigs.Get(nt) != chartnum)718{719tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);720if (!IsEdge(np1,np2))721{722dirtytrigs.Append(j); //local numbers!!!723cnt++;724break; //only once per trig!!!725}726}727}728}729cnt = 0;730731int ap1, ap2, tn1, tn2, l, problem, pn;732ARRAY<int> trigsaroundp;733734for (j = chart.GetNChartT(); j >= 1; j--)735{736int t = chart.GetChartTrig(j);737const STLTriangle& tt = GetTriangle(t);738739for (k = 1; k <= 3; k++)740{741pn = tt.PNum(k);742//if (chartpointchecked.Get(pn) == chartnum)743//{continue;}744745int checkpoint = 0;746for (n = 1; n <= trigsperpoint.EntrySize(pn); n++)747{748if (trigsperpoint.Get(pn,n) != t && //ueberfluessig???749GetChartNr(trigsperpoint.Get(pn,n)) != chartnum &&750outercharttrigs.Get(trigsperpoint.Get(pn,n)) != chartnum) {checkpoint = 1;};751}752if (checkpoint)753{754chartpointchecked.Elem(pn) = chartnum;755756GetSortedTrianglesAroundPoint(pn,t,trigsaroundp);757trigsaroundp.Append(t); //ring758759problem = 0;760//forward:761for (l = 2; l <= trigsaroundp.Size()-1; l++)762{763tn1 = trigsaroundp.Get(l-1);764tn2 = trigsaroundp.Get(l);765const STLTriangle& t1 = GetTriangle(tn1);766const STLTriangle& t2 = GetTriangle(tn2);767t1.GetNeighbourPoints(t2, ap1, ap2);768if (IsEdge(ap1,ap2)) break;769770if (GetChartNr(tn2) != chartnum && outercharttrigs.Get(tn2) != chartnum) {problem = 1;}771}772773//backwards:774for (l = trigsaroundp.Size()-1; l >= 2; l--)775{776tn1 = trigsaroundp.Get(l+1);777tn2 = trigsaroundp.Get(l);778const STLTriangle& t1 = GetTriangle(tn1);779const STLTriangle& t2 = GetTriangle(tn2);780t1.GetNeighbourPoints(t2, ap1, ap2);781if (IsEdge(ap1,ap2)) break;782783if (GetChartNr(tn2) != chartnum && outercharttrigs.Get(tn2) != chartnum) {problem = 1;}784}785if (problem && !IsInArray(j,dirtytrigs))786{787dirtytrigs.Append(j);788cnt++;789break; //only once per triangle790}791}792}793}794795}796797}798799800