]> OCCT Git - occt.git/commitdiff
Fixing remarks
authordkulikov <dkulikov@opencascade.com>
Thu, 3 Apr 2025 08:57:36 +0000 (09:57 +0100)
committerdkulikov <dkulikov@opencascade.com>
Thu, 3 Apr 2025 10:06:07 +0000 (11:06 +0100)
74 files changed:
src/DataExchange/TKDESTEP/GTests/FILES.cmake
src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_Axis2Placement3dProcessor_Test.cxx [deleted file]
src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_BaseTestFixture.hxx [deleted file]
src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_CartesianPointProcessor_Test.cxx [deleted file]
src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_CircleProcessor_Test.cxx [deleted file]
src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_DirectionProcessor_Test.cxx [deleted file]
src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_LineProcessor_Test.cxx [deleted file]
src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_Merger_Test.cxx [deleted file]
src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_PlaneProcessor_Test.cxx [deleted file]
src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_VectorProcessor_Test.cxx [deleted file]
src/DataExchange/TKDESTEP/GTests/StepTidy_Axis2Placement3dReducer_Test.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/GTests/StepTidy_BaseTestFixture.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/GTests/StepTidy_CartesianPointReducer_Test.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/GTests/StepTidy_CircleReducer_Test.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/GTests/StepTidy_DirectionReducer_Test.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/GTests/StepTidy_LineReducer_Test.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/GTests/StepTidy_Merger_Test.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/GTests/StepTidy_PlaneReducer_Test.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/GTests/StepTidy_VectorReducer_Test.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/MergeSTEPEntities/FILES.cmake [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement2dHasher.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement3dHasher.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement3dProcessor.cxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement3dProcessor.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CartesianPointHasher.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CartesianPointProcessor.cxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CartesianPointProcessor.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CircleHasher.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CircleProcessor.cxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CircleProcessor.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_DirectionHasher.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_DirectionProcessor.cxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_DirectionProcessor.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_EntityProcessor.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_LineHasher.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_LineProcessor.cxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_LineProcessor.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Merger.cxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Merger.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_PlaneHasher.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_PlaneProcessor.cxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_PlaneProcessor.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_VectorHasher.hxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_VectorProcessor.cxx [deleted file]
src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_VectorProcessor.hxx [deleted file]
src/DataExchange/TKDESTEP/PACKAGES.cmake
src/DataExchange/TKDESTEP/RWStepGeom/RWStepGeom_RWBSplineCurveWithKnots.cxx
src/DataExchange/TKDESTEP/StepTidy/FILES.cmake [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement2dHasher.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement3dHasher.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement3dReducer.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement3dReducer.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_CartesianPointHasher.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_CartesianPointReducer.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_CartesianPointReducer.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_CircleHasher.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_CircleReducer.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_CircleReducer.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_DirectionHasher.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_DirectionReducer.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_DirectionReducer.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_DuplicateCleaner.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_DuplicateCleaner.hxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_EntityReducer.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_LineHasher.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_LineReducer.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_LineReducer.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_PlaneHasher.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_PlaneReducer.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_PlaneReducer.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_VectorHasher.pxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_VectorReducer.cxx [new file with mode: 0644]
src/DataExchange/TKDESTEP/StepTidy/StepTidy_VectorReducer.pxx [new file with mode: 0644]
src/Draw/TKXSDRAWSTEP/XSDRAWSTEP/XSDRAWSTEP.cxx

index 008a21f8a13ff4a1a595a46d11ad69c358d2ecec..235d256623a00d968dcae37fbeba2b59aa5b35f2 100644 (file)
@@ -2,14 +2,13 @@
 set(OCCT_TKDESTEP_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
 
 set(OCCT_TKDESTEP_GTests_FILES
-    MergeSTEPEntities_Axis2Placement3dProcessor_Test.cxx
-    MergeSTEPEntities_BaseTestFixture.hxx
-    MergeSTEPEntities_CartesianPointProcessor_Test.cxx
-    MergeSTEPEntities_CircleProcessor_Test.cxx
-    MergeSTEPEntities_DirectionProcessor_Test.cxx
-    MergeSTEPEntities_LineProcessor_Test.cxx
-    MergeSTEPEntities_PlaneProcessor_Test.cxx
-    MergeSTEPEntities_Merger_Test.cxx
-
-    MergeSTEPEntities_VectorProcessor_Test.cxx
+    StepTidy_BaseTestFixture.pxx
+    StepTidy_Axis2Placement3dReducer_Test.cxx
+    StepTidy_CartesianPointReducer_Test.cxx
+    StepTidy_CircleReducer_Test.cxx
+    StepTidy_DirectionReducer_Test.cxx
+    StepTidy_LineReducer_Test.cxx
+    StepTidy_PlaneReducer_Test.cxx
+    StepTidy_Merger_Test.cxx
+    StepTidy_VectorReducer_Test.cxx
 )
diff --git a/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_Axis2Placement3dProcessor_Test.cxx b/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_Axis2Placement3dProcessor_Test.cxx
deleted file mode 100644 (file)
index 3b8f397..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-// 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.
-
-#include "MergeSTEPEntities_BaseTestFixture.hxx"
-
-#include <MergeSTEPEntities_Axis2Placement3dProcessor.hxx>
-
-#include <StepGeom_Plane.hxx>
-#include <StepRepr_ItemDefinedTransformation.hxx>
-#include <StepGeom_CylindricalSurface.hxx>
-#include <StepShape_ShapeRepresentation.hxx>
-#include <StepRepr_RepresentationContext.hxx>
-#include <StepRepr_ConstructiveGeometryRepresentation.hxx>
-#include <StepGeom_Circle.hxx>
-#include <StepVisual_PresentationLayerAssignment.hxx>
-#include <StepVisual_StyledItem.hxx>
-#include <StepGeom_Ellipse.hxx>
-#include <StepGeom_ConicalSurface.hxx>
-#include <StepGeom_ToroidalSurface.hxx>
-#include <StepShape_AdvancedBrepShapeRepresentation.hxx>
-#include <StepGeom_SphericalSurface.hxx>
-
-class MergeSTEPEntities_Axis2Placement3dProcessorTest : public MergeSTEPEntities_BaseTestFixture
-{
-protected:
-  //! Perform removal of duplicate entities.
-  TColStd_MapOfTransient replaceDuplicateAxis2Placement3ds()
-  {
-    MergeSTEPEntities_Axis2Placement3dProcessor aProcessor(myWS);
-    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
-    {
-      aProcessor.ProcessEntity(myWS->Model()->Value(anIndex));
-    }
-
-    TColStd_MapOfTransient aRemovedEntities;
-    aProcessor.Perform(aRemovedEntities);
-    return aRemovedEntities;
-  }
-};
-
-// Check that Axis2Placement3ds with the same coordinates and different names are not merged.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, DifferentNames)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d("Axis1");
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d("Axis2");
-
-  // Creating a plane containing the first Axis2Placement3d.
-  Handle(StepGeom_Plane) aPlane1 = new StepGeom_Plane;
-  aPlane1->Init(new TCollection_HAsciiString, anAxis1);
-  addToModel(aPlane1);
-
-  // Creating a plane containing the second Axis2Placement3d.
-  Handle(StepGeom_Plane) aPlane2 = new StepGeom_Plane;
-  aPlane2->Init(new TCollection_HAsciiString, anAxis2);
-  addToModel(aPlane2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that nothing was removed.
-  EXPECT_TRUE(aRemovedEntities.IsEmpty());
-}
-
-// Check that equal Axis2Placement3ds are merged for StepShape_GeometricCurveSet.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepGeom_Plane)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating a plane containing the first Axis2Placement3d.
-  Handle(StepGeom_Plane) aPlane1 = new StepGeom_Plane;
-  aPlane1->Init(new TCollection_HAsciiString, anAxis1);
-  addToModel(aPlane1);
-
-  // Creating a plane containing the second Axis2Placement3d.
-  Handle(StepGeom_Plane) aPlane2 = new StepGeom_Plane;
-  aPlane2->Init(new TCollection_HAsciiString, anAxis2);
-  addToModel(aPlane2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepRepr_ItemDefinedTransformation.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepRepr_ItemDefinedTransformation)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis3 = addAxis2Placement3d(nullptr, gp_XYZ(1., 1., 1.));
-
-  // Creating ItemDefinedTransformation containing the first Axis2Placement3d.
-  Handle(StepRepr_ItemDefinedTransformation) aItem1 = new StepRepr_ItemDefinedTransformation;
-  aItem1->Init(new TCollection_HAsciiString, new TCollection_HAsciiString, anAxis1, anAxis3);
-  addToModel(aItem1);
-
-  // Creating ItemDefinedTransformation containing the second Axis2Placement3d.
-  Handle(StepRepr_ItemDefinedTransformation) aItem2 = new StepRepr_ItemDefinedTransformation;
-  aItem1->Init(new TCollection_HAsciiString, new TCollection_HAsciiString, anAxis2, anAxis3);
-  addToModel(aItem2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepGeom_CylindricalSurface.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepGeom_CylindricalSurface)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating a cylindrical surface containing the first Axis2Placement3d.
-  Handle(StepGeom_CylindricalSurface) aCylindricalSurface1 = new StepGeom_CylindricalSurface;
-  aCylindricalSurface1->Init(new TCollection_HAsciiString, anAxis1, 1.0);
-  addToModel(aCylindricalSurface1);
-
-  // Creating a cylindrical surface containing the second Axis2Placement3d.
-  Handle(StepGeom_CylindricalSurface) aCylindricalSurface2 = new StepGeom_CylindricalSurface;
-  aCylindricalSurface2->Init(new TCollection_HAsciiString, anAxis2, 1.0);
-  addToModel(aCylindricalSurface2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepShape_ShapeRepresentation.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepShape_ShapeRepresentation)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating a shape representation containing the first Axis2Placement3d.
-  Handle(StepRepr_HArray1OfRepresentationItem) aItems1 =
-    new StepRepr_HArray1OfRepresentationItem(1, 1);
-  aItems1->SetValue(1, anAxis1);
-  Handle(StepShape_ShapeRepresentation) aShapeRepresentation1 = new StepShape_ShapeRepresentation;
-  aShapeRepresentation1->Init(new TCollection_HAsciiString,
-                              aItems1,
-                              new StepRepr_RepresentationContext);
-  addToModel(aShapeRepresentation1);
-
-  // Creating a shape representation containing the second Axis2Placement3d.
-  Handle(StepRepr_HArray1OfRepresentationItem) aItems2 =
-    new StepRepr_HArray1OfRepresentationItem(1, 1);
-  aItems2->SetValue(1, anAxis2);
-  Handle(StepShape_ShapeRepresentation) aShapeRepresentation2 = new StepShape_ShapeRepresentation;
-  aShapeRepresentation2->Init(new TCollection_HAsciiString,
-                              aItems2,
-                              new StepRepr_RepresentationContext);
-  addToModel(aShapeRepresentation2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepRepr_ConstructiveGeometryRepresentation.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepRepr_ConstructiveGeometryRepresentation)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating a constructive geometry representation containing the first Axis2Placement3d.
-  Handle(StepRepr_HArray1OfRepresentationItem) aItems1 =
-    new StepRepr_HArray1OfRepresentationItem(1, 1);
-  aItems1->SetValue(1, anAxis1);
-  Handle(StepRepr_ConstructiveGeometryRepresentation) aConstructiveGeometryRepresentation1 =
-    new StepRepr_ConstructiveGeometryRepresentation;
-  aConstructiveGeometryRepresentation1->Init(new TCollection_HAsciiString,
-                                             aItems1,
-                                             new StepRepr_RepresentationContext);
-  addToModel(aConstructiveGeometryRepresentation1);
-
-  // Creating a constructive geometry representation containing the second Axis2Placement3d.
-  Handle(StepRepr_HArray1OfRepresentationItem) aItems2 =
-    new StepRepr_HArray1OfRepresentationItem(1, 1);
-  aItems2->SetValue(1, anAxis2);
-  Handle(StepRepr_ConstructiveGeometryRepresentation) aConstructiveGeometryRepresentation2 =
-    new StepRepr_ConstructiveGeometryRepresentation;
-  aConstructiveGeometryRepresentation2->Init(new TCollection_HAsciiString,
-                                             aItems2,
-                                             new StepRepr_RepresentationContext);
-  addToModel(aConstructiveGeometryRepresentation2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepGeom_Circle.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepGeom_Circle)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating a circle containing the first Axis2Placement3d.
-  StepGeom_Axis2Placement aSelector1;
-  aSelector1.SetValue(anAxis1);
-  Handle(StepGeom_Circle) aCircle1 = new StepGeom_Circle;
-  aCircle1->Init(new TCollection_HAsciiString, aSelector1, 1.0);
-  addToModel(aCircle1);
-
-  // Creating a circle containing the second Axis2Placement3d.
-  StepGeom_Axis2Placement aSelector2;
-  aSelector2.SetValue(anAxis2);
-  Handle(StepGeom_Circle) aCircle2 = new StepGeom_Circle;
-  aCircle2->Init(new TCollection_HAsciiString, aSelector2, 1.0);
-  addToModel(aCircle2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepVisual_PresentationLayerAssignment.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepVisual_PresentationLayerAssignment)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating a presentation layer assignment containing the first Axis2Placement3d.
-  Handle(StepVisual_HArray1OfLayeredItem) aAssignedItems1 =
-    new StepVisual_HArray1OfLayeredItem(1, 1);
-  StepVisual_LayeredItem aLayeredItem1;
-  aLayeredItem1.SetValue(anAxis1);
-  aAssignedItems1->SetValue(1, aLayeredItem1);
-  Handle(StepVisual_PresentationLayerAssignment) aPresentationLayerAssignment1 =
-    new StepVisual_PresentationLayerAssignment;
-  aPresentationLayerAssignment1->Init(new TCollection_HAsciiString,
-                                      new TCollection_HAsciiString,
-                                      aAssignedItems1);
-  addToModel(aPresentationLayerAssignment1);
-
-  // Creating a presentation layer assignment containing the second Axis2Placement3d.
-  Handle(StepVisual_HArray1OfLayeredItem) aAssignedItems2 =
-    new StepVisual_HArray1OfLayeredItem(1, 1);
-  StepVisual_LayeredItem aLayeredItem2;
-  aLayeredItem2.SetValue(anAxis2);
-  aAssignedItems2->SetValue(1, aLayeredItem2);
-  Handle(StepVisual_PresentationLayerAssignment) aPresentationLayerAssignment2 =
-    new StepVisual_PresentationLayerAssignment;
-  aPresentationLayerAssignment2->Init(new TCollection_HAsciiString,
-                                      new TCollection_HAsciiString,
-                                      aAssignedItems2);
-  addToModel(aPresentationLayerAssignment2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepVisual_StyledItem.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepVisual_StyledItem)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating a styled item containing the first Axis2Placement3d.
-  Handle(StepVisual_StyledItem) aStiledItem1 = new StepVisual_StyledItem;
-  aStiledItem1->Init(new TCollection_HAsciiString,
-                     new StepVisual_HArray1OfPresentationStyleAssignment(1, 1),
-                     anAxis1);
-  addToModel(aStiledItem1);
-
-  // Creating a styled item containing the second Axis2Placement3d.
-  Handle(StepVisual_StyledItem) aStiledItem2 = new StepVisual_StyledItem;
-  aStiledItem2->Init(new TCollection_HAsciiString,
-                     new StepVisual_HArray1OfPresentationStyleAssignment(1, 1),
-                     anAxis2);
-  addToModel(aStiledItem2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepGeom_Ellipse.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepGeom_Ellipse)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating an ellipse containing the first Axis2Placement3d.
-  StepGeom_Axis2Placement aSelector1;
-  aSelector1.SetValue(anAxis1);
-  Handle(StepGeom_Ellipse) aEllipse1 = new StepGeom_Ellipse;
-  aEllipse1->Init(new TCollection_HAsciiString, aSelector1, 1.0, 2.0);
-  addToModel(aEllipse1);
-
-  // Creating an ellipse containing the second Axis2Placement3d.
-  StepGeom_Axis2Placement aSelector2;
-  aSelector2.SetValue(anAxis2);
-  Handle(StepGeom_Ellipse) aEllipse2 = new StepGeom_Ellipse;
-  aEllipse2->Init(new TCollection_HAsciiString, aSelector2, 1.0, 2.0);
-  addToModel(aEllipse2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepGeom_ConicalSurface.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepGeom_ConicalSurface)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating a conical surface containing the first Axis2Placement3d.
-  Handle(StepGeom_ConicalSurface) aConicalSurface1 = new StepGeom_ConicalSurface;
-  aConicalSurface1->Init(new TCollection_HAsciiString, anAxis1, 1.0, 1.0);
-  addToModel(aConicalSurface1);
-
-  // Creating a conical surface containing the second Axis2Placement3d.
-  Handle(StepGeom_ConicalSurface) aConicalSurface2 = new StepGeom_ConicalSurface;
-  aConicalSurface2->Init(new TCollection_HAsciiString, anAxis2, 1.0, 1.0);
-  addToModel(aConicalSurface2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepGeom_ToroidalSurface.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepGeom_ToroidalSurface)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating a toroidal surface containing the first Axis2Placement3d.
-  Handle(StepGeom_ToroidalSurface) aToroidalSurface1 = new StepGeom_ToroidalSurface;
-  aToroidalSurface1->Init(new TCollection_HAsciiString, anAxis1, 1.0, 1.0);
-  addToModel(aToroidalSurface1);
-
-  // Creating a toroidal surface containing the second Axis2Placement3d.
-  Handle(StepGeom_ToroidalSurface) aToroidalSurface2 = new StepGeom_ToroidalSurface;
-  aToroidalSurface2->Init(new TCollection_HAsciiString, anAxis2, 1.0, 1.0);
-  addToModel(aToroidalSurface2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepShape_AdvancedBrepShapeRepresentation.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepShape_AdvancedBrepShapeRepresentation)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating a shape representation containing the first Axis2Placement3d.
-  Handle(StepRepr_HArray1OfRepresentationItem) aItems1 =
-    new StepRepr_HArray1OfRepresentationItem(1, 1);
-  aItems1->SetValue(1, anAxis1);
-  Handle(StepShape_AdvancedBrepShapeRepresentation) aShapeRepresentation1 =
-    new StepShape_AdvancedBrepShapeRepresentation;
-  aShapeRepresentation1->Init(new TCollection_HAsciiString,
-                              aItems1,
-                              new StepRepr_RepresentationContext);
-  addToModel(aShapeRepresentation1);
-
-  // Creating a shape representation containing the second Axis2Placement3d.
-  Handle(StepRepr_HArray1OfRepresentationItem) aItems2 =
-    new StepRepr_HArray1OfRepresentationItem(1, 1);
-  aItems2->SetValue(1, anAxis2);
-  Handle(StepShape_AdvancedBrepShapeRepresentation) aShapeRepresentation2 =
-    new StepShape_AdvancedBrepShapeRepresentation;
-  aShapeRepresentation2->Init(new TCollection_HAsciiString,
-                              aItems2,
-                              new StepRepr_RepresentationContext);
-  addToModel(aShapeRepresentation2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
-
-// Check that equal Axis2Placement3ds are merged for StepGeom_SphericalSurface.
-TEST_F(MergeSTEPEntities_Axis2Placement3dProcessorTest, StepGeom_SphericalSurface)
-{
-  // Creating Axis2Placement3ds.
-  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
-  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
-
-  // Creating a spherical surface containing the first Axis2Placement3d.
-  Handle(StepGeom_SphericalSurface) aSphericalSurface1 = new StepGeom_SphericalSurface;
-  aSphericalSurface1->Init(new TCollection_HAsciiString, anAxis1, 1.0);
-  addToModel(aSphericalSurface1);
-
-  // Creating a spherical surface containing the second Axis2Placement3d.
-  Handle(StepGeom_SphericalSurface) aSphericalSurface2 = new StepGeom_SphericalSurface;
-  aSphericalSurface2->Init(new TCollection_HAsciiString, anAxis2, 1.0);
-  addToModel(aSphericalSurface2);
-
-  // Performing removal of duplicate Axis2Placement3ds.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
-
-  // Check that one Axis2Placement3d was removed.
-  EXPECT_EQ(aRemovedEntities.Extent(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
-}
diff --git a/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_BaseTestFixture.hxx b/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_BaseTestFixture.hxx
deleted file mode 100644 (file)
index f0d3892..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-// 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 _MergeSTEPEntities_BaseTestFixture_HeaderFile
-#define _MergeSTEPEntities_BaseTestFixture_HeaderFile
-
-#include <STEPControl_Controller.hxx>
-#include <StepGeom_Axis2Placement3d.hxx>
-#include <StepGeom_CartesianPoint.hxx>
-#include <StepGeom_Circle.hxx>
-#include <StepGeom_Direction.hxx>
-#include <StepGeom_Line.hxx>
-#include <StepGeom_Plane.hxx>
-#include <StepGeom_Vector.hxx>
-#include <XSControl_WorkSession.hxx>
-
-#include <gtest/gtest.h>
-
-class MergeSTEPEntities_BaseTestFixture : public testing::Test
-{
-protected:
-  // Initialize the work session and model.
-  MergeSTEPEntities_BaseTestFixture()
-      : myWS()
-  {
-    STEPControl_Controller::Init();
-    myWS = new XSControl_WorkSession;
-    myWS->SelectNorm("STEP");
-    myWS->SetModel(myWS->NormAdaptor()->NewModel());
-  }
-
-  // Add a Cartesian point to the model.
-  // @param theName the name of the Cartesian point.
-  // @param thePoint the coordinates of the Cartesian point.
-  // @return the added Cartesian point.
-  Handle(StepGeom_CartesianPoint) addCartesianPoint(const char*   theName  = nullptr,
-                                                    const gp_XYZ& thePoint = gp_XYZ(0.,
-                                                                                    0.,
-                                                                                    0.)) const
-  {
-    const Handle(StepGeom_CartesianPoint)  aCartesianPoint = new StepGeom_CartesianPoint;
-    const Handle(TCollection_HAsciiString) aName =
-      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
-    aCartesianPoint->Init3D(aName, thePoint.X(), thePoint.Y(), thePoint.Z());
-    myWS->Model()->AddWithRefs(aCartesianPoint);
-    return aCartesianPoint;
-  }
-
-  // Add a direction to the model.
-  // @param theName the name of the direction.
-  // @param theDirection the direction ratios.
-  // @return the added direction.
-  Handle(StepGeom_Direction) addDirection(const char*   theName      = nullptr,
-                                          const gp_XYZ& theDirection = gp_XYZ(0., 0., 1.)) const
-  {
-    const Handle(StepGeom_Direction)       aDirection = new StepGeom_Direction;
-    const Handle(TCollection_HAsciiString) aName =
-      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
-    Handle(TColStd_HArray1OfReal) aDirectionRatios = new TColStd_HArray1OfReal(1, 3);
-    aDirectionRatios->SetValue(1, theDirection.X());
-    aDirectionRatios->SetValue(2, theDirection.Y());
-    aDirectionRatios->SetValue(3, theDirection.Z());
-    aDirection->Init(aName, aDirectionRatios);
-    myWS->Model()->AddWithRefs(aDirection);
-    return aDirection;
-  }
-
-  // Add a vector to the model.
-  // @param theName the name of the vector.
-  // @param theOrientation the orientation of the vector.
-  // @param aMagnitude the magnitude of the vector.
-  // @return the added vector.
-  Handle(StepGeom_Vector) addVector(const char*   theName        = nullptr,
-                                    const gp_XYZ& theOrientation = gp_XYZ(0., 0., 1.),
-                                    const double  aMagnitude     = 1.) const
-  {
-    const Handle(StepGeom_Vector)          aVector = new StepGeom_Vector;
-    const Handle(TCollection_HAsciiString) aName =
-      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
-    aVector->Init(aName, addDirection(nullptr, theOrientation), aMagnitude);
-    myWS->Model()->AddWithRefs(aVector);
-    return aVector;
-  }
-
-  // Add an Axis2Placement3d to the model.
-  // @param theName the name of the Axis2Placement3d.
-  // @param theLocation the location of the Axis2Placement3d.
-  // @param theAxis the axis of the Axis2Placement3d.
-  // @param theRefDirection the reference direction of the Axis2Placement3d.
-  // @return the added Axis2Placement3d.
-  Handle(StepGeom_Axis2Placement3d) addAxis2Placement3d(
-    const char*   theName         = nullptr,
-    const gp_XYZ& theLocation     = gp_XYZ(0., 0., 0.),
-    const gp_XYZ& theAxis         = gp_XYZ(0., 0., 1.),
-    const gp_XYZ& theRefDirection = gp_XYZ(0., 1., 0.)) const
-  {
-    const Handle(StepGeom_Axis2Placement3d) aAxis2Placement3d = new StepGeom_Axis2Placement3d;
-    const Handle(TCollection_HAsciiString)  aName =
-      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
-    aAxis2Placement3d->Init(aName,
-                            addCartesianPoint(nullptr, theLocation),
-                            true,
-                            addDirection(nullptr, theAxis),
-                            true,
-                            addDirection(nullptr, theRefDirection));
-    myWS->Model()->AddWithRefs(aAxis2Placement3d);
-    return aAxis2Placement3d;
-  }
-
-  // Add a line to the model.
-  // @param theName the name of the line.
-  // @param theLocation the location of the line.
-  // @param theOrientation the orientation of the line vector.
-  // @param theMagnitude the magnitude of the line vector.
-  // @return the added line.
-  Handle(StepGeom_Line) addLine(const char*   theName        = nullptr,
-                                const gp_XYZ& theLocation    = gp_XYZ(0., 0., 0.),
-                                const gp_XYZ& theOrientation = gp_XYZ(0., 0., 1.),
-                                const double  aMagnitude     = 1.) const
-  {
-    const Handle(StepGeom_Line)            aLine = new StepGeom_Line;
-    const Handle(TCollection_HAsciiString) aName =
-      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
-    aLine->Init(aName,
-                addCartesianPoint(nullptr, theLocation),
-                addVector(nullptr, theOrientation, aMagnitude));
-    myWS->Model()->AddWithRefs(aLine);
-    return aLine;
-  }
-
-  // Add a circle to the model.
-  // @param theName the name of the circle.
-  // @param theLocation the location of the circle.
-  // @param theAxis the axis of the circle.
-  // @param theRefDirection the reference direction of the circle.
-  // @param theRadius the radius of the circle.
-  // @return the added circle.
-  Handle(StepGeom_Circle) addCircle(const char*   theName         = nullptr,
-                                    const gp_XYZ& theLocation     = gp_XYZ(0., 0., 0.),
-                                    const gp_XYZ& theAxis         = gp_XYZ(0., 0., 1.),
-                                    const gp_XYZ& theRefDirection = gp_XYZ(0., 1., 0.),
-                                    const double  theRadius       = 1.) const
-  {
-    const Handle(StepGeom_Circle)          aCircle = new StepGeom_Circle;
-    const Handle(TCollection_HAsciiString) aName =
-      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
-    StepGeom_Axis2Placement aSelector;
-    aSelector.SetValue(addAxis2Placement3d(nullptr, theLocation, theAxis, theRefDirection));
-    aCircle->Init(aName, aSelector, theRadius);
-    myWS->Model()->AddWithRefs(aCircle);
-    return aCircle;
-  }
-
-  // Add a plane to the model.
-  // @param theName the name of the plane.
-  // @param theLocation the location of the plane.
-  // @param theAxis the axis of the plane.
-  // @param theRefDirection the reference direction of the plane.
-  // @return the added plane.
-  Handle(StepGeom_Plane) addPlane(const char*   theName         = nullptr,
-                                  const gp_XYZ& theLocation     = gp_XYZ(0., 0., 0.),
-                                  const gp_XYZ& theAxis         = gp_XYZ(0., 0., 1.),
-                                  const gp_XYZ& theRefDirection = gp_XYZ(0., 1., 0.)) const
-  {
-    const Handle(StepGeom_Plane)           aPlane = new StepGeom_Plane;
-    const Handle(TCollection_HAsciiString) aName =
-      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
-    aPlane->Init(aName, addAxis2Placement3d(nullptr, theLocation, theAxis, theRefDirection));
-    myWS->Model()->AddWithRefs(aPlane);
-    return aPlane;
-  }
-
-  // Add an entity to the model.
-  // @param theEntity the entity to add.
-  void addToModel(const Handle(Standard_Transient)& theEntity) const
-  {
-    myWS->Model()->AddWithRefs(theEntity);
-  }
-
-protected:
-  Handle(XSControl_WorkSession) myWS;
-};
-
-#endif // _MergeSTEPEntities_BaseTestFixture_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_CartesianPointProcessor_Test.cxx b/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_CartesianPointProcessor_Test.cxx
deleted file mode 100644 (file)
index 0a45609..0000000
+++ /dev/null
@@ -1,594 +0,0 @@
-// 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.
-
-#include "MergeSTEPEntities_BaseTestFixture.hxx"
-
-#include <MergeSTEPEntities_CartesianPointProcessor.hxx>
-
-#include <StepGeom_Axis1Placement.hxx>
-#include <StepGeom_Axis2Placement3d.hxx>
-#include <StepGeom_BSplineCurveWithKnots.hxx>
-#include <StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve.hxx>
-#include <StepGeom_BSplineSurfaceWithKnots.hxx>
-#include <StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface.hxx>
-#include <StepGeom_Line.hxx>
-#include <StepGeom_RationalBSplineSurface.hxx>
-#include <StepRepr_Representation.hxx>
-#include <StepRepr_RepresentationContext.hxx>
-#include <StepShape_GeometricCurveSet.hxx>
-#include <StepShape_VertexPoint.hxx>
-#include <StepVisual_PresentationLayerAssignment.hxx>
-#include <StepVisual_StyledItem.hxx>
-
-class MergeSTEPEntities_CartesianPointProcessorTest : public MergeSTEPEntities_BaseTestFixture
-{
-protected:
-  // Perform removal of duplicate Cartesian points.
-  TColStd_MapOfTransient replaceDuplicateCartesianPoints()
-  {
-    MergeSTEPEntities_CartesianPointProcessor aProcessor(myWS);
-    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
-    {
-      aProcessor.ProcessEntity(myWS->Model()->Value(anIndex));
-    }
-
-    TColStd_MapOfTransient aRemovedEntities;
-    aProcessor.Perform(aRemovedEntities);
-    return aRemovedEntities;
-  }
-};
-
-// Check that points with the same coordinates and different names are not merged.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest, DifferentNames)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint("FirstPt");
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint("SecondPt");
-
-  // Creating direction.
-  Handle(TColStd_HArray1OfReal) aDirCoords = new TColStd_HArray1OfReal(1, 3);
-  aDirCoords->SetValue(1, 0.);
-  aDirCoords->SetValue(2, 0.);
-  aDirCoords->SetValue(3, 1.);
-  Handle(StepGeom_Direction) aDir = new StepGeom_Direction;
-  aDir->Init(new TCollection_HAsciiString, aDirCoords);
-  addToModel(aDir);
-
-  // Creating axis containing the first Cartesian point.
-  Handle(StepGeom_Axis2Placement3d) aFirstAxis = new StepGeom_Axis2Placement3d;
-  aFirstAxis
-    ->Init(new TCollection_HAsciiString, aPt1, Standard_True, aDir, Standard_False, nullptr);
-  addToModel(aFirstAxis);
-
-  // Creating axis containing the second Cartesian point.
-  Handle(StepGeom_Axis2Placement3d) aSecondAxis = new StepGeom_Axis2Placement3d;
-  aSecondAxis
-    ->Init(new TCollection_HAsciiString, aPt2, Standard_True, aDir, Standard_False, nullptr);
-  addToModel(aSecondAxis);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that nothing was removed.
-  EXPECT_TRUE(aRemovedEntities.IsEmpty());
-}
-
-// Check that points with the same coordinates and same names are
-// merged for StepGeom_Axis2Placement3d.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest, StepGeom_Axis2Placement3d)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating direction.
-  Handle(TColStd_HArray1OfReal) aDirCoords = new TColStd_HArray1OfReal(1, 3);
-  aDirCoords->SetValue(1, 0.);
-  aDirCoords->SetValue(2, 0.);
-  aDirCoords->SetValue(3, 1.);
-  Handle(StepGeom_Direction) aDir = new StepGeom_Direction;
-  aDir->Init(new TCollection_HAsciiString, aDirCoords);
-  addToModel(aDir);
-
-  // Creating axis containing the first Cartesian point.
-  Handle(StepGeom_Axis2Placement3d) aFirstAxis = new StepGeom_Axis2Placement3d;
-  aFirstAxis
-    ->Init(new TCollection_HAsciiString, aPt1, Standard_True, aDir, Standard_False, nullptr);
-  addToModel(aFirstAxis);
-
-  // Creating axis containing the second Cartesian point.
-  Handle(StepGeom_Axis2Placement3d) aSecondAxis = new StepGeom_Axis2Placement3d;
-  aSecondAxis
-    ->Init(new TCollection_HAsciiString, aPt2, Standard_True, aDir, Standard_False, nullptr);
-  addToModel(aSecondAxis);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
-
-// Check that points with the same coordinates and same names are merged
-// for StepShape_VertexPoint.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest, StepShape_VertexPoint)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating vertex containing the first Cartesian point.
-  Handle(StepShape_VertexPoint) aFirstVertex = new StepShape_VertexPoint;
-  aFirstVertex->Init(new TCollection_HAsciiString, aPt1);
-  addToModel(aFirstVertex);
-
-  // Creating vertex containing the second Cartesian point.
-  Handle(StepShape_VertexPoint) aSecondVertex = new StepShape_VertexPoint;
-  aSecondVertex->Init(new TCollection_HAsciiString, aPt2);
-  addToModel(aSecondVertex);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
-
-// Check that points with the same coordinates and same names are merged
-// for StepShape_GeometricCurveSet.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest, StepShape_GeometricCurveSet)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating curve set containing the first Cartesian point.
-  Handle(StepShape_HArray1OfGeometricSetSelect) aFirstElements =
-    new StepShape_HArray1OfGeometricSetSelect(1, 1);
-  StepShape_GeometricSetSelect aFirstSelect;
-  aFirstSelect.SetValue(aPt1);
-  aFirstElements->SetValue(1, aFirstSelect);
-  addToModel(aFirstElements);
-  Handle(StepShape_GeometricCurveSet) aFirstCurveSet = new StepShape_GeometricCurveSet;
-  aFirstCurveSet->Init(new TCollection_HAsciiString, aFirstElements);
-  addToModel(aFirstCurveSet);
-
-  // Creating curve set containing the second Cartesian point.
-  Handle(StepShape_HArray1OfGeometricSetSelect) aSecondElements =
-    new StepShape_HArray1OfGeometricSetSelect(1, 1);
-  StepShape_GeometricSetSelect aSecondSelect;
-  aSecondSelect.SetValue(aPt2);
-  aSecondElements->SetValue(1, aSecondSelect);
-  addToModel(aSecondElements);
-  Handle(StepShape_GeometricCurveSet) aSecondCurveSet = new StepShape_GeometricCurveSet;
-  aSecondCurveSet->Init(new TCollection_HAsciiString, aSecondElements);
-  addToModel(aSecondCurveSet);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
-
-// Check that points with the same coordinates and same names are merged
-// for StepVisual_PresentationLayerAssignment.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest, StepVisual_PresentationLayerAssignment)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating presentation layer assignment containing the first Cartesian point.
-  Handle(StepVisual_HArray1OfLayeredItem) aFirstAssignedItems =
-    new StepVisual_HArray1OfLayeredItem(1, 1);
-  StepVisual_LayeredItem aFirstLayeredItem;
-  aFirstLayeredItem.SetValue(aPt1);
-  aFirstAssignedItems->SetValue(1, aFirstLayeredItem);
-  addToModel(aFirstAssignedItems);
-  Handle(StepVisual_PresentationLayerAssignment) aFirstAssignment =
-    new StepVisual_PresentationLayerAssignment;
-  aFirstAssignment->Init(new TCollection_HAsciiString,
-                         new TCollection_HAsciiString,
-                         aFirstAssignedItems);
-  addToModel(aFirstAssignment);
-
-  // Creating presentation layer assignment containing the second Cartesian point.
-  Handle(StepVisual_HArray1OfLayeredItem) aSecondAssignedItems =
-    new StepVisual_HArray1OfLayeredItem(1, 1);
-  StepVisual_LayeredItem aSecondLayeredItem;
-  aSecondLayeredItem.SetValue(aPt2);
-  aSecondAssignedItems->SetValue(1, aSecondLayeredItem);
-  addToModel(aSecondAssignedItems);
-  Handle(StepVisual_PresentationLayerAssignment) aSecondAssignment =
-    new StepVisual_PresentationLayerAssignment;
-  aSecondAssignment->Init(new TCollection_HAsciiString,
-                          new TCollection_HAsciiString,
-                          aSecondAssignedItems);
-  addToModel(aSecondAssignment);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
-
-// Check that points with the same coordinates and same names are merged
-// for StepVisual_StyledItem.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest, StepVisual_StyledItem)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating styled item containing the first Cartesian point.
-  Handle(StepVisual_HArray1OfPresentationStyleAssignment) aFirstAssignedItems =
-    new StepVisual_HArray1OfPresentationStyleAssignment(1, 1);
-  Handle(StepVisual_StyledItem) aFirstStyledItem = new StepVisual_StyledItem;
-  aFirstStyledItem->Init(new TCollection_HAsciiString, aFirstAssignedItems, aPt1);
-  addToModel(aFirstStyledItem);
-
-  // Creating styled item containing the second Cartesian point.
-  Handle(StepVisual_HArray1OfPresentationStyleAssignment) aSecondAssignedItems =
-    new StepVisual_HArray1OfPresentationStyleAssignment(1, 1);
-  Handle(StepVisual_StyledItem) aSecondStyledItem = new StepVisual_StyledItem;
-  aSecondStyledItem->Init(new TCollection_HAsciiString, aSecondAssignedItems, aPt2);
-  addToModel(aSecondStyledItem);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
-
-// Check that points with the same coordinates and same names are merged
-// for StepGeom_BSplineCurveWithKnots.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest, StepGeom_BSplineCurveWithKnots)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating curve containing the first Cartesian point.
-  Handle(StepGeom_HArray1OfCartesianPoint) aFirstControlPoints =
-    new StepGeom_HArray1OfCartesianPoint(1, 1);
-  aFirstControlPoints->SetValue(1, aPt1);
-  addToModel(aFirstControlPoints);
-  Handle(StepGeom_BSplineCurveWithKnots) aFirstCurve = new StepGeom_BSplineCurveWithKnots;
-  aFirstCurve->Init(new TCollection_HAsciiString,
-                    1,
-                    aFirstControlPoints,
-                    StepGeom_bscfUnspecified,
-                    StepData_LUnknown,
-                    StepData_LUnknown,
-                    new TColStd_HArray1OfInteger,
-                    new TColStd_HArray1OfReal,
-                    StepGeom_ktUnspecified);
-  addToModel(aFirstCurve);
-
-  // Creating curve containing the second Cartesian point.
-  Handle(StepGeom_HArray1OfCartesianPoint) aSecondControlPoints =
-    new StepGeom_HArray1OfCartesianPoint(1, 1);
-  aSecondControlPoints->SetValue(1, aPt2);
-  addToModel(aSecondControlPoints);
-  Handle(StepGeom_BSplineCurveWithKnots) aSecondCurve = new StepGeom_BSplineCurveWithKnots;
-  aSecondCurve->Init(new TCollection_HAsciiString,
-                     1,
-                     aSecondControlPoints,
-                     StepGeom_bscfUnspecified,
-                     StepData_LUnknown,
-                     StepData_LUnknown,
-                     new TColStd_HArray1OfInteger,
-                     new TColStd_HArray1OfReal,
-                     StepGeom_ktUnspecified);
-  addToModel(aSecondCurve);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
-
-// Check that points with the same coordinates and same names are merged
-// for StepGeom_Line.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest, StepGeom_Line)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating line containing the first Cartesian point.
-  Handle(StepGeom_Line) aFirstLine = new StepGeom_Line;
-  aFirstLine->Init(new TCollection_HAsciiString, aPt1, new StepGeom_Vector);
-  addToModel(aFirstLine);
-
-  // Creating line containing the second Cartesian point.
-  Handle(StepGeom_Line) aSecondLine = new StepGeom_Line;
-  aSecondLine->Init(new TCollection_HAsciiString, aPt2, new StepGeom_Vector);
-  addToModel(aSecondLine);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
-
-// Check that points with the same coordinates and same names are merged
-// for StepGeom_BSplineSurfaceWithKnots.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest, StepGeom_BSplineSurfaceWithKnots)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating surface containing the first Cartesian point.
-  Handle(StepGeom_HArray2OfCartesianPoint) aFirstControlPoints =
-    new StepGeom_HArray2OfCartesianPoint(1, 1, 1, 1);
-  aFirstControlPoints->SetValue(1, 1, aPt1);
-  addToModel(aFirstControlPoints);
-  Handle(StepGeom_BSplineSurfaceWithKnots) aFirstSurface = new StepGeom_BSplineSurfaceWithKnots;
-  aFirstSurface->Init(new TCollection_HAsciiString,
-                      1,
-                      1,
-                      aFirstControlPoints,
-                      StepGeom_bssfUnspecified,
-                      StepData_LUnknown,
-                      StepData_LUnknown,
-                      StepData_LUnknown,
-                      new TColStd_HArray1OfInteger,
-                      new TColStd_HArray1OfInteger,
-                      new TColStd_HArray1OfReal,
-                      new TColStd_HArray1OfReal,
-                      StepGeom_ktUnspecified);
-  addToModel(aFirstSurface);
-
-  // Creating surface containing the second Cartesian point.
-  Handle(StepGeom_HArray2OfCartesianPoint) aSecondControlPoints =
-    new StepGeom_HArray2OfCartesianPoint(1, 1, 1, 1);
-  aSecondControlPoints->SetValue(1, 1, aPt2);
-  addToModel(aSecondControlPoints);
-  Handle(StepGeom_BSplineSurfaceWithKnots) aSecondSurface = new StepGeom_BSplineSurfaceWithKnots;
-  aSecondSurface->Init(new TCollection_HAsciiString,
-                       1,
-                       1,
-                       aSecondControlPoints,
-                       StepGeom_bssfUnspecified,
-                       StepData_LUnknown,
-                       StepData_LUnknown,
-                       StepData_LUnknown,
-                       new TColStd_HArray1OfInteger,
-                       new TColStd_HArray1OfInteger,
-                       new TColStd_HArray1OfReal,
-                       new TColStd_HArray1OfReal,
-                       StepGeom_ktUnspecified);
-  addToModel(aSecondSurface);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
-
-// Check that points with the same coordinates and same names are merged
-// for StepGeom_Axis1Placement.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest, StepGeom_Axis1Placement)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating axis containing the first Cartesian point.
-  Handle(StepGeom_Axis1Placement) aFirstAxis = new StepGeom_Axis1Placement;
-  aFirstAxis->Init(new TCollection_HAsciiString, aPt1, false, new StepGeom_Direction);
-  addToModel(aFirstAxis);
-
-  // Creating axis containing the second Cartesian point.
-  Handle(StepGeom_Axis1Placement) aSecondAxis = new StepGeom_Axis1Placement;
-  aSecondAxis->Init(new TCollection_HAsciiString, aPt2, false, new StepGeom_Direction);
-  addToModel(aSecondAxis);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
-
-// Check that points with the same coordinates and same names are merged
-// for StepRepr_Representation.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest, StepRepr_Representation)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating representation containing the first Cartesian point.
-  Handle(StepRepr_HArray1OfRepresentationItem) aFirstItems =
-    new StepRepr_HArray1OfRepresentationItem(1, 1);
-  aFirstItems->SetValue(1, aPt1);
-  Handle(StepRepr_Representation) aFirstRepresentation = new StepRepr_Representation;
-  aFirstRepresentation->Init(new TCollection_HAsciiString,
-                             aFirstItems,
-                             new StepRepr_RepresentationContext);
-  addToModel(aFirstRepresentation);
-
-  // Creating representation containing the second Cartesian point.
-  Handle(StepRepr_HArray1OfRepresentationItem) aSecondItems =
-    new StepRepr_HArray1OfRepresentationItem(1, 1);
-  aSecondItems->SetValue(1, aPt2);
-  Handle(StepRepr_Representation) aSecondRepresentation = new StepRepr_Representation;
-  aSecondRepresentation->Init(new TCollection_HAsciiString,
-                              aSecondItems,
-                              new StepRepr_RepresentationContext);
-  addToModel(aSecondRepresentation);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
-
-// Check that points with the same coordinates and same names are merged
-// for StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest,
-       StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating curve containing the first Cartesian point.
-  Handle(StepGeom_HArray1OfCartesianPoint) aFirstControlPoints =
-    new StepGeom_HArray1OfCartesianPoint(1, 1);
-  aFirstControlPoints->SetValue(1, aPt1);
-  addToModel(aFirstControlPoints);
-  Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve) aFirstCurve =
-    new StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve;
-  aFirstCurve->Init(new TCollection_HAsciiString,
-                    1,
-                    aFirstControlPoints,
-                    StepGeom_bscfUnspecified,
-                    StepData_LUnknown,
-                    StepData_LUnknown,
-                    new TColStd_HArray1OfInteger,
-                    new TColStd_HArray1OfReal,
-                    StepGeom_ktUnspecified,
-                    new TColStd_HArray1OfReal);
-  addToModel(aFirstCurve);
-
-  // Creating curve containing the second Cartesian point.
-  Handle(StepGeom_HArray1OfCartesianPoint) aSecondControlPoints =
-    new StepGeom_HArray1OfCartesianPoint(1, 1);
-  aSecondControlPoints->SetValue(1, aPt2);
-  addToModel(aSecondControlPoints);
-  Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve) aSecondCurve =
-    new StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve;
-  aSecondCurve->Init(new TCollection_HAsciiString,
-                     1,
-                     aSecondControlPoints,
-                     StepGeom_bscfUnspecified,
-                     StepData_LUnknown,
-                     StepData_LUnknown,
-                     new TColStd_HArray1OfInteger,
-                     new TColStd_HArray1OfReal,
-                     StepGeom_ktUnspecified,
-                     new TColStd_HArray1OfReal);
-  addToModel(aSecondCurve);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
-
-// Check that points with the same coordinates and same names are merged
-// for StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface.
-TEST_F(MergeSTEPEntities_CartesianPointProcessorTest,
-       StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface)
-{
-  // Creating Cartesian points.
-  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
-  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
-
-  // Creating surface containing the first Cartesian point.
-  Handle(StepGeom_HArray2OfCartesianPoint) aFirstControlPoints =
-    new StepGeom_HArray2OfCartesianPoint(1, 1, 1, 1);
-  aFirstControlPoints->SetValue(1, 1, aPt1);
-  addToModel(aFirstControlPoints);
-  Handle(StepGeom_BSplineSurfaceWithKnots) aFirstBSSWN = new StepGeom_BSplineSurfaceWithKnots;
-  aFirstBSSWN->Init(new TCollection_HAsciiString,
-                    1,
-                    1,
-                    aFirstControlPoints,
-                    StepGeom_bssfUnspecified,
-                    StepData_LUnknown,
-                    StepData_LUnknown,
-                    StepData_LUnknown,
-                    new TColStd_HArray1OfInteger,
-                    new TColStd_HArray1OfInteger,
-                    new TColStd_HArray1OfReal,
-                    new TColStd_HArray1OfReal,
-                    StepGeom_ktUnspecified);
-  addToModel(aFirstBSSWN);
-  Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface) aFirstSurface =
-    new StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface;
-  aFirstSurface->Init(new TCollection_HAsciiString,
-                      1,
-                      1,
-                      aFirstControlPoints,
-                      StepGeom_bssfUnspecified,
-                      StepData_LUnknown,
-                      StepData_LUnknown,
-                      StepData_LUnknown,
-                      aFirstBSSWN,
-                      new StepGeom_RationalBSplineSurface);
-  addToModel(aFirstSurface);
-
-  // Creating surface containing the second Cartesian point.
-  Handle(StepGeom_HArray2OfCartesianPoint) aSecondControlPoints =
-    new StepGeom_HArray2OfCartesianPoint(1, 1, 1, 1);
-  aSecondControlPoints->SetValue(1, 1, aPt2);
-  addToModel(aSecondControlPoints);
-  Handle(StepGeom_BSplineSurfaceWithKnots) aSecondBSSWN = new StepGeom_BSplineSurfaceWithKnots;
-  aSecondBSSWN->Init(new TCollection_HAsciiString,
-                     1,
-                     1,
-                     aSecondControlPoints,
-                     StepGeom_bssfUnspecified,
-                     StepData_LUnknown,
-                     StepData_LUnknown,
-                     StepData_LUnknown,
-                     new TColStd_HArray1OfInteger,
-                     new TColStd_HArray1OfInteger,
-                     new TColStd_HArray1OfReal,
-                     new TColStd_HArray1OfReal,
-                     StepGeom_ktUnspecified);
-  addToModel(aSecondBSSWN);
-  Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface) aSecondSurface =
-    new StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface;
-  aSecondSurface->Init(new TCollection_HAsciiString,
-                       1,
-                       1,
-                       aSecondControlPoints,
-                       StepGeom_bssfUnspecified,
-                       StepData_LUnknown,
-                       StepData_LUnknown,
-                       StepData_LUnknown,
-                       new StepGeom_BSplineSurfaceWithKnots,
-                       new StepGeom_RationalBSplineSurface);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
-}
diff --git a/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_CircleProcessor_Test.cxx b/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_CircleProcessor_Test.cxx
deleted file mode 100644 (file)
index 4d8e3d9..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-// 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.
-
-#include "MergeSTEPEntities_BaseTestFixture.hxx"
-
-#include <MergeSTEPEntities_CircleProcessor.hxx>
-
-#include <StepShape_EdgeCurve.hxx>
-#include <StepGeom_SurfaceCurve.hxx>
-#include <StepGeom_SeamCurve.hxx>
-
-class MergeSTEPEntities_CircleProcessorTest : public MergeSTEPEntities_BaseTestFixture
-{
-protected:
-  //! Perform removal of duplicate entities.
-  TColStd_MapOfTransient replaceDuplicateCircles()
-  {
-    MergeSTEPEntities_CircleProcessor aProcessor(myWS);
-    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
-    {
-      aProcessor.ProcessEntity(myWS->Model()->Value(anIndex));
-    }
-
-    TColStd_MapOfTransient aRemovedEntities;
-    aProcessor.Perform(aRemovedEntities);
-    return aRemovedEntities;
-  }
-};
-
-// Check that Circles with the same coordinates and different names are not merged.
-TEST_F(MergeSTEPEntities_CircleProcessorTest, DifferentNames)
-{
-  // Creating Circles.
-  Handle(StepGeom_Circle) aCircle1 = addCircle("Circle1");
-  Handle(StepGeom_Circle) aCircle2 = addCircle("Circle2");
-
-  // Creating EdgeCurve containing the first Circle.
-  Handle(StepShape_EdgeCurve) aFirstEdgeCurve = new StepShape_EdgeCurve;
-  aFirstEdgeCurve->Init(new TCollection_HAsciiString,
-                        new StepShape_Vertex,
-                        new StepShape_Vertex,
-                        aCircle1,
-                        Standard_True);
-  addToModel(aFirstEdgeCurve);
-
-  // Creating EdgeCurve containing the second Circle.
-  Handle(StepShape_EdgeCurve) aSecondEdgeCurve = new StepShape_EdgeCurve;
-  aSecondEdgeCurve->Init(new TCollection_HAsciiString,
-                         new StepShape_Vertex,
-                         new StepShape_Vertex,
-                         aCircle2,
-                         Standard_True);
-  addToModel(aSecondEdgeCurve);
-
-  // Performing removal of duplicate Circles.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCircles();
-
-  // Check that nothing was removed.
-  EXPECT_TRUE(aRemovedEntities.IsEmpty());
-}
-
-// Check that equal Circles are merged for StepShape_EdgeCurve.
-TEST_F(MergeSTEPEntities_CircleProcessorTest, StepShape_EdgeCurve)
-{
-  // Creating Circles.
-  Handle(StepGeom_Circle) aCircle1 = addCircle();
-  Handle(StepGeom_Circle) aCircle2 = addCircle();
-
-  // Creating EdgeCurve containing the first Circle.
-  Handle(StepShape_EdgeCurve) aFirstEdgeCurve = new StepShape_EdgeCurve;
-  aFirstEdgeCurve->Init(new TCollection_HAsciiString,
-                        new StepShape_Vertex,
-                        new StepShape_Vertex,
-                        aCircle1,
-                        Standard_True);
-  addToModel(aFirstEdgeCurve);
-
-  // Creating EdgeCurve containing the second Circle.
-  Handle(StepShape_EdgeCurve) aSecondEdgeCurve = new StepShape_EdgeCurve;
-  aSecondEdgeCurve->Init(new TCollection_HAsciiString,
-                         new StepShape_Vertex,
-                         new StepShape_Vertex,
-                         aCircle2,
-                         Standard_True);
-  addToModel(aSecondEdgeCurve);
-
-  // Performing removal of duplicate Circles.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCircles();
-
-  // Check that one Circle was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aCircle1) || aRemovedEntities.Contains(aCircle2));
-}
-
-// Check that equal Circles are merged for StepGeom_SurfaceCurve.
-TEST_F(MergeSTEPEntities_CircleProcessorTest, StepGeom_SurfaceCurve)
-{
-  // Creating Circles.
-  Handle(StepGeom_Circle) aCircle1 = addCircle();
-  Handle(StepGeom_Circle) aCircle2 = addCircle();
-
-  // Creating SurfaceCurve containing the first Circle.
-  Handle(StepGeom_SurfaceCurve) aFirstSurfaceCurve = new StepGeom_SurfaceCurve;
-  aFirstSurfaceCurve->Init(new TCollection_HAsciiString,
-                           aCircle1,
-                           new StepGeom_HArray1OfPcurveOrSurface,
-                           StepGeom_pscrCurve3d);
-  addToModel(aFirstSurfaceCurve);
-
-  // Creating SurfaceCurve containing the second Circle.
-  Handle(StepGeom_SurfaceCurve) aSecondSurfaceCurve = new StepGeom_SurfaceCurve;
-  aSecondSurfaceCurve->Init(new TCollection_HAsciiString,
-                            aCircle2,
-                            new StepGeom_HArray1OfPcurveOrSurface,
-                            StepGeom_pscrCurve3d);
-  addToModel(aSecondSurfaceCurve);
-
-  // Performing removal of duplicate Circles.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCircles();
-
-  // Check that one Circle was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aCircle1) || aRemovedEntities.Contains(aCircle2));
-}
-
-// Check that equal Circles are merged for StepGeom_SeamCurve.
-TEST_F(MergeSTEPEntities_CircleProcessorTest, StepGeom_SeamCurve)
-{
-  // Creating Circles.
-  Handle(StepGeom_Circle) aCircle1 = addCircle();
-  Handle(StepGeom_Circle) aCircle2 = addCircle();
-
-  // Creating SeamCurve containing the first Circle.
-  Handle(StepGeom_SeamCurve) aFirstSeamCurve = new StepGeom_SeamCurve;
-  aFirstSeamCurve->Init(new TCollection_HAsciiString,
-                        aCircle1,
-                        new StepGeom_HArray1OfPcurveOrSurface,
-                        StepGeom_pscrCurve3d);
-  addToModel(aFirstSeamCurve);
-
-  // Creating SeamCurve containing the second Circle.
-  Handle(StepGeom_SeamCurve) aSecondSeamCurve = new StepGeom_SeamCurve;
-  aSecondSeamCurve->Init(new TCollection_HAsciiString,
-                         aCircle2,
-                         new StepGeom_HArray1OfPcurveOrSurface,
-                         StepGeom_pscrCurve3d);
-  addToModel(aSecondSeamCurve);
-
-  // Performing removal of duplicate Circles.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCircles();
-
-  // Check that one Circle was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aCircle1) || aRemovedEntities.Contains(aCircle2));
-}
diff --git a/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_DirectionProcessor_Test.cxx b/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_DirectionProcessor_Test.cxx
deleted file mode 100644 (file)
index 876cd29..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-// 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.
-
-#include "MergeSTEPEntities_BaseTestFixture.hxx"
-
-#include <MergeSTEPEntities_DirectionProcessor.hxx>
-
-#include <StepGeom_Axis1Placement.hxx>
-#include <StepGeom_Axis2Placement3d.hxx>
-
-class MergeSTEPEntities_DirectionProcessorTest : public MergeSTEPEntities_BaseTestFixture
-{
-protected:
-  //! Perform removal of duplicate entities.
-  TColStd_MapOfTransient replaceDuplicateDirections()
-  {
-    MergeSTEPEntities_DirectionProcessor aProcessor(myWS);
-    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
-    {
-      aProcessor.ProcessEntity(myWS->Model()->Value(anIndex));
-    }
-
-    TColStd_MapOfTransient aRemovedEntities;
-    aProcessor.Perform(aRemovedEntities);
-    return aRemovedEntities;
-  }
-};
-
-// Check that directions with the same coordinates and different names are not merged.
-TEST_F(MergeSTEPEntities_DirectionProcessorTest, DifferentNames)
-{
-  // Creating directions.
-  Handle(StepGeom_Direction) aDir1 = addDirection("dir1");
-  Handle(StepGeom_Direction) aDir2 = addDirection("dir2");
-
-  // Creating vector containing the first direction.
-  Handle(StepGeom_Vector) aFirstVector = new StepGeom_Vector;
-  aFirstVector->Init(new TCollection_HAsciiString, aDir1, 1.);
-  addToModel(aFirstVector);
-
-  // Creating vector containing the second direction.
-  Handle(StepGeom_Vector) aSecondVector = new StepGeom_Vector;
-  aSecondVector->Init(new TCollection_HAsciiString, aDir2, 1.);
-  addToModel(aSecondVector);
-
-  // Performing removal of duplicate directions.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateDirections();
-
-  // Check that nothing was removed.
-  EXPECT_TRUE(aRemovedEntities.IsEmpty());
-}
-
-// Check that directions with the same coordinates and same names are
-// merged for StepGeom_Axis1Placement.
-TEST_F(MergeSTEPEntities_DirectionProcessorTest, StepGeom_Axis1Placement)
-{
-  // Creating directions.
-  Handle(StepGeom_Direction) aDir1 = addDirection();
-  Handle(StepGeom_Direction) aDir2 = addDirection();
-
-  // Creating Cartesian point for the location.
-  Handle(StepGeom_CartesianPoint) aLocation       = new StepGeom_CartesianPoint;
-  Handle(TColStd_HArray1OfReal)   aLocationCoords = new TColStd_HArray1OfReal(1, 3);
-  aLocationCoords->SetValue(1, 0.);
-  aLocationCoords->SetValue(2, 0.);
-  aLocationCoords->SetValue(3, 0.);
-  aLocation->Init(new TCollection_HAsciiString, aLocationCoords);
-  addToModel(aLocation);
-
-  // Creating axis containing the first direction.
-  Handle(StepGeom_Axis1Placement) aFirstAxis = new StepGeom_Axis1Placement;
-  aFirstAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir1);
-  addToModel(aFirstAxis);
-
-  // Creating axis containing the second direction.
-  Handle(StepGeom_Axis1Placement) aSecondAxis = new StepGeom_Axis1Placement;
-  aSecondAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir2);
-  addToModel(aSecondAxis);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateDirections();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aDir1) || aRemovedEntities.Contains(aDir2));
-}
-
-// Check that directions with the same coordinates and same names are
-// merged for StepGeom_Axis2Placement.
-TEST_F(MergeSTEPEntities_DirectionProcessorTest, StepGeom_Axis2Placement)
-{
-  // Creating directions.
-  Handle(StepGeom_Direction) aDir1 = addDirection();
-  Handle(StepGeom_Direction) aDir2 = addDirection();
-
-  // Creating Cartesian point for the location.
-  Handle(StepGeom_CartesianPoint) aLocation       = new StepGeom_CartesianPoint;
-  Handle(TColStd_HArray1OfReal)   aLocationCoords = new TColStd_HArray1OfReal(1, 3);
-  aLocationCoords->SetValue(1, 0.);
-  aLocationCoords->SetValue(2, 0.);
-  aLocationCoords->SetValue(3, 0.);
-  aLocation->Init(new TCollection_HAsciiString, aLocationCoords);
-  addToModel(aLocation);
-
-  // Creating axis containing the first direction.
-  Handle(StepGeom_Axis2Placement3d) aFirstAxis = new StepGeom_Axis2Placement3d;
-  aFirstAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir1, false, nullptr);
-  addToModel(aFirstAxis);
-
-  // Creating axis containing the second direction.
-  Handle(StepGeom_Axis2Placement3d) aSecondAxis = new StepGeom_Axis2Placement3d;
-  aSecondAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir2, false, nullptr);
-  addToModel(aSecondAxis);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateDirections();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aDir1) || aRemovedEntities.Contains(aDir2));
-}
-
-// Check that points with the same coordinates and same names are
-// merged for StepGeom_Vector.
-TEST_F(MergeSTEPEntities_DirectionProcessorTest, StepGeom_Vector)
-{
-  // Creating directions.
-  Handle(StepGeom_Direction) aDir1 = addDirection();
-  Handle(StepGeom_Direction) aDir2 = addDirection();
-
-  // Creating vector containing the first direction.
-  Handle(StepGeom_Vector) aFirstVector = new StepGeom_Vector;
-  aFirstVector->Init(new TCollection_HAsciiString, aDir1, 1.);
-  addToModel(aFirstVector);
-
-  // Creating vector containing the second direction.
-  Handle(StepGeom_Vector) aSecondVector = new StepGeom_Vector;
-  aSecondVector->Init(new TCollection_HAsciiString, aDir2, 1.);
-  addToModel(aSecondVector);
-
-  // Performing removal of duplicate Cartesian points.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateDirections();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aDir1) || aRemovedEntities.Contains(aDir2));
-}
diff --git a/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_LineProcessor_Test.cxx b/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_LineProcessor_Test.cxx
deleted file mode 100644 (file)
index ed3ec53..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-// 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.
-
-#include "MergeSTEPEntities_BaseTestFixture.hxx"
-
-#include <MergeSTEPEntities_LineProcessor.hxx>
-
-#include <StepShape_EdgeCurve.hxx>
-#include <StepGeom_TrimmedCurve.hxx>
-#include <StepGeom_SurfaceCurve.hxx>
-#include <StepRepr_DefinitionalRepresentation.hxx>
-#include <StepGeom_SeamCurve.hxx>
-#include <StepRepr_RepresentationContext.hxx>
-
-class MergeSTEPEntities_LineProcessorTest : public MergeSTEPEntities_BaseTestFixture
-{
-protected:
-  //! Perform removal of duplicate entities.
-  TColStd_MapOfTransient replaceDuplicateLines()
-  {
-    MergeSTEPEntities_LineProcessor aProcessor(myWS);
-    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
-    {
-      aProcessor.ProcessEntity(myWS->Model()->Value(anIndex));
-    }
-
-    TColStd_MapOfTransient aRemovedEntities;
-    aProcessor.Perform(aRemovedEntities);
-    return aRemovedEntities;
-  }
-};
-
-// Check that Lines with different names are not merged.
-TEST_F(MergeSTEPEntities_LineProcessorTest, DifferentNames)
-{
-  // Creating Lines.
-  Handle(StepGeom_Line) aLine1 = addLine("Line1");
-  Handle(StepGeom_Line) aLine2 = addLine("Line2");
-
-  // Creating EdgeCurve containing the first Line.
-  Handle(StepShape_EdgeCurve) aFirstEdgeCurve = new StepShape_EdgeCurve;
-  aFirstEdgeCurve->Init(new TCollection_HAsciiString,
-                        new StepShape_Vertex,
-                        new StepShape_Vertex,
-                        aLine1,
-                        Standard_True);
-  addToModel(aFirstEdgeCurve);
-
-  // Creating EdgeCurve containing the second Line.
-  Handle(StepShape_EdgeCurve) aSecondEdgeCurve = new StepShape_EdgeCurve;
-  aSecondEdgeCurve->Init(new TCollection_HAsciiString,
-                         new StepShape_Vertex,
-                         new StepShape_Vertex,
-                         aLine2,
-                         Standard_True);
-  addToModel(aSecondEdgeCurve);
-
-  // Performing removal of duplicate Lines.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
-
-  // Check that nothing was removed.
-  EXPECT_TRUE(aRemovedEntities.IsEmpty());
-}
-
-// Check that equal Lines are merged for StepShape_EdgeCurve.
-TEST_F(MergeSTEPEntities_LineProcessorTest, StepShape_EdgeCurve)
-{
-  // Creating Lines.
-  Handle(StepGeom_Line) aLine1 = addLine();
-  Handle(StepGeom_Line) aLine2 = addLine();
-
-  // Creating EdgeCurve containing the first Line.
-  Handle(StepShape_EdgeCurve) aFirstEdgeCurve = new StepShape_EdgeCurve;
-  aFirstEdgeCurve->Init(new TCollection_HAsciiString,
-                        new StepShape_Vertex,
-                        new StepShape_Vertex,
-                        aLine1,
-                        Standard_True);
-  addToModel(aFirstEdgeCurve);
-
-  // Creating EdgeCurve containing the second Line.
-  Handle(StepShape_EdgeCurve) aSecondEdgeCurve = new StepShape_EdgeCurve;
-  aSecondEdgeCurve->Init(new TCollection_HAsciiString,
-                         new StepShape_Vertex,
-                         new StepShape_Vertex,
-                         aLine2,
-                         Standard_True);
-  addToModel(aSecondEdgeCurve);
-
-  // Performing removal of duplicate Lines.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
-
-  // Check that one Line was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aLine1) || aRemovedEntities.Contains(aLine2));
-}
-
-// Check that equal Lines are merged for StepGeom_TrimmedCurve.
-TEST_F(MergeSTEPEntities_LineProcessorTest, StepGeom_TrimmedCurve)
-{
-  // Creating Lines.
-  Handle(StepGeom_Line) aLine1 = addLine();
-  Handle(StepGeom_Line) aLine2 = addLine();
-
-  // Creating TrimmedCurve containing the first Line.
-  Handle(StepGeom_TrimmedCurve) aFirstTrimmedCurve = new StepGeom_TrimmedCurve;
-  aFirstTrimmedCurve->Init(new TCollection_HAsciiString,
-                           aLine1,
-                           new StepGeom_HArray1OfTrimmingSelect,
-                           new StepGeom_HArray1OfTrimmingSelect,
-                           Standard_True,
-                           StepGeom_tpUnspecified);
-  addToModel(aFirstTrimmedCurve);
-
-  // Creating TrimmedCurve containing the second Line.
-  Handle(StepGeom_TrimmedCurve) aSecondTrimmedCurve = new StepGeom_TrimmedCurve;
-  aSecondTrimmedCurve->Init(new TCollection_HAsciiString,
-                            aLine2,
-                            new StepGeom_HArray1OfTrimmingSelect,
-                            new StepGeom_HArray1OfTrimmingSelect,
-                            Standard_True,
-                            StepGeom_tpUnspecified);
-  addToModel(aSecondTrimmedCurve);
-
-  // Performing removal of duplicate Lines.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
-
-  // Check that one Line was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aLine1) || aRemovedEntities.Contains(aLine2));
-}
-
-// Check that equal Lines are merged for StepGeom_SurfaceCurve.
-TEST_F(MergeSTEPEntities_LineProcessorTest, StepGeom_SurfaceCurve)
-{
-  // Creating Lines.
-  Handle(StepGeom_Line) aLine1 = addLine();
-  Handle(StepGeom_Line) aLine2 = addLine();
-
-  // Creating SurfaceCurve containing the first Line.
-  Handle(StepGeom_SurfaceCurve) aFirstSurfaceCurve = new StepGeom_SurfaceCurve;
-  aFirstSurfaceCurve->Init(new TCollection_HAsciiString,
-                           aLine1,
-                           new StepGeom_HArray1OfPcurveOrSurface,
-                           StepGeom_pscrCurve3d);
-  addToModel(aFirstSurfaceCurve);
-
-  // Creating SurfaceCurve containing the second Line.
-  Handle(StepGeom_SurfaceCurve) aSecondSurfaceCurve = new StepGeom_SurfaceCurve;
-  aSecondSurfaceCurve->Init(new TCollection_HAsciiString,
-                            aLine2,
-                            new StepGeom_HArray1OfPcurveOrSurface,
-                            StepGeom_pscrCurve3d);
-  addToModel(aSecondSurfaceCurve);
-
-  // Performing removal of duplicate Lines.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
-
-  // Check that one Line was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aLine1) || aRemovedEntities.Contains(aLine2));
-}
-
-// Check that equal Lines are merged for StepRepr_DefinitionalRepresentation.
-TEST_F(MergeSTEPEntities_LineProcessorTest, StepRepr_DefinitionalRepresentation)
-{
-  // Creating Lines.
-  Handle(StepGeom_Line) aLine1 = addLine();
-  Handle(StepGeom_Line) aLine2 = addLine();
-
-  // Creating DefinitionalRepresentation containing the first Line.
-  Handle(StepRepr_HArray1OfRepresentationItem) aFirstItems =
-    new StepRepr_HArray1OfRepresentationItem(1, 1);
-  aFirstItems->SetValue(1, aLine1);
-  Handle(StepRepr_DefinitionalRepresentation) aFirstDefinitionalRepresentation =
-    new StepRepr_DefinitionalRepresentation;
-  aFirstDefinitionalRepresentation->Init(new TCollection_HAsciiString,
-                                         aFirstItems,
-                                         new StepRepr_RepresentationContext);
-  addToModel(aFirstDefinitionalRepresentation);
-
-  // Creating DefinitionalRepresentation containing the second Line.
-  Handle(StepRepr_HArray1OfRepresentationItem) aSecondItems =
-    new StepRepr_HArray1OfRepresentationItem(1, 1);
-  aSecondItems->SetValue(1, aLine2);
-  Handle(StepRepr_DefinitionalRepresentation) aSecondDefinitionalRepresentation =
-    new StepRepr_DefinitionalRepresentation;
-  aSecondDefinitionalRepresentation->Init(new TCollection_HAsciiString,
-                                          aSecondItems,
-                                          new StepRepr_RepresentationContext);
-
-  // Performing removal of duplicate Lines.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
-
-  // Check that one Line was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aLine1) || aRemovedEntities.Contains(aLine2));
-}
-
-// Check that equal Lines are merged for StepGeom_SeamCurve.
-TEST_F(MergeSTEPEntities_LineProcessorTest, StepGeom_SeamCurve)
-{
-  // Creating Lines.
-  Handle(StepGeom_Line) aLine1 = addLine();
-  Handle(StepGeom_Line) aLine2 = addLine();
-
-  // Creating SeamCurve containing the first Line.
-  Handle(StepGeom_SeamCurve) aFirstSeamCurve = new StepGeom_SeamCurve;
-  aFirstSeamCurve->Init(new TCollection_HAsciiString,
-                        aLine1,
-                        new StepGeom_HArray1OfPcurveOrSurface,
-                        StepGeom_pscrCurve3d);
-  addToModel(aFirstSeamCurve);
-
-  // Creating SeamCurve containing the second Line.
-  Handle(StepGeom_SeamCurve) aSecondSeamCurve = new StepGeom_SeamCurve;
-  aSecondSeamCurve->Init(new TCollection_HAsciiString,
-                         aLine2,
-                         new StepGeom_HArray1OfPcurveOrSurface,
-                         StepGeom_pscrCurve3d);
-  addToModel(aSecondSeamCurve);
-
-  // Performing removal of duplicate Lines.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
-
-  // Check that one Line was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aLine1) || aRemovedEntities.Contains(aLine2));
-}
diff --git a/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_Merger_Test.cxx b/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_Merger_Test.cxx
deleted file mode 100644 (file)
index 1ce9630..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-// 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.
-
-#include "MergeSTEPEntities_BaseTestFixture.hxx"
-
-#include <MergeSTEPEntities_Merger.hxx>
-
-#include <StepGeom_Axis1Placement.hxx>
-
-class MergeSTEPEntities_MergerTest : public MergeSTEPEntities_BaseTestFixture
-{
-protected:
-  // Get the number of entities of the specified type.
-  // @param theType the type of entities to count.
-  // @return the number of entities of the specified type.
-  int getEntitiesCount(const Handle(Standard_Type)& theType) const
-  {
-    int aCount = 0;
-    for (Standard_Integer i = 1; i <= myWS->Model()->NbEntities(); i++)
-    {
-      if (myWS->Model()->Value(i)->IsKind(theType))
-      {
-        aCount++;
-      }
-    }
-    return aCount;
-  }
-
-  //! Perform removal of duplicate entities points.
-  void performRemoval()
-  {
-    MergeSTEPEntities_Merger aMerger(myWS);
-    aMerger.Perform();
-  }
-};
-
-// Check that entities with the same coordinates and different names are not merged.
-TEST_F(MergeSTEPEntities_MergerTest, DifferentEntities)
-{
-  // Creating directions.
-  Handle(StepGeom_Direction) aDir1 = addDirection("dir1");
-  Handle(StepGeom_Direction) aDir2 = addDirection("dir2");
-
-  // Creating vector containing the first direction.
-  Handle(StepGeom_Vector) aFirstVector = new StepGeom_Vector;
-  aFirstVector->Init(new TCollection_HAsciiString, aDir1, 1.);
-  addToModel(aFirstVector);
-
-  // Creating vector containing the second direction.
-  Handle(StepGeom_Vector) aSecondVector = new StepGeom_Vector;
-  aSecondVector->Init(new TCollection_HAsciiString, aDir2, 1.);
-  addToModel(aSecondVector);
-
-  const int aDirectionCountBefore = getEntitiesCount(STANDARD_TYPE(StepGeom_Direction));
-
-  // Performing removal of duplicate directions.
-  performRemoval();
-
-  const int aDirectionCountAfter = getEntitiesCount(STANDARD_TYPE(StepGeom_Direction));
-
-  // Check that nothing was removed.
-  EXPECT_EQ(aDirectionCountBefore, 2);
-  EXPECT_EQ(aDirectionCountBefore, aDirectionCountAfter);
-}
-
-// Check that entities with the same coordinates and same names are
-// merged for StepGeom_Axis1Placement.
-TEST_F(MergeSTEPEntities_MergerTest, EqualEntities)
-{
-  // Creating directions.
-  Handle(StepGeom_Direction) aDir1 = addDirection();
-  Handle(StepGeom_Direction) aDir2 = addDirection();
-
-  // Creating Cartesian point for the location.
-  Handle(StepGeom_CartesianPoint) aLocation       = new StepGeom_CartesianPoint;
-  Handle(TColStd_HArray1OfReal)   aLocationCoords = new TColStd_HArray1OfReal(1, 3);
-  aLocationCoords->SetValue(1, 0.);
-  aLocationCoords->SetValue(2, 0.);
-  aLocationCoords->SetValue(3, 0.);
-  aLocation->Init(new TCollection_HAsciiString, aLocationCoords);
-  addToModel(aLocation);
-
-  // Creating axis containing the first direction.
-  Handle(StepGeom_Axis1Placement) aFirstAxis = new StepGeom_Axis1Placement;
-  aFirstAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir1);
-  addToModel(aFirstAxis);
-
-  // Creating axis containing the second direction.
-  Handle(StepGeom_Axis1Placement) aSecondAxis = new StepGeom_Axis1Placement;
-  aSecondAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir2);
-  addToModel(aSecondAxis);
-
-  const int aDirectionCountBefore = getEntitiesCount(STANDARD_TYPE(StepGeom_Direction));
-
-  // Performing removal of duplicate directions.
-  performRemoval();
-
-  const int aDirectionCountAfter = getEntitiesCount(STANDARD_TYPE(StepGeom_Direction));
-
-  // Check that one direction was removed.
-  EXPECT_EQ(aDirectionCountBefore, 2);
-  EXPECT_EQ(aDirectionCountAfter, 1);
-}
diff --git a/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_PlaneProcessor_Test.cxx b/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_PlaneProcessor_Test.cxx
deleted file mode 100644 (file)
index 64388d5..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-// 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.
-
-#include "MergeSTEPEntities_BaseTestFixture.hxx"
-
-#include <MergeSTEPEntities_PlaneProcessor.hxx>
-
-#include <StepShape_AdvancedFace.hxx>
-#include <StepGeom_Pcurve.hxx>
-#include <StepRepr_DefinitionalRepresentation.hxx>
-
-class MergeSTEPEntities_PlaneProcessorTest : public MergeSTEPEntities_BaseTestFixture
-{
-protected:
-  //! Perform removal of duplicate entities.
-  TColStd_MapOfTransient replaceDuplicatePlanes()
-  {
-    MergeSTEPEntities_PlaneProcessor aProcessor(myWS);
-    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
-    {
-      aProcessor.ProcessEntity(myWS->Model()->Value(anIndex));
-    }
-
-    TColStd_MapOfTransient aRemovedEntities;
-    aProcessor.Perform(aRemovedEntities);
-    return aRemovedEntities;
-  }
-};
-
-// Check that Planes with different names are not merged.
-TEST_F(MergeSTEPEntities_PlaneProcessorTest, DifferentNames)
-{
-  // Creating Planes.
-  Handle(StepGeom_Plane) aPlane1 = addPlane("Plane1");
-  Handle(StepGeom_Plane) aPlane2 = addPlane("Plane2");
-
-  // Creating StepShape_AdvancedFace containing the first Plane.
-  Handle(StepShape_AdvancedFace) aFirstAdvancedFace = new StepShape_AdvancedFace;
-  aFirstAdvancedFace->Init(new TCollection_HAsciiString,
-                           new StepShape_HArray1OfFaceBound,
-                           aPlane1,
-                           Standard_True);
-  addToModel(aFirstAdvancedFace);
-
-  // Creating StepShape_AdvancedFace containing the second Plane.
-  Handle(StepShape_AdvancedFace) aSecondAdvancedFace = new StepShape_AdvancedFace;
-  aSecondAdvancedFace->Init(new TCollection_HAsciiString,
-                            new StepShape_HArray1OfFaceBound,
-                            aPlane2,
-                            Standard_True);
-  addToModel(aSecondAdvancedFace);
-
-  // Performing removal of duplicate Planes.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicatePlanes();
-
-  // Check that nothing was removed.
-  EXPECT_TRUE(aRemovedEntities.IsEmpty());
-}
-
-// Check that equal Planes are merged for StepShape_AdvancedFace.
-TEST_F(MergeSTEPEntities_PlaneProcessorTest, StepShape_AdvancedFace)
-{
-  // Creating Planes.
-  Handle(StepGeom_Plane) aPlane1 = addPlane();
-  Handle(StepGeom_Plane) aPlane2 = addPlane();
-
-  // Creating StepShape_AdvancedFace containing the first Plane.
-  Handle(StepShape_AdvancedFace) aFirstAdvancedFace = new StepShape_AdvancedFace;
-  aFirstAdvancedFace->Init(new TCollection_HAsciiString,
-                           new StepShape_HArray1OfFaceBound,
-                           aPlane1,
-                           Standard_True);
-  addToModel(aFirstAdvancedFace);
-
-  // Creating StepShape_AdvancedFace containing the second Plane.
-  Handle(StepShape_AdvancedFace) aSecondAdvancedFace = new StepShape_AdvancedFace;
-  aSecondAdvancedFace->Init(new TCollection_HAsciiString,
-                            new StepShape_HArray1OfFaceBound,
-                            aPlane2,
-                            Standard_True);
-  addToModel(aSecondAdvancedFace);
-
-  // Performing removal of duplicate Planes.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicatePlanes();
-
-  // Check that one Plane was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPlane1) || aRemovedEntities.Contains(aPlane2));
-}
-
-// Check that equal Planes are merged for StepGeom_Pcurve.
-TEST_F(MergeSTEPEntities_PlaneProcessorTest, StepGeom_Pcurve)
-{
-  // Creating Planes.
-  Handle(StepGeom_Plane) aPlane1 = addPlane();
-  Handle(StepGeom_Plane) aPlane2 = addPlane();
-
-  // Creating StepGeom_Pcurve containing the first Plane.
-  Handle(StepGeom_Pcurve) aFirstPcurve = new StepGeom_Pcurve;
-  aFirstPcurve->Init(new TCollection_HAsciiString,
-                     aPlane1,
-                     new StepRepr_DefinitionalRepresentation);
-  addToModel(aFirstPcurve);
-
-  // Creating StepGeom_Pcurve containing the second Plane.
-  Handle(StepGeom_Pcurve) aSecondPcurve = new StepGeom_Pcurve;
-  aSecondPcurve->Init(new TCollection_HAsciiString,
-                      aPlane2,
-                      new StepRepr_DefinitionalRepresentation);
-  addToModel(aSecondPcurve);
-
-  // Performing removal of duplicate Planes.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicatePlanes();
-
-  // Check that one Plane was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aPlane1) || aRemovedEntities.Contains(aPlane2));
-}
diff --git a/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_VectorProcessor_Test.cxx b/src/DataExchange/TKDESTEP/GTests/MergeSTEPEntities_VectorProcessor_Test.cxx
deleted file mode 100644 (file)
index c66edf0..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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.
-
-#include "MergeSTEPEntities_BaseTestFixture.hxx"
-
-#include <MergeSTEPEntities_VectorProcessor.hxx>
-
-#include <StepGeom_Line.hxx>
-
-class MergeSTEPEntities_VectorProcessorTest : public MergeSTEPEntities_BaseTestFixture
-{
-protected:
-  //! Perform removal of duplicate entities.
-  TColStd_MapOfTransient replaceDuplicateVectors()
-  {
-    MergeSTEPEntities_VectorProcessor aProcessor(myWS);
-    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
-    {
-      aProcessor.ProcessEntity(myWS->Model()->Value(anIndex));
-    }
-
-    TColStd_MapOfTransient aRemovedEntities;
-    aProcessor.Perform(aRemovedEntities);
-    return aRemovedEntities;
-  }
-};
-
-// Check that Vectors with the same coordinates and different names are not merged.
-TEST_F(MergeSTEPEntities_VectorProcessorTest, DifferentNames)
-{
-  // Creating Vectors.
-  Handle(StepGeom_Vector) aVec1 = addVector("vec1");
-  Handle(StepGeom_Vector) aVec2 = addVector("vec2");
-
-  // Creating a cartesian point for the lines.
-  Handle(StepGeom_CartesianPoint) aPnt = addCartesianPoint(nullptr, {0., 0., 0.});
-
-  // Creating aLine containing the first Vector.
-  Handle(StepGeom_Line) aLine1 = new StepGeom_Line;
-  aLine1->Init(new TCollection_HAsciiString, aPnt, aVec1);
-  addToModel(aLine1);
-
-  // Creating aLine containing the second Vector.
-  Handle(StepGeom_Line) aLine2 = new StepGeom_Line;
-  aLine2->Init(new TCollection_HAsciiString, aPnt, aVec2);
-  addToModel(aLine2);
-
-  // Performing removal of duplicate Vectors.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateVectors();
-
-  // Check that nothing was removed.
-  EXPECT_TRUE(aRemovedEntities.IsEmpty());
-}
-
-// Check that Vectors with the same coordinates and same names are
-// merged for StepGeom_Axis1Placement.
-TEST_F(MergeSTEPEntities_VectorProcessorTest, StepGeom_Line)
-{
-  // Creating Vectors.
-  Handle(StepGeom_Vector) aVec1 = addVector();
-  Handle(StepGeom_Vector) aVec2 = addVector();
-
-  // Creating a cartesian point for the lines.
-  Handle(StepGeom_CartesianPoint) aPnt = addCartesianPoint(nullptr, {0., 0., 0.});
-
-  // Creating aLine containing the first Vector.
-  Handle(StepGeom_Line) aLine1 = new StepGeom_Line;
-  aLine1->Init(new TCollection_HAsciiString, aPnt, aVec1);
-  addToModel(aLine1);
-
-  // Creating aLine containing the second Vector.
-  Handle(StepGeom_Line) aLine2 = new StepGeom_Line;
-  aLine2->Init(new TCollection_HAsciiString, aPnt, aVec2);
-  addToModel(aLine2);
-
-  // Performing removal of duplicate Vectors.
-  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateVectors();
-
-  // Check that duplicate was removed.
-  EXPECT_EQ(aRemovedEntities.Size(), 1);
-  EXPECT_TRUE(aRemovedEntities.Contains(aVec1) || aRemovedEntities.Contains(aVec2));
-}
diff --git a/src/DataExchange/TKDESTEP/GTests/StepTidy_Axis2Placement3dReducer_Test.cxx b/src/DataExchange/TKDESTEP/GTests/StepTidy_Axis2Placement3dReducer_Test.cxx
new file mode 100644 (file)
index 0000000..956e17f
--- /dev/null
@@ -0,0 +1,461 @@
+// 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.
+
+#include "StepTidy_BaseTestFixture.pxx"
+
+#include <StepTidy_Axis2Placement3dReducer.pxx>
+
+#include <StepGeom_Plane.hxx>
+#include <StepRepr_ItemDefinedTransformation.hxx>
+#include <StepGeom_CylindricalSurface.hxx>
+#include <StepShape_ShapeRepresentation.hxx>
+#include <StepRepr_RepresentationContext.hxx>
+#include <StepRepr_ConstructiveGeometryRepresentation.hxx>
+#include <StepGeom_Circle.hxx>
+#include <StepVisual_PresentationLayerAssignment.hxx>
+#include <StepVisual_StyledItem.hxx>
+#include <StepGeom_Ellipse.hxx>
+#include <StepGeom_ConicalSurface.hxx>
+#include <StepGeom_ToroidalSurface.hxx>
+#include <StepShape_AdvancedBrepShapeRepresentation.hxx>
+#include <StepGeom_SphericalSurface.hxx>
+
+class StepTidy_Axis2Placement3dReducerTest : public StepTidy_BaseTestFixture
+{
+protected:
+  //! Perform removal of duplicate entities.
+  TColStd_MapOfTransient replaceDuplicateAxis2Placement3ds()
+  {
+    StepTidy_Axis2Placement3dReducer aReducer(myWS);
+    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
+    {
+      aReducer.ProcessEntity(myWS->Model()->Value(anIndex));
+    }
+
+    TColStd_MapOfTransient aRemovedEntities;
+    aReducer.Perform(aRemovedEntities);
+    return aRemovedEntities;
+  }
+};
+
+// Check that Axis2Placement3ds with the same coordinates and different names are not merged.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, DifferentNames)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d("Axis1");
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d("Axis2");
+
+  // Creating a plane containing the first Axis2Placement3d.
+  Handle(StepGeom_Plane) aPlane1 = new StepGeom_Plane;
+  aPlane1->Init(new TCollection_HAsciiString, anAxis1);
+  addToModel(aPlane1);
+
+  // Creating a plane containing the second Axis2Placement3d.
+  Handle(StepGeom_Plane) aPlane2 = new StepGeom_Plane;
+  aPlane2->Init(new TCollection_HAsciiString, anAxis2);
+  addToModel(aPlane2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that nothing was removed.
+  EXPECT_TRUE(aRemovedEntities.IsEmpty());
+}
+
+// Check that equal Axis2Placement3ds are merged for StepShape_GeometricCurveSet.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepGeom_Plane)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating a plane containing the first Axis2Placement3d.
+  Handle(StepGeom_Plane) aPlane1 = new StepGeom_Plane;
+  aPlane1->Init(new TCollection_HAsciiString, anAxis1);
+  addToModel(aPlane1);
+
+  // Creating a plane containing the second Axis2Placement3d.
+  Handle(StepGeom_Plane) aPlane2 = new StepGeom_Plane;
+  aPlane2->Init(new TCollection_HAsciiString, anAxis2);
+  addToModel(aPlane2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepRepr_ItemDefinedTransformation.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepRepr_ItemDefinedTransformation)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis3 = addAxis2Placement3d(nullptr, gp_XYZ(1., 1., 1.));
+
+  // Creating ItemDefinedTransformation containing the first Axis2Placement3d.
+  Handle(StepRepr_ItemDefinedTransformation) aItem1 = new StepRepr_ItemDefinedTransformation;
+  aItem1->Init(new TCollection_HAsciiString, new TCollection_HAsciiString, anAxis1, anAxis3);
+  addToModel(aItem1);
+
+  // Creating ItemDefinedTransformation containing the second Axis2Placement3d.
+  Handle(StepRepr_ItemDefinedTransformation) aItem2 = new StepRepr_ItemDefinedTransformation;
+  aItem1->Init(new TCollection_HAsciiString, new TCollection_HAsciiString, anAxis2, anAxis3);
+  addToModel(aItem2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepGeom_CylindricalSurface.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepGeom_CylindricalSurface)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating a cylindrical surface containing the first Axis2Placement3d.
+  Handle(StepGeom_CylindricalSurface) aCylindricalSurface1 = new StepGeom_CylindricalSurface;
+  aCylindricalSurface1->Init(new TCollection_HAsciiString, anAxis1, 1.0);
+  addToModel(aCylindricalSurface1);
+
+  // Creating a cylindrical surface containing the second Axis2Placement3d.
+  Handle(StepGeom_CylindricalSurface) aCylindricalSurface2 = new StepGeom_CylindricalSurface;
+  aCylindricalSurface2->Init(new TCollection_HAsciiString, anAxis2, 1.0);
+  addToModel(aCylindricalSurface2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepShape_ShapeRepresentation.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepShape_ShapeRepresentation)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating a shape representation containing the first Axis2Placement3d.
+  Handle(StepRepr_HArray1OfRepresentationItem) aItems1 =
+    new StepRepr_HArray1OfRepresentationItem(1, 1);
+  aItems1->SetValue(1, anAxis1);
+  Handle(StepShape_ShapeRepresentation) aShapeRepresentation1 = new StepShape_ShapeRepresentation;
+  aShapeRepresentation1->Init(new TCollection_HAsciiString,
+                              aItems1,
+                              new StepRepr_RepresentationContext);
+  addToModel(aShapeRepresentation1);
+
+  // Creating a shape representation containing the second Axis2Placement3d.
+  Handle(StepRepr_HArray1OfRepresentationItem) aItems2 =
+    new StepRepr_HArray1OfRepresentationItem(1, 1);
+  aItems2->SetValue(1, anAxis2);
+  Handle(StepShape_ShapeRepresentation) aShapeRepresentation2 = new StepShape_ShapeRepresentation;
+  aShapeRepresentation2->Init(new TCollection_HAsciiString,
+                              aItems2,
+                              new StepRepr_RepresentationContext);
+  addToModel(aShapeRepresentation2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepRepr_ConstructiveGeometryRepresentation.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepRepr_ConstructiveGeometryRepresentation)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating a constructive geometry representation containing the first Axis2Placement3d.
+  Handle(StepRepr_HArray1OfRepresentationItem) aItems1 =
+    new StepRepr_HArray1OfRepresentationItem(1, 1);
+  aItems1->SetValue(1, anAxis1);
+  Handle(StepRepr_ConstructiveGeometryRepresentation) aConstructiveGeometryRepresentation1 =
+    new StepRepr_ConstructiveGeometryRepresentation;
+  aConstructiveGeometryRepresentation1->Init(new TCollection_HAsciiString,
+                                             aItems1,
+                                             new StepRepr_RepresentationContext);
+  addToModel(aConstructiveGeometryRepresentation1);
+
+  // Creating a constructive geometry representation containing the second Axis2Placement3d.
+  Handle(StepRepr_HArray1OfRepresentationItem) aItems2 =
+    new StepRepr_HArray1OfRepresentationItem(1, 1);
+  aItems2->SetValue(1, anAxis2);
+  Handle(StepRepr_ConstructiveGeometryRepresentation) aConstructiveGeometryRepresentation2 =
+    new StepRepr_ConstructiveGeometryRepresentation;
+  aConstructiveGeometryRepresentation2->Init(new TCollection_HAsciiString,
+                                             aItems2,
+                                             new StepRepr_RepresentationContext);
+  addToModel(aConstructiveGeometryRepresentation2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepGeom_Circle.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepGeom_Circle)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating a circle containing the first Axis2Placement3d.
+  StepGeom_Axis2Placement aSelector1;
+  aSelector1.SetValue(anAxis1);
+  Handle(StepGeom_Circle) aCircle1 = new StepGeom_Circle;
+  aCircle1->Init(new TCollection_HAsciiString, aSelector1, 1.0);
+  addToModel(aCircle1);
+
+  // Creating a circle containing the second Axis2Placement3d.
+  StepGeom_Axis2Placement aSelector2;
+  aSelector2.SetValue(anAxis2);
+  Handle(StepGeom_Circle) aCircle2 = new StepGeom_Circle;
+  aCircle2->Init(new TCollection_HAsciiString, aSelector2, 1.0);
+  addToModel(aCircle2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepVisual_PresentationLayerAssignment.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepVisual_PresentationLayerAssignment)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating a presentation layer assignment containing the first Axis2Placement3d.
+  Handle(StepVisual_HArray1OfLayeredItem) aAssignedItems1 =
+    new StepVisual_HArray1OfLayeredItem(1, 1);
+  StepVisual_LayeredItem aLayeredItem1;
+  aLayeredItem1.SetValue(anAxis1);
+  aAssignedItems1->SetValue(1, aLayeredItem1);
+  Handle(StepVisual_PresentationLayerAssignment) aPresentationLayerAssignment1 =
+    new StepVisual_PresentationLayerAssignment;
+  aPresentationLayerAssignment1->Init(new TCollection_HAsciiString,
+                                      new TCollection_HAsciiString,
+                                      aAssignedItems1);
+  addToModel(aPresentationLayerAssignment1);
+
+  // Creating a presentation layer assignment containing the second Axis2Placement3d.
+  Handle(StepVisual_HArray1OfLayeredItem) aAssignedItems2 =
+    new StepVisual_HArray1OfLayeredItem(1, 1);
+  StepVisual_LayeredItem aLayeredItem2;
+  aLayeredItem2.SetValue(anAxis2);
+  aAssignedItems2->SetValue(1, aLayeredItem2);
+  Handle(StepVisual_PresentationLayerAssignment) aPresentationLayerAssignment2 =
+    new StepVisual_PresentationLayerAssignment;
+  aPresentationLayerAssignment2->Init(new TCollection_HAsciiString,
+                                      new TCollection_HAsciiString,
+                                      aAssignedItems2);
+  addToModel(aPresentationLayerAssignment2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepVisual_StyledItem.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepVisual_StyledItem)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating a styled item containing the first Axis2Placement3d.
+  Handle(StepVisual_StyledItem) aStiledItem1 = new StepVisual_StyledItem;
+  aStiledItem1->Init(new TCollection_HAsciiString,
+                     new StepVisual_HArray1OfPresentationStyleAssignment(1, 1),
+                     anAxis1);
+  addToModel(aStiledItem1);
+
+  // Creating a styled item containing the second Axis2Placement3d.
+  Handle(StepVisual_StyledItem) aStiledItem2 = new StepVisual_StyledItem;
+  aStiledItem2->Init(new TCollection_HAsciiString,
+                     new StepVisual_HArray1OfPresentationStyleAssignment(1, 1),
+                     anAxis2);
+  addToModel(aStiledItem2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepGeom_Ellipse.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepGeom_Ellipse)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating an ellipse containing the first Axis2Placement3d.
+  StepGeom_Axis2Placement aSelector1;
+  aSelector1.SetValue(anAxis1);
+  Handle(StepGeom_Ellipse) aEllipse1 = new StepGeom_Ellipse;
+  aEllipse1->Init(new TCollection_HAsciiString, aSelector1, 1.0, 2.0);
+  addToModel(aEllipse1);
+
+  // Creating an ellipse containing the second Axis2Placement3d.
+  StepGeom_Axis2Placement aSelector2;
+  aSelector2.SetValue(anAxis2);
+  Handle(StepGeom_Ellipse) aEllipse2 = new StepGeom_Ellipse;
+  aEllipse2->Init(new TCollection_HAsciiString, aSelector2, 1.0, 2.0);
+  addToModel(aEllipse2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepGeom_ConicalSurface.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepGeom_ConicalSurface)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating a conical surface containing the first Axis2Placement3d.
+  Handle(StepGeom_ConicalSurface) aConicalSurface1 = new StepGeom_ConicalSurface;
+  aConicalSurface1->Init(new TCollection_HAsciiString, anAxis1, 1.0, 1.0);
+  addToModel(aConicalSurface1);
+
+  // Creating a conical surface containing the second Axis2Placement3d.
+  Handle(StepGeom_ConicalSurface) aConicalSurface2 = new StepGeom_ConicalSurface;
+  aConicalSurface2->Init(new TCollection_HAsciiString, anAxis2, 1.0, 1.0);
+  addToModel(aConicalSurface2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepGeom_ToroidalSurface.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepGeom_ToroidalSurface)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating a toroidal surface containing the first Axis2Placement3d.
+  Handle(StepGeom_ToroidalSurface) aToroidalSurface1 = new StepGeom_ToroidalSurface;
+  aToroidalSurface1->Init(new TCollection_HAsciiString, anAxis1, 1.0, 1.0);
+  addToModel(aToroidalSurface1);
+
+  // Creating a toroidal surface containing the second Axis2Placement3d.
+  Handle(StepGeom_ToroidalSurface) aToroidalSurface2 = new StepGeom_ToroidalSurface;
+  aToroidalSurface2->Init(new TCollection_HAsciiString, anAxis2, 1.0, 1.0);
+  addToModel(aToroidalSurface2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepShape_AdvancedBrepShapeRepresentation.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepShape_AdvancedBrepShapeRepresentation)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating a shape representation containing the first Axis2Placement3d.
+  Handle(StepRepr_HArray1OfRepresentationItem) aItems1 =
+    new StepRepr_HArray1OfRepresentationItem(1, 1);
+  aItems1->SetValue(1, anAxis1);
+  Handle(StepShape_AdvancedBrepShapeRepresentation) aShapeRepresentation1 =
+    new StepShape_AdvancedBrepShapeRepresentation;
+  aShapeRepresentation1->Init(new TCollection_HAsciiString,
+                              aItems1,
+                              new StepRepr_RepresentationContext);
+  addToModel(aShapeRepresentation1);
+
+  // Creating a shape representation containing the second Axis2Placement3d.
+  Handle(StepRepr_HArray1OfRepresentationItem) aItems2 =
+    new StepRepr_HArray1OfRepresentationItem(1, 1);
+  aItems2->SetValue(1, anAxis2);
+  Handle(StepShape_AdvancedBrepShapeRepresentation) aShapeRepresentation2 =
+    new StepShape_AdvancedBrepShapeRepresentation;
+  aShapeRepresentation2->Init(new TCollection_HAsciiString,
+                              aItems2,
+                              new StepRepr_RepresentationContext);
+  addToModel(aShapeRepresentation2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
+
+// Check that equal Axis2Placement3ds are merged for StepGeom_SphericalSurface.
+TEST_F(StepTidy_Axis2Placement3dReducerTest, StepGeom_SphericalSurface)
+{
+  // Creating Axis2Placement3ds.
+  Handle(StepGeom_Axis2Placement3d) anAxis1 = addAxis2Placement3d();
+  Handle(StepGeom_Axis2Placement3d) anAxis2 = addAxis2Placement3d();
+
+  // Creating a spherical surface containing the first Axis2Placement3d.
+  Handle(StepGeom_SphericalSurface) aSphericalSurface1 = new StepGeom_SphericalSurface;
+  aSphericalSurface1->Init(new TCollection_HAsciiString, anAxis1, 1.0);
+  addToModel(aSphericalSurface1);
+
+  // Creating a spherical surface containing the second Axis2Placement3d.
+  Handle(StepGeom_SphericalSurface) aSphericalSurface2 = new StepGeom_SphericalSurface;
+  aSphericalSurface2->Init(new TCollection_HAsciiString, anAxis2, 1.0);
+  addToModel(aSphericalSurface2);
+
+  // Performing removal of duplicate Axis2Placement3ds.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateAxis2Placement3ds();
+
+  // Check that one Axis2Placement3d was removed.
+  EXPECT_EQ(aRemovedEntities.Extent(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(anAxis1) || aRemovedEntities.Contains(anAxis2));
+}
diff --git a/src/DataExchange/TKDESTEP/GTests/StepTidy_BaseTestFixture.pxx b/src/DataExchange/TKDESTEP/GTests/StepTidy_BaseTestFixture.pxx
new file mode 100644 (file)
index 0000000..23df1c6
--- /dev/null
@@ -0,0 +1,194 @@
+// 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 _StepTidy_BaseTestFixture_HeaderFile
+#define _StepTidy_BaseTestFixture_HeaderFile
+
+#include <STEPControl_Controller.hxx>
+#include <StepGeom_Axis2Placement3d.hxx>
+#include <StepGeom_CartesianPoint.hxx>
+#include <StepGeom_Circle.hxx>
+#include <StepGeom_Direction.hxx>
+#include <StepGeom_Line.hxx>
+#include <StepGeom_Plane.hxx>
+#include <StepGeom_Vector.hxx>
+#include <XSControl_WorkSession.hxx>
+
+#include <gtest/gtest.h>
+
+class StepTidy_BaseTestFixture : public testing::Test
+{
+protected:
+  // Initialize the work session and model.
+  StepTidy_BaseTestFixture()
+      : myWS()
+  {
+    STEPControl_Controller::Init();
+    myWS = new XSControl_WorkSession;
+    myWS->SelectNorm("STEP");
+    myWS->SetModel(myWS->NormAdaptor()->NewModel());
+  }
+
+  // Add a Cartesian point to the model.
+  // @param theName the name of the Cartesian point.
+  // @param thePoint the coordinates of the Cartesian point.
+  // @return the added Cartesian point.
+  Handle(StepGeom_CartesianPoint) addCartesianPoint(const char*   theName  = nullptr,
+                                                    const gp_XYZ& thePoint = gp_XYZ(0.,
+                                                                                    0.,
+                                                                                    0.)) const
+  {
+    const Handle(StepGeom_CartesianPoint)  aCartesianPoint = new StepGeom_CartesianPoint;
+    const Handle(TCollection_HAsciiString) aName =
+      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
+    aCartesianPoint->Init3D(aName, thePoint.X(), thePoint.Y(), thePoint.Z());
+    myWS->Model()->AddWithRefs(aCartesianPoint);
+    return aCartesianPoint;
+  }
+
+  // Add a direction to the model.
+  // @param theName the name of the direction.
+  // @param theDirection the direction ratios.
+  // @return the added direction.
+  Handle(StepGeom_Direction) addDirection(const char*   theName      = nullptr,
+                                          const gp_XYZ& theDirection = gp_XYZ(0., 0., 1.)) const
+  {
+    const Handle(StepGeom_Direction)       aDirection = new StepGeom_Direction;
+    const Handle(TCollection_HAsciiString) aName =
+      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
+    Handle(TColStd_HArray1OfReal) aDirectionRatios = new TColStd_HArray1OfReal(1, 3);
+    aDirectionRatios->SetValue(1, theDirection.X());
+    aDirectionRatios->SetValue(2, theDirection.Y());
+    aDirectionRatios->SetValue(3, theDirection.Z());
+    aDirection->Init(aName, aDirectionRatios);
+    myWS->Model()->AddWithRefs(aDirection);
+    return aDirection;
+  }
+
+  // Add a vector to the model.
+  // @param theName the name of the vector.
+  // @param theOrientation the orientation of the vector.
+  // @param aMagnitude the magnitude of the vector.
+  // @return the added vector.
+  Handle(StepGeom_Vector) addVector(const char*   theName        = nullptr,
+                                    const gp_XYZ& theOrientation = gp_XYZ(0., 0., 1.),
+                                    const double  aMagnitude     = 1.) const
+  {
+    const Handle(StepGeom_Vector)          aVector = new StepGeom_Vector;
+    const Handle(TCollection_HAsciiString) aName =
+      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
+    aVector->Init(aName, addDirection(nullptr, theOrientation), aMagnitude);
+    myWS->Model()->AddWithRefs(aVector);
+    return aVector;
+  }
+
+  // Add an Axis2Placement3d to the model.
+  // @param theName the name of the Axis2Placement3d.
+  // @param theLocation the location of the Axis2Placement3d.
+  // @param theAxis the axis of the Axis2Placement3d.
+  // @param theRefDirection the reference direction of the Axis2Placement3d.
+  // @return the added Axis2Placement3d.
+  Handle(StepGeom_Axis2Placement3d) addAxis2Placement3d(
+    const char*   theName         = nullptr,
+    const gp_XYZ& theLocation     = gp_XYZ(0., 0., 0.),
+    const gp_XYZ& theAxis         = gp_XYZ(0., 0., 1.),
+    const gp_XYZ& theRefDirection = gp_XYZ(0., 1., 0.)) const
+  {
+    const Handle(StepGeom_Axis2Placement3d) aAxis2Placement3d = new StepGeom_Axis2Placement3d;
+    const Handle(TCollection_HAsciiString)  aName =
+      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
+    aAxis2Placement3d->Init(aName,
+                            addCartesianPoint(nullptr, theLocation),
+                            true,
+                            addDirection(nullptr, theAxis),
+                            true,
+                            addDirection(nullptr, theRefDirection));
+    myWS->Model()->AddWithRefs(aAxis2Placement3d);
+    return aAxis2Placement3d;
+  }
+
+  // Add a line to the model.
+  // @param theName the name of the line.
+  // @param theLocation the location of the line.
+  // @param theOrientation the orientation of the line vector.
+  // @param theMagnitude the magnitude of the line vector.
+  // @return the added line.
+  Handle(StepGeom_Line) addLine(const char*   theName        = nullptr,
+                                const gp_XYZ& theLocation    = gp_XYZ(0., 0., 0.),
+                                const gp_XYZ& theOrientation = gp_XYZ(0., 0., 1.),
+                                const double  aMagnitude     = 1.) const
+  {
+    const Handle(StepGeom_Line)            aLine = new StepGeom_Line;
+    const Handle(TCollection_HAsciiString) aName =
+      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
+    aLine->Init(aName,
+                addCartesianPoint(nullptr, theLocation),
+                addVector(nullptr, theOrientation, aMagnitude));
+    myWS->Model()->AddWithRefs(aLine);
+    return aLine;
+  }
+
+  // Add a circle to the model.
+  // @param theName the name of the circle.
+  // @param theLocation the location of the circle.
+  // @param theAxis the axis of the circle.
+  // @param theRefDirection the reference direction of the circle.
+  // @param theRadius the radius of the circle.
+  // @return the added circle.
+  Handle(StepGeom_Circle) addCircle(const char*   theName         = nullptr,
+                                    const gp_XYZ& theLocation     = gp_XYZ(0., 0., 0.),
+                                    const gp_XYZ& theAxis         = gp_XYZ(0., 0., 1.),
+                                    const gp_XYZ& theRefDirection = gp_XYZ(0., 1., 0.),
+                                    const double  theRadius       = 1.) const
+  {
+    const Handle(StepGeom_Circle)          aCircle = new StepGeom_Circle;
+    const Handle(TCollection_HAsciiString) aName =
+      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
+    StepGeom_Axis2Placement aSelector;
+    aSelector.SetValue(addAxis2Placement3d(nullptr, theLocation, theAxis, theRefDirection));
+    aCircle->Init(aName, aSelector, theRadius);
+    myWS->Model()->AddWithRefs(aCircle);
+    return aCircle;
+  }
+
+  // Add a plane to the model.
+  // @param theName the name of the plane.
+  // @param theLocation the location of the plane.
+  // @param theAxis the axis of the plane.
+  // @param theRefDirection the reference direction of the plane.
+  // @return the added plane.
+  Handle(StepGeom_Plane) addPlane(const char*   theName         = nullptr,
+                                  const gp_XYZ& theLocation     = gp_XYZ(0., 0., 0.),
+                                  const gp_XYZ& theAxis         = gp_XYZ(0., 0., 1.),
+                                  const gp_XYZ& theRefDirection = gp_XYZ(0., 1., 0.)) const
+  {
+    const Handle(StepGeom_Plane)           aPlane = new StepGeom_Plane;
+    const Handle(TCollection_HAsciiString) aName =
+      theName ? new TCollection_HAsciiString(theName) : new TCollection_HAsciiString();
+    aPlane->Init(aName, addAxis2Placement3d(nullptr, theLocation, theAxis, theRefDirection));
+    myWS->Model()->AddWithRefs(aPlane);
+    return aPlane;
+  }
+
+  // Add an entity to the model.
+  // @param theEntity the entity to add.
+  void addToModel(const Handle(Standard_Transient)& theEntity) const
+  {
+    myWS->Model()->AddWithRefs(theEntity);
+  }
+
+protected:
+  Handle(XSControl_WorkSession) myWS;
+};
+
+#endif // _StepTidy_BaseTestFixture_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/GTests/StepTidy_CartesianPointReducer_Test.cxx b/src/DataExchange/TKDESTEP/GTests/StepTidy_CartesianPointReducer_Test.cxx
new file mode 100644 (file)
index 0000000..658d923
--- /dev/null
@@ -0,0 +1,585 @@
+// 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.
+
+#include "StepTidy_BaseTestFixture.pxx"
+
+#include <StepTidy_CartesianPointReducer.pxx>
+
+#include <StepGeom_Axis1Placement.hxx>
+#include <StepGeom_Axis2Placement3d.hxx>
+#include <StepGeom_BSplineCurveWithKnots.hxx>
+#include <StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve.hxx>
+#include <StepGeom_BSplineSurfaceWithKnots.hxx>
+#include <StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface.hxx>
+#include <StepGeom_Line.hxx>
+#include <StepGeom_RationalBSplineSurface.hxx>
+#include <StepRepr_Representation.hxx>
+#include <StepRepr_RepresentationContext.hxx>
+#include <StepShape_GeometricCurveSet.hxx>
+#include <StepShape_VertexPoint.hxx>
+#include <StepVisual_PresentationLayerAssignment.hxx>
+#include <StepVisual_StyledItem.hxx>
+
+class StepTidy_CartesianPointReducerTest : public StepTidy_BaseTestFixture
+{
+protected:
+  // Perform removal of duplicate Cartesian points.
+  TColStd_MapOfTransient replaceDuplicateCartesianPoints()
+  {
+    StepTidy_CartesianPointReducer aReducer(myWS);
+    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
+    {
+      aReducer.ProcessEntity(myWS->Model()->Value(anIndex));
+    }
+
+    TColStd_MapOfTransient aRemovedEntities;
+    aReducer.Perform(aRemovedEntities);
+    return aRemovedEntities;
+  }
+};
+
+// Check that points with the same coordinates and different names are not merged.
+TEST_F(StepTidy_CartesianPointReducerTest, DifferentNames)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint("FirstPt");
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint("SecondPt");
+
+  // Creating direction.
+  Handle(TColStd_HArray1OfReal) aDirCoords = new TColStd_HArray1OfReal(1, 3);
+  aDirCoords->SetValue(1, 0.);
+  aDirCoords->SetValue(2, 0.);
+  aDirCoords->SetValue(3, 1.);
+  Handle(StepGeom_Direction) aDir = new StepGeom_Direction;
+  aDir->Init(new TCollection_HAsciiString, aDirCoords);
+  addToModel(aDir);
+
+  // Creating axis containing the first Cartesian point.
+  Handle(StepGeom_Axis2Placement3d) aFirstAxis = new StepGeom_Axis2Placement3d;
+  aFirstAxis
+    ->Init(new TCollection_HAsciiString, aPt1, Standard_True, aDir, Standard_False, nullptr);
+  addToModel(aFirstAxis);
+
+  // Creating axis containing the second Cartesian point.
+  Handle(StepGeom_Axis2Placement3d) aSecondAxis = new StepGeom_Axis2Placement3d;
+  aSecondAxis
+    ->Init(new TCollection_HAsciiString, aPt2, Standard_True, aDir, Standard_False, nullptr);
+  addToModel(aSecondAxis);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that nothing was removed.
+  EXPECT_TRUE(aRemovedEntities.IsEmpty());
+}
+
+// Check that points with the same coordinates and same names are
+// merged for StepGeom_Axis2Placement3d.
+TEST_F(StepTidy_CartesianPointReducerTest, StepGeom_Axis2Placement3d)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating direction.
+  Handle(TColStd_HArray1OfReal) aDirCoords = new TColStd_HArray1OfReal(1, 3);
+  aDirCoords->SetValue(1, 0.);
+  aDirCoords->SetValue(2, 0.);
+  aDirCoords->SetValue(3, 1.);
+  Handle(StepGeom_Direction) aDir = new StepGeom_Direction;
+  aDir->Init(new TCollection_HAsciiString, aDirCoords);
+  addToModel(aDir);
+
+  // Creating axis containing the first Cartesian point.
+  Handle(StepGeom_Axis2Placement3d) aFirstAxis = new StepGeom_Axis2Placement3d;
+  aFirstAxis
+    ->Init(new TCollection_HAsciiString, aPt1, Standard_True, aDir, Standard_False, nullptr);
+  addToModel(aFirstAxis);
+
+  // Creating axis containing the second Cartesian point.
+  Handle(StepGeom_Axis2Placement3d) aSecondAxis = new StepGeom_Axis2Placement3d;
+  aSecondAxis
+    ->Init(new TCollection_HAsciiString, aPt2, Standard_True, aDir, Standard_False, nullptr);
+  addToModel(aSecondAxis);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
+
+// Check that points with the same coordinates and same names are merged
+// for StepShape_VertexPoint.
+TEST_F(StepTidy_CartesianPointReducerTest, StepShape_VertexPoint)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating vertex containing the first Cartesian point.
+  Handle(StepShape_VertexPoint) aFirstVertex = new StepShape_VertexPoint;
+  aFirstVertex->Init(new TCollection_HAsciiString, aPt1);
+  addToModel(aFirstVertex);
+
+  // Creating vertex containing the second Cartesian point.
+  Handle(StepShape_VertexPoint) aSecondVertex = new StepShape_VertexPoint;
+  aSecondVertex->Init(new TCollection_HAsciiString, aPt2);
+  addToModel(aSecondVertex);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
+
+// Check that points with the same coordinates and same names are merged
+// for StepShape_GeometricCurveSet.
+TEST_F(StepTidy_CartesianPointReducerTest, StepShape_GeometricCurveSet)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating curve set containing the first Cartesian point.
+  Handle(StepShape_HArray1OfGeometricSetSelect) aFirstElements =
+    new StepShape_HArray1OfGeometricSetSelect(1, 1);
+  StepShape_GeometricSetSelect aFirstSelect;
+  aFirstSelect.SetValue(aPt1);
+  aFirstElements->SetValue(1, aFirstSelect);
+  addToModel(aFirstElements);
+  Handle(StepShape_GeometricCurveSet) aFirstCurveSet = new StepShape_GeometricCurveSet;
+  aFirstCurveSet->Init(new TCollection_HAsciiString, aFirstElements);
+  addToModel(aFirstCurveSet);
+
+  // Creating curve set containing the second Cartesian point.
+  Handle(StepShape_HArray1OfGeometricSetSelect) aSecondElements =
+    new StepShape_HArray1OfGeometricSetSelect(1, 1);
+  StepShape_GeometricSetSelect aSecondSelect;
+  aSecondSelect.SetValue(aPt2);
+  aSecondElements->SetValue(1, aSecondSelect);
+  addToModel(aSecondElements);
+  Handle(StepShape_GeometricCurveSet) aSecondCurveSet = new StepShape_GeometricCurveSet;
+  aSecondCurveSet->Init(new TCollection_HAsciiString, aSecondElements);
+  addToModel(aSecondCurveSet);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
+
+// Check that points with the same coordinates and same names are merged
+// for StepVisual_PresentationLayerAssignment.
+TEST_F(StepTidy_CartesianPointReducerTest, StepVisual_PresentationLayerAssignment)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating presentation layer assignment containing the first Cartesian point.
+  Handle(StepVisual_HArray1OfLayeredItem) aFirstAssignedItems =
+    new StepVisual_HArray1OfLayeredItem(1, 1);
+  StepVisual_LayeredItem aFirstLayeredItem;
+  aFirstLayeredItem.SetValue(aPt1);
+  aFirstAssignedItems->SetValue(1, aFirstLayeredItem);
+  addToModel(aFirstAssignedItems);
+  Handle(StepVisual_PresentationLayerAssignment) aFirstAssignment =
+    new StepVisual_PresentationLayerAssignment;
+  aFirstAssignment->Init(new TCollection_HAsciiString,
+                         new TCollection_HAsciiString,
+                         aFirstAssignedItems);
+  addToModel(aFirstAssignment);
+
+  // Creating presentation layer assignment containing the second Cartesian point.
+  Handle(StepVisual_HArray1OfLayeredItem) aSecondAssignedItems =
+    new StepVisual_HArray1OfLayeredItem(1, 1);
+  StepVisual_LayeredItem aSecondLayeredItem;
+  aSecondLayeredItem.SetValue(aPt2);
+  aSecondAssignedItems->SetValue(1, aSecondLayeredItem);
+  addToModel(aSecondAssignedItems);
+  Handle(StepVisual_PresentationLayerAssignment) aSecondAssignment =
+    new StepVisual_PresentationLayerAssignment;
+  aSecondAssignment->Init(new TCollection_HAsciiString,
+                          new TCollection_HAsciiString,
+                          aSecondAssignedItems);
+  addToModel(aSecondAssignment);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
+
+// Check that points with the same coordinates and same names are merged
+// for StepVisual_StyledItem.
+TEST_F(StepTidy_CartesianPointReducerTest, StepVisual_StyledItem)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating styled item containing the first Cartesian point.
+  Handle(StepVisual_HArray1OfPresentationStyleAssignment) aFirstAssignedItems =
+    new StepVisual_HArray1OfPresentationStyleAssignment(1, 1);
+  Handle(StepVisual_StyledItem) aFirstStyledItem = new StepVisual_StyledItem;
+  aFirstStyledItem->Init(new TCollection_HAsciiString, aFirstAssignedItems, aPt1);
+  addToModel(aFirstStyledItem);
+
+  // Creating styled item containing the second Cartesian point.
+  Handle(StepVisual_HArray1OfPresentationStyleAssignment) aSecondAssignedItems =
+    new StepVisual_HArray1OfPresentationStyleAssignment(1, 1);
+  Handle(StepVisual_StyledItem) aSecondStyledItem = new StepVisual_StyledItem;
+  aSecondStyledItem->Init(new TCollection_HAsciiString, aSecondAssignedItems, aPt2);
+  addToModel(aSecondStyledItem);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
+
+// Check that points with the same coordinates and same names are merged
+// for StepGeom_BSplineCurveWithKnots.
+TEST_F(StepTidy_CartesianPointReducerTest, StepGeom_BSplineCurveWithKnots)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating curve containing the first Cartesian point.
+  Handle(StepGeom_HArray1OfCartesianPoint) aFirstControlPoints =
+    new StepGeom_HArray1OfCartesianPoint(1, 1);
+  aFirstControlPoints->SetValue(1, aPt1);
+  Handle(StepGeom_BSplineCurveWithKnots) aFirstCurve = new StepGeom_BSplineCurveWithKnots;
+  aFirstCurve->Init(new TCollection_HAsciiString,
+                    1,
+                    aFirstControlPoints,
+                    StepGeom_bscfUnspecified,
+                    StepData_LUnknown,
+                    StepData_LUnknown,
+                    new TColStd_HArray1OfInteger,
+                    new TColStd_HArray1OfReal,
+                    StepGeom_ktUnspecified);
+  addToModel(aFirstCurve);
+
+  // Creating curve containing the second Cartesian point.
+  Handle(StepGeom_HArray1OfCartesianPoint) aSecondControlPoints =
+    new StepGeom_HArray1OfCartesianPoint(1, 1);
+  aSecondControlPoints->SetValue(1, aPt2);
+  Handle(StepGeom_BSplineCurveWithKnots) aSecondCurve = new StepGeom_BSplineCurveWithKnots;
+  aSecondCurve->Init(new TCollection_HAsciiString,
+                     1,
+                     aSecondControlPoints,
+                     StepGeom_bscfUnspecified,
+                     StepData_LUnknown,
+                     StepData_LUnknown,
+                     new TColStd_HArray1OfInteger,
+                     new TColStd_HArray1OfReal,
+                     StepGeom_ktUnspecified);
+  addToModel(aSecondCurve);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
+
+// Check that points with the same coordinates and same names are merged
+// for StepGeom_Line.
+TEST_F(StepTidy_CartesianPointReducerTest, StepGeom_Line)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating line containing the first Cartesian point.
+  Handle(StepGeom_Line) aFirstLine = new StepGeom_Line;
+  aFirstLine->Init(new TCollection_HAsciiString, aPt1, new StepGeom_Vector);
+  addToModel(aFirstLine);
+
+  // Creating line containing the second Cartesian point.
+  Handle(StepGeom_Line) aSecondLine = new StepGeom_Line;
+  aSecondLine->Init(new TCollection_HAsciiString, aPt2, new StepGeom_Vector);
+  addToModel(aSecondLine);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
+
+// Check that points with the same coordinates and same names are merged
+// for StepGeom_BSplineSurfaceWithKnots.
+TEST_F(StepTidy_CartesianPointReducerTest, StepGeom_BSplineSurfaceWithKnots)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating surface containing the first Cartesian point.
+  Handle(StepGeom_HArray2OfCartesianPoint) aFirstControlPoints =
+    new StepGeom_HArray2OfCartesianPoint(1, 1, 1, 1);
+  aFirstControlPoints->SetValue(1, 1, aPt1);
+  Handle(StepGeom_BSplineSurfaceWithKnots) aFirstSurface = new StepGeom_BSplineSurfaceWithKnots;
+  aFirstSurface->Init(new TCollection_HAsciiString,
+                      1,
+                      1,
+                      aFirstControlPoints,
+                      StepGeom_bssfUnspecified,
+                      StepData_LUnknown,
+                      StepData_LUnknown,
+                      StepData_LUnknown,
+                      new TColStd_HArray1OfInteger,
+                      new TColStd_HArray1OfInteger,
+                      new TColStd_HArray1OfReal,
+                      new TColStd_HArray1OfReal,
+                      StepGeom_ktUnspecified);
+  addToModel(aFirstSurface);
+
+  // Creating surface containing the second Cartesian point.
+  Handle(StepGeom_HArray2OfCartesianPoint) aSecondControlPoints =
+    new StepGeom_HArray2OfCartesianPoint(1, 1, 1, 1);
+  aSecondControlPoints->SetValue(1, 1, aPt2);
+  Handle(StepGeom_BSplineSurfaceWithKnots) aSecondSurface = new StepGeom_BSplineSurfaceWithKnots;
+  aSecondSurface->Init(new TCollection_HAsciiString,
+                       1,
+                       1,
+                       aSecondControlPoints,
+                       StepGeom_bssfUnspecified,
+                       StepData_LUnknown,
+                       StepData_LUnknown,
+                       StepData_LUnknown,
+                       new TColStd_HArray1OfInteger,
+                       new TColStd_HArray1OfInteger,
+                       new TColStd_HArray1OfReal,
+                       new TColStd_HArray1OfReal,
+                       StepGeom_ktUnspecified);
+  addToModel(aSecondSurface);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
+
+// Check that points with the same coordinates and same names are merged
+// for StepGeom_Axis1Placement.
+TEST_F(StepTidy_CartesianPointReducerTest, StepGeom_Axis1Placement)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating axis containing the first Cartesian point.
+  Handle(StepGeom_Axis1Placement) aFirstAxis = new StepGeom_Axis1Placement;
+  aFirstAxis->Init(new TCollection_HAsciiString, aPt1, false, new StepGeom_Direction);
+  addToModel(aFirstAxis);
+
+  // Creating axis containing the second Cartesian point.
+  Handle(StepGeom_Axis1Placement) aSecondAxis = new StepGeom_Axis1Placement;
+  aSecondAxis->Init(new TCollection_HAsciiString, aPt2, false, new StepGeom_Direction);
+  addToModel(aSecondAxis);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
+
+// Check that points with the same coordinates and same names are merged
+// for StepRepr_Representation.
+TEST_F(StepTidy_CartesianPointReducerTest, StepRepr_Representation)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating representation containing the first Cartesian point.
+  Handle(StepRepr_HArray1OfRepresentationItem) aFirstItems =
+    new StepRepr_HArray1OfRepresentationItem(1, 1);
+  aFirstItems->SetValue(1, aPt1);
+  Handle(StepRepr_Representation) aFirstRepresentation = new StepRepr_Representation;
+  aFirstRepresentation->Init(new TCollection_HAsciiString,
+                             aFirstItems,
+                             new StepRepr_RepresentationContext);
+  addToModel(aFirstRepresentation);
+
+  // Creating representation containing the second Cartesian point.
+  Handle(StepRepr_HArray1OfRepresentationItem) aSecondItems =
+    new StepRepr_HArray1OfRepresentationItem(1, 1);
+  aSecondItems->SetValue(1, aPt2);
+  Handle(StepRepr_Representation) aSecondRepresentation = new StepRepr_Representation;
+  aSecondRepresentation->Init(new TCollection_HAsciiString,
+                              aSecondItems,
+                              new StepRepr_RepresentationContext);
+  addToModel(aSecondRepresentation);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
+
+// Check that points with the same coordinates and same names are merged
+// for StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve.
+TEST_F(StepTidy_CartesianPointReducerTest, StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating curve containing the first Cartesian point.
+  Handle(StepGeom_HArray1OfCartesianPoint) aFirstControlPoints =
+    new StepGeom_HArray1OfCartesianPoint(1, 1);
+  aFirstControlPoints->SetValue(1, aPt1);
+  Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve) aFirstCurve =
+    new StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve;
+  aFirstCurve->Init(new TCollection_HAsciiString,
+                    1,
+                    aFirstControlPoints,
+                    StepGeom_bscfUnspecified,
+                    StepData_LUnknown,
+                    StepData_LUnknown,
+                    new TColStd_HArray1OfInteger,
+                    new TColStd_HArray1OfReal,
+                    StepGeom_ktUnspecified,
+                    new TColStd_HArray1OfReal);
+  addToModel(aFirstCurve);
+
+  // Creating curve containing the second Cartesian point.
+  Handle(StepGeom_HArray1OfCartesianPoint) aSecondControlPoints =
+    new StepGeom_HArray1OfCartesianPoint(1, 1);
+  aSecondControlPoints->SetValue(1, aPt2);
+  Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve) aSecondCurve =
+    new StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve;
+  aSecondCurve->Init(new TCollection_HAsciiString,
+                     1,
+                     aSecondControlPoints,
+                     StepGeom_bscfUnspecified,
+                     StepData_LUnknown,
+                     StepData_LUnknown,
+                     new TColStd_HArray1OfInteger,
+                     new TColStd_HArray1OfReal,
+                     StepGeom_ktUnspecified,
+                     new TColStd_HArray1OfReal);
+  addToModel(aSecondCurve);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
+
+// Check that points with the same coordinates and same names are merged
+// for StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface.
+TEST_F(StepTidy_CartesianPointReducerTest,
+       StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface)
+{
+  // Creating Cartesian points.
+  Handle(StepGeom_CartesianPoint) aPt1 = addCartesianPoint();
+  Handle(StepGeom_CartesianPoint) aPt2 = addCartesianPoint();
+
+  // Creating surface containing the first Cartesian point.
+  Handle(StepGeom_HArray2OfCartesianPoint) aFirstControlPoints =
+    new StepGeom_HArray2OfCartesianPoint(1, 1, 1, 1);
+  aFirstControlPoints->SetValue(1, 1, aPt1);
+  Handle(StepGeom_BSplineSurfaceWithKnots) aFirstBSSWN = new StepGeom_BSplineSurfaceWithKnots;
+  aFirstBSSWN->Init(new TCollection_HAsciiString,
+                    1,
+                    1,
+                    aFirstControlPoints,
+                    StepGeom_bssfUnspecified,
+                    StepData_LUnknown,
+                    StepData_LUnknown,
+                    StepData_LUnknown,
+                    new TColStd_HArray1OfInteger,
+                    new TColStd_HArray1OfInteger,
+                    new TColStd_HArray1OfReal,
+                    new TColStd_HArray1OfReal,
+                    StepGeom_ktUnspecified);
+  addToModel(aFirstBSSWN);
+  Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface) aFirstSurface =
+    new StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface;
+  aFirstSurface->Init(new TCollection_HAsciiString,
+                      1,
+                      1,
+                      aFirstControlPoints,
+                      StepGeom_bssfUnspecified,
+                      StepData_LUnknown,
+                      StepData_LUnknown,
+                      StepData_LUnknown,
+                      aFirstBSSWN,
+                      new StepGeom_RationalBSplineSurface);
+  addToModel(aFirstSurface);
+
+  // Creating surface containing the second Cartesian point.
+  Handle(StepGeom_HArray2OfCartesianPoint) aSecondControlPoints =
+    new StepGeom_HArray2OfCartesianPoint(1, 1, 1, 1);
+  aSecondControlPoints->SetValue(1, 1, aPt2);
+  Handle(StepGeom_BSplineSurfaceWithKnots) aSecondBSSWN = new StepGeom_BSplineSurfaceWithKnots;
+  aSecondBSSWN->Init(new TCollection_HAsciiString,
+                     1,
+                     1,
+                     aSecondControlPoints,
+                     StepGeom_bssfUnspecified,
+                     StepData_LUnknown,
+                     StepData_LUnknown,
+                     StepData_LUnknown,
+                     new TColStd_HArray1OfInteger,
+                     new TColStd_HArray1OfInteger,
+                     new TColStd_HArray1OfReal,
+                     new TColStd_HArray1OfReal,
+                     StepGeom_ktUnspecified);
+  addToModel(aSecondBSSWN);
+  Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface) aSecondSurface =
+    new StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface;
+  aSecondSurface->Init(new TCollection_HAsciiString,
+                       1,
+                       1,
+                       aSecondControlPoints,
+                       StepGeom_bssfUnspecified,
+                       StepData_LUnknown,
+                       StepData_LUnknown,
+                       StepData_LUnknown,
+                       new StepGeom_BSplineSurfaceWithKnots,
+                       new StepGeom_RationalBSplineSurface);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCartesianPoints();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPt1) || aRemovedEntities.Contains(aPt2));
+}
diff --git a/src/DataExchange/TKDESTEP/GTests/StepTidy_CircleReducer_Test.cxx b/src/DataExchange/TKDESTEP/GTests/StepTidy_CircleReducer_Test.cxx
new file mode 100644 (file)
index 0000000..f2541a7
--- /dev/null
@@ -0,0 +1,165 @@
+// 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.
+
+#include "StepTidy_BaseTestFixture.pxx"
+
+#include <StepTidy_CircleReducer.pxx>
+
+#include <StepShape_EdgeCurve.hxx>
+#include <StepGeom_SurfaceCurve.hxx>
+#include <StepGeom_SeamCurve.hxx>
+
+class StepTidy_CircleReducerTest : public StepTidy_BaseTestFixture
+{
+protected:
+  //! Perform removal of duplicate entities.
+  TColStd_MapOfTransient replaceDuplicateCircles()
+  {
+    StepTidy_CircleReducer aReducer(myWS);
+    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
+    {
+      aReducer.ProcessEntity(myWS->Model()->Value(anIndex));
+    }
+
+    TColStd_MapOfTransient aRemovedEntities;
+    aReducer.Perform(aRemovedEntities);
+    return aRemovedEntities;
+  }
+};
+
+// Check that Circles with the same coordinates and different names are not merged.
+TEST_F(StepTidy_CircleReducerTest, DifferentNames)
+{
+  // Creating Circles.
+  Handle(StepGeom_Circle) aCircle1 = addCircle("Circle1");
+  Handle(StepGeom_Circle) aCircle2 = addCircle("Circle2");
+
+  // Creating EdgeCurve containing the first Circle.
+  Handle(StepShape_EdgeCurve) aFirstEdgeCurve = new StepShape_EdgeCurve;
+  aFirstEdgeCurve->Init(new TCollection_HAsciiString,
+                        new StepShape_Vertex,
+                        new StepShape_Vertex,
+                        aCircle1,
+                        Standard_True);
+  addToModel(aFirstEdgeCurve);
+
+  // Creating EdgeCurve containing the second Circle.
+  Handle(StepShape_EdgeCurve) aSecondEdgeCurve = new StepShape_EdgeCurve;
+  aSecondEdgeCurve->Init(new TCollection_HAsciiString,
+                         new StepShape_Vertex,
+                         new StepShape_Vertex,
+                         aCircle2,
+                         Standard_True);
+  addToModel(aSecondEdgeCurve);
+
+  // Performing removal of duplicate Circles.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCircles();
+
+  // Check that nothing was removed.
+  EXPECT_TRUE(aRemovedEntities.IsEmpty());
+}
+
+// Check that equal Circles are merged for StepShape_EdgeCurve.
+TEST_F(StepTidy_CircleReducerTest, StepShape_EdgeCurve)
+{
+  // Creating Circles.
+  Handle(StepGeom_Circle) aCircle1 = addCircle();
+  Handle(StepGeom_Circle) aCircle2 = addCircle();
+
+  // Creating EdgeCurve containing the first Circle.
+  Handle(StepShape_EdgeCurve) aFirstEdgeCurve = new StepShape_EdgeCurve;
+  aFirstEdgeCurve->Init(new TCollection_HAsciiString,
+                        new StepShape_Vertex,
+                        new StepShape_Vertex,
+                        aCircle1,
+                        Standard_True);
+  addToModel(aFirstEdgeCurve);
+
+  // Creating EdgeCurve containing the second Circle.
+  Handle(StepShape_EdgeCurve) aSecondEdgeCurve = new StepShape_EdgeCurve;
+  aSecondEdgeCurve->Init(new TCollection_HAsciiString,
+                         new StepShape_Vertex,
+                         new StepShape_Vertex,
+                         aCircle2,
+                         Standard_True);
+  addToModel(aSecondEdgeCurve);
+
+  // Performing removal of duplicate Circles.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCircles();
+
+  // Check that one Circle was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aCircle1) || aRemovedEntities.Contains(aCircle2));
+}
+
+// Check that equal Circles are merged for StepGeom_SurfaceCurve.
+TEST_F(StepTidy_CircleReducerTest, StepGeom_SurfaceCurve)
+{
+  // Creating Circles.
+  Handle(StepGeom_Circle) aCircle1 = addCircle();
+  Handle(StepGeom_Circle) aCircle2 = addCircle();
+
+  // Creating SurfaceCurve containing the first Circle.
+  Handle(StepGeom_SurfaceCurve) aFirstSurfaceCurve = new StepGeom_SurfaceCurve;
+  aFirstSurfaceCurve->Init(new TCollection_HAsciiString,
+                           aCircle1,
+                           new StepGeom_HArray1OfPcurveOrSurface,
+                           StepGeom_pscrCurve3d);
+  addToModel(aFirstSurfaceCurve);
+
+  // Creating SurfaceCurve containing the second Circle.
+  Handle(StepGeom_SurfaceCurve) aSecondSurfaceCurve = new StepGeom_SurfaceCurve;
+  aSecondSurfaceCurve->Init(new TCollection_HAsciiString,
+                            aCircle2,
+                            new StepGeom_HArray1OfPcurveOrSurface,
+                            StepGeom_pscrCurve3d);
+  addToModel(aSecondSurfaceCurve);
+
+  // Performing removal of duplicate Circles.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCircles();
+
+  // Check that one Circle was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aCircle1) || aRemovedEntities.Contains(aCircle2));
+}
+
+// Check that equal Circles are merged for StepGeom_SeamCurve.
+TEST_F(StepTidy_CircleReducerTest, StepGeom_SeamCurve)
+{
+  // Creating Circles.
+  Handle(StepGeom_Circle) aCircle1 = addCircle();
+  Handle(StepGeom_Circle) aCircle2 = addCircle();
+
+  // Creating SeamCurve containing the first Circle.
+  Handle(StepGeom_SeamCurve) aFirstSeamCurve = new StepGeom_SeamCurve;
+  aFirstSeamCurve->Init(new TCollection_HAsciiString,
+                        aCircle1,
+                        new StepGeom_HArray1OfPcurveOrSurface,
+                        StepGeom_pscrCurve3d);
+  addToModel(aFirstSeamCurve);
+
+  // Creating SeamCurve containing the second Circle.
+  Handle(StepGeom_SeamCurve) aSecondSeamCurve = new StepGeom_SeamCurve;
+  aSecondSeamCurve->Init(new TCollection_HAsciiString,
+                         aCircle2,
+                         new StepGeom_HArray1OfPcurveOrSurface,
+                         StepGeom_pscrCurve3d);
+  addToModel(aSecondSeamCurve);
+
+  // Performing removal of duplicate Circles.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateCircles();
+
+  // Check that one Circle was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aCircle1) || aRemovedEntities.Contains(aCircle2));
+}
diff --git a/src/DataExchange/TKDESTEP/GTests/StepTidy_DirectionReducer_Test.cxx b/src/DataExchange/TKDESTEP/GTests/StepTidy_DirectionReducer_Test.cxx
new file mode 100644 (file)
index 0000000..9b32c33
--- /dev/null
@@ -0,0 +1,157 @@
+// 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.
+
+#include "StepTidy_BaseTestFixture.pxx"
+
+#include <StepTidy_DirectionReducer.pxx>
+
+#include <StepGeom_Axis1Placement.hxx>
+#include <StepGeom_Axis2Placement3d.hxx>
+
+class StepTidy_DirectionReducerTest : public StepTidy_BaseTestFixture
+{
+protected:
+  //! Perform removal of duplicate entities.
+  TColStd_MapOfTransient replaceDuplicateDirections()
+  {
+    StepTidy_DirectionReducer aReducer(myWS);
+    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
+    {
+      aReducer.ProcessEntity(myWS->Model()->Value(anIndex));
+    }
+
+    TColStd_MapOfTransient aRemovedEntities;
+    aReducer.Perform(aRemovedEntities);
+    return aRemovedEntities;
+  }
+};
+
+// Check that directions with the same coordinates and different names are not merged.
+TEST_F(StepTidy_DirectionReducerTest, DifferentNames)
+{
+  // Creating directions.
+  Handle(StepGeom_Direction) aDir1 = addDirection("dir1");
+  Handle(StepGeom_Direction) aDir2 = addDirection("dir2");
+
+  // Creating vector containing the first direction.
+  Handle(StepGeom_Vector) aFirstVector = new StepGeom_Vector;
+  aFirstVector->Init(new TCollection_HAsciiString, aDir1, 1.);
+  addToModel(aFirstVector);
+
+  // Creating vector containing the second direction.
+  Handle(StepGeom_Vector) aSecondVector = new StepGeom_Vector;
+  aSecondVector->Init(new TCollection_HAsciiString, aDir2, 1.);
+  addToModel(aSecondVector);
+
+  // Performing removal of duplicate directions.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateDirections();
+
+  // Check that nothing was removed.
+  EXPECT_TRUE(aRemovedEntities.IsEmpty());
+}
+
+// Check that directions with the same coordinates and same names are
+// merged for StepGeom_Axis1Placement.
+TEST_F(StepTidy_DirectionReducerTest, StepGeom_Axis1Placement)
+{
+  // Creating directions.
+  Handle(StepGeom_Direction) aDir1 = addDirection();
+  Handle(StepGeom_Direction) aDir2 = addDirection();
+
+  // Creating Cartesian point for the location.
+  Handle(StepGeom_CartesianPoint) aLocation       = new StepGeom_CartesianPoint;
+  Handle(TColStd_HArray1OfReal)   aLocationCoords = new TColStd_HArray1OfReal(1, 3);
+  aLocationCoords->SetValue(1, 0.);
+  aLocationCoords->SetValue(2, 0.);
+  aLocationCoords->SetValue(3, 0.);
+  aLocation->Init(new TCollection_HAsciiString, aLocationCoords);
+  addToModel(aLocation);
+
+  // Creating axis containing the first direction.
+  Handle(StepGeom_Axis1Placement) aFirstAxis = new StepGeom_Axis1Placement;
+  aFirstAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir1);
+  addToModel(aFirstAxis);
+
+  // Creating axis containing the second direction.
+  Handle(StepGeom_Axis1Placement) aSecondAxis = new StepGeom_Axis1Placement;
+  aSecondAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir2);
+  addToModel(aSecondAxis);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateDirections();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aDir1) || aRemovedEntities.Contains(aDir2));
+}
+
+// Check that directions with the same coordinates and same names are
+// merged for StepGeom_Axis2Placement.
+TEST_F(StepTidy_DirectionReducerTest, StepGeom_Axis2Placement)
+{
+  // Creating directions.
+  Handle(StepGeom_Direction) aDir1 = addDirection();
+  Handle(StepGeom_Direction) aDir2 = addDirection();
+
+  // Creating Cartesian point for the location.
+  Handle(StepGeom_CartesianPoint) aLocation       = new StepGeom_CartesianPoint;
+  Handle(TColStd_HArray1OfReal)   aLocationCoords = new TColStd_HArray1OfReal(1, 3);
+  aLocationCoords->SetValue(1, 0.);
+  aLocationCoords->SetValue(2, 0.);
+  aLocationCoords->SetValue(3, 0.);
+  aLocation->Init(new TCollection_HAsciiString, aLocationCoords);
+  addToModel(aLocation);
+
+  // Creating axis containing the first direction.
+  Handle(StepGeom_Axis2Placement3d) aFirstAxis = new StepGeom_Axis2Placement3d;
+  aFirstAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir1, false, nullptr);
+  addToModel(aFirstAxis);
+
+  // Creating axis containing the second direction.
+  Handle(StepGeom_Axis2Placement3d) aSecondAxis = new StepGeom_Axis2Placement3d;
+  aSecondAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir2, false, nullptr);
+  addToModel(aSecondAxis);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateDirections();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aDir1) || aRemovedEntities.Contains(aDir2));
+}
+
+// Check that points with the same coordinates and same names are
+// merged for StepGeom_Vector.
+TEST_F(StepTidy_DirectionReducerTest, StepGeom_Vector)
+{
+  // Creating directions.
+  Handle(StepGeom_Direction) aDir1 = addDirection();
+  Handle(StepGeom_Direction) aDir2 = addDirection();
+
+  // Creating vector containing the first direction.
+  Handle(StepGeom_Vector) aFirstVector = new StepGeom_Vector;
+  aFirstVector->Init(new TCollection_HAsciiString, aDir1, 1.);
+  addToModel(aFirstVector);
+
+  // Creating vector containing the second direction.
+  Handle(StepGeom_Vector) aSecondVector = new StepGeom_Vector;
+  aSecondVector->Init(new TCollection_HAsciiString, aDir2, 1.);
+  addToModel(aSecondVector);
+
+  // Performing removal of duplicate Cartesian points.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateDirections();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aDir1) || aRemovedEntities.Contains(aDir2));
+}
diff --git a/src/DataExchange/TKDESTEP/GTests/StepTidy_LineReducer_Test.cxx b/src/DataExchange/TKDESTEP/GTests/StepTidy_LineReducer_Test.cxx
new file mode 100644 (file)
index 0000000..79e8f8c
--- /dev/null
@@ -0,0 +1,239 @@
+// 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.
+
+#include "StepTidy_BaseTestFixture.pxx"
+
+#include <StepTidy_LineReducer.pxx>
+
+#include <StepShape_EdgeCurve.hxx>
+#include <StepGeom_TrimmedCurve.hxx>
+#include <StepGeom_SurfaceCurve.hxx>
+#include <StepRepr_DefinitionalRepresentation.hxx>
+#include <StepGeom_SeamCurve.hxx>
+#include <StepRepr_RepresentationContext.hxx>
+
+class StepTidy_LineReducerTest : public StepTidy_BaseTestFixture
+{
+protected:
+  //! Perform removal of duplicate entities.
+  TColStd_MapOfTransient replaceDuplicateLines()
+  {
+    StepTidy_LineReducer aReducer(myWS);
+    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
+    {
+      aReducer.ProcessEntity(myWS->Model()->Value(anIndex));
+    }
+
+    TColStd_MapOfTransient aRemovedEntities;
+    aReducer.Perform(aRemovedEntities);
+    return aRemovedEntities;
+  }
+};
+
+// Check that Lines with different names are not merged.
+TEST_F(StepTidy_LineReducerTest, DifferentNames)
+{
+  // Creating Lines.
+  Handle(StepGeom_Line) aLine1 = addLine("Line1");
+  Handle(StepGeom_Line) aLine2 = addLine("Line2");
+
+  // Creating EdgeCurve containing the first Line.
+  Handle(StepShape_EdgeCurve) aFirstEdgeCurve = new StepShape_EdgeCurve;
+  aFirstEdgeCurve->Init(new TCollection_HAsciiString,
+                        new StepShape_Vertex,
+                        new StepShape_Vertex,
+                        aLine1,
+                        Standard_True);
+  addToModel(aFirstEdgeCurve);
+
+  // Creating EdgeCurve containing the second Line.
+  Handle(StepShape_EdgeCurve) aSecondEdgeCurve = new StepShape_EdgeCurve;
+  aSecondEdgeCurve->Init(new TCollection_HAsciiString,
+                         new StepShape_Vertex,
+                         new StepShape_Vertex,
+                         aLine2,
+                         Standard_True);
+  addToModel(aSecondEdgeCurve);
+
+  // Performing removal of duplicate Lines.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
+
+  // Check that nothing was removed.
+  EXPECT_TRUE(aRemovedEntities.IsEmpty());
+}
+
+// Check that equal Lines are merged for StepShape_EdgeCurve.
+TEST_F(StepTidy_LineReducerTest, StepShape_EdgeCurve)
+{
+  // Creating Lines.
+  Handle(StepGeom_Line) aLine1 = addLine();
+  Handle(StepGeom_Line) aLine2 = addLine();
+
+  // Creating EdgeCurve containing the first Line.
+  Handle(StepShape_EdgeCurve) aFirstEdgeCurve = new StepShape_EdgeCurve;
+  aFirstEdgeCurve->Init(new TCollection_HAsciiString,
+                        new StepShape_Vertex,
+                        new StepShape_Vertex,
+                        aLine1,
+                        Standard_True);
+  addToModel(aFirstEdgeCurve);
+
+  // Creating EdgeCurve containing the second Line.
+  Handle(StepShape_EdgeCurve) aSecondEdgeCurve = new StepShape_EdgeCurve;
+  aSecondEdgeCurve->Init(new TCollection_HAsciiString,
+                         new StepShape_Vertex,
+                         new StepShape_Vertex,
+                         aLine2,
+                         Standard_True);
+  addToModel(aSecondEdgeCurve);
+
+  // Performing removal of duplicate Lines.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
+
+  // Check that one Line was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aLine1) || aRemovedEntities.Contains(aLine2));
+}
+
+// Check that equal Lines are merged for StepGeom_TrimmedCurve.
+TEST_F(StepTidy_LineReducerTest, StepGeom_TrimmedCurve)
+{
+  // Creating Lines.
+  Handle(StepGeom_Line) aLine1 = addLine();
+  Handle(StepGeom_Line) aLine2 = addLine();
+
+  // Creating TrimmedCurve containing the first Line.
+  Handle(StepGeom_TrimmedCurve) aFirstTrimmedCurve = new StepGeom_TrimmedCurve;
+  aFirstTrimmedCurve->Init(new TCollection_HAsciiString,
+                           aLine1,
+                           new StepGeom_HArray1OfTrimmingSelect,
+                           new StepGeom_HArray1OfTrimmingSelect,
+                           Standard_True,
+                           StepGeom_tpUnspecified);
+  addToModel(aFirstTrimmedCurve);
+
+  // Creating TrimmedCurve containing the second Line.
+  Handle(StepGeom_TrimmedCurve) aSecondTrimmedCurve = new StepGeom_TrimmedCurve;
+  aSecondTrimmedCurve->Init(new TCollection_HAsciiString,
+                            aLine2,
+                            new StepGeom_HArray1OfTrimmingSelect,
+                            new StepGeom_HArray1OfTrimmingSelect,
+                            Standard_True,
+                            StepGeom_tpUnspecified);
+  addToModel(aSecondTrimmedCurve);
+
+  // Performing removal of duplicate Lines.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
+
+  // Check that one Line was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aLine1) || aRemovedEntities.Contains(aLine2));
+}
+
+// Check that equal Lines are merged for StepGeom_SurfaceCurve.
+TEST_F(StepTidy_LineReducerTest, StepGeom_SurfaceCurve)
+{
+  // Creating Lines.
+  Handle(StepGeom_Line) aLine1 = addLine();
+  Handle(StepGeom_Line) aLine2 = addLine();
+
+  // Creating SurfaceCurve containing the first Line.
+  Handle(StepGeom_SurfaceCurve) aFirstSurfaceCurve = new StepGeom_SurfaceCurve;
+  aFirstSurfaceCurve->Init(new TCollection_HAsciiString,
+                           aLine1,
+                           new StepGeom_HArray1OfPcurveOrSurface,
+                           StepGeom_pscrCurve3d);
+  addToModel(aFirstSurfaceCurve);
+
+  // Creating SurfaceCurve containing the second Line.
+  Handle(StepGeom_SurfaceCurve) aSecondSurfaceCurve = new StepGeom_SurfaceCurve;
+  aSecondSurfaceCurve->Init(new TCollection_HAsciiString,
+                            aLine2,
+                            new StepGeom_HArray1OfPcurveOrSurface,
+                            StepGeom_pscrCurve3d);
+  addToModel(aSecondSurfaceCurve);
+
+  // Performing removal of duplicate Lines.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
+
+  // Check that one Line was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aLine1) || aRemovedEntities.Contains(aLine2));
+}
+
+// Check that equal Lines are merged for StepRepr_DefinitionalRepresentation.
+TEST_F(StepTidy_LineReducerTest, StepRepr_DefinitionalRepresentation)
+{
+  // Creating Lines.
+  Handle(StepGeom_Line) aLine1 = addLine();
+  Handle(StepGeom_Line) aLine2 = addLine();
+
+  // Creating DefinitionalRepresentation containing the first Line.
+  Handle(StepRepr_HArray1OfRepresentationItem) aFirstItems =
+    new StepRepr_HArray1OfRepresentationItem(1, 1);
+  aFirstItems->SetValue(1, aLine1);
+  Handle(StepRepr_DefinitionalRepresentation) aFirstDefinitionalRepresentation =
+    new StepRepr_DefinitionalRepresentation;
+  aFirstDefinitionalRepresentation->Init(new TCollection_HAsciiString,
+                                         aFirstItems,
+                                         new StepRepr_RepresentationContext);
+  addToModel(aFirstDefinitionalRepresentation);
+
+  // Creating DefinitionalRepresentation containing the second Line.
+  Handle(StepRepr_HArray1OfRepresentationItem) aSecondItems =
+    new StepRepr_HArray1OfRepresentationItem(1, 1);
+  aSecondItems->SetValue(1, aLine2);
+  Handle(StepRepr_DefinitionalRepresentation) aSecondDefinitionalRepresentation =
+    new StepRepr_DefinitionalRepresentation;
+  aSecondDefinitionalRepresentation->Init(new TCollection_HAsciiString,
+                                          aSecondItems,
+                                          new StepRepr_RepresentationContext);
+
+  // Performing removal of duplicate Lines.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
+
+  // Check that one Line was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aLine1) || aRemovedEntities.Contains(aLine2));
+}
+
+// Check that equal Lines are merged for StepGeom_SeamCurve.
+TEST_F(StepTidy_LineReducerTest, StepGeom_SeamCurve)
+{
+  // Creating Lines.
+  Handle(StepGeom_Line) aLine1 = addLine();
+  Handle(StepGeom_Line) aLine2 = addLine();
+
+  // Creating SeamCurve containing the first Line.
+  Handle(StepGeom_SeamCurve) aFirstSeamCurve = new StepGeom_SeamCurve;
+  aFirstSeamCurve->Init(new TCollection_HAsciiString,
+                        aLine1,
+                        new StepGeom_HArray1OfPcurveOrSurface,
+                        StepGeom_pscrCurve3d);
+  addToModel(aFirstSeamCurve);
+
+  // Creating SeamCurve containing the second Line.
+  Handle(StepGeom_SeamCurve) aSecondSeamCurve = new StepGeom_SeamCurve;
+  aSecondSeamCurve->Init(new TCollection_HAsciiString,
+                         aLine2,
+                         new StepGeom_HArray1OfPcurveOrSurface,
+                         StepGeom_pscrCurve3d);
+  addToModel(aSecondSeamCurve);
+
+  // Performing removal of duplicate Lines.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateLines();
+
+  // Check that one Line was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aLine1) || aRemovedEntities.Contains(aLine2));
+}
diff --git a/src/DataExchange/TKDESTEP/GTests/StepTidy_Merger_Test.cxx b/src/DataExchange/TKDESTEP/GTests/StepTidy_Merger_Test.cxx
new file mode 100644 (file)
index 0000000..5dc9193
--- /dev/null
@@ -0,0 +1,113 @@
+// 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.
+
+#include "StepTidy_BaseTestFixture.pxx"
+
+#include <StepTidy_DuplicateCleaner.hxx>
+
+#include <StepGeom_Axis1Placement.hxx>
+
+class StepTidy_DuplicateCleanerTest : public StepTidy_BaseTestFixture
+{
+protected:
+  // Get the number of entities of the specified type.
+  // @param theType the type of entities to count.
+  // @return the number of entities of the specified type.
+  int getEntitiesCount(const Handle(Standard_Type)& theType) const
+  {
+    int aCount = 0;
+    for (Standard_Integer i = 1; i <= myWS->Model()->NbEntities(); i++)
+    {
+      if (myWS->Model()->Value(i)->IsKind(theType))
+      {
+        aCount++;
+      }
+    }
+    return aCount;
+  }
+
+  //! Perform removal of duplicate entities points.
+  void performRemoval()
+  {
+    StepTidy_DuplicateCleaner aMerger(myWS);
+    aMerger.Perform();
+  }
+};
+
+// Check that entities with the same coordinates and different names are not merged.
+TEST_F(StepTidy_DuplicateCleanerTest, DifferentEntities)
+{
+  // Creating directions.
+  Handle(StepGeom_Direction) aDir1 = addDirection("dir1");
+  Handle(StepGeom_Direction) aDir2 = addDirection("dir2");
+
+  // Creating vector containing the first direction.
+  Handle(StepGeom_Vector) aFirstVector = new StepGeom_Vector;
+  aFirstVector->Init(new TCollection_HAsciiString, aDir1, 1.);
+  addToModel(aFirstVector);
+
+  // Creating vector containing the second direction.
+  Handle(StepGeom_Vector) aSecondVector = new StepGeom_Vector;
+  aSecondVector->Init(new TCollection_HAsciiString, aDir2, 1.);
+  addToModel(aSecondVector);
+
+  const int aDirectionCountBefore = getEntitiesCount(STANDARD_TYPE(StepGeom_Direction));
+
+  // Performing removal of duplicate directions.
+  performRemoval();
+
+  const int aDirectionCountAfter = getEntitiesCount(STANDARD_TYPE(StepGeom_Direction));
+
+  // Check that nothing was removed.
+  EXPECT_EQ(aDirectionCountBefore, 2);
+  EXPECT_EQ(aDirectionCountBefore, aDirectionCountAfter);
+}
+
+// Check that entities with the same coordinates and same names are
+// merged for StepGeom_Axis1Placement.
+TEST_F(StepTidy_DuplicateCleanerTest, EqualEntities)
+{
+  // Creating directions.
+  Handle(StepGeom_Direction) aDir1 = addDirection();
+  Handle(StepGeom_Direction) aDir2 = addDirection();
+
+  // Creating Cartesian point for the location.
+  Handle(StepGeom_CartesianPoint) aLocation       = new StepGeom_CartesianPoint;
+  Handle(TColStd_HArray1OfReal)   aLocationCoords = new TColStd_HArray1OfReal(1, 3);
+  aLocationCoords->SetValue(1, 0.);
+  aLocationCoords->SetValue(2, 0.);
+  aLocationCoords->SetValue(3, 0.);
+  aLocation->Init(new TCollection_HAsciiString, aLocationCoords);
+  addToModel(aLocation);
+
+  // Creating axis containing the first direction.
+  Handle(StepGeom_Axis1Placement) aFirstAxis = new StepGeom_Axis1Placement;
+  aFirstAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir1);
+  addToModel(aFirstAxis);
+
+  // Creating axis containing the second direction.
+  Handle(StepGeom_Axis1Placement) aSecondAxis = new StepGeom_Axis1Placement;
+  aSecondAxis->Init(new TCollection_HAsciiString, aLocation, true, aDir2);
+  addToModel(aSecondAxis);
+
+  const int aDirectionCountBefore = getEntitiesCount(STANDARD_TYPE(StepGeom_Direction));
+
+  // Performing removal of duplicate directions.
+  performRemoval();
+
+  const int aDirectionCountAfter = getEntitiesCount(STANDARD_TYPE(StepGeom_Direction));
+
+  // Check that one direction was removed.
+  EXPECT_EQ(aDirectionCountBefore, 2);
+  EXPECT_EQ(aDirectionCountAfter, 1);
+}
diff --git a/src/DataExchange/TKDESTEP/GTests/StepTidy_PlaneReducer_Test.cxx b/src/DataExchange/TKDESTEP/GTests/StepTidy_PlaneReducer_Test.cxx
new file mode 100644 (file)
index 0000000..bc6e95e
--- /dev/null
@@ -0,0 +1,128 @@
+// 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.
+
+#include "StepTidy_BaseTestFixture.pxx"
+
+#include <StepTidy_PlaneReducer.pxx>
+
+#include <StepShape_AdvancedFace.hxx>
+#include <StepGeom_Pcurve.hxx>
+#include <StepRepr_DefinitionalRepresentation.hxx>
+
+class StepTidy_PlaneReducerTest : public StepTidy_BaseTestFixture
+{
+protected:
+  //! Perform removal of duplicate entities.
+  TColStd_MapOfTransient replaceDuplicatePlanes()
+  {
+    StepTidy_PlaneReducer aReducer(myWS);
+    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
+    {
+      aReducer.ProcessEntity(myWS->Model()->Value(anIndex));
+    }
+
+    TColStd_MapOfTransient aRemovedEntities;
+    aReducer.Perform(aRemovedEntities);
+    return aRemovedEntities;
+  }
+};
+
+// Check that Planes with different names are not merged.
+TEST_F(StepTidy_PlaneReducerTest, DifferentNames)
+{
+  // Creating Planes.
+  Handle(StepGeom_Plane) aPlane1 = addPlane("Plane1");
+  Handle(StepGeom_Plane) aPlane2 = addPlane("Plane2");
+
+  // Creating StepShape_AdvancedFace containing the first Plane.
+  Handle(StepShape_AdvancedFace) aFirstAdvancedFace = new StepShape_AdvancedFace;
+  aFirstAdvancedFace->Init(new TCollection_HAsciiString,
+                           new StepShape_HArray1OfFaceBound,
+                           aPlane1,
+                           Standard_True);
+  addToModel(aFirstAdvancedFace);
+
+  // Creating StepShape_AdvancedFace containing the second Plane.
+  Handle(StepShape_AdvancedFace) aSecondAdvancedFace = new StepShape_AdvancedFace;
+  aSecondAdvancedFace->Init(new TCollection_HAsciiString,
+                            new StepShape_HArray1OfFaceBound,
+                            aPlane2,
+                            Standard_True);
+  addToModel(aSecondAdvancedFace);
+
+  // Performing removal of duplicate Planes.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicatePlanes();
+
+  // Check that nothing was removed.
+  EXPECT_TRUE(aRemovedEntities.IsEmpty());
+}
+
+// Check that equal Planes are merged for StepShape_AdvancedFace.
+TEST_F(StepTidy_PlaneReducerTest, StepShape_AdvancedFace)
+{
+  // Creating Planes.
+  Handle(StepGeom_Plane) aPlane1 = addPlane();
+  Handle(StepGeom_Plane) aPlane2 = addPlane();
+
+  // Creating StepShape_AdvancedFace containing the first Plane.
+  Handle(StepShape_AdvancedFace) aFirstAdvancedFace = new StepShape_AdvancedFace;
+  aFirstAdvancedFace->Init(new TCollection_HAsciiString,
+                           new StepShape_HArray1OfFaceBound,
+                           aPlane1,
+                           Standard_True);
+  addToModel(aFirstAdvancedFace);
+
+  // Creating StepShape_AdvancedFace containing the second Plane.
+  Handle(StepShape_AdvancedFace) aSecondAdvancedFace = new StepShape_AdvancedFace;
+  aSecondAdvancedFace->Init(new TCollection_HAsciiString,
+                            new StepShape_HArray1OfFaceBound,
+                            aPlane2,
+                            Standard_True);
+  addToModel(aSecondAdvancedFace);
+
+  // Performing removal of duplicate Planes.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicatePlanes();
+
+  // Check that one Plane was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPlane1) || aRemovedEntities.Contains(aPlane2));
+}
+
+// Check that equal Planes are merged for StepGeom_Pcurve.
+TEST_F(StepTidy_PlaneReducerTest, StepGeom_Pcurve)
+{
+  // Creating Planes.
+  Handle(StepGeom_Plane) aPlane1 = addPlane();
+  Handle(StepGeom_Plane) aPlane2 = addPlane();
+
+  // Creating StepGeom_Pcurve containing the first Plane.
+  Handle(StepGeom_Pcurve) aFirstPcurve = new StepGeom_Pcurve;
+  aFirstPcurve->Init(new TCollection_HAsciiString,
+                     aPlane1,
+                     new StepRepr_DefinitionalRepresentation);
+  addToModel(aFirstPcurve);
+
+  // Creating StepGeom_Pcurve containing the second Plane.
+  Handle(StepGeom_Pcurve) aSecondPcurve = new StepGeom_Pcurve;
+  aSecondPcurve->Init(new TCollection_HAsciiString,
+                      aPlane2,
+                      new StepRepr_DefinitionalRepresentation);
+  addToModel(aSecondPcurve);
+
+  // Performing removal of duplicate Planes.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicatePlanes();
+
+  // Check that one Plane was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aPlane1) || aRemovedEntities.Contains(aPlane2));
+}
diff --git a/src/DataExchange/TKDESTEP/GTests/StepTidy_VectorReducer_Test.cxx b/src/DataExchange/TKDESTEP/GTests/StepTidy_VectorReducer_Test.cxx
new file mode 100644 (file)
index 0000000..f6a44e3
--- /dev/null
@@ -0,0 +1,92 @@
+// 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.
+
+#include "StepTidy_BaseTestFixture.pxx"
+
+#include <StepTidy_VectorReducer.pxx>
+
+#include <StepGeom_Line.hxx>
+
+class StepTidy_VectorReducerTest : public StepTidy_BaseTestFixture
+{
+protected:
+  //! Perform removal of duplicate entities.
+  TColStd_MapOfTransient replaceDuplicateVectors()
+  {
+    StepTidy_VectorReducer aReducer(myWS);
+    for (Standard_Integer anIndex = 1; anIndex <= myWS->Model()->NbEntities(); ++anIndex)
+    {
+      aReducer.ProcessEntity(myWS->Model()->Value(anIndex));
+    }
+
+    TColStd_MapOfTransient aRemovedEntities;
+    aReducer.Perform(aRemovedEntities);
+    return aRemovedEntities;
+  }
+};
+
+// Check that Vectors with the same coordinates and different names are not merged.
+TEST_F(StepTidy_VectorReducerTest, DifferentNames)
+{
+  // Creating Vectors.
+  Handle(StepGeom_Vector) aVec1 = addVector("vec1");
+  Handle(StepGeom_Vector) aVec2 = addVector("vec2");
+
+  // Creating a cartesian point for the lines.
+  Handle(StepGeom_CartesianPoint) aPnt = addCartesianPoint(nullptr, {0., 0., 0.});
+
+  // Creating aLine containing the first Vector.
+  Handle(StepGeom_Line) aLine1 = new StepGeom_Line;
+  aLine1->Init(new TCollection_HAsciiString, aPnt, aVec1);
+  addToModel(aLine1);
+
+  // Creating aLine containing the second Vector.
+  Handle(StepGeom_Line) aLine2 = new StepGeom_Line;
+  aLine2->Init(new TCollection_HAsciiString, aPnt, aVec2);
+  addToModel(aLine2);
+
+  // Performing removal of duplicate Vectors.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateVectors();
+
+  // Check that nothing was removed.
+  EXPECT_TRUE(aRemovedEntities.IsEmpty());
+}
+
+// Check that Vectors with the same coordinates and same names are
+// merged for StepGeom_Axis1Placement.
+TEST_F(StepTidy_VectorReducerTest, StepGeom_Line)
+{
+  // Creating Vectors.
+  Handle(StepGeom_Vector) aVec1 = addVector();
+  Handle(StepGeom_Vector) aVec2 = addVector();
+
+  // Creating a cartesian point for the lines.
+  Handle(StepGeom_CartesianPoint) aPnt = addCartesianPoint(nullptr, {0., 0., 0.});
+
+  // Creating aLine containing the first Vector.
+  Handle(StepGeom_Line) aLine1 = new StepGeom_Line;
+  aLine1->Init(new TCollection_HAsciiString, aPnt, aVec1);
+  addToModel(aLine1);
+
+  // Creating aLine containing the second Vector.
+  Handle(StepGeom_Line) aLine2 = new StepGeom_Line;
+  aLine2->Init(new TCollection_HAsciiString, aPnt, aVec2);
+  addToModel(aLine2);
+
+  // Performing removal of duplicate Vectors.
+  TColStd_MapOfTransient aRemovedEntities = replaceDuplicateVectors();
+
+  // Check that duplicate was removed.
+  EXPECT_EQ(aRemovedEntities.Size(), 1);
+  EXPECT_TRUE(aRemovedEntities.Contains(aVec1) || aRemovedEntities.Contains(aVec2));
+}
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/FILES.cmake b/src/DataExchange/TKDESTEP/MergeSTEPEntities/FILES.cmake
deleted file mode 100644 (file)
index c55d38e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Source files for STEPControl package
-set(OCCT_MergeSTEPEntities_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
-
-set(OCCT_MergeSTEPEntities_FILES
-  MergeSTEPEntities_Axis2Placement2dHasher.hxx
-  MergeSTEPEntities_Axis2Placement3dHasher.hxx
-  MergeSTEPEntities_Axis2Placement3dProcessor.cxx
-  MergeSTEPEntities_Axis2Placement3dProcessor.hxx
-  MergeSTEPEntities_CartesianPointHasher.hxx
-  MergeSTEPEntities_CartesianPointProcessor.cxx
-  MergeSTEPEntities_CartesianPointProcessor.hxx
-  MergeSTEPEntities_CircleHasher.hxx
-  MergeSTEPEntities_CircleProcessor.cxx
-  MergeSTEPEntities_CircleProcessor.hxx
-  MergeSTEPEntities_DirectionHasher.hxx
-  MergeSTEPEntities_DirectionProcessor.cxx
-  MergeSTEPEntities_DirectionProcessor.hxx
-  MergeSTEPEntities_EntityProcessor.hxx
-  MergeSTEPEntities_LineHasher.hxx
-  MergeSTEPEntities_LineProcessor.cxx
-  MergeSTEPEntities_LineProcessor.hxx
-  MergeSTEPEntities_Merger.cxx
-  MergeSTEPEntities_Merger.hxx
-  MergeSTEPEntities_PlaneHasher.hxx
-  MergeSTEPEntities_PlaneProcessor.cxx
-  MergeSTEPEntities_PlaneProcessor.hxx
-  MergeSTEPEntities_VectorHasher.hxx
-  MergeSTEPEntities_VectorProcessor.cxx
-  MergeSTEPEntities_VectorProcessor.hxx
-)
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement2dHasher.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement2dHasher.hxx
deleted file mode 100644 (file)
index a98f3bf..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-// 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 _MergeSTEPEntities_Axis2Placement2dHasher_HeaderFile
-#define _MergeSTEPEntities_Axis2Placement2dHasher_HeaderFile
-
-#include <Standard_HashUtils.hxx>
-#include <StepGeom_Axis2Placement2d.hxx>
-
-#include <MergeSTEPEntities_CartesianPointHasher.hxx>
-#include <MergeSTEPEntities_DirectionHasher.hxx>
-
-//! OCCT-style hasher for StepGeom_Axis2Placement2d entities.
-//! Currently only used for implementation of hasher for StepGeom_Circle.
-struct MergeSTEPEntities_Axis2Placement2dHasher
-{
-  // Hashes the axis placements.
-  std::size_t operator()(const Handle(StepGeom_Axis2Placement2d)& thePlacement) const noexcept
-  {
-    // Prepare an array of hashes for the location, axis, and ref direction.
-    // Optimal seed is used for the axis and ref direction if they are not present.
-    const size_t aHashes[2]{MergeSTEPEntities_CartesianPointHasher{}(thePlacement->Location()),
-                            thePlacement->HasRefDirection()
-                              ? MergeSTEPEntities_DirectionHasher{}(thePlacement->RefDirection())
-                              : opencascade::MurmurHash::optimalSeed()};
-    const size_t aHash = opencascade::hashBytes(aHashes, sizeof(aHashes));
-    if (thePlacement->Name().IsNull())
-    {
-      // If the name is not present, return the hash.
-      return aHash;
-    }
-    // Add the name to the hash if it is present.
-    const size_t aHashWithName[2]{
-      aHash,
-      std::hash<TCollection_AsciiString>{}(thePlacement->Name()->String())};
-    return opencascade::hashBytes(aHashWithName, sizeof(aHashWithName));
-  }
-
-  // Compares two axis placements.
-  bool operator()(const Handle(StepGeom_Axis2Placement2d)& thePlacement1,
-                  const Handle(StepGeom_Axis2Placement2d)& thePlacement2) const noexcept
-  {
-    // Compare names.
-    if (thePlacement1->Name().IsNull() != thePlacement2->Name().IsNull())
-    {
-      return false;
-    }
-    if (!thePlacement1->Name()->IsSameString(thePlacement2->Name()))
-    {
-      return false;
-    }
-
-    // Compare location, axis, and ref direction.
-    const bool isSameLocation = MergeSTEPEntities_CartesianPointHasher{}(thePlacement1->Location(),
-                                                                         thePlacement2->Location());
-    // Have to check if the axis is present and compare it.
-    // Have to check if the ref direction is present and compare it.
-    const bool isSameRefDirectionFlag =
-      thePlacement1->HasRefDirection() == thePlacement2->HasRefDirection();
-    const bool isSameRefDirection =
-      isSameRefDirectionFlag
-      && (!thePlacement1->HasRefDirection()
-          || MergeSTEPEntities_DirectionHasher{}(thePlacement1->RefDirection(),
-                                                 thePlacement2->RefDirection()));
-
-    return isSameLocation && isSameRefDirection;
-  }
-};
-
-#endif // _MergeSTEPEntities_Axis2Placement2dHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement3dHasher.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement3dHasher.hxx
deleted file mode 100644 (file)
index 9d0c70d..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-// 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 _MergeSTEPEntities_Axis2Placement3dHasher_HeaderFile
-#define _MergeSTEPEntities_Axis2Placement3dHasher_HeaderFile
-
-#include <Standard_HashUtils.hxx>
-#include <StepGeom_Axis2Placement3d.hxx>
-
-#include <MergeSTEPEntities_CartesianPointHasher.hxx>
-#include <MergeSTEPEntities_DirectionHasher.hxx>
-
-//! OCCT-style hasher for StepGeom_Axis2Placement3d entities.
-struct MergeSTEPEntities_Axis2Placement3dHasher
-{
-  // Hashes the axis placements.
-  std::size_t operator()(const Handle(StepGeom_Axis2Placement3d)& thePlacement) const noexcept
-  {
-    // Prepare an array of hashes for the location, axis, and ref direction.
-    // Optimal seed is used for the axis and ref direction if they are not present.
-    const size_t aHashes[3]{MergeSTEPEntities_CartesianPointHasher{}(thePlacement->Location()),
-                            thePlacement->HasAxis()
-                              ? MergeSTEPEntities_DirectionHasher{}(thePlacement->Axis())
-                              : opencascade::MurmurHash::optimalSeed(),
-                            thePlacement->HasRefDirection()
-                              ? MergeSTEPEntities_DirectionHasher{}(thePlacement->RefDirection())
-                              : opencascade::MurmurHash::optimalSeed()};
-    const size_t aHash = opencascade::hashBytes(aHashes, sizeof(aHashes));
-    if (thePlacement->Name().IsNull())
-    {
-      // If the name is not present, return the hash.
-      return aHash;
-    }
-    // Add the name to the hash if it is present.
-    const size_t aHashWithName[2]{
-      aHash,
-      std::hash<TCollection_AsciiString>{}(thePlacement->Name()->String())};
-    return opencascade::hashBytes(aHashWithName, sizeof(aHashWithName));
-  }
-
-  // Compares two axis placements.
-  bool operator()(const Handle(StepGeom_Axis2Placement3d)& thePlacement1,
-                  const Handle(StepGeom_Axis2Placement3d)& thePlacement2) const noexcept
-  {
-    // Compare names.
-    if (thePlacement1->Name().IsNull() != thePlacement2->Name().IsNull())
-    {
-      return false;
-    }
-    if (!thePlacement1->Name()->IsSameString(thePlacement2->Name()))
-    {
-      return false;
-    }
-
-    // Compare location, axis, and ref direction.
-    const bool isSameLocation = MergeSTEPEntities_CartesianPointHasher{}(thePlacement1->Location(),
-                                                                         thePlacement2->Location());
-    // Have to check if the axis is present and compare it.
-    const bool isSameAxisFlag = thePlacement1->HasAxis() == thePlacement2->HasAxis();
-    const bool isSameAxis =
-      isSameAxisFlag
-      && (!thePlacement1->HasAxis()
-          || MergeSTEPEntities_DirectionHasher{}(thePlacement1->Axis(), thePlacement2->Axis()));
-    // Have to check if the ref direction is present and compare it.
-    const bool isSameRefDirectionFlag =
-      thePlacement1->HasRefDirection() == thePlacement2->HasRefDirection();
-    const bool isSameRefDirection =
-      isSameRefDirectionFlag
-      && (!thePlacement1->HasRefDirection()
-          || MergeSTEPEntities_DirectionHasher{}(thePlacement1->RefDirection(),
-                                                 thePlacement2->RefDirection()));
-
-    return isSameLocation && isSameAxis && isSameRefDirection;
-  }
-};
-
-#endif // _MergeSTEPEntities_Axis2Placement3dHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement3dProcessor.cxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement3dProcessor.cxx
deleted file mode 100644 (file)
index b1e49a4..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-// 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.
-
-#include <MergeSTEPEntities_Axis2Placement3dProcessor.hxx>
-
-#include <StepGeom_Plane.hxx>
-#include <StepRepr_ItemDefinedTransformation.hxx>
-#include <StepGeom_CylindricalSurface.hxx>
-#include <StepShape_ShapeRepresentation.hxx>
-#include <StepRepr_ConstructiveGeometryRepresentation.hxx>
-#include <StepGeom_Circle.hxx>
-#include <StepVisual_PresentationLayerAssignment.hxx>
-#include <StepVisual_StyledItem.hxx>
-#include <StepGeom_Ellipse.hxx>
-#include <StepGeom_ConicalSurface.hxx>
-#include <StepGeom_ToroidalSurface.hxx>
-#include <StepShape_AdvancedBrepShapeRepresentation.hxx>
-#include <StepGeom_SphericalSurface.hxx>
-
-//==================================================================================================
-
-MergeSTEPEntities_Axis2Placement3dProcessor::MergeSTEPEntities_Axis2Placement3dProcessor(
-  const Handle(XSControl_WorkSession)& theWS)
-    : MergeSTEPEntities_EntityProcessor<StepGeom_Axis2Placement3d,
-                                        MergeSTEPEntities_Axis2Placement3dHasher>(theWS)
-{
-  registerReplacer(STANDARD_TYPE(StepGeom_Plane), replacePlane);
-  registerReplacer(STANDARD_TYPE(StepRepr_ItemDefinedTransformation),
-                   replaceItemDefinedTransformation);
-  registerReplacer(STANDARD_TYPE(StepGeom_CylindricalSurface), replaceCylindricalSurface);
-  registerReplacer(STANDARD_TYPE(StepShape_ShapeRepresentation), replaceShapeRepresentation);
-  registerReplacer(STANDARD_TYPE(StepRepr_ConstructiveGeometryRepresentation),
-                   replaceConstructiveGeometryRepresentation);
-  registerReplacer(STANDARD_TYPE(StepGeom_Circle), replaceCircle);
-  registerReplacer(STANDARD_TYPE(StepVisual_PresentationLayerAssignment),
-                   replacePresentationLayerAssignment);
-  registerReplacer(STANDARD_TYPE(StepVisual_StyledItem), replaceStyledItem);
-  registerReplacer(STANDARD_TYPE(StepGeom_Ellipse), replaceEllipse);
-  registerReplacer(STANDARD_TYPE(StepGeom_ConicalSurface), replaceConicalSurface);
-  registerReplacer(STANDARD_TYPE(StepGeom_ToroidalSurface), replaceToroidalSurface);
-  registerReplacer(STANDARD_TYPE(StepShape_AdvancedBrepShapeRepresentation),
-                   replaceAdvancedBrepShapeRepresentation);
-  registerReplacer(STANDARD_TYPE(StepGeom_SphericalSurface), replaceSphericalSurface);
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replacePlane(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepGeom_Plane) aSharing = Handle(StepGeom_Plane)::DownCast(theSharing);
-  if (aSharing->Position() == theOldEntity)
-  {
-    aSharing->SetPosition(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replaceItemDefinedTransformation(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepRepr_ItemDefinedTransformation) aSharing =
-    Handle(StepRepr_ItemDefinedTransformation)::DownCast(theSharing);
-  bool isReplaced = false;
-  if (aSharing->TransformItem1() == theOldEntity)
-  {
-    aSharing->SetTransformItem1(theNewEntity);
-    isReplaced = true;
-  }
-  if (aSharing->TransformItem2() == theOldEntity)
-  {
-    aSharing->SetTransformItem2(theNewEntity);
-    isReplaced = true;
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replaceCylindricalSurface(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepGeom_CylindricalSurface) aSharing =
-    Handle(StepGeom_CylindricalSurface)::DownCast(theSharing);
-  if (aSharing->Position() == theOldEntity)
-  {
-    aSharing->SetPosition(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replaceShapeRepresentation(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepShape_ShapeRepresentation) aSharing =
-    Handle(StepShape_ShapeRepresentation)::DownCast(theSharing);
-  bool isReplaced = false;
-  for (Standard_Integer anIndex = aSharing->Items()->Lower(); anIndex <= aSharing->Items()->Upper();
-       ++anIndex)
-  {
-    if (aSharing->Items()->Value(anIndex) == theOldEntity)
-    {
-      aSharing->Items()->SetValue(anIndex, theNewEntity);
-      isReplaced = true;
-    }
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replaceConstructiveGeometryRepresentation(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepRepr_ConstructiveGeometryRepresentation) aSharing =
-    Handle(StepRepr_ConstructiveGeometryRepresentation)::DownCast(theSharing);
-  bool isReplaced = false;
-  for (Standard_Integer anIndex = aSharing->Items()->Lower(); anIndex <= aSharing->Items()->Upper();
-       ++anIndex)
-  {
-    if (aSharing->Items()->Value(anIndex) == theOldEntity)
-    {
-      aSharing->Items()->SetValue(anIndex, theNewEntity);
-      isReplaced = true;
-    }
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replaceCircle(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepGeom_Circle) aSharing  = Handle(StepGeom_Circle)::DownCast(theSharing);
-  StepGeom_Axis2Placement aSelector = aSharing->Position();
-  if (aSelector.Axis2Placement3d() == theOldEntity)
-  {
-    aSelector.SetValue(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replacePresentationLayerAssignment(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepVisual_PresentationLayerAssignment) aSharing =
-    Handle(StepVisual_PresentationLayerAssignment)::DownCast(theSharing);
-  bool                                    isReplaced = false;
-  Handle(StepVisual_HArray1OfLayeredItem) anItems    = aSharing->AssignedItems();
-  for (Standard_Integer anIndex = anItems->Lower(); anIndex <= anItems->Upper(); ++anIndex)
-  {
-    StepVisual_LayeredItem& aLayeredItem = anItems->ChangeValue(anIndex);
-    if (aLayeredItem.RepresentationItem() == theOldEntity)
-    {
-      aLayeredItem.SetValue(theNewEntity);
-      isReplaced = true;
-    }
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replaceStyledItem(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepVisual_StyledItem) aSharing = Handle(StepVisual_StyledItem)::DownCast(theSharing);
-  if (aSharing->Item() == theOldEntity)
-  {
-    aSharing->SetItem(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replaceEllipse(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepGeom_Ellipse) aSharing  = Handle(StepGeom_Ellipse)::DownCast(theSharing);
-  StepGeom_Axis2Placement  aSelector = aSharing->Position();
-  if (aSelector.Axis2Placement3d() == theOldEntity)
-  {
-    aSelector.SetValue(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replaceConicalSurface(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepGeom_ConicalSurface) aSharing = Handle(StepGeom_ConicalSurface)::DownCast(theSharing);
-  if (aSharing->Position() == theOldEntity)
-  {
-    aSharing->SetPosition(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replaceToroidalSurface(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepGeom_ToroidalSurface) aSharing =
-    Handle(StepGeom_ToroidalSurface)::DownCast(theSharing);
-  if (aSharing->Position() == theOldEntity)
-  {
-    aSharing->SetPosition(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replaceAdvancedBrepShapeRepresentation(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepShape_AdvancedBrepShapeRepresentation) aSharing =
-    Handle(StepShape_AdvancedBrepShapeRepresentation)::DownCast(theSharing);
-  bool isReplaced = false;
-  for (Standard_Integer anIndex = aSharing->Items()->Lower(); anIndex <= aSharing->Items()->Upper();
-       ++anIndex)
-  {
-    if (aSharing->Items()->Value(anIndex) == theOldEntity)
-    {
-      aSharing->Items()->SetValue(anIndex, theNewEntity);
-      isReplaced = true;
-    }
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_Axis2Placement3dProcessor::replaceSphericalSurface(
-  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-  Handle(Standard_Transient)               theSharing)
-{
-  Handle(StepGeom_SphericalSurface) aSharing =
-    Handle(StepGeom_SphericalSurface)::DownCast(theSharing);
-  if (aSharing->Position() == theOldEntity)
-  {
-    aSharing->SetPosition(theNewEntity);
-    return true;
-  }
-  return false;
-}
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement3dProcessor.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Axis2Placement3dProcessor.hxx
deleted file mode 100644 (file)
index c46247c..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-// 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 _MergeSTEPEntities_Axis2Placement3dProcessor_HeaderFile
-#define _MergeSTEPEntities_Axis2Placement3dProcessor_HeaderFile
-
-#include <MergeSTEPEntities_EntityProcessor.hxx>
-#include <MergeSTEPEntities_Axis2Placement3dHasher.hxx>
-
-#include <StepGeom_Axis2Placement3d.hxx>
-
-//! Processor for merging StepGeom_Axis2Placement3d entities.
-//! This processor merges axis placements with the same location, axis, and ref direction.
-class MergeSTEPEntities_Axis2Placement3dProcessor
-    : public MergeSTEPEntities_EntityProcessor<StepGeom_Axis2Placement3d,
-                                               MergeSTEPEntities_Axis2Placement3dHasher>
-{
-public:
-  //! Constructor. Stores the work session and registers replacer functions.
-  //! @param theWS the work session.
-  Standard_EXPORT MergeSTEPEntities_Axis2Placement3dProcessor(
-    const Handle(XSControl_WorkSession)& theWS);
-
-private:
-  //! Replaces the old axis placement with the new one in the StepGeom_Plane entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepGeom_Plane entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replacePlane(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-                           const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-                           Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the StepRepr_ItemDefinedTransformation
-  //! entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepRepr_ItemDefinedTransformation entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replaceItemDefinedTransformation(
-    const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-    const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-    Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the StepGeom_CylindricalSurface entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepGeom_CylindricalSurface entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replaceCylindricalSurface(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-                                        const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-                                        Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the StepShape_ShapeRepresentation entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepShape_ShapeRepresentation entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replaceShapeRepresentation(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-                                         const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-                                         Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the
-  //! StepRepr_ConstructiveGeometryRepresentation entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepRepr_ConstructiveGeometryRepresentation entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replaceConstructiveGeometryRepresentation(
-    const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-    const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-    Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the StepGeom_Circle entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepGeom_Circle entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replaceCircle(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-                            const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-                            Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the StepGeom_PresentationLayerAssignment
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepGeom_PresentationLayerAssignment entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replacePresentationLayerAssignment(
-    const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-    const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-    Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the StepVisual_StyledItem entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepVisual_StyledItem entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replaceStyledItem(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-                                const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-                                Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the StepGeom_Ellipse entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepGeom_Ellipse entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replaceEllipse(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-                             const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-                             Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the StepGeom_ConicalSurface entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepGeom_ConicalSurface entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replaceConicalSurface(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-                                    const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-                                    Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the StepGeom_ToroidalSurface entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepGeom_ToroidalSurface entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replaceToroidalSurface(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-                                     const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-                                     Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the
-  //! StepShape_AdvancedBrepShapeRepresentation entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepShape_AdvancedBrepShapeRepresentation entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replaceAdvancedBrepShapeRepresentation(
-    const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-    const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-    Handle(Standard_Transient)               theSharing);
-
-  //! Replaces the old axis placement with the new one in the StepGeom_SphericalSurface entity.
-  //! @param theOldEntity the old axis placement.
-  //! @param theNewEntity the new axis placement to replace the old one.
-  //! @param theSharing the StepGeom_SphericalSurface entity to update.
-  //! @return true if the axis placement was replaced, false otherwise.
-  static bool replaceSphericalSurface(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
-                                      const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
-                                      Handle(Standard_Transient)               theSharing);
-};
-
-#endif // _MergeSTEPEntities_DirectionProcessor_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CartesianPointHasher.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CartesianPointHasher.hxx
deleted file mode 100644 (file)
index 1349227..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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 _MergeSTEPEntities_CartesianPointHasher_HeaderFile
-#define _MergeSTEPEntities_CartesianPointHasher_HeaderFile
-
-#include <Standard_HashUtils.hxx>
-#include <StepGeom_CartesianPoint.hxx>
-#include <TCollection_HAsciiString.hxx>
-
-//! OCCT-style hasher for StepGeom_CartesianPoint entities.
-struct MergeSTEPEntities_CartesianPointHasher
-{
-  // Hashes the Cartesian point by its name and coordinates.
-  std::size_t operator()(const Handle(StepGeom_CartesianPoint)& theCartesianPoint) const noexcept
-  {
-    const std::array<Standard_Real, 3>& aCoords = theCartesianPoint->Coordinates();
-    // If Cartesian point has no name, hash only coordinates.
-    if (theCartesianPoint->Name().IsNull())
-    {
-      return opencascade::hashBytes(aCoords.data(), static_cast<int>(aCoords.size()));
-    }
-    // Otherwise, hash both coordinates and name.
-    const size_t aHashes[2]{
-      opencascade::hashBytes(aCoords.data(), static_cast<int>(aCoords.size())),
-      std::hash<TCollection_AsciiString>{}(theCartesianPoint->Name()->String())};
-
-    return opencascade::hashBytes(aHashes, sizeof(aHashes));
-  }
-
-  // Compares two Cartesian points by their names and coordinates.
-  bool operator()(const Handle(StepGeom_CartesianPoint)& theCartesianPoint1,
-                  const Handle(StepGeom_CartesianPoint)& theCartesianPoint2) const noexcept
-  {
-    // Compare names.
-    if (theCartesianPoint1->Name().IsNull() != theCartesianPoint2->Name().IsNull())
-    {
-      return false;
-    }
-    if (!theCartesianPoint1->Name()->IsSameString(theCartesianPoint2->Name()))
-    {
-      return false;
-    }
-
-    // Compare coordinates.
-    constexpr double                    aTolerance = 1e-12;
-    const std::array<Standard_Real, 3>& aCoords1   = theCartesianPoint1->Coordinates();
-    const std::array<Standard_Real, 3>& aCoords2   = theCartesianPoint2->Coordinates();
-    if (aCoords1.size() != aCoords2.size())
-    {
-      return false;
-    }
-    for (size_t anIndex = 0; anIndex < aCoords1.size(); ++anIndex)
-    {
-      if (std::abs(aCoords1[anIndex] - aCoords2[anIndex]) > aTolerance)
-      {
-        return false;
-      }
-    }
-    return true;
-  }
-};
-
-#endif // _MergeSTEPEntities_CartesianPointHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CartesianPointProcessor.cxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CartesianPointProcessor.cxx
deleted file mode 100644 (file)
index 54fc8c6..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-// 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.
-
-#include <MergeSTEPEntities_CartesianPointProcessor.hxx>
-
-#include <Interface_Graph.hxx>
-#include <StepGeom_Axis1Placement.hxx>
-#include <StepGeom_Axis2Placement3d.hxx>
-#include <StepGeom_BSplineCurveWithKnots.hxx>
-#include <StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve.hxx>
-#include <StepGeom_BSplineSurfaceWithKnots.hxx>
-#include <StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface.hxx>
-#include <StepGeom_Line.hxx>
-#include <StepRepr_Representation.hxx>
-#include <StepShape_GeometricCurveSet.hxx>
-#include <StepShape_VertexPoint.hxx>
-#include <StepVisual_PresentationLayerAssignment.hxx>
-#include <StepVisual_StyledItem.hxx>
-
-//==================================================================================================
-
-MergeSTEPEntities_CartesianPointProcessor::MergeSTEPEntities_CartesianPointProcessor(
-  const Handle(XSControl_WorkSession)& theWS)
-    : MergeSTEPEntities_EntityProcessor<StepGeom_CartesianPoint,
-                                        MergeSTEPEntities_CartesianPointHasher>(theWS)
-{
-  registerReplacer(STANDARD_TYPE(StepGeom_Axis1Placement), replaceAxis1Placement);
-  registerReplacer(STANDARD_TYPE(StepGeom_Axis2Placement3d), replaceAxis2Placement3d);
-  registerReplacer(STANDARD_TYPE(StepShape_VertexPoint), replaceVertexPoint);
-  registerReplacer(STANDARD_TYPE(StepShape_GeometricCurveSet), replaceGeometricCurveSet);
-  registerReplacer(STANDARD_TYPE(StepVisual_PresentationLayerAssignment),
-                   replacePresentationLayerAssignment);
-  registerReplacer(STANDARD_TYPE(StepVisual_StyledItem), replaceStyledItem);
-  registerReplacer(STANDARD_TYPE(StepGeom_BSplineCurveWithKnots), replaceBSplineCurveWithKnots);
-  registerReplacer(STANDARD_TYPE(StepGeom_Line), replaceLine);
-  registerReplacer(STANDARD_TYPE(StepGeom_BSplineSurfaceWithKnots), replaceBSplineSurfaceWithKnots);
-  registerReplacer(STANDARD_TYPE(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve),
-                   replaceBSplineCurveWithKnotsAndRationalBSplineCurve);
-  registerReplacer(STANDARD_TYPE(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface),
-                   replaceBSplineSurfaceWithKnotsAndRationalBSplineSurface);
-  registerReplacer(STANDARD_TYPE(StepRepr_Representation), replaceRepresentation);
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::replaceAxis2Placement3d(
-  const Handle(StepGeom_CartesianPoint)& theOldEntity,
-  const Handle(StepGeom_CartesianPoint)& theNewEntity,
-  Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepGeom_Axis2Placement3d) aSharing =
-    Handle(StepGeom_Axis2Placement3d)::DownCast(theSharing);
-  if (aSharing->Location() == theOldEntity)
-  {
-    aSharing->SetLocation(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::replaceVertexPoint(
-  const Handle(StepGeom_CartesianPoint)& theOldEntity,
-  const Handle(StepGeom_CartesianPoint)& theNewEntity,
-  Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepShape_VertexPoint) aSharing = Handle(StepShape_VertexPoint)::DownCast(theSharing);
-  if (aSharing->VertexGeometry() == theOldEntity)
-  {
-    aSharing->SetVertexGeometry(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::replaceGeometricCurveSet(
-  const Handle(StepGeom_CartesianPoint)& theOldEntity,
-  const Handle(StepGeom_CartesianPoint)& theNewEntity,
-  Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepShape_GeometricSet) aSharing   = Handle(StepShape_GeometricSet)::DownCast(theSharing);
-  bool                           isReplaced = false;
-  for (auto& anElement : *aSharing->Elements())
-  {
-    const Handle(StepGeom_Point) aCurrentPoint = anElement.Point();
-    if (aCurrentPoint && aCurrentPoint == theOldEntity)
-    {
-      anElement.SetValue(theNewEntity);
-      isReplaced = true;
-    }
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::replacePresentationLayerAssignment(
-  const Handle(StepGeom_CartesianPoint)& theOldEntity,
-  const Handle(StepGeom_CartesianPoint)& theNewEntity,
-  Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepVisual_PresentationLayerAssignment) aSharing =
-    Handle(StepVisual_PresentationLayerAssignment)::DownCast(theSharing);
-  bool isReplaced = false;
-  for (auto& anAssignedItem : *aSharing->AssignedItems())
-  {
-    const Handle(StepRepr_RepresentationItem) aRepItem = anAssignedItem.RepresentationItem();
-    if (aRepItem == theOldEntity)
-    {
-      anAssignedItem.SetValue(theNewEntity);
-      isReplaced = true;
-    }
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::replaceStyledItem(
-  const Handle(StepGeom_CartesianPoint)& theOldEntity,
-  const Handle(StepGeom_CartesianPoint)& theNewEntity,
-  Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepVisual_StyledItem) aSharing = Handle(StepVisual_StyledItem)::DownCast(theSharing);
-  if (aSharing->Item() == theOldEntity)
-  {
-    aSharing->SetItem(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::replaceBSplineCurveWithKnots(
-  const Handle(StepGeom_CartesianPoint)& theOldEntity,
-  const Handle(StepGeom_CartesianPoint)& theNewEntity,
-  Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepGeom_BSplineCurveWithKnots) aSharing =
-    Handle(StepGeom_BSplineCurveWithKnots)::DownCast(theSharing);
-  bool                                     isReplaced     = false;
-  Handle(StepGeom_HArray1OfCartesianPoint) aControlPoints = aSharing->ControlPointsList();
-  for (Standard_Integer anIndex = aControlPoints->Lower(); anIndex <= aControlPoints->Upper();
-       ++anIndex)
-  {
-    if (aControlPoints->Value(anIndex) == theOldEntity)
-    {
-      aControlPoints->SetValue(anIndex, theNewEntity);
-      isReplaced = true;
-    }
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::replaceLine(
-  const Handle(StepGeom_CartesianPoint)& theOldEntity,
-  const Handle(StepGeom_CartesianPoint)& theNewEntity,
-  Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepGeom_Line) aSharing = Handle(StepGeom_Line)::DownCast(theSharing);
-  if (aSharing->Pnt() == theOldEntity)
-  {
-    aSharing->SetPnt(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::replaceBSplineSurfaceWithKnots(
-  const Handle(StepGeom_CartesianPoint)& theOldEntity,
-  const Handle(StepGeom_CartesianPoint)& theNewEntity,
-  Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepGeom_BSplineSurfaceWithKnots) aSharing =
-    Handle(StepGeom_BSplineSurfaceWithKnots)::DownCast(theSharing);
-  bool                                     isReplaced     = false;
-  Handle(StepGeom_HArray2OfCartesianPoint) aControlPoints = aSharing->ControlPointsList();
-  for (Standard_Integer anIndexI = aControlPoints->LowerRow();
-       anIndexI <= aControlPoints->UpperRow();
-       ++anIndexI)
-  {
-    for (Standard_Integer anIndexJ = aControlPoints->LowerCol();
-         anIndexJ <= aControlPoints->UpperCol();
-         ++anIndexJ)
-    {
-      if (aControlPoints->Value(anIndexI, anIndexJ) == theOldEntity)
-      {
-        aControlPoints->SetValue(anIndexI, anIndexJ, theNewEntity);
-        isReplaced = true;
-      }
-    }
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::replaceAxis1Placement(
-  const Handle(StepGeom_CartesianPoint)& theOldEntity,
-  const Handle(StepGeom_CartesianPoint)& theNewEntity,
-  Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepGeom_Axis1Placement) aSharing = Handle(StepGeom_Axis1Placement)::DownCast(theSharing);
-  if (aSharing->Location() == theOldEntity)
-  {
-    aSharing->SetLocation(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::replaceRepresentation(
-  const Handle(StepGeom_CartesianPoint)& theOldEntity,
-  const Handle(StepGeom_CartesianPoint)& theNewEntity,
-  Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepRepr_Representation) aSharing = Handle(StepRepr_Representation)::DownCast(theSharing);
-  bool                            isReplaced           = false;
-  Handle(StepRepr_HArray1OfRepresentationItem) anItems = aSharing->Items();
-  for (Standard_Integer anIndex = 1; anIndex <= aSharing->NbItems(); ++anIndex)
-  {
-    const Handle(StepRepr_RepresentationItem) aRepItem = anItems->Value(anIndex);
-    if (aRepItem == theOldEntity)
-    {
-      anItems->SetValue(anIndex, theNewEntity);
-      isReplaced = true;
-    }
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::replaceBSplineCurveWithKnotsAndRationalBSplineCurve(
-  const Handle(StepGeom_CartesianPoint)& theOldEntity,
-  const Handle(StepGeom_CartesianPoint)& theNewEntity,
-  Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve) aSharing =
-    Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve)::DownCast(theSharing);
-  bool                                     isReplaced     = false;
-  Handle(StepGeom_HArray1OfCartesianPoint) aControlPoints = aSharing->ControlPointsList();
-  for (Standard_Integer anIndex = aControlPoints->Lower(); anIndex <= aControlPoints->Upper();
-       ++anIndex)
-  {
-    if (aControlPoints->Value(anIndex) == theOldEntity)
-    {
-      aControlPoints->SetValue(anIndex, theNewEntity);
-      isReplaced = true;
-    }
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CartesianPointProcessor::
-  replaceBSplineSurfaceWithKnotsAndRationalBSplineSurface(
-    const Handle(StepGeom_CartesianPoint)& theOldEntity,
-    const Handle(StepGeom_CartesianPoint)& theNewEntity,
-    Handle(Standard_Transient)             theSharing)
-{
-  Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface) aSharing =
-    Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface)::DownCast(theSharing);
-  bool                                     isReplaced     = false;
-  Handle(StepGeom_HArray2OfCartesianPoint) aControlPoints = aSharing->ControlPointsList();
-  for (Standard_Integer anIndexI = aControlPoints->LowerRow();
-       anIndexI <= aControlPoints->UpperRow();
-       ++anIndexI)
-  {
-    for (Standard_Integer anIndexJ = aControlPoints->LowerCol();
-         anIndexJ <= aControlPoints->UpperCol();
-         ++anIndexJ)
-    {
-      if (aControlPoints->Value(anIndexI, anIndexJ) == theOldEntity)
-      {
-        aControlPoints->SetValue(anIndexI, anIndexJ, theNewEntity);
-        isReplaced = true;
-      }
-    }
-  }
-  return isReplaced;
-}
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CartesianPointProcessor.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CartesianPointProcessor.hxx
deleted file mode 100644 (file)
index 55c8d72..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-// 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 _MergeSTEPEntities_CartesianPointProcessor_HeaderFile
-#define _MergeSTEPEntities_CartesianPointProcessor_HeaderFile
-
-#include <MergeSTEPEntities_EntityProcessor.hxx>
-#include <MergeSTEPEntities_CartesianPointHasher.hxx>
-
-#include <StepGeom_CartesianPoint.hxx>
-
-//! Processor for merging StepGeom_CartesianPoint entities.
-//! This processor is responsible for merging Cartesian points with the same coordinates and names.
-//! It is used to remove duplicate Cartesian points from the STEP model.
-//! See MergeSTEPEntities_EntityProcessor for the description of the processor workflow.
-class MergeSTEPEntities_CartesianPointProcessor
-    : public MergeSTEPEntities_EntityProcessor<StepGeom_CartesianPoint,
-                                               MergeSTEPEntities_CartesianPointHasher>
-{
-public:
-  //! Constructor. Accepts a work session containing the model to process.
-  //! Registers replacer functions for all supported sharing entities.
-  //! @param theWS Work session.
-  Standard_EXPORT MergeSTEPEntities_CartesianPointProcessor(
-    const Handle(XSControl_WorkSession)& theWS);
-
-private:
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepGeom_Axis2Placement3d.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepGeom_Axis2Placement3d sharing the old entity.
-  //! @return True if the entity was replaced, false if it was not.
-  static bool replaceAxis2Placement3d(const Handle(StepGeom_CartesianPoint)& theOldEntity,
-                                      const Handle(StepGeom_CartesianPoint)& theNewEntity,
-                                      Handle(Standard_Transient)             theSharing);
-
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepShape_VertexPoint.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepShape_VertexPoint sharing the old entity.
-  //! @return True if the entity was replaced, false if it was not.
-  static bool replaceVertexPoint(const Handle(StepGeom_CartesianPoint)& theOldEntity,
-                                 const Handle(StepGeom_CartesianPoint)& theNewEntity,
-                                 Handle(Standard_Transient)             theSharing);
-
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepShape_GeometricSet.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepShape_GeometricSet sharing the old entity.
-  //! @return True if the entity was replaced, false if it was not.
-  static bool replaceGeometricCurveSet(const Handle(StepGeom_CartesianPoint)& theOldEntity,
-                                       const Handle(StepGeom_CartesianPoint)& theNewEntity,
-                                       Handle(Standard_Transient)             theSharing);
-
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepVisual_PresentationLayerAssignment.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepVisual_PresentationLayerAssignment sharing the old entity.
-  //! @return True if the entity was replaced, false if it was not.
-  static bool replacePresentationLayerAssignment(
-    const Handle(StepGeom_CartesianPoint)& theOldEntity,
-    const Handle(StepGeom_CartesianPoint)& theNewEntity,
-    Handle(Standard_Transient)             theSharing);
-
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepVisual_StyledItem.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepVisual_StyledItem sharing the old entity.
-  //! @return True if the entity was replaced, false if it was not.
-  static bool replaceStyledItem(const Handle(StepGeom_CartesianPoint)& theOldEntity,
-                                const Handle(StepGeom_CartesianPoint)& theNewEntity,
-                                Handle(Standard_Transient)             theSharing);
-
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepGeom_BSplineCurveWithKnots.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepGeom_BSplineCurveWithKnots sharing the old entity.
-  //! @return True if the entity was replaced, false if it was not.
-  static bool replaceBSplineCurveWithKnots(const Handle(StepGeom_CartesianPoint)& theOldEntity,
-                                           const Handle(StepGeom_CartesianPoint)& theNewEntity,
-                                           Handle(Standard_Transient)             theSharing);
-
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepGeom_Line.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepGeom_Line sharing the old entity.
-  //! @return True if the entity was replaced, false if it was not.
-  static bool replaceLine(const Handle(StepGeom_CartesianPoint)& theOldEntity,
-                          const Handle(StepGeom_CartesianPoint)& theNewEntity,
-                          Handle(Standard_Transient)             theSharing);
-
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepGeom_BSplineSurfaceWithKnots.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepGeom_BSplineSurfaceWithKnots sharing the old entity.
-  //! @return True if the entity was replaced, false if it was not.
-  static bool replaceBSplineSurfaceWithKnots(const Handle(StepGeom_CartesianPoint)& theOldEntity,
-                                             const Handle(StepGeom_CartesianPoint)& theNewEntity,
-                                             Handle(Standard_Transient)             theSharing);
-
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepGeom_Axis1Placement.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepGeom_Axis1Placement sharing the old entity.
-  //! @return True if the entity was replaced, false if it was not.
-  static bool replaceAxis1Placement(const Handle(StepGeom_CartesianPoint)& theOldEntity,
-                                    const Handle(StepGeom_CartesianPoint)& theNewEntity,
-                                    Handle(Standard_Transient)             theSharing);
-
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepRepr_Representation.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepRepr_Representation sharing the old entity.
-  //! @return True if the entity was replaced, false if it was not.
-  static bool replaceRepresentation(const Handle(StepGeom_CartesianPoint)& theOldEntity,
-                                    const Handle(StepGeom_CartesianPoint)& theNewEntity,
-                                    Handle(Standard_Transient)             theSharing);
-
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve sharing the old
-  //!        entity.
-  //! @return True if the entity was replaced, false if it was not.
-  static bool replaceBSplineCurveWithKnotsAndRationalBSplineCurve(
-    const Handle(StepGeom_CartesianPoint)& theOldEntity,
-    const Handle(StepGeom_CartesianPoint)& theNewEntity,
-    Handle(Standard_Transient)             theSharing);
-
-  //! Replaces the old Cartesian point with the new Cartesian point in
-  //! the sharing StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface.
-  //! @param theOldEntity Old Cartesian point to replace.
-  //! @param theNewEntity New Cartesian point to replace the old entity with.
-  //! @param theSharing The StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface sharing the
-  //!       old entity.
-  static bool replaceBSplineSurfaceWithKnotsAndRationalBSplineSurface(
-    const Handle(StepGeom_CartesianPoint)& theOldEntity,
-    const Handle(StepGeom_CartesianPoint)& theNewEntity,
-    Handle(Standard_Transient)             theSharing);
-};
-
-#endif // _MergeSTEPEntities_CartesianPointProcessor_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CircleHasher.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CircleHasher.hxx
deleted file mode 100644 (file)
index 31208dd..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-// 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 _MergeSTEPEntities_CircleHasher_HeaderFile
-#define _MergeSTEPEntities_CircleHasher_HeaderFile
-
-#include <MergeSTEPEntities_Axis2Placement2dHasher.hxx>
-#include <MergeSTEPEntities_Axis2Placement3dHasher.hxx>
-
-#include <Standard_HashUtils.hxx>
-#include <StepGeom_Circle.hxx>
-#include <TCollection_HAsciiString.hxx>
-
-//! OCCT-style hasher for StepGeom_Circle entities.
-struct MergeSTEPEntities_CircleHasher
-{
-  //! Returns hash for a Circle entity.
-  std::size_t operator()(const Handle(StepGeom_Circle)& theCircle) const noexcept
-  {
-    const size_t aPositionHash =
-      !theCircle->Position().Axis2Placement2d().IsNull()
-        ? MergeSTEPEntities_Axis2Placement2dHasher{}(theCircle->Position().Axis2Placement2d())
-      : !theCircle->Position().Axis2Placement3d().IsNull()
-        ? MergeSTEPEntities_Axis2Placement3dHasher{}(theCircle->Position().Axis2Placement3d())
-        : opencascade::MurmurHash::optimalSeed();
-
-    const size_t aRadiusHash = opencascade::hash(static_cast<int>(theCircle->Radius()));
-
-    const size_t aHashes[2]{aPositionHash, aRadiusHash};
-    const size_t aCombinedHash = opencascade::hashBytes(aHashes, sizeof(aHashes));
-    if (theCircle->Name().IsNull())
-    {
-      // If the name is not present, return the hash.
-      return aCombinedHash;
-    }
-    // Add the name to the hash if it is present.
-    const size_t aHashWithName[2]{
-      aCombinedHash,
-      std::hash<TCollection_AsciiString>{}(theCircle->Name()->String())};
-    return opencascade::hashBytes(aHashWithName, sizeof(aHashWithName));
-  }
-
-  //! Compares two Circle entities.
-  bool operator()(const Handle(StepGeom_Circle)& theCircle1,
-                  const Handle(StepGeom_Circle)& theCircle2) const noexcept
-  {
-    // Compare names.
-    if (theCircle1->Name().IsNull() != theCircle2->Name().IsNull())
-    {
-      return false;
-    }
-    if (!theCircle1->Name()->IsSameString(theCircle2->Name()))
-    {
-      return false;
-    }
-
-    // Compare axis placements.
-    if (theCircle1->Position().CaseNumber() != theCircle2->Position().CaseNumber())
-    {
-      return false;
-    }
-
-    if (theCircle1->Position().CaseNumber() == 1)
-    {
-      if (!MergeSTEPEntities_Axis2Placement2dHasher{}(theCircle1->Position().Axis2Placement2d(),
-                                                      theCircle2->Position().Axis2Placement2d()))
-      {
-        return false;
-      }
-    }
-    else if (theCircle1->Position().CaseNumber() == 2)
-    {
-      if (!MergeSTEPEntities_Axis2Placement3dHasher{}(theCircle1->Position().Axis2Placement3d(),
-                                                      theCircle2->Position().Axis2Placement3d()))
-      {
-        return false;
-      }
-    }
-
-    // Compare radius.
-    constexpr Standard_Real aTolerance = 1e-12;
-    if (Abs(theCircle1->Radius() - theCircle2->Radius()) > aTolerance)
-    {
-      return false;
-    }
-
-    return true;
-  }
-};
-
-#endif // _MergeSTEPEntities_CircleHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CircleProcessor.cxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CircleProcessor.cxx
deleted file mode 100644 (file)
index 32dbbc4..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-// 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.
-
-// 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.
-
-#include <MergeSTEPEntities_CircleProcessor.hxx>
-
-#include <Interface_Graph.hxx>
-#include <StepShape_EdgeCurve.hxx>
-#include <StepGeom_SurfaceCurve.hxx>
-#include <StepGeom_SeamCurve.hxx>
-
-//==================================================================================================
-
-MergeSTEPEntities_CircleProcessor::MergeSTEPEntities_CircleProcessor(
-  const Handle(XSControl_WorkSession)& theWS)
-    : MergeSTEPEntities_EntityProcessor<StepGeom_Circle, MergeSTEPEntities_CircleHasher>(theWS)
-{
-  registerReplacer(STANDARD_TYPE(StepShape_EdgeCurve), replaceEdgeCurve);
-  registerReplacer(STANDARD_TYPE(StepGeom_SurfaceCurve), replaceSurfaceCurve);
-  registerReplacer(STANDARD_TYPE(StepGeom_SeamCurve), replaceSeamCurve);
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CircleProcessor::replaceEdgeCurve(
-  const Handle(StepGeom_Circle)& theOldEntity,
-  const Handle(StepGeom_Circle)& theNewEntity,
-  Handle(Standard_Transient)     theSharing)
-{
-  Handle(StepShape_EdgeCurve) aSharing = Handle(StepShape_EdgeCurve)::DownCast(theSharing);
-  if (aSharing->EdgeGeometry() == theOldEntity)
-  {
-    aSharing->SetEdgeGeometry(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CircleProcessor::replaceSurfaceCurve(
-  const Handle(StepGeom_Circle)& theOldEntity,
-  const Handle(StepGeom_Circle)& theNewEntity,
-  Handle(Standard_Transient)     theSharing)
-{
-  Handle(StepGeom_SurfaceCurve) aSharing = Handle(StepGeom_SurfaceCurve)::DownCast(theSharing);
-  if (aSharing->Curve3d() == theOldEntity)
-  {
-    aSharing->SetCurve3d(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_CircleProcessor::replaceSeamCurve(
-  const Handle(StepGeom_Circle)& theOldEntity,
-  const Handle(StepGeom_Circle)& theNewEntity,
-  Handle(Standard_Transient)     theSharing)
-{
-  Handle(StepGeom_SeamCurve) aSharing = Handle(StepGeom_SeamCurve)::DownCast(theSharing);
-  if (aSharing->Curve3d() == theOldEntity)
-  {
-    aSharing->SetCurve3d(theNewEntity);
-    return true;
-  }
-  return false;
-}
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CircleProcessor.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_CircleProcessor.hxx
deleted file mode 100644 (file)
index f46c03a..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-// 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 _MergeSTEPEntities_CircleProcessor_HeaderFile
-#define _MergeSTEPEntities_CircleProcessor_HeaderFile
-
-#include <MergeSTEPEntities_EntityProcessor.hxx>
-#include <MergeSTEPEntities_CircleHasher.hxx>
-
-#include <StepGeom_Circle.hxx>
-
-//! Processor for merging StepGeom_Circle entities.
-//! This processor merges circles with the same position and radius and names.
-class MergeSTEPEntities_CircleProcessor
-    : public MergeSTEPEntities_EntityProcessor<StepGeom_Circle, MergeSTEPEntities_CircleHasher>
-{
-public:
-  //! Constructor. Stores the work session and registers replacer functions.
-  //! @param theWS the work session.
-  Standard_EXPORT MergeSTEPEntities_CircleProcessor(const Handle(XSControl_WorkSession)& theWS);
-
-private:
-  //! Replacer function for StepShape_EdgeCurve entities.
-  //! Replaces the old entity with the new one in the sharing entity.
-  //! @param theOldEntity the old entity to replace.
-  //! @param theNewEntity the new entity to replace with.
-  //! @param theSharing the sharing entity in which to replace the old entity.
-  //! @return true if the entity was replaced, false otherwise.
-  static bool replaceEdgeCurve(const Handle(StepGeom_Circle)& theOldEntity,
-                               const Handle(StepGeom_Circle)& theNewEntity,
-                               Handle(Standard_Transient)     theSharing);
-
-  //! Replacer function for StepGeom_SurfaceCurve entities.
-  //! Replaces the old entity with the new one in the sharing entity.
-  //! @param theOldEntity the old entity to replace.
-  //! @param theNewEntity the new entity to replace with.
-  //! @param theSharing the sharing entity in which to replace the old entity.
-  //! @return true if the entity was replaced, false otherwise.
-  static bool replaceSurfaceCurve(const Handle(StepGeom_Circle)& theOldEntity,
-                                  const Handle(StepGeom_Circle)& theNewEntity,
-                                  Handle(Standard_Transient)     theSharing);
-
-  //! Replacer function for StepGeom_SeamCurve entities.
-  //! Replaces the old entity with the new one in the sharing entity.
-  //! @param theOldEntity the old entity to replace.
-  //! @param theNewEntity the new entity to replace with.
-  //! @param theSharing the sharing entity in which to replace the old entity.
-  //! @return true if the entity was replaced, false otherwise.
-  static bool replaceSeamCurve(const Handle(StepGeom_Circle)& theOldEntity,
-                               const Handle(StepGeom_Circle)& theNewEntity,
-                               Handle(Standard_Transient)     theSharing);
-};
-
-#endif // _MergeSTEPEntities_CircleProcessor_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_DirectionHasher.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_DirectionHasher.hxx
deleted file mode 100644 (file)
index a9a93c5..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// 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 _MergeSTEPEntities_DirectionHasher_HeaderFile
-#define _MergeSTEPEntities_DirectionHasher_HeaderFile
-
-#include <Standard_HashUtils.hxx>
-#include <StepGeom_Direction.hxx>
-#include <TCollection_HAsciiString.hxx>
-
-//! OCCT-style hasher for StepGeom_Direction entities.
-struct MergeSTEPEntities_DirectionHasher
-{
-  // Hashes the direction by its name and direction ratios.
-  std::size_t operator()(const Handle(StepGeom_Direction)& theDirection) const noexcept
-  {
-    // Prepare an array of direction ratios.
-    const Handle(TColStd_HArray1OfReal) aCoords = theDirection->DirectionRatios();
-    int                                 anArray[3]{};
-    for (int anIndex = aCoords->Lower(); anIndex < aCoords->Upper(); ++anIndex)
-    {
-      anArray[anIndex] = static_cast<int>(aCoords->Value(anIndex));
-    }
-    // If direction has no name, hash only direction ratios.
-    if (theDirection->Name().IsNull())
-    {
-      return opencascade::hashBytes(anArray, sizeof(anArray));
-    }
-    // Otherwise, hash both direction ratios and name.
-    const size_t aHashes[2]{opencascade::hashBytes(anArray, sizeof(anArray)),
-                            std::hash<TCollection_AsciiString>{}(theDirection->Name()->String())};
-    return opencascade::hashBytes(aHashes, sizeof(aHashes));
-  }
-
-  // Compares two directions by their names and direction ratios.
-  bool operator()(const Handle(StepGeom_Direction)& theDirection1,
-                  const Handle(StepGeom_Direction)& theDirection2) const noexcept
-  {
-    // Compare names.
-    if (theDirection1->Name().IsNull() != theDirection2->Name().IsNull())
-    {
-      return false;
-    }
-    if (!theDirection1->Name()->IsSameString(theDirection2->Name()))
-    {
-      return false;
-    }
-
-    // Compare coordinates.
-    constexpr double                    aTolerance = 1e-12;
-    const Handle(TColStd_HArray1OfReal) aCoords1   = theDirection1->DirectionRatios();
-    const Handle(TColStd_HArray1OfReal) aCoords2   = theDirection2->DirectionRatios();
-    if (aCoords1->Length() != aCoords2->Length())
-    {
-      return false;
-    }
-    for (Standard_Integer i = aCoords1->Lower(); i <= aCoords1->Upper(); ++i)
-    {
-      if (std::abs(aCoords1->Value(i) - aCoords2->Value(i)) > aTolerance)
-      {
-        return false;
-      }
-    }
-    return true;
-  }
-};
-
-#endif // _MergeSTEPEntities_DirectionHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_DirectionProcessor.cxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_DirectionProcessor.cxx
deleted file mode 100644 (file)
index c561818..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-// 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.
-
-// 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.
-
-#include <MergeSTEPEntities_DirectionProcessor.hxx>
-
-#include <Interface_Graph.hxx>
-#include <StepGeom_Axis1Placement.hxx>
-#include <StepGeom_Axis2Placement3d.hxx>
-#include <StepGeom_Vector.hxx>
-
-//==================================================================================================
-
-MergeSTEPEntities_DirectionProcessor::MergeSTEPEntities_DirectionProcessor(
-  const Handle(XSControl_WorkSession)& theWS)
-    : MergeSTEPEntities_EntityProcessor<StepGeom_Direction, MergeSTEPEntities_DirectionHasher>(
-        theWS)
-{
-  registerReplacer(STANDARD_TYPE(StepGeom_Axis1Placement), replaceAxis1Placement);
-  registerReplacer(STANDARD_TYPE(StepGeom_Axis2Placement3d), replaceAxis2Placement3d);
-  registerReplacer(STANDARD_TYPE(StepGeom_Vector), replaceVector);
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_DirectionProcessor::replaceAxis1Placement(
-  const Handle(StepGeom_Direction)& theOldEntity,
-  const Handle(StepGeom_Direction)& theNewEntity,
-  Handle(Standard_Transient)        theSharing)
-{
-  Handle(StepGeom_Axis1Placement) aSharing = Handle(StepGeom_Axis1Placement)::DownCast(theSharing);
-  if (aSharing->Axis() == theOldEntity)
-  {
-    aSharing->SetAxis(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_DirectionProcessor::replaceAxis2Placement3d(
-  const Handle(StepGeom_Direction)& theOldEntity,
-  const Handle(StepGeom_Direction)& theNewEntity,
-  Handle(Standard_Transient)        theSharing)
-{
-  Handle(StepGeom_Axis2Placement3d) aSharing =
-    Handle(StepGeom_Axis2Placement3d)::DownCast(theSharing);
-  if (aSharing->Axis() == theOldEntity)
-  {
-    aSharing->SetAxis(theNewEntity);
-    return true;
-  }
-  else if (aSharing->RefDirection() == theOldEntity)
-  {
-    aSharing->SetRefDirection(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_DirectionProcessor::replaceVector(
-  const Handle(StepGeom_Direction)& theOldEntity,
-  const Handle(StepGeom_Direction)& theNewEntity,
-  Handle(Standard_Transient)        theSharing)
-{
-  Handle(StepGeom_Vector) aSharing = Handle(StepGeom_Vector)::DownCast(theSharing);
-  if (aSharing->Orientation() == theOldEntity)
-  {
-    aSharing->SetOrientation(theNewEntity);
-    return true;
-  }
-  return false;
-}
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_DirectionProcessor.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_DirectionProcessor.hxx
deleted file mode 100644 (file)
index 2e69e5a..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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 _MergeSTEPEntities_DirectionProcessor_HeaderFile
-#define _MergeSTEPEntities_DirectionProcessor_HeaderFile
-
-#include <MergeSTEPEntities_EntityProcessor.hxx>
-#include <MergeSTEPEntities_DirectionHasher.hxx>
-
-#include <StepGeom_Direction.hxx>
-
-//! Processor for merging StepGeom_Direction entities.
-//! This processor merges directions with the same direction ratios and names.
-//! The processor replaces all occurrences of the old directions with the new ones.
-//! The processor does not remove old directions from the model.
-//! See MergeSTEPEntities_EntityProcessor for the description of the processor workflow.
-class MergeSTEPEntities_DirectionProcessor
-    : public MergeSTEPEntities_EntityProcessor<StepGeom_Direction,
-                                               MergeSTEPEntities_DirectionHasher>
-{
-public:
-  //! Constructor. Stores the work session and registers replacer functions.
-  //! @param theWS the work session.
-  Standard_EXPORT MergeSTEPEntities_DirectionProcessor(const Handle(XSControl_WorkSession)& theWS);
-
-private:
-  //! Replaces the old direction with the new one in the StepGeom_Axis1Placement entity.
-  //! @param theOldEntity the old direction.
-  //! @param theNewEntity the new direction.
-  //! @param theSharing the StepGeom_Axis1Placement entity to update.
-  //! @return true if the direction was replaced, false otherwise.
-  static bool replaceAxis1Placement(const Handle(StepGeom_Direction)& theOldEntity,
-                                    const Handle(StepGeom_Direction)& theNewEntity,
-                                    Handle(Standard_Transient)        theSharing);
-
-  //! Replaces the old direction with the new one in the StepGeom_Axis2Placement3d entity.
-  //! @param theOldEntity the old direction.
-  //! @param theNewEntity the new direction.
-  //! @param theSharing the StepGeom_Axis2Placement3d entity to update.
-  //! @return true if the direction was replaced, false otherwise.
-  static bool replaceAxis2Placement3d(const Handle(StepGeom_Direction)& theOldEntity,
-                                      const Handle(StepGeom_Direction)& theNewEntity,
-                                      Handle(Standard_Transient)        theSharing);
-
-  //! Replaces the old direction with the new one in the StepGeom_Vector entity.
-  //! @param theOldEntity the old direction.
-  //! @param theNewEntity the new direction.
-  //! @param theSharing the StepGeom_Vector entity to update.
-  //! @return true if the direction was replaced, false otherwise.
-  static bool replaceVector(const Handle(StepGeom_Direction)& theOldEntity,
-                            const Handle(StepGeom_Direction)& theNewEntity,
-                            Handle(Standard_Transient)        theSharing);
-};
-
-#endif // _MergeSTEPEntities_DirectionProcessor_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_EntityProcessor.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_EntityProcessor.hxx
deleted file mode 100644 (file)
index 66f1f03..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-// 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 _MergeSTEPEntities_EntityProcessor_HeaderFile
-#define _MergeSTEPEntities_EntityProcessor_HeaderFile
-
-#include <Interface_Graph.hxx>
-#include <NCollection_Allocator.hxx>
-#include <NCollection_DataMap.hxx>
-#include <Standard_HashUtils.hxx>
-#include <XSControl_WorkSession.hxx>
-#include <TColStd_MapOfTransient.hxx>
-
-#include <functional>
-
-//! Base class for removing duplicate entities.
-//! Implements the logic of processing entities and removing duplicates.
-//! Child classes should only implement and register replacer functions
-//! for each specific type of sharing entity.
-//! How to use:
-//! 1. Create an instance of the child class.
-//! 2. Add entities to the processor using ProcessEntity() method. Entities
-//!    that can be merged will be stored in the internal map, others will be ignored.
-//! 3. Call Perform() method to replace duplicate entities. After this call
-//!    all duplicate entities will be replaced in a model with the first processed entity
-//!    that is evaluated as equal to them.
-//!    IMPORTANT: Duplicated entities will be replaced but not removed from the model!
-//! 4. Call GetReplacedEntities() to get a list of replaced duplicates. This list can be used
-//!    to remove entities from the model.
-//! @tparam ProcessedType Type of the processed entities.
-//! @tparam ProcessedTypeHasher OCCT-Style hasher for the processed entities.
-template <typename ProcessedType, typename ProcessedTypeHasher>
-class MergeSTEPEntities_EntityProcessor
-{
-protected:
-  // Map of duplicate entities. Key is the first processed entity, value is a list of duplicates.
-  using DuplicateMap = NCollection_DataMap<Handle(ProcessedType),
-                                           std::vector<Handle(ProcessedType)>,
-                                           ProcessedTypeHasher>;
-  // Function to replace an entity in sharings. First argument is the old entity, second is the new
-  // entity, third is the sharing in which the entity should be replaced. Returns true if the entity
-  // was replaced, false otherwise.
-  using ReplacerFunction = std::function<bool(const Handle(ProcessedType)&,
-                                              const Handle(ProcessedType)&,
-                                              const Handle(Standard_Transient))>;
-  // Map of replacer functions. Key is the type of the sharing entity, value is the replacer
-  // function for this type.
-  using ReplacerMap = NCollection_DataMap<Handle(Standard_Type), ReplacerFunction>;
-
-protected:
-  //! Constructor. Accepts a work session containing the model to process.
-  //! Protected to prevent direct instantiation of the base class. Only child classes should be
-  //! allowed to instantiate.
-  //! @param theWS Work session.
-  MergeSTEPEntities_EntityProcessor(const Handle(XSControl_WorkSession)& theWS);
-
-public:
-  //! Function to process an entity. If the entity can be merged, it will be stored in the internal
-  //! map. If the entity cannot be merged, it will be ignored.
-  //! Entity can only be processed if:
-  //! 1. The type of entity is ProcessedType.
-  //! 2. All sharings of the entity have a registered replacer function.
-  //! @param theEntity Entity to process.
-  //! @return True if the entity was processed, false if it was ignored.
-  Standard_EXPORT bool ProcessEntity(const Handle(Standard_Transient)& theEntity);
-
-  //! Function to replace duplicate entities. After this call, all duplicate entities will be
-  //! replaced with the first processed entity that is evaluated as equal to them.
-  //! IMPORTANT: Duplicated entities will be replaced but not removed from the model!
-  //! @param theReplacedEntities List where replaced entities will be stored.
-  //!        This list can be used to remove entities from the model.
-  Standard_EXPORT void Perform(TColStd_MapOfTransient& theReplacedEntities);
-
-protected:
-  //! Register a replacer function for a specific type of sharing entity.
-  //! Should be used by child classes to register replacer functions for each specific type of
-  //! sharing entity. If a sharing entity of the specified type is encountered during processing,
-  //! the registered replacer function will be called to replace the old entity with the new one.
-  //! All replacers must be registered before calling ProcessEntity() method.
-  //! @param theType Type of the sharing entity.
-  //! @param theReplacer Replacer function.
-  void registerReplacer(const Handle(Standard_Type)& theType, const ReplacerFunction& theReplacer);
-
-public:
-  //! Checks if all sharings have registered replacers for their types.
-  //! @param theSharings List of sharings to check.
-  //! @return True if all sharings have registered replacers, false otherwise.
-  bool hasAllReplacers(const Handle(TColStd_HSequenceOfTransient)& theSharings) const;
-
-  //! Replaces an old entity with a new entity in sharings.
-  //! Should only be called if all sharings have registered replacers.
-  //! @param theOldEntity Old entity to replace.
-  //! @param theNewEntity New entity to replace old entity with.
-  //! @param theSharings List of old entity sharings to replace the entity in.
-  //! @return True if all entities were replaced, false if at least one entity was not replaced.
-  bool replaceInSharings(const Handle(ProcessedType)&                theOldEntity,
-                         const Handle(ProcessedType)&                theNewEntity,
-                         const Handle(TColStd_HSequenceOfTransient)& theSharings) const;
-
-private:
-  Handle(XSControl_WorkSession) myWS;           //!< Work session.
-  ReplacerMap                   myReplacerMap;  //!< Map of replacer functions.
-  DuplicateMap                  myDuplicateMap; //!< Map of duplicate entities.
-};
-
-//==================================================================================================
-
-template <typename ProcessedType, typename ProcessedTypeHasher>
-MergeSTEPEntities_EntityProcessor<ProcessedType, ProcessedTypeHasher>::
-  MergeSTEPEntities_EntityProcessor(const Handle(XSControl_WorkSession)& theWS)
-    : myWS(theWS),
-      myReplacerMap(),
-      myDuplicateMap()
-{
-}
-
-//==================================================================================================
-
-template <typename ProcessedType, typename ProcessedTypeHasher>
-bool MergeSTEPEntities_EntityProcessor<ProcessedType, ProcessedTypeHasher>::ProcessEntity(
-  const Handle(Standard_Transient)& theEntity)
-{
-  const Handle(ProcessedType) anEntity = Handle(ProcessedType)::DownCast(theEntity);
-  if (anEntity.IsNull())
-  {
-    return false;
-  }
-  const Interface_Graph&                     aGraph    = myWS->Graph();
-  const Handle(TColStd_HSequenceOfTransient) aSharings = aGraph.GetSharings(anEntity);
-  if (hasAllReplacers(aSharings))
-  {
-    std::vector<Handle(ProcessedType)>* anIter = myDuplicateMap.ChangeSeek(anEntity);
-    if (anIter == nullptr)
-    {
-      // Add as a new key.
-      myDuplicateMap.Bind(anEntity, std::vector<Handle(ProcessedType)>{});
-    }
-    else
-    {
-      // Add as a value.
-      anIter->push_back(anEntity);
-    }
-  }
-
-  return true;
-}
-
-//==================================================================================================
-
-template <typename ProcessedType, typename ProcessedTypeHasher>
-void MergeSTEPEntities_EntityProcessor<ProcessedType, ProcessedTypeHasher>::Perform(
-  TColStd_MapOfTransient& theReplacedEntities)
-{
-  for (typename DuplicateMap::Iterator anIter(myDuplicateMap); anIter.More(); anIter.Next())
-  {
-    const Handle(ProcessedType)&              anEntity    = anIter.Key();
-    const std::vector<Handle(ProcessedType)>& aDuplicates = anIter.Value();
-    if (aDuplicates.empty())
-    {
-      continue;
-    }
-
-    const Interface_Graph& aGraph = myWS->Graph();
-    for (const auto& aDuplicate : aDuplicates)
-    {
-      Handle(TColStd_HSequenceOfTransient) aSharings = aGraph.GetSharings(aDuplicate);
-      if (aSharings.IsNull())
-      {
-        continue;
-      }
-
-      if (replaceInSharings(aDuplicate, anEntity, aSharings))
-      {
-        theReplacedEntities.Add(aDuplicate);
-      }
-    }
-  }
-}
-
-//==================================================================================================
-
-template <typename ProcessedType, typename ProcessedTypeHasher>
-void MergeSTEPEntities_EntityProcessor<ProcessedType, ProcessedTypeHasher>::registerReplacer(
-  const Handle(Standard_Type)& theType,
-  const ReplacerFunction&      theReplacer)
-{
-  myReplacerMap.Bind(theType, theReplacer);
-}
-
-//==================================================================================================
-
-template <typename ProcessedType, typename ProcessedTypeHasher>
-bool MergeSTEPEntities_EntityProcessor<ProcessedType, ProcessedTypeHasher>::hasAllReplacers(
-  const Handle(TColStd_HSequenceOfTransient)& theSharings) const
-{
-  if (theSharings.IsNull())
-  {
-    return false;
-  }
-  return std::all_of(theSharings->cbegin(),
-                     theSharings->cend(),
-                     [this](const Handle(Standard_Transient)& theSharing) {
-                       return myReplacerMap.IsBound(theSharing->DynamicType());
-                     });
-}
-
-//==================================================================================================
-template <typename ProcessedType, typename ProcessedTypeHasher>
-bool MergeSTEPEntities_EntityProcessor<ProcessedType, ProcessedTypeHasher>::replaceInSharings(
-  const Handle(ProcessedType)&                theOldEntity,
-  const Handle(ProcessedType)&                theNewEntity,
-  const Handle(TColStd_HSequenceOfTransient)& theSharings) const
-{
-  bool isAllReplaced = true;
-  for (const auto& aSharing : *theSharings)
-  {
-    if (aSharing.IsNull())
-    {
-      continue;
-    }
-
-    const ReplacerFunction& aReplacer = myReplacerMap.Find(aSharing->DynamicType());
-    if (!aReplacer(theOldEntity, theNewEntity, aSharing))
-    {
-      isAllReplaced = false;
-    }
-  }
-  return isAllReplaced;
-}
-
-#endif // _MergeSTEPEntities_EntityProcessor_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_LineHasher.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_LineHasher.hxx
deleted file mode 100644 (file)
index 3533d55..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// 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 _MergeSTEPEntities_LineHasher_HeaderFile
-#define _MergeSTEPEntities_LineHasher_HeaderFile
-
-#include <MergeSTEPEntities_CartesianPointHasher.hxx>
-#include <MergeSTEPEntities_VectorHasher.hxx>
-
-#include <Standard_HashUtils.hxx>
-#include <StepGeom_Line.hxx>
-#include <TCollection_HAsciiString.hxx>
-
-//! OCCT-style hasher for StepGeom_Line entities.
-struct MergeSTEPEntities_LineHasher
-{
-  // Hashes the Line by its name and Line ratios.
-  std::size_t operator()(const Handle(StepGeom_Line)& theLine) const noexcept
-  {
-    const size_t aHashes[2]{MergeSTEPEntities_CartesianPointHasher{}(theLine->Pnt()),
-                            MergeSTEPEntities_VectorHasher{}(theLine->Dir())};
-
-    const size_t aCombinedHash = opencascade::hashBytes(aHashes, sizeof(aHashes));
-    if (theLine->Name().IsNull())
-    {
-      // If the name is not present, return the hash.
-      return aCombinedHash;
-    }
-    // Add the name to the hash if it is present.
-    const size_t aCombinedHashWithName[2]{
-      aCombinedHash,
-      std::hash<TCollection_AsciiString>{}(theLine->Name()->String())};
-    return opencascade::hashBytes(aCombinedHashWithName, sizeof(aCombinedHashWithName));
-  }
-
-  // Compares two Lines by their names and Line ratios.
-  bool operator()(const Handle(StepGeom_Line)& theLine1,
-                  const Handle(StepGeom_Line)& theLine2) const noexcept
-
-  {
-    // Compare names.
-    if (theLine1->Name().IsNull() != theLine2->Name().IsNull())
-    {
-      return false;
-    }
-    if (!theLine1->Name()->IsSameString(theLine2->Name()))
-    {
-      return false;
-    }
-
-    // Compare points.
-    if (!MergeSTEPEntities_CartesianPointHasher{}(theLine1->Pnt(), theLine2->Pnt()))
-    {
-      return false;
-    }
-
-    // Compare directions.
-    if (!MergeSTEPEntities_VectorHasher{}(theLine1->Dir(), theLine2->Dir()))
-    {
-      return false;
-    }
-
-    return true;
-  }
-};
-
-#endif // _MergeSTEPEntities_LineHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_LineProcessor.cxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_LineProcessor.cxx
deleted file mode 100644 (file)
index 03f9d02..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-// 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.
-
-// 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.
-
-#include <MergeSTEPEntities_LineProcessor.hxx>
-
-#include <Interface_Graph.hxx>
-#include <StepShape_EdgeCurve.hxx>
-#include <StepGeom_TrimmedCurve.hxx>
-#include <StepGeom_SurfaceCurve.hxx>
-#include <StepRepr_DefinitionalRepresentation.hxx>
-#include <StepGeom_SeamCurve.hxx>
-
-//==================================================================================================
-
-MergeSTEPEntities_LineProcessor::MergeSTEPEntities_LineProcessor(
-  const Handle(XSControl_WorkSession)& theWS)
-    : MergeSTEPEntities_EntityProcessor<StepGeom_Line, MergeSTEPEntities_LineHasher>(theWS)
-{
-  registerReplacer(STANDARD_TYPE(StepShape_EdgeCurve), replaceEdgeCurve);
-  registerReplacer(STANDARD_TYPE(StepGeom_TrimmedCurve), replaceTrimmedCurve);
-  registerReplacer(STANDARD_TYPE(StepGeom_SurfaceCurve), replaceSurfaceCurve);
-  registerReplacer(STANDARD_TYPE(StepRepr_DefinitionalRepresentation),
-                   replaceDefinitionalRepresentation);
-  registerReplacer(STANDARD_TYPE(StepGeom_SeamCurve), replaceSeamCurve);
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_LineProcessor::replaceEdgeCurve(const Handle(StepGeom_Line)& theOldEntity,
-                                                       const Handle(StepGeom_Line)& theNewEntity,
-                                                       Handle(Standard_Transient)   theSharing)
-{
-  Handle(StepShape_EdgeCurve) aSharing = Handle(StepShape_EdgeCurve)::DownCast(theSharing);
-  if (aSharing->EdgeGeometry() == theOldEntity)
-  {
-    aSharing->SetEdgeGeometry(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_LineProcessor::replaceTrimmedCurve(const Handle(StepGeom_Line)& theOldEntity,
-                                                          const Handle(StepGeom_Line)& theNewEntity,
-                                                          Handle(Standard_Transient)   theSharing)
-{
-  Handle(StepGeom_TrimmedCurve) aSharing = Handle(StepGeom_TrimmedCurve)::DownCast(theSharing);
-  if (aSharing->BasisCurve() == theOldEntity)
-  {
-    aSharing->SetBasisCurve(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_LineProcessor::replaceSurfaceCurve(const Handle(StepGeom_Line)& theOldEntity,
-                                                          const Handle(StepGeom_Line)& theNewEntity,
-                                                          Handle(Standard_Transient)   theSharing)
-{
-  Handle(StepGeom_SurfaceCurve) aSharing = Handle(StepGeom_SurfaceCurve)::DownCast(theSharing);
-  if (aSharing->Curve3d() == theOldEntity)
-  {
-    aSharing->SetCurve3d(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_LineProcessor::replaceDefinitionalRepresentation(
-  const Handle(StepGeom_Line)& theOldEntity,
-  const Handle(StepGeom_Line)& theNewEntity,
-  Handle(Standard_Transient)   theSharing)
-{
-  Handle(StepRepr_DefinitionalRepresentation) aSharing =
-    Handle(StepRepr_DefinitionalRepresentation)::DownCast(theSharing);
-  bool                                         isReplaced = false;
-  Handle(StepRepr_HArray1OfRepresentationItem) anItems    = aSharing->Items();
-  for (Standard_Integer anIndex = 1; anIndex <= aSharing->NbItems(); ++anIndex)
-  {
-    const Handle(StepRepr_RepresentationItem) aRepItem = anItems->Value(anIndex);
-    if (aRepItem == theOldEntity)
-    {
-      anItems->SetValue(anIndex, theNewEntity);
-      isReplaced = true;
-    }
-  }
-  return isReplaced;
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_LineProcessor::replaceSeamCurve(const Handle(StepGeom_Line)& theOldEntity,
-                                                       const Handle(StepGeom_Line)& theNewEntity,
-                                                       Handle(Standard_Transient)   theSharing)
-{
-  Handle(StepGeom_SeamCurve) aSharing = Handle(StepGeom_SeamCurve)::DownCast(theSharing);
-  if (aSharing->Curve3d() == theOldEntity)
-  {
-    aSharing->SetCurve3d(theNewEntity);
-    return true;
-  }
-  return false;
-}
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_LineProcessor.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_LineProcessor.hxx
deleted file mode 100644 (file)
index 791ef42..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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 _MergeSTEPEntities_LineProcessor_HeaderFile
-#define _MergeSTEPEntities_LineProcessor_HeaderFile
-
-#include <MergeSTEPEntities_EntityProcessor.hxx>
-#include <MergeSTEPEntities_LineHasher.hxx>
-
-#include <StepGeom_Line.hxx>
-
-//! Processor for merging StepGeom_Line entities.
-//! This processor merges lines with the same point and direction and names.
-class MergeSTEPEntities_LineProcessor
-    : public MergeSTEPEntities_EntityProcessor<StepGeom_Line, MergeSTEPEntities_LineHasher>
-{
-public:
-  //! Constructor. Stores the work session and registers replacer functions.
-  //! @param theWS the work session.
-  Standard_EXPORT MergeSTEPEntities_LineProcessor(const Handle(XSControl_WorkSession)& theWS);
-
-private:
-  //! Replacer function for StepShape_EdgeCurve entities.
-  //! Replaces the old entity with the new one in the sharing entity.
-  //! @param theOldEntity the old entity to replace.
-  //! @param theNewEntity the new entity to replace with.
-  //! @param theSharing the sharing entity in which to replace the old entity.
-  //! @return true if the entity was replaced, false otherwise.
-  static bool replaceEdgeCurve(const Handle(StepGeom_Line)& theOldEntity,
-                               const Handle(StepGeom_Line)& theNewEntity,
-                               Handle(Standard_Transient)   theSharing);
-
-  //! Replacer function for StepGeom_TrimmedCurve entities.
-  //! Replaces the old entity with the new one in the sharing entity.
-  //! @param theOldEntity the old entity to replace.
-  //! @param theNewEntity the new entity to replace with.
-  //! @param theSharing the sharing entity in which to replace the old entity.
-  //! @return true if the entity was replaced, false otherwise.
-  static bool replaceTrimmedCurve(const Handle(StepGeom_Line)& theOldEntity,
-                                  const Handle(StepGeom_Line)& theNewEntity,
-                                  Handle(Standard_Transient)   theSharing);
-
-  //! Replacer function for StepGeom_SurfaceCurve entities.
-  //! Replaces the old entity with the new one in the sharing entity.
-  //! @param theOldEntity the old entity to replace.
-  //! @param theNewEntity the new entity to replace with.
-  //! @param theSharing the sharing entity in which to replace the old entity.
-  //! @return true if the entity was replaced, false otherwise.
-  static bool replaceSurfaceCurve(const Handle(StepGeom_Line)& theOldEntity,
-                                  const Handle(StepGeom_Line)& theNewEntity,
-                                  Handle(Standard_Transient)   theSharing);
-
-  //! Replacer function for StepRepr_DefinitionalRepresentation entities.
-  //! Replaces the old entity with the new one in the sharing entity.
-  //! @param theOldEntity the old entity to replace.
-  //! @param theNewEntity the new entity to replace with.
-  //! @param theSharing the sharing entity in which to replace the old entity.
-  //! @return true if the entity was replaced, false otherwise.
-  static bool replaceDefinitionalRepresentation(const Handle(StepGeom_Line)& theOldEntity,
-                                                const Handle(StepGeom_Line)& theNewEntity,
-                                                Handle(Standard_Transient)   theSharing);
-
-  //! Replacer function for StepGeom_SeamCurve entities.
-  //! Replaces the old entity with the new one in the sharing entity.
-  //! @param theOldEntity the old entity to replace.
-  //! @param theNewEntity the new entity to replace with.
-  //! @param theSharing the sharing entity in which to replace the old entity.
-  //! @return true if the entity was replaced, false otherwise.
-  static bool replaceSeamCurve(const Handle(StepGeom_Line)& theOldEntity,
-                               const Handle(StepGeom_Line)& theNewEntity,
-                               Handle(Standard_Transient)   theSharing);
-};
-
-#endif // _MergeSTEPEntities_LineProcessor_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Merger.cxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Merger.cxx
deleted file mode 100644 (file)
index 044c985..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-// 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.
-
-#include <MergeSTEPEntities_Merger.hxx>
-
-#include <Interface_EntityIterator.hxx>
-#include <Interface_Graph.hxx>
-#include <MergeSTEPEntities_Axis2Placement3dProcessor.hxx>
-#include <MergeSTEPEntities_CartesianPointProcessor.hxx>
-#include <MergeSTEPEntities_DirectionProcessor.hxx>
-#include <MergeSTEPEntities_LineProcessor.hxx>
-#include <MergeSTEPEntities_VectorProcessor.hxx>
-#include <MergeSTEPEntities_PlaneProcessor.hxx>
-#include <MergeSTEPEntities_CircleProcessor.hxx>
-#include <StepData_StepModel.hxx>
-
-//==================================================================================================
-
-MergeSTEPEntities_Merger::MergeSTEPEntities_Merger(Handle(XSControl_WorkSession) theWS)
-    : myWS(theWS)
-{
-}
-
-//==================================================================================================
-
-void MergeSTEPEntities_Merger::Perform()
-{
-  Handle(StepData_StepModel) aModel = Handle(StepData_StepModel)::DownCast(myWS->Model());
-  if (aModel.IsNull())
-  {
-    return;
-  }
-
-  //! Initialize processors.
-  MergeSTEPEntities_CartesianPointProcessor   aCartesianPointProcessor(myWS);
-  MergeSTEPEntities_DirectionProcessor        aDirectionProcessor(myWS);
-  MergeSTEPEntities_Axis2Placement3dProcessor aAxis2Placement3dProcessor(myWS);
-  MergeSTEPEntities_VectorProcessor           aVectorProcessor(myWS);
-  MergeSTEPEntities_LineProcessor             aLineProcessor(myWS);
-  MergeSTEPEntities_PlaneProcessor            aPlaneProcessor(myWS);
-  MergeSTEPEntities_CircleProcessor           aCircleProcessor(myWS);
-
-  // Process all entities.
-  for (Standard_Integer anIndex = 1; anIndex <= aModel->NbEntities(); ++anIndex)
-  {
-    const Handle(Standard_Transient) anEntity = aModel->Value(anIndex);
-    aCartesianPointProcessor.ProcessEntity(anEntity);
-    aDirectionProcessor.ProcessEntity(anEntity);
-    aAxis2Placement3dProcessor.ProcessEntity(anEntity);
-    aVectorProcessor.ProcessEntity(anEntity);
-    aLineProcessor.ProcessEntity(anEntity);
-    aPlaneProcessor.ProcessEntity(anEntity);
-    aCircleProcessor.ProcessEntity(anEntity);
-  }
-
-  // Perform replacement of duplicate entities.
-  TColStd_MapOfTransient aReplacedEntities;
-  aCartesianPointProcessor.Perform(aReplacedEntities);
-  aDirectionProcessor.Perform(aReplacedEntities);
-  aAxis2Placement3dProcessor.Perform(aReplacedEntities);
-  aVectorProcessor.Perform(aReplacedEntities);
-  aLineProcessor.Perform(aReplacedEntities);
-  aPlaneProcessor.Perform(aReplacedEntities);
-  aCircleProcessor.Perform(aReplacedEntities);
-
-  // Remove duplicate entities.
-  removeEntities(aReplacedEntities);
-}
-
-//==================================================================================================
-
-void MergeSTEPEntities_Merger::removeEntities(const TColStd_MapOfTransient& theToRemove)
-{
-  if (theToRemove.IsEmpty())
-  {
-    return;
-  }
-  // Remove entities.
-  Handle(StepData_StepModel) anIntermediateModel = new StepData_StepModel();
-  Handle(StepData_StepModel) aReadModel = Handle(StepData_StepModel)::DownCast(myWS->Model());
-  anIntermediateModel->SetProtocol(aReadModel->Protocol());
-  anIntermediateModel->SetGTool(aReadModel->GTool());
-
-  for (Standard_Integer i = 1; i <= aReadModel->NbEntities(); i++)
-  {
-    const Handle(Standard_Transient)& anEnt = aReadModel->Value(i);
-    if (!theToRemove.Contains(anEnt))
-    {
-      anIntermediateModel->AddWithRefs(anEnt);
-    }
-  }
-
-  myWS->SetModel(anIntermediateModel);
-  myWS->ComputeGraph();
-
-  // Clean hanged entities.
-  Handle(StepData_StepModel) aNewModel = new StepData_StepModel();
-  aNewModel->SetProtocol(anIntermediateModel->Protocol());
-  aNewModel->SetGTool(anIntermediateModel->GTool());
-  const auto& aGraph = myWS->Graph();
-
-  for (Standard_Integer i = 1; i <= anIntermediateModel->NbEntities(); i++)
-  {
-    const Handle(Standard_Transient)& anEnt = anIntermediateModel->Value(i);
-    if (aGraph.Shareds(anEnt).NbEntities() > 0 || aGraph.Sharings(anEnt).NbEntities() > 0)
-    {
-      aNewModel->AddWithRefs(anEnt);
-    }
-  }
-
-  myWS->SetModel(aNewModel);
-  myWS->ComputeGraph();
-}
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Merger.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_Merger.hxx
deleted file mode 100644 (file)
index 436ea41..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// 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 _MergeSTEPEntities_Merger_HeaderFile
-#define _MergeSTEPEntities_Merger_HeaderFile
-
-#include <TColStd_MapOfTransient.hxx>
-
-class XSControl_WorkSession;
-
-//! A class to merge STEP entities.
-//! This class is used to merge equal STEP entities in the work session and remove duplicates.
-//! More detailed information about merging entities cam be found in
-//! MergeSTEPEntities_EntityProcessor class and its descendants.
-class MergeSTEPEntities_Merger
-{
-public:
-  //! Constructor.
-  //! @param theWS the work session to merge entities in.
-  Standard_EXPORT MergeSTEPEntities_Merger(Handle(XSControl_WorkSession) theWS);
-
-  //! Perform the merging of entities.
-  //! All entities in a model stored in the provided work session that are considered equal to
-  //! each other will be merged, and duplicates will be removed.
-  Standard_EXPORT void Perform();
-
-private:
-  //! Remove entities from the work session.
-  //! @param theToRemove the entities to remove.
-  void removeEntities(const TColStd_MapOfTransient& theToRemove);
-
-private:
-  Handle(XSControl_WorkSession) myWS; //!< The work session containing the model with entities.
-};
-
-#endif // _MergeSTEPEntities_Merger_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_PlaneHasher.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_PlaneHasher.hxx
deleted file mode 100644 (file)
index 3e8ab9a..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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 _MergeSTEPEntities_PlaneHasher_HeaderFile
-#define _MergeSTEPEntities_PlaneHasher_HeaderFile
-
-#include <MergeSTEPEntities_Axis2Placement3dHasher.hxx>
-
-#include <Standard_HashUtils.hxx>
-#include <StepGeom_Plane.hxx>
-
-//! OCCT-style hasher for StepGeom_Plane entities.
-struct MergeSTEPEntities_PlaneHasher
-{
-  // Hashes the axis Planes.
-  std::size_t operator()(const Handle(StepGeom_Plane)& thePlane) const noexcept
-  {
-    const size_t aHash = MergeSTEPEntities_Axis2Placement3dHasher{}(thePlane->Position());
-    if (thePlane->Name().IsNull())
-    {
-      // If the name is not present, return the hash.
-      return aHash;
-    }
-    // Add the name to the hash if it is present.
-    const size_t aCombinedHashWithName[2]{
-      aHash,
-      std::hash<TCollection_AsciiString>{}(thePlane->Name()->String())};
-    return opencascade::hashBytes(aCombinedHashWithName, sizeof(aCombinedHashWithName));
-  }
-
-  // Compares two axis Planes.
-  bool operator()(const Handle(StepGeom_Plane)& thePlane1,
-                  const Handle(StepGeom_Plane)& thePlane2) const noexcept
-  {
-    // Compare names.
-    if (thePlane1->Name().IsNull() != thePlane2->Name().IsNull())
-    {
-      return false;
-    }
-    if (!thePlane1->Name()->IsSameString(thePlane2->Name()))
-    {
-      return false;
-    }
-
-    // Compare axis Planes.
-    return MergeSTEPEntities_Axis2Placement3dHasher{}(thePlane1->Position(), thePlane2->Position());
-  }
-};
-
-#endif // _MergeSTEPEntities_PlaneHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_PlaneProcessor.cxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_PlaneProcessor.cxx
deleted file mode 100644 (file)
index 24ec850..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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.
-
-#include <MergeSTEPEntities_PlaneProcessor.hxx>
-
-#include <StepShape_AdvancedFace.hxx>
-#include <StepGeom_Pcurve.hxx>
-
-//==================================================================================================
-
-MergeSTEPEntities_PlaneProcessor::MergeSTEPEntities_PlaneProcessor(
-  const Handle(XSControl_WorkSession)& theWS)
-    : MergeSTEPEntities_EntityProcessor<StepGeom_Plane, MergeSTEPEntities_PlaneHasher>(theWS)
-{
-  registerReplacer(STANDARD_TYPE(StepShape_AdvancedFace), replaceAdvancedFace);
-  registerReplacer(STANDARD_TYPE(StepGeom_Pcurve), replacePcurve);
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_PlaneProcessor::replaceAdvancedFace(
-  const Handle(StepGeom_Plane)& theOldEntity,
-  const Handle(StepGeom_Plane)& theNewEntity,
-  Handle(Standard_Transient)    theSharing)
-{
-  Handle(StepShape_AdvancedFace) aSharing = Handle(StepShape_AdvancedFace)::DownCast(theSharing);
-  if (aSharing->FaceGeometry() == theOldEntity)
-  {
-    aSharing->SetFaceGeometry(theNewEntity);
-    return true;
-  }
-  return false;
-}
-
-//==================================================================================================
-bool MergeSTEPEntities_PlaneProcessor::replacePcurve(const Handle(StepGeom_Plane)& theOldEntity,
-                                                     const Handle(StepGeom_Plane)& theNewEntity,
-                                                     Handle(Standard_Transient)    theSharing)
-{
-  Handle(StepGeom_Pcurve) aSharing = Handle(StepGeom_Pcurve)::DownCast(theSharing);
-  if (aSharing->BasisSurface() == theOldEntity)
-  {
-    aSharing->SetBasisSurface(theNewEntity);
-    return true;
-  }
-  return false;
-}
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_PlaneProcessor.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_PlaneProcessor.hxx
deleted file mode 100644 (file)
index 44dde07..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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 _MergeSTEPEntities_PlaneProcessor_HeaderFile
-#define _MergeSTEPEntities_PlaneProcessor_HeaderFile
-
-#include <MergeSTEPEntities_EntityProcessor.hxx>
-#include <MergeSTEPEntities_PlaneHasher.hxx>
-
-#include <StepGeom_Plane.hxx>
-
-//! Processor for merging StepGeom_Plane entities.
-//! This processor merges planes with the same names and placements.
-class MergeSTEPEntities_PlaneProcessor
-    : public MergeSTEPEntities_EntityProcessor<StepGeom_Plane, MergeSTEPEntities_PlaneHasher>
-{
-public:
-  //! Constructor. Stores the work session and registers replacer functions.
-  //! @param theWS the work session.
-  Standard_EXPORT MergeSTEPEntities_PlaneProcessor(const Handle(XSControl_WorkSession)& theWS);
-
-private:
-  //! Replacer function for StepShape_AdvancedFace entities.
-  //! Replaces the old entity with the new one in the sharing entity.
-  //! @param theOldEntity the old entity to replace.
-  //! @param theNewEntity the new entity to replace with.
-  //! @param theSharing the sharing StepShape_AdvancedFace in which to replace the old entity.
-  //! @return true if the entity was replaced, false otherwise.
-  static bool replaceAdvancedFace(const Handle(StepGeom_Plane)& theOldEntity,
-                                  const Handle(StepGeom_Plane)& theNewEntity,
-                                  Handle(Standard_Transient)    theSharing);
-
-  //! Replacer function for StepGeom_Pcurve entities.
-  //! Replaces the old entity with the new one in the sharing entity.
-  //! @param theOldEntity the old entity to replace.
-  //! @param theNewEntity the new entity to replace with.
-  //! @param theSharing the sharing StepGeom_Pcurve in which to replace the old entity.
-  //! @return true if the entity was replaced, false otherwise.
-  static bool replacePcurve(const Handle(StepGeom_Plane)& theOldEntity,
-                            const Handle(StepGeom_Plane)& theNewEntity,
-                            Handle(Standard_Transient)    theSharing);
-};
-
-#endif // _MergeSTEPEntities_DirectionProcessor_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_VectorHasher.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_VectorHasher.hxx
deleted file mode 100644 (file)
index 2144b1d..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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 _MergeSTEPEntities_VectorHasher_HeaderFile
-#define _MergeSTEPEntities_VectorHasher_HeaderFile
-
-#include <MergeSTEPEntities_DirectionHasher.hxx>
-
-#include <Standard_HashUtils.hxx>
-#include <StepGeom_Vector.hxx>
-#include <TCollection_HAsciiString.hxx>
-
-//! OCCT-style hasher for StepGeom_Vector entities.
-struct MergeSTEPEntities_VectorHasher
-{
-  // Hashes the Vector by its name and Vector ratios.
-  std::size_t operator()(const Handle(StepGeom_Vector)& theVector) const noexcept
-  {
-    const size_t aHashes[2]{MergeSTEPEntities_DirectionHasher{}(theVector->Orientation()),
-                            opencascade::hash(static_cast<int>(theVector->Magnitude()))};
-    const size_t aCombinedHash = opencascade::hashBytes(aHashes, sizeof(aHashes));
-    if (theVector->Name().IsNull())
-    {
-      // If the name is not present, return the hash.
-      return aCombinedHash;
-    }
-    // Add the name to the hash if it is present.
-    const size_t aCombinedHashWithName[2]{
-      aCombinedHash,
-      std::hash<TCollection_AsciiString>{}(theVector->Name()->String())};
-    return opencascade::hashBytes(aCombinedHashWithName, sizeof(aCombinedHashWithName));
-  }
-
-  // Compares two Vectors by their names and Vector ratios.
-  bool operator()(const Handle(StepGeom_Vector)& theVector1,
-                  const Handle(StepGeom_Vector)& theVector2) const noexcept
-  {
-    // Compare names.
-    if (theVector1->Name().IsNull() != theVector2->Name().IsNull())
-    {
-      return false;
-    }
-    if (!theVector1->Name()->IsSameString(theVector2->Name()))
-    {
-      return false;
-    }
-
-    // Compare magnitudes.
-    constexpr double aTolerance = 1e-12;
-    if (fabs(theVector1->Magnitude() - theVector2->Magnitude()) > aTolerance)
-    {
-      return false;
-    }
-
-    // Compare orientations.
-    return MergeSTEPEntities_DirectionHasher{}(theVector1->Orientation(),
-                                               theVector2->Orientation());
-  }
-};
-
-#endif // _MergeSTEPEntities_VectorHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_VectorProcessor.cxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_VectorProcessor.cxx
deleted file mode 100644 (file)
index 3eb340a..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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.
-
-// 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.
-
-#include <MergeSTEPEntities_VectorProcessor.hxx>
-
-#include <Interface_Graph.hxx>
-#include <StepGeom_Line.hxx>
-#include <StepGeom_Vector.hxx>
-
-//==================================================================================================
-
-MergeSTEPEntities_VectorProcessor::MergeSTEPEntities_VectorProcessor(
-  const Handle(XSControl_WorkSession)& theWS)
-    : MergeSTEPEntities_EntityProcessor<StepGeom_Vector, MergeSTEPEntities_VectorHasher>(theWS)
-{
-  registerReplacer(STANDARD_TYPE(StepGeom_Line), replaceLine);
-}
-
-//==================================================================================================
-
-bool MergeSTEPEntities_VectorProcessor::replaceLine(const Handle(StepGeom_Vector)& theOldEntity,
-                                                    const Handle(StepGeom_Vector)& theNewEntity,
-                                                    Handle(Standard_Transient)     theSharing)
-{
-  Handle(StepGeom_Line) aLine = Handle(StepGeom_Line)::DownCast(theSharing);
-  if (aLine->Dir() == theOldEntity)
-  {
-    aLine->SetDir(theNewEntity);
-    return true;
-  }
-  return false;
-}
diff --git a/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_VectorProcessor.hxx b/src/DataExchange/TKDESTEP/MergeSTEPEntities/MergeSTEPEntities_VectorProcessor.hxx
deleted file mode 100644 (file)
index 56d1986..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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 _MergeSTEPEntities_VectorProcessor_HeaderFile
-#define _MergeSTEPEntities_VectorProcessor_HeaderFile
-
-#include <MergeSTEPEntities_EntityProcessor.hxx>
-#include <MergeSTEPEntities_VectorHasher.hxx>
-
-#include <StepGeom_Vector.hxx>
-
-//! Processor for merging StepGeom_Vector entities.
-//! This processor merges vectors with the same orientation and magnitude and names.
-class MergeSTEPEntities_VectorProcessor
-    : public MergeSTEPEntities_EntityProcessor<StepGeom_Vector, MergeSTEPEntities_VectorHasher>
-{
-public:
-  //! Constructor. Stores the work session and registers replacer functions.
-  //! @param theWS the work session.
-  Standard_EXPORT MergeSTEPEntities_VectorProcessor(const Handle(XSControl_WorkSession)& theWS);
-
-private:
-  //! Replaces the old vector with the new one in the StepGeom_Line entity.
-  //! @param theOldEntity the old vector.
-  //! @param theNewEntity the new vector to replace the old one.
-  //! @param theSharing the StepGeom_Line entity to update.
-  //! @return true if the vector was replaced, false otherwise.
-  static bool replaceLine(const Handle(StepGeom_Vector)& theOldEntity,
-                          const Handle(StepGeom_Vector)& theNewEntity,
-                          Handle(Standard_Transient)     theSharing);
-};
-
-#endif // _MergeSTEPEntities_VectorProcessor_HeaderFile
index 356c180fb5d607f979625ba6f0bfde7975b2fcf6..6b3443ecc148d27ea300c8fd2feb447998fb1463 100644 (file)
@@ -41,5 +41,5 @@ set(OCCT_TKDESTEP_LIST_OF_PACKAGES
   APIHeaderSection
   HeaderSection
   DESTEP
-  MergeSTEPEntities
+  StepTidy
 )
index ede2a3d994b68ea8c399cc36b2d3f7d3c80df492..7db8774702846a85adafc99da6dfccb88f096a42 100644 (file)
@@ -312,6 +312,12 @@ void RWStepGeom_RWBSplineCurveWithKnots::Check(const Handle(StepGeom_BSplineCurv
   {
     ach->AddFail("ERROR: No.of KnotMultiplicities not equal No.of Knots");
   }
+  if (nbMult == 0)
+  {
+    ach->AddFail("ERROR: No.of KnotMultiplicities is equal to 0");
+    return;
+  }
+
   Standard_Integer i; // svv Jan 10 2000: porting on DEC
   for (i = 1; i <= nbMult - 1; i++)
   {
diff --git a/src/DataExchange/TKDESTEP/StepTidy/FILES.cmake b/src/DataExchange/TKDESTEP/StepTidy/FILES.cmake
new file mode 100644 (file)
index 0000000..c5447aa
--- /dev/null
@@ -0,0 +1,30 @@
+# Source files for StepTidy package
+set(OCCT_StepTidy_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
+
+set(OCCT_StepTidy_FILES
+  StepTidy_Axis2Placement2dHasher.pxx
+  StepTidy_Axis2Placement3dHasher.pxx
+  StepTidy_Axis2Placement3dReducer.cxx
+  StepTidy_Axis2Placement3dReducer.pxx
+  StepTidy_CartesianPointHasher.pxx
+  StepTidy_CartesianPointReducer.cxx
+  StepTidy_CartesianPointReducer.pxx
+  StepTidy_CircleHasher.pxx
+  StepTidy_CircleReducer.cxx
+  StepTidy_CircleReducer.pxx
+  StepTidy_DirectionHasher.pxx
+  StepTidy_DirectionReducer.cxx
+  StepTidy_DirectionReducer.pxx
+  StepTidy_EntityReducer.pxx
+  StepTidy_LineHasher.pxx
+  StepTidy_LineReducer.cxx
+  StepTidy_LineReducer.pxx
+  StepTidy_DuplicateCleaner.cxx
+  StepTidy_DuplicateCleaner.hxx
+  StepTidy_PlaneHasher.pxx
+  StepTidy_PlaneReducer.cxx
+  StepTidy_PlaneReducer.pxx
+  StepTidy_VectorHasher.pxx
+  StepTidy_VectorReducer.cxx
+  StepTidy_VectorReducer.pxx
+)
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement2dHasher.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement2dHasher.pxx
new file mode 100644 (file)
index 0000000..89420b2
--- /dev/null
@@ -0,0 +1,80 @@
+// 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 _StepTidy_Axis2Placement2dHasher_HeaderFile
+#define _StepTidy_Axis2Placement2dHasher_HeaderFile
+
+#include <StepTidy_CartesianPointHasher.pxx>
+#include <StepTidy_DirectionHasher.pxx>
+
+#include <Standard_HashUtils.hxx>
+#include <StepGeom_Axis2Placement2d.hxx>
+
+//! OCCT-style hasher for StepGeom_Axis2Placement2d entities.
+//! Currently only used for implementation of hasher for StepGeom_Circle.
+struct StepTidy_Axis2Placement2dHasher
+{
+  // Hashes the axis placements.
+  std::size_t operator()(const Handle(StepGeom_Axis2Placement2d)& thePlacement) const noexcept
+  {
+    // Prepare an array of hashes for the location, axis, and ref direction.
+    // Optimal seed is used for the axis and ref direction if they are not present.
+    const size_t aHashes[2]{StepTidy_CartesianPointHasher{}(thePlacement->Location()),
+                            thePlacement->HasRefDirection()
+                              ? StepTidy_DirectionHasher{}(thePlacement->RefDirection())
+                              : opencascade::MurmurHash::optimalSeed()};
+    const size_t aHash = opencascade::hashBytes(aHashes, sizeof(aHashes));
+    if (thePlacement->Name().IsNull())
+    {
+      // If the name is not present, return the hash.
+      return aHash;
+    }
+    // Add the name to the hash if it is present.
+    const size_t aHashWithName[2]{
+      aHash,
+      std::hash<TCollection_AsciiString>{}(thePlacement->Name()->String())};
+    return opencascade::hashBytes(aHashWithName, sizeof(aHashWithName));
+  }
+
+  // Compares two axis placements.
+  bool operator()(const Handle(StepGeom_Axis2Placement2d)& thePlacement1,
+                  const Handle(StepGeom_Axis2Placement2d)& thePlacement2) const noexcept
+  {
+    // Compare names.
+    if (thePlacement1->Name().IsNull() != thePlacement2->Name().IsNull())
+    {
+      return false;
+    }
+    if (!thePlacement1->Name()->IsSameString(thePlacement2->Name()))
+    {
+      return false;
+    }
+
+    // Compare location, axis, and ref direction.
+    const bool isSameLocation =
+      StepTidy_CartesianPointHasher{}(thePlacement1->Location(), thePlacement2->Location());
+    // Have to check if the axis is present and compare it.
+    // Have to check if the ref direction is present and compare it.
+    const bool isSameRefDirectionFlag =
+      thePlacement1->HasRefDirection() == thePlacement2->HasRefDirection();
+    const bool isSameRefDirection =
+      isSameRefDirectionFlag
+      && (!thePlacement1->HasRefDirection()
+          || StepTidy_DirectionHasher{}(thePlacement1->RefDirection(),
+                                        thePlacement2->RefDirection()));
+
+    return isSameLocation && isSameRefDirection;
+  }
+};
+
+#endif // _StepTidy_Axis2Placement2dHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement3dHasher.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement3dHasher.pxx
new file mode 100644 (file)
index 0000000..c3600f0
--- /dev/null
@@ -0,0 +1,86 @@
+// 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 _StepTidy_Axis2Placement3dHasher_HeaderFile
+#define _StepTidy_Axis2Placement3dHasher_HeaderFile
+
+#include <StepTidy_CartesianPointHasher.pxx>
+#include <StepTidy_DirectionHasher.pxx>
+
+#include <Standard_HashUtils.hxx>
+#include <StepGeom_Axis2Placement3d.hxx>
+
+//! OCCT-style hasher for StepGeom_Axis2Placement3d entities.
+struct StepTidy_Axis2Placement3dHasher
+{
+  // Hashes the axis placements.
+  std::size_t operator()(const Handle(StepGeom_Axis2Placement3d)& thePlacement) const noexcept
+  {
+    // Prepare an array of hashes for the location, axis, and ref direction.
+    // Optimal seed is used for the axis and ref direction if they are not present.
+    const size_t aHashes[3]{
+      StepTidy_CartesianPointHasher{}(thePlacement->Location()),
+      thePlacement->HasAxis() ? StepTidy_DirectionHasher{}(thePlacement->Axis())
+                              : opencascade::MurmurHash::optimalSeed(),
+      thePlacement->HasRefDirection() ? StepTidy_DirectionHasher{}(thePlacement->RefDirection())
+                                      : opencascade::MurmurHash::optimalSeed()};
+    const size_t aHash = opencascade::hashBytes(aHashes, sizeof(aHashes));
+    if (thePlacement->Name().IsNull())
+    {
+      // If the name is not present, return the hash.
+      return aHash;
+    }
+    // Add the name to the hash if it is present.
+    const size_t aHashWithName[2]{
+      aHash,
+      std::hash<TCollection_AsciiString>{}(thePlacement->Name()->String())};
+    return opencascade::hashBytes(aHashWithName, sizeof(aHashWithName));
+  }
+
+  // Compares two axis placements.
+  bool operator()(const Handle(StepGeom_Axis2Placement3d)& thePlacement1,
+                  const Handle(StepGeom_Axis2Placement3d)& thePlacement2) const noexcept
+  {
+    // Compare names.
+    if (thePlacement1->Name().IsNull() != thePlacement2->Name().IsNull())
+    {
+      return false;
+    }
+    if (!thePlacement1->Name()->IsSameString(thePlacement2->Name()))
+    {
+      return false;
+    }
+
+    // Compare location, axis, and ref direction.
+    const bool isSameLocation =
+      StepTidy_CartesianPointHasher{}(thePlacement1->Location(), thePlacement2->Location());
+    // Have to check if the axis is present and compare it.
+    const bool isSameAxisFlag = thePlacement1->HasAxis() == thePlacement2->HasAxis();
+    const bool isSameAxis =
+      isSameAxisFlag
+      && (!thePlacement1->HasAxis()
+          || StepTidy_DirectionHasher{}(thePlacement1->Axis(), thePlacement2->Axis()));
+    // Have to check if the ref direction is present and compare it.
+    const bool isSameRefDirectionFlag =
+      thePlacement1->HasRefDirection() == thePlacement2->HasRefDirection();
+    const bool isSameRefDirection =
+      isSameRefDirectionFlag
+      && (!thePlacement1->HasRefDirection()
+          || StepTidy_DirectionHasher{}(thePlacement1->RefDirection(),
+                                        thePlacement2->RefDirection()));
+
+    return isSameLocation && isSameAxis && isSameRefDirection;
+  }
+};
+
+#endif // _StepTidy_Axis2Placement3dHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement3dReducer.cxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement3dReducer.cxx
new file mode 100644 (file)
index 0000000..57c1389
--- /dev/null
@@ -0,0 +1,298 @@
+// 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.
+
+#include <StepTidy_Axis2Placement3dReducer.pxx>
+
+#include <StepGeom_Plane.hxx>
+#include <StepRepr_ItemDefinedTransformation.hxx>
+#include <StepGeom_CylindricalSurface.hxx>
+#include <StepShape_ShapeRepresentation.hxx>
+#include <StepRepr_ConstructiveGeometryRepresentation.hxx>
+#include <StepGeom_Circle.hxx>
+#include <StepVisual_PresentationLayerAssignment.hxx>
+#include <StepVisual_StyledItem.hxx>
+#include <StepGeom_Ellipse.hxx>
+#include <StepGeom_ConicalSurface.hxx>
+#include <StepGeom_ToroidalSurface.hxx>
+#include <StepShape_AdvancedBrepShapeRepresentation.hxx>
+#include <StepGeom_SphericalSurface.hxx>
+
+//==================================================================================================
+
+StepTidy_Axis2Placement3dReducer::StepTidy_Axis2Placement3dReducer(
+  const Handle(XSControl_WorkSession)& theWS)
+    : StepTidy_EntityReducer<StepGeom_Axis2Placement3d, StepTidy_Axis2Placement3dHasher>(theWS)
+{
+  registerReplacer(STANDARD_TYPE(StepGeom_Plane), replacePlane);
+  registerReplacer(STANDARD_TYPE(StepRepr_ItemDefinedTransformation),
+                   replaceItemDefinedTransformation);
+  registerReplacer(STANDARD_TYPE(StepGeom_CylindricalSurface), replaceCylindricalSurface);
+  registerReplacer(STANDARD_TYPE(StepShape_ShapeRepresentation), replaceShapeRepresentation);
+  registerReplacer(STANDARD_TYPE(StepRepr_ConstructiveGeometryRepresentation),
+                   replaceConstructiveGeometryRepresentation);
+  registerReplacer(STANDARD_TYPE(StepGeom_Circle), replaceCircle);
+  registerReplacer(STANDARD_TYPE(StepVisual_PresentationLayerAssignment),
+                   replacePresentationLayerAssignment);
+  registerReplacer(STANDARD_TYPE(StepVisual_StyledItem), replaceStyledItem);
+  registerReplacer(STANDARD_TYPE(StepGeom_Ellipse), replaceEllipse);
+  registerReplacer(STANDARD_TYPE(StepGeom_ConicalSurface), replaceConicalSurface);
+  registerReplacer(STANDARD_TYPE(StepGeom_ToroidalSurface), replaceToroidalSurface);
+  registerReplacer(STANDARD_TYPE(StepShape_AdvancedBrepShapeRepresentation),
+                   replaceAdvancedBrepShapeRepresentation);
+  registerReplacer(STANDARD_TYPE(StepGeom_SphericalSurface), replaceSphericalSurface);
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replacePlane(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepGeom_Plane) aSharing = Handle(StepGeom_Plane)::DownCast(theSharing);
+  if (aSharing->Position() == theOldEntity)
+  {
+    aSharing->SetPosition(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replaceItemDefinedTransformation(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepRepr_ItemDefinedTransformation) aSharing =
+    Handle(StepRepr_ItemDefinedTransformation)::DownCast(theSharing);
+  bool isReplaced = false;
+  if (aSharing->TransformItem1() == theOldEntity)
+  {
+    aSharing->SetTransformItem1(theNewEntity);
+    isReplaced = true;
+  }
+  if (aSharing->TransformItem2() == theOldEntity)
+  {
+    aSharing->SetTransformItem2(theNewEntity);
+    isReplaced = true;
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replaceCylindricalSurface(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepGeom_CylindricalSurface) aSharing =
+    Handle(StepGeom_CylindricalSurface)::DownCast(theSharing);
+  if (aSharing->Position() == theOldEntity)
+  {
+    aSharing->SetPosition(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replaceShapeRepresentation(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepShape_ShapeRepresentation) aSharing =
+    Handle(StepShape_ShapeRepresentation)::DownCast(theSharing);
+  bool isReplaced = false;
+  for (Standard_Integer anIndex = aSharing->Items()->Lower(); anIndex <= aSharing->Items()->Upper();
+       ++anIndex)
+  {
+    if (aSharing->Items()->Value(anIndex) == theOldEntity)
+    {
+      aSharing->Items()->SetValue(anIndex, theNewEntity);
+      isReplaced = true;
+    }
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replaceConstructiveGeometryRepresentation(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepRepr_ConstructiveGeometryRepresentation) aSharing =
+    Handle(StepRepr_ConstructiveGeometryRepresentation)::DownCast(theSharing);
+  bool isReplaced = false;
+  for (Standard_Integer anIndex = aSharing->Items()->Lower(); anIndex <= aSharing->Items()->Upper();
+       ++anIndex)
+  {
+    if (aSharing->Items()->Value(anIndex) == theOldEntity)
+    {
+      aSharing->Items()->SetValue(anIndex, theNewEntity);
+      isReplaced = true;
+    }
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replaceCircle(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepGeom_Circle) aSharing  = Handle(StepGeom_Circle)::DownCast(theSharing);
+  StepGeom_Axis2Placement aSelector = aSharing->Position();
+  if (aSelector.Axis2Placement3d() == theOldEntity)
+  {
+    aSelector.SetValue(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replacePresentationLayerAssignment(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepVisual_PresentationLayerAssignment) aSharing =
+    Handle(StepVisual_PresentationLayerAssignment)::DownCast(theSharing);
+  bool                                    isReplaced = false;
+  Handle(StepVisual_HArray1OfLayeredItem) anItems    = aSharing->AssignedItems();
+  for (Standard_Integer anIndex = anItems->Lower(); anIndex <= anItems->Upper(); ++anIndex)
+  {
+    StepVisual_LayeredItem& aLayeredItem = anItems->ChangeValue(anIndex);
+    if (aLayeredItem.RepresentationItem() == theOldEntity)
+    {
+      aLayeredItem.SetValue(theNewEntity);
+      isReplaced = true;
+    }
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replaceStyledItem(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepVisual_StyledItem) aSharing = Handle(StepVisual_StyledItem)::DownCast(theSharing);
+  if (aSharing->Item() == theOldEntity)
+  {
+    aSharing->SetItem(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replaceEllipse(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepGeom_Ellipse) aSharing  = Handle(StepGeom_Ellipse)::DownCast(theSharing);
+  StepGeom_Axis2Placement  aSelector = aSharing->Position();
+  if (aSelector.Axis2Placement3d() == theOldEntity)
+  {
+    aSelector.SetValue(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replaceConicalSurface(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepGeom_ConicalSurface) aSharing = Handle(StepGeom_ConicalSurface)::DownCast(theSharing);
+  if (aSharing->Position() == theOldEntity)
+  {
+    aSharing->SetPosition(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replaceToroidalSurface(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepGeom_ToroidalSurface) aSharing =
+    Handle(StepGeom_ToroidalSurface)::DownCast(theSharing);
+  if (aSharing->Position() == theOldEntity)
+  {
+    aSharing->SetPosition(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replaceAdvancedBrepShapeRepresentation(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepShape_AdvancedBrepShapeRepresentation) aSharing =
+    Handle(StepShape_AdvancedBrepShapeRepresentation)::DownCast(theSharing);
+  bool isReplaced = false;
+  for (Standard_Integer anIndex = aSharing->Items()->Lower(); anIndex <= aSharing->Items()->Upper();
+       ++anIndex)
+  {
+    if (aSharing->Items()->Value(anIndex) == theOldEntity)
+    {
+      aSharing->Items()->SetValue(anIndex, theNewEntity);
+      isReplaced = true;
+    }
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_Axis2Placement3dReducer::replaceSphericalSurface(
+  const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+  const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+  Handle(Standard_Transient)               theSharing)
+{
+  Handle(StepGeom_SphericalSurface) aSharing =
+    Handle(StepGeom_SphericalSurface)::DownCast(theSharing);
+  if (aSharing->Position() == theOldEntity)
+  {
+    aSharing->SetPosition(theNewEntity);
+    return true;
+  }
+  return false;
+}
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement3dReducer.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_Axis2Placement3dReducer.pxx
new file mode 100644 (file)
index 0000000..7cd8dad
--- /dev/null
@@ -0,0 +1,158 @@
+// 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 _StepTidy_Axis2Placement3dReducer_HeaderFile
+#define _StepTidy_Axis2Placement3dReducer_HeaderFile
+
+#include <StepTidy_EntityReducer.pxx>
+#include <StepTidy_Axis2Placement3dHasher.pxx>
+
+#include <StepGeom_Axis2Placement3d.hxx>
+
+//! Processor for merging StepGeom_Axis2Placement3d entities.
+//! This processor merges axis placements with the same location, axis, and ref direction.
+class StepTidy_Axis2Placement3dReducer
+    : public StepTidy_EntityReducer<StepGeom_Axis2Placement3d, StepTidy_Axis2Placement3dHasher>
+{
+public:
+  //! Constructor. Stores the work session and registers replacer functions.
+  //! @param theWS the work session.
+  Standard_EXPORT StepTidy_Axis2Placement3dReducer(const Handle(XSControl_WorkSession)& theWS);
+
+private:
+  //! Replaces the old axis placement with the new one in the StepGeom_Plane entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepGeom_Plane entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replacePlane(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+                           const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+                           Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the StepRepr_ItemDefinedTransformation
+  //! entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepRepr_ItemDefinedTransformation entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replaceItemDefinedTransformation(
+    const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+    const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+    Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the StepGeom_CylindricalSurface entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepGeom_CylindricalSurface entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replaceCylindricalSurface(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+                                        const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+                                        Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the StepShape_ShapeRepresentation entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepShape_ShapeRepresentation entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replaceShapeRepresentation(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+                                         const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+                                         Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the
+  //! StepRepr_ConstructiveGeometryRepresentation entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepRepr_ConstructiveGeometryRepresentation entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replaceConstructiveGeometryRepresentation(
+    const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+    const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+    Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the StepGeom_Circle entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepGeom_Circle entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replaceCircle(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+                            const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+                            Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the StepGeom_PresentationLayerAssignment
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepGeom_PresentationLayerAssignment entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replacePresentationLayerAssignment(
+    const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+    const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+    Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the StepVisual_StyledItem entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepVisual_StyledItem entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replaceStyledItem(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+                                const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+                                Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the StepGeom_Ellipse entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepGeom_Ellipse entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replaceEllipse(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+                             const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+                             Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the StepGeom_ConicalSurface entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepGeom_ConicalSurface entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replaceConicalSurface(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+                                    const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+                                    Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the StepGeom_ToroidalSurface entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepGeom_ToroidalSurface entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replaceToroidalSurface(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+                                     const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+                                     Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the
+  //! StepShape_AdvancedBrepShapeRepresentation entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepShape_AdvancedBrepShapeRepresentation entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replaceAdvancedBrepShapeRepresentation(
+    const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+    const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+    Handle(Standard_Transient)               theSharing);
+
+  //! Replaces the old axis placement with the new one in the StepGeom_SphericalSurface entity.
+  //! @param theOldEntity the old axis placement.
+  //! @param theNewEntity the new axis placement to replace the old one.
+  //! @param theSharing the StepGeom_SphericalSurface entity to update.
+  //! @return true if the axis placement was replaced, false otherwise.
+  static bool replaceSphericalSurface(const Handle(StepGeom_Axis2Placement3d)& theOldEntity,
+                                      const Handle(StepGeom_Axis2Placement3d)& theNewEntity,
+                                      Handle(Standard_Transient)               theSharing);
+};
+
+#endif // _StepTidy_DirectionReducer_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CartesianPointHasher.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CartesianPointHasher.pxx
new file mode 100644 (file)
index 0000000..61591d5
--- /dev/null
@@ -0,0 +1,74 @@
+// 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 _StepTidy_CartesianPointHasher_HeaderFile
+#define _StepTidy_CartesianPointHasher_HeaderFile
+
+#include <Standard_HashUtils.hxx>
+#include <StepGeom_CartesianPoint.hxx>
+#include <TCollection_HAsciiString.hxx>
+
+//! OCCT-style hasher for StepGeom_CartesianPoint entities.
+struct StepTidy_CartesianPointHasher
+{
+  // Hashes the Cartesian point by its name and coordinates.
+  std::size_t operator()(const Handle(StepGeom_CartesianPoint)& theCartesianPoint) const noexcept
+  {
+    const std::array<Standard_Real, 3>& aCoords = theCartesianPoint->Coordinates();
+    // If Cartesian point has no name, hash only coordinates.
+    if (theCartesianPoint->Name().IsNull())
+    {
+      return opencascade::hashBytes(aCoords.data(), static_cast<int>(aCoords.size()));
+    }
+    // Otherwise, hash both coordinates and name.
+    const size_t aHashes[2]{
+      opencascade::hashBytes(aCoords.data(), static_cast<int>(aCoords.size())),
+      std::hash<TCollection_AsciiString>{}(theCartesianPoint->Name()->String())};
+
+    return opencascade::hashBytes(aHashes, sizeof(aHashes));
+  }
+
+  // Compares two Cartesian points by their names and coordinates.
+  bool operator()(const Handle(StepGeom_CartesianPoint)& theCartesianPoint1,
+                  const Handle(StepGeom_CartesianPoint)& theCartesianPoint2) const noexcept
+  {
+    // Compare names.
+    if (theCartesianPoint1->Name().IsNull() != theCartesianPoint2->Name().IsNull())
+    {
+      return false;
+    }
+    if (!theCartesianPoint1->Name()->IsSameString(theCartesianPoint2->Name()))
+    {
+      return false;
+    }
+
+    // Compare coordinates.
+    constexpr double                    aTolerance = 1e-12;
+    const std::array<Standard_Real, 3>& aCoords1   = theCartesianPoint1->Coordinates();
+    const std::array<Standard_Real, 3>& aCoords2   = theCartesianPoint2->Coordinates();
+    if (aCoords1.size() != aCoords2.size())
+    {
+      return false;
+    }
+    for (size_t anIndex = 0; anIndex < aCoords1.size(); ++anIndex)
+    {
+      if (std::abs(aCoords1[anIndex] - aCoords2[anIndex]) > aTolerance)
+      {
+        return false;
+      }
+    }
+    return true;
+  }
+};
+
+#endif // _StepTidy_CartesianPointHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CartesianPointReducer.cxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CartesianPointReducer.cxx
new file mode 100644 (file)
index 0000000..144ff60
--- /dev/null
@@ -0,0 +1,301 @@
+// 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.
+
+#include <StepTidy_CartesianPointReducer.pxx>
+
+#include <Interface_Graph.hxx>
+#include <StepGeom_Axis1Placement.hxx>
+#include <StepGeom_Axis2Placement3d.hxx>
+#include <StepGeom_BSplineCurveWithKnots.hxx>
+#include <StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve.hxx>
+#include <StepGeom_BSplineSurfaceWithKnots.hxx>
+#include <StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface.hxx>
+#include <StepGeom_Line.hxx>
+#include <StepRepr_Representation.hxx>
+#include <StepShape_GeometricCurveSet.hxx>
+#include <StepShape_VertexPoint.hxx>
+#include <StepVisual_PresentationLayerAssignment.hxx>
+#include <StepVisual_StyledItem.hxx>
+
+//==================================================================================================
+
+StepTidy_CartesianPointReducer::StepTidy_CartesianPointReducer(
+  const Handle(XSControl_WorkSession)& theWS)
+    : StepTidy_EntityReducer<StepGeom_CartesianPoint, StepTidy_CartesianPointHasher>(theWS)
+{
+  registerReplacer(STANDARD_TYPE(StepGeom_Axis1Placement), replaceAxis1Placement);
+  registerReplacer(STANDARD_TYPE(StepGeom_Axis2Placement3d), replaceAxis2Placement3d);
+  registerReplacer(STANDARD_TYPE(StepShape_VertexPoint), replaceVertexPoint);
+  registerReplacer(STANDARD_TYPE(StepShape_GeometricCurveSet), replaceGeometricCurveSet);
+  registerReplacer(STANDARD_TYPE(StepVisual_PresentationLayerAssignment),
+                   replacePresentationLayerAssignment);
+  registerReplacer(STANDARD_TYPE(StepVisual_StyledItem), replaceStyledItem);
+  registerReplacer(STANDARD_TYPE(StepGeom_BSplineCurveWithKnots), replaceBSplineCurveWithKnots);
+  registerReplacer(STANDARD_TYPE(StepGeom_Line), replaceLine);
+  registerReplacer(STANDARD_TYPE(StepGeom_BSplineSurfaceWithKnots), replaceBSplineSurfaceWithKnots);
+  registerReplacer(STANDARD_TYPE(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve),
+                   replaceBSplineCurveWithKnotsAndRationalBSplineCurve);
+  registerReplacer(STANDARD_TYPE(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface),
+                   replaceBSplineSurfaceWithKnotsAndRationalBSplineSurface);
+  registerReplacer(STANDARD_TYPE(StepRepr_Representation), replaceRepresentation);
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replaceAxis2Placement3d(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepGeom_Axis2Placement3d) aSharing =
+    Handle(StepGeom_Axis2Placement3d)::DownCast(theSharing);
+  if (aSharing->Location() == theOldEntity)
+  {
+    aSharing->SetLocation(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replaceVertexPoint(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepShape_VertexPoint) aSharing = Handle(StepShape_VertexPoint)::DownCast(theSharing);
+  if (aSharing->VertexGeometry() == theOldEntity)
+  {
+    aSharing->SetVertexGeometry(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replaceGeometricCurveSet(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepShape_GeometricSet) aSharing   = Handle(StepShape_GeometricSet)::DownCast(theSharing);
+  bool                           isReplaced = false;
+  for (auto& anElement : *aSharing->Elements())
+  {
+    const Handle(StepGeom_Point) aCurrentPoint = anElement.Point();
+    if (aCurrentPoint && aCurrentPoint == theOldEntity)
+    {
+      anElement.SetValue(theNewEntity);
+      isReplaced = true;
+    }
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replacePresentationLayerAssignment(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepVisual_PresentationLayerAssignment) aSharing =
+    Handle(StepVisual_PresentationLayerAssignment)::DownCast(theSharing);
+  bool isReplaced = false;
+  for (auto& anAssignedItem : *aSharing->AssignedItems())
+  {
+    const Handle(StepRepr_RepresentationItem) aRepItem = anAssignedItem.RepresentationItem();
+    if (aRepItem == theOldEntity)
+    {
+      anAssignedItem.SetValue(theNewEntity);
+      isReplaced = true;
+    }
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replaceStyledItem(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepVisual_StyledItem) aSharing = Handle(StepVisual_StyledItem)::DownCast(theSharing);
+  if (aSharing->Item() == theOldEntity)
+  {
+    aSharing->SetItem(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replaceBSplineCurveWithKnots(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepGeom_BSplineCurveWithKnots) aSharing =
+    Handle(StepGeom_BSplineCurveWithKnots)::DownCast(theSharing);
+  bool                                     isReplaced     = false;
+  Handle(StepGeom_HArray1OfCartesianPoint) aControlPoints = aSharing->ControlPointsList();
+  for (Standard_Integer anIndex = aControlPoints->Lower(); anIndex <= aControlPoints->Upper();
+       ++anIndex)
+  {
+    if (aControlPoints->Value(anIndex) == theOldEntity)
+    {
+      aControlPoints->SetValue(anIndex, theNewEntity);
+      isReplaced = true;
+    }
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replaceLine(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepGeom_Line) aSharing = Handle(StepGeom_Line)::DownCast(theSharing);
+  if (aSharing->Pnt() == theOldEntity)
+  {
+    aSharing->SetPnt(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replaceBSplineSurfaceWithKnots(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepGeom_BSplineSurfaceWithKnots) aSharing =
+    Handle(StepGeom_BSplineSurfaceWithKnots)::DownCast(theSharing);
+  bool                                     isReplaced     = false;
+  Handle(StepGeom_HArray2OfCartesianPoint) aControlPoints = aSharing->ControlPointsList();
+  for (Standard_Integer anIndexI = aControlPoints->LowerRow();
+       anIndexI <= aControlPoints->UpperRow();
+       ++anIndexI)
+  {
+    for (Standard_Integer anIndexJ = aControlPoints->LowerCol();
+         anIndexJ <= aControlPoints->UpperCol();
+         ++anIndexJ)
+    {
+      if (aControlPoints->Value(anIndexI, anIndexJ) == theOldEntity)
+      {
+        aControlPoints->SetValue(anIndexI, anIndexJ, theNewEntity);
+        isReplaced = true;
+      }
+    }
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replaceAxis1Placement(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepGeom_Axis1Placement) aSharing = Handle(StepGeom_Axis1Placement)::DownCast(theSharing);
+  if (aSharing->Location() == theOldEntity)
+  {
+    aSharing->SetLocation(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replaceRepresentation(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepRepr_Representation) aSharing = Handle(StepRepr_Representation)::DownCast(theSharing);
+  bool                            isReplaced           = false;
+  Handle(StepRepr_HArray1OfRepresentationItem) anItems = aSharing->Items();
+  for (Standard_Integer anIndex = 1; anIndex <= aSharing->NbItems(); ++anIndex)
+  {
+    const Handle(StepRepr_RepresentationItem) aRepItem = anItems->Value(anIndex);
+    if (aRepItem == theOldEntity)
+    {
+      anItems->SetValue(anIndex, theNewEntity);
+      isReplaced = true;
+    }
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replaceBSplineCurveWithKnotsAndRationalBSplineCurve(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve) aSharing =
+    Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve)::DownCast(theSharing);
+  bool                                     isReplaced     = false;
+  Handle(StepGeom_HArray1OfCartesianPoint) aControlPoints = aSharing->ControlPointsList();
+  for (Standard_Integer anIndex = aControlPoints->Lower(); anIndex <= aControlPoints->Upper();
+       ++anIndex)
+  {
+    if (aControlPoints->Value(anIndex) == theOldEntity)
+    {
+      aControlPoints->SetValue(anIndex, theNewEntity);
+      isReplaced = true;
+    }
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_CartesianPointReducer::replaceBSplineSurfaceWithKnotsAndRationalBSplineSurface(
+  const Handle(StepGeom_CartesianPoint)& theOldEntity,
+  const Handle(StepGeom_CartesianPoint)& theNewEntity,
+  Handle(Standard_Transient)             theSharing)
+{
+  Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface) aSharing =
+    Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface)::DownCast(theSharing);
+  bool                                     isReplaced     = false;
+  Handle(StepGeom_HArray2OfCartesianPoint) aControlPoints = aSharing->ControlPointsList();
+  for (Standard_Integer anIndexI = aControlPoints->LowerRow();
+       anIndexI <= aControlPoints->UpperRow();
+       ++anIndexI)
+  {
+    for (Standard_Integer anIndexJ = aControlPoints->LowerCol();
+         anIndexJ <= aControlPoints->UpperCol();
+         ++anIndexJ)
+    {
+      if (aControlPoints->Value(anIndexI, anIndexJ) == theOldEntity)
+      {
+        aControlPoints->SetValue(anIndexI, anIndexJ, theNewEntity);
+        isReplaced = true;
+      }
+    }
+  }
+  return isReplaced;
+}
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CartesianPointReducer.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CartesianPointReducer.pxx
new file mode 100644 (file)
index 0000000..bc2a6cd
--- /dev/null
@@ -0,0 +1,161 @@
+// 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 _StepTidy_CartesianPointReducer_HeaderFile
+#define _StepTidy_CartesianPointReducer_HeaderFile
+
+#include <StepTidy_EntityReducer.pxx>
+#include <StepTidy_CartesianPointHasher.pxx>
+
+#include <StepGeom_CartesianPoint.hxx>
+
+//! Processor for merging StepGeom_CartesianPoint entities.
+//! This processor is responsible for merging Cartesian points with the same coordinates and names.
+//! It is used to remove duplicate Cartesian points from the STEP model.
+//! See StepTidy_EntityReducer for the description of the Reducer workflow.
+class StepTidy_CartesianPointReducer
+    : public StepTidy_EntityReducer<StepGeom_CartesianPoint, StepTidy_CartesianPointHasher>
+{
+public:
+  //! Constructor. Accepts a work session containing the model to process.
+  //! Registers replacer functions for all supported sharing entities.
+  //! @param theWS Work session.
+  Standard_EXPORT StepTidy_CartesianPointReducer(const Handle(XSControl_WorkSession)& theWS);
+
+private:
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepGeom_Axis2Placement3d.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepGeom_Axis2Placement3d sharing the old entity.
+  //! @return True if the entity was replaced, false if it was not.
+  static bool replaceAxis2Placement3d(const Handle(StepGeom_CartesianPoint)& theOldEntity,
+                                      const Handle(StepGeom_CartesianPoint)& theNewEntity,
+                                      Handle(Standard_Transient)             theSharing);
+
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepShape_VertexPoint.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepShape_VertexPoint sharing the old entity.
+  //! @return True if the entity was replaced, false if it was not.
+  static bool replaceVertexPoint(const Handle(StepGeom_CartesianPoint)& theOldEntity,
+                                 const Handle(StepGeom_CartesianPoint)& theNewEntity,
+                                 Handle(Standard_Transient)             theSharing);
+
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepShape_GeometricSet.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepShape_GeometricSet sharing the old entity.
+  //! @return True if the entity was replaced, false if it was not.
+  static bool replaceGeometricCurveSet(const Handle(StepGeom_CartesianPoint)& theOldEntity,
+                                       const Handle(StepGeom_CartesianPoint)& theNewEntity,
+                                       Handle(Standard_Transient)             theSharing);
+
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepVisual_PresentationLayerAssignment.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepVisual_PresentationLayerAssignment sharing the old entity.
+  //! @return True if the entity was replaced, false if it was not.
+  static bool replacePresentationLayerAssignment(
+    const Handle(StepGeom_CartesianPoint)& theOldEntity,
+    const Handle(StepGeom_CartesianPoint)& theNewEntity,
+    Handle(Standard_Transient)             theSharing);
+
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepVisual_StyledItem.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepVisual_StyledItem sharing the old entity.
+  //! @return True if the entity was replaced, false if it was not.
+  static bool replaceStyledItem(const Handle(StepGeom_CartesianPoint)& theOldEntity,
+                                const Handle(StepGeom_CartesianPoint)& theNewEntity,
+                                Handle(Standard_Transient)             theSharing);
+
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepGeom_BSplineCurveWithKnots.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepGeom_BSplineCurveWithKnots sharing the old entity.
+  //! @return True if the entity was replaced, false if it was not.
+  static bool replaceBSplineCurveWithKnots(const Handle(StepGeom_CartesianPoint)& theOldEntity,
+                                           const Handle(StepGeom_CartesianPoint)& theNewEntity,
+                                           Handle(Standard_Transient)             theSharing);
+
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepGeom_Line.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepGeom_Line sharing the old entity.
+  //! @return True if the entity was replaced, false if it was not.
+  static bool replaceLine(const Handle(StepGeom_CartesianPoint)& theOldEntity,
+                          const Handle(StepGeom_CartesianPoint)& theNewEntity,
+                          Handle(Standard_Transient)             theSharing);
+
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepGeom_BSplineSurfaceWithKnots.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepGeom_BSplineSurfaceWithKnots sharing the old entity.
+  //! @return True if the entity was replaced, false if it was not.
+  static bool replaceBSplineSurfaceWithKnots(const Handle(StepGeom_CartesianPoint)& theOldEntity,
+                                             const Handle(StepGeom_CartesianPoint)& theNewEntity,
+                                             Handle(Standard_Transient)             theSharing);
+
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepGeom_Axis1Placement.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepGeom_Axis1Placement sharing the old entity.
+  //! @return True if the entity was replaced, false if it was not.
+  static bool replaceAxis1Placement(const Handle(StepGeom_CartesianPoint)& theOldEntity,
+                                    const Handle(StepGeom_CartesianPoint)& theNewEntity,
+                                    Handle(Standard_Transient)             theSharing);
+
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepRepr_Representation.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepRepr_Representation sharing the old entity.
+  //! @return True if the entity was replaced, false if it was not.
+  static bool replaceRepresentation(const Handle(StepGeom_CartesianPoint)& theOldEntity,
+                                    const Handle(StepGeom_CartesianPoint)& theNewEntity,
+                                    Handle(Standard_Transient)             theSharing);
+
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve sharing the old
+  //!        entity.
+  //! @return True if the entity was replaced, false if it was not.
+  static bool replaceBSplineCurveWithKnotsAndRationalBSplineCurve(
+    const Handle(StepGeom_CartesianPoint)& theOldEntity,
+    const Handle(StepGeom_CartesianPoint)& theNewEntity,
+    Handle(Standard_Transient)             theSharing);
+
+  //! Replaces the old Cartesian point with the new Cartesian point in
+  //! the sharing StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface.
+  //! @param theOldEntity Old Cartesian point to replace.
+  //! @param theNewEntity New Cartesian point to replace the old entity with.
+  //! @param theSharing The StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface sharing the
+  //!       old entity.
+  static bool replaceBSplineSurfaceWithKnotsAndRationalBSplineSurface(
+    const Handle(StepGeom_CartesianPoint)& theOldEntity,
+    const Handle(StepGeom_CartesianPoint)& theNewEntity,
+    Handle(Standard_Transient)             theSharing);
+};
+
+#endif // _StepTidy_CartesianPointReducer_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CircleHasher.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CircleHasher.pxx
new file mode 100644 (file)
index 0000000..ae890b2
--- /dev/null
@@ -0,0 +1,101 @@
+// 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 _StepTidy_CircleHasher_HeaderFile
+#define _StepTidy_CircleHasher_HeaderFile
+
+#include <StepTidy_Axis2Placement2dHasher.pxx>
+#include <StepTidy_Axis2Placement3dHasher.pxx>
+
+#include <Standard_HashUtils.hxx>
+#include <StepGeom_Circle.hxx>
+#include <TCollection_HAsciiString.hxx>
+
+//! OCCT-style hasher for StepGeom_Circle entities.
+struct StepTidy_CircleHasher
+{
+  //! Returns hash for a Circle entity.
+  std::size_t operator()(const Handle(StepGeom_Circle)& theCircle) const noexcept
+  {
+    const size_t aPositionHash =
+      !theCircle->Position().Axis2Placement2d().IsNull()
+        ? StepTidy_Axis2Placement2dHasher{}(theCircle->Position().Axis2Placement2d())
+      : !theCircle->Position().Axis2Placement3d().IsNull()
+        ? StepTidy_Axis2Placement3dHasher{}(theCircle->Position().Axis2Placement3d())
+        : opencascade::MurmurHash::optimalSeed();
+
+    const size_t aRadiusHash = opencascade::hash(static_cast<int>(theCircle->Radius()));
+
+    const size_t aHashes[2]{aPositionHash, aRadiusHash};
+    const size_t aCombinedHash = opencascade::hashBytes(aHashes, sizeof(aHashes));
+    if (theCircle->Name().IsNull())
+    {
+      // If the name is not present, return the hash.
+      return aCombinedHash;
+    }
+    // Add the name to the hash if it is present.
+    const size_t aHashWithName[2]{
+      aCombinedHash,
+      std::hash<TCollection_AsciiString>{}(theCircle->Name()->String())};
+    return opencascade::hashBytes(aHashWithName, sizeof(aHashWithName));
+  }
+
+  //! Compares two Circle entities.
+  bool operator()(const Handle(StepGeom_Circle)& theCircle1,
+                  const Handle(StepGeom_Circle)& theCircle2) const noexcept
+  {
+    // Compare names.
+    if (theCircle1->Name().IsNull() != theCircle2->Name().IsNull())
+    {
+      return false;
+    }
+    if (!theCircle1->Name()->IsSameString(theCircle2->Name()))
+    {
+      return false;
+    }
+
+    // Compare axis placements.
+    if (theCircle1->Position().CaseNumber() != theCircle2->Position().CaseNumber())
+    {
+      return false;
+    }
+
+    if (theCircle1->Position().CaseNumber() == 1)
+    {
+      if (!StepTidy_Axis2Placement2dHasher{}(theCircle1->Position().Axis2Placement2d(),
+                                             theCircle2->Position().Axis2Placement2d()))
+      {
+        return false;
+      }
+    }
+    else if (theCircle1->Position().CaseNumber() == 2)
+    {
+      if (!StepTidy_Axis2Placement3dHasher{}(theCircle1->Position().Axis2Placement3d(),
+                                             theCircle2->Position().Axis2Placement3d()))
+      {
+        return false;
+      }
+    }
+
+    // Compare radius.
+    constexpr Standard_Real aTolerance = 1e-12;
+    if (Abs(theCircle1->Radius() - theCircle2->Radius()) > aTolerance)
+    {
+      return false;
+    }
+
+    return true;
+  }
+};
+
+#endif // _StepTidy_CircleHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CircleReducer.cxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CircleReducer.cxx
new file mode 100644 (file)
index 0000000..5dbad07
--- /dev/null
@@ -0,0 +1,74 @@
+// 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.
+
+#include <StepTidy_CircleReducer.pxx>
+
+#include <Interface_Graph.hxx>
+#include <StepShape_EdgeCurve.hxx>
+#include <StepGeom_SurfaceCurve.hxx>
+#include <StepGeom_SeamCurve.hxx>
+
+//==================================================================================================
+
+StepTidy_CircleReducer::StepTidy_CircleReducer(const Handle(XSControl_WorkSession)& theWS)
+    : StepTidy_EntityReducer<StepGeom_Circle, StepTidy_CircleHasher>(theWS)
+{
+  registerReplacer(STANDARD_TYPE(StepShape_EdgeCurve), replaceEdgeCurve);
+  registerReplacer(STANDARD_TYPE(StepGeom_SurfaceCurve), replaceSurfaceCurve);
+  registerReplacer(STANDARD_TYPE(StepGeom_SeamCurve), replaceSeamCurve);
+}
+
+//==================================================================================================
+
+bool StepTidy_CircleReducer::replaceEdgeCurve(const Handle(StepGeom_Circle)& theOldEntity,
+                                              const Handle(StepGeom_Circle)& theNewEntity,
+                                              Handle(Standard_Transient)     theSharing)
+{
+  Handle(StepShape_EdgeCurve) aSharing = Handle(StepShape_EdgeCurve)::DownCast(theSharing);
+  if (aSharing->EdgeGeometry() == theOldEntity)
+  {
+    aSharing->SetEdgeGeometry(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_CircleReducer::replaceSurfaceCurve(const Handle(StepGeom_Circle)& theOldEntity,
+                                                 const Handle(StepGeom_Circle)& theNewEntity,
+                                                 Handle(Standard_Transient)     theSharing)
+{
+  Handle(StepGeom_SurfaceCurve) aSharing = Handle(StepGeom_SurfaceCurve)::DownCast(theSharing);
+  if (aSharing->Curve3d() == theOldEntity)
+  {
+    aSharing->SetCurve3d(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_CircleReducer::replaceSeamCurve(const Handle(StepGeom_Circle)& theOldEntity,
+                                              const Handle(StepGeom_Circle)& theNewEntity,
+                                              Handle(Standard_Transient)     theSharing)
+{
+  Handle(StepGeom_SeamCurve) aSharing = Handle(StepGeom_SeamCurve)::DownCast(theSharing);
+  if (aSharing->Curve3d() == theOldEntity)
+  {
+    aSharing->SetCurve3d(theNewEntity);
+    return true;
+  }
+  return false;
+}
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CircleReducer.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_CircleReducer.pxx
new file mode 100644 (file)
index 0000000..479b5d8
--- /dev/null
@@ -0,0 +1,63 @@
+// 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 _StepTidy_CircleReducer_HeaderFile
+#define _StepTidy_CircleReducer_HeaderFile
+
+#include <StepTidy_EntityReducer.pxx>
+#include <StepTidy_CircleHasher.pxx>
+
+#include <StepGeom_Circle.hxx>
+
+//! Processor for merging StepGeom_Circle entities.
+//! This processor merges circles with the same position and radius and names.
+class StepTidy_CircleReducer : public StepTidy_EntityReducer<StepGeom_Circle, StepTidy_CircleHasher>
+{
+public:
+  //! Constructor. Stores the work session and registers replacer functions.
+  //! @param theWS the work session.
+  Standard_EXPORT StepTidy_CircleReducer(const Handle(XSControl_WorkSession)& theWS);
+
+private:
+  //! Replacer function for StepShape_EdgeCurve entities.
+  //! Replaces the old entity with the new one in the sharing entity.
+  //! @param theOldEntity the old entity to replace.
+  //! @param theNewEntity the new entity to replace with.
+  //! @param theSharing the sharing entity in which to replace the old entity.
+  //! @return true if the entity was replaced, false otherwise.
+  static bool replaceEdgeCurve(const Handle(StepGeom_Circle)& theOldEntity,
+                               const Handle(StepGeom_Circle)& theNewEntity,
+                               Handle(Standard_Transient)     theSharing);
+
+  //! Replacer function for StepGeom_SurfaceCurve entities.
+  //! Replaces the old entity with the new one in the sharing entity.
+  //! @param theOldEntity the old entity to replace.
+  //! @param theNewEntity the new entity to replace with.
+  //! @param theSharing the sharing entity in which to replace the old entity.
+  //! @return true if the entity was replaced, false otherwise.
+  static bool replaceSurfaceCurve(const Handle(StepGeom_Circle)& theOldEntity,
+                                  const Handle(StepGeom_Circle)& theNewEntity,
+                                  Handle(Standard_Transient)     theSharing);
+
+  //! Replacer function for StepGeom_SeamCurve entities.
+  //! Replaces the old entity with the new one in the sharing entity.
+  //! @param theOldEntity the old entity to replace.
+  //! @param theNewEntity the new entity to replace with.
+  //! @param theSharing the sharing entity in which to replace the old entity.
+  //! @return true if the entity was replaced, false otherwise.
+  static bool replaceSeamCurve(const Handle(StepGeom_Circle)& theOldEntity,
+                               const Handle(StepGeom_Circle)& theNewEntity,
+                               Handle(Standard_Transient)     theSharing);
+};
+
+#endif // _StepTidy_CircleReducer_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_DirectionHasher.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_DirectionHasher.pxx
new file mode 100644 (file)
index 0000000..3ef985f
--- /dev/null
@@ -0,0 +1,78 @@
+// 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 _StepTidy_DirectionHasher_HeaderFile
+#define _StepTidy_DirectionHasher_HeaderFile
+
+#include <Standard_HashUtils.hxx>
+#include <StepGeom_Direction.hxx>
+#include <TCollection_HAsciiString.hxx>
+
+//! OCCT-style hasher for StepGeom_Direction entities.
+struct StepTidy_DirectionHasher
+{
+  // Hashes the direction by its name and direction ratios.
+  std::size_t operator()(const Handle(StepGeom_Direction)& theDirection) const noexcept
+  {
+    // Prepare an array of direction ratios.
+    const Handle(TColStd_HArray1OfReal) aCoords = theDirection->DirectionRatios();
+    int                                 anArray[3]{};
+    for (int anIndex = aCoords->Lower(); anIndex < aCoords->Upper(); ++anIndex)
+    {
+      anArray[anIndex] = static_cast<int>(aCoords->Value(anIndex));
+    }
+    // If direction has no name, hash only direction ratios.
+    if (theDirection->Name().IsNull())
+    {
+      return opencascade::hashBytes(anArray, sizeof(anArray));
+    }
+    // Otherwise, hash both direction ratios and name.
+    const size_t aHashes[2]{opencascade::hashBytes(anArray, sizeof(anArray)),
+                            std::hash<TCollection_AsciiString>{}(theDirection->Name()->String())};
+    return opencascade::hashBytes(aHashes, sizeof(aHashes));
+  }
+
+  // Compares two directions by their names and direction ratios.
+  bool operator()(const Handle(StepGeom_Direction)& theDirection1,
+                  const Handle(StepGeom_Direction)& theDirection2) const noexcept
+  {
+    // Compare names.
+    if (theDirection1->Name().IsNull() != theDirection2->Name().IsNull())
+    {
+      return false;
+    }
+    if (!theDirection1->Name()->IsSameString(theDirection2->Name()))
+    {
+      return false;
+    }
+
+    // Compare coordinates.
+    constexpr double                    aTolerance = 1e-12;
+    const Handle(TColStd_HArray1OfReal) aCoords1   = theDirection1->DirectionRatios();
+    const Handle(TColStd_HArray1OfReal) aCoords2   = theDirection2->DirectionRatios();
+    if (aCoords1->Length() != aCoords2->Length())
+    {
+      return false;
+    }
+    for (Standard_Integer i = aCoords1->Lower(); i <= aCoords1->Upper(); ++i)
+    {
+      if (std::abs(aCoords1->Value(i) - aCoords2->Value(i)) > aTolerance)
+      {
+        return false;
+      }
+    }
+    return true;
+  }
+};
+
+#endif // _StepTidy_DirectionHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_DirectionReducer.cxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_DirectionReducer.cxx
new file mode 100644 (file)
index 0000000..a1c4749
--- /dev/null
@@ -0,0 +1,82 @@
+// 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.
+
+#include <StepTidy_DirectionReducer.pxx>
+
+#include <Interface_Graph.hxx>
+#include <StepGeom_Axis1Placement.hxx>
+#include <StepGeom_Axis2Placement3d.hxx>
+#include <StepGeom_Vector.hxx>
+
+//==================================================================================================
+
+StepTidy_DirectionReducer::StepTidy_DirectionReducer(const Handle(XSControl_WorkSession)& theWS)
+    : StepTidy_EntityReducer<StepGeom_Direction, StepTidy_DirectionHasher>(theWS)
+{
+  registerReplacer(STANDARD_TYPE(StepGeom_Axis1Placement), replaceAxis1Placement);
+  registerReplacer(STANDARD_TYPE(StepGeom_Axis2Placement3d), replaceAxis2Placement3d);
+  registerReplacer(STANDARD_TYPE(StepGeom_Vector), replaceVector);
+}
+
+//==================================================================================================
+
+bool StepTidy_DirectionReducer::replaceAxis1Placement(
+  const Handle(StepGeom_Direction)& theOldEntity,
+  const Handle(StepGeom_Direction)& theNewEntity,
+  Handle(Standard_Transient)        theSharing)
+{
+  Handle(StepGeom_Axis1Placement) aSharing = Handle(StepGeom_Axis1Placement)::DownCast(theSharing);
+  if (aSharing->Axis() == theOldEntity)
+  {
+    aSharing->SetAxis(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_DirectionReducer::replaceAxis2Placement3d(
+  const Handle(StepGeom_Direction)& theOldEntity,
+  const Handle(StepGeom_Direction)& theNewEntity,
+  Handle(Standard_Transient)        theSharing)
+{
+  Handle(StepGeom_Axis2Placement3d) aSharing =
+    Handle(StepGeom_Axis2Placement3d)::DownCast(theSharing);
+  if (aSharing->Axis() == theOldEntity)
+  {
+    aSharing->SetAxis(theNewEntity);
+    return true;
+  }
+  else if (aSharing->RefDirection() == theOldEntity)
+  {
+    aSharing->SetRefDirection(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_DirectionReducer::replaceVector(const Handle(StepGeom_Direction)& theOldEntity,
+                                              const Handle(StepGeom_Direction)& theNewEntity,
+                                              Handle(Standard_Transient)        theSharing)
+{
+  Handle(StepGeom_Vector) aSharing = Handle(StepGeom_Vector)::DownCast(theSharing);
+  if (aSharing->Orientation() == theOldEntity)
+  {
+    aSharing->SetOrientation(theNewEntity);
+    return true;
+  }
+  return false;
+}
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_DirectionReducer.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_DirectionReducer.pxx
new file mode 100644 (file)
index 0000000..618f2f1
--- /dev/null
@@ -0,0 +1,64 @@
+// 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 _StepTidy_DirectionReducer_HeaderFile
+#define _StepTidy_DirectionReducer_HeaderFile
+
+#include <StepTidy_EntityReducer.pxx>
+#include <StepTidy_DirectionHasher.pxx>
+
+#include <StepGeom_Direction.hxx>
+
+//! Processor for merging StepGeom_Direction entities.
+//! This processor merges directions with the same direction ratios and names.
+//! The processor replaces all occurrences of the old directions with the new ones.
+//! The processor does not remove old directions from the model.
+//! See StepTidy_EntityReducer for the description of the Reducer workflow.
+class StepTidy_DirectionReducer
+    : public StepTidy_EntityReducer<StepGeom_Direction, StepTidy_DirectionHasher>
+{
+public:
+  //! Constructor. Stores the work session and registers replacer functions.
+  //! @param theWS the work session.
+  Standard_EXPORT StepTidy_DirectionReducer(const Handle(XSControl_WorkSession)& theWS);
+
+private:
+  //! Replaces the old direction with the new one in the StepGeom_Axis1Placement entity.
+  //! @param theOldEntity the old direction.
+  //! @param theNewEntity the new direction.
+  //! @param theSharing the StepGeom_Axis1Placement entity to update.
+  //! @return true if the direction was replaced, false otherwise.
+  static bool replaceAxis1Placement(const Handle(StepGeom_Direction)& theOldEntity,
+                                    const Handle(StepGeom_Direction)& theNewEntity,
+                                    Handle(Standard_Transient)        theSharing);
+
+  //! Replaces the old direction with the new one in the StepGeom_Axis2Placement3d entity.
+  //! @param theOldEntity the old direction.
+  //! @param theNewEntity the new direction.
+  //! @param theSharing the StepGeom_Axis2Placement3d entity to update.
+  //! @return true if the direction was replaced, false otherwise.
+  static bool replaceAxis2Placement3d(const Handle(StepGeom_Direction)& theOldEntity,
+                                      const Handle(StepGeom_Direction)& theNewEntity,
+                                      Handle(Standard_Transient)        theSharing);
+
+  //! Replaces the old direction with the new one in the StepGeom_Vector entity.
+  //! @param theOldEntity the old direction.
+  //! @param theNewEntity the new direction.
+  //! @param theSharing the StepGeom_Vector entity to update.
+  //! @return true if the direction was replaced, false otherwise.
+  static bool replaceVector(const Handle(StepGeom_Direction)& theOldEntity,
+                            const Handle(StepGeom_Direction)& theNewEntity,
+                            Handle(Standard_Transient)        theSharing);
+};
+
+#endif // _StepTidy_DirectionReducer_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_DuplicateCleaner.cxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_DuplicateCleaner.cxx
new file mode 100644 (file)
index 0000000..5da6f01
--- /dev/null
@@ -0,0 +1,123 @@
+// 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.
+
+#include <StepTidy_DuplicateCleaner.hxx>
+
+#include <Interface_EntityIterator.hxx>
+#include <Interface_Graph.hxx>
+#include <StepTidy_Axis2Placement3dReducer.pxx>
+#include <StepTidy_CartesianPointReducer.pxx>
+#include <StepTidy_DirectionReducer.pxx>
+#include <StepTidy_LineReducer.pxx>
+#include <StepTidy_VectorReducer.pxx>
+#include <StepTidy_PlaneReducer.pxx>
+#include <StepTidy_CircleReducer.pxx>
+#include <StepData_StepModel.hxx>
+
+//==================================================================================================
+
+StepTidy_DuplicateCleaner::StepTidy_DuplicateCleaner(Handle(XSControl_WorkSession) theWS)
+    : myWS(theWS)
+{
+}
+
+//==================================================================================================
+
+void StepTidy_DuplicateCleaner::Perform()
+{
+  Handle(StepData_StepModel) aModel = Handle(StepData_StepModel)::DownCast(myWS->Model());
+  if (aModel.IsNull())
+  {
+    return;
+  }
+
+  //! Initialize Reducers.
+  StepTidy_CartesianPointReducer   aCartesianPointReducer(myWS);
+  StepTidy_DirectionReducer        aDirectionReducer(myWS);
+  StepTidy_Axis2Placement3dReducer aAxis2Placement3dReducer(myWS);
+  StepTidy_VectorReducer           aVectorReducer(myWS);
+  StepTidy_LineReducer             aLineReducer(myWS);
+  StepTidy_PlaneReducer            aPlaneReducer(myWS);
+  StepTidy_CircleReducer           aCircleReducer(myWS);
+
+  // Process all entities.
+  for (Standard_Integer anIndex = 1; anIndex <= aModel->NbEntities(); ++anIndex)
+  {
+    const Handle(Standard_Transient) anEntity = aModel->Value(anIndex);
+    aCartesianPointReducer.ProcessEntity(anEntity);
+    aDirectionReducer.ProcessEntity(anEntity);
+    aAxis2Placement3dReducer.ProcessEntity(anEntity);
+    aVectorReducer.ProcessEntity(anEntity);
+    aLineReducer.ProcessEntity(anEntity);
+    aPlaneReducer.ProcessEntity(anEntity);
+    aCircleReducer.ProcessEntity(anEntity);
+  }
+
+  // Perform replacement of duplicate entities.
+  TColStd_MapOfTransient aReplacedEntities;
+  aCartesianPointReducer.Perform(aReplacedEntities);
+  aDirectionReducer.Perform(aReplacedEntities);
+  aAxis2Placement3dReducer.Perform(aReplacedEntities);
+  aVectorReducer.Perform(aReplacedEntities);
+  aLineReducer.Perform(aReplacedEntities);
+  aPlaneReducer.Perform(aReplacedEntities);
+  aCircleReducer.Perform(aReplacedEntities);
+
+  // Remove duplicate entities.
+  removeEntities(aReplacedEntities);
+}
+
+//==================================================================================================
+
+void StepTidy_DuplicateCleaner::removeEntities(const TColStd_MapOfTransient& theToRemove)
+{
+  if (theToRemove.IsEmpty())
+  {
+    return;
+  }
+  // Remove entities.
+  Handle(StepData_StepModel) anIntermediateModel = new StepData_StepModel();
+  Handle(StepData_StepModel) aReadModel = Handle(StepData_StepModel)::DownCast(myWS->Model());
+  anIntermediateModel->SetProtocol(aReadModel->Protocol());
+  anIntermediateModel->SetGTool(aReadModel->GTool());
+
+  for (Standard_Integer i = 1; i <= aReadModel->NbEntities(); i++)
+  {
+    const Handle(Standard_Transient)& anEnt = aReadModel->Value(i);
+    if (!theToRemove.Contains(anEnt))
+    {
+      anIntermediateModel->AddWithRefs(anEnt);
+    }
+  }
+
+  myWS->SetModel(anIntermediateModel);
+  myWS->ComputeGraph();
+
+  // Clean hanged entities.
+  Handle(StepData_StepModel) aNewModel = new StepData_StepModel();
+  aNewModel->SetProtocol(anIntermediateModel->Protocol());
+  aNewModel->SetGTool(anIntermediateModel->GTool());
+  const auto& aGraph = myWS->Graph();
+
+  for (Standard_Integer i = 1; i <= anIntermediateModel->NbEntities(); i++)
+  {
+    const Handle(Standard_Transient)& anEnt = anIntermediateModel->Value(i);
+    if (aGraph.Shareds(anEnt).NbEntities() > 0 || aGraph.Sharings(anEnt).NbEntities() > 0)
+    {
+      aNewModel->AddWithRefs(anEnt);
+    }
+  }
+
+  myWS->SetModel(aNewModel);
+  myWS->ComputeGraph();
+}
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_DuplicateCleaner.hxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_DuplicateCleaner.hxx
new file mode 100644 (file)
index 0000000..d84156b
--- /dev/null
@@ -0,0 +1,62 @@
+// 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 _StepTidy_DuplicateCleaner_HeaderFile
+#define _StepTidy_DuplicateCleaner_HeaderFile
+
+#include <TColStd_MapOfTransient.hxx>
+
+class XSControl_WorkSession;
+
+//! A class to merge STEP entities.
+//! This class is used to merge equal STEP entities in the work session and remove duplicates.
+//! It uses the child classes of StepTidy_EntityReducer class to perform the merging.
+//! The child classes of StepTidy_EntityReducer are specialized for different types of entities.
+//! StepTidy_EntityReducer implements the basic logic for searching and merging entities
+//! while child classes implement the logic for replacing specific type of entities in the specific
+//! type of sharing entities.
+//! Classes StepTidy_*Hasher are used to hash the entities and compare them. They define which
+//! entities are considered equal to each other. The hashers are used in the StepTidy_EntityReducer
+//! class to store the entities in a map. The map is used to find the duplicates and replace them.
+//! From this perspective of this module, 'equal' or 'duplicate' entities are those that
+//! has equal names and very close numerical values, like for example Cartesian points with
+//! coordinates that are equal up to 1e-12 or Vectors with equal orientations and magnitudes
+//! up to 1e-12.
+//! After the merging this class calls its own method to remove the duplicates.
+//! How to use:
+//! 1. Create an instance of the class by providing a pointer to the work session where the
+//!    entities to process are stored.
+//! 2. Call Perform() method to perform the merging of entities. After this call all entities
+//!    that are considered equal to each other will be merged, and duplicates will be removed.
+class StepTidy_DuplicateCleaner
+{
+public:
+  //! Constructor.
+  //! @param theWS the work session to merge entities in.
+  Standard_EXPORT StepTidy_DuplicateCleaner(Handle(XSControl_WorkSession) theWS);
+
+  //! Perform the merging of entities.
+  //! All entities in a model stored in the provided work session that are considered equal to
+  //! each other will be merged, and duplicates will be removed.
+  Standard_EXPORT void Perform();
+
+private:
+  //! Remove entities from the work session.
+  //! @param theToRemove the entities to remove.
+  void removeEntities(const TColStd_MapOfTransient& theToRemove);
+
+private:
+  Handle(XSControl_WorkSession) myWS; //!< The work session containing the model with entities.
+};
+
+#endif // _StepTidy_DuplicateCleaner_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_EntityReducer.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_EntityReducer.pxx
new file mode 100644 (file)
index 0000000..76576b7
--- /dev/null
@@ -0,0 +1,241 @@
+// 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 _StepTidy_EntityReducer_HeaderFile
+#define _StepTidy_EntityReducer_HeaderFile
+
+#include <Interface_Graph.hxx>
+#include <NCollection_Allocator.hxx>
+#include <NCollection_DataMap.hxx>
+#include <Standard_HashUtils.hxx>
+#include <XSControl_WorkSession.hxx>
+#include <TColStd_MapOfTransient.hxx>
+
+#include <functional>
+
+//! Base class for removing duplicate entities.
+//! Implements the logic of processing entities and removing duplicates.
+//! Child classes should only implement and register replacer functions
+//! for each specific type of sharing entity.
+//! How to use:
+//! 1. Create an instance of the child class.
+//! 2. Add entities to the processor using ProcessEntity() method. Entities
+//!    that can be merged will be stored in the internal map, others will be ignored.
+//! 3. Call Perform() method to replace duplicate entities. After this call
+//!    all duplicate entities will be replaced in a model with the first processed entity
+//!    that is evaluated as equal to them.
+//!    IMPORTANT: Duplicated entities will be replaced but not removed from the model!
+//! 4. Call GetReplacedEntities() to get a list of replaced duplicates. This list can be used
+//!    to remove entities from the model.
+//! @tparam ProcessedType Type of the processed entities.
+//! @tparam ProcessedTypeHasher OCCT-Style hasher for the processed entities.
+template <typename ProcessedType, typename ProcessedTypeHasher>
+class StepTidy_EntityReducer
+{
+protected:
+  // Map of duplicate entities. Key is the first processed entity, value is a list of duplicates.
+  using DuplicateMap = NCollection_DataMap<Handle(ProcessedType),
+                                           std::vector<Handle(ProcessedType)>,
+                                           ProcessedTypeHasher>;
+  // Function to replace an entity in sharings. First argument is the old entity, second is the new
+  // entity, third is the sharing in which the entity should be replaced. Returns true if the entity
+  // was replaced, false otherwise.
+  using ReplacerFunction = std::function<bool(const Handle(ProcessedType)&,
+                                              const Handle(ProcessedType)&,
+                                              const Handle(Standard_Transient))>;
+  // Map of replacer functions. Key is the type of the sharing entity, value is the replacer
+  // function for this type.
+  using ReplacerMap = NCollection_DataMap<Handle(Standard_Type), ReplacerFunction>;
+
+protected:
+  //! Constructor. Accepts a work session containing the model to process.
+  //! Protected to prevent direct instantiation of the base class. Only child classes should be
+  //! allowed to instantiate.
+  //! @param theWS Work session.
+  StepTidy_EntityReducer(const Handle(XSControl_WorkSession)& theWS);
+
+public:
+  //! Function to process an entity. If the entity can be merged, it will be stored in the internal
+  //! map. If the entity cannot be merged, it will be ignored.
+  //! Entity can only be processed if:
+  //! 1. The type of entity is ProcessedType.
+  //! 2. All sharings of the entity have a registered replacer function.
+  //! @param theEntity Entity to process.
+  //! @return True if the entity was processed, false if it was ignored.
+  Standard_EXPORT bool ProcessEntity(const Handle(Standard_Transient)& theEntity);
+
+  //! Function to replace duplicate entities. After this call, all duplicate entities will be
+  //! replaced with the first processed entity that is evaluated as equal to them.
+  //! IMPORTANT: Duplicated entities will be replaced but not removed from the model!
+  //! @param theReplacedEntities List where replaced entities will be stored.
+  //!        This list can be used to remove entities from the model.
+  Standard_EXPORT void Perform(TColStd_MapOfTransient& theReplacedEntities);
+
+protected:
+  //! Register a replacer function for a specific type of sharing entity.
+  //! Should be used by child classes to register replacer functions for each specific type of
+  //! sharing entity. If a sharing entity of the specified type is encountered during processing,
+  //! the registered replacer function will be called to replace the old entity with the new one.
+  //! All replacers must be registered before calling ProcessEntity() method.
+  //! @param theType Type of the sharing entity.
+  //! @param theReplacer Replacer function.
+  void registerReplacer(const Handle(Standard_Type)& theType, const ReplacerFunction& theReplacer);
+
+public:
+  //! Checks if all sharings have registered replacers for their types.
+  //! @param theSharings List of sharings to check.
+  //! @return True if all sharings have registered replacers, false otherwise.
+  bool hasAllReplacers(const Handle(TColStd_HSequenceOfTransient)& theSharings) const;
+
+  //! Replaces an old entity with a new entity in sharings.
+  //! Should only be called if all sharings have registered replacers.
+  //! @param theOldEntity Old entity to replace.
+  //! @param theNewEntity New entity to replace old entity with.
+  //! @param theSharings List of old entity sharings to replace the entity in.
+  //! @return True if all entities were replaced, false if at least one entity was not replaced.
+  bool replaceInSharings(const Handle(ProcessedType)&                theOldEntity,
+                         const Handle(ProcessedType)&                theNewEntity,
+                         const Handle(TColStd_HSequenceOfTransient)& theSharings) const;
+
+private:
+  Handle(XSControl_WorkSession) myWS;           //!< Work session.
+  ReplacerMap                   myReplacerMap;  //!< Map of replacer functions.
+  DuplicateMap                  myDuplicateMap; //!< Map of duplicate entities.
+};
+
+//==================================================================================================
+
+template <typename ProcessedType, typename ProcessedTypeHasher>
+StepTidy_EntityReducer<ProcessedType, ProcessedTypeHasher>::StepTidy_EntityReducer(
+  const Handle(XSControl_WorkSession)& theWS)
+    : myWS(theWS),
+      myReplacerMap(),
+      myDuplicateMap()
+{
+}
+
+//==================================================================================================
+
+template <typename ProcessedType, typename ProcessedTypeHasher>
+bool StepTidy_EntityReducer<ProcessedType, ProcessedTypeHasher>::ProcessEntity(
+  const Handle(Standard_Transient)& theEntity)
+{
+  const Handle(ProcessedType) anEntity = Handle(ProcessedType)::DownCast(theEntity);
+  if (anEntity.IsNull())
+  {
+    return false;
+  }
+  const Interface_Graph&                     aGraph    = myWS->Graph();
+  const Handle(TColStd_HSequenceOfTransient) aSharings = aGraph.GetSharings(anEntity);
+  if (hasAllReplacers(aSharings))
+  {
+    std::vector<Handle(ProcessedType)>* anIter = myDuplicateMap.ChangeSeek(anEntity);
+    if (anIter == nullptr)
+    {
+      // Add as a new key.
+      myDuplicateMap.Bind(anEntity, std::vector<Handle(ProcessedType)>{});
+    }
+    else
+    {
+      // Add as a value.
+      anIter->push_back(anEntity);
+    }
+  }
+
+  return true;
+}
+
+//==================================================================================================
+
+template <typename ProcessedType, typename ProcessedTypeHasher>
+void StepTidy_EntityReducer<ProcessedType, ProcessedTypeHasher>::Perform(
+  TColStd_MapOfTransient& theReplacedEntities)
+{
+  for (typename DuplicateMap::Iterator anIter(myDuplicateMap); anIter.More(); anIter.Next())
+  {
+    const Handle(ProcessedType)&              anEntity    = anIter.Key();
+    const std::vector<Handle(ProcessedType)>& aDuplicates = anIter.Value();
+    if (aDuplicates.empty())
+    {
+      continue;
+    }
+
+    const Interface_Graph& aGraph = myWS->Graph();
+    for (const auto& aDuplicate : aDuplicates)
+    {
+      Handle(TColStd_HSequenceOfTransient) aSharings = aGraph.GetSharings(aDuplicate);
+      if (aSharings.IsNull())
+      {
+        continue;
+      }
+
+      if (replaceInSharings(aDuplicate, anEntity, aSharings))
+      {
+        theReplacedEntities.Add(aDuplicate);
+      }
+    }
+  }
+}
+
+//==================================================================================================
+
+template <typename ProcessedType, typename ProcessedTypeHasher>
+void StepTidy_EntityReducer<ProcessedType, ProcessedTypeHasher>::registerReplacer(
+  const Handle(Standard_Type)& theType,
+  const ReplacerFunction&      theReplacer)
+{
+  myReplacerMap.Bind(theType, theReplacer);
+}
+
+//==================================================================================================
+
+template <typename ProcessedType, typename ProcessedTypeHasher>
+bool StepTidy_EntityReducer<ProcessedType, ProcessedTypeHasher>::hasAllReplacers(
+  const Handle(TColStd_HSequenceOfTransient)& theSharings) const
+{
+  if (theSharings.IsNull())
+  {
+    return false;
+  }
+  return std::all_of(theSharings->cbegin(),
+                     theSharings->cend(),
+                     [this](const Handle(Standard_Transient)& theSharing) {
+                       return myReplacerMap.IsBound(theSharing->DynamicType());
+                     });
+}
+
+//==================================================================================================
+template <typename ProcessedType, typename ProcessedTypeHasher>
+bool StepTidy_EntityReducer<ProcessedType, ProcessedTypeHasher>::replaceInSharings(
+  const Handle(ProcessedType)&                theOldEntity,
+  const Handle(ProcessedType)&                theNewEntity,
+  const Handle(TColStd_HSequenceOfTransient)& theSharings) const
+{
+  bool isAllReplaced = true;
+  for (const auto& aSharing : *theSharings)
+  {
+    if (aSharing.IsNull())
+    {
+      continue;
+    }
+
+    const ReplacerFunction& aReplacer = myReplacerMap.Find(aSharing->DynamicType());
+    if (!aReplacer(theOldEntity, theNewEntity, aSharing))
+    {
+      isAllReplaced = false;
+    }
+  }
+  return isAllReplaced;
+}
+
+#endif // _StepTidy_EntityReducer_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_LineHasher.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_LineHasher.pxx
new file mode 100644 (file)
index 0000000..b1fbff7
--- /dev/null
@@ -0,0 +1,77 @@
+// 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 _StepTidy_LineHasher_HeaderFile
+#define _StepTidy_LineHasher_HeaderFile
+
+#include <StepTidy_CartesianPointHasher.pxx>
+#include <StepTidy_VectorHasher.pxx>
+
+#include <Standard_HashUtils.hxx>
+#include <StepGeom_Line.hxx>
+#include <TCollection_HAsciiString.hxx>
+
+//! OCCT-style hasher for StepGeom_Line entities.
+struct StepTidy_LineHasher
+{
+  // Hashes the Line by its name and Line ratios.
+  std::size_t operator()(const Handle(StepGeom_Line)& theLine) const noexcept
+  {
+    const size_t aHashes[2]{StepTidy_CartesianPointHasher{}(theLine->Pnt()),
+                            StepTidy_VectorHasher{}(theLine->Dir())};
+
+    const size_t aCombinedHash = opencascade::hashBytes(aHashes, sizeof(aHashes));
+    if (theLine->Name().IsNull())
+    {
+      // If the name is not present, return the hash.
+      return aCombinedHash;
+    }
+    // Add the name to the hash if it is present.
+    const size_t aCombinedHashWithName[2]{
+      aCombinedHash,
+      std::hash<TCollection_AsciiString>{}(theLine->Name()->String())};
+    return opencascade::hashBytes(aCombinedHashWithName, sizeof(aCombinedHashWithName));
+  }
+
+  // Compares two Lines by their names and Line ratios.
+  bool operator()(const Handle(StepGeom_Line)& theLine1,
+                  const Handle(StepGeom_Line)& theLine2) const noexcept
+
+  {
+    // Compare names.
+    if (theLine1->Name().IsNull() != theLine2->Name().IsNull())
+    {
+      return false;
+    }
+    if (!theLine1->Name()->IsSameString(theLine2->Name()))
+    {
+      return false;
+    }
+
+    // Compare points.
+    if (!StepTidy_CartesianPointHasher{}(theLine1->Pnt(), theLine2->Pnt()))
+    {
+      return false;
+    }
+
+    // Compare directions.
+    if (!StepTidy_VectorHasher{}(theLine1->Dir(), theLine2->Dir()))
+    {
+      return false;
+    }
+
+    return true;
+  }
+};
+
+#endif // _StepTidy_LineHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_LineReducer.cxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_LineReducer.cxx
new file mode 100644 (file)
index 0000000..4f55d14
--- /dev/null
@@ -0,0 +1,117 @@
+// 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.
+
+#include <StepTidy_LineReducer.pxx>
+
+#include <Interface_Graph.hxx>
+#include <StepShape_EdgeCurve.hxx>
+#include <StepGeom_TrimmedCurve.hxx>
+#include <StepGeom_SurfaceCurve.hxx>
+#include <StepRepr_DefinitionalRepresentation.hxx>
+#include <StepGeom_SeamCurve.hxx>
+
+//==================================================================================================
+
+StepTidy_LineReducer::StepTidy_LineReducer(const Handle(XSControl_WorkSession)& theWS)
+    : StepTidy_EntityReducer<StepGeom_Line, StepTidy_LineHasher>(theWS)
+{
+  registerReplacer(STANDARD_TYPE(StepShape_EdgeCurve), replaceEdgeCurve);
+  registerReplacer(STANDARD_TYPE(StepGeom_TrimmedCurve), replaceTrimmedCurve);
+  registerReplacer(STANDARD_TYPE(StepGeom_SurfaceCurve), replaceSurfaceCurve);
+  registerReplacer(STANDARD_TYPE(StepRepr_DefinitionalRepresentation),
+                   replaceDefinitionalRepresentation);
+  registerReplacer(STANDARD_TYPE(StepGeom_SeamCurve), replaceSeamCurve);
+}
+
+//==================================================================================================
+
+bool StepTidy_LineReducer::replaceEdgeCurve(const Handle(StepGeom_Line)& theOldEntity,
+                                            const Handle(StepGeom_Line)& theNewEntity,
+                                            Handle(Standard_Transient)   theSharing)
+{
+  Handle(StepShape_EdgeCurve) aSharing = Handle(StepShape_EdgeCurve)::DownCast(theSharing);
+  if (aSharing->EdgeGeometry() == theOldEntity)
+  {
+    aSharing->SetEdgeGeometry(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_LineReducer::replaceTrimmedCurve(const Handle(StepGeom_Line)& theOldEntity,
+                                               const Handle(StepGeom_Line)& theNewEntity,
+                                               Handle(Standard_Transient)   theSharing)
+{
+  Handle(StepGeom_TrimmedCurve) aSharing = Handle(StepGeom_TrimmedCurve)::DownCast(theSharing);
+  if (aSharing->BasisCurve() == theOldEntity)
+  {
+    aSharing->SetBasisCurve(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_LineReducer::replaceSurfaceCurve(const Handle(StepGeom_Line)& theOldEntity,
+                                               const Handle(StepGeom_Line)& theNewEntity,
+                                               Handle(Standard_Transient)   theSharing)
+{
+  Handle(StepGeom_SurfaceCurve) aSharing = Handle(StepGeom_SurfaceCurve)::DownCast(theSharing);
+  if (aSharing->Curve3d() == theOldEntity)
+  {
+    aSharing->SetCurve3d(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+
+bool StepTidy_LineReducer::replaceDefinitionalRepresentation(
+  const Handle(StepGeom_Line)& theOldEntity,
+  const Handle(StepGeom_Line)& theNewEntity,
+  Handle(Standard_Transient)   theSharing)
+{
+  Handle(StepRepr_DefinitionalRepresentation) aSharing =
+    Handle(StepRepr_DefinitionalRepresentation)::DownCast(theSharing);
+  bool                                         isReplaced = false;
+  Handle(StepRepr_HArray1OfRepresentationItem) anItems    = aSharing->Items();
+  for (Standard_Integer anIndex = 1; anIndex <= aSharing->NbItems(); ++anIndex)
+  {
+    const Handle(StepRepr_RepresentationItem) aRepItem = anItems->Value(anIndex);
+    if (aRepItem == theOldEntity)
+    {
+      anItems->SetValue(anIndex, theNewEntity);
+      isReplaced = true;
+    }
+  }
+  return isReplaced;
+}
+
+//==================================================================================================
+
+bool StepTidy_LineReducer::replaceSeamCurve(const Handle(StepGeom_Line)& theOldEntity,
+                                            const Handle(StepGeom_Line)& theNewEntity,
+                                            Handle(Standard_Transient)   theSharing)
+{
+  Handle(StepGeom_SeamCurve) aSharing = Handle(StepGeom_SeamCurve)::DownCast(theSharing);
+  if (aSharing->Curve3d() == theOldEntity)
+  {
+    aSharing->SetCurve3d(theNewEntity);
+    return true;
+  }
+  return false;
+}
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_LineReducer.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_LineReducer.pxx
new file mode 100644 (file)
index 0000000..40e0ca6
--- /dev/null
@@ -0,0 +1,83 @@
+// 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 _StepTidy_LineReducer_HeaderFile
+#define _StepTidy_LineReducer_HeaderFile
+
+#include <StepTidy_EntityReducer.pxx>
+#include <StepTidy_LineHasher.pxx>
+
+#include <StepGeom_Line.hxx>
+
+//! Processor for merging StepGeom_Line entities.
+//! This processor merges lines with the same point and direction and names.
+class StepTidy_LineReducer : public StepTidy_EntityReducer<StepGeom_Line, StepTidy_LineHasher>
+{
+public:
+  //! Constructor. Stores the work session and registers replacer functions.
+  //! @param theWS the work session.
+  Standard_EXPORT StepTidy_LineReducer(const Handle(XSControl_WorkSession)& theWS);
+
+private:
+  //! Replacer function for StepShape_EdgeCurve entities.
+  //! Replaces the old entity with the new one in the sharing entity.
+  //! @param theOldEntity the old entity to replace.
+  //! @param theNewEntity the new entity to replace with.
+  //! @param theSharing the sharing entity in which to replace the old entity.
+  //! @return true if the entity was replaced, false otherwise.
+  static bool replaceEdgeCurve(const Handle(StepGeom_Line)& theOldEntity,
+                               const Handle(StepGeom_Line)& theNewEntity,
+                               Handle(Standard_Transient)   theSharing);
+
+  //! Replacer function for StepGeom_TrimmedCurve entities.
+  //! Replaces the old entity with the new one in the sharing entity.
+  //! @param theOldEntity the old entity to replace.
+  //! @param theNewEntity the new entity to replace with.
+  //! @param theSharing the sharing entity in which to replace the old entity.
+  //! @return true if the entity was replaced, false otherwise.
+  static bool replaceTrimmedCurve(const Handle(StepGeom_Line)& theOldEntity,
+                                  const Handle(StepGeom_Line)& theNewEntity,
+                                  Handle(Standard_Transient)   theSharing);
+
+  //! Replacer function for StepGeom_SurfaceCurve entities.
+  //! Replaces the old entity with the new one in the sharing entity.
+  //! @param theOldEntity the old entity to replace.
+  //! @param theNewEntity the new entity to replace with.
+  //! @param theSharing the sharing entity in which to replace the old entity.
+  //! @return true if the entity was replaced, false otherwise.
+  static bool replaceSurfaceCurve(const Handle(StepGeom_Line)& theOldEntity,
+                                  const Handle(StepGeom_Line)& theNewEntity,
+                                  Handle(Standard_Transient)   theSharing);
+
+  //! Replacer function for StepRepr_DefinitionalRepresentation entities.
+  //! Replaces the old entity with the new one in the sharing entity.
+  //! @param theOldEntity the old entity to replace.
+  //! @param theNewEntity the new entity to replace with.
+  //! @param theSharing the sharing entity in which to replace the old entity.
+  //! @return true if the entity was replaced, false otherwise.
+  static bool replaceDefinitionalRepresentation(const Handle(StepGeom_Line)& theOldEntity,
+                                                const Handle(StepGeom_Line)& theNewEntity,
+                                                Handle(Standard_Transient)   theSharing);
+
+  //! Replacer function for StepGeom_SeamCurve entities.
+  //! Replaces the old entity with the new one in the sharing entity.
+  //! @param theOldEntity the old entity to replace.
+  //! @param theNewEntity the new entity to replace with.
+  //! @param theSharing the sharing entity in which to replace the old entity.
+  //! @return true if the entity was replaced, false otherwise.
+  static bool replaceSeamCurve(const Handle(StepGeom_Line)& theOldEntity,
+                               const Handle(StepGeom_Line)& theNewEntity,
+                               Handle(Standard_Transient)   theSharing);
+};
+
+#endif // _StepTidy_LineReducer_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_PlaneHasher.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_PlaneHasher.pxx
new file mode 100644 (file)
index 0000000..28d9347
--- /dev/null
@@ -0,0 +1,60 @@
+// 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 _StepTidy_PlaneHasher_HeaderFile
+#define _StepTidy_PlaneHasher_HeaderFile
+
+#include <StepTidy_Axis2Placement3dHasher.pxx>
+
+#include <Standard_HashUtils.hxx>
+#include <StepGeom_Plane.hxx>
+
+//! OCCT-style hasher for StepGeom_Plane entities.
+struct StepTidy_PlaneHasher
+{
+  // Hashes the axis Planes.
+  std::size_t operator()(const Handle(StepGeom_Plane)& thePlane) const noexcept
+  {
+    const size_t aHash = StepTidy_Axis2Placement3dHasher{}(thePlane->Position());
+    if (thePlane->Name().IsNull())
+    {
+      // If the name is not present, return the hash.
+      return aHash;
+    }
+    // Add the name to the hash if it is present.
+    const size_t aCombinedHashWithName[2]{
+      aHash,
+      std::hash<TCollection_AsciiString>{}(thePlane->Name()->String())};
+    return opencascade::hashBytes(aCombinedHashWithName, sizeof(aCombinedHashWithName));
+  }
+
+  // Compares two axis Planes.
+  bool operator()(const Handle(StepGeom_Plane)& thePlane1,
+                  const Handle(StepGeom_Plane)& thePlane2) const noexcept
+  {
+    // Compare names.
+    if (thePlane1->Name().IsNull() != thePlane2->Name().IsNull())
+    {
+      return false;
+    }
+    if (!thePlane1->Name()->IsSameString(thePlane2->Name()))
+    {
+      return false;
+    }
+
+    // Compare axis Planes.
+    return StepTidy_Axis2Placement3dHasher{}(thePlane1->Position(), thePlane2->Position());
+  }
+};
+
+#endif // _StepTidy_PlaneHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_PlaneReducer.cxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_PlaneReducer.cxx
new file mode 100644 (file)
index 0000000..24e5c62
--- /dev/null
@@ -0,0 +1,55 @@
+// 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.
+
+#include <StepTidy_PlaneReducer.pxx>
+
+#include <StepShape_AdvancedFace.hxx>
+#include <StepGeom_Pcurve.hxx>
+
+//==================================================================================================
+
+StepTidy_PlaneReducer::StepTidy_PlaneReducer(const Handle(XSControl_WorkSession)& theWS)
+    : StepTidy_EntityReducer<StepGeom_Plane, StepTidy_PlaneHasher>(theWS)
+{
+  registerReplacer(STANDARD_TYPE(StepShape_AdvancedFace), replaceAdvancedFace);
+  registerReplacer(STANDARD_TYPE(StepGeom_Pcurve), replacePcurve);
+}
+
+//==================================================================================================
+
+bool StepTidy_PlaneReducer::replaceAdvancedFace(const Handle(StepGeom_Plane)& theOldEntity,
+                                                const Handle(StepGeom_Plane)& theNewEntity,
+                                                Handle(Standard_Transient)    theSharing)
+{
+  Handle(StepShape_AdvancedFace) aSharing = Handle(StepShape_AdvancedFace)::DownCast(theSharing);
+  if (aSharing->FaceGeometry() == theOldEntity)
+  {
+    aSharing->SetFaceGeometry(theNewEntity);
+    return true;
+  }
+  return false;
+}
+
+//==================================================================================================
+bool StepTidy_PlaneReducer::replacePcurve(const Handle(StepGeom_Plane)& theOldEntity,
+                                          const Handle(StepGeom_Plane)& theNewEntity,
+                                          Handle(Standard_Transient)    theSharing)
+{
+  Handle(StepGeom_Pcurve) aSharing = Handle(StepGeom_Pcurve)::DownCast(theSharing);
+  if (aSharing->BasisSurface() == theOldEntity)
+  {
+    aSharing->SetBasisSurface(theNewEntity);
+    return true;
+  }
+  return false;
+}
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_PlaneReducer.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_PlaneReducer.pxx
new file mode 100644 (file)
index 0000000..90d753b
--- /dev/null
@@ -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 _StepTidy_PlaneReducer_HeaderFile
+#define _StepTidy_PlaneReducer_HeaderFile
+
+#include <StepTidy_EntityReducer.pxx>
+#include <StepTidy_PlaneHasher.pxx>
+
+#include <StepGeom_Plane.hxx>
+
+//! Processor for merging StepGeom_Plane entities.
+//! This processor merges planes with the same names and placements.
+class StepTidy_PlaneReducer : public StepTidy_EntityReducer<StepGeom_Plane, StepTidy_PlaneHasher>
+{
+public:
+  //! Constructor. Stores the work session and registers replacer functions.
+  //! @param theWS the work session.
+  Standard_EXPORT StepTidy_PlaneReducer(const Handle(XSControl_WorkSession)& theWS);
+
+private:
+  //! Replacer function for StepShape_AdvancedFace entities.
+  //! Replaces the old entity with the new one in the sharing entity.
+  //! @param theOldEntity the old entity to replace.
+  //! @param theNewEntity the new entity to replace with.
+  //! @param theSharing the sharing StepShape_AdvancedFace in which to replace the old entity.
+  //! @return true if the entity was replaced, false otherwise.
+  static bool replaceAdvancedFace(const Handle(StepGeom_Plane)& theOldEntity,
+                                  const Handle(StepGeom_Plane)& theNewEntity,
+                                  Handle(Standard_Transient)    theSharing);
+
+  //! Replacer function for StepGeom_Pcurve entities.
+  //! Replaces the old entity with the new one in the sharing entity.
+  //! @param theOldEntity the old entity to replace.
+  //! @param theNewEntity the new entity to replace with.
+  //! @param theSharing the sharing StepGeom_Pcurve in which to replace the old entity.
+  //! @return true if the entity was replaced, false otherwise.
+  static bool replacePcurve(const Handle(StepGeom_Plane)& theOldEntity,
+                            const Handle(StepGeom_Plane)& theNewEntity,
+                            Handle(Standard_Transient)    theSharing);
+};
+
+#endif // _StepTidy_DirectionReducer_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_VectorHasher.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_VectorHasher.pxx
new file mode 100644 (file)
index 0000000..7f7d69e
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 _StepTidy_VectorHasher_HeaderFile
+#define _StepTidy_VectorHasher_HeaderFile
+
+#include <StepTidy_DirectionHasher.pxx>
+
+#include <Standard_HashUtils.hxx>
+#include <StepGeom_Vector.hxx>
+#include <TCollection_HAsciiString.hxx>
+
+//! OCCT-style hasher for StepGeom_Vector entities.
+struct StepTidy_VectorHasher
+{
+  // Hashes the Vector by its name and Vector ratios.
+  std::size_t operator()(const Handle(StepGeom_Vector)& theVector) const noexcept
+  {
+    const size_t aHashes[2]{StepTidy_DirectionHasher{}(theVector->Orientation()),
+                            opencascade::hash(static_cast<int>(theVector->Magnitude()))};
+    const size_t aCombinedHash = opencascade::hashBytes(aHashes, sizeof(aHashes));
+    if (theVector->Name().IsNull())
+    {
+      // If the name is not present, return the hash.
+      return aCombinedHash;
+    }
+    // Add the name to the hash if it is present.
+    const size_t aCombinedHashWithName[2]{
+      aCombinedHash,
+      std::hash<TCollection_AsciiString>{}(theVector->Name()->String())};
+    return opencascade::hashBytes(aCombinedHashWithName, sizeof(aCombinedHashWithName));
+  }
+
+  // Compares two Vectors by their names and Vector ratios.
+  bool operator()(const Handle(StepGeom_Vector)& theVector1,
+                  const Handle(StepGeom_Vector)& theVector2) const noexcept
+  {
+    // Compare names.
+    if (theVector1->Name().IsNull() != theVector2->Name().IsNull())
+    {
+      return false;
+    }
+    if (!theVector1->Name()->IsSameString(theVector2->Name()))
+    {
+      return false;
+    }
+
+    // Compare magnitudes.
+    constexpr double aTolerance = 1e-12;
+    if (fabs(theVector1->Magnitude() - theVector2->Magnitude()) > aTolerance)
+    {
+      return false;
+    }
+
+    // Compare orientations.
+    return StepTidy_DirectionHasher{}(theVector1->Orientation(), theVector2->Orientation());
+  }
+};
+
+#endif // _StepTidy_VectorHasher_HeaderFile
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_VectorReducer.cxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_VectorReducer.cxx
new file mode 100644 (file)
index 0000000..94a1a94
--- /dev/null
@@ -0,0 +1,41 @@
+// 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.
+
+#include <StepTidy_VectorReducer.pxx>
+
+#include <Interface_Graph.hxx>
+#include <StepGeom_Line.hxx>
+#include <StepGeom_Vector.hxx>
+
+//==================================================================================================
+
+StepTidy_VectorReducer::StepTidy_VectorReducer(const Handle(XSControl_WorkSession)& theWS)
+    : StepTidy_EntityReducer<StepGeom_Vector, StepTidy_VectorHasher>(theWS)
+{
+  registerReplacer(STANDARD_TYPE(StepGeom_Line), replaceLine);
+}
+
+//==================================================================================================
+
+bool StepTidy_VectorReducer::replaceLine(const Handle(StepGeom_Vector)& theOldEntity,
+                                         const Handle(StepGeom_Vector)& theNewEntity,
+                                         Handle(Standard_Transient)     theSharing)
+{
+  Handle(StepGeom_Line) aLine = Handle(StepGeom_Line)::DownCast(theSharing);
+  if (aLine->Dir() == theOldEntity)
+  {
+    aLine->SetDir(theNewEntity);
+    return true;
+  }
+  return false;
+}
diff --git a/src/DataExchange/TKDESTEP/StepTidy/StepTidy_VectorReducer.pxx b/src/DataExchange/TKDESTEP/StepTidy/StepTidy_VectorReducer.pxx
new file mode 100644 (file)
index 0000000..e69b263
--- /dev/null
@@ -0,0 +1,42 @@
+// 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 _StepTidy_VectorReducer_HeaderFile
+#define _StepTidy_VectorReducer_HeaderFile
+
+#include <StepTidy_EntityReducer.pxx>
+#include <StepTidy_VectorHasher.pxx>
+
+#include <StepGeom_Vector.hxx>
+
+//! Processor for merging StepGeom_Vector entities.
+//! This processor merges vectors with the same orientation and magnitude and names.
+class StepTidy_VectorReducer : public StepTidy_EntityReducer<StepGeom_Vector, StepTidy_VectorHasher>
+{
+public:
+  //! Constructor. Stores the work session and registers replacer functions.
+  //! @param theWS the work session.
+  Standard_EXPORT StepTidy_VectorReducer(const Handle(XSControl_WorkSession)& theWS);
+
+private:
+  //! Replaces the old vector with the new one in the StepGeom_Line entity.
+  //! @param theOldEntity the old vector.
+  //! @param theNewEntity the new vector to replace the old one.
+  //! @param theSharing the StepGeom_Line entity to update.
+  //! @return true if the vector was replaced, false otherwise.
+  static bool replaceLine(const Handle(StepGeom_Vector)& theOldEntity,
+                          const Handle(StepGeom_Vector)& theNewEntity,
+                          Handle(Standard_Transient)     theSharing);
+};
+
+#endif // _StepTidy_VectorReducer_HeaderFile
index a3bd3ac0dad17e32041fab34d4a2ff16501f368e..5889b3be95efc3d8c30294923ed71ef45bff67d1 100644 (file)
@@ -23,7 +23,6 @@
 #include <Draw_ProgressIndicator.hxx>
 #include <Interface_Macros.hxx>
 #include <Interface_Static.hxx>
-#include <MergeSTEPEntities_Merger.hxx>
 #include <Message.hxx>
 #include <OSD_OpenFile.hxx>
 #include <OSD_Parallel.hxx>
@@ -1094,39 +1093,6 @@ static Standard_Integer WriteStep(Draw_Interpretor& theDI,
 
 //=================================================================================================
 
-static Standard_Integer MergeSTEPEntities(Draw_Interpretor& theDI,
-                                          Standard_Integer  theNbArgs,
-                                          const char**      theArgVec)
-{
-  if (theNbArgs < 2)
-  {
-    theDI << "Incorrect number of arguments\n";
-    theDI << "Usage: MergeSTEPEntities input_file output_file\n";
-    return 1;
-  }
-
-  STEPControl_Reader aReader;
-  if (aReader.ReadFile(theArgVec[1]) != IFSelect_RetDone)
-  {
-    theDI << "Error: Cannot read file " << theArgVec[1] << "\n";
-    return 1;
-  }
-
-  MergeSTEPEntities_Merger aMerger(aReader.WS());
-  aMerger.Perform();
-
-  STEPControl_Writer aWriter(aReader.WS(), Standard_False);
-  if (aWriter.Write(theArgVec[2]) != IFSelect_RetDone)
-  {
-    theDI << "Error: Cannot write file " << theArgVec[2] << "\n";
-    return 1;
-  }
-
-  return 0;
-}
-
-//=================================================================================================
-
 void XSDRAWSTEP::Factory(Draw_Interpretor& theDI)
 {
   static Standard_Boolean aIsActivated = Standard_False;
@@ -1179,15 +1145,6 @@ void XSDRAWSTEP::Factory(Draw_Interpretor& theDI)
     WriteStep,
     aGroup);
 
-  theDI.Add("MergeSTEPEntities",
-            "MergeSTEPEntities input_file output_file"
-            "\n\t\t: Merge equal entities in STEP file"
-            "\n\t\t:   input_file  - Step file to read"
-            "\n\t\t:   output_file - Step file to write output to",
-            __FILE__,
-            MergeSTEPEntities,
-            aGroup);
-
   // Load XSDRAW session for pilot activation
   XSDRAW::LoadDraw(theDI);
 }