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
7 // under the terms of the GNU Lesser General Public 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.
15 #include <BRepGProp_Face.ixx>
16 #include <BRep_Tool.hxx>
18 #include <GeomAdaptor_Surface.hxx>
19 #include <Geom_Surface.hxx>
20 #include <Geom_BezierSurface.hxx>
21 #include <Geom_BSplineSurface.hxx>
22 #include <Geom2d_BezierCurve.hxx>
23 #include <Geom2d_BSplineCurve.hxx>
25 #include <Bnd_Box2d.hxx>
26 #include <BndLib_Add2dCurve.hxx>
27 #include <GeomAdaptor_Curve.hxx>
28 #include <Geom_BSplineCurve.hxx>
29 #include <Precision.hxx>
30 #include <TColStd_SequenceOfReal.hxx>
31 #include <Geom_SurfaceOfLinearExtrusion.hxx>
32 #include <Geom2d_Line.hxx>
34 //=======================================================================
35 //function : UIntegrationOrder
37 //=======================================================================
39 Standard_Integer BRepGProp_Face::UIntegrationOrder() const {
42 switch (mySurface.GetType()) {
48 case GeomAbs_BezierSurface :
50 Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
54 case GeomAbs_BSplineSurface :
56 Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
57 Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots()-1;
69 //=======================================================================
70 //function : VIntegrationOrder
72 //=======================================================================
74 Standard_Integer BRepGProp_Face::VIntegrationOrder() const
77 switch (mySurface.GetType()) {
83 case GeomAbs_BezierSurface :
85 Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
90 case GeomAbs_BSplineSurface :
92 Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
93 Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots()-1;
105 //=======================================================================
106 //function : IntegrationOrder
108 //=======================================================================
110 Standard_Integer BRepGProp_Face::IntegrationOrder() const
114 switch (myCurve.GetType()) {
120 case GeomAbs_Circle :
121 case GeomAbs_Ellipse :
122 case GeomAbs_Hyperbola :
126 case GeomAbs_Parabola :
130 case GeomAbs_BezierCurve :
132 N = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree() + 1;
136 case GeomAbs_BSplineCurve :
138 Standard_Integer a = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree() + 1;
139 Standard_Integer b = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots() - 1;
152 //=======================================================================
155 //=======================================================================
157 void BRepGProp_Face::Bounds(Standard_Real& U1,
160 Standard_Real& V2)const
162 U1 = mySurface.FirstUParameter();
163 U2 = mySurface.LastUParameter();
164 V1 = mySurface.FirstVParameter();
165 V2 = mySurface.LastVParameter();
168 //=======================================================================
171 //=======================================================================
173 void BRepGProp_Face::Load(const TopoDS_Edge& E)
176 Handle(Geom2d_Curve) C =
177 BRep_Tool::CurveOnSurface(E, mySurface.Face(), a,b);
178 if (E.Orientation() == TopAbs_REVERSED) {
180 a = C->ReversedParameter(b);
181 b = C->ReversedParameter(x);
187 //=======================================================================
190 //=======================================================================
192 void BRepGProp_Face::Load(const TopoDS_Face& F)
194 TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);
195 mySurface.Initialize(TopoDS::Face(aLocalShape));
196 // mySurface.Initialize(TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
197 mySReverse = (F.Orientation() == TopAbs_REVERSED);
200 //=======================================================================
203 //=======================================================================
205 void BRepGProp_Face::Normal (const Standard_Real U,
206 const Standard_Real V,
211 mySurface.D1(U,V,P,D1U,D1V);
212 VNor = D1U.Crossed(D1V);
213 if (mySReverse) VNor.Reverse();
217 // APO 17.04.2002 (OCC104)
218 // This is functions that calculate coeff. to optimize "integration order".
219 //They had been produced experementally for some hard example.
220 static Standard_Real AS = -0.15, AL = -0.50, B = 1.0, C = 0.75, D = 0.25;
221 static inline Standard_Real SCoeff(const Standard_Real Eps){
222 return Eps < 0.1? AS*(B+Log10(Eps)) + C: C;
224 static inline Standard_Real LCoeff(const Standard_Real Eps){
225 return Eps < 0.1? AL*(B+Log10(Eps)) + D: D;
228 //=======================================================================
229 //function : SIntOrder
231 //=======================================================================
233 Standard_Integer BRepGProp_Face::SIntOrder(const Standard_Real Eps) const
235 Standard_Integer Nv, Nu;
236 switch (mySurface.GetType()) {
238 Nu = 1; Nv = 1; break;
239 case GeomAbs_Cylinder:
240 Nu = 2; Nv = 1; break;
242 Nu = 2; Nv = 1; break;
244 Nu = 2; Nv = 2; break;
246 Nu = 2; Nv = 2; break;
247 case GeomAbs_BezierSurface:
248 Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
249 Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
251 case GeomAbs_BSplineSurface:
252 Nv = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
253 Nu = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
256 Nu = 2; Nv = 2; break;
258 return Min(RealToInt(Ceiling(SCoeff(Eps)*Max((Nu+1),(Nv+1)))), math::GaussPointsMax());
261 //=======================================================================
262 //function : SUIntSubs
264 //=======================================================================
266 Standard_Integer BRepGProp_Face::SUIntSubs() const
269 switch (mySurface.GetType()) {
272 case GeomAbs_Cylinder:
280 case GeomAbs_BezierSurface:
282 case GeomAbs_BSplineSurface:
283 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots(); break;
290 //=======================================================================
291 //function : SVIntSubs
293 //=======================================================================
295 Standard_Integer BRepGProp_Face::SVIntSubs() const
298 switch (mySurface.GetType()) {
301 case GeomAbs_Cylinder:
309 case GeomAbs_BezierSurface:
311 case GeomAbs_BSplineSurface:
312 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots();
320 //=======================================================================
323 //=======================================================================
325 void BRepGProp_Face::UKnots(TColStd_Array1OfReal& Knots) const
327 switch (mySurface.GetType()) {
329 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
331 case GeomAbs_Cylinder:
335 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;
337 case GeomAbs_BSplineSurface:
338 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UKnots(Knots);
341 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
346 //=======================================================================
349 //=======================================================================
351 void BRepGProp_Face::VKnots(TColStd_Array1OfReal& Knots) const
353 switch (mySurface.GetType()) {
355 case GeomAbs_Cylinder:
357 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
360 Knots(1) = -M_PI/2.0; Knots(2) = 0.0; Knots(3) = +M_PI/2.0;
363 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;
365 case GeomAbs_BSplineSurface:
366 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VKnots(Knots);
369 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
374 //=======================================================================
375 //function : LIntOrder
377 //=======================================================================
379 Standard_Integer BRepGProp_Face::LIntOrder(const Standard_Real Eps) const
383 BndLib_Add2dCurve::Add(myCurve, 1.e-7, aBox);
384 Standard_Real aXmin, aXmax, aYmin, aYmax;
385 aBox.Get(aXmin, aYmin, aXmax, aYmax);
386 Standard_Real aVmin = mySurface.FirstVParameter();
387 Standard_Real aVmax = mySurface.LastVParameter();
389 Standard_Real anR = Min((aYmax-aYmin)/(aVmax-aVmin), 1.);
391 // Standard_Integer anRInt = Max(RealToInt(Ceiling(SVIntSubs()*anR)), 2);
392 Standard_Integer anRInt = RealToInt(Ceiling(SVIntSubs()*anR));
393 Standard_Integer aLSubs = LIntSubs();
396 // Standard_Real NL, NS = Max(SIntOrder(1.0)*anRInt/LIntSubs(), 1);
397 Standard_Real NL, NS = Max(SIntOrder(1.)*anRInt/aLSubs, 1);
398 switch (myCurve.GetType()) {
402 NL = 2 * 3; break; //correction for the spans of converted curve
403 case GeomAbs_Ellipse:
404 NL = 2 * 3; break; //
405 case GeomAbs_Parabola:
407 case GeomAbs_Hyperbola:
409 case GeomAbs_BezierCurve:
410 NL = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree();
412 case GeomAbs_BSplineCurve:
413 NL = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree();
421 Standard_Integer nn =
422 RealToInt (aLSubs <= 4 ? Ceiling(LCoeff(Eps)*(NL+1)) : NL+1);
424 //return Min(RealToInt(Ceiling(LCoeff(Eps)*(NL+1)*NS)), math::GaussPointsMax());
425 return Min(nn, math::GaussPointsMax());
428 //=======================================================================
429 //function : LIntSubs
431 //=======================================================================
433 Standard_Integer BRepGProp_Face::LIntSubs() const
436 switch (myCurve.GetType()) {
440 case GeomAbs_Ellipse:
442 case GeomAbs_Parabola:
443 case GeomAbs_Hyperbola:
445 case GeomAbs_BSplineCurve:
446 N = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots();
454 //=======================================================================
457 //=======================================================================
459 void BRepGProp_Face::LKnots(TColStd_Array1OfReal& Knots) const
461 switch (myCurve.GetType()) {
463 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
466 case GeomAbs_Ellipse:
467 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;
469 case GeomAbs_Parabola:
470 case GeomAbs_Hyperbola:
471 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
473 case GeomAbs_BSplineCurve:
474 (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Knots(Knots);
477 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
482 //=======================================================================
485 //=======================================================================
487 void BRepGProp_Face::Load(const Standard_Boolean IsFirstParam,
488 const GeomAbs_IsoType theIsoType)
498 Bounds(aU1, aU2, aV1, aV2);
500 if (theIsoType == GeomAbs_IsoU) {
504 aLoc.SetCoord(aU1, aV2);
505 aDir.SetCoord(0., -1.);
507 aLoc.SetCoord(aU2, aV1);
508 aDir.SetCoord(0., 1.);
510 } else if (theIsoType == GeomAbs_IsoV) {
514 aLoc.SetCoord(aU1, aV1);
515 aDir.SetCoord(1., 0.);
517 aLoc.SetCoord(aU2, aV2);
518 aDir.SetCoord(-1., 0.);
523 Handle(Geom2d_Curve) aLin = new Geom2d_Line(aLoc, aDir);
525 myCurve.Load(aLin, 0., aLen);
528 //=======================================================================
529 //function : GetRealKnots
531 //=======================================================================
533 static void GetRealKnots(const Standard_Real theMin,
534 const Standard_Real theMax,
535 const Handle(TColStd_HArray1OfReal) &theKnots,
536 Handle(TColStd_HArray1OfReal) &theRealKnots)
538 Standard_Integer i = theKnots->Lower() - 1;
539 Standard_Integer iU = theKnots->Upper();
540 Standard_Integer aStartI = 0;
541 Standard_Integer aEndI = 0;
542 Standard_Real aTol = Precision::Confusion();
545 if (aStartI == 0 && theKnots->Value(i) > theMin + aTol)
548 if (aEndI == 0 && theKnots->Value(i + 1) > theMax - aTol)
551 if (aStartI != 0 && aEndI != 0)
558 Standard_Integer aNbNode = Max(0, aEndI - aStartI + 1) + 2;
561 theRealKnots = new TColStd_HArray1OfReal(1, aNbNode);
562 theRealKnots->SetValue(1, theMin);
563 theRealKnots->SetValue(aNbNode, theMax);
566 for (i = 2, j = aStartI; j <= aEndI; i++, j++)
567 theRealKnots->SetValue(i, theKnots->Value(j));
570 //=======================================================================
571 //function : GetCurveKnots
573 //=======================================================================
575 static void GetCurveKnots(const Standard_Real theMin,
576 const Standard_Real theMax,
577 const Geom2dAdaptor_Curve &theCurve,
578 Handle(TColStd_HArray1OfReal) &theKnots)
580 Standard_Boolean isSBSpline = theCurve.GetType() == GeomAbs_BSplineCurve;
583 Handle(Geom2d_BSplineCurve) aCrv;
584 Standard_Integer aNbKnots;
585 Handle(TColStd_HArray1OfReal) aCrvKnots;
587 aCrv = Handle(Geom2d_BSplineCurve)::DownCast(theCurve.Curve());
588 aNbKnots = aCrv->NbKnots();
589 aCrvKnots = new TColStd_HArray1OfReal(1, aNbKnots);
590 aCrv->Knots(aCrvKnots->ChangeArray1());
591 GetRealKnots(theMin, theMax, aCrvKnots, theKnots);
593 theKnots = new TColStd_HArray1OfReal(1, 2);
594 theKnots->SetValue(1, theMin);
595 theKnots->SetValue(2, theMax);
599 //=======================================================================
600 //function : GetUKnots
602 //=======================================================================
604 void BRepGProp_Face::GetUKnots
605 (const Standard_Real theUMin,
606 const Standard_Real theUMax,
607 Handle(TColStd_HArray1OfReal) &theUKnots) const
609 Standard_Boolean isSBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
610 Standard_Boolean isCBSpline = Standard_False;
613 // Check the basis curve of the surface of linear extrusion.
614 if (mySurface.GetType() == GeomAbs_SurfaceOfExtrusion) {
615 GeomAdaptor_Curve aCurve;
616 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
618 aCurve.Load((*((Handle(Geom_SurfaceOfLinearExtrusion)*)&aSurf))->BasisCurve());
619 isCBSpline = aCurve.GetType() == GeomAbs_BSplineCurve;
623 if (myIsUseSpan && (isSBSpline || isCBSpline)) {
624 // Using span decomposition for BSpline.
625 Handle(TColStd_HArray1OfReal) aKnots;
626 Standard_Integer aNbKnots;
629 // Get U knots of BSpline surface.
630 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
631 Handle(Geom_BSplineSurface) aBSplSurf;
633 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
634 aNbKnots = aBSplSurf->NbUKnots();
635 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
636 aBSplSurf->UKnots(aKnots->ChangeArray1());
638 // Get U knots of BSpline curve - basis curve of
639 // the surface of linear extrusion.
640 GeomAdaptor_Curve aCurve;
641 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
642 Handle(Geom_BSplineCurve) aBSplCurve;
644 aCurve.Load((*((Handle(Geom_SurfaceOfLinearExtrusion)*)&aSurf))->BasisCurve());
645 aBSplCurve = aCurve.BSpline();
646 aNbKnots = aBSplCurve->NbKnots();
647 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
648 aBSplCurve->Knots(aKnots->ChangeArray1());
651 // Compute number of knots inside theUMin and theUMax.
652 GetRealKnots(theUMin, theUMax, aKnots, theUKnots);
654 // No span decomposition.
655 theUKnots = new TColStd_HArray1OfReal(1, 2);
656 theUKnots->SetValue(1, theUMin);
657 theUKnots->SetValue(2, theUMax);
661 //=======================================================================
662 //function : GetTKnots
664 //=======================================================================
666 void BRepGProp_Face::GetTKnots
667 (const Standard_Real theTMin,
668 const Standard_Real theTMax,
669 Handle(TColStd_HArray1OfReal) &theTKnots) const
671 Standard_Boolean isBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
673 if (myIsUseSpan && isBSpline) {
674 // Using span decomposition for BSpline.
675 Handle(TColStd_HArray1OfReal) aSurfKnots;
676 Standard_Integer aNbKnots;
678 // Get V knots of BSpline surface.
679 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
680 Handle(Geom_BSplineSurface) aBSplSurf;
682 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
683 aNbKnots = aBSplSurf->NbVKnots();
684 aSurfKnots = new TColStd_HArray1OfReal(1, aNbKnots);
685 aBSplSurf->VKnots(aSurfKnots->ChangeArray1());
687 // Handle(TColStd_HArray1OfReal) aCurveKnots;
689 // GetCurveKnots(theTMin, theTMax, myCurve, aCurveKnots);
690 // GetRealCurveKnots(aCurveKnots, aSurfKnots, myCurve, theTKnots);
691 GetCurveKnots(theTMin, theTMax, myCurve, theTKnots);
693 theTKnots = new TColStd_HArray1OfReal(1, 2);
694 theTKnots->SetValue(1, theTMin);
695 theTKnots->SetValue(2, theTMax);