netgen/libsrc/csg/revolution.cpp

1049 lines
28 KiB
C++
Raw Normal View History

2009-01-13 04:40:13 +05:00
#include <mystdlib.h>
#include <core/register_archive.hpp>
2009-01-13 04:40:13 +05:00
#include <linalg.hpp>
#include <csg.hpp>
namespace netgen
{
void RevolutionFace :: Init(void)
{
const LineSeg<2> * line = dynamic_cast<const LineSeg<2>*>(spline);
const SplineSeg3<2> * spline3 = dynamic_cast<const SplineSeg3<2>*>(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_vec.Size(); i++)
{
checklines_normal.Append(new Vec<2>);
(*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) :
2009-04-20 03:15:26 +06:00
isfirst(first), islast(last), spline(&spline_in), p0(p), v_axis(vec), id(id_in)
2009-01-13 04:40:13 +05:00
{
deletable = false;
maxh = spline_in.GetMaxh();
bcname = spline_in.GetBCName();
2009-01-13 04:40:13 +05:00
Init();
}
2019-07-09 13:39:16 +05:00
RevolutionFace :: RevolutionFace(const NgArray<double> & raw_data)
2009-01-13 04:40:13 +05:00
{
deletable = true;
int pos = 0;
2019-07-09 13:39:16 +05:00
NgArray< Point<2> > p(3);
2009-01-13 04:40:13 +05:00
int stype = int(raw_data[pos]); pos++;
for(int i=0; i<stype; i++)
{
p[i](0) = raw_data[pos]; pos++;
p[i](1) = raw_data[pos]; pos++;
}
if(stype == 2)
{
spline = new LineSeg<2>(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<checklines_start.Size(); i++)
{
delete checklines_start[i];
delete checklines_vec[i];
delete checklines_normal[i];
}
if(deletable)
delete spline;
}
void RevolutionFace :: CalcProj(const Point<3> & 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<const RevolutionFace*>(&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());
2009-01-13 04:40:13 +05:00
Point<2> p;
CalcProj(point,p);
2018-03-09 02:31:00 +05:00
/*
double val = spline_coefficient(0)*p(0)*p(0) + spline_coefficient(1)*p(1)*p(1)
2009-01-13 04:40:13 +05:00
+ spline_coefficient(2)*p(0)*p(1) + spline_coefficient(3)*p(0)
+ spline_coefficient(4)*p(1) + spline_coefficient(5);
2018-03-09 02:31:00 +05:00
*/
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;
2009-01-13 04:40:13 +05:00
}
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());
2009-01-13 04:40:13 +05:00
Vec<3> point_minus_p0 = point-p0;
Point<2> p;
CalcProj0(point_minus_p0,p);
/*
2009-01-13 04:40:13 +05:00
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("<<point<<") = " << grad << endl;
}
else
{
grad(0) = dFdxbar*v_axis(0);
grad(1) = dFdxbar*v_axis(1);
grad(2) = dFdxbar*v_axis(2);
//(*testout) << "grad2("<<point<<") = " << grad << endl;
}
*/
Vec<2> pr = p-spline->StartPI();
const double dFdxbar = 2.*spline_coefficient_shifted(0)*pr(0) + spline_coefficient_shifted(2)*pr(1) + spline_coefficient_shifted(3);
if(fabs(p(1)) > 1e-10)
{
const double dFdybar = 2.*spline_coefficient_shifted(1)*pr(1) + spline_coefficient_shifted(2)*pr(0) + spline_coefficient_shifted(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("<<point<<") = " << grad << endl;
}
else
{
grad(0) = dFdxbar*v_axis(0);
grad(1) = dFdxbar*v_axis(1);
grad(2) = dFdxbar*v_axis(2);
//(*testout) << "grad2("<<point<<") = " << grad << endl;
}
2009-01-13 04:40:13 +05:00
}
void RevolutionFace :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const
{
if(spline_coefficient.Size() == 0)
spline->GetCoeff(spline_coefficient);
Vec<3> point_minus_p0 = point-p0;
Point<2> p;
CalcProj0(point_minus_p0,p);
if(fabs(p(1)) > 1e-10)
{
const double dFdybar = 2.*spline_coefficient(1)*p(1) + spline_coefficient(2)*p(0) + spline_coefficient(4);
const double aux = -pow(p(1),-3);
const double aux0 = point_minus_p0(0) - v_axis(0)*p(0);
const double aux1 = point_minus_p0(1) - v_axis(1)*p(0);
const double aux2 = point_minus_p0(2) - v_axis(2)*p(0);
const double dybardx = aux0/p(1);
const double dybardy = aux1/p(1);
const double dybardz = aux2/p(1);
const double dybardxx = aux*aux0*aux0 + (1.-v_axis(0)*v_axis(0))/p(1);
const double dybardyy = aux*aux1*aux1 + (1.-v_axis(1)*v_axis(1))/p(1);
const double dybardzz = aux*aux2*aux2 + (1.-v_axis(2)*v_axis(2))/p(1);
const double dybardxy = aux*aux0*aux1 - v_axis(0)*v_axis(1)/p(1);
const double dybardxz = aux*aux0*aux2 - v_axis(0)*v_axis(2)/p(1);
const double dybardyz = aux*aux1*aux2 - v_axis(1)*v_axis(2)/p(1);
hesse(0,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(0) + 2.*spline_coefficient(2)*v_axis(0)*dybardx + 2.*spline_coefficient(1)*dybardx*dybardx
+ dFdybar*dybardxx;
hesse(1,1) = 2.*spline_coefficient(0)*v_axis(1)*v_axis(1) + 2.*spline_coefficient(2)*v_axis(1)*dybardy + 2.*spline_coefficient(1)*dybardy*dybardy
+ dFdybar*dybardyy;
hesse(2,2) = 2.*spline_coefficient(0)*v_axis(2)*v_axis(2) + 2.*spline_coefficient(2)*v_axis(2)*dybardz + 2.*spline_coefficient(1)*dybardz*dybardz
+ dFdybar*dybardzz;
hesse(0,1) = hesse(1,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(1) + spline_coefficient(2)*v_axis(0)*dybardy + spline_coefficient(2)*dybardx*v_axis(1)
+ 2.*spline_coefficient(2)*dybardx*dybardy + dFdybar*dybardxy;
hesse(0,2) = hesse(2,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(2) + spline_coefficient(2)*v_axis(0)*dybardz + spline_coefficient(2)*dybardx*v_axis(2)
+ 2.*spline_coefficient(2)*dybardx*dybardz + dFdybar*dybardxz;
hesse(1,2) = hesse(2,1) = 2.*spline_coefficient(0)*v_axis(1)*v_axis(2) + spline_coefficient(2)*v_axis(1)*dybardz + spline_coefficient(2)*dybardy*v_axis(2)
+ 2.*spline_coefficient(2)*dybardy*dybardz + dFdybar*dybardyz;
//(*testout) << "hesse1: " << hesse <<endl;
}
else if (fabs(spline_coefficient(2)) + fabs(spline_coefficient(4)) < 1.e-9 &&
fabs(spline_coefficient(0)) > 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 <<endl;
}
else if (fabs(spline_coefficient(1)) + fabs(spline_coefficient(3)) + fabs(spline_coefficient(4)) + fabs(spline_coefficient(5)) < 1.e-9) // line
{
hesse = 0;
//(*testout) << "hesse3: " << hesse <<endl;
}
else
{
2019-03-20 19:12:54 +05:00
hesse = 0;
2009-01-13 04:40:13 +05:00
(*testout) << "hesse4: " << hesse <<endl;
}
}
double RevolutionFace ::HesseNorm () const
{
if (fabs(spline_coefficient(1)) + fabs(spline_coefficient(3)) + fabs(spline_coefficient(4)) + fabs(spline_coefficient(5)) < 1.e-9) // line
return 0;
if (fabs(spline_coefficient(2)) + fabs(spline_coefficient(4)) < 1.e-9 &&
fabs(spline_coefficient(0)) > 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();
2019-07-09 13:39:16 +05:00
NgArray < Point<2> > checkpoints;
2009-01-13 04:40:13 +05:00
const SplineSeg3<2> * ss3 = dynamic_cast<const SplineSeg3<2> *>(spline);
const LineSeg<2> * ls = dynamic_cast<const LineSeg<2> *>(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<checkpoints.Size(); i+=2)
{
Vec<2> 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:
2019-07-09 13:39:16 +05:00
NgArray<double> testt;
2009-01-13 04:40:13 +05:00
if(!isfirst)
testt.Append(0);
if(!islast)
testt.Append(1);
const SplineSegment3 * s3 = dynamic_cast<const SplineSegment3 *>(&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<testt.Size(); i++)
{
double thisy = fabs(spline.GetPoint(testt[i])(1));
if(thisy < miny)
miny = thisy;
}
return max2(splinecurvature,1./miny);
*/
}
void RevolutionFace :: Project (Point<3> & 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++)
2009-01-13 04:40:13 +05:00
{
Point<2> sp = spline->GetPoint(double(i)/double(n));
for(int j=0; j<=n; j++)
2009-01-13 04:40:13 +05:00
{
double phi = 2.*M_PI*double(j)/double(n);
2009-01-13 04:40:13 +05:00
Point<3> p = p0 + sp(0)*v_axis + sp(1)*cos(phi)*v1 + sp(1)*sin(phi)*v2;
2009-01-13 04:40:13 +05:00
tas.AddPoint(p);
}
}
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
2009-01-13 04:40:13 +05:00
{
int pi = (n+1)*i+j;
tas.AddTriangle( TATriangle (id, pi,pi+1,pi+n+1));
tas.AddTriangle( TATriangle (id, pi+1,pi+n+1,pi+n+2));
}
}
bool RevolutionFace :: BoxIntersectsFace(const Box<3> & 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<const LineSegment*>(&spline);
const SplineSegment3 * spline3 = dynamic_cast<const SplineSegment3*>(&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<checklines_start.Size(); i++)
{
Vec<2> 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
2009-01-13 04:40:13 +05:00
{
Point<2> p2d;
CalcProj(p,p2d);
if (!spline -> InConvexHull(p2d, eps)) return false;
/*
2009-01-13 04:40:13 +05:00
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);
/*
2009-01-13 04:40:13 +05:00
if(val > eps)
return IS_OUTSIDE;
if(val < -eps)
return IS_INSIDE;
return DOES_INTERSECT;
*/
2009-01-13 04:40:13 +05:00
}
2019-07-09 13:39:16 +05:00
void RevolutionFace :: GetRawData(NgArray<double> & data) const
2009-01-13 04:40:13 +05:00
{
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<SplineGeometry<2>> spline_in) :
p0(p0_in), p1(p1_in), splinegeo(spline_in)
2009-01-13 04:40:13 +05:00
{
auto nsplines = spline_in->GetNSplines();
2009-01-13 04:40:13 +05:00
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.)
2009-01-13 04:40:13 +05:00
type = 2;
else if (Dist(spline_in->GetSpline(0).StartPI(),
spline_in->GetSpline(nsplines-1).EndPI()) < 1e-7)
2009-01-13 04:40:13 +05:00
type = 1;
else
cerr << "Surface of revolution cannot be constructed" << endl;
for(int i=0; i<spline_in->GetNSplines(); i++)
2009-01-13 04:40:13 +05:00
{
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);
2009-01-13 04:40:13 +05:00
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));
}
}
2009-01-13 04:40:13 +05:00
}
Revolution::~Revolution()
{
for(int i=0; i<faces.Size(); i++)
delete faces[i];
}
INSOLID_TYPE Revolution :: BoxInSolid (const BoxSphere<3> & box) const
{
for(int i=0; i<faces.Size(); i++)
if(faces[i]->BoxIntersectsFace(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) && i<faces.Size(); i++)
{
bool thisintersects;
bool thisuncertain;
thisintersects = faces[i]->BoxIntersectsFace(box2d,thisuncertain);
intersection = intersection || thisintersects;
if(thisintersects && !thisuncertain)
uncertain = false;
}
if(intersection)
{
if(!uncertain)
return DOES_INTERSECT;
else
{
2019-07-09 13:39:16 +05:00
NgArray < Point<3> > pext(2);
2009-01-13 04:40:13 +05:00
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;
2009-01-13 04:40:13 +05:00
const double a = randomy;
const double b = -randomx;
const double c = -a*p2d(0)-b*p2d(1);
2019-07-09 13:39:16 +05:00
NgArray < Point<2> > points;
2009-01-13 04:40:13 +05:00
//(*testout) << "face intersections at: " << endl;
for(int i=0; i<faces.Size(); i++)
{
faces[i]->GetSpline().LineIntersections(a,b,c,points,eps);
for(int j=0; j<points.Size(); j++)
{
double t = (points[j](0)-p2d(0))/randomx;
//(*testout) << t << endl;
if ( t < -eps )
intersections_before++;
else if ( t > eps )
intersections_after++;
else
{
intersecting_face = i;
return DOES_INTERSECT;
}
}
}
2019-03-20 19:12:54 +05:00
if(intersections_after % 2 == 0)
2009-01-13 04:40:13 +05:00
return IS_OUTSIDE;
else
return IS_INSIDE;
}
void Revolution :: GetTangentialSurfaceIndices (const Point<3> & p,
2019-07-09 13:39:16 +05:00
NgArray<int> & 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));
}
2009-01-13 04:40:13 +05:00
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;
}
2019-07-09 13:39:16 +05:00
NgArray<int> intersecting_faces;
2009-01-13 04:40:13 +05:00
for(int i=0; i<faces.Size(); i++)
if(faces[i]->PointInFace(p,eps)) // == DOES_INTERSECT)
2009-01-13 04:40:13 +05:00
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<const SplineSeg3<2> *>(&faces[intersecting_faces[0]]->GetSpline());
const LineSeg<2> * linesegment =
dynamic_cast<const LineSeg<2> *>(&faces[intersecting_faces[0]]->GetSpline());
2014-08-15 21:19:10 +06:00
Vec<2> t1(0),t2(0);
2009-01-13 04:40:13 +05:00
if(linesegment)
t1 = linesegment->StartPI() - linesegment->EndPI();
else if(splinesegment3)
t1 = splinesegment3->TangentPoint() - splinesegment3->EndPI();
linesegment =
dynamic_cast<const LineSeg<2> *>(&faces[intersecting_faces[1]]->GetSpline());
splinesegment3 =
dynamic_cast<const SplineSeg3<2> *>(&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;
2010-01-14 21:56:13 +05:00
return VecInSolid(p,v1+0.01*v2,eps);
2009-01-13 04:40:13 +05:00
}
void Revolution ::
GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,
NgArray<int> & 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));
}
}
}
2009-01-13 04:40:13 +05:00
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; i<faces.Size(); i++)
surfaceactive[i] = (faces[i]->BoxIntersectsFace(box));
//surfaceactive[i] = (faces[i]->BoxIntersectsFace(box,dummy));
}
void Revolution :: UnReduce ()
{
for(int i=0; i<faces.Size(); i++)
surfaceactive[i] = true;
}
2018-12-06 21:53:44 +05:00
RegisterClassForArchive<RevolutionFace, Surface> regrevf;
RegisterClassForArchive<Revolution, Primitive> regrev;
2009-01-13 04:40:13 +05:00
}