1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
16 #include <Bnd_Box2d.hxx>
17 #include <BndLib_Add2dCurve.hxx>
18 #include <BRepGProp_Face.hxx>
19 #include <Geom2d_BezierCurve.hxx>
20 #include <Geom2d_BSplineCurve.hxx>
21 #include <Geom2d_Line.hxx>
22 #include <Geom_BezierSurface.hxx>
23 #include <Geom_BSplineCurve.hxx>
24 #include <Geom_BSplineSurface.hxx>
25 #include <Geom_SurfaceOfLinearExtrusion.hxx>
26 #include <GeomAdaptor_Curve.hxx>
28 #include <gp_Pnt2d.hxx>
30 #include <gp_Vec2d.hxx>
32 #include <Precision.hxx>
34 #include <TopoDS_Edge.hxx>
35 #include <TopoDS_Face.hxx>
37 static const Standard_Real Epsilon1 = Epsilon(1.);
39 //=======================================================================
40 //function : UIntegrationOrder
42 //=======================================================================
43 Standard_Integer BRepGProp_Face::UIntegrationOrder() const {
46 switch (mySurface.GetType())
53 case GeomAbs_BezierSurface :
55 Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
59 case GeomAbs_BSplineSurface :
61 Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
62 Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots()-1;
74 //=======================================================================
75 //function : VIntegrationOrder
77 //=======================================================================
79 Standard_Integer BRepGProp_Face::VIntegrationOrder() const
82 switch (mySurface.GetType()) {
88 case GeomAbs_BezierSurface :
90 Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
95 case GeomAbs_BSplineSurface :
97 Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
98 Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots()-1;
110 //=======================================================================
111 //function : IntegrationOrder
113 //=======================================================================
115 Standard_Integer BRepGProp_Face::IntegrationOrder() const
119 switch (myCurve.GetType()) {
125 case GeomAbs_Circle :
126 case GeomAbs_Ellipse :
127 case GeomAbs_Hyperbola :
131 case GeomAbs_Parabola :
135 case GeomAbs_BezierCurve :
137 N = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree() + 1;
141 case GeomAbs_BSplineCurve :
143 Standard_Integer a = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree() + 1;
144 Standard_Integer b = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots() - 1;
157 //=======================================================================
160 //=======================================================================
162 void BRepGProp_Face::Bounds(Standard_Real& U1,
165 Standard_Real& V2)const
167 U1 = mySurface.FirstUParameter();
168 U2 = mySurface.LastUParameter();
169 V1 = mySurface.FirstVParameter();
170 V2 = mySurface.LastVParameter();
173 //=======================================================================
176 //=======================================================================
178 bool BRepGProp_Face::Load(const TopoDS_Edge& E)
181 Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E, mySurface.Face(), a,b);
186 if (E.Orientation() == TopAbs_REVERSED) {
188 a = C->ReversedParameter(b);
189 b = C->ReversedParameter(x);
196 //=======================================================================
199 //=======================================================================
201 void BRepGProp_Face::Load(const TopoDS_Face& F)
203 TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);
204 mySurface.Initialize(TopoDS::Face(aLocalShape));
205 // mySurface.Initialize(TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
206 mySReverse = (F.Orientation() == TopAbs_REVERSED);
209 //=======================================================================
212 //=======================================================================
214 void BRepGProp_Face::Normal (const Standard_Real U,
215 const Standard_Real V,
220 mySurface.D1(U,V,P,D1U,D1V);
221 VNor = D1U.Crossed(D1V);
222 if (mySReverse) VNor.Reverse();
226 // APO 17.04.2002 (OCC104)
227 // This is functions that calculate coeff. to optimize "integration order".
228 //They had been produced experementally for some hard example.
229 static Standard_Real AS = -0.15, AL = -0.50, B = 1.0, C = 0.75, D = 0.25;
230 static inline Standard_Real SCoeff(const Standard_Real Eps){
231 return Eps < 0.1? AS*(B+Log10(Eps)) + C: C;
233 static inline Standard_Real LCoeff(const Standard_Real Eps){
234 return Eps < 0.1? AL*(B+Log10(Eps)) + D: D;
237 //=======================================================================
238 //function : SIntOrder
240 //=======================================================================
242 Standard_Integer BRepGProp_Face::SIntOrder(const Standard_Real Eps) const
244 Standard_Integer Nv, Nu;
245 switch (mySurface.GetType()) {
247 Nu = 1; Nv = 1; break;
248 case GeomAbs_Cylinder:
249 Nu = 2; Nv = 1; break;
251 Nu = 2; Nv = 1; break;
253 Nu = 2; Nv = 2; break;
255 Nu = 2; Nv = 2; break;
256 case GeomAbs_BezierSurface:
257 Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
258 Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
260 case GeomAbs_BSplineSurface:
261 Nv = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
262 Nu = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
265 Nu = 2; Nv = 2; break;
267 return Min(RealToInt(Ceiling(SCoeff(Eps)*Max((Nu+1),(Nv+1)))), math::GaussPointsMax());
270 //=======================================================================
271 //function : SUIntSubs
273 //=======================================================================
275 Standard_Integer BRepGProp_Face::SUIntSubs() const
278 switch (mySurface.GetType()) {
281 case GeomAbs_Cylinder:
289 case GeomAbs_BezierSurface:
291 case GeomAbs_BSplineSurface:
292 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots(); break;
299 //=======================================================================
300 //function : SVIntSubs
302 //=======================================================================
304 Standard_Integer BRepGProp_Face::SVIntSubs() const
307 switch (mySurface.GetType()) {
310 case GeomAbs_Cylinder:
318 case GeomAbs_BezierSurface:
320 case GeomAbs_BSplineSurface:
321 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots();
329 //=======================================================================
332 //=======================================================================
334 void BRepGProp_Face::UKnots(TColStd_Array1OfReal& Knots) const
336 switch (mySurface.GetType()) {
338 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
340 case GeomAbs_Cylinder:
344 Knots(1) = 0.0; Knots(2) = M_PI*2.0/3.0; Knots(3) = M_PI*4.0/3.0; Knots(4) = M_PI*6.0/3.0;
346 case GeomAbs_BSplineSurface:
347 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UKnots(Knots);
350 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
355 //=======================================================================
358 //=======================================================================
360 void BRepGProp_Face::VKnots(TColStd_Array1OfReal& Knots) const
362 switch (mySurface.GetType()) {
364 case GeomAbs_Cylinder:
366 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
369 Knots(1) = -M_PI/2.0; Knots(2) = 0.0; Knots(3) = +M_PI/2.0;
372 Knots(1) = 0.0; Knots(2) = M_PI*2.0/3.0; Knots(3) = M_PI*4.0/3.0; Knots(4) = M_PI*6.0/3.0;
374 case GeomAbs_BSplineSurface:
375 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VKnots(Knots);
378 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
383 //=======================================================================
384 //function : LIntOrder
386 //=======================================================================
388 Standard_Integer BRepGProp_Face::LIntOrder(const Standard_Real Eps) const
392 BndLib_Add2dCurve::Add(myCurve, 1.e-7, aBox);
393 Standard_Real aXmin, aXmax, aYmin, aYmax;
394 aBox.Get(aXmin, aYmin, aXmax, aYmax);
395 Standard_Real aVmin = mySurface.FirstVParameter();
396 Standard_Real aVmax = mySurface.LastVParameter();
398 Standard_Real dv = (aVmax-aVmin);
399 Standard_Real anR = (dv > Epsilon1 ? Min ((aYmax - aYmin) / dv, 1.) : 1.);
401 // Standard_Integer anRInt = Max(RealToInt(Ceiling(SVIntSubs()*anR)), 2);
402 Standard_Integer anRInt = RealToInt(Ceiling(SVIntSubs()*anR));
403 Standard_Integer aLSubs = LIntSubs();
406 // Standard_Real NL, NS = Max(SIntOrder(1.0)*anRInt/LIntSubs(), 1);
407 Standard_Real NL, NS = Max(SIntOrder(1.)*anRInt/aLSubs, 1);
408 switch (myCurve.GetType()) {
412 NL = 2 * 3; break; //correction for the spans of converted curve
413 case GeomAbs_Ellipse:
414 NL = 2 * 3; break; //
415 case GeomAbs_Parabola:
417 case GeomAbs_Hyperbola:
419 case GeomAbs_BezierCurve:
420 NL = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree();
422 case GeomAbs_BSplineCurve:
423 NL = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree();
431 Standard_Integer nn =
432 RealToInt (aLSubs <= 4 ? Ceiling(LCoeff(Eps)*(NL+1)) : NL+1);
434 //return Min(RealToInt(Ceiling(LCoeff(Eps)*(NL+1)*NS)), math::GaussPointsMax());
435 return Min(nn, math::GaussPointsMax());
438 //=======================================================================
439 //function : LIntSubs
441 //=======================================================================
443 Standard_Integer BRepGProp_Face::LIntSubs() const
446 switch (myCurve.GetType()) {
450 case GeomAbs_Ellipse:
452 case GeomAbs_Parabola:
453 case GeomAbs_Hyperbola:
455 case GeomAbs_BSplineCurve:
456 N = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots();
464 //=======================================================================
467 //=======================================================================
469 void BRepGProp_Face::LKnots(TColStd_Array1OfReal& Knots) const
471 switch (myCurve.GetType()) {
473 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
476 case GeomAbs_Ellipse:
477 Knots(1) = 0.0; Knots(2) = M_PI*2.0/3.0; Knots(3) = M_PI*4.0/3.0; Knots(4) = M_PI*6.0/3.0;
479 case GeomAbs_Parabola:
480 case GeomAbs_Hyperbola:
481 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
483 case GeomAbs_BSplineCurve:
484 (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Knots(Knots);
487 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
492 //=======================================================================
495 //=======================================================================
497 void BRepGProp_Face::Load(const Standard_Boolean IsFirstParam,
498 const GeomAbs_IsoType theIsoType)
508 Bounds(aU1, aU2, aV1, aV2);
510 if (theIsoType == GeomAbs_IsoU) {
514 aLoc.SetCoord(aU1, aV2);
515 aDir.SetCoord(0., -1.);
517 aLoc.SetCoord(aU2, aV1);
518 aDir.SetCoord(0., 1.);
520 } else if (theIsoType == GeomAbs_IsoV) {
524 aLoc.SetCoord(aU1, aV1);
525 aDir.SetCoord(1., 0.);
527 aLoc.SetCoord(aU2, aV2);
528 aDir.SetCoord(-1., 0.);
533 Handle(Geom2d_Curve) aLin = new Geom2d_Line(aLoc, aDir);
535 myCurve.Load(aLin, 0., aLen);
538 //=======================================================================
539 //function : GetRealKnots
541 //=======================================================================
543 static void GetRealKnots(const Standard_Real theMin,
544 const Standard_Real theMax,
545 const Handle(TColStd_HArray1OfReal) &theKnots,
546 Handle(TColStd_HArray1OfReal) &theRealKnots)
548 Standard_Integer i = theKnots->Lower() - 1;
549 Standard_Integer iU = theKnots->Upper();
550 Standard_Integer aStartI = 0;
551 Standard_Integer aEndI = 0;
552 Standard_Real aTol = Precision::Confusion();
555 if (aStartI == 0 && theKnots->Value(i) > theMin + aTol)
558 if (aEndI == 0 && theKnots->Value(i + 1) > theMax - aTol)
561 if (aStartI != 0 && aEndI != 0)
568 Standard_Integer aNbNode = Max(0, aEndI - aStartI + 1) + 2;
571 theRealKnots = new TColStd_HArray1OfReal(1, aNbNode);
572 theRealKnots->SetValue(1, theMin);
573 theRealKnots->SetValue(aNbNode, theMax);
576 for (i = 2, j = aStartI; j <= aEndI; i++, j++)
577 theRealKnots->SetValue(i, theKnots->Value(j));
580 //=======================================================================
581 //function : GetCurveKnots
583 //=======================================================================
585 static void GetCurveKnots(const Standard_Real theMin,
586 const Standard_Real theMax,
587 const Geom2dAdaptor_Curve &theCurve,
588 Handle(TColStd_HArray1OfReal) &theKnots)
590 Standard_Boolean isSBSpline = theCurve.GetType() == GeomAbs_BSplineCurve;
593 Handle(Geom2d_BSplineCurve) aCrv;
594 Standard_Integer aNbKnots;
595 Handle(TColStd_HArray1OfReal) aCrvKnots;
597 aCrv = Handle(Geom2d_BSplineCurve)::DownCast(theCurve.Curve());
598 aNbKnots = aCrv->NbKnots();
599 aCrvKnots = new TColStd_HArray1OfReal(1, aNbKnots);
600 aCrv->Knots(aCrvKnots->ChangeArray1());
601 GetRealKnots(theMin, theMax, aCrvKnots, theKnots);
603 theKnots = new TColStd_HArray1OfReal(1, 2);
604 theKnots->SetValue(1, theMin);
605 theKnots->SetValue(2, theMax);
609 //=======================================================================
610 //function : GetUKnots
612 //=======================================================================
614 void BRepGProp_Face::GetUKnots
615 (const Standard_Real theUMin,
616 const Standard_Real theUMax,
617 Handle(TColStd_HArray1OfReal) &theUKnots) const
619 Standard_Boolean isSBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
620 Standard_Boolean isCBSpline = Standard_False;
623 // Check the basis curve of the surface of linear extrusion.
624 if (mySurface.GetType() == GeomAbs_SurfaceOfExtrusion) {
625 GeomAdaptor_Curve aCurve;
626 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
628 aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
629 isCBSpline = aCurve.GetType() == GeomAbs_BSplineCurve;
633 if (myIsUseSpan && (isSBSpline || isCBSpline)) {
634 // Using span decomposition for BSpline.
635 Handle(TColStd_HArray1OfReal) aKnots;
636 Standard_Integer aNbKnots;
639 // Get U knots of BSpline surface.
640 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
641 Handle(Geom_BSplineSurface) aBSplSurf;
643 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
644 aNbKnots = aBSplSurf->NbUKnots();
645 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
646 aBSplSurf->UKnots(aKnots->ChangeArray1());
648 // Get U knots of BSpline curve - basis curve of
649 // the surface of linear extrusion.
650 GeomAdaptor_Curve aCurve;
651 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
652 Handle(Geom_BSplineCurve) aBSplCurve;
654 aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
655 aBSplCurve = aCurve.BSpline();
656 aNbKnots = aBSplCurve->NbKnots();
657 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
658 aBSplCurve->Knots(aKnots->ChangeArray1());
661 // Compute number of knots inside theUMin and theUMax.
662 GetRealKnots(theUMin, theUMax, aKnots, theUKnots);
664 // No span decomposition.
665 theUKnots = new TColStd_HArray1OfReal(1, 2);
666 theUKnots->SetValue(1, theUMin);
667 theUKnots->SetValue(2, theUMax);
671 //=======================================================================
672 //function : GetTKnots
674 //=======================================================================
676 void BRepGProp_Face::GetTKnots
677 (const Standard_Real theTMin,
678 const Standard_Real theTMax,
679 Handle(TColStd_HArray1OfReal) &theTKnots) const
681 Standard_Boolean isBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
683 if (myIsUseSpan && isBSpline) {
684 // Using span decomposition for BSpline.
685 Handle(TColStd_HArray1OfReal) aSurfKnots;
686 Standard_Integer aNbKnots;
688 // Get V knots of BSpline surface.
689 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
690 Handle(Geom_BSplineSurface) aBSplSurf;
692 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
693 aNbKnots = aBSplSurf->NbVKnots();
694 aSurfKnots = new TColStd_HArray1OfReal(1, aNbKnots);
695 aBSplSurf->VKnots(aSurfKnots->ChangeArray1());
697 // Handle(TColStd_HArray1OfReal) aCurveKnots;
699 // GetCurveKnots(theTMin, theTMax, myCurve, aCurveKnots);
700 // GetRealCurveKnots(aCurveKnots, aSurfKnots, myCurve, theTKnots);
701 GetCurveKnots(theTMin, theTMax, myCurve, theTKnots);
703 theTKnots = new TColStd_HArray1OfReal(1, 2);
704 theTKnots->SetValue(1, theTMin);
705 theTKnots->SetValue(2, theTMax);