#include #include "meshing.hpp" #ifdef WIN32 #define COMMASIGN ':' #else #define COMMASIGN ',' #endif namespace netgen { extern const char * tetrules[]; void LoadVMatrixLine (istream & ist, DenseMatrix & m, int line) { char ch; int pnum; float f; ist >> ch; while (ch != '}') { ist.putback (ch); ist >> f; ist >> ch; ist >> pnum; if (ch == 'x' || ch == 'X') m.Elem(line, 3 * pnum - 2) = f; if (ch == 'y' || ch == 'Y') m.Elem(line, 3 * pnum - 1) = f; if (ch == 'z' || ch == 'Z') m.Elem(line, 3 * pnum ) = f; if (ch == 'p' || ch == 'P') { m.Elem(line , 3 * pnum-2) = f; m.Elem(line+1, 3 * pnum-1) = f; m.Elem(line+2, 3 * pnum ) = f; } ist >> ch; if (ch == COMMASIGN) ist >> ch; } } int vnetrule :: NeighbourTrianglePoint (const threeint & t1, const threeint & t2) const { NgArray tr1(3); NgArray tr2(3); tr1.Elem(1)=t1.i1; tr1.Elem(2)=t1.i2; tr1.Elem(3)=t1.i3; tr2.Elem(1)=t2.i1; tr2.Elem(2)=t2.i2; tr2.Elem(3)=t2.i3; int ret=0; for (int i=1; i<=3; i++) { for (int j=1; j<=3; j++) { if ((tr1.Get(i)==tr2.Get(j) && tr1.Get((i%3)+1)==tr2.Get((j%3)+1)) || (tr1.Get(i)==tr2.Get((j%3)+1) && tr1.Get((i%3)+1)==tr2.Get(j))) {ret = tr2.Get((j+1)%3+1);} } } return ret; } void vnetrule :: LoadRule (istream & ist) { char buf[256]; char ch, ok; Point3d p; Element2d face(TRIG); int i, j, i1, i2, i3, fs, ii, ii1, ii2, ii3; twoint edge; DenseMatrix tempoldutonewu(30, 20), tempoldutofreezone(30, 20), tempoldutofreezonelimit(30, 20), tfz(20, 20), tfzl(20, 20); tempoldutonewu = 0; tempoldutofreezone = 0; tfz = 0; tfzl = 0; noldp = 0; noldf = 0; ist.get (buf, sizeof(buf), '"'); ist.get (ch); ist.get (buf, sizeof(buf), '"'); ist.get (ch); delete [] name; name = new char[strlen (buf) + 1]; strcpy (name, buf); // (*mycout) << "Rule " << name << " found." << endl; do { ist >> buf; if (strcmp (buf, "quality") == 0) { ist >> quality; } else if (strcmp (buf, "flags") == 0) { ist >> ch; while (ch != ';') { flags.Append (ch); ist >> ch; } } else if (strcmp (buf, "mappoints") == 0) { ist >> ch; while (ch == '(') { ist >> p.X(); ist >> ch; // ',' ist >> p.Y(); ist >> ch; // ',' ist >> p.Z(); ist >> ch; // ')' points.Append (p); noldp++; tolerances.SetSize (noldp); tolerances.Elem(noldp) = 1; ist >> ch; while (ch != ';') { if (ch == '{') { ist >> tolerances.Elem(noldp); ist >> ch; // '}' } ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "mapfaces") == 0) { ist >> ch; while (ch == '(') { face.SetType(TRIG); ist >> face.PNum(1); ist >> ch; // ',' ist >> face.PNum(2); ist >> ch; // ',' ist >> face.PNum(3); ist >> ch; // ')' or ',' if (ch == COMMASIGN) { face.SetType(QUAD); ist >> face.PNum(4); ist >> ch; // ')' } faces.Append (face); noldf++; ist >> ch; while (ch != ';') { if (ch == 'd') { delfaces.Append (noldf); ist >> ch; // 'e' ist >> ch; // 'l' } ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "mapedges") == 0) { ist >> ch; while (ch == '(') { ist >> edge.i1; ist >> ch; // ',' ist >> edge.i2; ist >> ch; // ')' edges.Append (edge); ist >> ch; while (ch != ';') { ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "newpoints") == 0) { ist >> ch; while (ch == '(') { ist >> p.X(); ist >> ch; // ',' ist >> p.Y(); ist >> ch; // ',' ist >> p.Z(); ist >> ch; // ')' points.Append (p); ist >> ch; while (ch != ';') { if (ch == '{') { LoadVMatrixLine (ist, tempoldutonewu, 3 * (points.Size()-noldp) - 2); ist >> ch; // '{' LoadVMatrixLine (ist, tempoldutonewu, 3 * (points.Size()-noldp) - 1); ist >> ch; // '{' LoadVMatrixLine (ist, tempoldutonewu, 3 * (points.Size()-noldp) ); } ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "newfaces") == 0) { ist >> ch; while (ch == '(') { face.SetType(TRIG); ist >> face.PNum(1); ist >> ch; // ',' ist >> face.PNum(2); ist >> ch; // ',' ist >> face.PNum(3); ist >> ch; // ')' or ',' if (ch == COMMASIGN) { face.SetType(QUAD); ist >> face.PNum(4); ist >> ch; // ')' } faces.Append (face); ist >> ch; while (ch != ';') { ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "freezone") == 0) { ist >> ch; while (ch == '(') { ist >> p.X(); ist >> ch; // ',' ist >> p.Y(); ist >> ch; // ',' ist >> p.Z(); ist >> ch; // ')' freezone.Append (p); ist >> ch; while (ch != ';') { if (ch == '{') { LoadVMatrixLine (ist, tempoldutofreezone, 3 * freezone.Size() - 2); ist >> ch; // '{' LoadVMatrixLine (ist, tempoldutofreezone, 3 * freezone.Size() - 1); ist >> ch; // '{' LoadVMatrixLine (ist, tempoldutofreezone, 3 * freezone.Size() ); } ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "freezone2") == 0) { int k, nfp; nfp = 0; ist >> ch; DenseMatrix hm1(3, 50), hm2(50, 50), hm3(50, 50); hm3 = 0; while (ch == '{') { hm1 = 0; nfp++; LoadVMatrixLine (ist, hm1, 1); for (i = 1; i <= points.Size(); i++) tfz.Elem(nfp, i) = hm1.Get(1, 3*i-2); p.X() = p.Y() = p.Z() = 0; for (i = 1; i <= points.Size(); i++) { p.X() += hm1.Get(1, 3*i-2) * points.Get(i).X(); p.Y() += hm1.Get(1, 3*i-2) * points.Get(i).Y(); p.Z() += hm1.Get(1, 3*i-2) * points.Get(i).Z(); } freezone.Append (p); freezonelimit.Append (p); hm2 = 0; for (i = 1; i <= 3 * noldp; i++) hm2.Elem(i, i) = 1; for (i = 1; i <= 3 * noldp; i++) for (j = 1; j <= 3 * (points.Size() - noldp); j++) hm2.Elem(j + 3 * noldp, i) = tempoldutonewu.Get(j, i); for (i = 1; i <= 3; i++) for (j = 1; j <= 3 * noldp; j++) { double sum = 0; for (k = 1; k <= 3 * points.Size(); k++) sum += hm1.Get(i, k) * hm2.Get(k, j); hm3.Elem(i + 3 * (nfp-1), j) = sum; } // (*testout) << "freepoint: " << p << endl; while (ch != ';') ist >> ch; ist >> ch; } tfzl = tfz; tempoldutofreezone = hm3; tempoldutofreezonelimit = hm3; ist.putback(ch); } else if (strcmp (buf, "freezonelimit") == 0) { int k, nfp; nfp = 0; ist >> ch; DenseMatrix hm1(3, 50), hm2(50, 50), hm3(50, 50); hm3 = 0; while (ch == '{') { hm1 = 0; nfp++; LoadVMatrixLine (ist, hm1, 1); for (i = 1; i <= points.Size(); i++) tfzl.Elem(nfp, i) = hm1.Get(1, 3*i-2); p.X() = p.Y() = p.Z() = 0; for (i = 1; i <= points.Size(); i++) { p.X() += hm1.Get(1, 3*i-2) * points.Get(i).X(); p.Y() += hm1.Get(1, 3*i-2) * points.Get(i).Y(); p.Z() += hm1.Get(1, 3*i-2) * points.Get(i).Z(); } freezonelimit.Elem(nfp) = p; hm2 = 0; for (i = 1; i <= 3 * noldp; i++) hm2.Elem(i, i) = 1; for (i = 1; i <= 3 * noldp; i++) for (j = 1; j <= 3 * (points.Size() - noldp); j++) hm2.Elem(j + 3 * noldp, i) = tempoldutonewu.Get(j, i); for (i = 1; i <= 3; i++) for (j = 1; j <= 3 * noldp; j++) { double sum = 0; for (k = 1; k <= 3 * points.Size(); k++) sum += hm1.Get(i, k) * hm2.Get(k, j); hm3.Elem(i + 3 * (nfp-1), j) = sum; } // (*testout) << "freepoint: " << p << endl; while (ch != ';') ist >> ch; ist >> ch; } tempoldutofreezonelimit = hm3; ist.putback(ch); } else if (strcmp (buf, "freeset") == 0) { freesets.Append (new NgArray); ist >> ch; while (ch != ';') { ist.putback (ch); ist >> i; freesets.Last()->Append(i); ist >> ch; } } else if (strcmp (buf, "elements") == 0) { ist >> ch; while (ch == '(') { elements.Append (Element(TET)); // elements.Last().SetNP(1); ist >> elements.Last().PNum(1); ist >> ch; // ',' if (ch == COMMASIGN) { // elements.Last().SetNP(2); ist >> elements.Last().PNum(2); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(3); ist >> elements.Last().PNum(3); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(4); elements.Last().SetType(TET); ist >> elements.Last().PNum(4); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(5); elements.Last().SetType(PYRAMID); ist >> elements.Last().PNum(5); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(6); elements.Last().SetType(PRISM); ist >> elements.Last().PNum(6); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(6); elements.Last().SetType(HEX); ist >> elements.Last().PNum(7); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(6); elements.Last().SetType(HEX); ist >> elements.Last().PNum(8); ist >> ch; // ',' } /* orientations.Append (fourint()); orientations.Last().i1 = elements.Last().PNum(1); orientations.Last().i2 = elements.Last().PNum(2); orientations.Last().i3 = elements.Last().PNum(3); orientations.Last().i4 = elements.Last().PNum(4); */ ist >> ch; while (ch != ';') { ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "orientations") == 0) { ist >> ch; while (ch == '(') { // fourint a = fourint(); orientations.Append (fourint()); ist >> orientations.Last().i1; ist >> ch; // ',' ist >> orientations.Last().i2; ist >> ch; // ',' ist >> orientations.Last().i3; ist >> ch; // ',' ist >> orientations.Last().i4; ist >> ch; // ',' ist >> ch; while (ch != ';') { ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "endrule") != 0) { PrintSysError ("Parser3d, unknown token " , buf); } } while (!ist.eof() && strcmp (buf, "endrule") != 0); // (*testout) << endl; // (*testout) << Name() << endl; // (*testout) << "no1 = " << GetNO() << endl; oldutonewu.SetSize (3 * (points.Size() - noldp), 3 * noldp); oldutonewu = 0; for (i = 1; i <= oldutonewu.Height(); i++) for (j = 1; j <= oldutonewu.Width(); j++) oldutonewu.Elem(i, j) = tempoldutonewu.Elem(i, j); /* oldutofreezone = new SparseMatrixFlex (3 * freezone.Size(), 3 * noldp); oldutofreezonelimit = new SparseMatrixFlex (3 * freezone.Size(), 3 * noldp); oldutofreezone -> SetSymmetric(0); oldutofreezonelimit -> SetSymmetric(0); */ /* oldutofreezone = new DenseMatrix (3 * freezone.Size(), 3 * noldp); oldutofreezonelimit = new DenseMatrix (3 * freezone.Size(), 3 * noldp); for (i = 1; i <= oldutofreezone->Height(); i++) for (j = 1; j <= oldutofreezone->Width(); j++) // if (j == 4 || j >= 7) { if (tempoldutofreezone.Elem(i, j)) (*oldutofreezone)(i, j) = tempoldutofreezone(i, j); if (tempoldutofreezonelimit.Elem(i, j)) (*oldutofreezonelimit)(i, j) = tempoldutofreezonelimit(i, j); } */ oldutofreezone = new DenseMatrix (freezone.Size(), points.Size()); oldutofreezonelimit = new DenseMatrix (freezone.Size(), points.Size()); // oldutofreezone = new SparseMatrixFlex (freezone.Size(), points.Size()); // oldutofreezonelimit = new SparseMatrixFlex (freezone.Size(), points.Size()); for (i = 1; i <= freezone.Size(); i++) for (j = 1; j <= points.Size(); j++) { if (tfz.Elem(i, j)) (*oldutofreezone).Elem(i, j) = tfz.Elem(i, j); if (tfzl.Elem(i, j)) (*oldutofreezonelimit).Elem(i, j) = tfzl.Elem(i, j); } /* (*testout) << "Rule " << Name() << endl; (*testout) << "oldutofreezone = " << (*oldutofreezone) << endl; (*testout) << "oldutofreezonelimit = " << (*oldutofreezonelimit) << endl; */ freezonepi.SetSize (freezone.Size()); for (i = 1; i <= freezonepi.Size(); i++) freezonepi.Elem(i) = 0; for (i = 1; i <= freezone.Size(); i++) for (j = 1; j <= noldp; j++) if (Dist (freezone.Get(i), points.Get(j)) < 1e-8) freezonepi.Elem(i) = j; for (i = 1; i <= elements.Size(); i++) { if (elements.Elem(i).GetNP() == 4) { orientations.Append (fourint()); orientations.Last().i1 = elements.Get(i).PNum(1); orientations.Last().i2 = elements.Get(i).PNum(2); orientations.Last().i3 = elements.Get(i).PNum(3); orientations.Last().i4 = elements.Get(i).PNum(4); } if (elements.Elem(i).GetNP() == 5) { orientations.Append (fourint()); orientations.Last().i1 = elements.Get(i).PNum(1); orientations.Last().i2 = elements.Get(i).PNum(2); orientations.Last().i3 = elements.Get(i).PNum(3); orientations.Last().i4 = elements.Get(i).PNum(5); orientations.Append (fourint()); orientations.Last().i1 = elements.Get(i).PNum(1); orientations.Last().i2 = elements.Get(i).PNum(3); orientations.Last().i3 = elements.Get(i).PNum(4); orientations.Last().i4 = elements.Get(i).PNum(5); } } if (freesets.Size() == 0) { freesets.Append (new NgArray); for (i = 1; i <= freezone.Size(); i++) freesets.Elem(1)->Append(i); } // testout << "Freezone: " << endl; // for (i = 1; i <= freezone.Size(); i++) // (*testout) << "freepoint: " << freezone.Get(i) << endl; Vector vp(points.Size()), vfp(freezone.Size()); if (quality < 100) { for (int i = 1; i <= 3; i++) { for (int j = 1; j <= points.Size(); j++) vp(j-1) = points.Get(j).X(i); oldutofreezone->Mult(vp, vfp); for (int j = 1; j <= freezone.Size(); j++) freezone.Elem(j).X(i) = vfp(j-1); } // for (i = 1; i <= freezone.Size(); i++) // (*testout) << "freepoint: " << freezone.Get(i) << endl; } for (fs = 1; fs <= freesets.Size(); fs++) { freefaces.Append (new NgArray); NgArray & freeset = *freesets.Elem(fs); NgArray & freesetfaces = *freefaces.Last(); for (ii1 = 1; ii1 <= freeset.Size(); ii1++) for (ii2 = 1; ii2 <= freeset.Size(); ii2++) for (ii3 = 1; ii3 <= freeset.Size(); ii3++) if (ii1 < ii2 && ii1 < ii3 && ii2 != ii3) { i1 = freeset.Get(ii1); i2 = freeset.Get(ii2); i3 = freeset.Get(ii3); Vec3d v1, v2, n; v1 = freezone.Get(i3) - freezone.Get(i1); v2 = freezone.Get(i2) - freezone.Get(i1); n = Cross (v1, v2); n /= n.Length(); // (*testout) << "i1,2,3 = " << i1 << ", " << i2 << ", " << i3 << endl; // (*testout) << "v1 = " << v1 << " v2 = " << v2 << " n = " << n << endl; ok = 1; for (ii = 1; ii <= freeset.Size(); ii++) { i = freeset.Get(ii); // (*testout) << "i = " << i << endl; if (i != i1 && i != i2 && i != i3) if ( (freezone.Get(i) - freezone.Get(i1)) * n < 0 ) ok = 0; } if (ok) { freesetfaces.Append (threeint()); freesetfaces.Last().i1 = i1; freesetfaces.Last().i2 = i2; freesetfaces.Last().i3 = i3; } } } for (fs = 1; fs <= freesets.Size(); fs++) { freefaceinequ.Append (new DenseMatrix (freefaces.Get(fs)->Size(), 4)); } { int minn; // NgArray pnearness (noldp); pnearness.SetSize (noldp); for (i = 1; i <= pnearness.Size(); i++) pnearness.Elem(i) = INT_MAX/10; for (j = 1; j <= GetNP(1); j++) pnearness.Elem(GetPointNr (1, j)) = 0; do { ok = 1; for (i = 1; i <= noldf; i++) { minn = INT_MAX/10; for (j = 1; j <= GetNP(i); j++) minn = min2 (minn, pnearness.Get(GetPointNr (i, j))); for (j = 1; j <= GetNP(i); j++) if (pnearness.Get(GetPointNr (i, j)) > minn+1) { ok = 0; pnearness.Elem(GetPointNr (i, j)) = minn+1; } } for (i = 1; i <= edges.Size(); i++) { int pi1 = edges.Get(i).i1; int pi2 = edges.Get(i).i2; if (pnearness.Get(pi1) > pnearness.Get(pi2)+1) { ok = 0; pnearness.Elem(pi1) = pnearness.Get(pi2)+1; } if (pnearness.Get(pi2) > pnearness.Get(pi1)+1) { ok = 0; pnearness.Elem(pi2) = pnearness.Get(pi1)+1; } } for (i = 1; i <= elements.Size(); i++) if (elements.Get(i).GetNP() == 6) // prism rule { for (j = 1; j <= 3; j++) { int pi1 = elements.Get(i).PNum(j); int pi2 = elements.Get(i).PNum(j+3); if (pnearness.Get(pi1) > pnearness.Get(pi2)+1) { ok = 0; pnearness.Elem(pi1) = pnearness.Get(pi2)+1; } if (pnearness.Get(pi2) > pnearness.Get(pi1)+1) { ok = 0; pnearness.Elem(pi2) = pnearness.Get(pi1)+1; } } } } while (!ok); maxpnearness = 0; for (i = 1; i <= pnearness.Size(); i++) maxpnearness = max2 (maxpnearness, pnearness.Get(i)); fnearness.SetSize (noldf); for (i = 1; i <= noldf; i++) { fnearness.Elem(i) = 0; for (j = 1; j <= GetNP(i); j++) fnearness.Elem(i) += pnearness.Get(GetPointNr (i, j)); } // (*testout) << "rule " << name << ", pnear = " << pnearness << endl; } //Table of edges: for (fs = 1; fs <= freesets.Size(); fs++) { freeedges.Append (new NgArray); // NgArray & freeset = *freesets.Get(fs); NgArray & freesetedges = *freeedges.Last(); NgArray & freesetfaces = *freefaces.Get(fs); int k,l; INDEX ind; for (k = 1; k <= freesetfaces.Size(); k++) { // threeint tr = freesetfaces.Get(k); for (l = k+1; l <= freesetfaces.Size(); l++) { ind = NeighbourTrianglePoint(freesetfaces.Get(k), freesetfaces.Get(l)); if (!ind) continue; INDEX_3 f1(freesetfaces.Get(k).i1, freesetfaces.Get(k).i2, freesetfaces.Get(k).i3); INDEX_3 f2(freesetfaces.Get(l).i1, freesetfaces.Get(l).i2, freesetfaces.Get(l).i3); INDEX_2 ed(0, 0); for (int f11 = 1; f11 <= 3; f11++) for (int f12 = 1; f12 <= 3; f12++) if (f11 != f12) for (int f21 = 1; f21 <= 3; f21++) for (int f22 = 1; f22 <= 3; f22++) if (f1.I(f11) == f2.I(f21) && f1.I(f12) == f2.I(f22)) { ed.I(1) = f1.I(f11); ed.I(2) = f1.I(f12); } // (*testout) << "ed = " << ed.I(1) << "-" << ed.I(2) << endl; // (*testout) << "ind = " << ind << " ed = " << ed << endl; for (int eli = 1; eli <= GetNOldF(); eli++) { if (GetNP(eli) == 4) { for (int elr = 1; elr <= 4; elr++) { if (GetPointNrMod (eli, elr) == ed.I(1) && GetPointNrMod (eli, elr+2) == ed.I(2)) { /* (*testout) << "ed is diagonal of rectangle" << endl; (*testout) << "ed = " << ed.I(1) << "-" << ed.I(2) << endl; (*testout) << "ind = " << ind << endl; */ ind = 0; } } } } if (ind) { /* (*testout) << "new edge from face " << k << " = (" << freesetfaces.Get(k).i1 << ", " << freesetfaces.Get(k).i2 << ", " << freesetfaces.Get(k).i3 << "), point " << ind << endl; */ freesetedges.Append(twoint(k,ind)); } } } } } void Meshing3 :: LoadRules (const char * filename, const char ** prules) { char buf[256]; istream * ist; char *tr1 = NULL; if (filename) { PrintMessage (3, "rule-filename = ", filename); ist = new ifstream (filename); } else { /* connect tetrules to one string */ PrintMessage (3, "Use internal rules"); if (!prules) prules = tetrules; const char ** hcp = prules; size_t len = 0; while (*hcp) { len += strlen (*hcp); hcp++; } tr1 = new char[len+1]; tr1[0] = 0; hcp = prules; // tetrules; char * tt1 = tr1; while (*hcp) { strcat (tt1, *hcp); tt1 += strlen (*hcp); hcp++; } #ifdef WIN32 // VC++ 2005 workaround for(size_t i=0; igood()) { cerr << "Rule description file " << filename << " not found" << endl; delete ist; exit (1); } while (!ist->eof()) { buf[0] = 0; (*ist) >> buf; if (strcmp (buf, "rule") == 0) { vnetrule * rule = new vnetrule; rule -> LoadRule(*ist); rules.Append (rule); if (!rule->TestOk()) { PrintSysError ("Parser3d: Rule ", rules.Size(), " not ok"); exit (1); } } else if (strcmp (buf, "tolfak") == 0) { (*ist) >> tolfak; } } delete ist; delete [] tr1; } }