netgen/libsrc/occ/occmeshsurf.cpp
Joachim Schoeberl a8e41734cf no warnings
2023-07-31 00:13:56 +02:00

596 lines
14 KiB
C++

#ifdef OCCGEOMETRY
#include <mystdlib.h>
#include <meshing.hpp>
#include "occgeom.hpp"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#include <GeomLProp_SLProps.hxx>
#include <ShapeAnalysis_Surface.hxx>
#pragma clang diagnostic pop
#include "occmeshsurf.hpp"
namespace netgen
{
bool glob_testout(false);
void OCCSurface :: GetNormalVector (const Point<3> & p,
const PointGeomInfo & geominfo,
Vec<3> & n) const
{
GeomLProp_SLProps lprop(occface,geominfo.u,geominfo.v,1,1e-8);
if (lprop.IsNormalDefined())
{
n = occ2ng(lprop.Normal());
}
else
{
gp_Pnt pnt;
gp_Vec du, dv;
double setu=geominfo.u,setv=geominfo.v;
double ustep = 0.01*(umax-umin);
double vstep = 0.01*(vmax-vmin);
n=0;
while(setu < umax && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5))
setu += ustep;
if(setu < umax)
{
lprop.SetParameters(setu,setv);
/*
n(0)+=lprop.Normal().X();
n(1)+=lprop.Normal().Y();
n(2)+=lprop.Normal().Z();
*/
n += occ2ng(lprop.Normal());
}
setu = geominfo.u;
while(setu > umin && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5))
setu -= ustep;
if(setu > umin)
{
lprop.SetParameters(setu,setv);
/*
n(0)+=lprop.Normal().X();
n(1)+=lprop.Normal().Y();
n(2)+=lprop.Normal().Z();
*/
n += occ2ng(lprop.Normal());
}
setu = geominfo.u;
while(setv < vmax && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5))
setv += ustep;
if(setv < vmax)
{
lprop.SetParameters(setu,setv);
/*
n(0)+=lprop.Normal().X();
n(1)+=lprop.Normal().Y();
n(2)+=lprop.Normal().Z();
*/
n += occ2ng(lprop.Normal());
}
setv = geominfo.v;
while(setv > vmin && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5))
setv -= ustep;
if(setv > vmin)
{
lprop.SetParameters(setu,setv);
/*
n(0)+=lprop.Normal().X();
n(1)+=lprop.Normal().Y();
n(2)+=lprop.Normal().Z();
*/
n += occ2ng(lprop.Normal());
}
setv = geominfo.v;
n.Normalize();
}
if(glob_testout)
{
(*testout) << "u " << geominfo.u << " v " << geominfo.v
<< " du " << lprop.D1U().X() << " "<< lprop.D1U().Y() << " "<< lprop.D1U().Z()
<< " dv " << lprop.D1V().X() << " "<< lprop.D1V().Y() << " "<< lprop.D1V().Z() << endl;
}
if (orient == TopAbs_REVERSED) n = -n;
// (*testout) << "GetNormalVector" << endl;
}
void OCCSurface :: DefineTangentialPlane (const Point<3> & ap1,
const PointGeomInfo & geominfo1,
const Point<3> & ap2,
const PointGeomInfo & geominfo2)
{
if (projecttype == PLANESPACE)
{
p1 = ap1; p2 = ap2;
//cout << "p1 = " << p1 << endl;
//cout << "p2 = " << p2 << endl;
GetNormalVector (p1, geominfo1, ez);
ex = p2 - p1;
ex -= (ex * ez) * ez;
ex.Normalize();
ey = Cross (ez, ex);
GetNormalVector (p2, geominfo2, n2);
nmid = 0.5*(n2+ez);
ez = nmid;
ez.Normalize();
ex = (p2 - p1).Normalize();
ez -= (ez * ex) * ex;
ez.Normalize();
ey = Cross (ez, ex);
nmid = ez;
//cout << "ex " << ex << " ey " << ey << " ez " << ez << endl;
}
else
{
if ( (geominfo1.u < umin) ||
(geominfo1.u > umax) ||
(geominfo2.u < umin) ||
(geominfo2.u > umax) ||
(geominfo1.v < vmin) ||
(geominfo1.v > vmax) ||
(geominfo2.v < vmin) ||
(geominfo2.v > vmax) ) throw UVBoundsException();
p1 = ap1; p2 = ap2;
psp1 = Point<2>(geominfo1.u, geominfo1.v);
psp2 = Point<2>(geominfo2.u, geominfo2.v);
Vec<3> n;
GetNormalVector (p1, geominfo1, n);
gp_Pnt pnt;
gp_Vec du, dv;
occface->D1 (geominfo1.u, geominfo1.v, pnt, du, dv);
// static Timer t("occ-defintangplane calculations");
// RegionTimer reg(t);
Mat<3,2> D1_;
D1_(0,0) = du.X(); D1_(1,0) = du.Y(); D1_(2,0) = du.Z();
D1_(0,1) = dv.X(); D1_(1,1) = dv.Y(); D1_(2,1) = dv.Z();
auto D1T_ = Trans(D1_);
auto D1TD1_ = D1T_*D1_;
if (Det (D1TD1_) == 0) throw SingularMatrixException();
Mat<2,2> DDTinv_;
CalcInverse (D1TD1_, DDTinv_);
Mat<3,2> Y_;
Vec<3> y1_ = (ap2-ap1).Normalize();
Vec<3> y2_ = Cross(n, y1_).Normalize();
for (int i = 0; i < 3; i++)
{
Y_(i,0) = y1_(i);
Y_(i,1) = y2_(i);
}
auto A_ = DDTinv_ * D1T_ * Y_;
Mat<2,2> Ainv_;
if (Det(A_) == 0) throw SingularMatrixException();
CalcInverse (A_, Ainv_);
Vec<2> temp_ = Ainv_ * (psp2-psp1);
double r_ = temp_.Length();
Mat<2,2> R_;
R_(0,0) = temp_(0)/r_;
R_(1,0) = temp_(1)/r_;
R_(0,1) = -R_(1,0);
R_(1,1) = R_(0,0);
A_ = A_ * R_;
Ainv_ = Trans(R_) * Ainv_;
Amat = A_;
Amatinv = Ainv_;
// temp = Amatinv * (psp2-psp1);
#ifdef OLD
DenseMatrix D1(3,2), D1T(2,3), DDTinv(2,2);
D1(0,0) = du.X(); D1(1,0) = du.Y(); D1(2,0) = du.Z();
D1(0,1) = dv.X(); D1(1,1) = dv.Y(); D1(2,1) = dv.Z();
/*
(*testout) << "DefineTangentialPlane" << endl
<< "---------------------" << endl;
(*testout) << "D1 = " << endl << D1 << endl;
*/
Transpose (D1, D1T);
DenseMatrix D1TD1(3,3);
D1TD1 = D1T*D1;
if (D1TD1.Det() == 0) throw SingularMatrixException();
CalcInverse (D1TD1, DDTinv);
// cout << " =?= inv = " << DDTinv << endl;
DenseMatrix Y(3,2);
Vec<3> y1 = (ap2-ap1).Normalize();
Vec<3> y2 = Cross(n, y1).Normalize();
for (int i = 0; i < 3; i++)
{
Y(i,0) = y1(i);
Y(i,1) = y2(i);
}
DenseMatrix A(2,2);
A = DDTinv * D1T * Y;
DenseMatrix Ainv(2,2);
if (A.Det() == 0) throw SingularMatrixException();
CalcInverse (A, Ainv);
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
{
Amat(i,j) = A(i,j);
Amatinv(i,j) = Ainv(i,j);
}
Vec<2> temp = Amatinv * (psp2-psp1);
double r = temp.Length();
// double alpha = -acos (temp(0)/r);
double alpha = -atan2 (temp(1),temp(0));
DenseMatrix R(2,2);
R(0,0) = cos (alpha);
R(1,0) = -sin (alpha);
R(0,1) = sin (alpha);
R(1,1) = cos (alpha);
// cout << "=?= R = " << R << endl;
A = A*R;
if (A.Det() == 0) throw SingularMatrixException();
CalcInverse (A, Ainv);
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
{
Amat(i,j) = A(i,j);
Amatinv(i,j) = Ainv(i,j);
}
// cout << "=?= Ainv = " << endl << Ainv << endl;
temp = Amatinv * (psp2-psp1);
cout << " =?= Amatinv = " << Amatinv << endl;
#endif
};
}
void OCCSurface :: ToPlane (const Point<3> & p3d,
const PointGeomInfo & geominfo,
Point<2> & pplane,
double h, int & zone) const
{
if (projecttype == PLANESPACE)
{
Vec<3> p1p, n;
GetNormalVector (p3d, geominfo, n);
p1p = p3d - p1;
pplane(0) = (p1p * ex) / h;
pplane(1) = (p1p * ey) / h;
if (n * nmid < 0)
zone = -1;
else
zone = 0;
/*
if(zone == -1)
{
(*testout) << "zone = -1 for " << p3d << " 2D: " << pplane << " n " << n << " nmid " << nmid << endl;
glob_testout = true;
GetNormalVector (p3d, geominfo, n);
glob_testout = false;
}
*/
}
else
{
pplane = Point<2>(geominfo.u, geominfo.v);
// (*testout) << "(u,v) = " << geominfo.u << ", " << geominfo.v << endl;
pplane = Point<2> (1/h * (Amatinv * (pplane-psp1)));
// pplane = Point<2> (h * (Amatinv * (pplane-psp1)));
// pplane = Point<2> (1/h * ((pplane-psp1)));
zone = 0;
};
}
void OCCSurface :: FromPlane (const Point<2> & pplane,
Point<3> & p3d,
PointGeomInfo & gi,
double h)
{
static Timer t("FromPlane"); RegionTimer reg(t);
if (projecttype == PLANESPACE)
{
// cout << "2d : " << pplane << endl;
p3d = p1 + (h * pplane(0)) * ex + (h * pplane(1)) * ey;
// cout << "3d : " << p3d << endl;
Project (p3d, gi);
// cout << "proj : " << p3d << endl;
}
else
{
// Point<2> pspnew = Point<2>(1/h * (Amat * Vec<2>(pplane)) + Vec<2>(psp1));
Point<2> pspnew = Point<2>(h * (Amat * Vec<2>(pplane)) + Vec<2>(psp1));
// Point<2> pspnew = Point<2>(h * (Vec<2>(pplane)) + Vec<2>(psp1));
gi.u = pspnew(0);
gi.v = pspnew(1);
gi.trignum = 1;
p3d = occ2ng(occface->Value (gi.u, gi.v));
};
}
void OCCSurface :: Project (Point<3> & ap, PointGeomInfo & gi)
{
static Timer t("OccSurface::Project"); RegionTimer reg(t);
static Timer t2("OccSurface::Project actual");
// try Newton's method ...
gp_Pnt p = ng2occ(ap);
double u = gi.u;
double v = gi.v;
#ifdef OLD
// was a problem for pheres: got u-v parameters outside range of definition
gp_Pnt x = occface->Value (u,v);
if (p.SquareDistance(x) <= sqr(PROJECTION_TOLERANCE)) return;
gp_Vec du, dv;
occface->D1(u,v,x,du,dv);
int count = 0;
gp_Pnt xold;
gp_Vec n;
double det, lambda, mu;
do
{
count++;
n = du^dv;
det = Det3 (n.X(), du.X(), dv.X(),
n.Y(), du.Y(), dv.Y(),
n.Z(), du.Z(), dv.Z());
if (det < 1e-15)
break;
lambda = Det3 (n.X(), p.X()-x.X(), dv.X(),
n.Y(), p.Y()-x.Y(), dv.Y(),
n.Z(), p.Z()-x.Z(), dv.Z())/det;
mu = Det3 (n.X(), du.X(), p.X()-x.X(),
n.Y(), du.Y(), p.Y()-x.Y(),
n.Z(), du.Z(), p.Z()-x.Z())/det;
u += lambda;
v += mu;
xold = x;
occface->D1(u,v,x,du,dv);
if (xold.SquareDistance(x) < sqr(PROJECTION_TOLERANCE))
{
ap = Point<3> (x.X(), x.Y(), x.Z());
gi.u = u;
gi.v = v;
return;
}
}
while (count < 20);
#endif
// Newton did not converge, use OCC projection
// static int cnt = 0;
// if (cnt++ % 1000 == 0) cout << "********************************************** OCCSurfce :: Project, cnt = " << cnt << endl;
gp_Pnt pnt = p; // (p(0), p(1), p(2));
//(*testout) << "pnt = " << pnt.X() << ", " << pnt.Y() << ", " << pnt.Z() << endl;
/*
GeomAPI_ProjectPointOnSurf proj(pnt, occface, umin, umax, vmin, vmax);
if (!proj.NbPoints())
{
cout << "Project Point on Surface FAIL" << endl;
throw UVBoundsException();
}
*/
/*
cout << "NP = " << proj.NbPoints() << endl;
for (int i = 1; i <= proj.NbPoints(); i++)
{
gp_Pnt pnt2 = proj.Point(i);
Point<3> p2 = Point<3> (pnt2.X(), pnt2.Y(), pnt2.Z());
cout << i << ". p = " << p2 << ", dist = " << (p2-p).Length() << endl;
}
*/
/*
pnt = proj.NearestPoint();
proj.LowerDistanceParameters (gi.u, gi.v);
*/
// double u,v;
Handle( ShapeAnalysis_Surface ) su = new ShapeAnalysis_Surface( occface );
auto toltool = BRep_Tool::Tolerance( topods_face );
// gp_Pnt2d suval = su->ValueOfUV ( pnt, toltool);
t2.Start();
gp_Pnt2d suval = su->NextValueOfUV (gp_Pnt2d(u,v), pnt, toltool);
t2.Stop();
suval.Coord( u, v);
pnt = occface->Value( u, v );
//(*testout) << "pnt(proj) = " << pnt.X() << ", " << pnt.Y() << ", " << pnt.Z() << endl;
gi.u = u;
gi.v = v;
gi.trignum = 1;
ap = occ2ng(pnt); // Point<3> (pnt.X(), pnt.Y(), pnt.Z());
}
Meshing2OCCSurfaces :: Meshing2OCCSurfaces (const NetgenGeometry& geo,
const TopoDS_Shape & asurf,
const Box<3> & abb, int aprojecttype,
const MeshingParameters & mparam)
: Meshing2(geo, mparam, Box<3>(abb.PMin(), abb.PMax())),
surface(TopoDS::Face(asurf), aprojecttype)
{
;
}
void Meshing2OCCSurfaces :: DefineTransformation (const Point<3> & p1, const Point<3> & p2,
const PointGeomInfo * geominfo1,
const PointGeomInfo * geominfo2)
{
((OCCSurface&)surface).DefineTangentialPlane (p1, *geominfo1, p2, *geominfo2);
}
void Meshing2OCCSurfaces :: TransformToPlain (const Point<3>& locpoint,
const MultiPointGeomInfo & geominfo,
Point<2> & planepoint,
double h, int & zone)
{
surface.ToPlane (locpoint, geominfo.GetPGI(1), planepoint, h, zone);
}
int Meshing2OCCSurfaces :: TransformFromPlain (const Point<2> & planepoint,
Point<3> & locpoint,
PointGeomInfo & gi,
double h)
{
surface.FromPlane (planepoint, locpoint, gi, h);
return 0;
}
double Meshing2OCCSurfaces :: CalcLocalH (const Point<3> & p, double gh) const
{
return gh;
}
/*
inline double Det3 (double a00, double a01, double a02,
double a10, double a11, double a12,
double a20, double a21, double a22)
{
return a00*a11*a22 + a01*a12*a20 + a10*a21*a02 - a20*a11*a02 - a10*a01*a22 - a21*a12*a00;
}
bool ProjectToSurface (gp_Pnt & p, Handle(Geom_Surface) surface, double& u, double& v)
{
gp_Pnt x = surface->Value (u,v);
if (p.SquareDistance(x) <= sqr(PROJECTION_TOLERANCE)) return true;
gp_Vec du, dv;
surface->D1(u,v,x,du,dv);
int count = 0;
gp_Pnt xold;
gp_Vec n;
double det, lambda, mu;
do {
count++;
n = du^dv;
det = Det3 (n.X(), du.X(), dv.X(),
n.Y(), du.Y(), dv.Y(),
n.Z(), du.Z(), dv.Z());
if (det < 1e-15) return false;
lambda = Det3 (n.X(), p.X()-x.X(), dv.X(),
n.Y(), p.Y()-x.Y(), dv.Y(),
n.Z(), p.Z()-x.Z(), dv.Z())/det;
mu = Det3 (n.X(), du.X(), p.X()-x.X(),
n.Y(), du.Y(), p.Y()-x.Y(),
n.Z(), du.Z(), p.Z()-x.Z())/det;
u += lambda;
v += mu;
xold = x;
surface->D1(u,v,x,du,dv);
} while (xold.SquareDistance(x) > sqr(PROJECTION_TOLERANCE) || count > 50);
if (count > 50) return false;
p = x;
return true;
}
*/
}
#endif