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 //=======================================================================
38 //function : UIntegrationOrder
40 //=======================================================================
41 Standard_Integer BRepGProp_Face::UIntegrationOrder() const {
44 switch (mySurface.GetType())
51 case GeomAbs_BezierSurface :
53 Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
57 case GeomAbs_BSplineSurface :
59 Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
60 Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots()-1;
72 //=======================================================================
73 //function : VIntegrationOrder
75 //=======================================================================
77 Standard_Integer BRepGProp_Face::VIntegrationOrder() const
80 switch (mySurface.GetType()) {
86 case GeomAbs_BezierSurface :
88 Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
93 case GeomAbs_BSplineSurface :
95 Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
96 Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots()-1;
108 //=======================================================================
109 //function : IntegrationOrder
111 //=======================================================================
113 Standard_Integer BRepGProp_Face::IntegrationOrder() const
117 switch (myCurve.GetType()) {
123 case GeomAbs_Circle :
124 case GeomAbs_Ellipse :
125 case GeomAbs_Hyperbola :
129 case GeomAbs_Parabola :
133 case GeomAbs_BezierCurve :
135 N = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree() + 1;
139 case GeomAbs_BSplineCurve :
141 Standard_Integer a = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree() + 1;
142 Standard_Integer b = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots() - 1;
155 //=======================================================================
158 //=======================================================================
160 void BRepGProp_Face::Bounds(Standard_Real& U1,
163 Standard_Real& V2)const
165 U1 = mySurface.FirstUParameter();
166 U2 = mySurface.LastUParameter();
167 V1 = mySurface.FirstVParameter();
168 V2 = mySurface.LastVParameter();
171 //=======================================================================
174 //=======================================================================
176 void BRepGProp_Face::Load(const TopoDS_Edge& E)
179 Handle(Geom2d_Curve) C =
180 BRep_Tool::CurveOnSurface(E, mySurface.Face(), a,b);
181 if (E.Orientation() == TopAbs_REVERSED) {
183 a = C->ReversedParameter(b);
184 b = C->ReversedParameter(x);
190 //=======================================================================
193 //=======================================================================
195 void BRepGProp_Face::Load(const TopoDS_Face& F)
197 TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);
198 mySurface.Initialize(TopoDS::Face(aLocalShape));
199 // mySurface.Initialize(TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
200 mySReverse = (F.Orientation() == TopAbs_REVERSED);
203 //=======================================================================
206 //=======================================================================
208 void BRepGProp_Face::Normal (const Standard_Real U,
209 const Standard_Real V,
214 mySurface.D1(U,V,P,D1U,D1V);
215 VNor = D1U.Crossed(D1V);
216 if (mySReverse) VNor.Reverse();
220 // APO 17.04.2002 (OCC104)
221 // This is functions that calculate coeff. to optimize "integration order".
222 //They had been produced experementally for some hard example.
223 static Standard_Real AS = -0.15, AL = -0.50, B = 1.0, C = 0.75, D = 0.25;
224 static inline Standard_Real SCoeff(const Standard_Real Eps){
225 return Eps < 0.1? AS*(B+Log10(Eps)) + C: C;
227 static inline Standard_Real LCoeff(const Standard_Real Eps){
228 return Eps < 0.1? AL*(B+Log10(Eps)) + D: D;
231 //=======================================================================
232 //function : SIntOrder
234 //=======================================================================
236 Standard_Integer BRepGProp_Face::SIntOrder(const Standard_Real Eps) const
238 Standard_Integer Nv, Nu;
239 switch (mySurface.GetType()) {
241 Nu = 1; Nv = 1; break;
242 case GeomAbs_Cylinder:
243 Nu = 2; Nv = 1; break;
245 Nu = 2; Nv = 1; break;
247 Nu = 2; Nv = 2; break;
249 Nu = 2; Nv = 2; break;
250 case GeomAbs_BezierSurface:
251 Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
252 Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
254 case GeomAbs_BSplineSurface:
255 Nv = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
256 Nu = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
259 Nu = 2; Nv = 2; break;
261 return Min(RealToInt(Ceiling(SCoeff(Eps)*Max((Nu+1),(Nv+1)))), math::GaussPointsMax());
264 //=======================================================================
265 //function : SUIntSubs
267 //=======================================================================
269 Standard_Integer BRepGProp_Face::SUIntSubs() const
272 switch (mySurface.GetType()) {
275 case GeomAbs_Cylinder:
283 case GeomAbs_BezierSurface:
285 case GeomAbs_BSplineSurface:
286 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots(); break;
293 //=======================================================================
294 //function : SVIntSubs
296 //=======================================================================
298 Standard_Integer BRepGProp_Face::SVIntSubs() const
301 switch (mySurface.GetType()) {
304 case GeomAbs_Cylinder:
312 case GeomAbs_BezierSurface:
314 case GeomAbs_BSplineSurface:
315 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots();
323 //=======================================================================
326 //=======================================================================
328 void BRepGProp_Face::UKnots(TColStd_Array1OfReal& Knots) const
330 switch (mySurface.GetType()) {
332 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
334 case GeomAbs_Cylinder:
338 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;
340 case GeomAbs_BSplineSurface:
341 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UKnots(Knots);
344 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
349 //=======================================================================
352 //=======================================================================
354 void BRepGProp_Face::VKnots(TColStd_Array1OfReal& Knots) const
356 switch (mySurface.GetType()) {
358 case GeomAbs_Cylinder:
360 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
363 Knots(1) = -M_PI/2.0; Knots(2) = 0.0; Knots(3) = +M_PI/2.0;
366 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;
368 case GeomAbs_BSplineSurface:
369 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VKnots(Knots);
372 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
377 //=======================================================================
378 //function : LIntOrder
380 //=======================================================================
382 Standard_Integer BRepGProp_Face::LIntOrder(const Standard_Real Eps) const
386 BndLib_Add2dCurve::Add(myCurve, 1.e-7, aBox);
387 Standard_Real aXmin, aXmax, aYmin, aYmax;
388 aBox.Get(aXmin, aYmin, aXmax, aYmax);
389 Standard_Real aVmin = mySurface.FirstVParameter();
390 Standard_Real aVmax = mySurface.LastVParameter();
392 Standard_Real anR = Min((aYmax-aYmin)/(aVmax-aVmin), 1.);
394 // Standard_Integer anRInt = Max(RealToInt(Ceiling(SVIntSubs()*anR)), 2);
395 Standard_Integer anRInt = RealToInt(Ceiling(SVIntSubs()*anR));
396 Standard_Integer aLSubs = LIntSubs();
399 // Standard_Real NL, NS = Max(SIntOrder(1.0)*anRInt/LIntSubs(), 1);
400 Standard_Real NL, NS = Max(SIntOrder(1.)*anRInt/aLSubs, 1);
401 switch (myCurve.GetType()) {
405 NL = 2 * 3; break; //correction for the spans of converted curve
406 case GeomAbs_Ellipse:
407 NL = 2 * 3; break; //
408 case GeomAbs_Parabola:
410 case GeomAbs_Hyperbola:
412 case GeomAbs_BezierCurve:
413 NL = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree();
415 case GeomAbs_BSplineCurve:
416 NL = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree();
424 Standard_Integer nn =
425 RealToInt (aLSubs <= 4 ? Ceiling(LCoeff(Eps)*(NL+1)) : NL+1);
427 //return Min(RealToInt(Ceiling(LCoeff(Eps)*(NL+1)*NS)), math::GaussPointsMax());
428 return Min(nn, math::GaussPointsMax());
431 //=======================================================================
432 //function : LIntSubs
434 //=======================================================================
436 Standard_Integer BRepGProp_Face::LIntSubs() const
439 switch (myCurve.GetType()) {
443 case GeomAbs_Ellipse:
445 case GeomAbs_Parabola:
446 case GeomAbs_Hyperbola:
448 case GeomAbs_BSplineCurve:
449 N = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots();
457 //=======================================================================
460 //=======================================================================
462 void BRepGProp_Face::LKnots(TColStd_Array1OfReal& Knots) const
464 switch (myCurve.GetType()) {
466 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
469 case GeomAbs_Ellipse:
470 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;
472 case GeomAbs_Parabola:
473 case GeomAbs_Hyperbola:
474 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
476 case GeomAbs_BSplineCurve:
477 (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Knots(Knots);
480 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
485 //=======================================================================
488 //=======================================================================
490 void BRepGProp_Face::Load(const Standard_Boolean IsFirstParam,
491 const GeomAbs_IsoType theIsoType)
501 Bounds(aU1, aU2, aV1, aV2);
503 if (theIsoType == GeomAbs_IsoU) {
507 aLoc.SetCoord(aU1, aV2);
508 aDir.SetCoord(0., -1.);
510 aLoc.SetCoord(aU2, aV1);
511 aDir.SetCoord(0., 1.);
513 } else if (theIsoType == GeomAbs_IsoV) {
517 aLoc.SetCoord(aU1, aV1);
518 aDir.SetCoord(1., 0.);
520 aLoc.SetCoord(aU2, aV2);
521 aDir.SetCoord(-1., 0.);
526 Handle(Geom2d_Curve) aLin = new Geom2d_Line(aLoc, aDir);
528 myCurve.Load(aLin, 0., aLen);
531 //=======================================================================
532 //function : GetRealKnots
534 //=======================================================================
536 static void GetRealKnots(const Standard_Real theMin,
537 const Standard_Real theMax,
538 const Handle(TColStd_HArray1OfReal) &theKnots,
539 Handle(TColStd_HArray1OfReal) &theRealKnots)
541 Standard_Integer i = theKnots->Lower() - 1;
542 Standard_Integer iU = theKnots->Upper();
543 Standard_Integer aStartI = 0;
544 Standard_Integer aEndI = 0;
545 Standard_Real aTol = Precision::Confusion();
548 if (aStartI == 0 && theKnots->Value(i) > theMin + aTol)
551 if (aEndI == 0 && theKnots->Value(i + 1) > theMax - aTol)
554 if (aStartI != 0 && aEndI != 0)
561 Standard_Integer aNbNode = Max(0, aEndI - aStartI + 1) + 2;
564 theRealKnots = new TColStd_HArray1OfReal(1, aNbNode);
565 theRealKnots->SetValue(1, theMin);
566 theRealKnots->SetValue(aNbNode, theMax);
569 for (i = 2, j = aStartI; j <= aEndI; i++, j++)
570 theRealKnots->SetValue(i, theKnots->Value(j));
573 //=======================================================================
574 //function : GetCurveKnots
576 //=======================================================================
578 static void GetCurveKnots(const Standard_Real theMin,
579 const Standard_Real theMax,
580 const Geom2dAdaptor_Curve &theCurve,
581 Handle(TColStd_HArray1OfReal) &theKnots)
583 Standard_Boolean isSBSpline = theCurve.GetType() == GeomAbs_BSplineCurve;
586 Handle(Geom2d_BSplineCurve) aCrv;
587 Standard_Integer aNbKnots;
588 Handle(TColStd_HArray1OfReal) aCrvKnots;
590 aCrv = Handle(Geom2d_BSplineCurve)::DownCast(theCurve.Curve());
591 aNbKnots = aCrv->NbKnots();
592 aCrvKnots = new TColStd_HArray1OfReal(1, aNbKnots);
593 aCrv->Knots(aCrvKnots->ChangeArray1());
594 GetRealKnots(theMin, theMax, aCrvKnots, theKnots);
596 theKnots = new TColStd_HArray1OfReal(1, 2);
597 theKnots->SetValue(1, theMin);
598 theKnots->SetValue(2, theMax);
602 //=======================================================================
603 //function : GetUKnots
605 //=======================================================================
607 void BRepGProp_Face::GetUKnots
608 (const Standard_Real theUMin,
609 const Standard_Real theUMax,
610 Handle(TColStd_HArray1OfReal) &theUKnots) const
612 Standard_Boolean isSBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
613 Standard_Boolean isCBSpline = Standard_False;
616 // Check the basis curve of the surface of linear extrusion.
617 if (mySurface.GetType() == GeomAbs_SurfaceOfExtrusion) {
618 GeomAdaptor_Curve aCurve;
619 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
621 aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
622 isCBSpline = aCurve.GetType() == GeomAbs_BSplineCurve;
626 if (myIsUseSpan && (isSBSpline || isCBSpline)) {
627 // Using span decomposition for BSpline.
628 Handle(TColStd_HArray1OfReal) aKnots;
629 Standard_Integer aNbKnots;
632 // Get U knots of BSpline surface.
633 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
634 Handle(Geom_BSplineSurface) aBSplSurf;
636 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
637 aNbKnots = aBSplSurf->NbUKnots();
638 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
639 aBSplSurf->UKnots(aKnots->ChangeArray1());
641 // Get U knots of BSpline curve - basis curve of
642 // the surface of linear extrusion.
643 GeomAdaptor_Curve aCurve;
644 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
645 Handle(Geom_BSplineCurve) aBSplCurve;
647 aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
648 aBSplCurve = aCurve.BSpline();
649 aNbKnots = aBSplCurve->NbKnots();
650 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
651 aBSplCurve->Knots(aKnots->ChangeArray1());
654 // Compute number of knots inside theUMin and theUMax.
655 GetRealKnots(theUMin, theUMax, aKnots, theUKnots);
657 // No span decomposition.
658 theUKnots = new TColStd_HArray1OfReal(1, 2);
659 theUKnots->SetValue(1, theUMin);
660 theUKnots->SetValue(2, theUMax);
664 //=======================================================================
665 //function : GetTKnots
667 //=======================================================================
669 void BRepGProp_Face::GetTKnots
670 (const Standard_Real theTMin,
671 const Standard_Real theTMax,
672 Handle(TColStd_HArray1OfReal) &theTKnots) const
674 Standard_Boolean isBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
676 if (myIsUseSpan && isBSpline) {
677 // Using span decomposition for BSpline.
678 Handle(TColStd_HArray1OfReal) aSurfKnots;
679 Standard_Integer aNbKnots;
681 // Get V knots of BSpline surface.
682 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
683 Handle(Geom_BSplineSurface) aBSplSurf;
685 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
686 aNbKnots = aBSplSurf->NbVKnots();
687 aSurfKnots = new TColStd_HArray1OfReal(1, aNbKnots);
688 aBSplSurf->VKnots(aSurfKnots->ChangeArray1());
690 // Handle(TColStd_HArray1OfReal) aCurveKnots;
692 // GetCurveKnots(theTMin, theTMax, myCurve, aCurveKnots);
693 // GetRealCurveKnots(aCurveKnots, aSurfKnots, myCurve, theTKnots);
694 GetCurveKnots(theTMin, theTMax, myCurve, theTKnots);
696 theTKnots = new TColStd_HArray1OfReal(1, 2);
697 theTKnots->SetValue(1, theTMin);
698 theTKnots->SetValue(2, theTMax);