From 4045a54b6e34008535d3b62a96e1114607bbc562 Mon Sep 17 00:00:00 2001
From: Kirill Gavrilov <kirill@sview.ru>
Date: Wed, 25 Feb 2026 10:16:44 +0300
Subject: [PATCH] Visualization - use gp_GTrsf instead of gp_Trsf for local
 transformation

gp_GTrsf allows to apply non-uniform scaling transformation
to presentations without recomputing their geometry
(e.g. as a preview before applying BRepTools_GTrsfModification operation).

AIS_InteractiveObject now holds gp_GTrsf as Handle(Graphic3d_HGTrsf)
instead of gp_Trsf inside Handle(TopLoc_Datum3D).
This API change will require porting of existing code,
that manages local transformations of interactive objects.

gp_Dir, gp_Pnt, Bnd_Box have been extended with Transform()/Transformed()
methods taking gp_GTrsf on input (in addition to previously existing gp_Trsf).

TODO:
- add tests for visualization and selection;
- check picking of analythical cone/cylinder/sphere with non-uniform scaling;
- check performance implications;
- extend gp_GTrsf with methods extracting rotation part as Quaternion;
- extend `vlocation` command to handle gp_GTrsf in full extent;
- update Upgrade Guide and consider polishing API for smoother transition
  (e.g., add new methods working with gp_GTrsf and
   provide deprecated implementations working with gp_Trsf);
- check if there any use supporting non-uniform gp_GTrsf with HLR;
- check if there any use supporting non-uniform gp_GTrsf with AIS_ConnectedInteractive;
- extend Prs3d_ToolQuadric with support of gp_GTrsf in addition to gp_Trsf.
---
 src/AIS/AIS_ConnectedInteractive.cxx         |  14 +-
 src/AIS/AIS_ConnectedInteractive.hxx         |  10 +-
 src/AIS/AIS_InteractiveContext.cxx           |  38 +++-
 src/AIS/AIS_InteractiveContext.hxx           |   3 +
 src/AIS/AIS_LightSource.cxx                  |  16 +-
 src/AIS/AIS_LightSource.hxx                  |   2 +-
 src/AIS/AIS_Manipulator.cxx                  |  40 ++--
 src/AIS/AIS_Manipulator.hxx                  |  26 +--
 src/AIS/AIS_MultipleConnectedInteractive.cxx |   2 +-
 src/AIS/AIS_MultipleConnectedInteractive.hxx |   8 +-
 src/AIS/AIS_Shape.hxx                        |   6 +-
 src/Bnd/Bnd_Box.cxx                          |  97 ++++++++-
 src/Bnd/Bnd_Box.hxx                          |   9 +
 src/Graphic3d/FILES                          |   1 +
 src/Graphic3d/Graphic3d_CStructure.hxx       |   8 +-
 src/Graphic3d/Graphic3d_CView.cxx            |   6 +-
 src/Graphic3d/Graphic3d_CView.hxx            |   2 +-
 src/Graphic3d/Graphic3d_HGTrsf.hxx           |  23 +++
 src/Graphic3d/Graphic3d_Structure.cxx        |   8 +-
 src/Graphic3d/Graphic3d_Structure.hxx        |   6 +-
 src/Graphic3d/Graphic3d_StructureManager.cxx |   2 +-
 src/Graphic3d/Graphic3d_StructureManager.hxx |   2 +-
 src/Graphic3d/Graphic3d_ZLayerSettings.hxx   |   8 +-
 src/OpenGl/OpenGl_Structure.cxx              |  13 +-
 src/OpenGl/OpenGl_Structure.hxx              |   2 +-
 src/OpenGl/OpenGl_View.hxx                   |   2 +-
 src/OpenGl/OpenGl_View_Raytrace.cxx          |   6 +-
 src/Prs3d/Prs3d.cxx                          |   2 +-
 src/Prs3d/Prs3d.hxx                          |   2 +-
 src/PrsMgr/PrsMgr_PresentableObject.cxx      |  30 +--
 src/PrsMgr/PrsMgr_PresentableObject.hxx      |  34 ++--
 src/PrsMgr/PrsMgr_PresentationManager.cxx    |   7 +-
 src/PrsMgr/PrsMgr_PresentationManager.hxx    |   4 +-
 src/QADraw/QADraw_Tutorials.cxx              |   6 +-
 src/SelectMgr/SelectMgr.cxx                  |  16 +-
 src/SelectMgr/SelectMgr.hxx                  |   4 +-
 src/SelectMgr/SelectMgr_EntityOwner.hxx      |   8 +-
 src/SelectMgr/SelectMgr_SelectableObject.cxx |   2 +-
 src/SelectMgr/SelectMgr_ViewerSelector.cxx   |   2 +-
 src/SelectMgr/SelectMgr_ViewerSelector.hxx   |   2 +-
 src/StdPrs/StdPrs_WFShape.cxx                |   2 +-
 src/StdSelect/StdSelect_BRepOwner.cxx        |   2 +-
 src/StdSelect/StdSelect_BRepOwner.hxx        |   2 +-
 src/V3d/V3d_CircularGrid.cxx                 |   2 +-
 src/V3d/V3d_Plane.cxx                        |   2 +-
 src/V3d/V3d_RectangularGrid.cxx              |   2 +-
 src/ViewerTest/ViewerTest_ObjectCommands.cxx | 197 ++++++++++++++-----
 src/ViewerTest/ViewerTest_ViewerCommands.cxx |  14 +-
 src/gp/gp_Dir.cxx                            |  29 ++-
 src/gp/gp_Dir.hxx                            |  11 ++
 src/gp/gp_GTrsf.hxx                          |   3 +
 src/gp/gp_Pnt.cxx                            |  19 +-
 src/gp/gp_Pnt.hxx                            |  11 ++
 tests/v3d/trsf/affinity                      |  25 +++
 54 files changed, 590 insertions(+), 210 deletions(-)
 create mode 100644 src/Graphic3d/Graphic3d_HGTrsf.hxx
 create mode 100644 tests/v3d/trsf/affinity

diff --git a/src/AIS/AIS_ConnectedInteractive.cxx b/src/AIS/AIS_ConnectedInteractive.cxx
index ad4b70730e..7f6284194a 100644
--- a/src/AIS/AIS_ConnectedInteractive.cxx
+++ b/src/AIS/AIS_ConnectedInteractive.cxx
@@ -49,7 +49,7 @@ AIS_InteractiveObject(aTypeOfPresentation3d)
 //purpose  :
 //=======================================================================
 void AIS_ConnectedInteractive::connect (const Handle(AIS_InteractiveObject)& theAnotherObj,
-                                        const Handle(TopLoc_Datum3D)& theLocation)
+                                        const Handle(Graphic3d_HGTrsf)& theLocation)
 {
   if (myReference == theAnotherObj)
   {
@@ -135,7 +135,7 @@ void AIS_ConnectedInteractive::Compute (const Handle(PrsMgr_PresentationManager)
 //purpose  :
 //=======================================================================
 void AIS_ConnectedInteractive::computeHLR (const Handle(Graphic3d_Camera)& theProjector,
-                                           const Handle(TopLoc_Datum3D)& theTransformation,
+                                           const Handle(Graphic3d_HGTrsf)& theTransformation,
                                            const Handle(Prs3d_Presentation)& thePresentation)
 {
   const bool hasTrsf = !theTransformation.IsNull()
@@ -147,6 +147,9 @@ void AIS_ConnectedInteractive::computeHLR (const Handle(Graphic3d_Camera)& thePr
   }
   if (hasTrsf)
   {
+    if (theTransformation->Form() == gp_Other)
+      throw Standard_NotImplemented("AIS_ConnectedInteractive::computeHLR() - unsupported gp_Other transformation");
+
     const TopLoc_Location& aLocation = myShape.Location();
     TopoDS_Shape aShape = myShape.Located (TopLoc_Location (theTransformation->Trsf()) * aLocation, Standard_False);
     AIS_Shape::computeHlrPresentation (theProjector, thePresentation, aShape, myDrawer);
@@ -181,7 +184,7 @@ void AIS_ConnectedInteractive::updateShape (const Standard_Boolean isWithLocatio
   }
   else
   {
-    myShape = aShape.Moved (TopLoc_Location (Transformation()));
+    myShape = aShape.Moved (TopLoc_Location (Transformation().Trsf()));
   }
 }
 
@@ -211,8 +214,7 @@ void AIS_ConnectedInteractive::ComputeSelection (const Handle(SelectMgr_Selectio
   const Handle(SelectMgr_Selection)& TheRefSel = myReference->Selection (theMode);
   Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner (this);
 
-  TopLoc_Location aLocation (Transformation());
-  anOwner->SetLocation (aLocation);
+  anOwner->SetLocation (TransformationGeom());
 
   if (TheRefSel->IsEmpty())
   {
@@ -278,7 +280,7 @@ void AIS_ConnectedInteractive::computeSubShapeSelection (const Handle(SelectMgr_
   {
     const SensitiveList& aSEList = aMapIt.Value();
     Handle(StdSelect_BRepOwner) anOwner = new StdSelect_BRepOwner (aMapIt.Key(), this, aSEList.First()->OwnerId()->Priority(), Standard_True);
-    anOwner->SetLocation (Transformation());
+    anOwner->SetLocation (TransformationGeom());
     for (SensitiveList::Iterator aListIt (aSEList); aListIt.More(); aListIt.Next())
     {
       if (Handle(Select3D_SensitiveEntity) aNewSE = aListIt.Value()->GetConnected())
diff --git a/src/AIS/AIS_ConnectedInteractive.hxx b/src/AIS/AIS_ConnectedInteractive.hxx
index dc14e2dfd6..a72fe5b8bb 100644
--- a/src/AIS/AIS_ConnectedInteractive.hxx
+++ b/src/AIS/AIS_ConnectedInteractive.hxx
@@ -52,19 +52,19 @@ public:
   
   //! Establishes the connection between the Connected
   //! Interactive Object, anotherIobj, and its reference.
-  void Connect (const Handle(AIS_InteractiveObject)& theAnotherObj) { connect (theAnotherObj, Handle(TopLoc_Datum3D)()); }
+  void Connect (const Handle(AIS_InteractiveObject)& theAnotherObj) { connect (theAnotherObj, Handle(Graphic3d_HGTrsf)()); }
 
   //! Establishes the connection between the Connected
   //! Interactive Object, anotherIobj, and its reference.
   //! Locates instance in aLocation.
   void Connect (const Handle(AIS_InteractiveObject)& theAnotherObj,
-                const gp_Trsf& theLocation)  { connect (theAnotherObj, new TopLoc_Datum3D (theLocation)); }
+                const gp_Trsf& theLocation)  { connect (theAnotherObj, new Graphic3d_HGTrsf (theLocation)); }
 
   //! Establishes the connection between the Connected
   //! Interactive Object, anotherIobj, and its reference.
   //! Locates instance in aLocation.
   void Connect (const Handle(AIS_InteractiveObject)& theAnotherObj,
-                const Handle(TopLoc_Datum3D)& theLocation) { connect (theAnotherObj, theLocation); }
+                const Handle(Graphic3d_HGTrsf)& theLocation) { connect (theAnotherObj, theLocation); }
 
   //! Returns true if there is a connection established
   //! between the presentation and its source reference.
@@ -109,7 +109,7 @@ protected:
 
   //! Computes the presentation according to a point of view.
   Standard_EXPORT virtual void computeHLR (const Handle(Graphic3d_Camera)& theProjector,
-                                           const Handle(TopLoc_Datum3D)& theTrsf,
+                                           const Handle(Graphic3d_HGTrsf)& theTrsf,
                                            const Handle(Prs3d_Presentation)& thePrs) Standard_OVERRIDE;
 
   //! Generates sensitive entities by copying
@@ -125,7 +125,7 @@ protected:
   Standard_EXPORT void updateShape (const Standard_Boolean WithLocation = Standard_True);
 
   Standard_EXPORT void connect (const Handle(AIS_InteractiveObject)& theAnotherObj,
-                                const Handle(TopLoc_Datum3D)& theLocation);
+                                const Handle(Graphic3d_HGTrsf)& theLocation);
 
 protected:
 
diff --git a/src/AIS/AIS_InteractiveContext.cxx b/src/AIS/AIS_InteractiveContext.cxx
index 60c4480ede..58bf799662 100644
--- a/src/AIS/AIS_InteractiveContext.cxx
+++ b/src/AIS/AIS_InteractiveContext.cxx
@@ -1122,6 +1122,37 @@ void AIS_InteractiveContext::SetLocation (const Handle(AIS_InteractiveObject)& t
   }
 }
 
+
+//=======================================================================
+//function : SetLocalTransformation
+//purpose  :
+//=======================================================================
+void AIS_InteractiveContext::SetLocalTransformation(const Handle(AIS_InteractiveObject)& theIObj,
+                                                    const Handle(Graphic3d_HGTrsf)&      theLoc)
+{
+  if (theIObj.IsNull() ||
+      (!theIObj->HasTransformation() && (theLoc.IsNull() || theLoc->Form() == gp_Identity)))
+    return;
+
+  // reset the previous location to properly clean everything...
+  if (theIObj->HasTransformation())
+    theIObj->ResetTransformation();
+
+  theIObj->SetLocalTransformation(theLoc);
+
+  mgrSelector->Update(theIObj, Standard_False);
+
+  // if the object or its part is highlighted dynamically, it is necessary to apply location transformation
+  // to its highlight structure immediately
+  if (!myLastPicked.IsNull() && myLastPicked->IsSameSelectable(theIObj))
+  {
+    const Standard_Integer aHiMod = theIObj->HasHilightMode() ? theIObj->HilightMode() : 0;
+    myLastPicked->UpdateHighlightTrsf(myMainVwr,
+                                      myMainPM,
+                                      aHiMod);
+  }
+}
+
 //=======================================================================
 //function : ResetLocation
 //purpose  :
@@ -1153,7 +1184,7 @@ Standard_Boolean AIS_InteractiveContext::HasLocation (const Handle(AIS_Interacti
 //=======================================================================
 TopLoc_Location AIS_InteractiveContext::Location (const Handle(AIS_InteractiveObject)& theIObj) const
 {
-  return theIObj->Transformation();
+  return theIObj->Transformation().Trsf(); // will throw exception for non-uniform scale in gp_GTrsf
 }
 
 //=======================================================================
@@ -3505,7 +3536,10 @@ TopoDS_Shape AIS_InteractiveContext::SelectedShape() const
     return TopoDS_Shape();
   }
 
-  return anOwner->Shape().Located (anOwner->Location() * anOwner->Shape().Location());
+  if (anOwner->Location().IsNull())
+    anOwner->Shape();
+
+  return anOwner->Shape().Located (anOwner->Location()->Trsf() * anOwner->Shape().Location());
 }
 
 //=======================================================================
diff --git a/src/AIS/AIS_InteractiveContext.hxx b/src/AIS/AIS_InteractiveContext.hxx
index 2e0dcbc69c..0b848b4c9b 100644
--- a/src/AIS/AIS_InteractiveContext.hxx
+++ b/src/AIS/AIS_InteractiveContext.hxx
@@ -322,6 +322,9 @@ public: //! @name object local transformation management
   //! Puts the location on the initial graphic representation and the selection for the Object.
   Standard_EXPORT void SetLocation (const Handle(AIS_InteractiveObject)& theObject, const TopLoc_Location& theLocation);
 
+  //! Puts the location on the initial graphic representation and the selection for the Object.
+  Standard_EXPORT void SetLocalTransformation(const Handle(AIS_InteractiveObject)& theObject, const Handle(Graphic3d_HGTrsf)& theLocation);
+
   //! Puts the Object back into its initial position.
   Standard_EXPORT void ResetLocation (const Handle(AIS_InteractiveObject)& theObject);
 
diff --git a/src/AIS/AIS_LightSource.cxx b/src/AIS/AIS_LightSource.cxx
index f70f4e70d8..f7ae10c4a9 100644
--- a/src/AIS/AIS_LightSource.cxx
+++ b/src/AIS/AIS_LightSource.cxx
@@ -256,7 +256,7 @@ Standard_Boolean AIS_LightSource::ProcessDragging (const Handle(AIS_InteractiveC
   {
     case AIS_DragAction_Start:
     {
-      myLocTrsfStart = LocalTransformation();
+      myLocTrsfStart = LocalTransformation().Trsf();
       return Standard_True;
     }
     case AIS_DragAction_Update:
@@ -433,7 +433,7 @@ void AIS_LightSource::updateLightLocalTransformation()
       {
         gp_Trsf aTrsf;
         aTrsf.SetTranslation (gp::Origin(), myLightSource->Position());
-        myLocalTransformation = new TopLoc_Datum3D (aTrsf);
+        myLocalTransformation = new Graphic3d_HGTrsf (aTrsf);
       }
       break;
     }
@@ -445,7 +445,7 @@ void AIS_LightSource::updateLightLocalTransformation()
       gp_Trsf aTrsf;
       const gp_Ax2 anAx2 (aLightPos, -myLightSource->Direction());
       aTrsf.SetTransformation (anAx2, gp_Ax3());
-      myLocalTransformation = new TopLoc_Datum3D (aTrsf);
+      myLocalTransformation = new Graphic3d_HGTrsf (aTrsf);
       break;
     }
     case Graphic3d_TypeOfLightSource_Positional:
@@ -454,7 +454,7 @@ void AIS_LightSource::updateLightLocalTransformation()
       {
         gp_Trsf aTrsf;
         aTrsf.SetTranslation (gp::Origin(), myLightSource->Position());
-        myLocalTransformation = new TopLoc_Datum3D (aTrsf);
+        myLocalTransformation = new Graphic3d_HGTrsf (aTrsf);
       }
       break;
     }
@@ -463,7 +463,7 @@ void AIS_LightSource::updateLightLocalTransformation()
       gp_Trsf aTrsf;
       const gp_Ax2 anAx2 (myIsZoomable ? myLightSource->Position() : gp::Origin(), -myLightSource->Direction());
       aTrsf.SetTransformation (anAx2, gp_Ax3());
-      myLocalTransformation = new TopLoc_Datum3D (aTrsf);
+      myLocalTransformation = new Graphic3d_HGTrsf (aTrsf);
       break;
     }
   }
@@ -474,9 +474,9 @@ void AIS_LightSource::updateLightLocalTransformation()
 // function : setLocalTransformation
 // purpose  :
 // =======================================================================
-void AIS_LightSource::setLocalTransformation (const Handle(TopLoc_Datum3D)& theTrsf)
+void AIS_LightSource::setLocalTransformation (const Handle(Graphic3d_HGTrsf)& theTrsf)
 {
-  const gp_Trsf aTrsf = !theTrsf.IsNull() ? theTrsf->Transformation() : gp_Trsf();
+  const gp_GTrsf aTrsf = !theTrsf.IsNull() ? *theTrsf : gp_GTrsf();
   switch (myLightSource->Type())
   {
     case Graphic3d_TypeOfLightSource_Ambient:
@@ -511,7 +511,7 @@ void AIS_LightSource::setLocalTransformation (const Handle(TopLoc_Datum3D)& theT
     }
   }
 
-  base_type::setLocalTransformation (new TopLoc_Datum3D (aTrsf));
+  base_type::setLocalTransformation (new Graphic3d_HGTrsf (aTrsf));
 
   updateLightAspects();
   updateLightTransformPersistence();
diff --git a/src/AIS/AIS_LightSource.hxx b/src/AIS/AIS_LightSource.hxx
index 8edf24d471..6dd123f584 100644
--- a/src/AIS/AIS_LightSource.hxx
+++ b/src/AIS/AIS_LightSource.hxx
@@ -221,7 +221,7 @@ protected:
                                                             const AIS_DragAction theAction) Standard_OVERRIDE;
 
   //! Sets new local transformation, which is propagated to Graphic3d_CLight instance.
-  Standard_EXPORT virtual void setLocalTransformation (const Handle(TopLoc_Datum3D)& theTrsf) Standard_OVERRIDE;
+  Standard_EXPORT virtual void setLocalTransformation (const Handle(Graphic3d_HGTrsf)& theTrsf) Standard_OVERRIDE;
 
   //! Updates local transformation basing on a type of light source.
   Standard_EXPORT virtual void updateLightLocalTransformation();
diff --git a/src/AIS/AIS_Manipulator.cxx b/src/AIS/AIS_Manipulator.cxx
index b42cedcda4..a05b8afa45 100644
--- a/src/AIS/AIS_Manipulator.cxx
+++ b/src/AIS/AIS_Manipulator.cxx
@@ -395,7 +395,7 @@ Handle(AIS_InteractiveObject) AIS_Manipulator::Object() const
 //purpose  :
 //=======================================================================
 Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer theMaxX, const Standard_Integer theMaxY,
-                                                        const Handle(V3d_View)& theView, gp_Trsf& theTrsf)
+                                                        const Handle(V3d_View)& theView, gp_GTrsf& theTrsf)
 {
   // Initialize start reference data
   if (!myHasStartedTransformation)
@@ -403,7 +403,7 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
     myStartTrsfs.Clear();
     Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
     for (AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects); anObjIter.More(); anObjIter.Next())
-      myStartTrsfs.Append (anObjIter.Value()->LocalTransformation());
+      myStartTrsfs.Append (anObjIter.Value()->LocalTransformationGeom());
 
     myStartPosition = myPosition;
   }
@@ -445,7 +445,7 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
       if (myCurrentMode == AIS_MM_Translation)
       {
         aNewTrsf.SetTranslation (gp_Vec(myStartPick, aNewPosition));
-        theTrsf *= aNewTrsf;
+        theTrsf *= gp_GTrsf(aNewTrsf);
       }
       else if (myCurrentMode == AIS_MM_Scaling)
       {
@@ -503,7 +503,7 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
 
       gp_Trsf aNewTrsf;
       aNewTrsf.SetRotation (aCurrAxis, anAngle);
-      theTrsf *= aNewTrsf;
+      theTrsf *= gp_GTrsf(aNewTrsf);
       myPrevState = anAngle;
       return Standard_True;
     }
@@ -532,7 +532,7 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
 
       gp_Trsf aNewTrsf;
       aNewTrsf.SetTranslation(gp_Vec(myStartPick, aNewPosition));
-      theTrsf *= aNewTrsf;
+      theTrsf *= gp_GTrsf(aNewTrsf);
       return Standard_True;
     }
     case AIS_MM_None:
@@ -583,7 +583,7 @@ Standard_Boolean AIS_Manipulator::ProcessDragging (const Handle(AIS_InteractiveC
 
       // update selection manager for moved objects
       for (const Handle(AIS_InteractiveObject)& anObjIter : *anObjects)
-        anObjIter->InteractiveContext()->SetLocation(anObjIter, anObjIter->LocalTransformation());
+        anObjIter->InteractiveContext()->SetLocalTransformation (anObjIter, anObjIter->LocalTransformationGeom());
 
       break;
     }
@@ -600,7 +600,7 @@ void AIS_Manipulator::StartTransform (const Standard_Integer theX, const Standar
   if (myHasStartedTransformation)
     return;
 
-  gp_Trsf aTrsf;
+  gp_GTrsf aTrsf;
   ObjectTransformation (theX, theY, theView, aTrsf);
 }
 
@@ -619,9 +619,9 @@ void AIS_Manipulator::StopTransform (const Standard_Boolean theToApply)
 
   Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
   AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects);
-  NCollection_Sequence<gp_Trsf>::Iterator aTrsfIter (myStartTrsfs);
+  NCollection_Sequence<Handle(Graphic3d_HGTrsf)>::Iterator aTrsfIter (myStartTrsfs);
   for (; anObjIter.More(); anObjIter.Next(), aTrsfIter.Next())
-    anObjIter.Value()->InteractiveContext()->SetLocation(anObjIter.Value(), aTrsfIter.Value());
+    anObjIter.Value()->InteractiveContext()->SetLocalTransformation(anObjIter.Value(), aTrsfIter.Value());
 
   SetPosition (myStartPosition);
 }
