// File: GeomLib_IsPlanarSurface.cxx // Created: Mon Nov 23 11:12:10 1998 // Author: Philippe MANGIN // #include #include #include #include #include #include #include #include #include #include #include #include #include #include static Standard_Boolean Controle(const TColgp_Array1OfPnt& P, const gp_Pln& Plan, const Standard_Real Tol) { Standard_Integer ii; Standard_Boolean B=Standard_True; for (ii=1; ii<=P.Length() && B; ii++) B = (Plan.Distance(P(ii)) < Tol); return B; } static Standard_Boolean Controle(const TColgp_Array1OfPnt& Poles, const Standard_Real Tol, const Handle(Geom_Surface)& S, gp_Pln& Plan) { Standard_Boolean IsPlan = Standard_False; Standard_Boolean Essai = Standard_True; Standard_Real gx,gy,gz; Standard_Integer Nb = Poles.Length(); gp_Pnt Bary; gp_Dir DX, DY; if (Nb > 10) { // Test allege (pour une rejection rapide) TColgp_Array1OfPnt Aux(1,5); Aux(1) = Poles(1); Aux(2) = Poles(Nb/3); Aux(3) = Poles(Nb/2); Aux(4) = Poles(Nb/2+Nb/3); Aux(5) = Poles(Nb); GeomLib::Inertia(Aux, Bary, DX, DY, gx, gy, gz); Essai = (gzTol) { gp_Pnt P; gp_Vec DU, DV; Standard_Real umin, umax, vmin, vmax; S->Bounds(umin, umax, vmin, vmax); S->D1( (umin+umax)/2, (vmin+vmax)/2, P, DU, DV); // On prend DX le plus proche possible de DU gp_Dir du(DU); Standard_Real Angle1 = du.Angle(DX); Standard_Real Angle2 = du.Angle(DY); if (Angle1 > PI/2) Angle1 = PI-Angle1; if (Angle2 > PI/2) Angle2 = PI-Angle2; if (Angle2 < Angle1) { du = DY; DY = DX; DX = du; } if (DX.Angle(DU) > PI/2) DX.Reverse(); if (DY.Angle(DV) > PI/2) DY.Reverse(); gp_Ax3 axe(Bary, DX^DY, DX); Plan.SetPosition(axe); Plan.SetLocation(Bary); IsPlan = Standard_True; } } return IsPlan; } static Standard_Boolean Controle(const Handle(Geom_Curve)& C, const gp_Pln& Plan, const Standard_Real Tol) { Standard_Boolean B = Standard_True; Standard_Integer ii, Nb; GeomAbs_CurveType Type; GeomAdaptor_Curve AC(C); Type = AC.GetType(); Handle(TColgp_HArray1OfPnt) TabP; TabP.Nullify(); switch (Type) { case GeomAbs_Line : { Nb = 2; break; } case GeomAbs_Circle: { Nb = 3; break; } case GeomAbs_Ellipse: case GeomAbs_Hyperbola: case GeomAbs_Parabola: { Nb = 5; break; } case GeomAbs_BezierCurve: { Nb = AC.NbPoles(); Handle (Geom_BezierCurve) BZ = AC.Bezier(); TabP = new (TColgp_HArray1OfPnt) (1, AC.NbPoles()); for (ii=1; ii<=Nb; ii++) TabP->SetValue(ii, BZ->Pole(ii)); break; } case GeomAbs_BSplineCurve: { Nb = AC.NbPoles(); Handle (Geom_BSplineCurve) BZ = AC.BSpline(); TabP = new (TColgp_HArray1OfPnt) (1, AC.NbPoles()); for (ii=1; ii<=Nb; ii++) TabP->SetValue(ii, BZ->Pole(ii)); break; } default : { Nb = 8 + 3*AC.NbIntervals(GeomAbs_CN); } } if (TabP.IsNull()) { Standard_Real u, du, f, l, d; f = AC.FirstParameter(); l = AC.LastParameter(); du = (l-f)/(Nb-1); for (ii=1; ii<=Nb && B ; ii++) { u = (ii-1)*du + f; d = Plan.Distance(C->Value(u)); B = (d < Tol); } } else { B = Controle(TabP->Array1(), Plan, Tol); } return B; } GeomLib_IsPlanarSurface::GeomLib_IsPlanarSurface(const Handle(Geom_Surface)& S, const Standard_Real Tol) { GeomAdaptor_Surface AS(S); GeomAbs_SurfaceType Type; Type = AS.GetType(); switch (Type) { case GeomAbs_Plane : { IsPlan = Standard_True; myPlan = AS.Plane(); break; } case GeomAbs_Cylinder : case GeomAbs_Cone : case GeomAbs_Sphere : case GeomAbs_Torus : { IsPlan = Standard_False; break; } case GeomAbs_BezierSurface : case GeomAbs_BSplineSurface : { Standard_Integer ii, jj, kk, NbU = AS.NbUPoles(), NbV = AS.NbVPoles(); TColgp_Array1OfPnt Poles(1, NbU*NbV); if (Type == GeomAbs_BezierSurface) { Handle(Geom_BezierSurface) BZ; BZ = AS.Bezier(); for(ii=1, kk=1; ii<=NbU; ii++) for(jj=1; jj<=NbV; jj++,kk++) Poles(kk) = BZ->Pole(ii,jj); } else { Handle(Geom_BSplineSurface) BS; BS = AS.BSpline(); for(ii=1, kk=1; ii<=NbU; ii++) for(jj=1; jj<=NbV; jj++,kk++) Poles(kk) = BS->Pole(ii,jj); } IsPlan = Controle(Poles, Tol, S, myPlan); break; } case GeomAbs_SurfaceOfRevolution : { Standard_Boolean Essai = Standard_True; gp_Pnt P; gp_Vec DU, DV, Dn; gp_Dir Dir = AS.AxeOfRevolution().Direction(); Standard_Real Umin, Umax, Vmin, Vmax; S->Bounds(Umin, Umax, Vmin, Vmax); S->D1((Umin+Umax)/2, (Vmin+Vmax)/2, P, DU, DV); Dn = DU^DV; if (Dn.Magnitude() > 1.e-7) { Standard_Real angle = Dir.Angle(Dn); if (angle > PI/2) { angle = PI - angle; Dir.Reverse(); } Essai = (angle < 0.1); } if (Essai) { gp_Ax3 axe(P, Dir); axe.SetXDirection(DU); myPlan.SetPosition(axe); myPlan.SetLocation(P); Handle(Geom_Curve) C; C = S->UIso(Umin); IsPlan = Controle(C, myPlan, Tol); } else IsPlan = Standard_False; break; } case GeomAbs_SurfaceOfExtrusion : { Standard_Boolean Essai = Standard_False; Standard_Real Umin, Umax, Vmin, Vmax; Standard_Real norm; gp_Vec Du, Dv, Dn; gp_Pnt P; S->Bounds(Umin, Umax, Vmin, Vmax); S->D1((Umin+Umax)/2, (Vmin+Vmax)/2, P, Du, Dv); Dn = Du^Dv; norm = Dn.Magnitude(); if (norm > 1.e-15) { Dn /= norm; Standard_Real angmax = Tol / (Vmax-Vmin); gp_Dir D(Dn); Essai = (D.IsNormal(AS.Direction(), angmax)); } if (Essai) { gp_Ax3 axe(P, Dn, Du); myPlan.SetPosition(axe); myPlan.SetLocation(P); Handle(Geom_Curve) C; C = S->VIso((Vmin+Vmax)/2); IsPlan = Controle(C, myPlan, Tol); } else IsPlan = Standard_False; break; } default : { Standard_Integer NbU,NbV, ii, jj, kk; NbU = 8 + 3*AS.NbUIntervals(GeomAbs_CN); NbV = 8 + 3*AS.NbVIntervals(GeomAbs_CN); Standard_Real Umin, Umax, Vmin, Vmax, du, dv, U, V; S->Bounds(Umin, Umax, Vmin, Vmax); du = (Umax-Umin)/(NbU-1); dv = (Vmax-Vmin)/(NbV-1); TColgp_Array1OfPnt Pnts(1, NbU*NbV); for(ii=0, kk=1; iiD0(U,V, Pnts(kk)); } } IsPlan = Controle(Pnts, Tol, S, myPlan); } } } Standard_Boolean GeomLib_IsPlanarSurface::IsPlanar() const { return IsPlan; } const gp_Pln& GeomLib_IsPlanarSurface::Plan() const { if (!IsPlan) StdFail_NotDone::Raise(" GeomLib_IsPlanarSurface"); return myPlan; }