1 #include <BRepGProp_Face.ixx>
2 #include <BRep_Tool.hxx>
4 #include <GeomAdaptor_Surface.hxx>
5 #include <Geom_Surface.hxx>
6 #include <Geom_BezierSurface.hxx>
7 #include <Geom_BSplineSurface.hxx>
8 #include <Geom2d_BezierCurve.hxx>
9 #include <Geom2d_BSplineCurve.hxx>
11 #include <Bnd_Box2d.hxx>
12 #include <BndLib_Add2dCurve.hxx>
13 #include <GeomAdaptor_Curve.hxx>
14 #include <Geom_BSplineCurve.hxx>
15 #include <Precision.hxx>
16 #include <TColStd_SequenceOfReal.hxx>
17 #include <Geom_SurfaceOfLinearExtrusion.hxx>
18 #include <Geom2d_Line.hxx>
20 //=======================================================================
21 //function : UIntegrationOrder
23 //=======================================================================
25 Standard_Integer BRepGProp_Face::UIntegrationOrder() const {
28 switch (mySurface.GetType()) {
34 case GeomAbs_BezierSurface :
36 Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
40 case GeomAbs_BSplineSurface :
42 Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
43 Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots()-1;
55 //=======================================================================
56 //function : VIntegrationOrder
58 //=======================================================================
60 Standard_Integer BRepGProp_Face::VIntegrationOrder() const
63 switch (mySurface.GetType()) {
69 case GeomAbs_BezierSurface :
71 Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
76 case GeomAbs_BSplineSurface :
78 Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
79 Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots()-1;
91 //=======================================================================
92 //function : IntegrationOrder
94 //=======================================================================
96 Standard_Integer BRepGProp_Face::IntegrationOrder() const
100 switch (myCurve.GetType()) {
106 case GeomAbs_Circle :
107 case GeomAbs_Ellipse :
108 case GeomAbs_Hyperbola :
112 case GeomAbs_Parabola :
116 case GeomAbs_BezierCurve :
118 N = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree() + 1;
122 case GeomAbs_BSplineCurve :
124 Standard_Integer a = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree() + 1;
125 Standard_Integer b = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots() - 1;
138 //=======================================================================
141 //=======================================================================
143 void BRepGProp_Face::Bounds(Standard_Real& U1,
146 Standard_Real& V2)const
148 U1 = mySurface.FirstUParameter();
149 U2 = mySurface.LastUParameter();
150 V1 = mySurface.FirstVParameter();
151 V2 = mySurface.LastVParameter();
154 //=======================================================================
157 //=======================================================================
159 void BRepGProp_Face::Load(const TopoDS_Edge& E)
162 Handle(Geom2d_Curve) C =
163 BRep_Tool::CurveOnSurface(E, mySurface.Face(), a,b);
164 if (E.Orientation() == TopAbs_REVERSED) {
166 a = C->ReversedParameter(b);
167 b = C->ReversedParameter(x);
173 //=======================================================================
176 //=======================================================================
178 void BRepGProp_Face::Load(const TopoDS_Face& F)
180 TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);
181 mySurface.Initialize(TopoDS::Face(aLocalShape));
182 // mySurface.Initialize(TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
183 mySReverse = (F.Orientation() == TopAbs_REVERSED);
186 //=======================================================================
189 //=======================================================================
191 void BRepGProp_Face::Normal (const Standard_Real U,
192 const Standard_Real V,
197 mySurface.D1(U,V,P,D1U,D1V);
198 VNor = D1U.Crossed(D1V);
199 if (mySReverse) VNor.Reverse();
203 // APO 17.04.2002 (OCC104)
204 // This is functions that calculate coeff. to optimize "integration order".
205 //They had been produced experementally for some hard example.
206 static Standard_Real AS = -0.15, AL = -0.50, B = 1.0, C = 0.75, D = 0.25;
207 static inline Standard_Real SCoeff(const Standard_Real Eps){
208 return Eps < 0.1? AS*(B+Log10(Eps)) + C: C;
210 static inline Standard_Real LCoeff(const Standard_Real Eps){
211 return Eps < 0.1? AL*(B+Log10(Eps)) + D: D;
214 //=======================================================================
215 //function : SIntOrder
217 //=======================================================================
219 Standard_Integer BRepGProp_Face::SIntOrder(const Standard_Real Eps) const
221 Standard_Integer Nv, Nu;
222 switch (mySurface.GetType()) {
224 Nu = 1; Nv = 1; break;
225 case GeomAbs_Cylinder:
226 Nu = 2; Nv = 1; break;
228 Nu = 2; Nv = 1; break;
230 Nu = 2; Nv = 2; break;
232 Nu = 2; Nv = 2; break;
233 case GeomAbs_BezierSurface:
234 Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
235 Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
237 case GeomAbs_BSplineSurface:
238 Nv = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
239 Nu = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
242 Nu = 2; Nv = 2; break;
244 return Min(RealToInt(Ceiling(SCoeff(Eps)*Max((Nu+1),(Nv+1)))), math::GaussPointsMax());
247 //=======================================================================
248 //function : SUIntSubs
250 //=======================================================================
252 Standard_Integer BRepGProp_Face::SUIntSubs() const
255 switch (mySurface.GetType()) {
258 case GeomAbs_Cylinder:
266 case GeomAbs_BezierSurface:
268 case GeomAbs_BSplineSurface:
269 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots(); break;
276 //=======================================================================
277 //function : SVIntSubs
279 //=======================================================================
281 Standard_Integer BRepGProp_Face::SVIntSubs() const
284 switch (mySurface.GetType()) {
287 case GeomAbs_Cylinder:
295 case GeomAbs_BezierSurface:
297 case GeomAbs_BSplineSurface:
298 N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots();
306 //=======================================================================
309 //=======================================================================
311 void BRepGProp_Face::UKnots(TColStd_Array1OfReal& Knots) const
313 switch (mySurface.GetType()) {
315 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
317 case GeomAbs_Cylinder:
321 Knots(1) = 0.0; Knots(2) = PI*2.0/3.0; Knots(3) = PI*4.0/3.0; Knots(4) = PI*6.0/3.0;
323 case GeomAbs_BSplineSurface:
324 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UKnots(Knots);
327 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
332 //=======================================================================
335 //=======================================================================
337 void BRepGProp_Face::VKnots(TColStd_Array1OfReal& Knots) const
339 switch (mySurface.GetType()) {
341 case GeomAbs_Cylinder:
343 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
346 Knots(1) = -PI/2.0; Knots(2) = 0.0; Knots(3) = +PI/2.0;
349 Knots(1) = 0.0; Knots(2) = PI*2.0/3.0; Knots(3) = PI*4.0/3.0; Knots(4) = PI*6.0/3.0;
351 case GeomAbs_BSplineSurface:
352 (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VKnots(Knots);
355 Knots(1) = mySurface.FirstUParameter(); Knots(2) = mySurface.LastUParameter();
360 //=======================================================================
361 //function : LIntOrder
363 //=======================================================================
365 Standard_Integer BRepGProp_Face::LIntOrder(const Standard_Real Eps) const
368 BndLib_Add2dCurve aB;
369 aB.Add(myCurve, 1.e-7, aBox);
370 Standard_Real aXmin, aXmax, aYmin, aYmax;
371 aBox.Get(aXmin, aYmin, aXmax, aYmax);
372 Standard_Real aVmin = mySurface.FirstVParameter();
373 Standard_Real aVmax = mySurface.LastVParameter();
375 Standard_Real anR = Min((aYmax-aYmin)/(aVmax-aVmin), 1.);
377 // Standard_Integer anRInt = Max(RealToInt(Ceiling(SVIntSubs()*anR)), 2);
378 Standard_Integer anRInt = RealToInt(Ceiling(SVIntSubs()*anR));
379 Standard_Integer aLSubs = LIntSubs();
382 // Standard_Real NL, NS = Max(SIntOrder(1.0)*anRInt/LIntSubs(), 1);
383 Standard_Real NL, NS = Max(SIntOrder(1.)*anRInt/aLSubs, 1);
384 switch (myCurve.GetType()) {
388 NL = 2 * 3; break; //correction for the spans of converted curve
389 case GeomAbs_Ellipse:
390 NL = 2 * 3; break; //
391 case GeomAbs_Parabola:
393 case GeomAbs_Hyperbola:
395 case GeomAbs_BezierCurve:
396 NL = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree();
398 case GeomAbs_BSplineCurve:
399 NL = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree();
407 Standard_Integer nn =
408 RealToInt (aLSubs <= 4 ? Ceiling(LCoeff(Eps)*(NL+1)) : NL+1);
410 //return Min(RealToInt(Ceiling(LCoeff(Eps)*(NL+1)*NS)), math::GaussPointsMax());
411 return Min(nn, math::GaussPointsMax());
414 //=======================================================================
415 //function : LIntSubs
417 //=======================================================================
419 Standard_Integer BRepGProp_Face::LIntSubs() const
422 switch (myCurve.GetType()) {
426 case GeomAbs_Ellipse:
428 case GeomAbs_Parabola:
429 case GeomAbs_Hyperbola:
431 case GeomAbs_BSplineCurve:
432 N = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots();
440 //=======================================================================
443 //=======================================================================
445 void BRepGProp_Face::LKnots(TColStd_Array1OfReal& Knots) const
447 switch (myCurve.GetType()) {
449 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
452 case GeomAbs_Ellipse:
453 Knots(1) = 0.0; Knots(2) = PI*2.0/3.0; Knots(3) = PI*4.0/3.0; Knots(2) = PI*6.0/3.0;
455 case GeomAbs_Parabola:
456 case GeomAbs_Hyperbola:
457 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
459 case GeomAbs_BSplineCurve:
460 (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Knots(Knots);
463 Knots(1) = myCurve.FirstParameter(); Knots(2) = myCurve.LastParameter();
468 //=======================================================================
471 //=======================================================================
473 void BRepGProp_Face::Load(const Standard_Boolean IsFirstParam,
474 const GeomAbs_IsoType theIsoType)
484 Bounds(aU1, aU2, aV1, aV2);
486 if (theIsoType == GeomAbs_IsoU) {
490 aLoc.SetCoord(aU1, aV2);
491 aDir.SetCoord(0., -1.);
493 aLoc.SetCoord(aU2, aV1);
494 aDir.SetCoord(0., 1.);
496 } else if (theIsoType == GeomAbs_IsoV) {
500 aLoc.SetCoord(aU1, aV1);
501 aDir.SetCoord(1., 0.);
503 aLoc.SetCoord(aU2, aV2);
504 aDir.SetCoord(-1., 0.);
509 Handle(Geom2d_Curve) aLin = new Geom2d_Line(aLoc, aDir);
511 myCurve.Load(aLin, 0., aLen);
514 //=======================================================================
515 //function : GetRealKnots
517 //=======================================================================
519 static void GetRealKnots(const Standard_Real theMin,
520 const Standard_Real theMax,
521 const Handle(TColStd_HArray1OfReal) &theKnots,
522 Handle(TColStd_HArray1OfReal) &theRealKnots)
524 Standard_Integer i = theKnots->Lower() - 1;
525 Standard_Integer iU = theKnots->Upper();
526 Standard_Integer aStartI = 0;
527 Standard_Integer aEndI = 0;
528 Standard_Real aTol = Precision::Confusion();
531 if (aStartI == 0 && theKnots->Value(i) > theMin + aTol)
534 if (aEndI == 0 && theKnots->Value(i + 1) > theMax - aTol)
537 if (aStartI != 0 && aEndI != 0)
544 Standard_Integer aNbNode = Max(0, aEndI - aStartI + 1) + 2;
547 theRealKnots = new TColStd_HArray1OfReal(1, aNbNode);
548 theRealKnots->SetValue(1, theMin);
549 theRealKnots->SetValue(aNbNode, theMax);
552 for (i = 2, j = aStartI; j <= aEndI; i++, j++)
553 theRealKnots->SetValue(i, theKnots->Value(j));
556 //=======================================================================
557 //function : GetCurveKnots
559 //=======================================================================
561 static void GetCurveKnots(const Standard_Real theMin,
562 const Standard_Real theMax,
563 const Geom2dAdaptor_Curve &theCurve,
564 Handle(TColStd_HArray1OfReal) &theKnots)
566 Standard_Boolean isSBSpline = theCurve.GetType() == GeomAbs_BSplineCurve;
569 Handle(Geom2d_BSplineCurve) aCrv;
570 Standard_Integer aNbKnots;
571 Handle(TColStd_HArray1OfReal) aCrvKnots;
573 aCrv = Handle(Geom2d_BSplineCurve)::DownCast(theCurve.Curve());
574 aNbKnots = aCrv->NbKnots();
575 aCrvKnots = new TColStd_HArray1OfReal(1, aNbKnots);
576 aCrv->Knots(aCrvKnots->ChangeArray1());
577 GetRealKnots(theMin, theMax, aCrvKnots, theKnots);
579 theKnots = new TColStd_HArray1OfReal(1, 2);
580 theKnots->SetValue(1, theMin);
581 theKnots->SetValue(2, theMax);
585 //=======================================================================
586 //function : GetIntervalNbr
588 //=======================================================================
590 static Standard_Integer GetIntervalNbr
591 (const Standard_Real theParam,
592 const Handle(TColStd_HArray1OfReal) &theSurfKnots,
593 const Standard_Integer theIndStart,
594 const Standard_Integer theIndEnd)
597 Standard_Real aTol = Precision::Confusion();
599 for (i = theIndStart + 1; i < theIndEnd; i++) {
600 if (theSurfKnots->Value(i) > theParam + aTol)
604 return Min(theIndStart, theIndEnd - 1);
607 //=======================================================================
608 //function : GetRealCurveKnots
610 //=======================================================================
612 static void GetRealCurveKnots
613 (const Handle(TColStd_HArray1OfReal) &theCurveKnots,
614 const Handle(TColStd_HArray1OfReal) &theSurfKnots,
615 const Geom2dAdaptor_Curve &theCurve,
616 Handle(TColStd_HArray1OfReal) &theTKnots)
618 Standard_Integer i = theCurveKnots->Lower();
619 Standard_Integer iU = theCurveKnots->Upper();
620 Standard_Integer aNbIntPnt = 23;
621 TColStd_SequenceOfReal aSeqKnot;
622 Standard_Real aTol = Precision::Confusion();
623 Standard_Real aTParam;
626 Standard_Real aT1 = theCurveKnots->Value(i++);
627 Standard_Real aT2 = theCurveKnots->Value(i);
628 Standard_Real aStep = (aT2 - aT1)/(aNbIntPnt + 1.);
632 Standard_Integer aSurfLInd = theSurfKnots->Lower();
633 Standard_Integer aSurfUInd = theSurfKnots->Upper();
634 Standard_Integer anIntrvlInd;
635 Standard_Real aTParamOld;
636 Standard_Real aVParam;
637 Standard_Real aVParamOld;
638 Standard_Real aDiffOld;
642 // Append the first curve knot of each interval in the sequence of knots.
643 aSeqKnot.Append(aT1);
646 theCurve.D0(aTParamOld, aValue);
647 aVParamOld = aValue.Y();
648 anIntrvlInd = GetIntervalNbr(aVParamOld, theSurfKnots,
649 aSurfLInd, aSurfUInd);
650 aDiffOld = Min(Abs(aVParamOld - theSurfKnots->Value(anIntrvlInd)),
651 Abs(aVParamOld - theSurfKnots->Value(anIntrvlInd + 1)));
653 for (j = 1; j <= aNbIntPnt; j++) {
654 aTParam = aT1 + j*aStep;
655 theCurve.D1(aTParam, aValue, aDir);
656 aVParam = aValue.Y();
657 aDiff = Min(Abs(aVParam - theSurfKnots->Value(anIntrvlInd)),
658 Abs(aVParam - theSurfKnots->Value(anIntrvlInd + 1)));
660 // Skip points if the curve goes along V isoline.
661 if (Abs(aDir.Y()) > aTol) {
662 Standard_Boolean isLower =
663 (aVParam - aTol < theSurfKnots->Value(anIntrvlInd));
664 Standard_Boolean isUpper =
665 (aVParam + aTol > theSurfKnots->Value(anIntrvlInd + 1));
667 if (isLower || isUpper) {
669 aSurfLInd = theSurfKnots->Lower();
670 aSurfUInd = anIntrvlInd - 1;
671 } else if (isUpper) {
672 aSurfLInd = anIntrvlInd + 1;
673 aSurfUInd = theSurfKnots->Upper();
676 // The V interval is changed. Find new interval.
677 anIntrvlInd = GetIntervalNbr(aVParam, theSurfKnots,
678 aSurfLInd, aSurfUInd);
680 // Add the value that is closer to surface knots.
681 // Check if the previous value is already added.
682 if (aDiff < aDiffOld)
683 aSeqKnot.Append(aTParam);
684 else if (Abs(aSeqKnot.Last() - aTParamOld) > aTol)
685 aSeqKnot.Append(aTParamOld);
689 // Prepare data for the next iteration.
690 aTParamOld = aTParam;
691 aVParamOld = aVParam;
696 // Add the last curve knot to the sequence.
697 aSeqKnot.Append(theCurveKnots->Value(iU));
699 // Fill the array of knots.
700 Standard_Integer aKnotsLen = aSeqKnot.Length();
702 theTKnots = new TColStd_HArray1OfReal(1, aKnotsLen);
704 for (i = 1; i <= aKnotsLen; i++) {
705 aTParam = aSeqKnot.Value(i);
706 theTKnots->SetValue(i, aTParam);
710 //=======================================================================
711 //function : GetUKnots
713 //=======================================================================
715 void BRepGProp_Face::GetUKnots
716 (const Standard_Real theUMin,
717 const Standard_Real theUMax,
718 Handle(TColStd_HArray1OfReal) &theUKnots) const
720 Standard_Boolean isSBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
721 Standard_Boolean isCBSpline = Standard_False;
724 // Check the basis curve of the surface of linear extrusion.
725 if (mySurface.GetType() == GeomAbs_SurfaceOfExtrusion) {
726 GeomAdaptor_Curve aCurve;
727 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
729 aCurve.Load((*((Handle(Geom_SurfaceOfLinearExtrusion)*)&aSurf))->BasisCurve());
730 isCBSpline = aCurve.GetType() == GeomAbs_BSplineCurve;
734 if (myIsUseSpan && (isSBSpline || isCBSpline)) {
735 // Using span decomposition for BSpline.
736 Handle(TColStd_HArray1OfReal) aKnots;
737 Standard_Integer aNbKnots;
740 // Get U knots of BSpline surface.
741 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
742 Handle(Geom_BSplineSurface) aBSplSurf;
744 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
745 aNbKnots = aBSplSurf->NbUKnots();
746 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
747 aBSplSurf->UKnots(aKnots->ChangeArray1());
749 // Get U knots of BSpline curve - basis curve of
750 // the surface of linear extrusion.
751 GeomAdaptor_Curve aCurve;
752 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
753 Handle(Geom_BSplineCurve) aBSplCurve;
755 aCurve.Load((*((Handle(Geom_SurfaceOfLinearExtrusion)*)&aSurf))->BasisCurve());
756 aBSplCurve = aCurve.BSpline();
757 aNbKnots = aBSplCurve->NbKnots();
758 aKnots = new TColStd_HArray1OfReal(1, aNbKnots);
759 aBSplCurve->Knots(aKnots->ChangeArray1());
762 // Compute number of knots inside theUMin and theUMax.
763 GetRealKnots(theUMin, theUMax, aKnots, theUKnots);
765 // No span decomposition.
766 theUKnots = new TColStd_HArray1OfReal(1, 2);
767 theUKnots->SetValue(1, theUMin);
768 theUKnots->SetValue(2, theUMax);
772 //=======================================================================
773 //function : GetTKnots
775 //=======================================================================
777 void BRepGProp_Face::GetTKnots
778 (const Standard_Real theTMin,
779 const Standard_Real theTMax,
780 Handle(TColStd_HArray1OfReal) &theTKnots) const
782 Standard_Boolean isBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
784 if (myIsUseSpan && isBSpline) {
785 // Using span decomposition for BSpline.
786 Handle(TColStd_HArray1OfReal) aSurfKnots;
787 Standard_Integer aNbKnots;
789 // Get V knots of BSpline surface.
790 Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
791 Handle(Geom_BSplineSurface) aBSplSurf;
793 aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
794 aNbKnots = aBSplSurf->NbVKnots();
795 aSurfKnots = new TColStd_HArray1OfReal(1, aNbKnots);
796 aBSplSurf->VKnots(aSurfKnots->ChangeArray1());
798 // Handle(TColStd_HArray1OfReal) aCurveKnots;
800 // GetCurveKnots(theTMin, theTMax, myCurve, aCurveKnots);
801 // GetRealCurveKnots(aCurveKnots, aSurfKnots, myCurve, theTKnots);
802 GetCurveKnots(theTMin, theTMax, myCurve, theTKnots);
804 theTKnots = new TColStd_HArray1OfReal(1, 2);
805 theTKnots->SetValue(1, theTMin);
806 theTKnots->SetValue(2, theTMax);