@@ -630,7 +630,7 @@ void AIS_Manipulator::StopTransform (const Standard_Boolean theToApply)
 //function : Transform
 //purpose  : 
 //=======================================================================
-void AIS_Manipulator::Transform (const gp_Trsf& theTrsf)
+void AIS_Manipulator::Transform (const gp_GTrsf& theTrsf)
 {
   if (!IsAttached() || !myHasStartedTransformation)
     return;
@@ -638,19 +638,19 @@ void AIS_Manipulator::Transform (const gp_Trsf& theTrsf)
   {
     Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
     AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects);
-    NCollection_Sequence<gp_Trsf>::Iterator aTrsfIter (myStartTrsfs);
+    NCollection_Sequence<Handle(Graphic3d_HGTrsf)>::Iterator aTrsfIter (myStartTrsfs);
     for (; anObjIter.More(); anObjIter.Next(), aTrsfIter.Next())
     {
       const Handle(AIS_InteractiveObject)& anObj = anObjIter.ChangeValue();
-      const gp_Trsf& anOldTrsf = aTrsfIter.Value();
-      const Handle(TopLoc_Datum3D)& aParentTrsf = anObj->CombinedParentTransformation();
+      const gp_GTrsf anOldTrsf = !aTrsfIter.Value().IsNull() ? *aTrsfIter.Value() : gp_GTrsf();
+      const Handle(Graphic3d_HGTrsf)& aParentTrsf = anObj->CombinedParentTransformation();
       // intentionally avoid calling AIS_InteractiveConext::SetLocation()
       // to postpone invalidation of selection manager
       if (!aParentTrsf.IsNull()
         && aParentTrsf->Form() != gp_Identity)
       {
         // recompute local transformation relative to parent transformation
-        const gp_Trsf aNewLocalTrsf = aParentTrsf->Trsf().Inverted() * theTrsf * aParentTrsf->Trsf() * anOldTrsf;
+        const gp_GTrsf aNewLocalTrsf = aParentTrsf->Inverted() * theTrsf * (*aParentTrsf) * anOldTrsf;
         anObj->SetLocalTransformation (aNewLocalTrsf);
       }
       else
@@ -675,10 +675,10 @@ void AIS_Manipulator::Transform (const gp_Trsf& theTrsf)
 //function : Transform
 //purpose  :
 //=======================================================================
-gp_Trsf AIS_Manipulator::Transform (const Standard_Integer thePX, const Standard_Integer thePY,
-                                    const Handle(V3d_View)& theView)
+gp_GTrsf AIS_Manipulator::Transform (const Standard_Integer thePX, const Standard_Integer thePY,
+                                     const Handle(V3d_View)& theView)
 {
-  gp_Trsf aTrsf;
+  gp_GTrsf aTrsf;
   if (ObjectTransformation (thePX, thePY, theView, aTrsf))
     Transform (aTrsf);
 
@@ -722,7 +722,7 @@ void AIS_Manipulator::updateTransformation()
     aTrsf.SetTransformation (gp_Ax2 (gp::Origin(), aVDir, aXDir), gp::XOY());
   }
 
-  Handle(TopLoc_Datum3D) aGeomTrsf = new TopLoc_Datum3D (aTrsf);
+  Handle(Graphic3d_HGTrsf) aGeomTrsf = new Graphic3d_HGTrsf (aTrsf);
   // we explicitly call here setLocalTransformation() of the base class
   // since AIS_Manipulator::setLocalTransformation() implementation throws exception
   // as protection from external calls
@@ -844,7 +844,7 @@ void AIS_Manipulator::setTransformPersistence (const Handle(Graphic3d_TransformP
 //function : setLocalTransformation
 //purpose  :
 //=======================================================================
-void AIS_Manipulator::setLocalTransformation (const Handle(TopLoc_Datum3D)& /*theTrsf*/)
+void AIS_Manipulator::setLocalTransformation (const Handle(Graphic3d_HGTrsf)& /*theTrsf*/)
 {
   Standard_ASSERT_INVOKE ("AIS_Manipulator::setLocalTransformation: "
                           "Custom transformation is not supported by this class");
@@ -1325,7 +1325,7 @@ void AIS_Manipulator::Axis::SetTransformPersistence(const Handle(Graphic3d_Trans
 //class    : Axis
 //function : Transform
 //=======================================================================
-void AIS_Manipulator::Axis::Transform(const Handle(TopLoc_Datum3D)& theTransformation)
+void AIS_Manipulator::Axis::Transform(const Handle(Graphic3d_HGTrsf)& theTransformation)
 {
   if (!myHighlightTranslator.IsNull())
     myHighlightTranslator->SetTransformation(theTransformation);
diff --git a/src/AIS/AIS_Manipulator.hxx b/src/AIS/AIS_Manipulator.hxx
index de9367f404..39c43879fc 100644
--- a/src/AIS/AIS_Manipulator.hxx
+++ b/src/AIS/AIS_Manipulator.hxx
@@ -169,7 +169,7 @@ public:
                                                             const AIS_DragAction theAction) Standard_OVERRIDE;
 
   //! Init start (reference) transformation.
-  //! @warning It is used in chain with StartTransform-Transform(gp_Trsf)-StopTransform
+  //! @warning It is used in chain with StartTransform-Transform(gp_GTrsf)-StopTransform
   //! and is used only for custom transform set. If Transform(const Standard_Integer, const Standard_Integer) is used,
   //! initial data is set automatically, and it is reset on DeactivateCurrentMode call if it is not reset yet.
   Standard_EXPORT void StartTransform (const Standard_Integer theX, const Standard_Integer theY, const Handle(V3d_View)& theView);
@@ -178,29 +178,29 @@ public:
   //! @remark The transformation is set using SetLocalTransformation for owning objects.
   //! The location of the manipulator is stored also in Local Transformation,
   //! so that there's no need to redisplay objects.
-  //! @warning It is used in chain with StartTransform-Transform(gp_Trsf)-StopTransform
+  //! @warning It is used in chain with StartTransform-Transform(gp_GTrsf)-StopTransform
   //! and is used only for custom transform set.
   //! @warning It will does nothing if transformation is not initiated (with StartTransform() call).
-  Standard_EXPORT void Transform (const gp_Trsf& aTrsf);
+  Standard_EXPORT void Transform (const gp_GTrsf& aTrsf);
 
   //! Reset start (reference) transformation.
   //! @param[in] theToApply  option to apply or to cancel the started transformation.
-  //! @warning It is used in chain with StartTransform-Transform(gp_Trsf)-StopTransform
+  //! @warning It is used in chain with StartTransform-Transform(gp_GTrsf)-StopTransform
   //! and is used only for custom transform set.
   Standard_EXPORT void StopTransform (const Standard_Boolean theToApply = Standard_True);
 
   //! Apply transformation made from mouse moving from start position
   //! (save on the first Transform() call and reset on DeactivateCurrentMode() call.)
   //! to the in/out mouse position (theX, theY)
-  Standard_EXPORT gp_Trsf Transform (const Standard_Integer theX, const Standard_Integer theY,
-                                     const Handle(V3d_View)& theView);
+  Standard_EXPORT gp_GTrsf Transform (const Standard_Integer theX, const Standard_Integer theY,
+                                      const Handle(V3d_View)& theView);
 
   //! Computes transformation of parent object according to the active mode and input motion vector.
   //! You can use this method to get object transformation according to current mode or use own algorithm
   //! to implement any other transformation for modes.
   //! @return transformation of parent object.
   Standard_EXPORT Standard_Boolean ObjectTransformation (const Standard_Integer theX, const Standard_Integer theY,
-                                                         const Handle(V3d_View)& theView, gp_Trsf& theTrsf);
+                                                         const Handle(V3d_View)& theView, gp_GTrsf& theTrsf);
 
   //! Make inactive the current selected manipulator part and reset current axis index and current mode.
   //! After its call HasActiveMode() returns false.
@@ -228,13 +228,13 @@ public:
 
   Standard_Boolean HasActiveTransformation() { return myHasStartedTransformation; }
 
-  gp_Trsf StartTransformation() const { return !myStartTrsfs.IsEmpty() ? myStartTrsfs.First() : gp_Trsf(); }
+  Handle(Graphic3d_HGTrsf) StartTransformation() const { return !myStartTrsfs.IsEmpty() ? myStartTrsfs.First() : Handle(Graphic3d_HGTrsf)(); }
 
-  gp_Trsf StartTransformation (Standard_Integer theIndex) const
+  Handle(Graphic3d_HGTrsf) StartTransformation (Standard_Integer theIndex) const
   {
     Standard_ProgramError_Raise_if (theIndex < 1 || theIndex > Objects()->Upper(),
       "AIS_Manipulator::StartTransformation(): theIndex is out of bounds");
-    return !myStartTrsfs.IsEmpty() ? myStartTrsfs (theIndex) : gp_Trsf();
+    return !myStartTrsfs.IsEmpty() ? myStartTrsfs (theIndex) : Handle(Graphic3d_HGTrsf)();
   }
 
 public: //! @name Configuration of graphical transformations
@@ -361,7 +361,7 @@ protected:
   //! without need for recomputing presentation.
   //! @warning Invokes debug assertion in debug to catch incompatible usage of the
   //! method, silently does nothing in release mode.
-  Standard_EXPORT virtual void setLocalTransformation (const Handle(TopLoc_Datum3D)& theTrsf) Standard_OVERRIDE;
+  Standard_EXPORT virtual void setLocalTransformation (const Handle(Graphic3d_HGTrsf)& theTrsf) Standard_OVERRIDE;
   using AIS_InteractiveObject::SetLocalTransformation; // hide visibility
 
 protected: //! @name Auxiliary classes to fill presentation with proper primitives
@@ -391,7 +391,7 @@ protected: //! @name Auxiliary classes to fill presentation with proper primitiv
 
     Standard_EXPORT void SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers);
 
-    Standard_EXPORT void Transform (const Handle(TopLoc_Datum3D)& theTransformation);
+    Standard_EXPORT void Transform (const Handle(Graphic3d_HGTrsf)& theTransformation);
 
     Standard_Boolean HasTranslation() const { return myHasTranslation; }
 
@@ -525,7 +525,7 @@ protected:
 
 protected: //! @name Fields for interactive transformation. Fields only for internal needs. They do not have public interface.
 
-  NCollection_Sequence<gp_Trsf> myStartTrsfs; //!< Owning object transformation for start. It is used internally.
+  NCollection_Sequence<Handle(Graphic3d_HGTrsf)> myStartTrsfs; //!< Owning object transformation for start. It is used internally.
   Standard_Boolean myHasStartedTransformation; //!< Shows if transformation is processed (sequential calls of Transform()).
   gp_Ax2 myStartPosition; //! Start position of manipulator.
   gp_Pnt myStartPick; //! 3d point corresponding to start mouse pick.
diff --git a/src/AIS/AIS_MultipleConnectedInteractive.cxx b/src/AIS/AIS_MultipleConnectedInteractive.cxx
index 90383d0dd3..d14fd79c2d 100644
--- a/src/AIS/AIS_MultipleConnectedInteractive.cxx
+++ b/src/AIS/AIS_MultipleConnectedInteractive.cxx
@@ -39,7 +39,7 @@ AIS_MultipleConnectedInteractive::AIS_MultipleConnectedInteractive()
 //purpose  :
 //=======================================================================
 Handle(AIS_InteractiveObject) AIS_MultipleConnectedInteractive::connect (const Handle(AIS_InteractiveObject)& theAnotherObj,
-                                                                         const Handle(TopLoc_Datum3D)& theTrsf,
+                                                                         const Handle(Graphic3d_HGTrsf)& theTrsf,
                                                                          const Handle(Graphic3d_TransformPers)& theTrsfPers)
 {
   if (myAssemblyOwner.IsNull())
diff --git a/src/AIS/AIS_MultipleConnectedInteractive.hxx b/src/AIS/AIS_MultipleConnectedInteractive.hxx
index ab11283d6b..9ba01cc9c2 100644
--- a/src/AIS/AIS_MultipleConnectedInteractive.hxx
+++ b/src/AIS/AIS_MultipleConnectedInteractive.hxx
@@ -38,7 +38,7 @@ public:
   //! Locates instance in theLocation and applies specified transformation persistence mode.
   //! @return created instance object (AIS_ConnectedInteractive or AIS_MultipleConnectedInteractive)
   Handle(AIS_InteractiveObject) Connect (const Handle(AIS_InteractiveObject)& theAnotherObj,
-                                         const Handle(TopLoc_Datum3D)& theLocation,
+                                         const Handle(Graphic3d_HGTrsf)& theLocation,
                                          const Handle(Graphic3d_TransformPers)& theTrsfPers)
   {
     return connect (theAnotherObj, theLocation, theTrsfPers);
@@ -86,7 +86,7 @@ public: // short aliases to Connect() method
   Handle(AIS_InteractiveObject) Connect (const Handle(AIS_InteractiveObject)& theAnotherObj,
                                          const gp_Trsf& theLocation)
   {
-    return connect (theAnotherObj, new TopLoc_Datum3D (theLocation), theAnotherObj->TransformPersistence());
+    return connect (theAnotherObj, new Graphic3d_HGTrsf (theLocation), theAnotherObj->TransformPersistence());
   }
 
   //! Establishes the connection between the Connected Interactive Object, theInteractive, and its reference.
@@ -96,7 +96,7 @@ public: // short aliases to Connect() method
                                          const gp_Trsf& theLocation,
                                          const Handle(Graphic3d_TransformPers)& theTrsfPers)
   {
-    return connect (theAnotherObj, new TopLoc_Datum3D (theLocation), theTrsfPers);
+    return connect (theAnotherObj, new Graphic3d_HGTrsf (theLocation), theTrsfPers);
   }
 
 protected:
@@ -115,7 +115,7 @@ protected:
   //! Locates instance in theLocation and applies specified transformation persistence mode.
   //! @return created instance object (AIS_ConnectedInteractive or AIS_MultipleConnectedInteractive)
   Standard_EXPORT virtual Handle(AIS_InteractiveObject) connect (const Handle(AIS_InteractiveObject)& theInteractive,
-                                                                 const Handle(TopLoc_Datum3D)& theLocation,
+                                                                 const Handle(Graphic3d_HGTrsf)& theLocation,
                                                                  const Handle(Graphic3d_TransformPers)& theTrsfPers);
 
 private:
diff --git a/src/AIS/AIS_Shape.hxx b/src/AIS/AIS_Shape.hxx
index 5af2f0ba55..00cd8ae88c 100644
--- a/src/AIS/AIS_Shape.hxx
+++ b/src/AIS/AIS_Shape.hxx
@@ -259,12 +259,16 @@ protected:
 
   //! Compute projected presentation.
   virtual void computeHLR (const Handle(Graphic3d_Camera)& theProjector,
-                           const Handle(TopLoc_Datum3D)& theTrsf,
+                           const Handle(Graphic3d_HGTrsf)& theTrsf,
                            const Handle(Prs3d_Presentation)& thePrs) Standard_OVERRIDE
   {
     if (!theTrsf.IsNull()
       && theTrsf->Form() != gp_Identity)
     {
+      if (theTrsf->Form() == gp_Other)
+      {
+        throw Standard_ProgramError("AIS_Shape::computeHLR() - gp_Other transformation is unsupported by HLR");
+      }
       const TopLoc_Location& aLoc = myshape.Location();
       const TopoDS_Shape aShape = myshape.Located (TopLoc_Location (theTrsf->Trsf()) * aLoc);
       computeHlrPresentation (theProjector, thePrs, aShape, myDrawer);
diff --git a/src/Bnd/Bnd_Box.cxx b/src/Bnd/Bnd_Box.cxx
index 7c66d0faae..bfdcab1a64 100644
--- a/src/Bnd/Bnd_Box.cxx
+++ b/src/Bnd/Bnd_Box.cxx
@@ -18,7 +18,7 @@
 #include <gp_Dir.hxx>
 #include <gp_Pln.hxx>
 #include <gp_Pnt.hxx>
-#include <gp_Trsf.hxx>
+#include <gp_GTrsf.hxx>
 #include <Standard_ConstructionError.hxx>
 #include <Standard_Dump.hxx>
 
@@ -395,6 +395,101 @@ Bnd_Box Bnd_Box::Transformed (const gp_Trsf& T) const
   return aNewBox;
 }
 
+//=======================================================================
+//function : Transformed
+//purpose  :
+//=======================================================================
+
+Bnd_Box Bnd_Box::Transformed(const gp_GTrsf& T) const
+{
+  if (IsVoid())
+  {
+    return Bnd_Box();
+  }
+  else if (T.Form() == gp_Identity)
+  {
+    return *this;
+  }
+  else if (T.Form() == gp_Translation)
+  {
+    if (!HasFinitePart())
+    {
+      return *this;
+    }
+
+    const gp_XYZ& aDelta = T.TranslationPart();
+    Bnd_Box aNewBox(*this);
+    aNewBox.Xmin += aDelta.X();
+    aNewBox.Xmax += aDelta.X();
+    aNewBox.Ymin += aDelta.Y();
+    aNewBox.Ymax += aDelta.Y();
+    aNewBox.Zmin += aDelta.Z();
+    aNewBox.Zmax += aDelta.Z();
+    return aNewBox;
+  }
+
+  Bnd_Box aNewBox;
+  if (HasFinitePart())
+  {
+    gp_Pnt aCorners[8] =
+    {
+      gp_Pnt(Xmin, Ymin, Zmin),
+      gp_Pnt(Xmax, Ymin, Zmin),
+      gp_Pnt(Xmin, Ymax, Zmin),
+      gp_Pnt(Xmax, Ymax, Zmin),
+      gp_Pnt(Xmin, Ymin, Zmax),
+      gp_Pnt(Xmax, Ymin, Zmax),
+      gp_Pnt(Xmin, Ymax, Zmax),
+      gp_Pnt(Xmax, Ymax, Zmax),
+    };
+    for (Standard_Integer aCornerIter = 0; aCornerIter < 8; ++aCornerIter)
+    {
+      aCorners[aCornerIter].Transform(T);
+      aNewBox.Add(aCorners[aCornerIter]);
+    }
+  }
+  aNewBox.Gap = Gap;
+  if (!IsOpen())
+  {
+    return aNewBox;
+  }
+
+  gp_Dir aDirs[6];
+  Standard_Integer aNbDirs = 0;
+  if (IsOpenXmin())
+  {
+    aDirs[aNbDirs++].SetCoord(-1., 0., 0.);
+  }
+  if (IsOpenXmax())
+  {
+    aDirs[aNbDirs++].SetCoord(1., 0., 0.);
+  }
+  if (IsOpenYmin())
+  {
+    aDirs[aNbDirs++].SetCoord(0., -1., 0.);
+  }
+  if (IsOpenYmax())
+  {
+    aDirs[aNbDirs++].SetCoord(0., 1., 0.);
+  }
+  if (IsOpenZmin())
+  {
+    aDirs[aNbDirs++].SetCoord(0., 0., -1.);
+  }
+  if (IsOpenZmax())
+  {
+    aDirs[aNbDirs++].SetCoord(0., 0., 1.);
+  }
+
+  for (Standard_Integer aDirIter = 0; aDirIter < aNbDirs; ++aDirIter)
+  {
+    aDirs[aDirIter].Transform(T);
+    aNewBox.Add(aDirs[aDirIter]);
+  }
+
+  return aNewBox;
+}
+
 //=======================================================================
 //function : Add
 //purpose  : 
diff --git a/src/Bnd/Bnd_Box.hxx b/src/Bnd/Bnd_Box.hxx
index f9390cb87f..7bfb79280f 100644
--- a/src/Bnd/Bnd_Box.hxx
+++ b/src/Bnd/Bnd_Box.hxx
@@ -27,6 +27,7 @@
 class gp_Pnt;
 class gp_Dir;
 class gp_Trsf;
+class gp_GTrsf;
 class gp_Lin;
 class gp_Pln;
 
@@ -218,6 +219,14 @@ public:
   //! rotation) to a bounding box generally increases its
   //! dimensions. This is not optimal for algorithms which use it.
   Standard_NODISCARD Standard_EXPORT Bnd_Box Transformed (const gp_Trsf& T) const;
+
+  //! Returns a bounding box which is the result of applying the
+  //! transformation T to this bounding box.
+  //! Warning
+  //! Applying a geometric transformation (for example, a
+  //! rotation) to a bounding box generally increases its
+  //! dimensions. This is not optimal for algorithms which use it.
+  Standard_NODISCARD Standard_EXPORT Bnd_Box Transformed(const gp_GTrsf& T) const;
   
   //! Adds the box <Other> to <me>.
   Standard_EXPORT void Add (const Bnd_Box& Other);
diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES
index 7cf38a2579..b2a4ba7368 100755
--- a/src/Graphic3d/FILES
+++ b/src/Graphic3d/FILES
@@ -82,6 +82,7 @@ Graphic3d_GroupAspect.hxx
 Graphic3d_GroupDefinitionError.hxx
 Graphic3d_HatchStyle.hxx
 Graphic3d_HatchStyle.cxx
+Graphic3d_HGTrsf.hxx
 Graphic3d_PresentationAttributes.hxx
 Graphic3d_PresentationAttributes.cxx
 Graphic3d_HorizontalTextAlignment.hxx
diff --git a/src/Graphic3d/Graphic3d_CStructure.hxx b/src/Graphic3d/Graphic3d_CStructure.hxx
index 8138cd165f..b01ebe51df 100644
--- a/src/Graphic3d/Graphic3d_CStructure.hxx
+++ b/src/Graphic3d/Graphic3d_CStructure.hxx
@@ -22,7 +22,7 @@
 #include <Graphic3d_ViewAffinity.hxx>
 #include <Graphic3d_TransformPers.hxx>
 #include <Graphic3d_ZLayerId.hxx>
-#include <TopLoc_Datum3D.hxx>
+#include <Graphic3d_HGTrsf.hxx>
 #include <NCollection_IndexedMap.hxx>
 
 class Graphic3d_GraphicDriver;
@@ -77,10 +77,10 @@ public:
   }
 
   //! Return transformation.
-  const Handle(TopLoc_Datum3D)& Transformation() const { return myTrsf; }
+  const Handle(Graphic3d_HGTrsf)& Transformation() const { return myTrsf; }
 
   //! Assign transformation.
-  virtual void SetTransformation (const Handle(TopLoc_Datum3D)& theTrsf) { myTrsf = theTrsf; }
+  virtual void SetTransformation (const Handle(Graphic3d_HGTrsf)& theTrsf) { myTrsf = theTrsf; }
 
   //! Return transformation persistence.
   const Handle(Graphic3d_TransformPers)& TransformPersistence() const { return myTrsfPers; }
@@ -229,7 +229,7 @@ protected:
   Handle(Graphic3d_GraphicDriver) myGraphicDriver;
   Graphic3d_SequenceOfGroup       myGroups;
   Graphic3d_BndBox3d              myBndBox;
-  Handle(TopLoc_Datum3D)          myTrsf;
+  Handle(Graphic3d_HGTrsf)        myTrsf;
   Handle(Graphic3d_TransformPers) myTrsfPers;
   Handle(Graphic3d_SequenceOfHClipPlane) myClipPlanes;
   Handle(Graphic3d_PresentationAttributes) myHighlightStyle; //! Current highlight style; is set only if highlight flag is true
diff --git a/src/Graphic3d/Graphic3d_CView.cxx b/src/Graphic3d/Graphic3d_CView.cxx
index 6f38c05b88..aae3c45787 100644
--- a/src/Graphic3d/Graphic3d_CView.cxx
+++ b/src/Graphic3d/Graphic3d_CView.cxx
@@ -457,7 +457,7 @@ void Graphic3d_CView::ReCompute (const Handle(Graphic3d_Structure)& theStruct)
   // compute + validation
   Handle(Graphic3d_Structure) aCompStructOld = myStructsComputed.ChangeValue (anIndex);
   Handle(Graphic3d_Structure) aCompStruct    = aCompStructOld;
-  aCompStruct->SetTransformation (Handle(TopLoc_Datum3D)());
+  aCompStruct->SetTransformation (Handle(Graphic3d_HGTrsf)());
   theStruct->computeHLR (myCamera, aCompStruct);
   if (aCompStruct.IsNull())
   {
@@ -900,7 +900,7 @@ void Graphic3d_CView::Display (const Handle(Graphic3d_Structure)& theStructure)
   if (anIndex != 0)
   {
     aStruct = myStructsComputed.Value (anIndex);
-    aStruct->SetTransformation (Handle(TopLoc_Datum3D)());
+    aStruct->SetTransformation (Handle(Graphic3d_HGTrsf)());
   }
   theStructure->computeHLR (myCamera, aStruct);
   if (aStruct.IsNull())
@@ -1006,7 +1006,7 @@ void Graphic3d_CView::Highlight (const Handle(Graphic3d_Structure)& theStructure
 // purpose  :
 // =======================================================================
 void Graphic3d_CView::SetTransform (const Handle(Graphic3d_Structure)& theStructure,
-                                    const Handle(TopLoc_Datum3D)& theTrsf)
+                                    const Handle(Graphic3d_HGTrsf)& theTrsf)
 {
   const Standard_Integer anIndex = IsComputed (theStructure);
   if (anIndex != 0)
diff --git a/src/Graphic3d/Graphic3d_CView.hxx b/src/Graphic3d/Graphic3d_CView.hxx
index c17f572976..693da5f105 100644
--- a/src/Graphic3d/Graphic3d_CView.hxx
+++ b/src/Graphic3d/Graphic3d_CView.hxx
@@ -184,7 +184,7 @@ private:
 
   //! Transforms the structure in the view.
   Standard_EXPORT void SetTransform (const Handle(Graphic3d_Structure)& theStructure,
-                                     const Handle(TopLoc_Datum3D)& theTrsf);
+                                     const Handle(Graphic3d_HGTrsf)& theTrsf);
 
   //! Suppress the highlighting on the structure <AStructure>
   //! in the view <me>.
diff --git a/src/Graphic3d/Graphic3d_HGTrsf.hxx b/src/Graphic3d/Graphic3d_HGTrsf.hxx
new file mode 100644
index 0000000000..4fa04e6df6
--- /dev/null
+++ b/src/Graphic3d/Graphic3d_HGTrsf.hxx
@@ -0,0 +1,23 @@
+// Copyright (c) 2014 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 _Graphic3d_HGTrsf_HeaderFile
+#define _Graphic3d_HGTrsf_HeaderFile
+
+#include <gp_GTrsf.hxx>
+#include <NCollection_Shared.hxx>
+
+//! Type for sharing gp_GTrsf as smart-pointer.
+typedef NCollection_Shared<gp_GTrsf> Graphic3d_HGTrsf;
+
+#endif // _Graphic3d_HGTrsf_HeaderFile
diff --git a/src/Graphic3d/Graphic3d_Structure.cxx b/src/Graphic3d/Graphic3d_Structure.cxx
index 983525b281..91a1776191 100644
--- a/src/Graphic3d/Graphic3d_Structure.cxx
+++ b/src/Graphic3d/Graphic3d_Structure.cxx
@@ -624,16 +624,16 @@ void Graphic3d_Structure::DisconnectAll (const Graphic3d_TypeOfConnection theTyp
 //function : SetTransform
 //purpose  :
 //=============================================================================
-void Graphic3d_Structure::SetTransformation (const Handle(TopLoc_Datum3D)& theTrsf)
+void Graphic3d_Structure::SetTransformation (const Handle(Graphic3d_HGTrsf)& theTrsf)
 {
   if (IsDeleted()) return;
 
   const Standard_Boolean wasTransformed = IsTransformed();
 
   if (!theTrsf.IsNull()
-    && theTrsf->Trsf().Form() == gp_Identity)
+    && theTrsf->Form() == gp_Identity)
   {
-    myCStructure->SetTransformation (Handle(TopLoc_Datum3D)());
+    myCStructure->SetTransformation (Handle(Graphic3d_HGTrsf)());
   }
   else
   {
@@ -823,7 +823,7 @@ void Graphic3d_Structure::addTransformed (Graphic3d_BndBox3d&    theBox,
     if (!myCStructure->Transformation().IsNull())
     {
       Graphic3d_Mat4d aMat4;
-      myCStructure->Transformation()->Trsf().GetMat4 (aMat4);
+      myCStructure->Transformation()->GetMat4 (aMat4);
       aBox.Transform (aMat4);
     }
 
diff --git a/src/Graphic3d/Graphic3d_Structure.hxx b/src/Graphic3d/Graphic3d_Structure.hxx
index 291004ec1d..599beef263 100644
--- a/src/Graphic3d/Graphic3d_Structure.hxx
+++ b/src/Graphic3d/Graphic3d_Structure.hxx
@@ -355,10 +355,10 @@ public:
   }
 
   //! Return local transformation.
-  const Handle(TopLoc_Datum3D)& Transformation() const { return myCStructure->Transformation(); }
+  const Handle(Graphic3d_HGTrsf)& Transformation() const { return myCStructure->Transformation(); }
 
   //! Modifies the current local transformation
-  Standard_EXPORT void SetTransformation (const Handle(TopLoc_Datum3D)& theTrsf);
+  Standard_EXPORT void SetTransformation (const Handle(Graphic3d_HGTrsf)& theTrsf);
 
   //! Modifies the current transform persistence (pan, zoom or rotate)
   Standard_EXPORT void SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers);
@@ -396,7 +396,7 @@ public:
   }
 
   //! Internal method which sets new transformation without calling graphic manager callbacks.
-  void GraphicTransform (const Handle(TopLoc_Datum3D)& theTrsf)
+  void GraphicTransform (const Handle(Graphic3d_HGTrsf)& theTrsf)
   {
     if (!myCStructure.IsNull()) { myCStructure->SetTransformation (theTrsf); }
   }
diff --git a/src/Graphic3d/Graphic3d_StructureManager.cxx b/src/Graphic3d/Graphic3d_StructureManager.cxx
index 7b1953f00a..73db293b62 100644
--- a/src/Graphic3d/Graphic3d_StructureManager.cxx
+++ b/src/Graphic3d/Graphic3d_StructureManager.cxx
@@ -416,7 +416,7 @@ void Graphic3d_StructureManager::UnHighlight()
 // purpose  :
 // ========================================================================
 void Graphic3d_StructureManager::SetTransform (const Handle(Graphic3d_Structure)& theStructure,
-                                               const Handle(TopLoc_Datum3D)& theTrsf)
+                                               const Handle(Graphic3d_HGTrsf)& theTrsf)
 {
   for (Graphic3d_IndexedMapOfView::Iterator aViewIt (myDefinedViews); aViewIt.More(); aViewIt.Next())
   {
diff --git a/src/Graphic3d/Graphic3d_StructureManager.hxx b/src/Graphic3d/Graphic3d_StructureManager.hxx
index 8f2778948b..95a19b9c20 100644
--- a/src/Graphic3d/Graphic3d_StructureManager.hxx
+++ b/src/Graphic3d/Graphic3d_StructureManager.hxx
@@ -107,7 +107,7 @@ public:
   Standard_EXPORT virtual void Highlight (const Handle(Graphic3d_Structure)& theStructure);
 
   //! Transforms the structure.
-  Standard_EXPORT virtual void SetTransform (const Handle(Graphic3d_Structure)& theStructure, const Handle(TopLoc_Datum3D)& theTrsf);
+  Standard_EXPORT virtual void SetTransform (const Handle(Graphic3d_Structure)& theStructure, const Handle(Graphic3d_HGTrsf)& theTrsf);
 
   //! Changes the display priority of the structure <AStructure>.
   Standard_EXPORT virtual void ChangeDisplayPriority (const Handle(Graphic3d_Structure)& theStructure,
diff --git a/src/Graphic3d/Graphic3d_ZLayerSettings.hxx b/src/Graphic3d/Graphic3d_ZLayerSettings.hxx
index 9c3cdf1f37..27eeaed537 100644
--- a/src/Graphic3d/Graphic3d_ZLayerSettings.hxx
+++ b/src/Graphic3d/Graphic3d_ZLayerSettings.hxx
@@ -15,7 +15,7 @@
 #define _Graphic3d_ZLayerSettings_HeaderFile
 
 #include <gp_XYZ.hxx>
-#include <TopLoc_Datum3D.hxx>
+#include <Graphic3d_HGTrsf.hxx>
 #include <Graphic3d_LightSet.hxx>
 #include <Graphic3d_PolygonOffset.hxx>
 #include <Precision.hxx>
@@ -55,7 +55,7 @@ struct Graphic3d_ZLayerSettings
   const gp_XYZ& Origin() const { return myOrigin; }
 
   //! Return the transformation to the origin.
-  const Handle(TopLoc_Datum3D)& OriginTransformation() const { return myOriginTrsf; }
+  const Handle(Graphic3d_HGTrsf)& OriginTransformation() const { return myOriginTrsf; }
 
   //! Set the origin of all objects within the layer.
   void SetOrigin (const gp_XYZ& theOrigin)
@@ -66,7 +66,7 @@ struct Graphic3d_ZLayerSettings
     {
       gp_Trsf aTrsf;
       aTrsf.SetTranslation (theOrigin);
-      myOriginTrsf = new TopLoc_Datum3D (aTrsf);
+      myOriginTrsf = new Graphic3d_HGTrsf (aTrsf);
     }
   }
 
@@ -189,7 +189,7 @@ protected:
 
   TCollection_AsciiString     myName;                  //!< user-provided name
   Handle(Graphic3d_LightSet)  myLights;                //!< lights list
-  Handle(TopLoc_Datum3D)      myOriginTrsf;            //!< transformation to the origin
+  Handle(Graphic3d_HGTrsf)    myOriginTrsf;            //!< transformation to the origin
   gp_XYZ                      myOrigin;                //!< the origin of all objects within the layer
   Standard_Real               myCullingDistance;       //!< distance to discard objects
   Standard_Real               myCullingSize;           //!< size to discard objects
diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx
index d5c3c5270b..e42c2d5bc1 100644
--- a/src/OpenGl/OpenGl_Structure.cxx
+++ b/src/OpenGl/OpenGl_Structure.cxx
@@ -131,14 +131,14 @@ void OpenGl_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerIndex)
 // function : SetTransformation
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetTransformation (const Handle(TopLoc_Datum3D)& theTrsf)
+void OpenGl_Structure::SetTransformation (const Handle(Graphic3d_HGTrsf)& theTrsf)
 {
   myTrsf = theTrsf;
   myIsMirrored = Standard_False;
   if (!myTrsf.IsNull())
   {
     // Determinant of transform matrix less then 0 means that mirror transform applied.
-    const gp_Trsf& aTrsf = myTrsf->Transformation();
+    const gp_GTrsf& aTrsf = *myTrsf;
     const Standard_Real aDet = aTrsf.Value(1, 1) * (aTrsf.Value (2, 2) * aTrsf.Value (3, 3) - aTrsf.Value (3, 2) * aTrsf.Value (2, 3))
                              - aTrsf.Value(1, 2) * (aTrsf.Value (2, 1) * aTrsf.Value (3, 3) - aTrsf.Value (3, 1) * aTrsf.Value (2, 3))
                              + aTrsf.Value(1, 3) * (aTrsf.Value (2, 1) * aTrsf.Value (3, 2) - aTrsf.Value (3, 1) * aTrsf.Value (2, 2));
@@ -172,10 +172,10 @@ void OpenGl_Structure::SetTransformPersistence (const Handle(Graphic3d_Transform
 // =======================================================================
 void OpenGl_Structure::updateLayerTransformation()
 {
-  gp_Trsf aRenderTrsf;
+  gp_GTrsf aRenderTrsf;
   if (!myTrsf.IsNull())
   {
-    aRenderTrsf = myTrsf->Trsf();
+    aRenderTrsf = *myTrsf;
   }
 
   const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer);
@@ -445,8 +445,9 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
   if (aCtx->core11ffp != NULL
   && !myTrsf.IsNull())
   {
-    const Standard_Real aScale = myTrsf->Trsf().ScaleFactor();
-    if (Abs (aScale - 1.0) > Precision::Confusion())
+    const Standard_Real aScale = myTrsf->ScaleFactor();
+    if (myTrsf->Form() == gp_Other
+     || Abs (aScale - 1.0) > Precision::Confusion())
     {
       aCtx->SetGlNormalizeEnabled (Standard_True);
     }
diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx
index b770323783..f261211685 100644
--- a/src/OpenGl/OpenGl_Structure.hxx
+++ b/src/OpenGl/OpenGl_Structure.hxx
@@ -59,7 +59,7 @@ public:
   Standard_EXPORT virtual void Disconnect (Graphic3d_CStructure& theStructure) Standard_OVERRIDE;
 
   //! Synchronize structure transformation
-  Standard_EXPORT virtual void SetTransformation (const Handle(TopLoc_Datum3D)& theTrsf) Standard_OVERRIDE;
+  Standard_EXPORT virtual void SetTransformation (const Handle(Graphic3d_HGTrsf)& theTrsf) Standard_OVERRIDE;
 
   //! Set transformation persistence.
   Standard_EXPORT virtual void SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers) Standard_OVERRIDE;
diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx
index 853146c4f2..c9420236e9 100644
--- a/src/OpenGl/OpenGl_View.hxx
+++ b/src/OpenGl/OpenGl_View.hxx
@@ -795,7 +795,7 @@ protected: //! @name methods related to ray-tracing
   //! Adds OpenGL groups to ray-traced scene geometry.
   Standard_Boolean addRaytraceGroups (const OpenGl_Structure*        theStructure,
                                       const OpenGl_RaytraceMaterial& theStructMat,
-                                      const Handle(TopLoc_Datum3D)&  theTrsf,
+                                      const Handle(Graphic3d_HGTrsf)& theTrsf,
                                       const Handle(OpenGl_Context)&  theGlContext);
 
   //! Creates ray-tracing material properties.
diff --git a/src/OpenGl/OpenGl_View_Raytrace.cxx b/src/OpenGl/OpenGl_View_Raytrace.cxx
index 299b7b014b..a836708097 100644
--- a/src/OpenGl/OpenGl_View_Raytrace.cxx
+++ b/src/OpenGl/OpenGl_View_Raytrace.cxx
@@ -509,7 +509,7 @@ Standard_Boolean OpenGl_View::addRaytraceStructure (const OpenGl_Structure*
 // =======================================================================
 Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure*        theStructure,
                                                  const OpenGl_RaytraceMaterial& theStructMat,
-                                                 const Handle(TopLoc_Datum3D)&  theTrsf,
+                                                 const Handle(Graphic3d_HGTrsf)& theTrsf,
                                                  const Handle(OpenGl_Context)&  theGlContext)
 {
   OpenGl_Mat4 aMat4;
@@ -554,7 +554,7 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure*
             opencascade::handle<BVH_Transform<Standard_ShortReal, 4> > aTransform = new BVH_Transform<Standard_ShortReal, 4>();
             if (!theTrsf.IsNull())
             {
-              theTrsf->Trsf().GetMat4 (aMat4);
+              theTrsf->GetMat4 (aMat4);
               aTransform->SetTransform (aMat4);
             }
 
@@ -571,7 +571,7 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure*
               opencascade::handle<BVH_Transform<Standard_ShortReal, 4> > aTransform = new BVH_Transform<Standard_ShortReal, 4>();
               if (!theTrsf.IsNull())
               {
-                theTrsf->Trsf().GetMat4 (aMat4);
+                theTrsf->GetMat4 (aMat4);
                 aTransform->SetTransform (aMat4);
               }
 
diff --git a/src/Prs3d/Prs3d.cxx b/src/Prs3d/Prs3d.cxx
index d282190260..1979228d52 100644
--- a/src/Prs3d/Prs3d.cxx
+++ b/src/Prs3d/Prs3d.cxx
@@ -29,7 +29,7 @@
 // =========================================================================
 void Prs3d::AddFreeEdges (TColgp_SequenceOfPnt& theSegments,
                           const Handle(Poly_Triangulation)& thePolyTri,
-                          const gp_Trsf& theLocation)
+                          const gp_GTrsf& theLocation)
 {
   if (thePolyTri.IsNull() || !thePolyTri->HasGeometry())
   {
diff --git a/src/Prs3d/Prs3d.hxx b/src/Prs3d/Prs3d.hxx
index 17a1d8ebd1..25fbb1c050 100644
--- a/src/Prs3d/Prs3d.hxx
+++ b/src/Prs3d/Prs3d.hxx
@@ -106,7 +106,7 @@ public:
   //! @param[in] theLocation   transformation to apply
   Standard_EXPORT static void AddFreeEdges (TColgp_SequenceOfPnt& theSegments,
                                             const Handle(Poly_Triangulation)& thePolyTri,
-                                            const gp_Trsf& theLocation);
+                                            const gp_GTrsf& theLocation);
 
 };
 
diff --git a/src/PrsMgr/PrsMgr_PresentableObject.cxx b/src/PrsMgr/PrsMgr_PresentableObject.cxx
index 0e9beef09f..bb27fc3a2e 100644
--- a/src/PrsMgr/PrsMgr_PresentableObject.cxx
+++ b/src/PrsMgr/PrsMgr_PresentableObject.cxx
@@ -33,9 +33,9 @@ IMPLEMENT_STANDARD_RTTIEXT(PrsMgr_PresentableObject, Standard_Transient)
 //function : getIdentityTrsf
 //purpose  :
 //=======================================================================
-const gp_Trsf& PrsMgr_PresentableObject::getIdentityTrsf()
+const gp_GTrsf& PrsMgr_PresentableObject::getIdentityTrsf()
 {
-  static const gp_Trsf THE_IDENTITY_TRSF;
+  static const gp_GTrsf THE_IDENTITY_TRSF;
   return THE_IDENTITY_TRSF;
 }
 
@@ -79,7 +79,7 @@ PrsMgr_PresentableObject::~PrsMgr_PresentableObject()
 
   for (PrsMgr_ListOfPresentableObjectsIter anIter (myChildren); anIter.More(); anIter.Next())
   {
-    anIter.Value()->SetCombinedParentTransform (Handle(TopLoc_Datum3D)());
+    anIter.Value()->SetCombinedParentTransform (Handle(Graphic3d_HGTrsf)());
     anIter.Value()->myParent = NULL;
   }
 }
@@ -104,7 +104,7 @@ void PrsMgr_PresentableObject::Fill (const Handle(PrsMgr_PresentationManager)& t
 //purpose  :
 //=======================================================================
 void PrsMgr_PresentableObject::computeHLR (const Handle(Graphic3d_Camera)& ,
-                                           const Handle(TopLoc_Datum3D)& ,
+                                           const Handle(Graphic3d_HGTrsf)& ,
                                            const Handle(Prs3d_Presentation)& )
 {
   throw Standard_NotImplemented("cannot compute under a specific projector");
@@ -248,7 +248,7 @@ void PrsMgr_PresentableObject::SetTypeOfPresentation (const PrsMgr_TypeOfPresent
 //function : setLocalTransformation
 //purpose  :
 //=======================================================================
-void PrsMgr_PresentableObject::setLocalTransformation (const Handle(TopLoc_Datum3D)& theTransformation)
+void PrsMgr_PresentableObject::setLocalTransformation (const Handle(Graphic3d_HGTrsf)& theTransformation)
 {
   myLocalTransformation = theTransformation;
   UpdateTransformation();
@@ -260,14 +260,14 @@ void PrsMgr_PresentableObject::setLocalTransformation (const Handle(TopLoc_Datum
 //=======================================================================
 void PrsMgr_PresentableObject::ResetTransformation() 
 {
-  setLocalTransformation (Handle(TopLoc_Datum3D)());
+  setLocalTransformation (Handle(Graphic3d_HGTrsf)());
 }
 
 //=======================================================================
 //function : SetCombinedParentTransform
 //purpose  : 
 //=======================================================================
-void PrsMgr_PresentableObject::SetCombinedParentTransform (const Handle(TopLoc_Datum3D)& theTrsf)
+void PrsMgr_PresentableObject::SetCombinedParentTransform (const Handle(Graphic3d_HGTrsf)& theTrsf)
 {
   myCombinedParentTransform = theTrsf;
   UpdateTransformation();
@@ -285,20 +285,20 @@ void PrsMgr_PresentableObject::UpdateTransformation()
   {
     if (!myLocalTransformation.IsNull() && myLocalTransformation->Form() != gp_Identity)
     {
-      const gp_Trsf aTrsf = myCombinedParentTransform->Trsf() * myLocalTransformation->Trsf();
-      myTransformation    = new TopLoc_Datum3D (aTrsf);
-      myInvTransformation = aTrsf.Inverted();
+      const gp_GTrsf aTrsf = *myCombinedParentTransform * *myLocalTransformation;
+      myTransformation     = new Graphic3d_HGTrsf (aTrsf);
+      myInvTransformation  = aTrsf.Inverted();
     }
     else
     {
       myTransformation    = myCombinedParentTransform;
-      myInvTransformation = myCombinedParentTransform->Trsf().Inverted();
+      myInvTransformation = myCombinedParentTransform->Inverted();
     }
   }
   else if (!myLocalTransformation.IsNull() && myLocalTransformation->Form() != gp_Identity)
   {
     myTransformation    = myLocalTransformation;
-    myInvTransformation = myLocalTransformation->Trsf().Inverted();
+    myInvTransformation = myLocalTransformation->Inverted();
   }
 
   for (PrsMgr_Presentations::Iterator aPrsIter (myPresentations); aPrsIter.More(); aPrsIter.Next())
@@ -364,7 +364,7 @@ void PrsMgr_PresentableObject::AddChild (const Handle(PrsMgr_PresentableObject)&
 //=======================================================================
 void PrsMgr_PresentableObject::AddChildWithCurrentTransformation(const Handle(PrsMgr_PresentableObject)& theObject)
 {
-  gp_Trsf aTrsf = Transformation().Inverted() * theObject->Transformation();
+  gp_GTrsf aTrsf = Transformation().Inverted() * theObject->Transformation();
   theObject->SetLocalTransformation(aTrsf);
   AddChild(theObject);
 }
@@ -381,7 +381,7 @@ void PrsMgr_PresentableObject::RemoveChild (const Handle(PrsMgr_PresentableObjec
     if (anIter.Value() == theObject)
     {
       theObject->myParent = NULL;
-      theObject->SetCombinedParentTransform (Handle(TopLoc_Datum3D)());
+      theObject->SetCombinedParentTransform (Handle(Graphic3d_HGTrsf)());
       myChildren.Remove (anIter);
       break;
     }
@@ -394,7 +394,7 @@ void PrsMgr_PresentableObject::RemoveChild (const Handle(PrsMgr_PresentableObjec
 //=======================================================================
 void PrsMgr_PresentableObject::RemoveChildWithRestoreTransformation(const Handle(PrsMgr_PresentableObject)& theObject)
 {
-  gp_Trsf aTrsf = theObject->Transformation();
+  gp_GTrsf aTrsf = theObject->Transformation();
   RemoveChild(theObject);
   theObject->SetLocalTransformation(aTrsf);
 }
diff --git a/src/PrsMgr/PrsMgr_PresentableObject.hxx b/src/PrsMgr/PrsMgr_PresentableObject.hxx
index 638c90e79b..3e4a3ef26a 100644
--- a/src/PrsMgr/PrsMgr_PresentableObject.hxx
+++ b/src/PrsMgr/PrsMgr_PresentableObject.hxx
@@ -226,17 +226,17 @@ public: //! @name object transformation
   //! Return the local transformation.
   //! Note that the local transformation of the object having Transformation Persistence
   //! is applied within Local Coordinate system defined by this Persistence.
-  const Handle(TopLoc_Datum3D)& LocalTransformationGeom() const { return myLocalTransformation; }
+  const Handle(Graphic3d_HGTrsf)& LocalTransformationGeom() const { return myLocalTransformation; }
 
   //! Sets local transformation to theTransformation.
   //! Note that the local transformation of the object having Transformation Persistence
   //! is applied within Local Coordinate system defined by this Persistence.
-  void SetLocalTransformation (const gp_Trsf& theTrsf) { setLocalTransformation (new TopLoc_Datum3D (theTrsf)); }
+  void SetLocalTransformation (const gp_GTrsf& theTrsf) { setLocalTransformation (new Graphic3d_HGTrsf (theTrsf)); }
 
   //! Sets local transformation to theTransformation.
   //! Note that the local transformation of the object having Transformation Persistence
   //! is applied within Local Coordinate system defined by this Persistence.
-  void SetLocalTransformation (const Handle(TopLoc_Datum3D)& theTrsf) { setLocalTransformation (theTrsf); }
+  void SetLocalTransformation (const Handle(Graphic3d_HGTrsf)& theTrsf) { setLocalTransformation (theTrsf); }
 
   //! Returns true if object has a transformation that is different from the identity.
   Standard_Boolean HasTransformation() const { return !myTransformation.IsNull() && myTransformation->Form() != gp_Identity; }
@@ -244,27 +244,27 @@ public: //! @name object transformation
   //! Return the transformation taking into account transformation of parent object(s).
   //! Note that the local transformation of the object having Transformation Persistence
   //! is applied within Local Coordinate system defined by this Persistence.
-  const Handle(TopLoc_Datum3D)& TransformationGeom() const { return myTransformation; }
+  const Handle(Graphic3d_HGTrsf)& TransformationGeom() const { return myTransformation; }
 
   //! Return the local transformation.
   //! Note that the local transformation of the object having Transformation Persistence
   //! is applied within Local Coordinate system defined by this Persistence.
-  const gp_Trsf& LocalTransformation() const { return !myLocalTransformation.IsNull()
-                                                     ? myLocalTransformation->Trsf()
-                                                     : getIdentityTrsf(); }
+  const gp_GTrsf& LocalTransformation() const { return !myLocalTransformation.IsNull()
+                                                      ? *myLocalTransformation
+                                                      : getIdentityTrsf(); }
 
   //! Return the transformation taking into account transformation of parent object(s).
   //! Note that the local transformation of the object having Transformation Persistence
   //! is applied within Local Coordinate system defined by this Persistence.
-  const gp_Trsf& Transformation() const { return !myTransformation.IsNull()
-                                                ? myTransformation->Trsf()
+  const gp_GTrsf& Transformation() const { return !myTransformation.IsNull()
+                                                ? *myTransformation
                                                 : getIdentityTrsf(); }
 
   //! Return inversed transformation.
   const gp_GTrsf& InversedTransformation() const { return myInvTransformation; }
 
   //! Return combined parent transformation.
-  const Handle(TopLoc_Datum3D)& CombinedParentTransformation() const { return myCombinedParentTransform; }
+  const Handle(Graphic3d_HGTrsf)& CombinedParentTransformation() const { return myCombinedParentTransform; }
 
   //! resets local transformation to identity.
   Standard_EXPORT virtual void ResetTransformation();
@@ -366,7 +366,7 @@ protected: //! @name interface methods
   //! @param[in] theTrsf  additional transformation, or NULL if undefined
   //! @param[in] thePrs   presentation to fill
   Standard_EXPORT virtual void computeHLR (const Handle(Graphic3d_Camera)& theProjector,
-                                           const Handle(TopLoc_Datum3D)& theTrsf,
+                                           const Handle(Graphic3d_HGTrsf)& theTrsf,
                                            const Handle(Prs3d_Presentation)& thePrs);
 
   //! Recomputes invalidated presentations of the object.
@@ -381,13 +381,13 @@ protected: //! @name interface methods
 
   //! Sets myCombinedParentTransform to theTransformation. Thus object receives transformation
   //! from parent node and able to derive its own.
-  Standard_EXPORT virtual void SetCombinedParentTransform (const Handle(TopLoc_Datum3D)& theTrsf);
+  Standard_EXPORT virtual void SetCombinedParentTransform (const Handle(Graphic3d_HGTrsf)& theTrsf);
 
   //! Sets local transformation to theTransformation.
-  Standard_EXPORT virtual void setLocalTransformation (const Handle(TopLoc_Datum3D)& theTransformation);
+  Standard_EXPORT virtual void setLocalTransformation (const Handle(Graphic3d_HGTrsf)& theTransformation);
 
   //! Return the identity transformation.
-  Standard_EXPORT static const gp_Trsf& getIdentityTrsf();
+  Standard_EXPORT static const gp_GTrsf& getIdentityTrsf();
 
   //! Recompute computed (HLR) presentations (when view is in computed mode).
   Standard_EXPORT void recomputeComputed() const;
@@ -534,9 +534,9 @@ protected:
   Handle(Prs3d_Drawer)                   myHilightDrawer;           //!< (optional) custom presentation attributes for highlighting selected object
   Handle(Prs3d_Drawer)                   myDynHilightDrawer;        //!< (optional) custom presentation attributes for highlighting detected object
   Handle(Graphic3d_TransformPers)        myTransformPersistence;    //!< transformation persistence
-  Handle(TopLoc_Datum3D)                 myLocalTransformation;     //!< local transformation relative to parent object
-  Handle(TopLoc_Datum3D)                 myTransformation;          //!< absolute transformation of this object (combined parents + local transformations)
-  Handle(TopLoc_Datum3D)                 myCombinedParentTransform; //!< transformation of parent object (combined for all parents)
+  Handle(Graphic3d_HGTrsf)               myLocalTransformation;     //!< local transformation relative to parent object
+  Handle(Graphic3d_HGTrsf)               myTransformation;          //!< absolute transformation of this object (combined parents + local transformations)
+  Handle(Graphic3d_HGTrsf)               myCombinedParentTransform; //!< transformation of parent object (combined for all parents)
   PrsMgr_ListOfPresentableObjects        myChildren;                //!< list of children
   gp_GTrsf                               myInvTransformation;       //!< inversion of absolute transformation (combined parents + local transformations)
   PrsMgr_TypeOfPresentation3d            myTypeOfPresentation3d;    //!< presentation type
diff --git a/src/PrsMgr/PrsMgr_PresentationManager.cxx b/src/PrsMgr/PrsMgr_PresentationManager.cxx
index 1003c6d929..73e118770b 100644
--- a/src/PrsMgr/PrsMgr_PresentationManager.cxx
+++ b/src/PrsMgr/PrsMgr_PresentationManager.cxx
@@ -14,7 +14,6 @@
 
 #include <PrsMgr_PresentationManager.hxx>
 
-#include <TopLoc_Datum3D.hxx>
 #include <Prs3d_PresentationShadow.hxx>
 #include <PrsMgr_PresentableObject.hxx>
 #include <PrsMgr_Presentation.hxx>
@@ -600,7 +599,7 @@ void PrsMgr_PresentationManager::Connect (const Handle(PrsMgr_PresentableObject)
 // purpose  :
 // =======================================================================
 void PrsMgr_PresentationManager::Transform (const Handle(PrsMgr_PresentableObject)& thePrsObj,
-                                            const Handle(TopLoc_Datum3D)& theTransformation,
+                                            const Handle(Graphic3d_HGTrsf)& theTransformation,
                                             const Standard_Integer theMode)
 {
   Presentation (thePrsObj, theMode)->SetTransformation (theTransformation);
@@ -673,7 +672,7 @@ namespace
   //! of shadow presentation is equal to theRefId
   static void updatePrsTransformation (const PrsMgr_ListOfPresentations& thePrsList,
                                        const Standard_Integer theRefId,
-                                       const Handle(TopLoc_Datum3D)& theTrsf)
+                                       const Handle(Graphic3d_HGTrsf)& theTrsf)
   {
     for (PrsMgr_ListOfPresentations::Iterator anIter (thePrsList); anIter.More(); anIter.Next())
     {
@@ -708,7 +707,7 @@ void PrsMgr_PresentationManager::UpdateHighlightTrsf (const Handle(V3d_Viewer)&
     return;
   }
 
-  Handle(TopLoc_Datum3D) aTrsf = theObj->LocalTransformationGeom();
+  Handle(Graphic3d_HGTrsf) aTrsf = theObj->LocalTransformationGeom();
   const Standard_Integer aParentId = aPrs->CStructure()->Identification();
   updatePrsTransformation (myImmediateList, aParentId, aTrsf);
 
diff --git a/src/PrsMgr/PrsMgr_PresentationManager.hxx b/src/PrsMgr/PrsMgr_PresentationManager.hxx
index d47a5980c2..73041d6ca8 100644
--- a/src/PrsMgr/PrsMgr_PresentationManager.hxx
+++ b/src/PrsMgr/PrsMgr_PresentationManager.hxx
@@ -19,12 +19,12 @@
 
 #include <Graphic3d_StructureManager.hxx>
 #include <Graphic3d_ZLayerId.hxx>
+#include <Graphic3d_HGTrsf.hxx>
 #include <PrsMgr_ListOfPresentations.hxx>
 
 class Graphic3d_Structure;
 typedef Graphic3d_Structure Prs3d_Presentation;
 
-class TopLoc_Datum3D;
 class Prs3d_Drawer;
 class PrsMgr_Presentation;
 class PrsMgr_PresentableObject;
@@ -126,7 +126,7 @@ public:
   //! Sets the transformation theTransformation for the presentable object thePrsObject.
   //! thePrsObject has the display mode theMode; this has the default value of 0, that is, the wireframe display mode.
   Standard_EXPORT void Transform (const Handle(PrsMgr_PresentableObject)& thePrsObject,
-                                  const Handle(TopLoc_Datum3D)& theTransformation,
+                                  const Handle(Graphic3d_HGTrsf)& theTransformation,
                                   const Standard_Integer theMode = 0);
   
   //! Returns the structure manager.
diff --git a/src/QADraw/QADraw_Tutorials.cxx b/src/QADraw/QADraw_Tutorials.cxx
index 3fc6924bb5..35d3f10bab 100644
--- a/src/QADraw/QADraw_Tutorials.cxx
+++ b/src/QADraw/QADraw_Tutorials.cxx
@@ -170,9 +170,9 @@ public:
                                  Aspect_VKeyMouse theButton,
                                  Aspect_VKeyFlags theModifiers,
                                  bool theIsDoubleClick) override;
-  virtual void SetLocation (const TopLoc_Location& theLocation) override
+  virtual void SetLocation (const Handle(Graphic3d_HGTrsf)& theLocation) override
   {
-    if (!myPrs.IsNull()) { myPrs->SetTransformation (new TopLoc_Datum3D (theLocation.Transformation())); }
+    if (!myPrs.IsNull()) { myPrs->SetTransformation (theLocation); }
   }
 protected:
   Handle(Prs3d_Presentation) myPrs;
@@ -269,7 +269,7 @@ bool MyAisOwner::HandleMouseClick (const Graphic3d_Vec2i& thePoint,
 
     gp_Trsf aTrsfTo;
     aTrsfTo.SetRotation (gp_Ax1 (gp::Origin(), gp::DX()), isFirst ? M_PI * 0.5 : -M_PI * 0.5);
-    gp_Trsf aTrsfFrom = anObj->LocalTransformation();
+    gp_Trsf aTrsfFrom = anObj->LocalTransformation().Trsf();
     Handle(AIS_AnimationObject) anAnim = new AIS_AnimationObject ("MyAnim", anObj->InteractiveContext(), anObj, aTrsfFrom, aTrsfTo);
     anAnim->SetOwnDuration (2.0);
 
diff --git a/src/SelectMgr/SelectMgr.cxx b/src/SelectMgr/SelectMgr.cxx
index 1f647b3d28..26ea0595d7 100644
--- a/src/SelectMgr/SelectMgr.cxx
+++ b/src/SelectMgr/SelectMgr.cxx
@@ -55,12 +55,12 @@ namespace
   static void addTriangulation (Prs3d_NListOfSequenceOfPnt& theSeqLines,
                                 Prs3d_NListOfSequenceOfPnt& theSeqFree,
                                 const Handle(Select3D_SensitiveTriangulation)& theTri,
-                                const gp_Trsf& theLoc)
+                                const gp_GTrsf& theLoc)
   {
-    gp_Trsf aTrsf = theLoc;
+    gp_GTrsf aTrsf = theLoc;
     if (theTri->HasInitLocation())
     {
-      aTrsf = theLoc * theTri->GetInitLocation();
+      aTrsf = theLoc * gp_GTrsf(theTri->GetInitLocation());
     }
     const Handle(Poly_Triangulation)& aPolyTri = theTri->Triangulation();
     for (Standard_Integer aTriIter = 1; aTriIter <= aPolyTri->NbTriangles(); ++aTriIter)
@@ -87,7 +87,7 @@ namespace
   //! Fill in bounding box polylines.
   static void addBoundingBox (Prs3d_NListOfSequenceOfPnt& theSeqLines,
                               const Handle(Select3D_SensitiveBox)& theSensBox,
-                              const gp_Trsf& theLoc)
+                              const gp_GTrsf& theLoc)
   {
     Graphic3d_Vec3d aMin, aMax;
     theSensBox->Box().Get (aMin.x(), aMin.y(), aMin.z(), aMax.x(), aMax.y(), aMax.z());
@@ -137,7 +137,7 @@ namespace
   //! Fill in circle polylines.
   static void addCircle (Prs3d_NListOfSequenceOfPnt& theSeqLines,
                          const Standard_Real theRadius,
-                         const gp_Trsf& theTrsf,
+                         const gp_GTrsf& theTrsf,
                          const Standard_Real theHeight = 0)
   {
     const Standard_Real anUStep = 0.1;
@@ -157,12 +157,12 @@ namespace
   //! Fill in cylinder polylines.
   static void addCylinder (Prs3d_NListOfSequenceOfPnt& theSeqLines,
                            const Handle(Select3D_SensitiveCylinder)& theSensCyl,
-                           const gp_Trsf& theLoc)
+                           const gp_GTrsf& theLoc)
   {
     Handle(TColgp_HSequenceOfPnt) aVertLine1 = new TColgp_HSequenceOfPnt();
     Handle(TColgp_HSequenceOfPnt) aVertLine2 = new TColgp_HSequenceOfPnt();
 
-    const gp_Trsf& aTrsf = theLoc.Multiplied (theSensCyl->Transformation());
+    const gp_GTrsf aTrsf = theLoc.Multiplied (gp_GTrsf(theSensCyl->Transformation()));
     const Standard_Real aHeight = theSensCyl->Height();
 
     for (int aCircNum = 0; aCircNum < 3; aCircNum++)
@@ -193,7 +193,7 @@ namespace
 //=======================================================================
 void SelectMgr::ComputeSensitivePrs (const Handle(Graphic3d_Structure)& thePrs,
                                      const Handle(SelectMgr_Selection)& theSel,
-                                     const gp_Trsf& theLoc,
+                                     const gp_GTrsf& theLoc,
                                      const Handle(Graphic3d_TransformPers)& theTrsfPers)
 {
   thePrs->SetTransformPersistence (theTrsfPers);
diff --git a/src/SelectMgr/SelectMgr.hxx b/src/SelectMgr/SelectMgr.hxx
index 72281a9552..c361bb0458 100644
--- a/src/SelectMgr/SelectMgr.hxx
+++ b/src/SelectMgr/SelectMgr.hxx
@@ -19,7 +19,7 @@
 class Graphic3d_Structure;
 class Graphic3d_TransformPers;
 class SelectMgr_Selection;
-class gp_Trsf;
+class gp_GTrsf;
 
 //! Auxiliary tools for SelectMgr package.
 class SelectMgr
@@ -29,7 +29,7 @@ public:
   //! Compute debug presentation for sensitive objects.
   Standard_EXPORT static void ComputeSensitivePrs (const Handle(Graphic3d_Structure)& theStructure,
                                                    const Handle(SelectMgr_Selection)& theSel,
-                                                   const gp_Trsf& theLoc,
+                                                   const gp_GTrsf& theLoc,
                                                    const Handle(Graphic3d_TransformPers)& theTrsfPers);
 
 };
diff --git a/src/SelectMgr/SelectMgr_EntityOwner.hxx b/src/SelectMgr/SelectMgr_EntityOwner.hxx
index 42caefe775..be8666ff40 100644
--- a/src/SelectMgr/SelectMgr_EntityOwner.hxx
+++ b/src/SelectMgr/SelectMgr_EntityOwner.hxx
@@ -125,15 +125,15 @@ public:
   virtual Standard_Boolean HasLocation() const { return mySelectable != NULL && mySelectable->HasTransformation(); }
 
   //! Returns transformation of selectable.
-  virtual TopLoc_Location Location() const
+  virtual Handle(Graphic3d_HGTrsf) Location() const
   {
     return mySelectable != NULL && mySelectable->HasTransformation()
-         ? TopLoc_Location(mySelectable->Transformation())
-         : TopLoc_Location();
+         ? mySelectable->TransformationGeom()
+         : Handle(Graphic3d_HGTrsf)();
   }
 
   //! Change owner location (callback for handling change of location of selectable object).
-  virtual void SetLocation (const TopLoc_Location& theLocation)
+  virtual void SetLocation (const Handle(Graphic3d_HGTrsf)& theLocation)
   {
     (void )theLocation;
   }
diff --git a/src/SelectMgr/SelectMgr_SelectableObject.cxx b/src/SelectMgr/SelectMgr_SelectableObject.cxx
index 87006c49f2..70d17ec653 100644
--- a/src/SelectMgr/SelectMgr_SelectableObject.cxx
+++ b/src/SelectMgr/SelectMgr_SelectableObject.cxx
@@ -258,7 +258,7 @@ void SelectMgr_SelectableObject::UpdateTransformation()
 //=======================================================================
 void SelectMgr_SelectableObject::UpdateTransformations (const Handle(SelectMgr_Selection)& theSel)
 {
-  const TopLoc_Location aSelfLocation (Transformation());
+  const Handle(Graphic3d_HGTrsf) aSelfLocation (TransformationGeom());
   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSel->Entities()); aSelEntIter.More(); aSelEntIter.Next())
   {
     if (const Handle(Select3D_SensitiveEntity)& aSensEntity = aSelEntIter.Value()->BaseSensitive())
diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx
index c7f6514904..44e5de9ed7 100644
--- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx
+++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx
@@ -1345,7 +1345,7 @@ void SelectMgr_ViewerSelector::ClearSensitive (const Handle(V3d_View)& theView)
 //purpose  :
 //=======================================================================
 void SelectMgr_ViewerSelector::DisplaySensitive (const Handle(SelectMgr_Selection)& theSel,
-                                                 const gp_Trsf& theTrsf,
+                                                 const gp_GTrsf& theTrsf,
                                                  const Handle(V3d_View)& theView,
                                                  const Standard_Boolean theToClearOthers)
 {
diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.hxx b/src/SelectMgr/SelectMgr_ViewerSelector.hxx
index 39e57a40e5..07e597b3ae 100644
--- a/src/SelectMgr/SelectMgr_ViewerSelector.hxx
+++ b/src/SelectMgr/SelectMgr_ViewerSelector.hxx
@@ -293,7 +293,7 @@ public:
   Standard_EXPORT void ClearSensitive (const Handle(V3d_View)& theView);
 
   Standard_EXPORT void DisplaySensitive (const Handle(SelectMgr_Selection)& theSel,
-                                         const gp_Trsf& theTrsf,
+                                         const gp_GTrsf& theTrsf,
                                          const Handle(V3d_View)& theView,
                                          const Standard_Boolean theToClearOthers = Standard_True);
 
diff --git a/src/StdPrs/StdPrs_WFShape.cxx b/src/StdPrs/StdPrs_WFShape.cxx
index 9f281e102c..8f7b2b3b01 100644
--- a/src/StdPrs/StdPrs_WFShape.cxx
+++ b/src/StdPrs/StdPrs_WFShape.cxx
@@ -430,7 +430,7 @@ void StdPrs_WFShape::AddEdgesOnTriangulation (TColgp_SequenceOfPnt& theSegments,
     }
     if (const Handle(Poly_Triangulation)& aPolyTri = BRep_Tool::Triangulation (aFace, aLocation))
     {
-      Prs3d::AddFreeEdges (theSegments, aPolyTri, aLocation);
+      Prs3d::AddFreeEdges (theSegments, aPolyTri, aLocation.Transformation());
     }
   }
 }
diff --git a/src/StdSelect/StdSelect_BRepOwner.cxx b/src/StdSelect/StdSelect_BRepOwner.cxx
index c39ed2f86f..3c885a017d 100644
--- a/src/StdSelect/StdSelect_BRepOwner.cxx
+++ b/src/StdSelect/StdSelect_BRepOwner.cxx
@@ -151,7 +151,7 @@ void StdSelect_BRepOwner::Clear(const Handle(PrsMgr_PresentationManager)& PM,
   myPrsSh.Nullify();
 }
 
-void StdSelect_BRepOwner::SetLocation(const TopLoc_Location& aLoc)
+void StdSelect_BRepOwner::SetLocation(const Handle(Graphic3d_HGTrsf)& aLoc)
 {
   SelectMgr_EntityOwner::SetLocation(aLoc);
   if (!myPrsSh.IsNull())
diff --git a/src/StdSelect/StdSelect_BRepOwner.hxx b/src/StdSelect/StdSelect_BRepOwner.hxx
index 3290fdce70..617933a592 100644
--- a/src/StdSelect/StdSelect_BRepOwner.hxx
+++ b/src/StdSelect/StdSelect_BRepOwner.hxx
@@ -106,7 +106,7 @@ public:
   //! shapes with the selection mode aMode.
   Standard_EXPORT virtual void Clear (const Handle(PrsMgr_PresentationManager)& aPM, const Standard_Integer aMode = 0) Standard_OVERRIDE;
   
-  Standard_EXPORT virtual void SetLocation (const TopLoc_Location& aLoc) Standard_OVERRIDE;
+  Standard_EXPORT virtual void SetLocation (const Handle(Graphic3d_HGTrsf)& aLoc) Standard_OVERRIDE;
 
   //! Implements immediate application of location transformation of parent object to dynamic highlight structure
   Standard_EXPORT virtual void UpdateHighlightTrsf (const Handle(V3d_Viewer)& theViewer,
diff --git a/src/V3d/V3d_CircularGrid.cxx b/src/V3d/V3d_CircularGrid.cxx
index ca4a7c911d..a7f5187cf0 100644
--- a/src/V3d/V3d_CircularGrid.cxx
+++ b/src/V3d/V3d_CircularGrid.cxx
@@ -170,7 +170,7 @@ void V3d_CircularGrid::UpdateDisplay ()
                       -SinAlpha, CosAlpha, 0.0, -YOrigin(),
                             0.0,      0.0, 1.0, 0.0);
     aTrsf.Multiply (aTrsf2);
-    myStructure->SetTransformation (new TopLoc_Datum3D (aTrsf));
+    myStructure->SetTransformation (new Graphic3d_HGTrsf(aTrsf));
 
     myCurAngle = RotationAngle ();
     myCurXo = XOrigin (), myCurYo = YOrigin ();
diff --git a/src/V3d/V3d_Plane.cxx b/src/V3d/V3d_Plane.cxx
index c40df8d197..3b2dadd9c5 100755
--- a/src/V3d/V3d_Plane.cxx
+++ b/src/V3d/V3d_Plane.cxx
@@ -145,5 +145,5 @@ void V3d_Plane::Update()
   gp_Trsf aTransform;
   aTransform.SetTransformation (aGeomPln.Position());
   aTransform.Invert();
-  myGraphicStructure->SetTransformation (new TopLoc_Datum3D (aTransform));
+  myGraphicStructure->SetTransformation (new Graphic3d_HGTrsf(aTransform));
 }
diff --git a/src/V3d/V3d_RectangularGrid.cxx b/src/V3d/V3d_RectangularGrid.cxx
index 35b1d2b257..3465a06afe 100644
--- a/src/V3d/V3d_RectangularGrid.cxx
+++ b/src/V3d/V3d_RectangularGrid.cxx
@@ -169,7 +169,7 @@ void V3d_RectangularGrid::UpdateDisplay ()
                       -SinAlpha, CosAlpha, 0.0, -YOrigin(),
                             0.0,      0.0, 1.0, 0.0);
     aTrsf.Multiply (aTrsf2);
-    myStructure->SetTransformation (new TopLoc_Datum3D (aTrsf));
+    myStructure->SetTransformation (new Graphic3d_HGTrsf(aTrsf));
 
     myCurAngle = RotationAngle ();
     myCurXo = XOrigin (), myCurYo = YOrigin ();
diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx
index 4427704ea7..28f5dceb91 100644
--- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx
+++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx
@@ -3971,7 +3971,11 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
       }
 
       ++anArgIter;
-      aContext->SetLocation (anObj, anObj2->LocalTransformation());
+      Handle(Graphic3d_HGTrsf) aTrsf;
+      if (anObj2->LocalTransformation().Form() != gp_Identity)
+        aTrsf = new Graphic3d_HGTrsf(anObj2->LocalTransformation());
+
+      aContext->SetLocalTransformation (anObj, aTrsf);
     }
     else if (anArg == "-rotate"
           || anArg == "-prerotate")
@@ -3983,14 +3987,15 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
         return 1;
       }
 
-      gp_Trsf aTrsf;
-      aTrsf.SetRotation (gp_Ax1 (gp_Pnt (Draw::Atof (theArgVec[anArgIter + 1]),
-                                         Draw::Atof (theArgVec[anArgIter + 2]),
-                                         Draw::Atof (theArgVec[anArgIter + 3])),
-                                 gp_Vec (Draw::Atof (theArgVec[anArgIter + 4]),
-                                         Draw::Atof (theArgVec[anArgIter + 5]),
-                                         Draw::Atof (theArgVec[anArgIter + 6]))),
-                                         Draw::Atof (theArgVec[anArgIter + 7]) * (M_PI / 180.0));
+      gp_Trsf aTrsfRot;
+      aTrsfRot.SetRotation (gp_Ax1 (gp_Pnt (Draw::Atof (theArgVec[anArgIter + 1]),
+                                            Draw::Atof (theArgVec[anArgIter + 2]),
+                                            Draw::Atof (theArgVec[anArgIter + 3])),
+                                    gp_Vec (Draw::Atof (theArgVec[anArgIter + 4]),
+                                            Draw::Atof (theArgVec[anArgIter + 5]),
+                                            Draw::Atof (theArgVec[anArgIter + 6]))),
+                                            Draw::Atof (theArgVec[anArgIter + 7]) * (M_PI / 180.0));
+      gp_GTrsf aTrsf(aTrsfRot);
       anArgIter += 7;
 
       if (anArg == "-prerotate")
@@ -4001,7 +4006,7 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
       {
         aTrsf = aTrsf * anObj->LocalTransformation();
      }
-      aContext->SetLocation (anObj, aTrsf);
+      aContext->SetLocalTransformation (anObj, new Graphic3d_HGTrsf(aTrsf));
     }
     else if (anArg == "-translate"
           || anArg == "-pretranslate")
@@ -4016,8 +4021,9 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
         return 1;
       }
 
-      gp_Trsf aTrsf;
-      aTrsf.SetTranslationPart (aLocVec);
+      gp_Trsf aTrsfVec;
+      aTrsfVec.SetTranslationPart (aLocVec);
+      gp_GTrsf aTrsf(aTrsfVec);
       if (anArg == "-pretranslate")
       {
         aTrsf = anObj->LocalTransformation() * aTrsf;
@@ -4026,7 +4032,7 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
       {
         aTrsf = aTrsf * anObj->LocalTransformation();
       }
-      aContext->SetLocation (anObj, aTrsf);
+      aContext->SetLocalTransformation (anObj, new Graphic3d_HGTrsf(aTrsf));
     }
     else if (anArg == "-scale"
           || anArg == "-prescale"
@@ -4097,7 +4103,13 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
 
       if (anArg == "-setscale")
       {
-        gp_Trsf aTrsf = anObj->LocalTransformation();
+        if (anObj->LocalTransformation().Form() == gp_Other)
+        {
+          /// TODO
+          theDI << "Error: updating of gp_Other transformation is not implemented\n";
+          return 1;
+        }
+        gp_Trsf aTrsf = anObj->LocalTransformation().Trsf();
         if (hasScaleLoc)
         {
           aTrsf.SetScale (aScaleLoc, aScale);
@@ -4110,15 +4122,16 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
       }
       else
       {
-        gp_Trsf aTrsf;
+        gp_Trsf aTrsfScale;
         if (hasScaleLoc)
         {
-          aTrsf.SetScale (aScaleLoc, aScale);
+          aTrsfScale.SetScale (aScaleLoc, aScale);
         }
         else
         {
-          aTrsf.SetScaleFactor (aScale);
+          aTrsfScale.SetScaleFactor (aScale);
         }
+        gp_GTrsf aTrsf(aTrsfScale);
 
         if (anArg == "-prescale")
         {
@@ -4128,7 +4141,7 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
         {
           aTrsf = aTrsf * anObj->LocalTransformation();
         }
-        aContext->SetLocation (anObj, aTrsf);
+        aContext->SetLocalTransformation (anObj, new Graphic3d_HGTrsf(aTrsf));
       }
     }
     else if (anArg == "-mirror"
@@ -4141,14 +4154,15 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
         return 1;
       }
 
-      gp_Trsf aTrsf;
-      aTrsf.SetMirror (gp_Ax2 (gp_Pnt (Draw::Atof(theArgVec[theArgNb - 6]),
-                                       Draw::Atof(theArgVec[theArgNb - 5]),
-                                       Draw::Atof(theArgVec[theArgNb - 4])),
-                               gp_Vec (Draw::Atof(theArgVec[theArgNb - 3]),
-                                       Draw::Atof(theArgVec[theArgNb - 2]),
-                                       Draw::Atof(theArgVec[theArgNb - 1]))));
+      gp_Trsf aTrsfMirr;
+      aTrsfMirr.SetMirror (gp_Ax2 (gp_Pnt (Draw::Atof(theArgVec[theArgNb - 6]),
+                                           Draw::Atof(theArgVec[theArgNb - 5]),
+                                           Draw::Atof(theArgVec[theArgNb - 4])),
+                                   gp_Vec (Draw::Atof(theArgVec[theArgNb - 3]),
+                                           Draw::Atof(theArgVec[theArgNb - 2]),
+                                           Draw::Atof(theArgVec[theArgNb - 1]))));
       anArgIter += 6;
+      gp_GTrsf aTrsf(aTrsfMirr);
       if (anArg == "-premirror")
       {
         aTrsf = anObj->LocalTransformation() * aTrsf;
@@ -4157,7 +4171,7 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
       {
         aTrsf = aTrsf * anObj->LocalTransformation();
       }
-      aContext->SetLocation (anObj, aTrsf);
+      aContext->SetLocalTransformation (anObj, new Graphic3d_HGTrsf(aTrsf));
     }
     else if (anArg == "-setrotation"
           || anArg == "-rotation")
@@ -4188,9 +4202,18 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
                                      aQuatArgs[1].RealValue(),
                                      aQuatArgs[2].RealValue(),
                                      aQuatArgs[3].RealValue());
-          gp_Trsf aTrsf = anObj->LocalTransformation();
-          aTrsf.SetRotationPart (aQuat);
-          aContext->SetLocation (anObj, aTrsf);
+          if (anObj->LocalTransformation().Form() == gp_Other)
+          {
+            /// TODO
+            theDI << "Error: chaning rotation for gp_Other transformation is not implemented";
+            return 1;
+          }
+          else
+          {
+            gp_Trsf aTrsf = anObj->LocalTransformation().Trsf();
+            aTrsf.SetRotationPart (aQuat);
+            aContext->SetLocation (anObj, aTrsf);
+          }
           continue;
         }
         else if (anArg == "-setrotation")
@@ -4200,11 +4223,76 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
         }
       }
 
-      char aText[1024];
-      const gp_Quaternion aQuat = anObj->LocalTransformation().GetRotation();
-      Sprintf (aText, "%g %g %g %g ", aQuat.X(), aQuat.Y(), aQuat.Z(), aQuat.W());
+      char aText[1024] = {};
+      if (anObj->LocalTransformation().Form() == gp_Other)
+      {
+        /// TODO
+        theDI << "Error: rotation cannot be displayed for gp_Other\n";
+        const gp_Mat& aMat = anObj->LocalTransformation().VectorialPart();
+        Sprintf(aText,
+                "%g %g %g\n"
+                "%g %g %g\n"
+                "%g %g %g\n",
+                aMat(1, 1), aMat(1, 2), aMat(1, 3),
+                aMat(2, 1), aMat(2, 2), aMat(2, 3),
+                aMat(3, 1), aMat(3, 2), aMat(3, 3));
+      }
+      else
+      {
+        gp_Quaternion aQuat = anObj->LocalTransformation().Trsf().GetRotation();
+        Sprintf(aText, "%g %g %g %g ", aQuat.X(), aQuat.Y(), aQuat.Z(), aQuat.W());
+      }
       theDI << aText;
     }
+    else if ((anArg == "-affinity"
+           || anArg == "-preaffinity") && anArgIter + 7 < theArgNb)
+    {
+      toPrintInfo = Standard_False;
+
+      gp_Ax1 anAx1(gp_Pnt(Draw::Atof(theArgVec[anArgIter + 1]),
+                          Draw::Atof(theArgVec[anArgIter + 2]),
+                          Draw::Atof(theArgVec[anArgIter + 3])),
+                   gp_Vec(Draw::Atof(theArgVec[anArgIter + 4]),
+                          Draw::Atof(theArgVec[anArgIter + 5]),
+                          Draw::Atof(theArgVec[anArgIter + 6])));
+      double aRatio = Draw::Atof(theArgVec[anArgIter + 7]);
+
+      anArgIter += 7;
+      gp_GTrsf aTrsf;
+      aTrsf.SetAffinity(anAx1, aRatio);
+      if (anArg.StartsWith("-pre"))
+        aTrsf = anObj->LocalTransformation() * aTrsf;
+      else
+        aTrsf = aTrsf * anObj->LocalTransformation();
+
+      aContext->SetLocalTransformation(anObj, new Graphic3d_HGTrsf(aTrsf));
+    }
+    else if ((anArg == "-affinity2"
+           || anArg == "-preaffinity2") && anArgIter + 10 < theArgNb)
+    {
+      toPrintInfo = Standard_False;
+
+      gp_Ax2 anAx2(gp_Pnt(Draw::Atof(theArgVec[anArgIter + 1]),
+                          Draw::Atof(theArgVec[anArgIter + 2]),
+                          Draw::Atof(theArgVec[anArgIter + 3])),
+                   gp_Vec(Draw::Atof(theArgVec[anArgIter + 4]),
+                          Draw::Atof(theArgVec[anArgIter + 5]),
+                          Draw::Atof(theArgVec[anArgIter + 6])),
+                   gp_Vec(Draw::Atof(theArgVec[anArgIter + 7]),
+                          Draw::Atof(theArgVec[anArgIter + 8]),
+                          Draw::Atof(theArgVec[anArgIter + 9])));
+      double aRatio = Draw::Atof(theArgVec[anArgIter + 10]);
+
+      anArgIter += 10;
+      gp_GTrsf aTrsf;
+      aTrsf.SetAffinity(anAx2, aRatio);
+      if (anArg.StartsWith("-pre"))
+        aTrsf = anObj->LocalTransformation() * aTrsf;
+      else
+        aTrsf = aTrsf * anObj->LocalTransformation();
+
+      aContext->SetLocalTransformation(anObj, new Graphic3d_HGTrsf(aTrsf));
+    }
     else if (anArg == "-setlocation"
           || anArg == "-location")
     {
@@ -4214,9 +4302,9 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
       anArgIter += aNbParsed;
       if (aNbParsed != 0)
       {
-        gp_Trsf aTrsf = anObj->LocalTransformation();
-        aTrsf.SetTranslationPart (aLocVec);
-        aContext->SetLocation (anObj, aTrsf);
+        gp_GTrsf aTrsf = anObj->LocalTransformation();
+        aTrsf.SetTranslationPart (aLocVec.XYZ());
+        aContext->SetLocalTransformation (anObj, new Graphic3d_HGTrsf(aTrsf));
       }
       else if (anArg == "-setlocation")
       {
@@ -4263,16 +4351,34 @@ static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
     return 0;
   }
 
-  const gp_Trsf       aTrsf = anObj->LocalTransformation();
-  const gp_XYZ        aLoc  = aTrsf.TranslationPart();
-  const gp_Quaternion aRot  = aTrsf.GetRotation();
+  const gp_GTrsf aTrsf = anObj->LocalTransformation();
+  const gp_XYZ   aLoc = aTrsf.TranslationPart();
   char aText[4096];
-  Sprintf (aText, "Location: %g %g %g\n"
-                  "Rotation: %g %g %g %g\n"
-                  "Scale:    %g\n",
-                  aLoc.X(), aLoc.Y(), aLoc.Z(),
-                  aRot.X(), aRot.Y(), aRot.Z(), aRot.W(),
-                  aTrsf.ScaleFactor());
+  if (aTrsf.Form() == gp_Other)
+  {
+    const gp_Mat aMat = aTrsf.VectorialPart();
+    Sprintf(aText,
+            "Location: %g %g %g\n"
+            "Matrix:   %g %g %g\n"
+            "          %g %g %g\n"
+            "          %g %g %g\n"
+            "Scale:    %g\n",
+            aLoc.X(), aLoc.Y(), aLoc.Z(),
+            aMat(1, 1), aMat(1, 2), aMat(1, 3),
+            aMat(2, 1), aMat(2, 2), aMat(2, 3),
+            aMat(3, 1), aMat(3, 2), aMat(3, 3),
+            aTrsf.ScaleFactor());
+  }
+  else
+  {
+    const gp_Quaternion aRot = aTrsf.Trsf().GetRotation();
+    Sprintf (aText, "Location: %g %g %g\n"
+                    "Rotation: %g %g %g %g\n"
+                    "Scale:    %g\n",
+                    aLoc.X(), aLoc.Y(), aLoc.Z(),
+                    aRot.X(), aRot.Y(), aRot.Z(), aRot.W(),
+                    aTrsf.ScaleFactor());
+  }
   theDI << aText;
   return 0;
 }
@@ -7065,6 +7171,7 @@ vlocation name
     [-pretranslate X Y [Z]] [-prerotate x y z dx dy dz angle] [-prescale [X Y Z] scale]
     [-mirror x y z dx dy dz] [-premirror x y z dx dy dz]
     [-setLocation X Y [Z]] [-setRotation QX QY QZ QW] [-setScale [X Y Z] scale]
+    [-affinity x y z dx dy dz ratio] [-affinity2 x y z dx dy dz d2x d2y d2z ratio]
 Object local transformation management:
  -reset        resets transformation to identity
  -translate    applies translation vector
@@ -7078,6 +7185,8 @@ Object local transformation management:
  -setLocation  overrides translation part
  -setRotation  overrides rotation part with specified quaternion
  -setScale     overrides scale factor
+ -affinity     applies affinity transformation along one axis
+ -affinity2    applies affinity transformation along two axes
 )" /* [vlocation] */);
 
   addCmd ("vsetlocation", VSetLocation, /* [vsetlocation] */ R"(
diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx
index 5dfe2ce587..3e245dbe4e 100644
--- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx
+++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx
@@ -7910,7 +7910,8 @@ static Standard_Integer VAnimation (Draw_Interpretor& theDI,
         return 1;
       }
 
-      gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
+      gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation().Trsf(),
+                                     anObject->LocalTransformation().Trsf() };
       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
@@ -13170,7 +13171,7 @@ static int VManipulator (Draw_Interpretor& theDi,
    && (anAttachObject.IsNull() || anAttachPos != ManipAjustPosition_Center))
   {
     gp_Ax2 aPosition = gp::XOY();
-    const gp_Trsf aBaseTrsf = aManipulator->Object()->LocalTransformation();
+    const gp_GTrsf aBaseTrsf = aManipulator->Object()->LocalTransformation();
     switch (anAttachPos)
     {
       case ManipAjustPosition_Off:
@@ -13179,14 +13180,19 @@ static int VManipulator (Draw_Interpretor& theDi,
       }
       case ManipAjustPosition_Location:
       {
-        aPosition = gp::XOY().Transformed (aBaseTrsf);
+        gp_Dir aDirN = aPosition.Direction().Transformed(aBaseTrsf);
+        gp_Dir aDirX = aPosition.XDirection().Transformed(aBaseTrsf);
+        aPosition = gp_Ax2(aBaseTrsf.TranslationPart(), aDirN, aDirX);
         break;
       }
       case ManipAjustPosition_ShapeLocation:
       {
         if (Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (aManipulator->Object()))
         {
-          aPosition = gp::XOY().Transformed (aBaseTrsf * aShapePrs->Shape().Location());
+          gp_GTrsf aTrsfComb = aBaseTrsf * aShapePrs->Shape().Location().Transformation();
+          gp_Dir aDirN = aPosition.Direction().Transformed(aTrsfComb);
+          gp_Dir aDirX = aPosition.XDirection().Transformed(aTrsfComb);
+          aPosition = gp_Ax2(aTrsfComb.TranslationPart(), aDirN, aDirX);
         }
         else
         {
diff --git a/src/gp/gp_Dir.cxx b/src/gp/gp_Dir.cxx
index f5997d04ef..b91151c047 100644
--- a/src/gp/gp_Dir.cxx
+++ b/src/gp/gp_Dir.cxx
@@ -17,7 +17,7 @@
 #include <gp_Dir.hxx>
 
 #include <gp_Ax2.hxx>
-#include <gp_Trsf.hxx>
+#include <gp_GTrsf.hxx>
 #include <gp_XYZ.hxx>
 #include <Standard_ConstructionError.hxx>
 #include <Standard_DomainError.hxx>
@@ -118,6 +118,33 @@ void gp_Dir::Transform (const gp_Trsf& T)
   } 
 }
 
+void gp_Dir::Transform(const gp_GTrsf& T)
+{
+  if (T.Form() == gp_Identity || T.Form() == gp_Translation) {}
+  else if (T.Form() == gp_PntMirror) { coord.Reverse(); }
+  else if (T.Form() == gp_Scale)
+  {
+    if (T.ScaleFactor() < 0.0) { coord.Reverse(); }
+  }
+  else if (T.Form() == gp_Other)
+  {
+    // apply transposed-inversed transformation
+    // to handle non-uniform scaling
+    coord.Multiply(T.VectorialPart());
+    Standard_Real D = coord.Modulus();
+    coord.Divide(D);
+    if (T.ScaleFactor() < 0.0) { coord.Reverse(); }
+  }
+  else
+  {
+    // actually it is like gp_Trsf::HVectorialPart() in this case
+    coord.Multiply(T.VectorialPart());
+    Standard_Real D = coord.Modulus();
+    coord.Divide(D);
+    if (T.ScaleFactor() < 0.0) { coord.Reverse(); }
+  }
+}
+
 gp_Dir gp_Dir::Mirrored (const gp_Dir& V) const
 {
   gp_Dir Vres = *this;
diff --git a/src/gp/gp_Dir.hxx b/src/gp/gp_Dir.hxx
index 37b6e7b231..99b8b128db 100644
--- a/src/gp/gp_Dir.hxx
+++ b/src/gp/gp_Dir.hxx
@@ -23,6 +23,7 @@
 class gp_Vec;
 class gp_Ax1;
 class gp_Ax2;
+class gp_GTrsf;
 class gp_Trsf;
 
 //! Describes a unit vector in 3D space. This unit vector is also called "Direction".
@@ -268,6 +269,16 @@ public:
     return aV;
   }
 
+  Standard_EXPORT void Transform(const gp_GTrsf& theT);
+
+  //! Transforms a direction with a "Trsf" from gp.
+  Standard_NODISCARD gp_Dir Transformed(const gp_GTrsf& theT) const
+  {
+    gp_Dir aV = *this;
+    aV.Transform(theT);
+    return aV;
+  }
+
   //! Dumps the content of me into the stream
   Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
 
diff --git a/src/gp/gp_GTrsf.hxx b/src/gp/gp_GTrsf.hxx
index c30726337d..bc37d2ae4f 100644
--- a/src/gp/gp_GTrsf.hxx
+++ b/src/gp/gp_GTrsf.hxx
@@ -168,6 +168,9 @@ public:
   //! @endcode
   Standard_EXPORT void SetForm();
 
+  //! Returns the scale factor.
+  Standard_Real ScaleFactor() const { return scale; }
+
   //! Returns the translation part of the GTrsf.
   const gp_XYZ& TranslationPart() const { return loc; }
 
diff --git a/src/gp/gp_Pnt.cxx b/src/gp/gp_Pnt.cxx
index 38a09b5b19..84050ad481 100644
--- a/src/gp/gp_Pnt.cxx
+++ b/src/gp/gp_Pnt.cxx
@@ -21,7 +21,7 @@
 #include <gp_Pnt.hxx>
 
 #include <gp_Ax2.hxx>
-#include <gp_Trsf.hxx>
+#include <gp_GTrsf.hxx>
 #include <gp_Vec.hxx>
 #include <gp_XYZ.hxx>
 #include <Standard_Dump.hxx>
@@ -42,6 +42,23 @@ void gp_Pnt::Transform (const gp_Trsf& T)
   else { T.Transforms(coord); }
 }
 
+void gp_Pnt::Transform(const gp_GTrsf& T)
+{
+  if (T.Form() == gp_Identity) {}
+  else if (T.Form() == gp_Translation) { coord.Add(T.TranslationPart()); }
+  else if (T.Form() == gp_Scale)
+  {
+    coord.Multiply(T.ScaleFactor());
+    coord.Add(T.TranslationPart());
+  }
+  else if (T.Form() == gp_PntMirror)
+  {
+    coord.Reverse();
+    coord.Add(T.TranslationPart());
+  }
+  else { T.Transforms(coord); }
+}
+
 void gp_Pnt::Mirror (const gp_Pnt& P)
 {
   coord.Reverse ();
diff --git a/src/gp/gp_Pnt.hxx b/src/gp/gp_Pnt.hxx
index 09667d182d..e773518f4e 100644
--- a/src/gp/gp_Pnt.hxx
+++ b/src/gp/gp_Pnt.hxx
@@ -25,6 +25,7 @@
 class gp_Ax1;
 class gp_Ax2;
 class gp_Trsf;
+class gp_GTrsf;
 class gp_Vec;
 
 //! Defines a 3D cartesian point.
@@ -182,6 +183,16 @@ public:
     return aP;
   }
 
+  //! Transforms a point with the transformation T.
+  Standard_EXPORT void Transform(const gp_GTrsf& theT);
+
+  Standard_NODISCARD gp_Pnt Transformed(const gp_GTrsf& theT) const
+  {
+    gp_Pnt aP = *this;
+    aP.Transform(theT);
+    return aP;
+  }
+
   //! Translates a point in the direction of the vector theV.
   //! The magnitude of the translation is the vector's magnitude.
   void Translate (const gp_Vec& theV);
diff --git a/tests/v3d/trsf/affinity b/tests/v3d/trsf/affinity
new file mode 100644
index 0000000000..52f13fbf7b
--- /dev/null
+++ b/tests/v3d/trsf/affinity
@@ -0,0 +1,25 @@
+puts "========"
+puts "Apply affinity gp_GTrsf transformation to AIS presentation"
+puts "========"
+
+pload MODELING VISUALIZATION
+vinit View1
+box b1 -200 0 0 100 100 100
+box b2    0 0 0 100 100 100
+psphere s 50
+ttranslate s 200 50 50
+vdisplay b1 b2 s
+vfit
+vlocation s  -affinity   200 0 0  0 1  1  0.5
+vlocation b1 -affinity2 -200 0 0  0 0 -1  1 1 0  1.5
+vlocation b2 -affinity     0 0 0  0 1  1  0.75
+
+tcopy s  si
+tcopy b1 b1i
+tcopy b2 b2i
+vdisplay b1i b2i si
+vlocation si  -location  0 200 0
+vlocation b1i -location  0 200 0
+vlocation b2i -location  0 200 0
+
+vdump ${imagedir}/${casename}.png
-- 
2.33.0.windows.2

