diff --git a/src/DataExchange/TKDEIGES/DEIGES/DEIGES_Parameters.hxx b/src/DataExchange/TKDEIGES/DEIGES/DEIGES_Parameters.hxx index 82088bf2a2..86b87ab062 100644 --- a/src/DataExchange/TKDEIGES/DEIGES/DEIGES_Parameters.hxx +++ b/src/DataExchange/TKDEIGES/DEIGES/DEIGES_Parameters.hxx @@ -126,4 +126,4 @@ public: // clang-format on }; -#endif // _DESTEP_Parameters_HeaderFile +#endif // _DEIGES_Parameters_HeaderFile diff --git a/src/DataExchange/TKDESTEP/DESTEP/DESTEP_ConfigurationNode.cxx b/src/DataExchange/TKDESTEP/DESTEP/DESTEP_ConfigurationNode.cxx index 3d1395350b..b35be0c85e 100644 --- a/src/DataExchange/TKDESTEP/DESTEP/DESTEP_ConfigurationNode.cxx +++ b/src/DataExchange/TKDESTEP/DESTEP/DESTEP_ConfigurationNode.cxx @@ -200,6 +200,8 @@ bool DESTEP_ConfigurationNode::Load(const Handle(DE_ConfigurationContext)& theRe aScope); InternalParameters.CleanDuplicates = theResource->BooleanVal("write.cleanduplicates", InternalParameters.CleanDuplicates, aScope); + InternalParameters.WriteScalingTrsf = + theResource->BooleanVal("write.scaling.trsf", InternalParameters.WriteScalingTrsf, aScope); return DE_ShapeFixConfigurationNode::Load(theResource); } @@ -589,6 +591,13 @@ TCollection_AsciiString DESTEP_ConfigurationNode::Save() const aResult += aScope + "write.cleanduplicates :\t " + InternalParameters.CleanDuplicates + "\n"; aResult += "!\n"; + aResult += "!\n"; + aResult += + "!Defines export scaling factor in transformation as Cartesian Operator (On) or skip(Off)"; + aResult += "!Default value: 1(\"On\"). Available values: 0(\"OFF\"), 1(\"On\")\n"; + aResult += aScope + "write.scaling.trsf :\t " + InternalParameters.WriteScalingTrsf + "\n"; + aResult += "!\n"; + aResult += DE_ShapeFixConfigurationNode::Save(); aResult += "!*****************************************************************************\n"; diff --git a/src/DataExchange/TKDESTEP/DESTEP/DESTEP_Parameters.hxx b/src/DataExchange/TKDESTEP/DESTEP/DESTEP_Parameters.hxx index c4557fec45..16f702309c 100644 --- a/src/DataExchange/TKDESTEP/DESTEP/DESTEP_Parameters.hxx +++ b/src/DataExchange/TKDESTEP/DESTEP/DESTEP_Parameters.hxx @@ -203,6 +203,7 @@ public: bool WriteVisMaterial = false; // + +#include +#include +#include + +//============================================================================= + +GeomToStep_MakeCartesianTransformationOperator::GeomToStep_MakeCartesianTransformationOperator( + const gp_Trsf& theTrsf, + const StepData_Factors& theLocalFactors) +{ + gp_Trsf anInvTrsf = theTrsf; + anInvTrsf.Invert(); + Standard_Real aScale = anInvTrsf.ScaleFactor(); + gp_Mat anInvMat = anInvTrsf.HVectorialPart(); + + gp_Mat aMat = theTrsf.HVectorialPart(); + gp_XYZ aTranslation = anInvTrsf.TranslationPart().Multiplied(aMat); + aTranslation.Reverse(); + + GeomToStep_MakeCartesianPoint aMkPoint(aTranslation, theLocalFactors.LengthFactor()); + GeomToStep_MakeDirection aMkDir1(anInvMat.Row(1)); + GeomToStep_MakeDirection aMkDir2(anInvMat.Row(2)); + GeomToStep_MakeDirection aMkDir3(anInvMat.Row(3)); + + myTrsfOp = new StepGeom_CartesianTransformationOperator3d(); + myTrsfOp->SetName(new TCollection_HAsciiString("")); + myTrsfOp->SetAxis1(aMkDir1.Value()); + myTrsfOp->SetAxis2(aMkDir2.Value()); + myTrsfOp->SetAxis3(aMkDir3.Value()); + myTrsfOp->SetLocalOrigin(aMkPoint.Value()); + myTrsfOp->SetScale(aScale); + + done = Standard_True; +} diff --git a/src/DataExchange/TKDESTEP/GeomToStep/GeomToStep_MakeCartesianTransformationOperator.hxx b/src/DataExchange/TKDESTEP/GeomToStep/GeomToStep_MakeCartesianTransformationOperator.hxx new file mode 100644 index 0000000000..d6d5598855 --- /dev/null +++ b/src/DataExchange/TKDESTEP/GeomToStep/GeomToStep_MakeCartesianTransformationOperator.hxx @@ -0,0 +1,53 @@ +// Copyright (c) 2025 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. + +#ifndef _GeomToStep_MakeCartesianTransformationOperator_HeaderFile +#define _GeomToStep_MakeCartesianTransformationOperator_HeaderFile + +#include +#include +#include + +#include +#include +#include + +class gp_Trsf; + +//! This class creates a cartesian_transformation_operator from gp_Trsf. +//! This entity is used in OCCT to implement a transformation with scaling. +//! In case of other inputs without scaling use Axis2Placement3d. +class GeomToStep_MakeCartesianTransformationOperator : public GeomToStep_Root +{ +public: + DEFINE_STANDARD_ALLOC + + //! Main constructor. + //! @param[in] theTrsf Transformation to create the operator from it. + //! @param[in] theLocalFactors Unit scale factors + Standard_EXPORT GeomToStep_MakeCartesianTransformationOperator( + const gp_Trsf& theTrsf, + const StepData_Factors& theLocalFactors = StepData_Factors()); + + //! Returns the created entity. + //! @return The created value. + inline const Handle(StepGeom_CartesianTransformationOperator3d)& Value() const + { + return myTrsfOp; + } + +private: + Handle(StepGeom_CartesianTransformationOperator3d) myTrsfOp; +}; + +#endif // _GeomToStep_MakeCartesianTransformationOperator_HeaderFile diff --git a/src/DataExchange/TKDESTEP/STEPConstruct/STEPConstruct_Assembly.cxx b/src/DataExchange/TKDESTEP/STEPConstruct/STEPConstruct_Assembly.cxx index 37b26b09da..551fa9a58a 100644 --- a/src/DataExchange/TKDESTEP/STEPConstruct/STEPConstruct_Assembly.cxx +++ b/src/DataExchange/TKDESTEP/STEPConstruct/STEPConstruct_Assembly.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -51,8 +52,25 @@ void STEPConstruct_Assembly::Init(const Handle(StepShape_ShapeDefinitionRepresen thesr = Handle(StepShape_ShapeRepresentation)::DownCast(aSDR->UsedRepresentation()); thesr0 = Handle(StepShape_ShapeRepresentation)::DownCast(SDR0->UsedRepresentation()); theval.Nullify(); - theax0 = Ax0; - theloc = AxLoc; + theax0 = Ax0; + theloc = AxLoc; + myIsCartesianTrsf = false; +} + +//================================================================================================= + +void STEPConstruct_Assembly::Init( + const Handle(StepShape_ShapeDefinitionRepresentation)& aSDR, + const Handle(StepShape_ShapeDefinitionRepresentation)& SDR0, + const Handle(StepGeom_CartesianTransformationOperator3d)& theTrsfOp) +{ + thesdr = aSDR; + thesdr0 = SDR0; + thesr = Handle(StepShape_ShapeRepresentation)::DownCast(aSDR->UsedRepresentation()); + thesr0 = Handle(StepShape_ShapeRepresentation)::DownCast(SDR0->UsedRepresentation()); + theval.Nullify(); + myTrsfOp = theTrsfOp; + myIsCartesianTrsf = true; } //================================================================================================= @@ -91,10 +109,19 @@ void STEPConstruct_Assembly::MakeRelationship() PDS->Init(pdsname, Standard_True, pdsdesc, CD); // create transformation - Handle(StepRepr_ItemDefinedTransformation) ItemDef = new StepRepr_ItemDefinedTransformation; - Handle(TCollection_HAsciiString) idname = new TCollection_HAsciiString(""); - Handle(TCollection_HAsciiString) idescr = new TCollection_HAsciiString(""); - ItemDef->Init(idname, idescr, theax0, theloc); + Handle(Standard_Transient) aTrsfItem; + if (!myIsCartesianTrsf) + { + Handle(StepRepr_ItemDefinedTransformation) ItemDef = new StepRepr_ItemDefinedTransformation; + Handle(TCollection_HAsciiString) idname = new TCollection_HAsciiString(""); + Handle(TCollection_HAsciiString) idescr = new TCollection_HAsciiString(""); + ItemDef->Init(idname, idescr, theax0, theloc); + aTrsfItem = ItemDef; + } + else + { + aTrsfItem = myTrsfOp; + } // create SRRWT Handle(StepRepr_ShapeRepresentationRelationshipWithTransformation) SRRWT = @@ -102,7 +129,7 @@ void STEPConstruct_Assembly::MakeRelationship() Handle(TCollection_HAsciiString) stname = new TCollection_HAsciiString(""); Handle(TCollection_HAsciiString) stescr = new TCollection_HAsciiString(""); StepRepr_Transformation StepTrans; - StepTrans.SetValue(ItemDef); + StepTrans.SetValue(aTrsfItem); SRRWT->Init(stname, stescr, thesr, thesr0, StepTrans); // create CDSR (final result, root) diff --git a/src/DataExchange/TKDESTEP/STEPConstruct/STEPConstruct_Assembly.hxx b/src/DataExchange/TKDESTEP/STEPConstruct/STEPConstruct_Assembly.hxx index a3bcef0895..f2e037f0aa 100644 --- a/src/DataExchange/TKDESTEP/STEPConstruct/STEPConstruct_Assembly.hxx +++ b/src/DataExchange/TKDESTEP/STEPConstruct/STEPConstruct_Assembly.hxx @@ -24,6 +24,7 @@ class StepShape_ShapeDefinitionRepresentation; class StepShape_ShapeRepresentation; class StepGeom_Axis2Placement3d; +class StepGeom_CartesianTransformationOperator3d; class StepRepr_NextAssemblyUsageOccurrence; class StepShape_ContextDependentShapeRepresentation; class Interface_Graph; @@ -52,6 +53,14 @@ public: const Handle(StepGeom_Axis2Placement3d)& Ax0, const Handle(StepGeom_Axis2Placement3d)& Loc); + //! Initialises with starting values + //! theTrsfOp : local transformation to apply, may have scaling factor + //! Makes a MappedItem + //! Resulting Value is returned by ItemValue + Standard_EXPORT void Init(const Handle(StepShape_ShapeDefinitionRepresentation)& theSR, + const Handle(StepShape_ShapeDefinitionRepresentation)& theSDR0, + const Handle(StepGeom_CartesianTransformationOperator3d)& theTrsfOp); + //! Make a (ShapeRepresentationRelationship,...WithTransformation) //! Resulting Value is returned by ItemValue Standard_EXPORT void MakeRelationship(); @@ -74,13 +83,15 @@ public: protected: private: - Handle(StepShape_ShapeDefinitionRepresentation) thesdr; - Handle(StepShape_ShapeDefinitionRepresentation) thesdr0; - Handle(StepShape_ShapeRepresentation) thesr; - Handle(StepShape_ShapeRepresentation) thesr0; - Handle(Standard_Transient) theval; - Handle(StepGeom_Axis2Placement3d) theloc; - Handle(StepGeom_Axis2Placement3d) theax0; + Handle(StepShape_ShapeDefinitionRepresentation) thesdr; + Handle(StepShape_ShapeDefinitionRepresentation) thesdr0; + Handle(StepShape_ShapeRepresentation) thesr; + Handle(StepShape_ShapeRepresentation) thesr0; + Handle(Standard_Transient) theval; + Handle(StepGeom_Axis2Placement3d) theloc; + Handle(StepGeom_Axis2Placement3d) theax0; + Handle(StepGeom_CartesianTransformationOperator3d) myTrsfOp; + bool myIsCartesianTrsf; }; #endif // _STEPConstruct_Assembly_HeaderFile diff --git a/src/DataExchange/TKDESTEP/STEPControl/STEPControl_ActorWrite.cxx b/src/DataExchange/TKDESTEP/STEPControl/STEPControl_ActorWrite.cxx index 4f4b1e0dc1..033070539a 100644 --- a/src/DataExchange/TKDESTEP/STEPControl/STEPControl_ActorWrite.cxx +++ b/src/DataExchange/TKDESTEP/STEPControl/STEPControl_ActorWrite.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -1656,8 +1658,8 @@ Handle(Transfer_Binder) STEPControl_ActorWrite::TransferCompound( Message_ProgressScope aPS(theProgress, NULL, nbs); for (i = 1; i <= nbs && aPS.More(); i++) { - Handle(TransferBRep_ShapeMapper) subs = TransferBRep::ShapeMapper(FP, RepItemSeq->Value(i)); - Handle(StepGeom_Axis2Placement3d) AX1; + Handle(TransferBRep_ShapeMapper) subs = TransferBRep::ShapeMapper(FP, RepItemSeq->Value(i)); + Handle(StepGeom_GeometricRepresentationItem) AX1; Handle(Transfer_Binder) bnd = TransferSubShape(subs, SDR0, @@ -1709,7 +1711,7 @@ Handle(Transfer_Binder) STEPControl_ActorWrite::TransferCompound( Handle(Transfer_Binder) STEPControl_ActorWrite::TransferSubShape( const Handle(Transfer_Finder)& start, const Handle(StepShape_ShapeDefinitionRepresentation)& SDR0, - Handle(StepGeom_Axis2Placement3d)& AX1, + Handle(StepGeom_GeometricRepresentationItem)& AX1, const Handle(Transfer_FinderProcess)& FP, const StepData_Factors& theLocalFactors, const Handle(TopTools_HSequenceOfShape)& shapeGroup, @@ -1781,14 +1783,39 @@ Handle(Transfer_Binder) STEPControl_ActorWrite::TransferSubShape( // FP->GetTypedTransient (resbind,STANDARD_TYPE(StepShape_ShapeRepresentation),resultat); // sdr->SetUsedRepresentation(resultat); // to be used by MakeItem - // make location for assembly placement - GeomToStep_MakeAxis2Placement3d mkax(aLoc, theLocalFactors); - const Handle(StepGeom_Axis2Placement3d)& AxLoc = mkax.Value(); - AX1 = AxLoc; - // create assembly structures (CDSR, NAUO etc.) STEPConstruct_Assembly mkitem; - mkitem.Init(sdr, SDR0, myContext.GetDefaultAxis(), AxLoc); + + // make location for assembly placement + if (Abs(aLoc.ScaleFactor() - 1.0) > Precision::Confusion()) + { + if (aStepModel->InternalParameters.WriteScalingTrsf) + FP->AddWarning( + start, + "The shape has a scaling factor, exported as cartesian_transformation_operator"); + else + FP->AddWarning(start, "The shape has a scaling factor, skipped"); + } + if (Abs(aLoc.ScaleFactor() - 1.0) < Precision::Confusion() + || !aStepModel->InternalParameters.WriteScalingTrsf) + { + // create a new axis2placement3d + GeomToStep_MakeAxis2Placement3d mkax(aLoc, theLocalFactors); + mkitem.Init(sdr, SDR0, myContext.GetDefaultAxis(), mkax.Value()); + AX1 = mkax.Value(); + } + else + { + // create a new cartesian transformation + GeomToStep_MakeCartesianTransformationOperator aMaker(aLoc, theLocalFactors); + if (!aMaker.IsDone()) + { + FP->AddFail(start, "The transfomation relation creation failed"); + } + mkitem.Init(sdr, SDR0, aMaker.Value()); + AX1 = aMaker.Value(); + } + mkitem.MakeRelationship(); Handle(TColStd_HSequenceOfTransient) roots = myContext.GetRootsForAssemblyLink(mkitem); diff --git a/src/DataExchange/TKDESTEP/STEPControl/STEPControl_ActorWrite.hxx b/src/DataExchange/TKDESTEP/STEPControl/STEPControl_ActorWrite.hxx index 84b6a0a796..20e239cf20 100644 --- a/src/DataExchange/TKDESTEP/STEPControl/STEPControl_ActorWrite.hxx +++ b/src/DataExchange/TKDESTEP/STEPControl/STEPControl_ActorWrite.hxx @@ -29,7 +29,7 @@ class Transfer_Finder; class Transfer_Binder; class Transfer_FinderProcess; class StepShape_ShapeDefinitionRepresentation; -class StepGeom_Axis2Placement3d; +class StepGeom_GeometricRepresentationItem; class TopoDS_Shape; class StepShape_NonManifoldSurfaceShapeRepresentation; @@ -55,7 +55,7 @@ public: Standard_EXPORT Handle(Transfer_Binder) TransferSubShape( const Handle(Transfer_Finder)& start, const Handle(StepShape_ShapeDefinitionRepresentation)& SDR, - Handle(StepGeom_Axis2Placement3d)& AX1, + Handle(StepGeom_GeometricRepresentationItem)& AX1, const Handle(Transfer_FinderProcess)& FP, const StepData_Factors& theLocalFactors = StepData_Factors(), const Handle(TopTools_HSequenceOfShape)& shapeGroup = NULL, diff --git a/src/DataExchange/TKDESTEP/StepToGeom/StepToGeom.cxx b/src/DataExchange/TKDESTEP/StepToGeom/StepToGeom.cxx index f67a75741b..9c4a9201f1 100644 --- a/src/DataExchange/TKDESTEP/StepToGeom/StepToGeom.cxx +++ b/src/DataExchange/TKDESTEP/StepToGeom/StepToGeom.cxx @@ -2131,6 +2131,10 @@ Standard_Boolean StepToGeom::MakeTransformation3d( const gp_Ax3 result(Pgp, D3, D1); CT.SetTransformation(result); + if (SCTO->HasScale()) + { + CT.SetScaleFactor(SCTO->Scale()); + } CT = CT.Inverted(); //: n8 abv 16 Feb 99: tr8_as2_db.stp: reverse for accordance with LV tool return Standard_True; } diff --git a/tests/bugs/step/bug_ocp1949 b/tests/bugs/step/bug_ocp1949 new file mode 100644 index 0000000000..6e3d5b7af3 --- /dev/null +++ b/tests/bugs/step/bug_ocp1949 @@ -0,0 +1,51 @@ +puts "================================================" +puts "OCP-1949: Apply a scaling transformation to STEP" +puts "================================================" +puts "" + +pload OCAF + +Close D1 -silent +Close D2 -silent + +ReadGltf D1 [locate_data_file bug_ocp1948_PSU_Cartoning_subunit__right-01.01.01.03-CART-03_green_bottom.glb] + +# apply parameters for tessellation export +set conf " +provider.STEP.OCC.write.schema : 5 +provider.STEP.OCC.write.tessellated : 1 +" +LoadConfiguration ${conf} -recursive on +param write.step.schema 5 +param write.step.tessellated 1 + +WriteStep D1 "$imagedir/${casename}.stp" +ReadStep D2 "$imagedir/${casename}.stp" + +XGetOneShape a1 D1 +XGetOneShape a2 D2 + +# check center of gravity +set pos1 [vprops a1] +set pos2 [vprops a2] + +set REF_X [lindex $pos1 9] +set REF_Y [lindex $pos1 12] +set REF_Z [lindex $pos1 15] +set tol 1e-4 + +if {([expr abs($REF_X - [lindex $pos2 9])] > $tol) || + ([expr abs($REF_Y - [lindex $pos2 12])] > $tol) || + ([expr abs($REF_Z - [lindex $pos2 15])] > $tol)} { + puts "Error: wrong position of the imported model." + } + +# cleaning +Close D1 +Close D2 +file delete "$imagedir/${casename}.stp" +set conf " +provider.STEP.OCC.write.schema : 4 +provider.STEP.OCC.write.tessellated : 2 +" +LoadConfiguration ${conf} -recursive on diff --git a/tests/bugs/xde/bug27142 b/tests/bugs/xde/bug27142 index 49a76ca165..4bf74aea42 100644 --- a/tests/bugs/xde/bug27142 +++ b/tests/bugs/xde/bug27142 @@ -3,7 +3,6 @@ puts "0027142: Data Exchange - add possibility to set location in XCAFDoc_ShapeT puts "==========" puts "" -puts "TODO 0027142 ALL: Error: area of d1" puts "TODO 0027142 ALL: Error: area of d2" puts "TODO 0027142 ALL: Error: center of gravity" diff --git a/tests/de_wrapper/configuration/A3 b/tests/de_wrapper/configuration/A3 index 9401a71317..cf0895b777 100644 --- a/tests/de_wrapper/configuration/A3 +++ b/tests/de_wrapper/configuration/A3 @@ -199,6 +199,7 @@ provider.STEP.OCC.write.vismaterial : 0 provider.STEP.OCC.write.props : 1 provider.STEP.OCC.write.model.type : 0 provider.STEP.OCC.write.cleanduplicates : 0 +provider.STEP.OCC.write.scaling.trsf : 1 provider.STEP.OCC.healing.tolerance3d : 1e-06 provider.STEP.OCC.healing.max.tolerance3d : 1 provider.STEP.OCC.healing.min.tolerance3d : 1e-07 diff --git a/tests/de_wrapper/configuration/A4 b/tests/de_wrapper/configuration/A4 index 9099d77f66..4999dddb44 100644 --- a/tests/de_wrapper/configuration/A4 +++ b/tests/de_wrapper/configuration/A4 @@ -143,6 +143,7 @@ provider.STEP.OCC.write.material : 1 provider.STEP.OCC.write.vismaterial : 0 provider.STEP.OCC.write.model.type : 0 provider.STEP.OCC.write.cleanduplicates : 0 +provider.STEP.OCC.write.scaling.trsf : 1 provider.STEP.OCC.healing.tolerance3d : 1e-06 provider.STEP.OCC.healing.max.tolerance3d : 1 provider.STEP.OCC.healing.min.tolerance3d : 1e-07