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 void BRepGProp_Face::Load(const TopoDS_Edge& E)
181 Handle(Geom2d_Curve) C =
182 BRep_Tool::CurveOnSurface(E, mySurface.Face(), a,b);
183 if (E.Orientation() == TopAbs_REVERSED) {
185 a = C->ReversedParameter(b);
186 b = C->ReversedParameter(x);
192 //=======================================================================
195 //=======================================================================
197 void BRepGProp_Face::Load(const TopoDS_Face& F)
199 TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);
200 mySurface.Initialize(TopoDS::Face(aLocalShape));
201 // mySurface.Initialize(TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
202 mySReverse = (F.Orientation() == TopAbs_REVERSED);
205 //=======================================================================
208 //=======================================================================
210 void BRepGProp_Face::Normal (const Standard_Real U,
211 const Standard_Real V,
216 mySurface.D1(U,V,P,D1U,D1V);
217 VNor = D1U.Crossed(D1V);
218 if (mySReverse) VNor.Reverse();
222 // APO 17.04.2002 (OCC104)
223 // This is functions that calculate coeff. to optimize "integration order".
224 //They had been produced experementally for some hard example.
225 static Standard_Real AS = -0.15, AL = -0.50, B = 1.0, C = 0.75, D = 0.25;
226 static inline Standard_Real SCoeff(const Standard_Real Eps){
227 return Eps < 0.1? AS*(B+Log10(Eps)) + C: C;
229 static inline Standard_Real LCoeff(const Standard_Real Eps){
230 return Eps < 0.1? AL*(B+Log10(Eps)) + D: D;
233 //=======================================================================
234 //function : SIntOrder
236 //=======================================================================
238 Standard_Integer BRepGProp_Face::SIntOrder(const Standard_Real Eps) const
240 Standard_Integer Nv, Nu;
241 switch (mySurface.GetType()) {
243 Nu = 1; Nv = 1; break;
244 case GeomAbs_Cylinder:
245 Nu = 2; Nv = 1; break;
247 Nu = 2; Nv = 1; break;
249 Nu = 2; Nv = 2; break;
251 Nu = 2; Nv = 2; break;
252 case GeomAbs_BezierSurface:
253 Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
254 Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
256 case GeomAbs_BSplineSurface:
257 Nv = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
258 Nu = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
261 Nu = 2; Nv = 2; break;
263 return Min(RealToInt(Ceiling(SCoeff(Eps)*Max((Nu+1),(Nv+1)))), math::GaussPointsMax());
266 //=======================================================================
267 //function : SUIntSubs
269 //=======================================================================
271 Standard_Integer BRepGProp_Face::SUIntSubs() const
274 switch (mySurface.GetType()) {
277 case GeomAbs_Cylinder:
285 case GeomAbs_BezierSurface:
287 case GeomAbs_BSplineSurface:
288 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots(); break;
295 //=======================================================================
296 //function : SVIntSubs
298 //=======================================================================
300 Standard_Integer BRepGProp_Face::SVIntSubs() const
303 switch (mySurface.GetType()) {
306 case GeomAbs_Cylinder:
314 case GeomAbs_BezierSurface:
316 case GeomAbs_BSplineSurface:
317 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots();
325 //=======================================================================
328 //=======================================================================
330 void BRepGProp_Face::UKnots(TColStd_Array1OfReal& Knots) const
332 switch (mySurface.GetType()) {
334 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
336 case GeomAbs_Cylinder:
340 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;
342 case GeomAbs_BSplineSurface:
343 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UKnots(Knots);
346 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
351 //=======================================================================
354 //=======================================================================
356 void BRepGProp_Face::VKnots(TColStd_Array1OfReal& Knots) const
358 switch (mySurface.GetType()) {
360 case GeomAbs_Cylinder:
362 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
365 Knots(1) = -M_PI/2.0; Knots(2) = 0.0; Knots(3) = +M_PI/2.0;
368 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;
370 case GeomAbs_BSplineSurface:
371 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VKnots(Knots);
374 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
379 //=======================================================================
380 //function : LIntOrder
382 //=======================================================================
384 Standard_Integer BRepGProp_Face::LIntOrder(const Standard_Real Eps) const
388 BndLib_Add2dCurve::Add(myCurve, 1.e-7, aBox);
389 Standard_Real aXmin, aXmax, aYmin, aYmax;
390 aBox.Get(aXmin, aYmin, aXmax, aYmax);
391 Standard_Real aVmin = mySurface.FirstVParameter();
392 Standard_Real aVmax = mySurface.LastVParameter();
394 Standard_Real dv = (aVmax-aVmin);
395 Standard_Real anR = (dv > Epsilon1 ? Min ((aYmax - aYmin) / dv, 1.) : 1.);
397 // Standard_Integer anRInt = Max(RealToInt(Ceiling(SVIntSubs()*anR)), 2);
398 Standard_Integer anRInt = RealToInt(Ceiling(SVIntSubs()*anR));
399 Standard_Integer aLSubs = LIntSubs();
402 // Standard_Real NL, NS = Max(SIntOrder(1.0)*anRInt/LIntSubs(), 1);
403 Standard_Real NL, NS = Max(SIntOrder(1.)*anRInt/aLSubs, 1);
404 switch (myCurve.GetType()) {
408 NL = 2 * 3; break; //correction for the spans of converted curve
409 case GeomAbs_Ellipse:
410 NL = 2 * 3; break; //
411 case GeomAbs_Parabola:
413 case GeomAbs_Hyperbola:
415 case GeomAbs_BezierCurve:
416 NL = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree();
418 case GeomAbs_BSplineCurve:
419 NL = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree();
427 Standard_Integer nn =
428 RealToInt (aLSubs <= 4 ? Ceiling(LCoeff(Eps)*(NL+1)) : NL+1);
430 //return Min(RealToInt(Ceiling(LCoeff(Eps)*(NL+1)*NS)), math::GaussPointsMax());
431 return Min(nn, math::GaussPointsMax());
434 //=======================================================================
435 //function : LIntSubs
437 //=======================================================================
439 Standard_Integer BRepGProp_Face::LIntSubs() const
442 switch (myCurve.GetType()) {
446 case GeomAbs_Ellipse:
448 case GeomAbs_Parabola:
449 case GeomAbs_Hyperbola:
451 case GeomAbs_BSplineCurve:
452 N = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots();
460 //=======================================================================
463 //=======================================================================
465 void BRepGProp_Face::LKnots(TColStd_Array1OfReal& Knots) const
467 switch (myCurve.GetType()) {
469 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
472 case GeomAbs_Ellipse:
473 Knots(1) = 0.0; Knots(2) = M_PI*2.0/3.0; Knots(3) = M_PI*4.0/3.0; Knots(2) = M_PI*6.0/3.0;
475 case GeomAbs_Parabola:
476 case GeomAbs_Hyperbola:
477 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
479 case GeomAbs_BSplineCurve:
480 (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Knots(Knots);
483 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
488 //=======================================================================
491 //=======================================================================
493 void BRepGProp_Face::Load(const Standard_Boolean IsFirstParam,
494 const GeomAbs_IsoType theIsoType)
504 Bounds(aU1, aU2, aV1, aV2);
506 if (theIsoType == GeomAbs_IsoU) {
510 aLoc.SetCoord(aU1, aV2);
511 aDir.SetCoord(0., -1.);
513 aLoc.SetCoord(aU2, aV1);
514 aDir.SetCoord(0., 1.);
516 } else if (theIsoType == GeomAbs_IsoV) {
520 aLoc.SetCoord(aU1, aV1);
521 aDir.SetCoord(1., 0.);
523 aLoc.SetCoord(aU2, aV2);
524 aDir.SetCoord(-1., 0.);
529 Handle(Geom2d_Curve) aLin = new Geom2d_Line(aLoc, aDir);
531 myCurve.Load(aLin, 0., aLen);
534 //=======================================================================
535 //function : GetRealKnots
537 //=======================================================================
539 static void GetRealKnots(const Standard_Real theMin,
540 const Standard_Real theMax,
541 const Handle(TColStd_HArray1OfReal) &theKnots,
542 Handle(TColStd_HArray1OfReal) &theRealKnots)
544 Standard_Integer i = theKnots->Lower() - 1;
545 Standard_Integer iU = theKnots->Upper();
546 Standard_Integer aStartI = 0;
547 Standard_Integer aEndI = 0;
548 Standard_Real aTol = Precision::Confusion();
551 if (aStartI == 0 && theKnots->Value(i) > theMin + aTol)
554 if (aEndI == 0 && theKnots->Value(i + 1) > theMax - aTol)
557 if (aStartI != 0 && aEndI != 0)
564 Standard_Integer aNbNode = Max(0, aEndI - aStartI + 1) + 2;
567 theRealKnots = new TColStd_HArray1OfReal(1, aNbNode);
568 theRealKnots->SetValue(1, theMin);
569 theRealKnots->SetValue(aNbNode, theMax);
572 for (i = 2, j = aStartI; j <= aEndI; i++, j++)
573 theRealKnots->SetValue(i, theKnots->Value(j));
576 //=======================================================================
577 //function : GetCurveKnots
579 //=======================================================================
581 static void GetCurveKnots(const Standard_Real theMin,
582 const Standard_Real theMax,
583 const Geom2dAdaptor_Curve &theCurve,
584 Handle(TColStd_HArray1OfReal) &theKnots)
586 Standard_Boolean isSBSpline = theCurve.GetType() == GeomAbs_BSplineCurve;
589 Handle(Geom2d_BSplineCurve) aCrv;
590 Standard_Integer aNbKnots;
591 Handle(TColStd_HArray1OfReal) aCrvKnots;
593 aCrv = Handle(Geom2d_BSplineCurve)::DownCast(theCurve.Curve());
594 aNbKnots = aCrv->NbKnots();
595 aCrvKnots = new TColStd_HArray1OfReal(1, aNbKnots);
596 aCrv->Knots(aCrvKnots->ChangeArray1());
597 GetRealKnots(theMin, theMax, aCrvKnots, theKnots);
599 theKnots = new TColStd_HArray1OfReal(1, 2);
600 theKnots->SetValue(1, theMin);
601 theKnots->SetValue(2, theMax);
605 //=======================================================================
606 //function : GetUKnots
608 //=======================================================================
610 void BRepGProp_Face::GetUKnots
611 (const Standard_Real theUMin,
612 const Standard_Real theUMax,
613 Handle(TColStd_HArray1OfReal) &theUKnots) const
615 Standard_Boolean isSBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
616 Standard_Boolean isCBSpline = Standard_False;
619 // Check the basis curve of the surface of linear extrusion.
620 if (mySurface.GetType() == GeomAbs_SurfaceOfExtrusion) {
621 GeomAdaptor_Curve aCurve;
622 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
624 aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
625 isCBSpline = aCurve.GetType() == GeomAbs_BSplineCurve;
629 if (myIsUseSpan && (isSBSpline || isCBSpline)) {
630 // Using span decomposition for BSpline.
631 Handle(TColStd_HArray1OfReal) aKnots;
632 Standard_Integer aNbKnots;
635 // Get U knots of BSpline surface.
636 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
637 Handle(Geom_BSplineSurface) aBSplSurf;
639 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
640 aNbKnots = aBSplSurf->NbUKnots();
641 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
642 aBSplSurf->UKnots(aKnots->ChangeArray1());
644 // Get U knots of BSpline curve - basis curve of
645 // the surface of linear extrusion.
646 GeomAdaptor_Curve aCurve;
647 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
648 Handle(Geom_BSplineCurve) aBSplCurve;
650 aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
651 aBSplCurve = aCurve.BSpline();
652 aNbKnots = aBSplCurve->NbKnots();
653 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
654 aBSplCurve->Knots(aKnots->ChangeArray1());
657 // Compute number of knots inside theUMin and theUMax.
658 GetRealKnots(theUMin, theUMax, aKnots, theUKnots);
660 // No span decomposition.
661 theUKnots = new TColStd_HArray1OfReal(1, 2);
662 theUKnots->SetValue(1, theUMin);
663 theUKnots->SetValue(2, theUMax);
667 //=======================================================================
668 //function : GetTKnots
670 //=======================================================================
672 void BRepGProp_Face::GetTKnots
673 (const Standard_Real theTMin,
674 const Standard_Real theTMax,
675 Handle(TColStd_HArray1OfReal) &theTKnots) const
677 Standard_Boolean isBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
679 if (myIsUseSpan && isBSpline) {
680 // Using span decomposition for BSpline.
681 Handle(TColStd_HArray1OfReal) aSurfKnots;
682 Standard_Integer aNbKnots;
684 // Get V knots of BSpline surface.
685 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
686 Handle(Geom_BSplineSurface) aBSplSurf;
688 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
689 aNbKnots = aBSplSurf->NbVKnots();
690 aSurfKnots = new TColStd_HArray1OfReal(1, aNbKnots);
691 aBSplSurf->VKnots(aSurfKnots->ChangeArray1());
693 // Handle(TColStd_HArray1OfReal) aCurveKnots;
695 // GetCurveKnots(theTMin, theTMax, myCurve, aCurveKnots);
696 // GetRealCurveKnots(aCurveKnots, aSurfKnots, myCurve, theTKnots);
697 GetCurveKnots(theTMin, theTMax, myCurve, theTKnots);
699 theTKnots = new TColStd_HArray1OfReal(1, 2);
700 theTKnots->SetValue(1, theTMin);
701 theTKnots->SetValue(2, theTMax);