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>
31 #include <Precision.hxx>
33 #include <TopoDS_Edge.hxx>
34 #include <TopoDS_Face.hxx>
36 static const Standard_Real Epsilon1 = Epsilon(1.);
38 //=======================================================================
39 //function : UIntegrationOrder
41 //=======================================================================
42 Standard_Integer BRepGProp_Face::UIntegrationOrder() const {
45 switch (mySurface.GetType())
52 case GeomAbs_BezierSurface :
54 Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
58 case GeomAbs_BSplineSurface :
60 Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
61 Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots()-1;
73 //=======================================================================
74 //function : VIntegrationOrder
76 //=======================================================================
78 Standard_Integer BRepGProp_Face::VIntegrationOrder() const
81 switch (mySurface.GetType()) {
87 case GeomAbs_BezierSurface :
89 Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
94 case GeomAbs_BSplineSurface :
96 Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
97 Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots()-1;
109 //=======================================================================
110 //function : IntegrationOrder
112 //=======================================================================
114 Standard_Integer BRepGProp_Face::IntegrationOrder() const
118 switch (myCurve.GetType()) {
124 case GeomAbs_Circle :
125 case GeomAbs_Ellipse :
126 case GeomAbs_Hyperbola :
130 case GeomAbs_Parabola :
134 case GeomAbs_BezierCurve :
136 N = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree() + 1;
140 case GeomAbs_BSplineCurve :
142 Standard_Integer a = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree() + 1;
143 Standard_Integer b = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots() - 1;
156 //=======================================================================
159 //=======================================================================
161 void BRepGProp_Face::Bounds(Standard_Real& U1,
164 Standard_Real& V2)const
166 U1 = mySurface.FirstUParameter();
167 U2 = mySurface.LastUParameter();
168 V1 = mySurface.FirstVParameter();
169 V2 = mySurface.LastVParameter();
172 //=======================================================================
175 //=======================================================================
177 bool BRepGProp_Face::Load(const TopoDS_Edge& E)
180 Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E, mySurface.Face(), a,b);
185 if (E.Orientation() == TopAbs_REVERSED) {
187 a = C->ReversedParameter(b);
188 b = C->ReversedParameter(x);
195 //=======================================================================
198 //=======================================================================
200 void BRepGProp_Face::Load(const TopoDS_Face& F)
202 TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);
203 mySurface.Initialize(TopoDS::Face(aLocalShape));
204 // mySurface.Initialize(TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
205 mySReverse = (F.Orientation() == TopAbs_REVERSED);
208 //=======================================================================
211 //=======================================================================
213 void BRepGProp_Face::Normal (const Standard_Real U,
214 const Standard_Real V,
219 mySurface.D1(U,V,P,D1U,D1V);
220 VNor = D1U.Crossed(D1V);
221 if (mySReverse) VNor.Reverse();
225 // APO 17.04.2002 (OCC104)
226 // This is functions that calculate coeff. to optimize "integration order".
227 // They had been produced experimentally for some hard example.
228 static Standard_Real AS = -0.15, AL = -0.50, B = 1.0, C = 0.75, D = 0.25;
229 static inline Standard_Real SCoeff(const Standard_Real Eps){
230 return Eps < 0.1? AS*(B+Log10(Eps)) + C: C;
232 static inline Standard_Real LCoeff(const Standard_Real Eps){
233 return Eps < 0.1? AL*(B+Log10(Eps)) + D: D;
236 //=======================================================================
237 //function : SIntOrder
239 //=======================================================================
241 Standard_Integer BRepGProp_Face::SIntOrder(const Standard_Real Eps) const
243 Standard_Integer Nv, Nu;
244 switch (mySurface.GetType()) {
246 Nu = 1; Nv = 1; break;
247 case GeomAbs_Cylinder:
248 Nu = 2; Nv = 1; break;
250 Nu = 2; Nv = 1; break;
252 Nu = 2; Nv = 2; break;
254 Nu = 2; Nv = 2; break;
255 case GeomAbs_BezierSurface:
256 Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
257 Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
259 case GeomAbs_BSplineSurface:
260 Nv = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
261 Nu = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
264 Nu = 2; Nv = 2; break;
266 return Min(RealToInt(Ceiling(SCoeff(Eps)*Max((Nu+1),(Nv+1)))), math::GaussPointsMax());
269 //=======================================================================
270 //function : SUIntSubs
272 //=======================================================================
274 Standard_Integer BRepGProp_Face::SUIntSubs() const
277 switch (mySurface.GetType()) {
280 case GeomAbs_Cylinder:
288 case GeomAbs_BezierSurface:
290 case GeomAbs_BSplineSurface:
291 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots(); break;
298 //=======================================================================
299 //function : SVIntSubs
301 //=======================================================================
303 Standard_Integer BRepGProp_Face::SVIntSubs() const
306 switch (mySurface.GetType()) {
309 case GeomAbs_Cylinder:
317 case GeomAbs_BezierSurface:
319 case GeomAbs_BSplineSurface:
320 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots();
328 //=======================================================================
331 //=======================================================================
333 void BRepGProp_Face::UKnots(TColStd_Array1OfReal& Knots) const
335 switch (mySurface.GetType()) {
337 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
339 case GeomAbs_Cylinder:
343 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;
345 case GeomAbs_BSplineSurface:
346 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UKnots(Knots);
349 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
354 //=======================================================================
357 //=======================================================================
359 void BRepGProp_Face::VKnots(TColStd_Array1OfReal& Knots) const
361 switch (mySurface.GetType()) {
363 case GeomAbs_Cylinder:
365 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
368 Knots(1) = -M_PI/2.0; Knots(2) = 0.0; Knots(3) = +M_PI/2.0;
371 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;
373 case GeomAbs_BSplineSurface:
374 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VKnots(Knots);
377 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
382 //=======================================================================
383 //function : LIntOrder
385 //=======================================================================
387 Standard_Integer BRepGProp_Face::LIntOrder(const Standard_Real Eps) const
391 BndLib_Add2dCurve::Add(myCurve, 1.e-7, aBox);
392 Standard_Real aXmin, aXmax, aYmin, aYmax;
393 aBox.Get(aXmin, aYmin, aXmax, aYmax);
394 Standard_Real aVmin = mySurface.FirstVParameter();
395 Standard_Real aVmax = mySurface.LastVParameter();
397 Standard_Real dv = (aVmax-aVmin);
398 Standard_Real anR = (dv > Epsilon1 ? Min ((aYmax - aYmin) / dv, 1.) : 1.);
400 // Standard_Integer anRInt = Max(RealToInt(Ceiling(SVIntSubs()*anR)), 2);
401 Standard_Integer anRInt = RealToInt(Ceiling(SVIntSubs()*anR));
402 Standard_Integer aLSubs = LIntSubs();
405 // Standard_Real NL, NS = Max(SIntOrder(1.0)*anRInt/LIntSubs(), 1);
406 Standard_Real NL, NS = Max(SIntOrder(1.)*anRInt/aLSubs, 1);
407 switch (myCurve.GetType()) {
411 NL = 2 * 3; break; //correction for the spans of converted curve
412 case GeomAbs_Ellipse:
413 NL = 2 * 3; break; //
414 case GeomAbs_Parabola:
416 case GeomAbs_Hyperbola:
418 case GeomAbs_BezierCurve:
419 NL = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree();
421 case GeomAbs_BSplineCurve:
422 NL = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree();
430 Standard_Integer nn =
431 RealToInt (aLSubs <= 4 ? Ceiling(LCoeff(Eps)*(NL+1)) : NL+1);
433 //return Min(RealToInt(Ceiling(LCoeff(Eps)*(NL+1)*NS)), math::GaussPointsMax());
434 return Min(nn, math::GaussPointsMax());
437 //=======================================================================
438 //function : LIntSubs
440 //=======================================================================
442 Standard_Integer BRepGProp_Face::LIntSubs() const
445 switch (myCurve.GetType()) {
449 case GeomAbs_Ellipse:
451 case GeomAbs_Parabola:
452 case GeomAbs_Hyperbola:
454 case GeomAbs_BSplineCurve:
455 N = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots();
463 //=======================================================================
466 //=======================================================================
468 void BRepGProp_Face::LKnots(TColStd_Array1OfReal& Knots) const
470 switch (myCurve.GetType()) {
472 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
475 case GeomAbs_Ellipse:
476 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;
478 case GeomAbs_Parabola:
479 case GeomAbs_Hyperbola:
480 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
482 case GeomAbs_BSplineCurve:
483 (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Knots(Knots);
486 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
491 //=======================================================================
494 //=======================================================================
496 void BRepGProp_Face::Load(const Standard_Boolean IsFirstParam,
497 const GeomAbs_IsoType theIsoType)
507 Bounds(aU1, aU2, aV1, aV2);
509 if (theIsoType == GeomAbs_IsoU) {
513 aLoc.SetCoord(aU1, aV2);
514 aDir.SetCoord(0., -1.);
516 aLoc.SetCoord(aU2, aV1);
517 aDir.SetCoord(0., 1.);
519 } else if (theIsoType == GeomAbs_IsoV) {
523 aLoc.SetCoord(aU1, aV1);
524 aDir.SetCoord(1., 0.);
526 aLoc.SetCoord(aU2, aV2);
527 aDir.SetCoord(-1., 0.);
532 Handle(Geom2d_Curve) aLin = new Geom2d_Line(aLoc, aDir);
534 myCurve.Load(aLin, 0., aLen);
537 //=======================================================================
538 //function : GetRealKnots
540 //=======================================================================
542 static void GetRealKnots(const Standard_Real theMin,
543 const Standard_Real theMax,
544 const Handle(TColStd_HArray1OfReal) &theKnots,
545 Handle(TColStd_HArray1OfReal) &theRealKnots)
547 Standard_Integer i = theKnots->Lower() - 1;
548 Standard_Integer iU = theKnots->Upper();
549 Standard_Integer aStartI = 0;
550 Standard_Integer aEndI = 0;
551 Standard_Real aTol = Precision::Confusion();
554 if (aStartI == 0 && theKnots->Value(i) > theMin + aTol)
557 if (aEndI == 0 && theKnots->Value(i + 1) > theMax - aTol)
560 if (aStartI != 0 && aEndI != 0)
567 Standard_Integer aNbNode = Max(0, aEndI - aStartI + 1) + 2;
570 theRealKnots = new TColStd_HArray1OfReal(1, aNbNode);
571 theRealKnots->SetValue(1, theMin);
572 theRealKnots->SetValue(aNbNode, theMax);
575 for (i = 2, j = aStartI; j <= aEndI; i++, j++)
576 theRealKnots->SetValue(i, theKnots->Value(j));
579 //=======================================================================
580 //function : GetCurveKnots
582 //=======================================================================
584 static void GetCurveKnots(const Standard_Real theMin,
585 const Standard_Real theMax,
586 const Geom2dAdaptor_Curve &theCurve,
587 Handle(TColStd_HArray1OfReal) &theKnots)
589 Standard_Boolean isSBSpline = theCurve.GetType() == GeomAbs_BSplineCurve;
592 Handle(Geom2d_BSplineCurve) aCrv;
593 Standard_Integer aNbKnots;
594 Handle(TColStd_HArray1OfReal) aCrvKnots;
596 aCrv = Handle(Geom2d_BSplineCurve)::DownCast(theCurve.Curve());
597 aNbKnots = aCrv->NbKnots();
598 aCrvKnots = new TColStd_HArray1OfReal(1, aNbKnots);
599 aCrv->Knots(aCrvKnots->ChangeArray1());
600 GetRealKnots(theMin, theMax, aCrvKnots, theKnots);
602 theKnots = new TColStd_HArray1OfReal(1, 2);
603 theKnots->SetValue(1, theMin);
604 theKnots->SetValue(2, theMax);
608 //=======================================================================
609 //function : GetUKnots
611 //=======================================================================
613 void BRepGProp_Face::GetUKnots
614 (const Standard_Real theUMin,
615 const Standard_Real theUMax,
616 Handle(TColStd_HArray1OfReal) &theUKnots) const
618 Standard_Boolean isSBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
619 Standard_Boolean isCBSpline = Standard_False;
622 // Check the basis curve of the surface of linear extrusion.
623 if (mySurface.GetType() == GeomAbs_SurfaceOfExtrusion) {
624 GeomAdaptor_Curve aCurve;
625 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
627 aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
628 isCBSpline = aCurve.GetType() == GeomAbs_BSplineCurve;
632 if (myIsUseSpan && (isSBSpline || isCBSpline)) {
633 // Using span decomposition for BSpline.
634 Handle(TColStd_HArray1OfReal) aKnots;
635 Standard_Integer aNbKnots;
638 // Get U knots of BSpline surface.
639 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
640 Handle(Geom_BSplineSurface) aBSplSurf;
642 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
643 aNbKnots = aBSplSurf->NbUKnots();
644 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
645 aBSplSurf->UKnots(aKnots->ChangeArray1());
647 // Get U knots of BSpline curve - basis curve of
648 // the surface of linear extrusion.
649 GeomAdaptor_Curve aCurve;
650 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
651 Handle(Geom_BSplineCurve) aBSplCurve;
653 aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
654 aBSplCurve = aCurve.BSpline();
655 aNbKnots = aBSplCurve->NbKnots();
656 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
657 aBSplCurve->Knots(aKnots->ChangeArray1());
660 // Compute number of knots inside theUMin and theUMax.
661 GetRealKnots(theUMin, theUMax, aKnots, theUKnots);
663 // No span decomposition.
664 theUKnots = new TColStd_HArray1OfReal(1, 2);
665 theUKnots->SetValue(1, theUMin);
666 theUKnots->SetValue(2, theUMax);
670 //=======================================================================
671 //function : GetTKnots
673 //=======================================================================
675 void BRepGProp_Face::GetTKnots
676 (const Standard_Real theTMin,
677 const Standard_Real theTMax,
678 Handle(TColStd_HArray1OfReal) &theTKnots) const
680 Standard_Boolean isBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
682 if (myIsUseSpan && isBSpline) {
683 // Using span decomposition for BSpline.
684 Handle(TColStd_HArray1OfReal) aSurfKnots;
685 Standard_Integer aNbKnots;
687 // Get V knots of BSpline surface.
688 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
689 Handle(Geom_BSplineSurface) aBSplSurf;
691 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
692 aNbKnots = aBSplSurf->NbVKnots();
693 aSurfKnots = new TColStd_HArray1OfReal(1, aNbKnots);
694 aBSplSurf->VKnots(aSurfKnots->ChangeArray1());
696 // Handle(TColStd_HArray1OfReal) aCurveKnots;
698 // GetCurveKnots(theTMin, theTMax, myCurve, aCurveKnots);
699 // GetRealCurveKnots(aCurveKnots, aSurfKnots, myCurve, theTKnots);
700 GetCurveKnots(theTMin, theTMax, myCurve, theTKnots);
702 theTKnots = new TColStd_HArray1OfReal(1, 2);
703 theTKnots->SetValue(1, theTMin);
704 theTKnots->SetValue(2, theTMax);