From 763931a9f84c388353c852a0d69e2a3b432c5d1d Mon Sep 17 00:00:00 2001 From: Pasukhin Dmitry Date: Sat, 7 Mar 2026 12:44:06 +0000 Subject: [PATCH] Modeling - Cache transformed surfaces and update fillet/grid evaluators (#1147) Refactor transformed-surface handling to avoid repeated transformations, remove mutable surface access patterns, and align dependent code paths. - Add cached transformed data in GeomAdaptor_TransformedSurface and rebuild it on ctor/Load/SetTrsf. - Add explicit original/transformed surface accessors and deprecate legacy GeomSurface() usage. - Preserve transformed cache state in BRepAdaptor_Surface shallow copy/initialization. - Expose GeomAdaptor_Surface::ToleranceU()/ToleranceV() and use them in bounded-surface reload. - Rework ChFi3d bounded surface helper to support both GeomAdaptor_Surface and BRepAdaptor_Surface. - Replace ChangeSurface()-based usages in fillet code with const surface access. - Add and register GeomAdaptor_TransformedSurface GTests. --- ...mlConverter_WFDeflectionRestrictedFace.cxx | 2 +- src/Draw/TKDCAF/DrawDim/DrawDim_Radius.cxx | 4 +- .../TKBO/BOPAlgo/BOPAlgo_WireSplitter_1.cxx | 25 +- .../TKBO/BOPTools/BOPTools_AlgoTools2D.cxx | 3 +- .../IntTools/IntTools_BeanFaceIntersector.cxx | 17 +- .../TopOpeBRep_EdgesIntersector_1.cxx | 9 +- .../TopOpeBRepTool_ShapeTool.cxx | 9 +- .../TKFillet/ChFi3d/ChFi3d_Builder_0.cxx | 189 +++++++---- .../TKFillet/ChFi3d/ChFi3d_Builder_C1.cxx | 7 +- .../TKFillet/ChFi3d/ChFi3d_ChBuilder_C3.cxx | 5 +- .../TKFillet/ChFi3d/ChFi3d_FilBuilder_C3.cxx | 5 +- .../BRepMesh_DefaultRangeSplitter.cxx | 2 +- ...Mesh_DelaunayDeflectionControlMeshAlgo.hxx | 2 +- .../BRepMesh/BRepMesh_NURBSRangeSplitter.cxx | 6 +- .../TKTopAlgo/BRepBndLib/BRepBndLib_1.cxx | 2 +- .../TKTopAlgo/BRepGProp/BRepGProp_Face.cxx | 40 +-- .../TKTopAlgo/BRepLib/BRepLib.cxx | 3 +- .../BRepAdaptor/BRepAdaptor_Surface.cxx | 12 +- .../BRepAdaptor/BRepAdaptor_Surface.hxx | 1 - src/ModelingData/TKG3d/GTests/FILES.cmake | 1 + .../GeomAdaptor_TransformedSurface_Test.cxx | 300 ++++++++++++++++++ .../TKG3d/GeomAdaptor/GeomAdaptor_Surface.cxx | 86 ++--- .../TKG3d/GeomAdaptor/GeomAdaptor_Surface.hxx | 6 + .../GeomAdaptor_TransformedSurface.cxx | 205 ++++++++++-- .../GeomAdaptor_TransformedSurface.hxx | 75 ++++- .../GeomGridEval/GeomGridEval_Surface.cxx | 2 +- src/Visualization/TKV3d/PrsDim/PrsDim.cxx | 4 +- .../TKV3d/StdPrs/StdPrs_WFRestrictedFace.cxx | 8 +- 28 files changed, 780 insertions(+), 250 deletions(-) create mode 100644 src/ModelingData/TKG3d/GTests/GeomAdaptor_TransformedSurface_Test.cxx diff --git a/src/DataExchange/TKDEVRML/VrmlConverter/VrmlConverter_WFDeflectionRestrictedFace.cxx b/src/DataExchange/TKDEVRML/VrmlConverter/VrmlConverter_WFDeflectionRestrictedFace.cxx index a923101949..16899d1f56 100644 --- a/src/DataExchange/TKDEVRML/VrmlConverter/VrmlConverter_WFDeflectionRestrictedFace.cxx +++ b/src/DataExchange/TKDEVRML/VrmlConverter/VrmlConverter_WFDeflectionRestrictedFace.cxx @@ -39,7 +39,7 @@ static double GetDeflection(const occ::handle& aFace, if (aDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE) // TOD_RELATIVE, TOD_ABSOLUTE { Bnd_Box box; - BndLib_AddSurface::Add(aFace->Surface(), Precision::Confusion(), box); + BndLib_AddSurface::Add(*aFace, Precision::Confusion(), box); double Xmin, Xmax, Ymin, Ymax, Zmin, Zmax, diagonal; box.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); diff --git a/src/Draw/TKDCAF/DrawDim/DrawDim_Radius.cxx b/src/Draw/TKDCAF/DrawDim/DrawDim_Radius.cxx index c971d5f367..f369f549d5 100644 --- a/src/Draw/TKDCAF/DrawDim/DrawDim_Radius.cxx +++ b/src/Draw/TKDCAF/DrawDim/DrawDim_Radius.cxx @@ -80,8 +80,8 @@ void DrawDim_Radius::DrawOn(Draw_Display& dis) const double vMoy = (vFirst + vLast) / 2; gp_Pnt curpos; surfAlgo.D0(uMoy, vMoy, curpos); - const occ::handle& surf = surfAlgo.Surface().Surface(); - occ::handle aCurve; + const occ::handle surf = surfAlgo.GeomSurfaceTransformed(); + occ::handle aCurve; if (surf->DynamicType() == STANDARD_TYPE(Geom_ToroidalSurface)) { aCurve = surf->UIso(uMoy); diff --git a/src/ModelingAlgorithms/TKBO/BOPAlgo/BOPAlgo_WireSplitter_1.cxx b/src/ModelingAlgorithms/TKBO/BOPAlgo/BOPAlgo_WireSplitter_1.cxx index e3d38c574c..7794b7f436 100644 --- a/src/ModelingAlgorithms/TKBO/BOPAlgo/BOPAlgo_WireSplitter_1.cxx +++ b/src/ModelingAlgorithms/TKBO/BOPAlgo/BOPAlgo_WireSplitter_1.cxx @@ -52,7 +52,7 @@ static double Angle(const gp_Dir2d& aDir2D); static double Angle2D(const TopoDS_Vertex& aV, const TopoDS_Edge& anEdge, const TopoDS_Face& myFace, - const GeomAdaptor_Surface& aGAS, + const BRepAdaptor_Surface& aGAS, const bool aFlag, const occ::handle& theContext); @@ -68,7 +68,7 @@ static gp_Pnt2d Coord2d(const TopoDS_Vertex& aV1, const TopoDS_Edge& aE1, const static double ClockWiseAngle(const double aAngleIn, const double aAngleOut); -static void Path(const GeomAdaptor_Surface& aGAS, +static void Path(const BRepAdaptor_Surface& aGAS, const TopoDS_Face& myFace, const MyDataMapOfShapeBoolean& aVertMap, const TopoDS_Vertex& aVa, @@ -84,10 +84,10 @@ static void Path(const GeomAdaptor_Surface& aGAS, static double Angle(const gp_Dir2d& aDir2D); -static double Tolerance2D(const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS); +static double Tolerance2D(const TopoDS_Vertex& aV, const BRepAdaptor_Surface& aGAS); -static double UTolerance2D(const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS); -static double VTolerance2D(const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS); +static double UTolerance2D(const TopoDS_Vertex& aV, const BRepAdaptor_Surface& aGAS); +static double VTolerance2D(const TopoDS_Vertex& aV, const BRepAdaptor_Surface& aGAS); static void RefineAngles(const TopoDS_Face& myFace, NCollection_IndexedDataMapSurfaceAdaptor(myFace); - const GeomAdaptor_Surface& aGAS = aBAS.Surface(); // for (i = 1; i <= aNb; i++) { @@ -313,7 +312,7 @@ void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFac bIsIN = aEI.IsIn(); aOr = bIsIN ? TopAbs_REVERSED : TopAbs_FORWARD; aVV.Orientation(aOr); - aAngle = Angle2D(aVV, aE, myFace, aGAS, bIsIN, theContext); + aAngle = Angle2D(aVV, aE, myFace, aBAS, bIsIN, theContext); aEI.SetAngle(aAngle); } } // for (i=1; i<=aNb; i++) { @@ -348,7 +347,7 @@ void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFac aVertVa.Clear(); aCoordVa.Clear(); // - Path(aGAS, myFace, aVertMap, aVa, aEOuta, aEI, aLS, aVertVa, aCoordVa, aCB, mySmartMap); + Path(aBAS, myFace, aVertMap, aVa, aEOuta, aEI, aLS, aVertVa, aCoordVa, aCB, mySmartMap); } } } // for (i=1; i<=aNb; ++i) { @@ -356,7 +355,7 @@ void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFac //================================================================================================= -void Path(const GeomAdaptor_Surface& aGAS, +void Path(const BRepAdaptor_Surface& aGAS, const TopoDS_Face& myFace, const MyDataMapOfShapeBoolean& aVertMap, const TopoDS_Vertex& aVFirst, @@ -769,7 +768,7 @@ void GetNextVertex(const TopoDS_Vertex& aV, const TopoDS_Edge& aE, TopoDS_Vertex double Angle2D(const TopoDS_Vertex& aV, const TopoDS_Edge& anEdge, const TopoDS_Face& myFace, - const GeomAdaptor_Surface& aGAS, + const BRepAdaptor_Surface& aGAS, const bool bIsIN, const occ::handle& theContext) { @@ -855,7 +854,7 @@ double Angle(const gp_Dir2d& aDir2D) //================================================================================================= -double Tolerance2D(const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS) +double Tolerance2D(const TopoDS_Vertex& aV, const BRepAdaptor_Surface& aGAS) { double aTol2D, anUr, aVr, aTolV3D; GeomAbs_SurfaceType aType; @@ -881,7 +880,7 @@ double Tolerance2D(const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS) //================================================================================================= -double UTolerance2D(const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS) +double UTolerance2D(const TopoDS_Vertex& aV, const BRepAdaptor_Surface& aGAS) { const double aTolV3D = BRep_Tool::Tolerance(aV); const double anUr = aGAS.UResolution(aTolV3D); @@ -891,7 +890,7 @@ double UTolerance2D(const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS) //================================================================================================= -double VTolerance2D(const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS) +double VTolerance2D(const TopoDS_Vertex& aV, const BRepAdaptor_Surface& aGAS) { const double aTolV3D = BRep_Tool::Tolerance(aV); const double anVr = aGAS.VResolution(aTolV3D); diff --git a/src/ModelingAlgorithms/TKBO/BOPTools/BOPTools_AlgoTools2D.cxx b/src/ModelingAlgorithms/TKBO/BOPTools/BOPTools_AlgoTools2D.cxx index e7d6aa9899..09638a16ba 100644 --- a/src/ModelingAlgorithms/TKBO/BOPTools/BOPTools_AlgoTools2D.cxx +++ b/src/ModelingAlgorithms/TKBO/BOPTools/BOPTools_AlgoTools2D.cxx @@ -629,8 +629,7 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace(const TopoDS_Face& } // compute the appropriate tolerance for the edge - occ::handle aS = pBAS->Surface().Surface(); - aS = occ::down_cast(aS->Transformed(pBAS->Trsf())); + const occ::handle aS = pBAS->GeomSurfaceTransformed(); // double aT; if (IntTools_Tools::ComputeTolerance(aC3D, aC2D, aS, aT1, aT2, aTolR, aT)) diff --git a/src/ModelingAlgorithms/TKBO/IntTools/IntTools_BeanFaceIntersector.cxx b/src/ModelingAlgorithms/TKBO/IntTools/IntTools_BeanFaceIntersector.cxx index 6dbe3775f8..777ff30504 100644 --- a/src/ModelingAlgorithms/TKBO/IntTools/IntTools_BeanFaceIntersector.cxx +++ b/src/ModelingAlgorithms/TKBO/IntTools/IntTools_BeanFaceIntersector.cxx @@ -176,9 +176,8 @@ IntTools_BeanFaceIntersector::IntTools_BeanFaceIntersector(const BRepAdaptor_Cur myCriteria = myBeanTolerance + myFaceTolerance; myCurveResolution = myCurve.Resolution(myCriteria); - mySurface = theSurface; - myTrsfSurface = - occ::down_cast(mySurface.Surface().Surface()->Transformed(mySurface.Trsf())); + mySurface = theSurface; + myTrsfSurface = mySurface.GeomSurfaceTransformed(); } //================================================================================================= @@ -191,9 +190,8 @@ void IntTools_BeanFaceIntersector::Init(const TopoDS_Edge& theEdge, const TopoDS } // myCurve.Initialize(theEdge); - mySurface = myContext->SurfaceAdaptor(theFace); - myTrsfSurface = - occ::down_cast(mySurface.Surface().Surface()->Transformed(mySurface.Trsf())); + mySurface = myContext->SurfaceAdaptor(theFace); + myTrsfSurface = mySurface.GeomSurfaceTransformed(); myBeanTolerance = BRep_Tool::Tolerance(theEdge); myFaceTolerance = BRep_Tool::Tolerance(theFace); @@ -214,10 +212,9 @@ void IntTools_BeanFaceIntersector::Init(const BRepAdaptor_Curve& theCurve, const double theBeanTolerance, const double theFaceTolerance) { - myCurve = theCurve; - mySurface = theSurface; - myTrsfSurface = - occ::down_cast(mySurface.Surface().Surface()->Transformed(mySurface.Trsf())); + myCurve = theCurve; + mySurface = theSurface; + myTrsfSurface = mySurface.GeomSurfaceTransformed(); myBeanTolerance = theBeanTolerance; myFaceTolerance = theFaceTolerance; diff --git a/src/ModelingAlgorithms/TKBool/TopOpeBRep/TopOpeBRep_EdgesIntersector_1.cxx b/src/ModelingAlgorithms/TKBool/TopOpeBRep/TopOpeBRep_EdgesIntersector_1.cxx index 3ddd216252..424078f471 100644 --- a/src/ModelingAlgorithms/TKBool/TopOpeBRep/TopOpeBRep_EdgesIntersector_1.cxx +++ b/src/ModelingAlgorithms/TKBool/TopOpeBRep/TopOpeBRep_EdgesIntersector_1.cxx @@ -425,13 +425,12 @@ const TopoDS_Shape& TopOpeBRep_EdgesIntersector::Vertex1(const int Index) gp_Pnt TopOpeBRep_EdgesIntersector::Value1() const { gp_Pnt2d p2 = Point1().Value(); - gp_Pnt p; if (Precision::IsInfinite(p2.X()) || Precision::IsInfinite(p2.Y())) { - double inf = Precision::Infinite(); - p.SetCoord(inf, inf, inf); + return gp_Pnt(Precision::Infinite(), Precision::Infinite(), Precision::Infinite()); } else - mySurface1->Surface().D0(p2.X(), p2.Y(), p); - return p; + { + return mySurface1->EvalD0(p2.X(), p2.Y()); + } } diff --git a/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_ShapeTool.cxx b/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_ShapeTool.cxx index 91d70ea410..0e423f8514 100644 --- a/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_ShapeTool.cxx +++ b/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_ShapeTool.cxx @@ -442,11 +442,10 @@ bool TopOpeBRepTool_ShapeTool::SurfacesSameOriented(const BRepAdaptor_Surface& S S1.D1(u1, v1, p1, d1u, d1v); gp_Vec n1 = d1u.Crossed(d1v); - occ::handle HS2 = S2.Surface().Surface(); - HS2 = occ::down_cast(HS2->Transformed(S2.Trsf())); - gp_Pnt2d p22d; - double dp2; - bool ok = FUN_tool_projPonS(p1, HS2, p22d, dp2); + const occ::handle HS2 = S2.GeomSurfaceTransformed(); + gp_Pnt2d p22d; + double dp2; + bool ok = FUN_tool_projPonS(p1, HS2, p22d, dp2); if (!ok) return so; // NYI : raise diff --git a/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_Builder_0.cxx b/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_Builder_0.cxx index 5a945f323f..6213e869bf 100644 --- a/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_Builder_0.cxx +++ b/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_Builder_0.cxx @@ -103,6 +103,132 @@ double ChFi3d_InPeriod(const double U, const double UFirst, const double ULast, return u; } +namespace +{ +const occ::handle& ChFi3d_BaseSurface(const GeomAdaptor_Surface& theSurface) +{ + return theSurface.Surface(); +} + +const occ::handle& ChFi3d_BaseSurface(const BRepAdaptor_Surface& theSurface) +{ + return theSurface.GeomSurfaceOriginal(); +} + +void ChFi3d_ApplyBounds(GeomAdaptor_Surface& theSurface, + const occ::handle& theGeomSurface, + const double theUFirst, + const double theULast, + const double theVFirst, + const double theVLast) +{ + theSurface.Load(theGeomSurface, + theUFirst, + theULast, + theVFirst, + theVLast, + theSurface.ToleranceU(), + theSurface.ToleranceV()); +} + +void ChFi3d_ApplyBounds(BRepAdaptor_Surface& theSurface, + const occ::handle& theGeomSurface, + const double theUFirst, + const double theULast, + const double theVFirst, + const double theVLast) +{ + theSurface.Load(theGeomSurface, + theUFirst, + theULast, + theVFirst, + theVLast, + theSurface.Trsf(), + theSurface.ToleranceU(), + theSurface.ToleranceV()); +} + +template +void ChFi3d_BoundSrfImpl(SurfaceAdaptor& theSurface, + const double theUmin, + const double theUmax, + const double theVmin, + const double theVmax, + const bool theCheckNaturalBounds) +{ + double aUmin = theUmin; + double aUmax = theUmax; + double aVmin = theVmin; + double aVmax = theVmax; + occ::handle aSurface = ChFi3d_BaseSurface(theSurface); + occ::handle aTrimmedSurface = + occ::down_cast(aSurface); + if (!aTrimmedSurface.IsNull()) + { + aSurface = aTrimmedSurface->BasisSurface(); + } + + double aU1, aU2, aV1, aV2; + aSurface->Bounds(aU1, aU2, aV1, aV2); + + double aPeriodU = 0.0; + double aPeriodV = 0.0; + if (aSurface->IsUPeriodic()) + { + aPeriodU = aSurface->UPeriod(); + } + if (aSurface->IsVPeriodic()) + { + aPeriodV = aSurface->VPeriod(); + } + + double aStepU = aUmax - aUmin; + double aStepV = aVmax - aVmin; + const double aScaleU = theSurface.UResolution(1.0); + const double aScaleV = theSurface.VResolution(1.0); + const double aStep3dU = aStepU / aScaleU; + const double aStep3dV = aStepV / aScaleV; + + if (aStep3dU > aStep3dV) + { + aStepV = aStep3dU * aScaleV; + } + if (aStep3dV > aStep3dU) + { + aStepU = aStep3dV * aScaleU; + } + + if (aPeriodU > 0.0) + { + aStepU = 0.1 * (aPeriodU - (aUmax - aUmin)); + } + if (aPeriodV > 0.0) + { + aStepV = 0.1 * (aPeriodV - (aVmax - aVmin)); + } + + double aUU1 = aUmin - aStepU; + double aUU2 = aUmax + aStepU; + double aVV1 = aVmin - aStepV; + double aVV2 = aVmax + aStepV; + if (theCheckNaturalBounds) + { + if (!theSurface.IsUPeriodic()) + { + aUU1 = std::max(aUU1, aU1); + aUU2 = std::min(aUU2, aU2); + } + if (!theSurface.IsVPeriodic()) + { + aVV1 = std::max(aVV1, aV1); + aVV2 = std::min(aVV2, aV2); + } + } + + ChFi3d_ApplyBounds(theSurface, aSurface, aUU1, aUU2, aVV1, aVV2); +} +} // namespace + //======================================================================= // function : Box // purpose : Calculation of min/max uv of the fillet to intersect. @@ -537,7 +663,7 @@ void ChFi3d_BoundFac(BRepAdaptor_Surface& S, const double vvmax, const bool checknaturalbounds) { - ChFi3d_BoundSrf(S.ChangeSurface(), uumin, uumax, vvmin, vvmax, checknaturalbounds); + ChFi3d_BoundSrfImpl(S, uumin, uumax, vvmin, vvmax, checknaturalbounds); } //======================================================================= @@ -552,62 +678,7 @@ void ChFi3d_BoundSrf(GeomAdaptor_Surface& S, const double vvmax, const bool checknaturalbounds) { - double umin = uumin, umax = uumax, vmin = vvmin, vmax = vvmax; - occ::handle surface = S.Surface(); - occ::handle trs = - occ::down_cast(surface); - if (!trs.IsNull()) - surface = trs->BasisSurface(); - double u1, u2, v1, v2; - surface->Bounds(u1, u2, v1, v2); - double peru = 0, perv = 0; - if (surface->IsUPeriodic()) - { - peru = surface->UPeriod(); - } - if (surface->IsVPeriodic()) - { - perv = surface->VPeriod(); - } - double Stepu = umax - umin; - double Stepv = vmax - vmin; - - // It is supposed that box uv is not null in at least - // one direction. - double scalu = S.UResolution(1.); - double scalv = S.VResolution(1.); - - double step3du = Stepu / scalu; - double step3dv = Stepv / scalv; - - if (step3du > step3dv) - Stepv = step3du * scalv; - if (step3dv > step3du) - Stepu = step3dv * scalu; - - if (peru > 0) - Stepu = 0.1 * (peru - (umax - umin)); - if (perv > 0) - Stepv = 0.1 * (perv - (vmax - vmin)); - - double uu1 = umin - Stepu; - double uu2 = umax + Stepu; - double vv1 = vmin - Stepv; - double vv2 = vmax + Stepv; - if (checknaturalbounds) - { - if (!S.IsUPeriodic()) - { - uu1 = std::max(uu1, u1); - uu2 = std::min(uu2, u2); - } - if (!S.IsVPeriodic()) - { - vv1 = std::max(vv1, v1); - vv2 = std::min(vv2, v2); - } - } - S.Load(surface, uu1, uu2, vv1, vv2); + ChFi3d_BoundSrfImpl(S, uumin, uumax, vvmin, vvmax, checknaturalbounds); } //================================================================================================= @@ -3328,9 +3399,7 @@ occ::handle trsfsurf(const occ::handle& HS, occ::handle hgs = occ::down_cast(HS); if (!hbs.IsNull()) { - res = hbs->Surface().Surface(); - gp_Trsf trsf = hbs->Trsf(); - res = occ::down_cast(res->Transformed(trsf)); + res = hbs->GeomSurfaceTransformed(); } else if (!hgs.IsNull()) { diff --git a/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_Builder_C1.cxx b/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_Builder_C1.cxx index 46db12d019..b57f825bff 100644 --- a/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_Builder_C1.cxx +++ b/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_Builder_C1.cxx @@ -452,9 +452,12 @@ static void ComputeCurve2d(const occ::handle& Ct, //================================================================================================= -static void ChFi3d_Recale(BRepAdaptor_Surface& Bs, gp_Pnt2d& p1, gp_Pnt2d& p2, const bool refon1) +static void ChFi3d_Recale(const BRepAdaptor_Surface& Bs, + gp_Pnt2d& p1, + gp_Pnt2d& p2, + const bool refon1) { - occ::handle surf = Bs.ChangeSurface().Surface(); + occ::handle surf = Bs.GeomSurfaceOriginal(); occ::handle ts = occ::down_cast(surf); if (!ts.IsNull()) diff --git a/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_ChBuilder_C3.cxx b/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_ChBuilder_C3.cxx index 63e5da5447..7c49c1f610 100644 --- a/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_ChBuilder_C3.cxx +++ b/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_ChBuilder_C3.cxx @@ -421,7 +421,7 @@ void ChFi3d_ChBuilder::PerformThreeCorner(const int Jndex) // ---------------------------------------------------------- occ::handle Fac = new BRepAdaptor_Surface(face[pivot]); - occ::handle bidsurf = new GeomAdaptor_Surface(Fac->Surface()); + occ::handle bidsurf = new GeomAdaptor_Surface(Fac->AdaptorSurfaceOriginal()); occ::handle IFac = new Adaptor3d_TopolTool(bidsurf); occ::handle Surf = @@ -669,8 +669,7 @@ void ChFi3d_ChBuilder::PerformThreeCorner(const int Jndex) { GeomInt_IntSS inter; BRepAdaptor_Surface facebid(face[pivot]); - occ::handle surfbid = - occ::down_cast(facebid.Surface().Surface()->Transformed(facebid.Trsf())); + occ::handle surfbid = facebid.GeomSurfaceTransformed(); inter.Perform(gpl, surfbid, Precision::Intersection()); if (inter.IsDone()) { diff --git a/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_FilBuilder_C3.cxx b/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_FilBuilder_C3.cxx index ba5b4deb37..29b09e20c2 100644 --- a/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_FilBuilder_C3.cxx +++ b/src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_FilBuilder_C3.cxx @@ -584,9 +584,8 @@ void ChFi3d_FilBuilder::PerformThreeCorner(const int Jndex) // occ::handle IFac = new BRepTopAdaptor_TopolTool(Fac); // Try to not classify on the face for cases of reentering fillets which naturally depass // the border. - occ::handle bidsurf = - new GeomAdaptor_Surface(Fac->ChangeSurface().Surface()); - occ::handle IFac = new Adaptor3d_TopolTool(bidsurf); + occ::handle bidsurf = new GeomAdaptor_Surface(Fac->GeomSurfaceOriginal()); + occ::handle IFac = new Adaptor3d_TopolTool(bidsurf); // end of the attempt. occ::handle ISurf = new Adaptor3d_TopolTool(Surf); occ::handle corner = new ChFiDS_Stripe(); diff --git a/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_DefaultRangeSplitter.cxx b/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_DefaultRangeSplitter.cxx index ad76ca5093..a71a2143ae 100644 --- a/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_DefaultRangeSplitter.cxx +++ b/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_DefaultRangeSplitter.cxx @@ -117,7 +117,7 @@ void BRepMesh_DefaultRangeSplitter::computeTolerance(const double /*theLenU*/, // Slightly increase exact resolution so to cover links with approximate // length equal to resolution itself on sub-resolution differences. const double aTolerance = BRep_Tool::Tolerance(myDFace->GetFace()); - const Adaptor3d_Surface& aSurface = GetSurface()->Surface(); + const Adaptor3d_Surface& aSurface = *GetSurface(); const double aResU = aSurface.UResolution(aTolerance) * 1.1; const double aResV = aSurface.VResolution(aTolerance) * 1.1; diff --git a/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx b/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx index 554934b1ff..1b316e0732 100644 --- a/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx +++ b/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx @@ -353,7 +353,7 @@ private: const gp_XY& /*theMidPoint*/) { gp_Dir aNorm1, aNorm2; - const occ::handle& aSurf = this->getDFace()->GetSurface()->Surface().Surface(); + const occ::handle& aSurf = this->getDFace()->GetSurface()->GeomSurfaceOriginal(); if ((GeomLib::NormEstim(aSurf, theNodeInfo1.Point2d, Precision::Confusion(), aNorm1) == 0) && (GeomLib::NormEstim(aSurf, theNodeInfo2.Point2d, Precision::Confusion(), aNorm2) == 0)) diff --git a/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx b/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx index f3661a8978..3a58d7f20e 100644 --- a/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx +++ b/src/ModelingAlgorithms/TKMesh/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx @@ -36,7 +36,7 @@ public: const Handle(IMeshData::MapOfReal)& theParamsForbiddenToRemove, const Handle(IMeshData::MapOfReal)& theControlParamsForbiddenToRemove) : myDFace(theDFace), - mySurface(myDFace->GetSurface()->Surface().Surface()), + mySurface(myDFace->GetSurface()->GeomSurfaceOriginal()), myIsoU(theIsoType == GeomAbs_IsoU), myParams(theParams), myControlParams(theControlParams), @@ -322,7 +322,7 @@ Handle(IMeshData::ListOfPnt2d) BRepMesh_NURBSRangeSplitter::GenerateSurfaceNodes const double aDefFace = GetDFace()->GetDeflection(); const occ::handle& gFace = GetSurface(); - occ::handle aSurface = gFace->Surface().Surface(); + occ::handle aSurface = gFace->GeomSurfaceOriginal(); const occ::handle aTmpAlloc = new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); @@ -456,7 +456,7 @@ bool BRepMesh_NURBSRangeSplitter::initParameters() const getUndefinedInterval(aSurface, true, aContinuity, GetRangeU(), aIntervals[0]); getUndefinedInterval(aSurface, false, aContinuity, GetRangeV(), aIntervals[1]); - const bool isSplitIntervals = toSplitIntervals(aSurface->Surface().Surface(), aIntervals); + const bool isSplitIntervals = toSplitIntervals(aSurface->GeomSurfaceOriginal(), aIntervals); if (!initParamsFromIntervals(aIntervals[0], GetRangeU(), diff --git a/src/ModelingAlgorithms/TKTopAlgo/BRepBndLib/BRepBndLib_1.cxx b/src/ModelingAlgorithms/TKTopAlgo/BRepBndLib/BRepBndLib_1.cxx index 3e349b66db..cad0f1872d 100644 --- a/src/ModelingAlgorithms/TKTopAlgo/BRepBndLib/BRepBndLib_1.cxx +++ b/src/ModelingAlgorithms/TKTopAlgo/BRepBndLib/BRepBndLib_1.cxx @@ -142,7 +142,7 @@ static int PointsForOBB(const TopoDS_Shape& theS, const TopoDS_Face& aF = TopoDS::Face(anExpF.Current()); const BRepAdaptor_Surface anAS(aF, false); - if (!IsPlanar(anAS.Surface())) + if (!IsPlanar(anAS)) { if (!theIsTriangulationUsed) // not planar and triangulation usage disabled diff --git a/src/ModelingAlgorithms/TKTopAlgo/BRepGProp/BRepGProp_Face.cxx b/src/ModelingAlgorithms/TKTopAlgo/BRepGProp/BRepGProp_Face.cxx index bbeb73362d..ca7f6e595a 100644 --- a/src/ModelingAlgorithms/TKTopAlgo/BRepGProp/BRepGProp_Face.cxx +++ b/src/ModelingAlgorithms/TKTopAlgo/BRepGProp/BRepGProp_Face.cxx @@ -48,15 +48,17 @@ int BRepGProp_Face::UIntegrationOrder() const break; case GeomAbs_BezierSurface: { - Nu = (*((occ::handle*)&((mySurface.Surface()).Surface())))->UDegree() + 1; + Nu = + (*((occ::handle*)&((mySurface.GeomSurfaceOriginal()))))->UDegree() + 1; Nu = std::max(4, Nu); } break; case GeomAbs_BSplineSurface: { int a = - (*((occ::handle*)&((mySurface.Surface()).Surface())))->UDegree() + 1; + (*((occ::handle*)&((mySurface.GeomSurfaceOriginal()))))->UDegree() + 1; int b = - (*((occ::handle*)&((mySurface.Surface()).Surface())))->NbUKnots() - 1; + (*((occ::handle*)&((mySurface.GeomSurfaceOriginal()))))->NbUKnots() + - 1; Nu = std::max(4, a * b); } break; @@ -81,16 +83,18 @@ int BRepGProp_Face::VIntegrationOrder() const break; case GeomAbs_BezierSurface: { - Nv = (*((occ::handle*)&((mySurface.Surface()).Surface())))->VDegree() + 1; + Nv = + (*((occ::handle*)&((mySurface.GeomSurfaceOriginal()))))->VDegree() + 1; Nv = std::max(4, Nv); } break; case GeomAbs_BSplineSurface: { int a = - (*((occ::handle*)&((mySurface.Surface()).Surface())))->VDegree() + 1; + (*((occ::handle*)&((mySurface.GeomSurfaceOriginal()))))->VDegree() + 1; int b = - (*((occ::handle*)&((mySurface.Surface()).Surface())))->NbVKnots() - 1; + (*((occ::handle*)&((mySurface.GeomSurfaceOriginal()))))->NbVKnots() + - 1; Nv = std::max(4, a * b); } break; @@ -246,12 +250,12 @@ int BRepGProp_Face::SIntOrder(const double Eps) const Nv = 2; break; case GeomAbs_BezierSurface: - Nv = (*((occ::handle*)&((mySurface.Surface()).Surface())))->VDegree(); - Nu = (*((occ::handle*)&((mySurface.Surface()).Surface())))->UDegree(); + Nv = (*(occ::handle*)&mySurface.GeomSurfaceOriginal())->VDegree(); + Nu = (*(occ::handle*)&mySurface.GeomSurfaceOriginal())->UDegree(); break; case GeomAbs_BSplineSurface: - Nv = (*((occ::handle*)&((mySurface.Surface()).Surface())))->VDegree(); - Nu = (*((occ::handle*)&((mySurface.Surface()).Surface())))->UDegree(); + Nv = (*(occ::handle*)&mySurface.GeomSurfaceOriginal())->VDegree(); + Nu = (*(occ::handle*)&mySurface.GeomSurfaceOriginal())->UDegree(); break; default: Nu = 2; @@ -288,7 +292,7 @@ int BRepGProp_Face::SUIntSubs() const N = 2; break; case GeomAbs_BSplineSurface: - N = (*((occ::handle*)&((mySurface.Surface()).Surface())))->NbUKnots(); + N = (*(occ::handle*)&mySurface.GeomSurfaceOriginal())->NbUKnots(); break; default: N = 2; @@ -323,7 +327,7 @@ int BRepGProp_Face::SVIntSubs() const N = 2; break; case GeomAbs_BSplineSurface: - N = (*((occ::handle*)&((mySurface.Surface()).Surface())))->NbVKnots(); + N = (*(occ::handle*)&mySurface.GeomSurfaceOriginal())->NbVKnots(); break; default: N = 2; @@ -353,7 +357,7 @@ void BRepGProp_Face::UKnots(NCollection_Array1& Knots) const break; case GeomAbs_BSplineSurface: { const NCollection_Array1& aSrcKnots = - (*((occ::handle*)&((mySurface.Surface()).Surface())))->UKnots(); + (*((occ::handle*)&((mySurface.GeomSurfaceOriginal()))))->UKnots(); for (int i = Knots.Lower(); i <= Knots.Upper(); i++) Knots(i) = aSrcKnots(i); } @@ -390,7 +394,7 @@ void BRepGProp_Face::VKnots(NCollection_Array1& Knots) const break; case GeomAbs_BSplineSurface: { const NCollection_Array1& aSrcKnots = - (*((occ::handle*)&((mySurface.Surface()).Surface())))->VKnots(); + (*((occ::handle*)&((mySurface.GeomSurfaceOriginal()))))->VKnots(); for (int i = Knots.Lower(); i <= Knots.Upper(); i++) Knots(i) = aSrcKnots(i); } @@ -653,7 +657,7 @@ void BRepGProp_Face::GetUKnots(const double theUMin if (mySurface.GetType() == GeomAbs_SurfaceOfExtrusion) { GeomAdaptor_Curve aCurve; - occ::handle aSurf = mySurface.Surface().Surface(); + occ::handle aSurf = mySurface.GeomSurfaceOriginal(); aCurve.Load(occ::down_cast(aSurf)->BasisCurve()); isCBSpline = aCurve.GetType() == GeomAbs_BSplineCurve; @@ -668,7 +672,7 @@ void BRepGProp_Face::GetUKnots(const double theUMin if (isSBSpline) { // Get U knots of BSpline surface. - occ::handle aSurf = mySurface.Surface().Surface(); + occ::handle aSurf = mySurface.GeomSurfaceOriginal(); occ::handle aBSplSurf; aBSplSurf = occ::down_cast(aSurf); @@ -679,7 +683,7 @@ void BRepGProp_Face::GetUKnots(const double theUMin // Get U knots of BSpline curve - basis curve of // the surface of linear extrusion. GeomAdaptor_Curve aCurve; - occ::handle aSurf = mySurface.Surface().Surface(); + occ::handle aSurf = mySurface.GeomSurfaceOriginal(); occ::handle aBSplCurve; aCurve.Load(occ::down_cast(aSurf)->BasisCurve()); @@ -713,7 +717,7 @@ void BRepGProp_Face::GetTKnots(const double theTMin occ::handle> aSurfKnots; // Get V knots of BSpline surface. - occ::handle aSurf = mySurface.Surface().Surface(); + occ::handle aSurf = mySurface.GeomSurfaceOriginal(); occ::handle aBSplSurf; aBSplSurf = occ::down_cast(aSurf); diff --git a/src/ModelingAlgorithms/TKTopAlgo/BRepLib/BRepLib.cxx b/src/ModelingAlgorithms/TKTopAlgo/BRepLib/BRepLib.cxx index 48ecb974a3..f946628b6d 100644 --- a/src/ModelingAlgorithms/TKTopAlgo/BRepLib/BRepLib.cxx +++ b/src/ModelingAlgorithms/TKTopAlgo/BRepLib/BRepLib.cxx @@ -2943,8 +2943,7 @@ void BRepLib::ExtendFace(const TopoDS_Face& theF, || aType == GeomAbs_Torus || aType == GeomAbs_Cone) { // Get basis transformed basis surface - occ::handle aSurf = - occ::down_cast(aBAS.Surface().Surface()->Transformed(aBAS.Trsf())); + occ::handle aSurf = aBAS.GeomSurfaceTransformed(); // Get bounds of the basis surface double aSUMin, aSUMax, aSVMin, aSVMax; diff --git a/src/ModelingData/TKBRep/BRepAdaptor/BRepAdaptor_Surface.cxx b/src/ModelingData/TKBRep/BRepAdaptor/BRepAdaptor_Surface.cxx index 8f971e2a78..49b057b622 100644 --- a/src/ModelingData/TKBRep/BRepAdaptor/BRepAdaptor_Surface.cxx +++ b/src/ModelingData/TKBRep/BRepAdaptor/BRepAdaptor_Surface.cxx @@ -44,8 +44,9 @@ occ::handle BRepAdaptor_Surface::ShallowCopy() const const GeomAdaptor_Surface& aGeomSurface = *occ::down_cast(aSurface); aCopy->mySurf = aGeomSurface; - aCopy->myTrsf = myTrsf; - aCopy->myFace = myFace; + aCopy->myTrsf = myTrsf; + aCopy->myFace = myFace; + aCopy->myTransformedAdaptor = myTransformedAdaptor; return aCopy; } @@ -69,11 +70,12 @@ void BRepAdaptor_Surface::Initialize(const TopoDS_Face& F, const bool Restrictio { double umin, umax, vmin, vmax; BRepTools::UVBounds(F, umin, umax, vmin, vmax); - mySurf.Load(aSurface, umin, umax, vmin, vmax); + Load(aSurface, umin, umax, vmin, vmax, L.Transformation()); } else - mySurf.Load(aSurface); - myTrsf = L.Transformation(); + { + Load(aSurface, L.Transformation()); + } } //================================================================================================= diff --git a/src/ModelingData/TKBRep/BRepAdaptor/BRepAdaptor_Surface.hxx b/src/ModelingData/TKBRep/BRepAdaptor/BRepAdaptor_Surface.hxx index 57a6c2e5be..3c83bc892a 100644 --- a/src/ModelingData/TKBRep/BRepAdaptor/BRepAdaptor_Surface.hxx +++ b/src/ModelingData/TKBRep/BRepAdaptor/BRepAdaptor_Surface.hxx @@ -73,7 +73,6 @@ public: // Note: Most methods are inherited from GeomAdaptor_TransformedSurface. // The following methods provide access to the underlying surface/transformation: // - Surface() - returns const GeomAdaptor_Surface& - // - ChangeSurface() - returns GeomAdaptor_Surface& // - Trsf() - returns const gp_Trsf& // // Value, D0, D1, D2, D3, DN methods are inherited and marked as final. diff --git a/src/ModelingData/TKG3d/GTests/FILES.cmake b/src/ModelingData/TKG3d/GTests/FILES.cmake index 428e837c48..698885e2d7 100644 --- a/src/ModelingData/TKG3d/GTests/FILES.cmake +++ b/src/ModelingData/TKG3d/GTests/FILES.cmake @@ -27,6 +27,7 @@ set(OCCT_TKG3d_GTests_FILES GeomEval_TBezierSurface_Test.cxx GeomAPI_ExtremaCurveCurve_Test.cxx GeomAPI_Interpolate_Test.cxx + GeomAdaptor_TransformedSurface_Test.cxx GeomAdaptor_TransformedCurve_Test.cxx GeomGridEval_BezierCurve_Test.cxx GeomGridEval_BezierSurface_Test.cxx diff --git a/src/ModelingData/TKG3d/GTests/GeomAdaptor_TransformedSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomAdaptor_TransformedSurface_Test.cxx new file mode 100644 index 0000000000..edb5bfee7c --- /dev/null +++ b/src/ModelingData/TKG3d/GTests/GeomAdaptor_TransformedSurface_Test.cxx @@ -0,0 +1,300 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +constexpr double THE_TOLERANCE = 1.0e-10; + +gp_Trsf createTranslation(const double theDx, const double theDy, const double theDz) +{ + gp_Trsf aTrsf; + aTrsf.SetTranslation(gp_Vec(theDx, theDy, theDz)); + return aTrsf; +} + +gp_Trsf createRotationY(const double theAngle) +{ + gp_Trsf aTrsf; + aTrsf.SetRotation(gp_Ax1(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 1.0, 0.0)), theAngle); + return aTrsf; +} + +occ::handle createBSplineSurface() +{ + NCollection_Array2 aPoles(1, 2, 1, 2); + aPoles.SetValue(1, 1, gp_Pnt(0.0, 0.0, 0.0)); + aPoles.SetValue(2, 1, gp_Pnt(1.0, 0.0, 0.0)); + aPoles.SetValue(1, 2, gp_Pnt(0.0, 1.0, 0.0)); + aPoles.SetValue(2, 2, gp_Pnt(1.0, 1.0, 1.0)); + + NCollection_Array1 aUKnots(1, 2); + NCollection_Array1 aVKnots(1, 2); + NCollection_Array1 aUMults(1, 2); + NCollection_Array1 aVMults(1, 2); + aUKnots.SetValue(1, 0.0); + aUKnots.SetValue(2, 1.0); + aVKnots.SetValue(1, 0.0); + aVKnots.SetValue(2, 1.0); + aUMults.SetValue(1, 2); + aUMults.SetValue(2, 2); + aVMults.SetValue(1, 2); + aVMults.SetValue(2, 2); + return new Geom_BSplineSurface(aPoles, aUKnots, aVKnots, aUMults, aVMults, 1, 1); +} +} // namespace + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, IdentityTransformUsesOriginalSurface) +{ + occ::handle aPlane = new Geom_Plane(gp_Pln(gp::XOY())); + + GeomAdaptor_TransformedSurface anAdaptor(aPlane, gp_Trsf()); + + EXPECT_EQ(anAdaptor.GeomSurfaceOriginal(), aPlane); + EXPECT_EQ(anAdaptor.GeomSurfaceTransformed(), aPlane); +} + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, PlaneCachesTransformedSurface) +{ + occ::handle aPlane = new Geom_Plane(gp_Pln(gp::XOY())); + + GeomAdaptor_TransformedSurface anAdaptor(aPlane, createTranslation(0.0, 0.0, 5.0)); + + const occ::handle& aFirst = anAdaptor.GeomSurfaceTransformed(); + const occ::handle& aSecond = anAdaptor.GeomSurfaceTransformed(); + EXPECT_EQ(aFirst, aSecond); + + const gp_Pln aCachedPlane = anAdaptor.Plane(); + EXPECT_NEAR(aCachedPlane.Location().Z(), 5.0, THE_TOLERANCE); +} + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, BSplineCachePreservedByShallowCopy) +{ + GeomAdaptor_TransformedSurface anAdaptor(createBSplineSurface(), + createTranslation(4.0, 0.0, 0.0)); + + const occ::handle& aSurface = anAdaptor.GeomSurfaceTransformed(); + const occ::handle aBSpline = anAdaptor.BSpline(); + + const occ::handle aCopyBase = anAdaptor.ShallowCopy(); + const occ::handle aCopy = + occ::down_cast(aCopyBase); + ASSERT_FALSE(aCopy.IsNull()); + + EXPECT_EQ(aCopy->GeomSurfaceTransformed(), aSurface); + EXPECT_EQ(aCopy->BSpline(), aBSpline); +} + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, ShallowCopyFromUnbuiltStateBuildsCacheLazily) +{ + occ::handle aPlane = new Geom_Plane(gp_Pln(gp::XOY())); + GeomAdaptor_TransformedSurface anAdaptor(aPlane, createTranslation(0.0, 0.0, 4.0)); + + const occ::handle aCopyBase = anAdaptor.ShallowCopy(); + const occ::handle aCopy = + occ::down_cast(aCopyBase); + ASSERT_FALSE(aCopy.IsNull()); + + const occ::handle& aFirst = aCopy->GeomSurfaceTransformed(); + const occ::handle& aSecond = aCopy->GeomSurfaceTransformed(); + EXPECT_EQ(aFirst, aSecond); + EXPECT_NEAR(aCopy->Plane().Location().Z(), 4.0, THE_TOLERANCE); +} + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, SetTrsfRebuildsCache) +{ + occ::handle aPlane = new Geom_Plane(gp_Pln(gp::XOY())); + GeomAdaptor_TransformedSurface anAdaptor(aPlane, createTranslation(0.0, 0.0, 1.0)); + + const occ::handle aFirst = anAdaptor.GeomSurfaceTransformed(); + anAdaptor.SetTrsf(createTranslation(0.0, 0.0, 3.0)); + const occ::handle aSecond = anAdaptor.GeomSurfaceTransformed(); + + EXPECT_NE(aFirst, aSecond); + EXPECT_NEAR(anAdaptor.Plane().Location().Z(), 3.0, THE_TOLERANCE); +} + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, LoadRebuildsCache) +{ + occ::handle aPlane = new Geom_Plane(gp_Pln(gp::XOY())); + GeomAdaptor_TransformedSurface anAdaptor(aPlane, createTranslation(0.0, 0.0, 2.0)); + + const occ::handle aFirst = anAdaptor.GeomSurfaceTransformed(); + + gp_Ax3 aSphereAx(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)); + occ::handle aSphere = new Geom_SphericalSurface(aSphereAx, 3.0); + anAdaptor.Load(aSphere, gp_Trsf()); + + const occ::handle aSecond = anAdaptor.GeomSurfaceTransformed(); + EXPECT_NE(aFirst, aSecond); + EXPECT_EQ(anAdaptor.GetType(), GeomAbs_Sphere); + EXPECT_NEAR(anAdaptor.Sphere().Radius(), 3.0, THE_TOLERANCE); +} + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, ExtrusionCachesDirectionAndBasisCurve) +{ + occ::handle aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0)); + occ::handle anExt = + new Geom_SurfaceOfLinearExtrusion(aLine, gp_Dir(0.0, 0.0, 1.0)); + + GeomAdaptor_TransformedSurface anAdaptor(anExt, createRotationY(M_PI / 2.0)); + + const gp_Dir aDirection = anAdaptor.Direction(); + EXPECT_NEAR(aDirection.X(), 1.0, THE_TOLERANCE); + EXPECT_NEAR(aDirection.Y(), 0.0, THE_TOLERANCE); + EXPECT_NEAR(aDirection.Z(), 0.0, THE_TOLERANCE); + + const occ::handle aCurve = anAdaptor.BasisCurve(); + ASSERT_FALSE(aCurve.IsNull()); + EXPECT_EQ(aCurve->GetType(), GeomAbs_Line); +} + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, RevolutionCachesAxisAndBasisCurve) +{ + occ::handle aLine = new Geom_Line(gp_Pnt(2.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)); + occ::handle aRev = + new Geom_SurfaceOfRevolution(aLine, gp_Ax1(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0))); + + GeomAdaptor_TransformedSurface anAdaptor(aRev, createRotationY(M_PI / 2.0)); + + const gp_Ax1 aAxis = anAdaptor.AxeOfRevolution(); + EXPECT_NEAR(aAxis.Direction().X(), 1.0, THE_TOLERANCE); + EXPECT_NEAR(aAxis.Direction().Y(), 0.0, THE_TOLERANCE); + EXPECT_NEAR(aAxis.Direction().Z(), 0.0, THE_TOLERANCE); + + const occ::handle aCurve = anAdaptor.BasisCurve(); + ASSERT_FALSE(aCurve.IsNull()); + EXPECT_EQ(aCurve->GetType(), GeomAbs_Line); +} + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, OffsetCachesBasisSurfaceAndOffsetValue) +{ + occ::handle aPlane = new Geom_Plane(gp_Pln(gp::XOY())); + occ::handle anOffset = new Geom_OffsetSurface(aPlane, 2.5); + + GeomAdaptor_TransformedSurface anAdaptor(anOffset, createTranslation(0.0, 0.0, 3.0)); + + const occ::handle aBasis = anAdaptor.BasisSurface(); + ASSERT_FALSE(aBasis.IsNull()); + EXPECT_EQ(aBasis->GetType(), GeomAbs_Plane); + EXPECT_NEAR(anAdaptor.OffsetValue(), 2.5, THE_TOLERANCE); +} + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, UTrimPreservesRestrictedBounds) +{ + occ::handle aPlane = new Geom_Plane(gp_Pln(gp::XOY())); + + GeomAdaptor_TransformedSurface + anAdaptor(aPlane, 2.0, 8.0, 3.0, 9.0, createTranslation(0.0, 0.0, 5.0), 0.1, 0.2); + + const occ::handle aTrimmedBase = anAdaptor.UTrim(4.0, 6.0, 0.05); + const occ::handle aTrimmed = + occ::down_cast(aTrimmedBase); + ASSERT_FALSE(aTrimmed.IsNull()); + + EXPECT_NEAR(aTrimmed->FirstUParameter(), 4.0, THE_TOLERANCE); + EXPECT_NEAR(aTrimmed->LastUParameter(), 6.0, THE_TOLERANCE); + EXPECT_NEAR(aTrimmed->FirstVParameter(), 3.0, THE_TOLERANCE); + EXPECT_NEAR(aTrimmed->LastVParameter(), 9.0, THE_TOLERANCE); + EXPECT_NEAR(aTrimmed->ToleranceU(), 0.05, THE_TOLERANCE); + EXPECT_NEAR(aTrimmed->ToleranceV(), 0.2, THE_TOLERANCE); + + const gp_Pnt aPoint = aTrimmed->EvalD0(4.0, 3.0); + EXPECT_NEAR(aPoint.Z(), 5.0, THE_TOLERANCE); +} + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, VTrimPreservesRestrictedBounds) +{ + occ::handle aPlane = new Geom_Plane(gp_Pln(gp::XOY())); + + GeomAdaptor_TransformedSurface + anAdaptor(aPlane, 2.0, 8.0, 3.0, 9.0, createTranslation(0.0, 0.0, 7.0), 0.1, 0.2); + + const occ::handle aTrimmedBase = anAdaptor.VTrim(4.0, 6.0, 0.15); + const occ::handle aTrimmed = + occ::down_cast(aTrimmedBase); + ASSERT_FALSE(aTrimmed.IsNull()); + + EXPECT_NEAR(aTrimmed->FirstUParameter(), 2.0, THE_TOLERANCE); + EXPECT_NEAR(aTrimmed->LastUParameter(), 8.0, THE_TOLERANCE); + EXPECT_NEAR(aTrimmed->FirstVParameter(), 4.0, THE_TOLERANCE); + EXPECT_NEAR(aTrimmed->LastVParameter(), 6.0, THE_TOLERANCE); + EXPECT_NEAR(aTrimmed->ToleranceU(), 0.1, THE_TOLERANCE); + EXPECT_NEAR(aTrimmed->ToleranceV(), 0.15, THE_TOLERANCE); + + const gp_Pnt aPoint = aTrimmed->EvalD0(2.0, 4.0); + EXPECT_NEAR(aPoint.Z(), 7.0, THE_TOLERANCE); +} + +//================================================================================================= + +TEST(GeomAdaptor_TransformedSurfaceTest, GridEvalUsesTransformedGeometryOnlyOnce) +{ + occ::handle aPlane = new Geom_Plane(gp_Pln(gp::XOY())); + GeomAdaptor_TransformedSurface anAdaptor(aPlane, createTranslation(0.0, 0.0, 5.0)); + + GeomGridEval_Surface anEval(anAdaptor); + + NCollection_Array1 aUParams(1, 2); + NCollection_Array1 aVParams(1, 2); + aUParams.SetValue(1, 0.0); + aUParams.SetValue(2, 1.0); + aVParams.SetValue(1, 0.0); + aVParams.SetValue(2, 1.0); + + const NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); + EXPECT_NEAR(aGrid.Value(1, 1).Z(), 5.0, THE_TOLERANCE); + EXPECT_NEAR(aGrid.Value(2, 2).Z(), 5.0, THE_TOLERANCE); +} diff --git a/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_Surface.cxx b/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_Surface.cxx index 838dad8e65..0d222df3f6 100644 --- a/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_Surface.cxx +++ b/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_Surface.cxx @@ -450,7 +450,7 @@ void GeomAdaptor_Surface::load(const occ::handle& S, occ::down_cast(mySurface); // Populate revolution surface data GeomAdaptor_Surface::RevolutionData aRevData; - aRevData.BasisCurve = new GeomAdaptor_Curve(aRevSurf->BasisCurve()); + aRevData.BasisCurve = new GeomAdaptor_Curve(aRevSurf->BasisCurve(), myVFirst, myVLast); aRevData.Axis = aRevSurf->Axis(); aRevData.EvalRep = aRevSurf->EvalRepresentation(); mySurfaceData = aRevData; @@ -462,7 +462,7 @@ void GeomAdaptor_Surface::load(const occ::handle& S, occ::down_cast(mySurface); // Populate extrusion surface data with XYZ for fast evaluation GeomAdaptor_Surface::ExtrusionData anExtData; - anExtData.BasisCurve = new GeomAdaptor_Curve(anExtSurf->BasisCurve()); + anExtData.BasisCurve = new GeomAdaptor_Curve(anExtSurf->BasisCurve(), myUFirst, myULast); anExtData.Direction = anExtSurf->Direction().XYZ(); anExtData.EvalRep = anExtSurf->EvalRepresentation(); mySurfaceData = anExtData; @@ -558,10 +558,7 @@ GeomAbs_Shape GeomAdaptor_Surface::UContinuity() const break; } case GeomAbs_SurfaceOfExtrusion: { - occ::handle myExtSurf = - occ::down_cast(mySurface); - GeomAdaptor_Curve GC(myExtSurf->BasisCurve(), myUFirst, myULast); - return GC.Continuity(); + return std::get(mySurfaceData).BasisCurve->Continuity(); } case GeomAbs_OtherSurface: throw Standard_NoSuchObject("GeomAdaptor_Surface::UContinuity"); @@ -613,10 +610,7 @@ GeomAbs_Shape GeomAdaptor_Surface::VContinuity() const break; } case GeomAbs_SurfaceOfRevolution: { - occ::handle myRevSurf = - occ::down_cast(mySurface); - GeomAdaptor_Curve GC(myRevSurf->BasisCurve(), myVFirst, myVLast); - return GC.Continuity(); + return std::get(mySurfaceData).BasisCurve->Continuity(); } case GeomAbs_OtherSurface: throw Standard_NoSuchObject("GeomAdaptor_Surface::VContinuity"); @@ -673,9 +667,7 @@ int GeomAdaptor_Surface::NbUIntervals(const GeomAbs_Shape S) const case GeomAbs_CN: break; } - occ::handle myOffSurf = occ::down_cast(mySurface); - GeomAdaptor_Surface Sur(myOffSurf->BasisSurface(), myUFirst, myULast, myVFirst, myVLast); - return Sur.NbUIntervals(BaseS); + return std::get(mySurfaceData).BasisAdaptor->NbUIntervals(BaseS); } case GeomAbs_Plane: case GeomAbs_Cylinder: @@ -731,9 +723,7 @@ int GeomAdaptor_Surface::NbVIntervals(const GeomAbs_Shape S) const case GeomAbs_CN: break; } - occ::handle myOffSurf = occ::down_cast(mySurface); - GeomAdaptor_Surface Sur(myOffSurf->BasisSurface(), myUFirst, myULast, myVFirst, myVLast); - return Sur.NbVIntervals(BaseS); + return std::get(mySurfaceData).BasisAdaptor->NbVIntervals(BaseS); } case GeomAbs_Plane: case GeomAbs_Cylinder: @@ -794,9 +784,7 @@ void GeomAdaptor_Surface::UIntervals(NCollection_Array1& T, const GeomAb case GeomAbs_CN: break; } - occ::handle myOffSurf = occ::down_cast(mySurface); - GeomAdaptor_Surface Sur(myOffSurf->BasisSurface(), myUFirst, myULast, myVFirst, myVLast); - Sur.UIntervals(T, BaseS); + std::get(mySurfaceData).BasisAdaptor->UIntervals(T, BaseS); return; } case GeomAbs_Plane: @@ -859,9 +847,7 @@ void GeomAdaptor_Surface::VIntervals(NCollection_Array1& T, const GeomAb case GeomAbs_CN: break; } - occ::handle myOffSurf = occ::down_cast(mySurface); - GeomAdaptor_Surface Sur(myOffSurf->BasisSurface(), myUFirst, myULast, myVFirst, myVLast); - Sur.VIntervals(T, BaseS); + std::get(mySurfaceData).BasisAdaptor->VIntervals(T, BaseS); return; } case GeomAbs_Plane: @@ -1739,11 +1725,8 @@ double GeomAdaptor_Surface::UResolution(const double R3d) const switch (mySurfaceType) { case GeomAbs_SurfaceOfExtrusion: { - GeomAdaptor_Curve myBasisCurve( - occ::down_cast(mySurface)->BasisCurve(), - myUFirst, - myULast); - return myBasisCurve.Resolution(R3d); + return std::get(mySurfaceData) + .BasisCurve->Resolution(R3d); } case GeomAbs_Torus: { occ::handle S(occ::down_cast(mySurface)); @@ -1794,10 +1777,8 @@ double GeomAdaptor_Surface::UResolution(const double R3d) const return Ures; } case GeomAbs_OffsetSurface: { - occ::handle base = - occ::down_cast(mySurface)->BasisSurface(); - GeomAdaptor_Surface gabase(base, myUFirst, myULast, myVFirst, myVLast); - return gabase.UResolution(R3d); + return std::get(mySurfaceData) + .BasisAdaptor->UResolution(R3d); } default: return Precision::Parametric(R3d); @@ -1818,11 +1799,8 @@ double GeomAdaptor_Surface::VResolution(const double R3d) const switch (mySurfaceType) { case GeomAbs_SurfaceOfRevolution: { - GeomAdaptor_Curve myBasisCurve( - occ::down_cast(mySurface)->BasisCurve(), - myUFirst, - myULast); - return myBasisCurve.Resolution(R3d); + return std::get(mySurfaceData) + .BasisCurve->Resolution(R3d); } case GeomAbs_Torus: { occ::handle S(occ::down_cast(mySurface)); @@ -1855,10 +1833,8 @@ double GeomAdaptor_Surface::VResolution(const double R3d) const return Vres; } case GeomAbs_OffsetSurface: { - occ::handle base = - occ::down_cast(mySurface)->BasisSurface(); - GeomAdaptor_Surface gabase(base, myUFirst, myULast, myVFirst, myVLast); - return gabase.VResolution(R3d); + return std::get(mySurfaceData) + .BasisAdaptor->VResolution(R3d); } default: return Precision::Parametric(R3d); @@ -1925,11 +1901,7 @@ int GeomAdaptor_Surface::UDegree() const return occ::down_cast(mySurface)->UDegree(); if (mySurfaceType == GeomAbs_SurfaceOfExtrusion) { - GeomAdaptor_Curve myBasisCurve( - occ::down_cast(mySurface)->BasisCurve(), - myUFirst, - myULast); - return myBasisCurve.Degree(); + return std::get(mySurfaceData).BasisCurve->Degree(); } throw Standard_NoSuchObject("GeomAdaptor_Surface::UDegree"); } @@ -1944,11 +1916,7 @@ int GeomAdaptor_Surface::NbUPoles() const return occ::down_cast(mySurface)->NbUPoles(); if (mySurfaceType == GeomAbs_SurfaceOfExtrusion) { - GeomAdaptor_Curve myBasisCurve( - occ::down_cast(mySurface)->BasisCurve(), - myUFirst, - myULast); - return myBasisCurve.NbPoles(); + return std::get(mySurfaceData).BasisCurve->NbPoles(); } throw Standard_NoSuchObject("GeomAdaptor_Surface::NbUPoles"); } @@ -1963,11 +1931,7 @@ int GeomAdaptor_Surface::VDegree() const return occ::down_cast(mySurface)->VDegree(); if (mySurfaceType == GeomAbs_SurfaceOfRevolution) { - GeomAdaptor_Curve myBasisCurve( - occ::down_cast(mySurface)->BasisCurve(), - myUFirst, - myULast); - return myBasisCurve.Degree(); + return std::get(mySurfaceData).BasisCurve->Degree(); } throw Standard_NoSuchObject("GeomAdaptor_Surface::VDegree"); } @@ -1982,11 +1946,7 @@ int GeomAdaptor_Surface::NbVPoles() const return occ::down_cast(mySurface)->NbVPoles(); if (mySurfaceType == GeomAbs_SurfaceOfRevolution) { - GeomAdaptor_Curve myBasisCurve( - occ::down_cast(mySurface)->BasisCurve(), - myUFirst, - myULast); - return myBasisCurve.NbPoles(); + return std::get(mySurfaceData).BasisCurve->NbPoles(); } throw Standard_NoSuchObject("GeomAdaptor_Surface::NbVPoles"); } @@ -1999,11 +1959,7 @@ int GeomAdaptor_Surface::NbUKnots() const return std::get(mySurfaceData).Surface->NbUKnots(); if (mySurfaceType == GeomAbs_SurfaceOfExtrusion) { - GeomAdaptor_Curve myBasisCurve( - occ::down_cast(mySurface)->BasisCurve(), - myUFirst, - myULast); - return myBasisCurve.NbKnots(); + return std::get(mySurfaceData).BasisCurve->NbKnots(); } throw Standard_NoSuchObject("GeomAdaptor_Surface::NbUKnots"); } diff --git a/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_Surface.hxx b/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_Surface.hxx index 3ceff119ee..7a4b102481 100644 --- a/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_Surface.hxx +++ b/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_Surface.hxx @@ -203,6 +203,12 @@ public: theV2 = LastVParameter(); } + //! Returns tolerance in U direction. + double ToleranceU() const { return myTolU; } + + //! Returns tolerance in V direction. + double ToleranceV() const { return myTolV; } + Standard_EXPORT GeomAbs_Shape UContinuity() const override; Standard_EXPORT GeomAbs_Shape VContinuity() const override; diff --git a/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_TransformedSurface.cxx b/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_TransformedSurface.cxx index e7722b9ac5..294364cc51 100644 --- a/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_TransformedSurface.cxx +++ b/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_TransformedSurface.cxx @@ -15,6 +15,17 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include IMPLEMENT_STANDARD_RTTIEXT(GeomAdaptor_TransformedSurface, Adaptor3d_Surface) @@ -30,6 +41,7 @@ GeomAdaptor_TransformedSurface::GeomAdaptor_TransformedSurface( : mySurf(theSurface), myTrsf(theTrsf) { + invalidateTransformedCache(); } //================================================================================================= @@ -46,6 +58,7 @@ GeomAdaptor_TransformedSurface::GeomAdaptor_TransformedSurface( : mySurf(theSurface, theUFirst, theULast, theVFirst, theVLast, theTolU, theTolV), myTrsf(theTrsf) { + invalidateTransformedCache(); } //================================================================================================= @@ -58,12 +71,135 @@ occ::handle GeomAdaptor_TransformedSurface::ShallowCopy() con const GeomAdaptor_Surface& aGeomSurface = *occ::down_cast(aSurface); aCopy->mySurf = aGeomSurface; aCopy->myTrsf = myTrsf; + aCopy->myTransformedAdaptor = myTransformedAdaptor; return aCopy; } //================================================================================================= +void GeomAdaptor_TransformedSurface::Load(const occ::handle& theSurface, + const gp_Trsf& theTrsf) +{ + mySurf.Load(theSurface); + myTrsf = theTrsf; + invalidateTransformedCache(); +} + +//================================================================================================= + +void GeomAdaptor_TransformedSurface::Load(const occ::handle& theSurface, + const double theUFirst, + const double theULast, + const double theVFirst, + const double theVLast, + const gp_Trsf& theTrsf, + const double theTolU, + const double theTolV) +{ + mySurf.Load(theSurface, theUFirst, theULast, theVFirst, theVLast, theTolU, theTolV); + myTrsf = theTrsf; + invalidateTransformedCache(); +} + +//================================================================================================= + +void GeomAdaptor_TransformedSurface::SetTrsf(const gp_Trsf& theTrsf) +{ + myTrsf = theTrsf; + invalidateTransformedCache(); +} + +//================================================================================================= + +const occ::handle& GeomAdaptor_TransformedSurface::GeomSurfaceTransformed() const +{ + if (myTrsf.Form() == gp_Identity) + { + return mySurf.Surface(); + } + + ensureTransformedCache(); + return myTransformedAdaptor->Surface(); +} + +//================================================================================================= + +void GeomAdaptor_TransformedSurface::invalidateTransformedCache() +{ + myTransformedAdaptor.reset(); +} + +//================================================================================================= + +void GeomAdaptor_TransformedSurface::ensureTransformedCache() const +{ + if (myTrsf.Form() == gp_Identity || myTransformedAdaptor.has_value()) + { + return; + } + initTransformedCache(); +} + +//================================================================================================= + +void GeomAdaptor_TransformedSurface::initTransformedCache() const +{ + if (mySurf.Surface().IsNull()) + { + myTransformedAdaptor.emplace(); + return; + } + + const bool isIdentity = myTrsf.Form() == gp_Identity; + const gp_Trsf& aTrsf = myTrsf; + occ::handle aSurface; + switch (mySurf.GetType()) + { + case GeomAbs_Plane: + aSurface = isIdentity + ? mySurf.Surface() + : occ::handle(new Geom_Plane(mySurf.Plane().Transformed(aTrsf))); + break; + case GeomAbs_Cylinder: + aSurface = isIdentity ? mySurf.Surface() + : occ::handle( + new Geom_CylindricalSurface(mySurf.Cylinder().Transformed(aTrsf))); + break; + case GeomAbs_Cone: + aSurface = + isIdentity + ? mySurf.Surface() + : occ::handle(new Geom_ConicalSurface(mySurf.Cone().Transformed(aTrsf))); + break; + case GeomAbs_Sphere: + aSurface = isIdentity ? mySurf.Surface() + : occ::handle( + new Geom_SphericalSurface(mySurf.Sphere().Transformed(aTrsf))); + break; + case GeomAbs_Torus: + aSurface = + isIdentity + ? mySurf.Surface() + : occ::handle(new Geom_ToroidalSurface(mySurf.Torus().Transformed(aTrsf))); + break; + default: + aSurface = isIdentity ? mySurf.Surface() + : occ::down_cast(mySurf.Surface()->Transformed(aTrsf)); + break; + } + + myTransformedAdaptor.emplace(aSurface, + mySurf.FirstUParameter(), + mySurf.LastUParameter(), + mySurf.FirstVParameter(), + mySurf.LastVParameter(), + mySurf.ToleranceU(), + mySurf.ToleranceV()); +} + +//================================================================================================= + void GeomAdaptor_TransformedSurface::UIntervals(NCollection_Array1& theT, const GeomAbs_Shape theS) const { @@ -84,9 +220,7 @@ occ::handle GeomAdaptor_TransformedSurface::UTrim(const doubl const double theLast, const double theTol) const { - occ::handle HS = new GeomAdaptor_Surface(); - HS->Load(occ::down_cast(mySurf.Surface()->Transformed(myTrsf))); - return HS->UTrim(theFirst, theLast, theTol); + return transformedAdaptor().UTrim(theFirst, theLast, theTol); } //================================================================================================= @@ -95,15 +229,17 @@ occ::handle GeomAdaptor_TransformedSurface::VTrim(const doubl const double theLast, const double theTol) const { - occ::handle HS = new GeomAdaptor_Surface(); - HS->Load(occ::down_cast(mySurf.Surface()->Transformed(myTrsf))); - return HS->VTrim(theFirst, theLast, theTol); + return transformedAdaptor().VTrim(theFirst, theLast, theTol); } //================================================================================================= gp_Pnt GeomAdaptor_TransformedSurface::EvalD0(double theU, double theV) const { + if (myTrsf.Form() == gp_Identity) + { + return mySurf.EvalD0(theU, theV); + } return mySurf.EvalD0(theU, theV).Transformed(myTrsf); } @@ -111,6 +247,10 @@ gp_Pnt GeomAdaptor_TransformedSurface::EvalD0(double theU, double theV) const Geom_Surface::ResD1 GeomAdaptor_TransformedSurface::EvalD1(double theU, double theV) const { + if (myTrsf.Form() == gp_Identity) + { + return mySurf.EvalD1(theU, theV); + } Geom_Surface::ResD1 aRes = mySurf.EvalD1(theU, theV); aRes.Point.Transform(myTrsf); aRes.D1U.Transform(myTrsf); @@ -122,6 +262,10 @@ Geom_Surface::ResD1 GeomAdaptor_TransformedSurface::EvalD1(double theU, double t Geom_Surface::ResD2 GeomAdaptor_TransformedSurface::EvalD2(double theU, double theV) const { + if (myTrsf.Form() == gp_Identity) + { + return mySurf.EvalD2(theU, theV); + } Geom_Surface::ResD2 aRes = mySurf.EvalD2(theU, theV); aRes.Point.Transform(myTrsf); aRes.D1U.Transform(myTrsf); @@ -136,6 +280,10 @@ Geom_Surface::ResD2 GeomAdaptor_TransformedSurface::EvalD2(double theU, double t Geom_Surface::ResD3 GeomAdaptor_TransformedSurface::EvalD3(double theU, double theV) const { + if (myTrsf.Form() == gp_Identity) + { + return mySurf.EvalD3(theU, theV); + } Geom_Surface::ResD3 aRes = mySurf.EvalD3(theU, theV); aRes.Point.Transform(myTrsf); aRes.D1U.Transform(myTrsf); @@ -154,6 +302,10 @@ Geom_Surface::ResD3 GeomAdaptor_TransformedSurface::EvalD3(double theU, double t gp_Vec GeomAdaptor_TransformedSurface::EvalDN(double theU, double theV, int theNu, int theNv) const { + if (myTrsf.Form() == gp_Identity) + { + return mySurf.EvalDN(theU, theV, theNu, theNv); + } return mySurf.EvalDN(theU, theV, theNu, theNv).Transformed(myTrsf); } @@ -161,86 +313,95 @@ gp_Vec GeomAdaptor_TransformedSurface::EvalDN(double theU, double theV, int theN gp_Pln GeomAdaptor_TransformedSurface::Plane() const { - return mySurf.Plane().Transformed(myTrsf); + return transformedAdaptor().Plane(); } //================================================================================================= gp_Cylinder GeomAdaptor_TransformedSurface::Cylinder() const { - return mySurf.Cylinder().Transformed(myTrsf); + return transformedAdaptor().Cylinder(); } //================================================================================================= gp_Cone GeomAdaptor_TransformedSurface::Cone() const { - return mySurf.Cone().Transformed(myTrsf); + return transformedAdaptor().Cone(); } //================================================================================================= gp_Sphere GeomAdaptor_TransformedSurface::Sphere() const { - return mySurf.Sphere().Transformed(myTrsf); + return transformedAdaptor().Sphere(); } //================================================================================================= gp_Torus GeomAdaptor_TransformedSurface::Torus() const { - return mySurf.Torus().Transformed(myTrsf); + return transformedAdaptor().Torus(); } //================================================================================================= occ::handle GeomAdaptor_TransformedSurface::Bezier() const { - return occ::down_cast(mySurf.Bezier()->Transformed(myTrsf)); + return transformedAdaptor().Bezier(); } //================================================================================================= occ::handle GeomAdaptor_TransformedSurface::BSpline() const { - return occ::down_cast(mySurf.BSpline()->Transformed(myTrsf)); + return transformedAdaptor().BSpline(); } //================================================================================================= gp_Ax1 GeomAdaptor_TransformedSurface::AxeOfRevolution() const { - return mySurf.AxeOfRevolution().Transformed(myTrsf); + return transformedAdaptor().AxeOfRevolution(); } //================================================================================================= gp_Dir GeomAdaptor_TransformedSurface::Direction() const { - return mySurf.Direction().Transformed(myTrsf); + return transformedAdaptor().Direction(); } //================================================================================================= occ::handle GeomAdaptor_TransformedSurface::BasisCurve() const { - occ::handle HS = new GeomAdaptor_Surface(); - HS->Load(occ::down_cast(mySurf.Surface()->Transformed(myTrsf))); - return HS->BasisCurve(); + return transformedAdaptor().BasisCurve(); } //================================================================================================= occ::handle GeomAdaptor_TransformedSurface::BasisSurface() const { - occ::handle HS = new GeomAdaptor_Surface(); - HS->Load(occ::down_cast(mySurf.Surface()->Transformed(myTrsf))); - return HS->BasisSurface(); + return transformedAdaptor().BasisSurface(); } //================================================================================================= double GeomAdaptor_TransformedSurface::OffsetValue() const { - return mySurf.OffsetValue(); + return transformedAdaptor().OffsetValue(); +} + +//================================================================================================= + +const GeomAdaptor_Surface& GeomAdaptor_TransformedSurface::transformedAdaptor() const +{ + if (myTrsf.Form() == gp_Identity) + { + return mySurf; + } + + ensureTransformedCache(); + return *myTransformedAdaptor; } diff --git a/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_TransformedSurface.hxx b/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_TransformedSurface.hxx index 39a4fc4ce0..b4bf5ad975 100644 --- a/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_TransformedSurface.hxx +++ b/src/ModelingData/TKG3d/GeomAdaptor/GeomAdaptor_TransformedSurface.hxx @@ -18,6 +18,12 @@ #include #include +#include + +class Geom_BezierSurface; +class Geom_BSplineSurface; +class Geom_Surface; + //! An adaptor for surfaces with an applied transformation. //! //! This class wraps a GeomAdaptor_Surface and applies a gp_Trsf transformation @@ -63,7 +69,8 @@ public: //! Loads the surface geometry. //! @param theSurface underlying geometry - void Load(const occ::handle& theSurface) { mySurf.Load(theSurface); } + //! @param theTrsf transformation to apply + Standard_EXPORT void Load(const occ::handle& theSurface, const gp_Trsf& theTrsf); //! Loads the surface geometry with parameter bounds. //! @param theSurface underlying geometry @@ -71,34 +78,45 @@ public: //! @param theULast maximum U parameter //! @param theVFirst minimum V parameter //! @param theVLast maximum V parameter + //! @param theTrsf transformation to apply //! @param theTolU tolerance in U direction //! @param theTolV tolerance in V direction - void Load(const occ::handle& theSurface, - const double theUFirst, - const double theULast, - const double theVFirst, - const double theVLast, - const double theTolU = 0.0, - const double theTolV = 0.0) - { - mySurf.Load(theSurface, theUFirst, theULast, theVFirst, theVLast, theTolU, theTolV); - } + Standard_EXPORT void Load(const occ::handle& theSurface, + const double theUFirst, + const double theULast, + const double theVFirst, + const double theVLast, + const gp_Trsf& theTrsf, + const double theTolU = 0.0, + const double theTolV = 0.0); //! Sets the transformation. //! @param theTrsf transformation to apply - void SetTrsf(const gp_Trsf& theTrsf) { myTrsf = theTrsf; } + Standard_EXPORT void SetTrsf(const gp_Trsf& theTrsf); + + //! Returns true if non-identity transformation is applied. + bool HasTrsf() const { return myTrsf.Form() != gp_Identity; } //! Returns the transformation. const gp_Trsf& Trsf() const { return myTrsf; } //! Returns the underlying GeomAdaptor_Surface. + Standard_DEPRECATED( + "Use AdaptorSurfaceOriginal() instead to get the original surface without transformation") const GeomAdaptor_Surface& Surface() const { return mySurf; } - //! Returns the underlying GeomAdaptor_Surface for modification. - GeomAdaptor_Surface& ChangeSurface() { return mySurf; } + //! Returns the underlying original GeomAdaptor_Surface without transformation applied. + const GeomAdaptor_Surface& AdaptorSurfaceOriginal() const { return mySurf; } + + //! Returns the underlying original Geom_Surface without transformation applied. + const occ::handle& GeomSurfaceOriginal() const { return mySurf.Surface(); } + + //! Returns the transformed Geom_Surface cached for current state. + Standard_EXPORT const occ::handle& GeomSurfaceTransformed() const; //! Returns the underlying Geom_Surface. - const occ::handle& GeomSurface() const { return mySurf.Surface(); } + Standard_DEPRECATED("Use GeomSurfaceOriginal() or GeomSurfaceTransformed() instead") + const occ::handle& GeomSurface() const { return GeomSurfaceOriginal(); } // Parameter range methods - delegate to underlying surface double FirstUParameter() const override { return mySurf.FirstUParameter(); } @@ -143,6 +161,12 @@ public: double VPeriod() const override { return mySurf.VPeriod(); } + //! Returns tolerance in U direction. + double ToleranceU() const { return mySurf.ToleranceU(); } + + //! Returns tolerance in V direction. + double ToleranceV() const { return mySurf.ToleranceV(); } + //! Point evaluation. Applies transformation after evaluation. [[nodiscard]] Standard_EXPORT gp_Pnt EvalD0(const double theU, const double theV) const final; @@ -211,8 +235,25 @@ public: Standard_EXPORT double OffsetValue() const override; protected: - GeomAdaptor_Surface mySurf; - gp_Trsf myTrsf; + //! Invalidates transformed cache for subsequent lazy rebuild. + void invalidateTransformedCache(); + + //! Ensures transformed cache is built on demand. + //! Non-thread-safe: mutable cache is initialized in const context without synchronization. + void ensureTransformedCache() const; + + //! Rebuilds transformed geometry for current surface and transformation. + //! Non-thread-safe: invoked by ensureTransformedCache() for lazy initialization. + void initTransformedCache() const; + + //! Returns an adaptor for the transformed surface state. + //! Uses the original adaptor for identity transformation to preserve existing trimming. + const GeomAdaptor_Surface& transformedAdaptor() const; + +protected: + GeomAdaptor_Surface mySurf; + gp_Trsf myTrsf; + mutable std::optional myTransformedAdaptor; }; #endif // _GeomAdaptor_TransformedSurface_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.cxx index 5df76ee7cd..6342d8c41e 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.cxx @@ -152,7 +152,7 @@ void GeomGridEval_Surface::initialization(const Adaptor3d_Surface& theSurface) } // Initialize with the underlying Geom_Surface - initialization(aTransformed.GeomSurface()); + initialization(aTransformed.GeomSurfaceOriginal()); return; } diff --git a/src/Visualization/TKV3d/PrsDim/PrsDim.cxx b/src/Visualization/TKV3d/PrsDim/PrsDim.cxx index a3213386f9..33d3b36d1f 100644 --- a/src/Visualization/TKV3d/PrsDim/PrsDim.cxx +++ b/src/Visualization/TKV3d/PrsDim/PrsDim.cxx @@ -755,9 +755,7 @@ bool PrsDim::GetPlaneFromFace(const TopoDS_Face& aFace, else surf2 = new BRepAdaptor_Surface(surf1); - aSurf = surf1.Surface().Surface(); - // aSurf->Transform(surf1.Trsf()) ; - aSurf = occ::down_cast(aSurf->Transformed(surf1.Trsf())); + aSurf = surf1.GeomSurfaceTransformed(); if (surf2->GetType() == GeomAbs_Plane) { diff --git a/src/Visualization/TKV3d/StdPrs/StdPrs_WFRestrictedFace.cxx b/src/Visualization/TKV3d/StdPrs/StdPrs_WFRestrictedFace.cxx index c694effaa0..20a2de0872 100755 --- a/src/Visualization/TKV3d/StdPrs/StdPrs_WFRestrictedFace.cxx +++ b/src/Visualization/TKV3d/StdPrs/StdPrs_WFRestrictedFace.cxx @@ -60,10 +60,10 @@ void StdPrs_WFRestrictedFace::Add( aBndBox.Get(aUMin, aVMin, aUMax, aVMax); else { // No pcurves -- take natural bounds - aUMin = theFace->Surface().FirstUParameter(); - aVMin = theFace->Surface().FirstVParameter(); - aUMax = theFace->Surface().LastUParameter(); - aVMax = theFace->Surface().LastVParameter(); + aUMin = theFace->FirstUParameter(); + aVMin = theFace->FirstVParameter(); + aUMax = theFace->LastUParameter(); + aVMax = theFace->LastVParameter(); } // Load the isos