mirror of
https://github.com/NGSolve/netgen.git
synced 2024-11-12 00:59:16 +05:00
1048 lines
28 KiB
C++
1048 lines
28 KiB
C++
#include <mystdlib.h>
|
|
|
|
#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) :
|
|
isfirst(first), islast(last), spline(&spline_in), p0(p), v_axis(vec), id(id_in)
|
|
{
|
|
deletable = false;
|
|
maxh = spline_in.GetMaxh();
|
|
bcname = spline_in.GetBCName();
|
|
Init();
|
|
}
|
|
|
|
|
|
RevolutionFace :: RevolutionFace(const NgArray<double> & raw_data)
|
|
{
|
|
deletable = true;
|
|
|
|
int pos = 0;
|
|
|
|
NgArray< Point<2> > p(3);
|
|
|
|
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());
|
|
|
|
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("<<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;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
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
|
|
{
|
|
hesse = 0;
|
|
(*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();
|
|
|
|
NgArray < Point<2> > checkpoints;
|
|
|
|
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:
|
|
NgArray<double> testt;
|
|
|
|
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++)
|
|
{
|
|
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<n; i++)
|
|
for(int j=0; j<n; j++)
|
|
{
|
|
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
|
|
{
|
|
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<double> & 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<SplineGeometry<2>> 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; i<spline_in->GetNSplines(); 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<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
|
|
{
|
|
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; 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(intersections_after % 2 == 0)
|
|
return IS_OUTSIDE;
|
|
else
|
|
return IS_INSIDE;
|
|
}
|
|
|
|
void Revolution :: GetTangentialSurfaceIndices (const Point<3> & p,
|
|
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));
|
|
}
|
|
|
|
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<int> intersecting_faces;
|
|
|
|
for(int i=0; i<faces.Size(); i++)
|
|
if(faces[i]->PointInFace(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<const SplineSeg3<2> *>(&faces[intersecting_faces[0]]->GetSpline());
|
|
const LineSeg<2> * linesegment =
|
|
dynamic_cast<const LineSeg<2> *>(&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<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;
|
|
|
|
return VecInSolid(p,v1+0.01*v2,eps);
|
|
}
|
|
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
RegisterClassForArchive<RevolutionFace, Surface> regrevf;
|
|
RegisterClassForArchive<Revolution, Primitive> regrev;
|
|
}
|