Path: blob/devel/ElmerGUI/netgen/libsrc/stlgeom/stltopology.cpp
3206 views
#include <mystdlib.h>12#include <myadt.hpp>3#include <linalg.hpp>4#include <gprim.hpp>56#include <meshing.hpp>78#include "stlgeom.hpp"910namespace netgen11{121314STLTopology :: STLTopology()15: trias(), topedges(), points(), ht_topedges(NULL),16neighbourtrigs(), trigsperpoint()17{18;19}2021STLTopology :: ~STLTopology()22{23;24}2526272829STLGeometry * STLTopology :: LoadBinary (istream & ist)30{31STLGeometry * geom = new STLGeometry();32ARRAY<STLReadTriangle> readtrigs;3334PrintMessage(1,"Read STL binary file");3536if (sizeof(int) != 4 || sizeof(float) != 4)37{38PrintWarning("for stl-binary compatibility only use 32 bit compilation!!!");39}4041//specific settings for stl-binary format42const int namelen = 80; //length of name of header in file43const int nospaces = 2; //number of spaces after a triangle4445//read header: name46char buf[namelen+1];47FIOReadStringE(ist,buf,namelen);48PrintMessage(5,"header = ",buf);4950//Read Number of facets51int nofacets;52FIOReadInt(ist,nofacets);53PrintMessage(5,"NO facets = ",nofacets);5455Point<3> pts[3];56Vec<3> normal;5758int cntface, j;59//int vertex = 0;60float f;61char spaces[nospaces+1];6263for (cntface = 0; cntface < nofacets; cntface++)64{65if (cntface % 10000 == 9999) { PrintDot(); }6667FIOReadFloat(ist,f); normal(0) = f;68FIOReadFloat(ist,f); normal(1) = f;69FIOReadFloat(ist,f); normal(2) = f;7071for (j = 0; j < 3; j++)72{73FIOReadFloat(ist,f); pts[j](0) = f;74FIOReadFloat(ist,f); pts[j](1) = f;75FIOReadFloat(ist,f); pts[j](2) = f;76}7778readtrigs.Append (STLReadTriangle (pts, normal));79FIOReadString(ist,spaces,nospaces);80}818283geom->InitSTLGeometry(readtrigs);8485return geom;86}878889void STLTopology :: SaveBinary (const char* filename, const char* aname)90{91ofstream ost(filename);92PrintFnStart("Write STL binary file '",filename,"'");9394if (sizeof(int) != 4 || sizeof(float) != 4)95{PrintWarning("for stl-binary compatibility only use 32 bit compilation!!!");}9697//specific settings for stl-binary format98const int namelen = 80; //length of name of header in file99const int nospaces = 2; //number of spaces after a triangle100101//write header: aname102int i, j;103char buf[namelen+1];104int strend = 0;105for(i = 0; i <= namelen; i++)106{107if (aname[i] == 0) {strend = 1;}108if (!strend) {buf[i] = aname[i];}109else {buf[i] = 0;}110}111112FIOWriteString(ost,buf,namelen);113PrintMessage(5,"header = ",buf);114115//RWrite Number of facets116int nofacets = GetNT();117FIOWriteInt(ost,nofacets);118PrintMessage(5,"NO facets = ", nofacets);119120float f;121char spaces[nospaces+1];122for (i = 0; i < nospaces; i++) {spaces[i] = ' ';}123spaces[nospaces] = 0;124125for (i = 1; i <= GetNT(); i++)126{127const STLTriangle & t = GetTriangle(i);128129const Vec<3> & n = t.Normal();130f = n(0); FIOWriteFloat(ost,f);131f = n(1); FIOWriteFloat(ost,f);132f = n(2); FIOWriteFloat(ost,f);133134for (j = 1; j <= 3; j++)135{136const Point3d p = GetPoint(t.PNum(j));137138f = p.X(); FIOWriteFloat(ost,f);139f = p.Y(); FIOWriteFloat(ost,f);140f = p.Z(); FIOWriteFloat(ost,f);141}142FIOWriteString(ost,spaces,nospaces);143}144PrintMessage(5,"done");145}146147148void STLTopology :: SaveSTLE (const char* filename)149{150ofstream outf (filename);151int i, j;152153outf << GetNT() << endl;154for (i = 1; i <= GetNT(); i++)155{156const STLTriangle & t = GetTriangle(i);157for (j = 1; j <= 3; j++)158{159const Point3d p = GetPoint(t.PNum(j));160outf << p.X() << " " << p.Y() << " " << p.Z() << endl;161}162}163164165int ned = 0;166for (i = 1; i <= GetNTE(); i++)167{168if (GetTopEdge (i).GetStatus() == ED_CONFIRMED)169ned++;170}171172outf << ned << endl;173174for (i = 1; i <= GetNTE(); i++)175{176const STLTopEdge & edge = GetTopEdge (i);177if (edge.GetStatus() == ED_CONFIRMED)178for (j = 1; j <= 2; j++)179{180const Point3d p = GetPoint(edge.PNum(j));181outf << p.X() << " " << p.Y() << " " << p.Z() << endl;182}183}184}185186187188STLGeometry * STLTopology :: LoadNaomi (istream & ist)189{190int i;191STLGeometry * geom = new STLGeometry();192ARRAY<STLReadTriangle> readtrigs;193194PrintFnStart("read NAOMI file format");195196char buf[100];197Vec<3> normal;198199//int cntface = 0;200//int cntvertex = 0;201double px, py, pz;202203204int noface, novertex;205ARRAY<Point<3> > readpoints;206207ist >> buf;208if (strcmp (buf, "NODES") == 0)209{210ist >> novertex;211PrintMessage(5,"nuber of vertices = ", novertex);212for (i = 0; i < novertex; i++)213{214ist >> px;215ist >> py;216ist >> pz;217readpoints.Append(Point<3> (px,py,pz));218}219}220else221{222PrintFileError("no node information");223}224225226ist >> buf;227if (strcmp (buf, "2D_EDGES") == 0)228{229ist >> noface;230PrintMessage(5,"number of faces=",noface);231int dummy, p1, p2, p3;232Point<3> pts[3];233234for (i = 0; i < noface; i++)235{236ist >> dummy; //2237ist >> dummy; //1238ist >> p1;239ist >> p2;240ist >> p3;241ist >> dummy; //0242243pts[0] = readpoints.Get(p1);244pts[1] = readpoints.Get(p2);245pts[2] = readpoints.Get(p3);246247normal = Cross (pts[1]-pts[0], pts[2]-pts[0]) . Normalize();248249readtrigs.Append (STLReadTriangle (pts, normal));250251}252PrintMessage(5,"read ", readtrigs.Size(), " triangles");253}254else255{256PrintMessage(5,"read='",buf,"'\n");257PrintFileError("ERROR: no Triangle information");258}259260geom->InitSTLGeometry(readtrigs);261262return geom;263}264265void STLTopology :: Save (const char* filename)266{267PrintFnStart("Write stl-file '",filename, "'");268269ofstream fout(filename);270fout << "solid\n";271272char buf1[50];273char buf2[50];274char buf3[50];275276int i, j;277for (i = 1; i <= GetNT(); i++)278{279const STLTriangle & t = GetTriangle(i);280281fout << "facet normal ";282const Vec3d& n = GetTriangle(i).Normal();283284sprintf(buf1,"%1.9g",n.X());285sprintf(buf2,"%1.9g",n.Y());286sprintf(buf3,"%1.9g",n.Z());287288fout << buf1 << " " << buf2 << " " << buf3 << "\n";289fout << "outer loop\n";290291for (j = 1; j <= 3; j++)292{293const Point3d p = GetPoint(t.PNum(j));294295sprintf(buf1,"%1.9g",p.X());296sprintf(buf2,"%1.9g",p.Y());297sprintf(buf3,"%1.9g",p.Z());298299fout << "vertex " << buf1 << " " << buf2 << " " << buf3 << "\n";300}301302fout << "endloop\n";303fout << "endfacet\n";304}305fout << "endsolid\n";306307308// write also NETGEN surface mesh:309ofstream fout2("geom.surf");310fout2 << "surfacemesh" << endl;311fout2 << GetNP() << endl;312for (i = 1; i <= GetNP(); i++)313{314for (j = 0; j < 3; j++)315{316fout2.width(8);317fout2 << GetPoint(i)(j);318}319320fout2 << endl;321}322323fout2 << GetNT() << endl;324for (i = 1; i <= GetNT(); i++)325{326const STLTriangle & t = GetTriangle(i);327for (j = 1; j <= 3; j++)328{329fout2.width(8);330fout2 << t.PNum(j);331}332fout2 << endl;333}334}335336337STLGeometry * STLTopology ::Load (istream & ist)338{339size_t i;340STLGeometry * geom = new STLGeometry();341342ARRAY<STLReadTriangle> readtrigs;343344char buf[100];345Point<3> pts[3];346Vec<3> normal;347348int cntface = 0;349int vertex = 0;350bool badnormals = 0;351352while (ist.good())353{354ist >> buf;355356size_t n = strlen (buf);357for (i = 0; i < n; i++)358buf[i] = tolower (buf[i]);359360if (strcmp (buf, "facet") == 0)361{362cntface++;363}364365if (strcmp (buf, "normal") == 0)366{367ist >> normal(0)368>> normal(1)369>> normal(2);370normal.Normalize();371}372373if (strcmp (buf, "vertex") == 0)374{375ist >> pts[vertex](0)376>> pts[vertex](1)377>> pts[vertex](2);378379vertex++;380381if (vertex == 3)382{383if (normal.Length() <= 1e-5)384385{386normal = Cross (pts[1]-pts[0], pts[2]-pts[0]);387normal.Normalize();388}389390else391392{393Vec<3> hnormal;394hnormal = Cross (pts[1]-pts[0], pts[2]-pts[0]);395hnormal.Normalize();396397if (normal * hnormal < 0.5)398{399badnormals = 1;400}401}402403vertex = 0;404405if ( (Dist2 (pts[0], pts[1]) > 1e-16) &&406(Dist2 (pts[0], pts[2]) > 1e-16) &&407(Dist2 (pts[1], pts[2]) > 1e-16) )408409readtrigs.Append (STLReadTriangle (pts, normal));410}411}412}413414if (badnormals)415{416PrintWarning("File has normal vectors which differ extremly from geometry->correct with stldoctor!!!");417}418419geom->InitSTLGeometry(readtrigs);420return geom;421}422423424425426427428429430431432433434435void STLTopology :: InitSTLGeometry(const ARRAY<STLReadTriangle> & readtrigs)436{437int i, k;438439// const double geometry_tol_fact = 1E6;440// distances lower than max_box_size/tol are ignored441442trias.SetSize(0);443points.SetSize(0);444445PrintMessage(3,"number of triangles = ", readtrigs.Size());446447if (!readtrigs.Size())448return;449450451boundingbox.Set (readtrigs[0][0]);452for (i = 0; i < readtrigs.Size(); i++)453for (k = 0; k < 3; k++)454boundingbox.Add (readtrigs[i][k]);455456PrintMessage(5,"boundingbox: ", Point3d(boundingbox.PMin()), " - ",457Point3d(boundingbox.PMax()));458459Box<3> bb = boundingbox;460bb.Increase (1);461462pointtree = new Point3dTree (bb.PMin(), bb.PMax());463464465466ARRAY<int> pintersect;467468pointtol = boundingbox.Diam() * stldoctor.geom_tol_fact;469PrintMessage(5,"point tolerance = ", pointtol);470471for(i = 0; i < readtrigs.Size(); i++)472{473const STLReadTriangle & t = readtrigs[i];474STLTriangle st;475Vec<3> n = t.Normal();476st.SetNormal (t.Normal());477478for (k = 0; k < 3; k++)479{480Point<3> p = t[k];481482Point<3> pmin = p - Vec<3> (pointtol, pointtol, pointtol);483Point<3> pmax = p + Vec<3> (pointtol, pointtol, pointtol);484485pointtree->GetIntersecting (pmin, pmax, pintersect);486487if (pintersect.Size() > 1)488PrintError("too many close points");489int foundpos = -1;490if (pintersect.Size())491foundpos = pintersect[0];492493if (foundpos == -1)494{495foundpos = AddPoint(p);496pointtree->Insert (p, foundpos);497}498st[k] = foundpos;499}500501if ( (st[0] == st[1]) ||502(st[0] == st[2]) ||503(st[1] == st[2]) )504{505PrintError("STL Triangle degenerated");506}507else508{509AddTriangle(st);510}511512}513514FindNeighbourTrigs();515}516517518519520int STLTopology :: GetPointNum (const Point<3> & p)521{522Point<3> pmin = p - Vec<3> (pointtol, pointtol, pointtol);523Point<3> pmax = p + Vec<3> (pointtol, pointtol, pointtol);524525ARRAY<int> pintersect;526527pointtree->GetIntersecting (pmin, pmax, pintersect);528if (pintersect.Size() == 1)529return pintersect[0];530else531return 0;532}533534535536void STLTopology :: FindNeighbourTrigs()537{538// if (topedges.Size()) return;539540PushStatusF("Find Neighbour Triangles");541542int i, j, k, l;543544// build up topology tables545546//int np = GetNP();547int nt = GetNT();548549INDEX_2_HASHTABLE<int> * oldedges = ht_topedges;550ht_topedges = new INDEX_2_HASHTABLE<int> (GetNP()+1);551topedges.SetSize(0);552553for (i = 1; i <= nt; i++)554{555STLTriangle & trig = GetTriangle(i);556557558for (j = 1; j <= 3; j++)559{560int pi1 = trig.PNumMod (j+1);561int pi2 = trig.PNumMod (j+2);562563INDEX_2 i2(pi1, pi2);564i2.Sort();565566int enr;567int othertn;568569if (ht_topedges->Used(i2))570{571enr = ht_topedges->Get(i2);572topedges.Elem(enr).TrigNum(2) = i;573574othertn = topedges.Get(enr).TrigNum(1);575STLTriangle & othertrig = GetTriangle(othertn);576577trig.NBTrigNum(j) = othertn;578trig.EdgeNum(j) = enr;579for (k = 1; k <= 3; k++)580if (othertrig.EdgeNum(k) == enr)581othertrig.NBTrigNum(k) = i;582}583else584{585enr = topedges.Append (STLTopEdge (pi1, pi2, i, 0));586ht_topedges->Set (i2, enr);587trig.EdgeNum(j) = enr;588}589}590}591592593PrintMessage(5,"topology built, checking");594595topology_ok = 1;596int ne = GetNTE();597598for (i = 1; i <= nt; i++)599GetTriangle(i).flags.toperror = 0;600601for (i = 1; i <= nt; i++)602for (j = 1; j <= 3; j++)603{604const STLTopEdge & edge = GetTopEdge (GetTriangle(i).EdgeNum(j));605if (edge.TrigNum(1) != i && edge.TrigNum(2) != i)606{607topology_ok = 0;608GetTriangle(i).flags.toperror = 1;609}610}611612for (i = 1; i <= ne; i++)613{614const STLTopEdge & edge = GetTopEdge (i);615if (!edge.TrigNum(2))616{617topology_ok = 0;618GetTriangle(edge.TrigNum(1)).flags.toperror = 1;619}620}621622if (topology_ok)623{624orientation_ok = 1;625for (i = 1; i <= nt; i++)626{627const STLTriangle & t = GetTriangle (i);628for (j = 1; j <= 3; j++)629{630const STLTriangle & nbt = GetTriangle (t.NBTrigNum(j));631if (!t.IsNeighbourFrom (nbt))632orientation_ok = 0;633}634}635}636else637orientation_ok = 0;638639640641status = STL_GOOD;642statustext = "";643if (!topology_ok || !orientation_ok)644{645status = STL_ERROR;646if (!topology_ok)647statustext = "Topology not ok";648else649statustext = "Orientation not ok";650}651652653PrintMessage(3,"topology_ok = ",topology_ok);654PrintMessage(3,"orientation_ok = ",orientation_ok);655PrintMessage(3,"topology found");656657// generate point -> trig table658659trigsperpoint.SetSize(GetNP());660for (i = 1; i <= GetNT(); i++)661for (j = 1; j <= 3; j++)662trigsperpoint.Add1(GetTriangle(i).PNum(j),i);663664665//check trigs per point:666/*667for (i = 1; i <= GetNP(); i++)668{669if (trigsperpoint.EntrySize(i) < 3)670{671(*testout) << "ERROR: Point " << i << " has " << trigsperpoint.EntrySize(i) << " triangles!!!" << endl;672}673}674*/675topedgesperpoint.SetSize (GetNP());676for (i = 1; i <= ne; i++)677for (j = 1; j <= 2; j++)678topedgesperpoint.Add1 (GetTopEdge (i).PNum(j), i);679680PrintMessage(5,"point -> trig table generated");681682683684// transfer edge data:685// .. to be done686delete oldedges;687688689690for (STLTrigIndex ti = 0; ti < GetNT(); ti++)691{692STLTriangle & trig = trias[ti];693for (k = 0; k < 3; k++)694{695STLPointIndex pi = trig[k] - STLBASE;696STLPointIndex pi2 = trig[(k+1)%3] - STLBASE;697STLPointIndex pi3 = trig[(k+2)%3] - STLBASE;698699// vector along edge700Vec<3> ve = points[pi2] - points[pi];701ve.Normalize();702703// vector along third point704Vec<3> vt = points[pi3] - points[pi];705vt -= (vt * ve) * ve;706vt.Normalize();707708Vec<3> vn = trig.GeomNormal (points);709vn.Normalize();710711double phimin = 10, phimax = -1; // out of (0, 2 pi)712713for (j = 0; j < trigsperpoint[pi].Size(); j++)714{715STLTrigIndex ti2 = trigsperpoint[pi][j] - STLBASE;716const STLTriangle & trig2 = trias[ti2];717718if (ti == ti2) continue;719720bool hasboth = 0;721for (l = 0; l < 3; l++)722if (trig2[l] - STLBASE == pi2)723{724hasboth = 1;725break;726}727if (!hasboth) continue;728729STLPointIndex pi4(0);730for (l = 0; l < 3; l++)731if (trig2[l] - STLBASE != pi && trig2[l] - STLBASE != pi2)732pi4 = trig2[l] - STLBASE;733734Vec<3> vt2 = points[pi4] - points[pi];735736double phi = atan2 (vt2 * vn, vt2 * vt);737if (phi < 0) phi += 2 * M_PI;738739if (phi < phimin)740{741phimin = phi;742trig.NBTrig (0, (k+2)%3) = ti2 + STLBASE;743}744if (phi > phimax)745{746phimax = phi;747trig.NBTrig (1, (k+2)%3) = ti2 + STLBASE;748}749}750}751}752753754755756if (status == STL_GOOD)757{758// for compatibility:759neighbourtrigs.SetSize(GetNT());760for (i = 1; i <= GetNT(); i++)761for (k = 1; k <= 3; k++)762AddNeighbourTrig (i, GetTriangle(i).NBTrigNum(k));763}764else765{766// assemble neighbourtrigs (should be done only for illegal topology):767768neighbourtrigs.SetSize(GetNT());769770int tr, found;771int wrongneighbourfound = 0;772for (i = 1; i <= GetNT(); i++)773{774SetThreadPercent((double)i/(double)GetNT()*100.);775if (multithread.terminate)776{777PopStatus();778return;779}780781for (k = 1; k <= 3; k++)782{783for (j = 1; j <= trigsperpoint.EntrySize(GetTriangle(i).PNum(k)); j++)784{785tr = trigsperpoint.Get(GetTriangle(i).PNum(k),j);786if (i != tr && (GetTriangle(i).IsNeighbourFrom(GetTriangle(tr))787|| GetTriangle(i).IsWrongNeighbourFrom(GetTriangle(tr))))788{789if (GetTriangle(i).IsWrongNeighbourFrom(GetTriangle(tr)))790{791/*(*testout) << "ERROR: triangle " << i << " has a wrong neighbour triangle!!!" << endl;*/792wrongneighbourfound ++;793}794795found = 0;796for (int ii = 1; ii <= NONeighbourTrigs(i); ii++)797{if (NeighbourTrig(i,ii) == tr) {found = 1;break;};}798if (! found) {AddNeighbourTrig(i,tr);}799}800}801}802if (NONeighbourTrigs(i) != 3)803{804PrintError("TRIG ",i," has ",NONeighbourTrigs(i)," neighbours!!!!");805for (int kk=1; kk <= NONeighbourTrigs(i); kk++)806{807PrintMessage(5,"neighbour-trig",kk," = ",NeighbourTrig(i,kk));808}809};810}811if (wrongneighbourfound)812{813PrintError("++++++++++++++++++++\n");814PrintError(wrongneighbourfound, " wrong oriented neighbourtriangles found!");815PrintError("try to correct it (with stldoctor)!");816PrintError("++++++++++++++++++++\n");817818status = STL_ERROR;819statustext = "STL Mesh not consistent";820821multithread.terminate = 1;822#ifdef STAT_STREAM823(*statout) << "non-conform stl geometry \\hline" << endl;824#endif825}826}827828TopologyChanged();829830PopStatus();831}832833834835836837838839void STLTopology :: GetTrianglesInBox (/*840const Point<3> & pmin,841const Point<3> & pmax,842*/843const Box<3> & box,844ARRAY<int> & btrias) const845{846if (searchtree)847848searchtree -> GetIntersecting (box.PMin(), box.PMax(), btrias);849850else851{852int i;853Box<3> box1 = box;854box1.Increase (1e-4);855856btrias.SetSize(0);857858int nt = GetNT();859for (i = 1; i <= nt; i++)860{861if (box1.Intersect (GetTriangle(i).box))862{863btrias.Append (i);864}865}866}867}868869870871void STLTopology :: AddTriangle(const STLTriangle& t)872{873trias.Append(t);874875const Point<3> & p1 = GetPoint (t.PNum(1));876const Point<3> & p2 = GetPoint (t.PNum(2));877const Point<3> & p3 = GetPoint (t.PNum(3));878879Box<3> box;880box.Set (p1);881box.Add (p2);882box.Add (p3);883/*884// Point<3> pmin(p1), pmax(p1);885pmin.SetToMin (p2);886pmin.SetToMin (p3);887pmax.SetToMax (p2);888pmax.SetToMax (p3);889*/890891trias.Last().box = box;892trias.Last().center = Center (p1, p2, p3);893double r1 = Dist (p1, trias.Last().center);894double r2 = Dist (p2, trias.Last().center);895double r3 = Dist (p3, trias.Last().center);896trias.Last().rad = max2 (max2 (r1, r2), r3);897898if (geomsearchtreeon)899{searchtree->Insert (box.PMin(), box.PMax(), trias.Size());}900}901902903904905int STLTopology :: GetLeftTrig(int p1, int p2) const906{907int i;908for (i = 1; i <= trigsperpoint.EntrySize(p1); i++)909{910if (GetTriangle(trigsperpoint.Get(p1,i)).HasEdge(p1,p2)) {return trigsperpoint.Get(p1,i);}911}912PrintSysError("ERROR in GetLeftTrig !!!");913914return 0;915}916917int STLTopology :: GetRightTrig(int p1, int p2) const918{919return GetLeftTrig(p2,p1);920}921922923int STLTopology :: NeighbourTrigSorted(int trig, int edgenum) const924{925int i, p1, p2;926int psearch = GetTriangle(trig).PNum(edgenum);927928for (i = 1; i <= 3; i++)929{930GetTriangle(trig).GetNeighbourPoints(GetTriangle(NeighbourTrig(trig,i)),p1,p2);931if (p1 == psearch) {return NeighbourTrig(trig,i);}932}933934PrintSysError("ERROR in NeighbourTrigSorted");935return 0;936}937938939940941942943int STLTopology :: GetTopEdgeNum (int pi1, int pi2) const944{945if (!ht_topedges) return 0;946947INDEX_2 i2(pi1, pi2);948i2.Sort();949950if (!ht_topedges->Used(i2)) return 0;951return ht_topedges->Get(i2);952}953954955956957void STLTopology :: InvertTrig (int trig)958{959if (trig >= 1 && trig <= GetNT())960{961GetTriangle(trig).ChangeOrientation();962FindNeighbourTrigs();963}964else965{966PrintUserError("no triangle selected!");967}968}969970971972973void STLTopology :: DeleteTrig (int trig)974{975if (trig >= 1 && trig <= GetNT())976{977trias.DeleteElement(trig);978FindNeighbourTrigs();979}980else981{982PrintUserError("no triangle selected!");983}984}985986987988void STLTopology :: OrientAfterTrig (int trig)989{990int starttrig = trig;991992if (starttrig >= 1 && starttrig <= GetNT())993{994995ARRAY <int> oriented;996oriented.SetSize(GetNT());997int i;998for (i = 1; i <= oriented.Size(); i++)999{1000oriented.Elem(i) = 0;1001}10021003oriented.Elem(starttrig) = 1;10041005int k;10061007ARRAY <int> list1;1008list1.SetSize(0);1009ARRAY <int> list2;1010list2.SetSize(0);1011list1.Append(starttrig);10121013int cnt = 1;1014int end = 0;1015int nt;1016while (!end)1017{1018end = 1;1019for (i = 1; i <= list1.Size(); i++)1020{1021const STLTriangle& tt = GetTriangle(list1.Get(i));1022for (k = 1; k <= 3; k++)1023{1024nt = tt.NBTrigNum (k); // NeighbourTrig(list1.Get(i),k);1025if (oriented.Get(nt) == 0)1026{1027if (tt.IsWrongNeighbourFrom(GetTriangle(nt)))1028{1029GetTriangle(nt).ChangeOrientation();1030}1031oriented.Elem(nt) = 1;1032list2.Append(nt);1033cnt++;1034end = 0;1035}1036}1037}1038list1.SetSize(0);1039for (i = 1; i <= list2.Size(); i++)1040{1041list1.Append(list2.Get(i));1042}1043list2.SetSize(0);1044}10451046PrintMessage(5,"NO corrected triangles = ",cnt);1047if (cnt == GetNT())1048{1049PrintMessage(5,"ALL triangles oriented in same way!");1050}1051else1052{1053PrintWarning("NOT ALL triangles oriented in same way!");1054}10551056// topedges.SetSize(0);1057FindNeighbourTrigs();1058}1059else1060{1061PrintUserError("no triangle selected!");1062}1063}106410651066}106710681069