#include #include #include // #undef DEVELOP // #define DEVELOP namespace netgen { EdgeCalculation :: EdgeCalculation (const CSGeometry & ageometry, Array & aspecpoints) : geometry(ageometry), specpoints(aspecpoints) { Box<3> bbox = geometry.BoundingBox(); searchtree = new Point3dTree (bbox.PMin(), bbox.PMax()); meshpoint_tree = new Point3dTree (bbox.PMin(), bbox.PMax()); for (int i = 0; i < specpoints.Size(); i++) searchtree->Insert (specpoints[i].p, i); ideps = 1e-9; } EdgeCalculation :: ~EdgeCalculation() { delete searchtree; delete meshpoint_tree; } void EdgeCalculation :: Calc(double h, Mesh & mesh) { static int timer = NgProfiler::CreateTimer ("CSG: mesh edges"); NgProfiler::RegionTimer reg (timer); PrintMessage (1, "Find edges"); PushStatus ("Find edges"); for (int i = 1; i <= mesh.GetNP(); i++) meshpoint_tree->Insert (mesh.Point(i), i); // add all special points before edge points (important for periodic identification) // JS, Jan 2007 const double di=1e-7*geometry.MaxSize(); Array locsearch; for (int i = 0; i < specpoints.Size(); i++) if (specpoints[i].unconditional) { Point<3> p = specpoints[i].p; meshpoint_tree -> GetIntersecting (p-Vec<3> (di,di,di), p+Vec<3> (di,di,di), locsearch); if (locsearch.Size() == 0) { PointIndex pi = mesh.AddPoint (p, specpoints[i].GetLayer(), FIXEDPOINT); meshpoint_tree -> Insert (p, pi); } } /* // slow version for (int i = 0; i < specpoints.Size(); i++) if (specpoints[i].unconditional) { Point<3> p = specpoints[i].p; bool found = false; for (int j = 1; j <= mesh.GetNP(); j++) if (Dist (p, mesh.Point(j)) < 1e-8) found = true; if (!found) mesh.AddPoint (p, specpoints[i].GetLayer(), FIXEDPOINT); } */ CalcEdges1 (h, mesh); SplitEqualOneSegEdges (mesh); FindClosedSurfaces (h, mesh); PrintMessage (3, cntedge, " edges found"); PopStatus (); } void EdgeCalculation :: CalcEdges1 (double h, Mesh & mesh) { Array hsp(specpoints.Size()); Array glob2hsp(specpoints.Size()); Array startpoints, endpoints; int pos, ep; int layer; Point<3> p, np; int pi1, s1, s2, s1_orig, s2_orig; Array > edgepoints; Array curvelength; int copyedge = 0, copyfromedge = -1, copyedgeidentification = -1; Array locsurfind, locind; int checkedcopy = 0; // double size = geometry.MaxSize(); // double epspointdist2 = sqr (size) * 1e-12; // copy special points to work with for (int i = 0; i < specpoints.Size(); i++) { hsp[i] = i; glob2hsp[i] = i; } //for(int i=0; i identification_used(100); // identification i already used for startpoint j mesh.GetIdentifications().Delete(); TABLE specpoint2surface(specpoints.Size()); if (geometry.identifications.Size()) { for (int i = 0; i < specpoints.Size(); i++) for (int j = 0; j < geometry.GetNSurf(); j++) if (geometry.GetSurface(j)->PointOnSurface (specpoints[i].p)) specpoint2surface.Add (i, j); } TABLE specpoint2tlo(specpoints.Size()); if (geometry.identifications.Size()) { for (int i = 0; i < specpoints.Size(); i++) for (int j = 0; j < geometry.GetNTopLevelObjects(); j++) { const TopLevelObject * tlo = geometry.GetTopLevelObject (j); if (tlo->GetSolid() && tlo->GetSolid()->VectorIn (specpoints[i].p,specpoints[i].v)) //if (tlo->GetSolid() && tlo->GetSolid()->IsIn (specpoints[i].p)) { #ifdef DEVELOP (*testout) << "point " << specpoints[i].p << " v " <GetSolid()->Name() << endl; #endif specpoint2tlo.Add (i, j); } } } for (int i = 0; i < specpoints.Size(); i++) specpoints[i].nr = i; while (hsp.Size()) { SetThreadPercent(100 - 100 * double (hsp.Size()) / specpoints.Size()); #ifdef DEVELOP (*testout) << "hsp.Size() " << hsp.Size() << " specpoints.Size() " << specpoints.Size() << endl; (*testout) << endl << "edge nr " << cntedge+1 << endl; #endif edgepoints.SetSize (0); curvelength.SetSize (0); pi1 = 0; copyedge = 0; // identifyable point available ? for (int i = 0; i < geometry.identifications.Size() && !pi1; i++) for (int j = checkedcopy; j < startpoints.Size() && !pi1; j++) { #ifdef DEVELOP (*testout) << "checking point " << specpoints[startpoints[j]].p << ", v = " << specpoints[startpoints[j]].v << " for copying (i,j = " << i << ", " << j << ")" << endl; #endif if (geometry.identifications[i]->IdentifyableCandidate (specpoints[startpoints[j]]) && geometry.identifications[i]->IdentifyableCandidate (specpoints[endpoints[j]])) { int pi1cand = 0; double mindist = 1e10; for (int k = 0; k < hsp.Size() && !pi1; k++) { //(*testout) << " ? identifyable with " << specpoints[hsp[k]].p //<< ", v = " << specpoints[hsp[k]].v // << endl; if (identification_used.Used (INDEX_2(i, startpoints[j])) || identification_used.Used (INDEX_2(i, hsp[k]))) { //(*testout) << "failed at pos0" << endl; continue; } if (geometry.identifications[i] ->Identifyable(specpoints[startpoints[j]], specpoints[hsp[k]], specpoint2tlo, specpoint2surface) || geometry.identifications[i] ->Identifyable(specpoints[hsp[k]], specpoints[startpoints[j]], specpoint2tlo, specpoint2surface)) { #ifdef DEVELOP (*testout) << "identifyable: " << specpoints[hsp[k]].p << ", v = " << specpoints[hsp[k]].v << " and " << specpoints[startpoints[j]].p << ", v = " << specpoints[startpoints[j]].v << " (identification " << i+1 << ")" << endl; #endif if (Dist (specpoints[startpoints[j]].p, specpoints[hsp[k]].p) < mindist) { mindist = Dist (specpoints[startpoints[j]].p, specpoints[hsp[k]].p); pi1cand = k+1; } } } if (pi1cand) { pi1 = pi1cand; copyedge = 1; copyfromedge = j+1; copyedgeidentification = i+1; identification_used.Set (INDEX_2(i, startpoints[j]), 1); identification_used.Set (INDEX_2(i, hsp.Get(pi1)), 1); } } } // cannot copy from other ege ? if (!pi1) checkedcopy = startpoints.Size(); // unconditional special point available ? if (!pi1) for (int i = 1; i <= hsp.Size(); i++) if (specpoints[hsp.Get(i)].unconditional == 1) { pi1 = i; break; } if (!pi1) { // no unconditional points available, choose first conitional pi1 = 1; } layer = specpoints[hsp.Get(pi1)].GetLayer(); if (!specpoints[hsp.Get(pi1)].unconditional) { specpoints[hsp.Elem(pi1)].unconditional = 1; for (int i = 1; i <= hsp.Size(); i++) if (i != pi1 && Dist (specpoints[hsp.Get(pi1)].p, specpoints[hsp.Get(i)].p) < 1e-8*geometry.MaxSize() && (specpoints[hsp.Get(pi1)].v + specpoints[hsp.Get(i)].v).Length() < 1e-4) { // opposite direction specpoints[hsp.Elem(i)].unconditional = 1; } } cntedge++; startpoints.Append (hsp.Get(pi1)); #ifdef DEVELOP (*testout) << "start followedge: p1 = " << specpoints[hsp.Get(pi1)].p << ", v = " << specpoints[hsp.Get(pi1)].v << endl; #endif FollowEdge (pi1, ep, pos, hsp, h, mesh, edgepoints, curvelength); if (multithread.terminate) return; if (!ep) { // ignore starting point hsp.DeleteElement (pi1); cout << "yes, this happens" << endl; continue; } endpoints.Append (hsp.Get(ep)); double elen = 0; for (int i = 1; i <= edgepoints.Size()-1; i++) elen += Dist (edgepoints.Get(i), edgepoints.Get(i+1)); int shortedge = 0; for (int i = 1; i <= geometry.identifications.Size(); i++) if (geometry.identifications.Get(i)->ShortEdge(specpoints[hsp.Get(pi1)], specpoints[hsp.Get(ep)])) shortedge = 1; // (*testout) << "shortedge = " << shortedge << endl; if (!shortedge) { mesh.RestrictLocalHLine (Point3d (specpoints[hsp.Get(pi1)].p), Point3d (specpoints[hsp.Get(ep)].p), elen / mparam.segmentsperedge); } s1 = specpoints[hsp.Get(pi1)].s1; s2 = specpoints[hsp.Get(pi1)].s2; s1_orig = specpoints[hsp.Get(pi1)].s1_orig; s2_orig = specpoints[hsp.Get(pi1)].s2_orig; // delete initial, terminal and conditional points #ifdef DEVELOP (*testout) << "terminal point: p = " << specpoints[hsp.Get(ep)].p << ", v = " << specpoints[hsp.Get(ep)].v << endl; #endif searchtree -> DeleteElement (hsp.Get(ep)); searchtree -> DeleteElement (hsp.Get(pi1)); if (ep > pi1) { glob2hsp[hsp[ep-1]] = -1; glob2hsp[hsp.Last()] = ep-1; hsp.DeleteElement (ep); glob2hsp[hsp[pi1-1]] = -1; glob2hsp[hsp.Last()] = pi1-1; hsp.DeleteElement (pi1); } else { glob2hsp[hsp[pi1-1]] = -1; glob2hsp[hsp.Last()] = pi1-1; hsp.DeleteElement (pi1); glob2hsp[hsp[ep-1]] = -1; glob2hsp[hsp.Last()] = ep-1; hsp.DeleteElement (ep); } for (int j = 1; j <= edgepoints.Size()-1; j++) { p = edgepoints.Get(j); np = Center (p, edgepoints.Get(j+1)); double hd = Dist (p, np); Box<3> boxp (np - (1.2 * hd) * Vec<3> (1, 1, 1), np + (1.2 * hd) * Vec<3> (1, 1, 1)); searchtree -> GetIntersecting (boxp.PMin(), boxp.PMax(), locind); for (int i = 0; i < locind.Size(); i++) { if ( specpoints[locind[i]].HasSurfaces (s1, s2) && specpoints[locind[i]].unconditional == 0) { searchtree -> DeleteElement (locind[i]); int li = glob2hsp[locind[i]]; glob2hsp[locind[i]] = -1; glob2hsp[hsp.Last()] = li; hsp.Delete (li); } } /* for (int i = 1; i <= hsp.Size(); i++) if ( specpoints[hsp.Get(i)].HasSurfaces (s1, s2) && specpoints[hsp.Get(i)].unconditional == 0 && Dist2 (np, specpoints[hsp.Get(i)].p) < 1.2 * hd) { searchtree -> DeleteElement (hsp.Get(i)+1); hsp.DeleteElement (i); i--; } */ } Array refedges; Array refedgesinv; AnalyzeEdge (s1_orig, s2_orig, s1, s2, pos, layer, edgepoints, refedges, refedgesinv); for (int i = 0; i < refedges.Size(); i++) refedges[i].edgenr = cntedge; #ifdef DEVELOP (*testout) << "edge " << cntedge << endl << "startp: " << specpoints[startpoints.Last()].p << ", v = " << specpoints[startpoints.Last()].v << endl << "copy = " << copyedge << endl << refedges.Size() << " refedges: "; for (int i = 1; i <= refedges.Size(); i++) (*testout) << " " << refedges.Get(i).si; (*testout) << endl; if (refedgesinv.Size()) (*testout) << "inv[1] = " << refedgesinv.Get(1) << endl; #endif if (refedges.Size() == 0) throw NgException ("Problem in edge detection"); if (!copyedge) { // (*testout) << "store edge" << endl; // int oldnseg = mesh.GetNSeg(); if (!shortedge) StoreEdge (refedges, refedgesinv, edgepoints, curvelength, layer, mesh); else StoreShortEdge (refedges, refedgesinv, edgepoints, curvelength, layer, mesh); for(int i = 0; i < refedges.Size(); i++) { refedges[i].surfnr1 = geometry.GetSurfaceClassRepresentant(refedges[i].surfnr1); refedges[i].surfnr2 = geometry.GetSurfaceClassRepresentant(refedges[i].surfnr2); } /* for (int i = oldnseg+1; i <= mesh.GetNSeg(); i++) for (int j = 1; j <= oldnseg; j++) { const Point<3> & l1p1 = mesh.Point (mesh.LineSegment(i).p1); const Point<3> & l1p2 = mesh.Point (mesh.LineSegment(i).p2); const Point<3> & l2p1 = mesh.Point (mesh.LineSegment(j).p1); const Point<3> & l2p2 = mesh.Point (mesh.LineSegment(j).p2); Vec<3> vl1(l1p1, l1p2); for (double lamk = 0; lamk <= 1; lamk += 0.1) { Point<3> l2p = l1p1 + lamk * vl1; double dist = sqrt (MinDistLP2 (l2p1, l2p2, l2p)); if (dist > 1e-12) mesh.RestrictLocalH (l2p, 3*dist); } } */ } else { CopyEdge (refedges, refedgesinv, copyfromedge, specpoints[startpoints.Get(copyfromedge)].p, specpoints[endpoints.Get(copyfromedge)].p, edgepoints.Get(1), edgepoints.Last(), copyedgeidentification, layer, mesh); } /* // not available ... for (int i = 0; i < refedges.Size(); i++) { EdgeDescriptor ed; ed.SetSurfNr(0, refedges[i].surfnr1); ed.SetSurfNr(1, refedges[i].surfnr2); int hnr = mesh.AddEdgeDescriptor(ed); if (hnr != refedges[i].edgenr) { cerr << "edgedescriptor index wrong: new : " << hnr << " old = " << refedges[i].edgenr << endl; } } */ // for(int i=0; i osedges(cntedge); INDEX_2_HASHTABLE osedgesht (cntedge+1); osedges = 2; // count segments on edges for (si = 0; si < mesh.GetNSeg(); si++) { const Segment & seg = mesh[si]; if (seg.seginfo && seg.edgenr >= 1 && seg.edgenr <= cntedge) osedges.Elem(seg.edgenr)--; } // flag one segment edges for (int i = 0; i < cntedge; i++) osedges[i] = (osedges[i] > 0) ? 1 : 0; for (si = 0; si < mesh.GetNSeg(); si++) { const Segment & seg = mesh[si]; if (seg.seginfo && seg.edgenr >= 1 && seg.edgenr <= cntedge) { if (osedges.Get(seg.edgenr)) { INDEX_2 i2(seg[0], seg[1]); i2.Sort (); if (osedgesht.Used (i2)) osedgesht.Set (i2, 2); else osedgesht.Set (i2, 1); } } } // one edge 1 segment, other 2 segments // yes, it happens ! point_on_edge_problem = 0; for (int i = 1; i <= osedgesht.GetNBags(); i++) for (int j = 1; j <= osedgesht.GetBagSize(i); j++) { INDEX_2 i2; int val; osedgesht.GetData (i, j, i2, val); const Point<3> & p1 = mesh[PointIndex(i2.I1())]; const Point<3> & p2 = mesh[PointIndex(i2.I2())]; Vec<3> v = p2 - p1; double vlen = v.Length(); v /= vlen; for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (pi != i2.I1() && pi != i2.I2()) { const Point<3> & p = mesh[pi]; Vec<3> v2 = p - p1; double lam = (v2 * v); if (lam > 0 && lam < vlen) { Point<3> hp = p1 + lam * v; if (Dist (p, hp) < 1e-4 * vlen) { PrintWarning ("Point on edge !!!"); cout << "seg: " << i2 << ", p = " << pi << endl; osedgesht.Set (i2, 2); point_on_edge_problem = 1; (*testout) << "Point on edge" << endl << "seg = " << i2 << ", p = " << pi << endl << "pos = " << p << ", projected = " << hp << endl << "seg is = " << mesh.Point(i2.I1()) << " - " << mesh.Point(i2.I2()) << endl; } } } } // insert new points osedges = -1; int nseg = mesh.GetNSeg(); for (si = 0; si < nseg; si++) { const Segment & seg = mesh[si]; if (seg.seginfo && seg.edgenr >= 1 && seg.edgenr <= cntedge) { INDEX_2 i2(seg[0], seg[1]); i2.Sort (); if (osedgesht.Used (i2) && osedgesht.Get (i2) == 2 && osedges.Elem(seg.edgenr) == -1) { Point<3> newp = Center (mesh[PointIndex(seg[0])], mesh[PointIndex(seg[1])]); ProjectToEdge (geometry.GetSurface(seg.surfnr1), geometry.GetSurface(seg.surfnr2), newp); osedges.Elem(seg.edgenr) = mesh.AddPoint (newp, mesh[PointIndex(seg[0])].GetLayer(), EDGEPOINT); meshpoint_tree -> Insert (newp, osedges.Elem(seg.edgenr)); } } } for (int i = 1; i <= nseg; i++) { Segment & seg = mesh.LineSegment (i); if (seg.edgenr >= 1 && seg.edgenr <= cntedge) { if (osedges.Get(seg.edgenr) != -1) { Segment newseg = seg; newseg[0] = osedges.Get(seg.edgenr); seg[1] = osedges.Get(seg.edgenr); mesh.AddSegment (newseg); } } } } void EdgeCalculation :: FollowEdge (int pi1, int & ep, int & pos, const Array & hsp, double h, const Mesh & mesh, Array > & edgepoints, Array & curvelength) { int s1, s2, s1_rep, s2_rep; double len, steplen, cursteplen, loch; Point<3> p, np, pnp; Vec<3> a1, a2, t; Array locind; double size = geometry.MaxSize(); double epspointdist2 = size * 1e-6; epspointdist2 = sqr (epspointdist2); int uselocalh = mparam.uselocalh; s1_rep = specpoints[hsp.Get(pi1)].s1; s2_rep = specpoints[hsp.Get(pi1)].s2; s1 = specpoints[hsp.Get(pi1)].s1_orig; s2 = specpoints[hsp.Get(pi1)].s2_orig; p = specpoints[hsp.Get(pi1)].p; //ProjectToEdge (geometry.GetSurface(s1), // geometry.GetSurface(s2), p); geometry.GetSurface(s1) -> CalcGradient (p, a1); geometry.GetSurface(s2) -> CalcGradient (p, a2); t = Cross (a1, a2); t.Normalize(); pos = (specpoints[hsp.Get(pi1)].v * t) > 0; if (!pos) t *= -1; edgepoints.Append (p); curvelength.Append (0); len = 0; // (*testout) << "geometry.GetSurface(s1) -> LocH (p, 3, 1, h) " << geometry.GetSurface(s1) -> LocH (p, 3, 1, h) // << " geometry.GetSurface(s2) -> LocH (p, 3, 1, h) " << geometry.GetSurface(s2) -> LocH (p, 3, 1, h) << endl; loch = min2 (geometry.GetSurface(s1) -> LocH (p, 3, 1, h), geometry.GetSurface(s2) -> LocH (p, 3, 1, h)); if (uselocalh) { double lh = mesh.GetH(p); // (*testout) << "lh " << lh << endl; if (lh < loch) loch = lh; } steplen = 0.1 * loch; do { if (multithread.terminate) return; if (fabs (p(0)) + fabs (p(1)) + fabs (p(2)) > 100000*size) { ep = 0; PrintWarning ("Give up line"); break; } if (steplen > 0.1 * loch) steplen = 0.1 * loch; steplen *= 2; do { steplen *= 0.5; np = p + steplen * t; pnp = np; ProjectToEdge (geometry.GetSurface(s1), geometry.GetSurface(s2), pnp); } while (Dist (np, pnp) > 0.1 * steplen); cursteplen = steplen; if (Dist (np, pnp) < 0.01 * steplen) steplen *= 2; np = pnp; ep = 0; double hvtmin = 1.5 * cursteplen; Box<3> boxp (p - (2 * cursteplen) * Vec<3> (1, 1, 1), p + (2 * cursteplen) * Vec<3> (1, 1, 1)); searchtree -> GetIntersecting (boxp.PMin(), boxp.PMax(), locind); for (int i = 0; i < locind.Size(); i++) { Vec<3> hv = specpoints[locind[i]].p - p; if (hv.Length2() > 9 * cursteplen * cursteplen) continue; double hvt = hv * t; hv -= hvt * t; if (hv.Length() < 0.2 * cursteplen && hvt > 0 && // hvt < 1.5 * cursteplen && hvt < hvtmin && specpoints[locind[i]].unconditional == 1 && (specpoints[locind[i]].v + t).Length() < 0.4 ) { Point<3> hep = specpoints[locind[i]].p; ProjectToEdge (geometry.GetSurface(s1), geometry.GetSurface(s2), hep); if (Dist2 (hep, specpoints[locind[i]].p) < epspointdist2 ) { geometry.GetSurface(s1) -> CalcGradient (hep, a1); geometry.GetSurface(s2) -> CalcGradient (hep, a2); Vec<3> ept = Cross (a1, a2); ept /= ept.Length(); if (!pos) ept *= -1; if ( (specpoints[locind[i]].v + ept).Length() < 1e-4 ) { np = specpoints[locind[i]].p; for (int jj = 0; jj < hsp.Size(); jj++) if (hsp[jj] == locind[i]) ep = jj+1; if (!ep) cerr << "endpoint not found" << endl; // ep = i; hvtmin = hvt; // break; } } } } /* for (int i = 1; i <= hsp.Size(); i++) { if (!boxp.IsIn (specpoints[hsp.Get(i)].p)) continue; Vec<3> hv = specpoints[hsp.Get(i)].p - p; if (hv.Length2() > 9 * cursteplen * cursteplen) continue; double hvt = hv * t; hv -= hvt * t; if (hv.Length() < 0.2 * cursteplen && hvt > 0 && // hvt < 1.5 * cursteplen && hvt < hvtmin && specpoints[hsp.Get(i)].unconditional == 1 && (specpoints[hsp.Get(i)].v + t).Length() < 0.4 ) { Point<3> hep = specpoints[hsp.Get(i)].p; ProjectToEdge (geometry.GetSurface(s1), geometry.GetSurface(s2), hep); if (Dist2 (hep, specpoints[hsp.Get(i)].p) < epspointdist2 ) { geometry.GetSurface(s1) -> CalcGradient (hep, a1); geometry.GetSurface(s2) -> CalcGradient (hep, a2); Vec<3> ept = Cross (a1, a2); ept /= ept.Length(); if (!pos) ept *= -1; if ( (specpoints[hsp.Get(i)].v + ept).Length() < 1e-4 ) { np = specpoints[hsp.Get(i)].p; ep = i; hvtmin = hvt; // break; } } } } */ loch = min2 (geometry.GetSurface(s1_rep) -> LocH (np, 3, 1, h), geometry.GetSurface(s2_rep) -> LocH (np, 3, 1, h)); loch = max2 (loch, mparam.minh); if (uselocalh) { double lh = mesh.GetH(np); if (lh < loch) loch = lh; } len += Dist (p, np) / loch; edgepoints.Append (np); curvelength.Append (len); p = np; geometry.GetSurface(s1) -> CalcGradient (p, a1); geometry.GetSurface(s2) -> CalcGradient (p, a2); t = Cross (a1, a2); t.Normalize(); if (!pos) t *= -1; } while (! ep); } void EdgeCalculation :: AnalyzeEdge (int s1, int s2, int s1_rep, int s2_rep, int pos, int layer, const Array > & edgepoints, Array & refedges, Array & refedgesinv) { Segment seg; Array locsurfind, locsurfind2; Array edges_priority; double size = geometry.MaxSize(); bool debug = 0; #ifdef DEVELOP debug = 1; #endif if (debug) { (*testout) << "debug edge !!!" << endl; (*testout) << "edgepoints = " << edgepoints << endl; (*testout) << "s1, s2 = " << s1 << " - " << s2 << endl; (*testout) << "s1_rep, s2_rep = " << s1_rep << " - " << s2_rep << endl; } refedges.SetSize(0); refedgesinv.SetSize(0); Point<3> hp = Center (edgepoints[0], edgepoints[1]); ProjectToEdge (geometry.GetSurface(s1), geometry.GetSurface(s2), hp); if (debug) *testout << "hp = " << hp << endl; Vec<3> t, a1, a2; geometry.GetSurface(s1) -> CalcGradient (hp, a1); geometry.GetSurface(s2) -> CalcGradient (hp, a2); t = Cross (a1, a2); t.Normalize(); if (!pos) t *= -1; for (int i = 0; i < geometry.GetNTopLevelObjects(); i++) { Solid * locsol; if (geometry.GetTopLevelObject(i)->GetLayer() != layer) continue; const Solid * sol = geometry.GetTopLevelObject(i)->GetSolid(); const Surface * surf = geometry.GetTopLevelObject(i)->GetSurface(); sol -> TangentialSolid (hp, locsol, locsurfind, size*ideps); //*testout << "hp = " << hp << endl; //(*testout) << "locsol: " << endl; //if (locsol) locsol->Print(*testout); //(*testout) << endl; if (!locsol) continue; BoxSphere<3> boxp (hp, hp); boxp.Increase (1e-8*size); boxp.CalcDiamCenter(); ReducePrimitiveIterator rpi(boxp); UnReducePrimitiveIterator urpi; ((Solid*)locsol) -> IterateSolid (rpi); locsol -> CalcSurfaceInverse (); if (!surf) { locsol -> GetTangentialSurfaceIndices (hp,locsurfind,ideps*size); } else { /* if (fabs (surf->CalcFunctionValue (hp)) < 1e-6) continue; */ locsurfind.SetSize(1); locsurfind[0] = -1; for (int j = 0; j < geometry.GetNSurf(); j++) if (geometry.GetSurface(j) == surf) { locsurfind[0] = j; // geometry.GetSurfaceClassRepresentant(j); break; } } ((Solid*)locsol) -> IterateSolid (urpi); if (debug) (*testout) << "edge of tlo " << i << ", has " << locsurfind.Size() << " faces." << endl; for (int j = locsurfind.Size()-1; j >= 0; j--) if (fabs (geometry.GetSurface(locsurfind[j]) ->CalcFunctionValue (hp) ) > ideps*size) locsurfind.Delete(j); if (debug) (*testout) << locsurfind.Size() << " faces on hp" << endl; for (int j = 0; j < locsurfind.Size(); j++) { int lsi = locsurfind[j]; int rlsi = geometry.GetSurfaceClassRepresentant(lsi); // n is outer normal to solid Vec<3> n = geometry.GetSurface(lsi) -> GetNormalVector (hp); if (debug) *testout << "n1 = " << n << endl; if (geometry.GetSurface (lsi)->Inverse()) n *= -1; if (fabs (t * n) > 1e-4) continue; if (debug) { (*testout) << "face " << locsurfind[j] << ", rep = " << rlsi << " has (t*n) = " << (t*n) << endl; (*testout) << "n = " << n << endl; } // rn is normal to class representant Vec<3> rn = geometry.GetSurface(rlsi) -> GetNormalVector (hp); if (debug) { (*testout) << "rn = " << rn << endl; } //if( n*rn < 0) // rn *= -1; bool sameasref = ((n * rn) > 0); //m = Cross (t, rn); Vec<3> m = Cross (t, n); if(!sameasref) m*=-1.; m.Normalize(); if (debug) (*testout) << "m = " << m << endl; //bool founddirection = false; //int k; double eps = 1e-8*size; Array pre_ok(2); do { eps *= 0.5; pre_ok[0] = (locsol -> VectorIn2 (hp, m, n, eps) == IS_OUTSIDE && locsol -> VectorIn2 (hp, m, -1. * n, eps) == IS_INSIDE); pre_ok[1] = (locsol -> VectorIn2 (hp, -1.*m, n, eps) == IS_OUTSIDE && locsol -> VectorIn2 (hp, -1.*m, -1. * n, eps) == IS_INSIDE); if (debug) { *testout << "eps = " << eps << endl; *testout << "in,1 = " << locsol -> VectorIn2 (hp, m, n, eps) << endl; *testout << "in,1 = " << locsol -> VectorIn2 (hp, m, -1. * n, eps) << endl; *testout << "in,1 = " << locsol -> VectorIn2 (hp, -1.*m, n, eps) << endl; *testout << "in,1 = " << locsol -> VectorIn2 (hp, -1.*m, -1. * n, eps) << endl; } } while(pre_ok[0] && pre_ok[1] && eps > 1e-16*size); if (debug) { *testout << "eps = " << eps << ", size = " << size << endl; *testout << "pre_ok[0,1] = " << pre_ok[0] << "," << pre_ok[1] << endl; } eps = 1e-8*size; for (int k = 1; k <= 2; k ++) { bool edgeinv = (k == 2); if (debug) { (*testout) << "onface(" << hp << ", " << m << ")= " << flush; (*testout) << locsol->OnFace (hp, m, eps) << flush; (*testout) << " n " << n << flush; (*testout) << " vec2in = " << locsol -> VectorIn2 (hp, m, n, eps) << " and " << locsol -> VectorIn2 (hp, m, -1 * n, eps) << endl; } // if (locsol -> OnFace (hp, m)) // one side must be inside, the other must be outside bool ok = (pre_ok[k-1] || (locsol -> VectorIn2 (hp, m, n, eps) == IS_OUTSIDE && locsol -> VectorIn2 (hp, m, -1 * n, eps) == IS_INSIDE)); if (debug) (*testout) << "ok (before) " << ok << endl; // compute second order approximation // curve = hp + t m + t*t/2 m2 Vec<3> grad, m2; Mat<3> hesse; geometry.GetSurface(lsi) -> CalcGradient (hp, grad); geometry.GetSurface(lsi) -> CalcHesse (hp, hesse); double fac = -(m * (hesse * m)) / (grad * grad); m2 = fac * grad; // (*testout) << "hp = " << hp << ", m = " << m << ", m2 = " << m2 << endl; Solid * locsol2; locsol -> TangentialSolid3 (hp, m, m2, locsol2, locsurfind2, ideps*size); if (!locsol2) ok = 0; delete locsol2; if (ok) { if (debug) (*testout) << "is true" << endl; int hi = 0; for (int l = 1; !hi && l <= refedges.Size(); l++) { if (refedges.Get(l).si == rlsi && // JS sept 2006 // if (refedges.Get(l).si == lsi && refedgesinv.Get(l) == edgeinv) { hi = l; } } if (!hi) { seg.si = rlsi; // JS Sept 2006 // seg.si = lsi; seg.domin = -1; seg.domout = -1; seg.tlosurf = -1; //seg.surfnr1 = s1_rep; //seg.surfnr2 = s2_rep; seg.surfnr1 = s1; seg.surfnr2 = s2; hi = refedges.Append (seg); refedgesinv.Append (edgeinv); edges_priority.Append((pre_ok[k-1]) ? 1 : 0); } else { if(edges_priority[hi-1] / 10 == -i-1) edges_priority[hi-1] = 10*(i+1); else edges_priority[hi-1] = -10*(i+1); } if (!surf) { if (sameasref) refedges.Elem(hi).domin = i; else refedges.Elem(hi).domout = i; } else refedges.Elem(hi).tlosurf = i; if(pre_ok[k-1]) edges_priority[hi-1] = 1; if (debug) (*testout) << "add ref seg:" << "si = " << refedges.Get(hi).si << ", domin = " << refedges.Get(hi).domin << ", domout = " << refedges.Get(hi).domout << ", surfnr1/2 = " << refedges.Get(hi).surfnr1 << ", " << refedges.Get(hi).surfnr2 << ", inv = " << refedgesinv.Get(hi) << ", refedgenr = " << hi << ", priority = " << edges_priority[hi-1] << ", hi = " << hi << endl; } else { if (debug) (*testout) << "is false" << endl; } m *= -1; } } delete locsol; } if (debug) { *testout << "Refsegments, before delete: " << endl << refedges << endl; *testout << "inv: " << endl << refedgesinv << endl; } BitArray todelete(refedges.Size()); todelete.Clear(); for(int i=0; i edges_priority[j]) { todelete.Set(j); } } } } int num = refedges.Size(); for(int i=refedges.Size()-1; num>2 && i>=0; i--) if(todelete.Test(i)) { refedges.Delete(i); refedgesinv.Delete(i); num--; } if (debug) { *testout << "Refsegments: " << endl << refedges << endl; } } void EdgeCalculation :: StoreEdge (const Array & refedges, const Array & refedgesinv, const Array > & edgepoints, const Array & curvelength, int layer, Mesh & mesh) { // Calculate optimal element-length int i, j, k; PointIndex pi; int ne; double len, corr, lam; PointIndex thispi, lastpi; Point<3> p, np; Segment seg; const Surface * surf1 = geometry.GetSurface (refedges.Get(1).surfnr1); const Surface * surf2 = geometry.GetSurface (refedges.Get(1).surfnr2); (*testout) << "s1 " << refedges.Get(1).surfnr1 << " s2 " << refedges.Get(1).surfnr2 << " rs1 " << geometry.GetSurfaceClassRepresentant(refedges.Get(1).surfnr1) << " rs2 " << geometry.GetSurfaceClassRepresentant(refedges.Get(1).surfnr2) << endl; len = curvelength.Last(); ne = int (len + 0.5); if (ne == 0) ne = 1; if (Dist (edgepoints.Get(1), edgepoints.Last()) < 1e-8*geometry.MaxSize() && ne <= 6) ne = 6; corr = len / ne; // generate initial point p = edgepoints.Get(1); lastpi = -1; /* for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (Dist (mesh[pi], p) < 1e-6) { lastpi = pi; break; } */ const double di=1e-7*geometry.MaxSize(); Array locsearch; meshpoint_tree -> GetIntersecting (p-Vec<3> (di,di,di), p+Vec<3> (di,di,di), locsearch); if (locsearch.Size()) lastpi = locsearch[0]; if (lastpi == -1) { lastpi = mesh.AddPoint (p, layer, FIXEDPOINT); meshpoint_tree -> Insert (p, lastpi); // (*testout) << "test1, store point " << lastpi << ", p = " << p << endl; } j = 1; for (i = 1; i <= ne; i++) { while (curvelength.Get(j) < i * corr && j < curvelength.Size()) j++; lam = (i * corr - curvelength.Get(j-1)) / (curvelength.Get(j) - curvelength.Get(j-1)); np(0) = (1-lam) * edgepoints.Get(j-1)(0) + lam * edgepoints.Get(j)(0); np(1) = (1-lam) * edgepoints.Get(j-1)(1) + lam * edgepoints.Get(j)(1); np(2) = (1-lam) * edgepoints.Get(j-1)(2) + lam * edgepoints.Get(j)(2); thispi = -1; if (i == ne) { /* for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (Dist(mesh[pi], np) < 1e-6) thispi = pi; */ meshpoint_tree -> GetIntersecting (np-Vec<3> (di,di,di), np+Vec<3> (di,di,di), locsearch); if (locsearch.Size()) thispi = locsearch[0]; } if (thispi == -1) { ProjectToEdge (surf1, surf2, np); thispi = mesh.AddPoint (np, layer, (i==ne) ? FIXEDPOINT : EDGEPOINT); meshpoint_tree -> Insert (np, thispi); // (*testout) << "test2, store point " << thispi << ", p = " << np << endl; } for (k = 1; k <= refedges.Size(); k++) { if (refedgesinv.Get(k)) { seg[0] = lastpi; seg[1] = thispi; } else { seg[0] = thispi; seg[1] = lastpi; } seg.si = refedges.Get(k).si; seg.domin = refedges.Get(k).domin; seg.domout = refedges.Get(k).domout; seg.tlosurf = refedges.Get(k).tlosurf; seg.edgenr = refedges.Get(k).edgenr; seg.surfnr1 = refedges.Get(k).surfnr1; seg.surfnr2 = refedges.Get(k).surfnr2; seg.seginfo = 0; if (k == 1) seg.seginfo = (refedgesinv.Get(k)) ? 2 : 1; mesh.AddSegment (seg); //(*testout) << "add seg " << mesh[seg.p1] << "-" << mesh[seg.p2] << endl; //(*testout) << "refedge " << k << " surf1 " << seg.surfnr1 << " surf2 " << seg.surfnr2 << " inv " << refedgesinv.Get(k) << endl; double maxh = min2 (geometry.GetSurface(seg.surfnr1)->GetMaxH(), geometry.GetSurface(seg.surfnr2)->GetMaxH()); if (seg.domin != -1) { const Solid * s1 = geometry.GetTopLevelObject(seg.domin) -> GetSolid(); maxh = min2 (maxh, s1->GetMaxH()); maxh = min2 (maxh, geometry.GetTopLevelObject(seg.domin)->GetMaxH()); mesh.RestrictLocalH (p, maxh); mesh.RestrictLocalH (np, maxh); } if (seg.domout != -1) { const Solid * s1 = geometry.GetTopLevelObject(seg.domout) -> GetSolid(); maxh = min2 (maxh, s1->GetMaxH()); maxh = min2 (maxh, geometry.GetTopLevelObject(seg.domout)->GetMaxH()); mesh.RestrictLocalH (p, maxh); mesh.RestrictLocalH (np, maxh); } if (seg.tlosurf != -1) { double hi = geometry.GetTopLevelObject(seg.tlosurf) -> GetMaxH(); maxh = min2 (maxh, hi); mesh.RestrictLocalH (p, maxh); mesh.RestrictLocalH (np, maxh); } } p = np; lastpi = thispi; } #ifdef DEVELOP (*testout) << " eplast = " << lastpi << " = " << p << endl; #endif } void EdgeCalculation :: StoreShortEdge (const Array & refedges, const Array & refedgesinv, const Array > & edgepoints, const Array & curvelength, int layer, Mesh & mesh) { // Calculate optimal element-length PointIndex pi; // int ne; Segment seg; /* double len, corr, lam; int thispi, lastpi; Point<3> p, np; const Surface * surf1 = geometry.GetSurface (refedges.Get(1).surfnr1); const Surface * surf2 = geometry.GetSurface (refedges.Get(1).surfnr2); len = curvelength.Last(); ne = int (len + 0.5); if (ne == 0) ne = 1; if (Dist2 (edgepoints[1], edgepoints.Last()) < 1e-8 && ne <= 6) ne = 6; corr = len / ne; */ // generate initial point Point<3> p = edgepoints[0]; PointIndex pi1 = -1; for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (Dist (mesh[pi], p) < 1e-6*geometry.MaxSize()) { pi1 = pi; break; } if (pi1 == -1) { pi1 = mesh.AddPoint (p, layer, FIXEDPOINT); meshpoint_tree -> Insert (p, pi1); // (*testout) << "test3, store point " << pi1 << ", p = " << p << endl; } p = edgepoints.Last(); PointIndex pi2 = -1; for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (Dist (mesh[pi], p) < 1e-6*geometry.MaxSize()) { pi2 = pi; break; } if (pi2==-1) { pi2 = mesh.AddPoint (p, layer, FIXEDPOINT); meshpoint_tree -> Insert (p, pi2); // (*testout) << "test4, store point " << pi2 << ", p = " << p << endl; } /* j = 1; for (i = 1; i <= ne; i++) { while (curvelength[j] < i * corr && j < curvelength.Size()) j++; lam = (i * corr - curvelength[j-1]) / (curvelength[j] - curvelength[j-1]); np(0) = (1-lam) * edgepoints[j-1](0) + lam * edgepoints[j](0); np(1) = (1-lam) * edgepoints[j-1](1) + lam * edgepoints[j](1); np(2) = (1-lam) * edgepoints[j-1](2) + lam * edgepoints[j](2); thispi = 0; if (i == ne) for (j = 1; j <= mesh.GetNP(); j++) if (Dist(mesh.Point(j), np) < 1e-6) thispi = j; if (!thispi) { ProjectToEdge (surf1, surf2, np); thispi = mesh.AddPoint (np); } */ // (*testout) << "short edge " << pi1 << " - " << pi2 << endl; for (int k = 1; k <= refedges.Size(); k++) { if (refedgesinv.Get(k)) { seg[0] = pi1; seg[1] = pi2; } else { seg[0] = pi2; seg[1] = pi1; } seg.si = refedges.Get(k).si; seg.domin = refedges.Get(k).domin; seg.domout = refedges.Get(k).domout; seg.tlosurf = refedges.Get(k).tlosurf; seg.edgenr = refedges.Get(k).edgenr; seg.surfnr1 = refedges.Get(k).surfnr1; seg.surfnr2 = refedges.Get(k).surfnr2; seg.seginfo = 0; if (k == 1) seg.seginfo = (refedgesinv.Get(k)) ? 2 : 1; mesh.AddSegment (seg); // (*testout) << "add seg " << seg[0] << "-" << seg[1] << endl; } } void EdgeCalculation :: CopyEdge (const Array & refedges, const Array & refedgesinv, int copyfromedge, const Point<3> & fromstart, const Point<3> & fromend, const Point<3> & tostart, const Point<3> & toend, int copyedgeidentification, int layer, Mesh & mesh) { int k; PointIndex pi; double size = geometry.MaxSize(); // copy start and end points for (int i = 1; i <= 2; i++) { Point<3> fromp = (i == 1) ? fromstart : fromend; Point<3> top = (i == 1) ? tostart : toend; PointIndex frompi = -1; PointIndex topi = -1; for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) { if (Dist2 (mesh[pi], fromp) <= 1e-16*size) frompi = pi; if (Dist2 (mesh[pi], top) <= 1e-16*size) topi = pi; } if (topi == -1) { topi = mesh.AddPoint (top, layer, FIXEDPOINT); meshpoint_tree -> Insert (top, topi); } const Identification & csi = (*geometry.identifications.Get(copyedgeidentification)); if (csi.Identifyable (mesh[frompi], mesh[topi])) mesh.GetIdentifications().Add(frompi, topi, copyedgeidentification); else if (csi.Identifyable (mesh[topi], mesh[frompi])) mesh.GetIdentifications().Add(topi, frompi, copyedgeidentification); else { cerr << "edgeflw.cpp: should identify, but cannot"; exit(1); } #ifdef DEVELOP (*testout) << "adding identification " << mesh[frompi] << "; " << mesh[topi] << " (id " << copyedgeidentification <<")" << endl; #endif /* (*testout) << "Add Identification from CopyEdge, p1 = " << mesh[PointIndex(frompi)] << ", p2 = " << mesh[PointIndex(topi)] << endl; mesh.GetIdentifications().Add(frompi, topi, copyedgeidentification); */ } int oldns = mesh.GetNSeg(); for (int i = 1; i <= oldns; i++) { // real copy, since array might be reallocated !! const Segment oldseg = mesh.LineSegment(i); if (oldseg.edgenr != copyfromedge) continue; if (oldseg.seginfo == 0) continue; int pi1 = oldseg[0]; int pi2 = oldseg[1]; int npi1 = geometry.identifications.Get(copyedgeidentification) -> GetIdentifiedPoint (mesh, pi1); int npi2 = geometry.identifications.Get(copyedgeidentification) -> GetIdentifiedPoint (mesh, pi2); //(*testout) << "copy edge, pts = " << npi1 << " - " << npi2 << endl; Segment seg; for (k = 1; k <= refedges.Size(); k++) { bool inv = refedgesinv.Get(k); // other edge is inverse if (oldseg.seginfo == 1) inv = !inv; // (*testout) << "inv, now = " << inv << endl; if (inv) { seg[0] = npi1; seg[1] = npi2; } else { seg[0] = npi2; seg[1] = npi1; } seg.si = refedges.Get(k).si; seg.domin = refedges.Get(k).domin; seg.domout = refedges.Get(k).domout; seg.tlosurf = refedges.Get(k).tlosurf; seg.edgenr = refedges.Get(k).edgenr; seg.surfnr1 = refedges.Get(k).surfnr1; seg.surfnr2 = refedges.Get(k).surfnr2; seg.seginfo = 0; if (k == 1) seg.seginfo = refedgesinv.Get(k) ? 2 : 1; mesh.AddSegment (seg); // (*testout) << "copy seg " << seg[0] << "-" << seg[1] << endl; #ifdef DEVELOP (*testout) << "copy seg, face = " << seg.si << ": " << " inv = " << inv << ", refinv = " << refedgesinv.Get(k) << mesh.Point(seg[0]) << ", " << mesh.Point(seg[1]) << endl; #endif } } } void EdgeCalculation :: FindClosedSurfaces (double h, Mesh & mesh) { // if there is no special point at a sphere, one has to add a segment pair int nsurf = geometry.GetNSurf(); int layer = 0; Solid * tansol; Array tansurfind; double size = geometry.MaxSize(); int nsol = geometry.GetNTopLevelObjects(); BitArray pointatsurface (nsurf); pointatsurface.Clear(); for (int i = 1; i <= mesh.GetNSeg(); i++) { const Segment & seg = mesh.LineSegment(i); #ifdef DEVELOP (*testout) << seg.surfnr1 << ", " << seg.surfnr2 << ", si = " << seg.si << endl; #endif int classrep = geometry.GetSurfaceClassRepresentant (seg.si); pointatsurface.Set (classrep); } for (int i = 0; i < nsurf; i++) { int classrep = geometry.GetSurfaceClassRepresentant (i); if (!pointatsurface.Test(classrep)) { const Surface * s = geometry.GetSurface(i); Point<3> p1 = s -> GetSurfacePoint(); Vec<3> nv = s -> GetNormalVector (p1); double hloc = min2 (s->LocH (p1, 3, 1, h), mesh.GetH(p1)); Segment seg1; seg1.si = i; seg1.domin = -1; seg1.domout = -1; Segment seg2; seg2.si = i; seg2.domin = -1; seg2.domout = -1; seg1.surfnr1 = i; seg2.surfnr1 = i; seg1.surfnr2 = i; seg2.surfnr2 = i; for (int j = 0; j < nsol; j++) { if (geometry.GetTopLevelObject(j)->GetSurface()) continue; const Solid * sol = geometry.GetTopLevelObject(j)->GetSolid(); sol -> TangentialSolid (p1, tansol, tansurfind, ideps*size); layer = geometry.GetTopLevelObject(j)->GetLayer(); if (tansol) { tansol -> GetSurfaceIndices (tansurfind); if (tansurfind.Size() == 1 && tansurfind.Get(1) == i) { hloc = min2 (hloc, geometry.GetTopLevelObject(j)->GetMaxH()); if (!tansol->VectorIn(p1, nv)) { seg1.domin = j; seg2.domin = j; seg1.tlosurf = j; seg2.tlosurf = j; } else { seg1.domout = j; seg2.domout = j; seg1.tlosurf = j; seg2.tlosurf = j; } // seg.s2 = i; // seg.invs1 = surfaces[i] -> Inverse(); // seg.invs2 = ! (surfaces[i] -> Inverse()); } delete tansol; } } Vec<3> tv = nv.GetNormal (); tv *= (hloc / tv.Length()); Point<3> p2 = p1 + tv; s->Project (p2); if (seg1.domin != -1 || seg1.domout != -1) { mesh.AddPoint (p1, layer, EDGEPOINT); mesh.AddPoint (p2, layer, EDGEPOINT); seg1[0] = mesh.GetNP()-1; seg1[1] = mesh.GetNP(); seg2[1] = mesh.GetNP()-1; seg2[0] = mesh.GetNP(); seg1.geominfo[0].trignum = 1; seg1.geominfo[1].trignum = 1; seg2.geominfo[0].trignum = 1; seg2.geominfo[1].trignum = 1; mesh.AddSegment (seg1); mesh.AddSegment (seg2); PrintMessage (5, "Add line segment to smooth surface"); #ifdef DEVELOP (*testout) << "Add segment at smooth surface " << i; if (i != classrep) (*testout) << ", classrep = " << classrep; (*testout) << ": " << mesh.Point (mesh.GetNP()-1) << " - " << mesh.Point (mesh.GetNP()) << endl; #endif } } } } }