#include #include #include namespace netgen { void RevolutionFace :: Init(void) { const LineSeg<2> * line = dynamic_cast*>(spline); const SplineSeg3<2> * spline3 = dynamic_cast*>(spline); if(line) { checklines_start.Append(new Point<2>(line->StartPI())); checklines_vec.Append(new Vec<2>(line->EndPI() - line->StartPI())); (*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!! } else if (spline3) { checklines_start.Append(new Point<2>(spline3->EndPI())); checklines_start.Append(new Point<2>(spline3->TangentPoint())); checklines_start.Append(new Point<2>(spline3->StartPI())); checklines_vec.Append(new Vec<2>(spline3->StartPI() - spline3->EndPI())); (*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!! checklines_vec.Append(new Vec<2>(spline3->EndPI() - spline3->TangentPoint())); (*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!! checklines_vec.Append(new Vec<2>(spline3->TangentPoint() - spline3->StartPI())); (*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!! } for(int i=0; i); (*checklines_normal.Last())(0) = - (*checklines_vec[i])(1); (*checklines_normal.Last())(1) = (*checklines_vec[i])(0); checklines_normal.Last()->Normalize(); } } RevolutionFace :: RevolutionFace(const SplineSeg<2> & spline_in, const Point<3> & p, const Vec<3> & vec, bool first, bool last, const int id_in) : isfirst(first), islast(last), spline(&spline_in), p0(p), v_axis(vec), id(id_in) { deletable = false; Init(); } RevolutionFace :: RevolutionFace(const NgArray & raw_data) { deletable = true; int pos = 0; NgArray< Point<2> > p(3); int stype = int(raw_data[pos]); pos++; for(int i=0; i(GeomPoint<2>(p[0],1), GeomPoint<2>(p[1],1)); //(*testout) << "appending LineSeg<2> " << p[0] // << " to " << p[1] << endl; } else if(stype == 3) { spline = new SplineSeg3<2>(GeomPoint<2>(p[0],1), GeomPoint<2>(p[1],1), GeomPoint<2>(p[2],1)); //(*testout) << "appending SplineSeg<3> " // << p[0] << " -- " << p[1] << " -- " << p[2] << endl; } for(int i=0; i<3; i++) { p0(i) = raw_data[pos]; pos++; } for(int i=0; i<3; i++) { v_axis(i) = raw_data[pos]; pos++; } isfirst = (raw_data[pos] > 0.9); pos++; islast = (raw_data[pos] < 0.1); pos++; } RevolutionFace :: ~RevolutionFace() { for(int i=0; i & point3d, Point<2> & point2d, const Vec<3> & vector3d, Vec<2> & vector2d) const { Vec<3> pmp0 = point3d-p0; CalcProj0(pmp0,point2d); Vec<3> y=pmp0-point2d(0)*v_axis; y.Normalize(); vector2d(0) = vector3d*v_axis; vector2d(1) = vector3d*y; } void RevolutionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d) const { Vec<3> pmp0 = point3d-p0; CalcProj0(pmp0,point2d); } void RevolutionFace :: CalcProj0(const Vec<3> & point3d_minus_p0, Point<2> & point2d) const { point2d(0) = point3d_minus_p0 * v_axis; point2d(1) = sqrt( point3d_minus_p0 * point3d_minus_p0 - point2d(0)*point2d(0) ); } int RevolutionFace ::IsIdentic (const Surface & s2, int & inv, double eps) const { const RevolutionFace * rev2 = dynamic_cast(&s2); if(!rev2) return 0; if(rev2 == this) return 1; return 0; } double RevolutionFace :: CalcFunctionValue (const Point<3> & point) const { if(spline_coefficient.Size() == 0) spline->GetCoeff(spline_coefficient); if(spline_coefficient_shifted.Size() == 0) spline->GetCoeff(spline_coefficient_shifted, spline->StartPI()); Point<2> p; CalcProj(point,p); /* double val = spline_coefficient(0)*p(0)*p(0) + spline_coefficient(1)*p(1)*p(1) + spline_coefficient(2)*p(0)*p(1) + spline_coefficient(3)*p(0) + spline_coefficient(4)*p(1) + spline_coefficient(5); */ Vec<2> pr = p-spline->StartPI(); // cout << "spline_coefficinet = " << spline_coefficient << endl; // cout << "shifted = " << spline_coefficient_shifted << endl; double val2 = spline_coefficient_shifted(0)*pr(0)*pr(0) + spline_coefficient_shifted(1)*pr(1)*pr(1) + spline_coefficient_shifted(2)*pr(0)*pr(1) + spline_coefficient_shifted(3)*pr(0) + spline_coefficient_shifted(4)*pr(1) + spline_coefficient_shifted(5); // cout << "val = " << val << " =?= " << val2 << endl; return val2; } void RevolutionFace :: CalcGradient (const Point<3> & point, Vec<3> & grad) const { if(spline_coefficient.Size() == 0) spline->GetCoeff(spline_coefficient); if(spline_coefficient_shifted.Size() == 0) spline->GetCoeff(spline_coefficient_shifted, spline->StartPI()); Vec<3> point_minus_p0 = point-p0; Point<2> p; CalcProj0(point_minus_p0,p); /* const double dFdxbar = 2.*spline_coefficient(0)*p(0) + spline_coefficient(2)*p(1) + spline_coefficient(3); if(fabs(p(1)) > 1e-10) { const double dFdybar = 2.*spline_coefficient(1)*p(1) + spline_coefficient(2)*p(0) + spline_coefficient(4); grad(0) = dFdxbar*v_axis(0) + dFdybar * ( point_minus_p0(0)-v_axis(0)*p(0) )/p(1); grad(1) = dFdxbar*v_axis(1) + dFdybar * ( point_minus_p0(1)-v_axis(1)*p(0) )/p(1); grad(2) = dFdxbar*v_axis(2) + dFdybar * ( point_minus_p0(2)-v_axis(2)*p(0) )/p(1); //(*testout) << "grad1("< 1e-10) { double aux = spline_coefficient(0)-spline_coefficient(1); hesse(0,0) = aux*v_axis(0)*v_axis(0) + spline_coefficient(1); hesse(0,0) = aux*v_axis(1)*v_axis(1) + spline_coefficient(1); hesse(0,0) = aux*v_axis(2)*v_axis(2) + spline_coefficient(1); hesse(0,1) = hesse(1,0) = aux*v_axis(0)*v_axis(1); hesse(0,2) = hesse(2,0) = aux*v_axis(0)*v_axis(2); hesse(1,2) = hesse(2,1) = aux*v_axis(1)*v_axis(2); //(*testout) << "hesse2: " << hesse < 1e-10) return 2.*max2(fabs(spline_coefficient(0)),fabs(spline_coefficient(1))); double alpha = fabs(spline_coefficient(2)*(spline->StartPI()(0)-spline->EndPI()(0))) / max2(fabs(spline->StartPI()(1)),fabs(spline->EndPI()(1))); return max2(2.*fabs(spline_coefficient(0))+sqrt(2.)*fabs(spline_coefficient(2)), 2.*fabs(spline_coefficient(1))+spline_coefficient(2)+1.5*alpha); } double RevolutionFace :: MaxCurvature() const { double retval = spline->MaxCurvature(); NgArray < Point<2> > checkpoints; const SplineSeg3<2> * ss3 = dynamic_cast *>(spline); const LineSeg<2> * ls = dynamic_cast *>(spline); if(ss3) { checkpoints.Append(ss3->StartPI()); checkpoints.Append(ss3->TangentPoint()); checkpoints.Append(ss3->TangentPoint()); checkpoints.Append(ss3->EndPI()); } else if(ls) { checkpoints.Append(ls->StartPI()); checkpoints.Append(ls->EndPI()); } for(int i=0; i v = checkpoints[i+1]-checkpoints[i]; Vec<2> n(v(1),-v(0)); n.Normalize(); //if(ss3) // (*testout) << "n " << n << endl; if(fabs(n(1)) < 1e-15) continue; double t1 = -checkpoints[i](1)/n(1); double t2 = -checkpoints[i+1](1)/n(1); double c1 = (t1 > 0) ? (1./t1) : -1; double c2 = (t2 > 0) ? (1./t2) : -1; //if(ss3) // (*testout) << "t1 " << t1 << " t2 " << t2 << " c1 " << c1 << " c2 " << c2 << endl; if(c1 > retval) retval = c1; if(c2 > retval) retval = c2; } //if(ss3) // (*testout) << "curvature " << retval << endl; return retval; /* // find smallest y value of spline: NgArray testt; if(!isfirst) testt.Append(0); if(!islast) testt.Append(1); const SplineSegment3 * s3 = dynamic_cast(&spline); if(s3) { double denom = (2.-sqrt(2.))*(s3->EndPI()(1) - s3->StartPI()(1)); if(fabs(denom) < 1e-20) testt.Append(0.5); else { double sD = sqrt(pow(s3->TangentPoint()(1) - s3->StartPI()(1),2)+ pow(s3->TangentPoint()(1) - s3->EndPI()(1),2)); testt.Append((s3->StartPI()(1)*(sqrt(2.)-1.) - sqrt(2.)*s3->TangentPoint()(1) + s3->EndPI()(1) + sD)/denom); testt.Append((s3->StartPI()(1)*(sqrt(2.)-1.) - sqrt(2.)*s3->TangentPoint()(1) + s3->EndPI()(1) - sD)/denom); } } double miny = fabs(spline.GetPoint(testt[0])(1)); for(int i=1; i & p) const { Point<2> p2d; CalcProj(p,p2d); const Vec<3> y = (p-p0)-p2d(0)*v_axis; const double yl = y.Length(); double dummy; spline->Project(p2d,p2d,dummy); p = p0 + p2d(0)*v_axis; if(yl > 1e-20*Dist(spline->StartPI(),spline->EndPI())) p+= (p2d(1)/yl)*y; } Point<3> RevolutionFace :: GetSurfacePoint () const { Vec<3> random_vec(0.760320,-0.241175,0.60311534); Vec<3> n = Cross(v_axis,random_vec); n.Normalize(); Point<2> sp = spline->GetPoint(0.5); Point<3> retval = p0 + sp(0)*v_axis + sp(1)*n; return retval; } void RevolutionFace :: Print (ostream & str) const { if(spline_coefficient.Size() == 0) spline->GetCoeff(spline_coefficient); str << p0(0) << " " << p0(1) << " " << p0(2) << " " << v_axis(0) << " " << v_axis(1) << " " << v_axis(2) << " "; for(int i=0; i<6; i++) str << spline_coefficient(i) << " "; str << endl; } void RevolutionFace :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & boundingbox, double facets) const { Vec<3> random_vec(0.760320,-0.241175,0.60311534); Vec<3> v1 = Cross(v_axis,random_vec); v1.Normalize(); Vec<3> v2 = Cross(v1,v_axis); v2.Normalize(); int n = int(2.*facets) + 1; for(int i=0; i<=n; i++) { Point<2> sp = spline->GetPoint(double(i)/double(n)); for(int j=0; j<=n; j++) { double phi = 2.*M_PI*double(j)/double(n); Point<3> p = p0 + sp(0)*v_axis + sp(1)*cos(phi)*v1 + sp(1)*sin(phi)*v2; tas.AddPoint(p); } } for(int i=0; i & box) const { Point<3> center = box.Center(); Project(center); return (Dist(box.Center(),center) < 0.5*box.Diam()); } /* bool RevolutionFace :: BoxIntersectsFace (const BoxSphere<3> & box, bool & uncertain) const { Point<2> c,pmin,pmax; CalcProj(box.Center(),c); double aux = box.Diam()/sqrt(8.); pmin(0) = c(0)-aux; pmin(1) = c(1)-aux; pmax(0) = c(0)+aux; pmax(1) = c(1)+aux; BoxSphere<2> box2d(pmin,pmax); return BoxIntersectsFace(box2d, uncertain); } bool RevolutionFace :: BoxIntersectsFace (const BoxSphere<2> & box, bool & uncertain) const { const LineSegment * line = dynamic_cast(&spline); const SplineSegment3 * spline3 = dynamic_cast(&spline); bool always_right = true, always_left = true; bool retval = false; bool thisint; bool intdirect = false; bool inttangent = false; uncertain = false; if(line) inttangent = true; for(int i=0; i b = box.Center()- (*checklines_start[i]); double d; double checkdist = b * (*checklines_vec[i]); double ncomp = b * (*checklines_normal[i]); if(checkdist < 0) d = b.Length(); else if (checkdist > 1) { if(spline3) d = Dist(box.Center(),*checklines_start[(i+1)%3]); else d = Dist(box.Center(),(*checklines_start[i]) + pow(checklines_vec[i]->Length(),2)*(*checklines_vec[i])); } else d = fabs(ncomp); thisint = (box.Diam() >= 2.*d); retval = retval || thisint; if(thisint) { if(i==0) intdirect = true; else inttangent = true; } if(ncomp > 0) always_right = false; else if(ncomp < 0) always_left = false; } if(retval && !(intdirect && inttangent)) uncertain = true; if(!retval && spline3 && (always_right || always_left)) { retval = true; uncertain = true; } return retval; } */ /* INSOLID_TYPE */ bool RevolutionFace :: PointInFace (const Point<3> & p, const double eps) const { Point<2> p2d; CalcProj(p,p2d); if (!spline -> InConvexHull(p2d, eps)) return false; /* double val = spline_coefficient(0)*p2d(0)*p2d(0) + spline_coefficient(1)*p2d(1)*p2d(1) + spline_coefficient(2)*p2d(0)*p2d(1) + spline_coefficient(3)*p2d(0) + spline_coefficient(4)*p2d(1) + spline_coefficient(5); */ Vec<2> pr = p2d - spline->StartPI(); double val = spline_coefficient_shifted(0)*pr(0)*pr(0) + spline_coefficient_shifted(1)*pr(1)*pr(1) + spline_coefficient_shifted(2)*pr(0)*pr(1) + spline_coefficient_shifted(3)*pr(0) + spline_coefficient_shifted(4)*pr(1) + spline_coefficient_shifted(5); return (fabs(val) < eps); /* if(val > eps) return IS_OUTSIDE; if(val < -eps) return IS_INSIDE; return DOES_INTERSECT; */ } void RevolutionFace :: GetRawData(NgArray & data) const { data.DeleteAll(); spline->GetRawData(data); for(int i=0; i<3; i++) data.Append(p0(i)); for(int i=0; i<3; i++) data.Append(v_axis(i)); data.Append((isfirst) ? 1. : 0.); data.Append((islast) ? 1. : 0.); } Revolution :: Revolution(const Point<3> & p0_in, const Point<3> & p1_in, shared_ptr> spline_in) : p0(p0_in), p1(p1_in), splinegeo(spline_in) { auto nsplines = spline_in->GetNSplines(); surfaceactive.SetSize(0); surfaceids.SetSize(0); v_axis = p1-p0; v_axis.Normalize(); if(spline_in->GetSpline(0).StartPI()(1) <= 0. && spline_in->GetSpline(nsplines-1).EndPI()(1) <= 0.) type = 2; else if (Dist(spline_in->GetSpline(0).StartPI(), spline_in->GetSpline(nsplines-1).EndPI()) < 1e-7) type = 1; else cerr << "Surface of revolution cannot be constructed" << endl; for(int i=0; iGetNSplines(); i++) { faces.Append(new RevolutionFace (spline_in->GetSpline(i), p0,v_axis, type==2 && i==0, type==2 && i==spline_in->GetNSplines()-1)); surfaceactive.Append(1); surfaceids.Append(0); } // checking if (type == 2) { auto t0 = spline_in->GetSpline(0).GetTangent(0); cout << "tstart (must be vertically): " << t0 << endl; auto tn = spline_in->GetSpline(nsplines-1).GetTangent(1); cout << "tend (must be vertically): " << tn << endl; for (int i = 0; i < nsplines-1; i++) { auto ta = spline_in->GetSpline(i).GetTangent(1); auto tb = spline_in->GetSpline(i+1).GetTangent(0); cout << "sin (must not be 0) = " << abs(ta(0)*tb(1)-ta(1)*tb(0)) / (Abs(ta)*Abs(tb)); } } } Revolution::~Revolution() { for(int i=0; i & box) const { for(int i=0; iBoxIntersectsFace(box)) return DOES_INTERSECT; return PointInSolid(box.Center(),0); /* Point<2> c,pmin,pmax; faces[0]->CalcProj(box.Center(),c); double aux = box.Diam()/sqrt(8.); pmin(0) = c(0)-aux; pmin(1) = c(1)-aux; pmax(0) = c(0)+aux; pmax(1) = c(1)+aux; BoxSphere<2> box2d(pmin,pmax); bool intersection = false; bool uncertain = true; for(int i=0; !(intersection && !uncertain) && iBoxIntersectsFace(box2d,thisuncertain); intersection = intersection || thisintersects; if(thisintersects && !thisuncertain) uncertain = false; } if(intersection) { if(!uncertain) return DOES_INTERSECT; else { NgArray < Point<3> > pext(2); Point<3> p; pext[0] = box.PMin(); pext[1] = box.PMax(); INSOLID_TYPE position; bool firsttime = true; for(int i=0; i<2; i++) for(int j=0; j<2; j++) for(int k=0; k<2; k++) { p(0) = pext[i](0); p(1) = pext[j](1); p(2) = pext[k](2); INSOLID_TYPE ppos = PointInSolid(p,0); if(ppos == DOES_INTERSECT) return DOES_INTERSECT; if(firsttime) { firsttime = false; position = ppos; } if(position != ppos) return DOES_INTERSECT; } return position; } } return PointInSolid(box.Center(),0); */ } INSOLID_TYPE Revolution :: PointInSolid (const Point<3> & p, double eps) const { Point<2> p2d; faces[0]->CalcProj(p,p2d); int intersections_before(0), intersections_after(0); double randomx = 7.42357; double randomy = 1.814756; double randomlen = sqrt(randomx*randomx+randomy*randomy); randomx *= 1./randomlen; randomy *= 1./randomlen; const double a = randomy; const double b = -randomx; const double c = -a*p2d(0)-b*p2d(1); NgArray < Point<2> > points; //(*testout) << "face intersections at: " << endl; for(int i=0; iGetSpline().LineIntersections(a,b,c,points,eps); for(int j=0; j eps ) intersections_after++; else { intersecting_face = i; return DOES_INTERSECT; } } } if(intersections_after % 2 == 0) return IS_OUTSIDE; else return IS_INSIDE; } void Revolution :: GetTangentialSurfaceIndices (const Point<3> & p, NgArray & surfind, double eps) const { for (int j = 0; j < faces.Size(); j++) if (faces[j] -> PointInFace(p, eps)) if (!surfind.Contains (GetSurfaceId(j))) surfind.Append (GetSurfaceId(j)); } INSOLID_TYPE Revolution :: VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const { INSOLID_TYPE pInSolid = PointInSolid(p,eps); if(pInSolid != DOES_INTERSECT) { //(*testout) << "pInSolid" << endl; return pInSolid; } NgArray intersecting_faces; for(int i=0; iPointInFace(p,eps)) // == DOES_INTERSECT) intersecting_faces.Append(i); Vec<3> hv; if(intersecting_faces.Size() == 1) { faces[intersecting_faces[0]]->CalcGradient(p,hv); double hv1; hv1 = v * hv; if (hv1 <= -eps) return IS_INSIDE; if (hv1 >= eps) return IS_OUTSIDE; return DOES_INTERSECT; } else if(intersecting_faces.Size() == 2) { Point<2> p2d; Vec<2> v2d; faces[intersecting_faces[0]]->CalcProj(p,p2d,v,v2d); if(Dist(faces[intersecting_faces[0]]->GetSpline().StartPI(),p2d) < Dist(faces[intersecting_faces[0]]->GetSpline().EndPI(),p2d)) { int aux = intersecting_faces[0]; intersecting_faces[0] = intersecting_faces[1]; intersecting_faces[1] = aux; } const SplineSeg3<2> * splinesegment3 = dynamic_cast *>(&faces[intersecting_faces[0]]->GetSpline()); const LineSeg<2> * linesegment = dynamic_cast *>(&faces[intersecting_faces[0]]->GetSpline()); Vec<2> t1(0),t2(0); if(linesegment) t1 = linesegment->StartPI() - linesegment->EndPI(); else if(splinesegment3) t1 = splinesegment3->TangentPoint() - splinesegment3->EndPI(); linesegment = dynamic_cast *>(&faces[intersecting_faces[1]]->GetSpline()); splinesegment3 = dynamic_cast *>(&faces[intersecting_faces[1]]->GetSpline()); if(linesegment) t2 = linesegment->EndPI() - linesegment->StartPI(); else if(splinesegment3) t2 = splinesegment3->TangentPoint() - splinesegment3->StartPI(); t1.Normalize(); t2.Normalize(); double d1 = v2d*t1; double d2 = v2d*t2; Vec<2> n; if(d1 > d2) { n(0) = t1(1); n(1) = -t1(0); } else { n(0) = -t2(1); n(1) = t2(0); } double d = v2d*n; if(d > eps) return IS_OUTSIDE; else if (d < -eps) return IS_INSIDE; else return DOES_INTERSECT; } else { cerr << "Jo gibt's denn des?" << endl; } return DOES_INTERSECT; } INSOLID_TYPE Revolution :: VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { INSOLID_TYPE ret1 = VecInSolid(p,v1,eps); if(ret1 != DOES_INTERSECT) return ret1; return VecInSolid(p,v1+0.01*v2,eps); } void Revolution :: GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, NgArray & surfind, double eps) const { *testout << "tangentialvecsurfind2, p = " << p << endl; for (int i = 0; i < faces.Size(); i++) if (faces[i]->PointInFace (p, eps)) { *testout << "check face " << i << endl; Point<2> p2d; Vec<2> v12d; faces[i]->CalcProj(p,p2d,v1,v12d); *testout << "v12d = " << v12d << endl; auto & spline = faces[i]->GetSpline(); if (Dist2 (spline.StartPI(), p2d) < sqr(eps)) { *testout << "start pi" << endl; Vec<2> tang = spline.GetTangent(0); double ip = tang*v12d; *testout << "ip = " << ip << endl; if (ip > eps) surfind.Append(GetSurfaceId(i)); else if (ip > -eps) { Vec<2> v22d; faces[i]->CalcProj(p,p2d,v2,v22d); double ip2 = tang*v22d; *testout << "ip2 = " << ip2 << endl; if (ip2 > -eps) surfind.Append(GetSurfaceId(i)); } } else if (Dist2 (faces[i]->GetSpline().EndPI(), p2d) < sqr(eps)) { *testout << "end pi" << endl; Vec<2> tang = spline.GetTangent(1); double ip = tang*v12d; *testout << "ip = " << ip << endl; if (ip < -eps) surfind.Append(GetSurfaceId(i)); else if (ip < eps) { Vec<2> v22d; faces[i]->CalcProj(p,p2d,v2,v22d); double ip2 = tang*v22d; *testout << "ip2 = " << ip2 << endl; if (ip2 < eps) surfind.Append(GetSurfaceId(i)); } } else { *testout << "inner point" << endl; surfind.Append(GetSurfaceId(i)); } } } int Revolution :: GetNSurfaces() const { return faces.Size(); } Surface & Revolution :: GetSurface (int i) { return *faces[i]; } const Surface & Revolution :: GetSurface (int i) const { return *faces[i]; } void Revolution :: Reduce (const BoxSphere<3> & box) { //bool dummy; for(int i=0; iBoxIntersectsFace(box)); //surfaceactive[i] = (faces[i]->BoxIntersectsFace(box,dummy)); } void Revolution :: UnReduce () { for(int i=0; i regrevf; RegisterClassForArchive regrev; }