]> OCCT Git - occt-copy.git/commitdiff
0026195: Visualization - optimize selection algorithms
authorvpa <vpa@opencascade.com>
Sun, 30 Aug 2015 21:07:01 +0000 (00:07 +0300)
committervpa <vpa@opencascade.com>
Mon, 31 Aug 2015 03:43:42 +0000 (06:43 +0300)
- initial transformation of triangulation is now applied to selecting frustum;
- switched from NCollection_Vec3 to gp collections to avoid conversions and usage of macros;
- calculation of frustum was refactored to reduce its build time;
- double pixel tolerances for selection were replaced by integer ones;
- switched to splitting along the main axis only in SelectMgr BVH selection primitive sets.

49 files changed:
src/AIS/AIS_InteractiveContext.cdl
src/AIS/AIS_InteractiveContext.cxx
src/AIS/AIS_LocalContext.cdl
src/AIS/AIS_LocalContext.cxx
src/IVtkOCC/IVtkOCC_ViewerSelector.cxx
src/MeshVS/MeshVS_DummySensitiveEntity.cxx
src/MeshVS/MeshVS_DummySensitiveEntity.hxx
src/QABugs/QABugs_19.cxx
src/Select3D/Select3D_SensitiveBox.cxx
src/Select3D/Select3D_SensitiveCircle.cxx
src/Select3D/Select3D_SensitiveCurve.cxx
src/Select3D/Select3D_SensitiveEntity.cxx
src/Select3D/Select3D_SensitiveEntity.hxx
src/Select3D/Select3D_SensitivePoint.cxx
src/Select3D/Select3D_SensitivePoly.cxx
src/Select3D/Select3D_SensitiveTriangle.cxx
src/Select3D/Select3D_SensitiveTriangulation.cxx
src/Select3D/Select3D_SensitiveTriangulation.hxx
src/Select3D/Select3D_SensitiveTriangulation.lxx
src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx
src/SelectBasics/SelectBasics_SensitiveEntity.cdl
src/SelectBasics/SelectBasics_SensitiveEntity.cxx
src/SelectBasics/SelectBasics_SensitiveEntity.lxx
src/SelectMgr/SelectMgr_BaseFrustum.cxx
src/SelectMgr/SelectMgr_BaseFrustum.hxx
src/SelectMgr/SelectMgr_Frustum.hxx
src/SelectMgr/SelectMgr_Frustum.lxx
src/SelectMgr/SelectMgr_FrustumBuilder.cxx
src/SelectMgr/SelectMgr_FrustumBuilder.hxx
src/SelectMgr/SelectMgr_RectangularFrustum.cxx
src/SelectMgr/SelectMgr_RectangularFrustum.hxx
src/SelectMgr/SelectMgr_SelectableObjectSet.cxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx
src/SelectMgr/SelectMgr_Selection.cxx
src/SelectMgr/SelectMgr_Selection.hxx
src/SelectMgr/SelectMgr_TriangularFrustum.cxx
src/SelectMgr/SelectMgr_TriangularFrustum.hxx
src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx
src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx
src/SelectMgr/SelectMgr_ViewerSelector.cxx
src/SelectMgr/SelectMgr_ViewerSelector.hxx
src/SelectMgr/SelectMgr_ViewerSelector.lxx
src/StdSelect/StdSelect_ViewerSelector3d.cxx
src/StdSelect/StdSelect_ViewerSelector3d.hxx
src/StdSelect/StdSelect_ViewerSelector3d.lxx
src/ViewerTest/ViewerTest.cxx
src/gp/gp_XYZ.cdl
src/gp/gp_XYZ.lxx

index 8026b714fcea995918a940222c9095b14e1abc9e..b149dfd17337c11bc6f1a920bd26aa4d27ea417a 100644 (file)
@@ -428,8 +428,8 @@ is
 -- Removes selection mode from Interactive Objects.
 -- aMode provides the selection mode index of the entity aniobj.
 
-    SetPixelTolerance(me:mutable;
-                       aPrecision: Real from Standard = 2.0);
+    SetPixelTolerance (me:mutable;
+                       aPrecision: Integer from Standard = 2);
     ---Level: Public
     ---Purpose: Disables the mechanism of adaptive tolerance calculation in SelectMgr_ViewerSelector and
     --          sets the given tolerance for ALL sensitive entities activated. For more information, see
@@ -437,7 +437,7 @@ is
     --  Warning: When a local context is open the sensitivity is apply on it 
     --          instead on the main context.
 
-    PixelTolerance(me) returns Real from Standard;
+    PixelTolerance(me) returns Integer from Standard;
     ---Level: Public 
     ---Purpose: Returns the pixel tolerance.
 
index e65348102845ece84313e80223a5494f963508b6..da36d0752a27df78d10ba8e24ec92d9cb4080928 100644 (file)
@@ -2596,7 +2596,7 @@ void AIS_InteractiveContext::UnsetSelectionMode (const Handle(AIS_InteractiveObj
 //           sensitive entities activated. For more information, see
 //           SelectMgr_ViewerSelector.hxx
 //=======================================================================
-void AIS_InteractiveContext::SetPixelTolerance (const Standard_Real thePrecision)
+void AIS_InteractiveContext::SetPixelTolerance (const Standard_Integer thePrecision)
 {
   if (HasOpenedContext())
   {
@@ -2612,7 +2612,7 @@ void AIS_InteractiveContext::SetPixelTolerance (const Standard_Real thePrecision
 //function : PixelTolerance
 //purpose  :
 //=======================================================================
-Standard_Real AIS_InteractiveContext::PixelTolerance() const
+Standard_Integer AIS_InteractiveContext::PixelTolerance() const
 {
   return HasOpenedContext()
        ? myLocalContexts (myCurLocalIndex)->PixelTolerance()
@@ -2677,7 +2677,7 @@ void AIS_InteractiveContext::InitAttributes()
   aLineAspect->SetTypeOfLine (Aspect_TOL_DASH);
 
   // tolerance to 2 pixels...
-  SetPixelTolerance (2.0);
+  SetPixelTolerance (2);
 
   // Customizing the drawer for trihedrons and planes...
   Handle(Prs3d_DatumAspect) aTrihAspect = myDefaultDrawer->DatumAspect();
index 5a9b10424fd57e55980c38bfd2bcff83e521f478..f123a8693c19f0808c1f26b6967f2276b9bf624b 100644 (file)
@@ -437,13 +437,13 @@ is
                 HiCol     : out NameOfColor from Quantity)
     returns Boolean from Standard;
 
-    SetPixelTolerance(me:mutable;
-                        aPrecision: Real from Standard = 2);
+    SetPixelTolerance (me:mutable;
+                       aPrecision: Integer from Standard = 2);
     ---Level: Public
     ---Purpose: Define the current selection sensitivity for
     --          this local context according to the view size.
 
-    PixelTolerance(me) returns Real from Standard;
+    PixelTolerance(me) returns Integer from Standard;
     ---Level: Public 
     ---Purpose: Returns the pixel tolerance.
 
index 259cf016f6d794f17e5d15dc21d8ee2dd3f82b8a..389a9f4d0e17b030555faeb017175b5653c60c87 100644 (file)
@@ -1139,12 +1139,12 @@ Standard_Boolean AIS_LocalContext::IsImmediateModeOn() const
   return myMainPM->IsImmediateModeOn();
 }
 
-void AIS_LocalContext::SetPixelTolerance(const Standard_Real aPrecision) {
+void AIS_LocalContext::SetPixelTolerance(const Standard_Integer aPrecision) {
 
   myMainVS->SetPixelTolerance(aPrecision);
 }
 
-Standard_Real AIS_LocalContext::PixelTolerance() const {
+Standard_Integer AIS_LocalContext::PixelTolerance() const {
 
   return myMainVS->PixelTolerance();
 }
index 1a17c1b4b6405685974be86bf50d5d15c51fe862..c276f47e9e2542c42ca30a14248d0152024a982a 100644 (file)
@@ -187,7 +187,6 @@ void IVtkOCC_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSel
   theSelection->SetSelectionState (SelectMgr_SOS_Activated);
 
   myTolerances.Add (theSelection->Sensitivity());
-  mytolerance = myTolerances.Tolerance();
   myToUpdateTolerance = Standard_True;
 }
 
@@ -205,6 +204,5 @@ void IVtkOCC_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theS
   theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
 
   myTolerances.Decrement (theSelection->Sensitivity());
-  mytolerance = myTolerances.Tolerance();
   myToUpdateTolerance = Standard_True;
 }
index 16c53eae64a895aa0c39d6616a56b1a4aa176276..bfe2204f6d2b78ef6ee7852a8d1b1fe22a90d15c 100644 (file)
@@ -71,3 +71,21 @@ void MeshVS_DummySensitiveEntity::BVH()
 //================================================================
 void MeshVS_DummySensitiveEntity::Clear()
 {}
+
+//=======================================================================
+//function : HasInitLocation
+//purpose  :
+//=======================================================================
+Standard_Boolean MeshVS_DummySensitiveEntity::HasInitLocation() const
+{
+  return Standard_False;
+}
+
+//=======================================================================
+//function : InvInitLocation
+//purpose  :
+//=======================================================================
+inline gp_Trsf MeshVS_DummySensitiveEntity::InvInitLocation() const
+{
+  return gp_Trsf();
+}
index 6e7402006b77a0f332fa4faebc9dc3d1486af2d3..f9101eefd1cb8e8d18f200db05e2439bf739106e 100644 (file)
@@ -48,6 +48,10 @@ public:
 
   Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
 
+  Standard_EXPORT virtual Standard_Boolean HasInitLocation() const Standard_OVERRIDE;
+
+  Standard_EXPORT virtual gp_Trsf InvInitLocation() const Standard_OVERRIDE;
+
   DEFINE_STANDARD_RTTI(MeshVS_DummySensitiveEntity)
 };
 
index 208c9c66abc40b38f317e472e36ce20bc8add862..703dc6fa3d40e9eacbc902331b49296d96ae803b 100755 (executable)
@@ -3866,6 +3866,118 @@ static Standard_Integer OCC24923(
   return 0;
 }
 
+//=======================================================================
+//function : OCC26195
+//purpose  :
+//=======================================================================
+#include <AIS_Line.hxx>
+#include <Aspect_Window.hxx>
+#include <BRepBuilderAPI_MakePolygon.hxx>
+#include <Geom_CartesianPoint.hxx>
+#include <SelectMgr_SelectingVolumeManager.hxx>
+#include <Visual3d_View.hxx>
+static Standard_Integer OCC26195 (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
+{
+  if (theArgNb < 3)
+  {
+    std::cerr << "Error: wrong number of arguments! See usage:\n";
+    theDI.PrintHelp (theArgVec[0]);
+    return 1;
+  }
+
+  if (ViewerTest::GetAISContext().IsNull())
+  {
+    std::cerr << "Error: No opened context!\n";
+    return 1;
+  }
+
+  gp_Pnt2d aPxPnt1, aPxPnt2;
+  aPxPnt1.SetX (Draw::Atof (theArgVec[1]));
+  aPxPnt1.SetY (Draw::Atof (theArgVec[2]));
+  if (theArgNb > 4)
+  {
+    aPxPnt2.SetX (Draw::Atof (theArgVec[3]));
+    aPxPnt2.SetY (Draw::Atof (theArgVec[4]));
+  }
+  Standard_Boolean toPrint = Standard_False;
+  if (theArgNb % 2 == 0)
+  {
+    toPrint = Draw::Atoi (theArgVec[theArgNb - 1]);
+  }
+
+  SelectMgr_SelectingVolumeManager* aMgr = new SelectMgr_SelectingVolumeManager();
+  aMgr->SetActiveSelectionType (theArgNb > 4 ?
+    SelectMgr_SelectingVolumeManager::Box : SelectMgr_SelectingVolumeManager::Point);
+  aMgr->SetCamera (ViewerTest::CurrentView()->Camera());
+  aMgr->SetPixelTolerance (ViewerTest::GetAISContext()->PixelTolerance());
+  Standard_Integer aWidth, aHeight;
+  ViewerTest::CurrentView()->View()->Window()->Size (aWidth, aHeight);
+  aMgr->SetWindowSize (aWidth, aHeight);
+  if (theArgNb > 4)
+  {
+    aMgr->BuildSelectingVolume (aPxPnt1, aPxPnt2);
+  }
+  else
+  {
+    aMgr->BuildSelectingVolume (aPxPnt1);
+  }
+  const gp_Pnt* aVerts = aMgr->GetVertices();
+  gp_Pnt aNearPnt = aMgr->GetNearPnt();
+  gp_Pnt aFarPnt  = aMgr->GetFarPnt();
+  BRepBuilderAPI_MakePolygon aWireBldrs[4];
+
+  aWireBldrs[0].Add (gp_Pnt (aVerts[0].X(), aVerts[0].Y(), aVerts[0].Z()));
+  aWireBldrs[0].Add (gp_Pnt (aVerts[4].X(), aVerts[4].Y(), aVerts[4].Z()));
+  aWireBldrs[0].Add (gp_Pnt (aVerts[6].X(), aVerts[6].Y(), aVerts[6].Z()));
+  aWireBldrs[0].Add (gp_Pnt (aVerts[2].X(), aVerts[2].Y(), aVerts[2].Z()));
+  aWireBldrs[0].Add (gp_Pnt (aVerts[0].X(), aVerts[0].Y(), aVerts[0].Z()));
+
+  aWireBldrs[1].Add (gp_Pnt (aVerts[4].X(), aVerts[4].Y(), aVerts[4].Z()));
+  aWireBldrs[1].Add (gp_Pnt (aVerts[5].X(), aVerts[5].Y(), aVerts[5].Z()));
+  aWireBldrs[1].Add (gp_Pnt (aVerts[7].X(), aVerts[7].Y(), aVerts[7].Z()));
+  aWireBldrs[1].Add (gp_Pnt (aVerts[6].X(), aVerts[6].Y(), aVerts[6].Z()));
+  aWireBldrs[1].Add (gp_Pnt (aVerts[4].X(), aVerts[4].Y(), aVerts[4].Z()));
+
+  aWireBldrs[2].Add (gp_Pnt (aVerts[1].X(), aVerts[1].Y(), aVerts[1].Z()));
+  aWireBldrs[2].Add (gp_Pnt (aVerts[5].X(), aVerts[5].Y(), aVerts[5].Z()));
+  aWireBldrs[2].Add (gp_Pnt (aVerts[7].X(), aVerts[7].Y(), aVerts[7].Z()));
+  aWireBldrs[2].Add (gp_Pnt (aVerts[3].X(), aVerts[3].Y(), aVerts[3].Z()));
+  aWireBldrs[2].Add (gp_Pnt (aVerts[1].X(), aVerts[1].Y(), aVerts[1].Z()));
+
+  aWireBldrs[3].Add (gp_Pnt (aVerts[0].X(), aVerts[0].Y(), aVerts[0].Z()));
+  aWireBldrs[3].Add (gp_Pnt (aVerts[1].X(), aVerts[1].Y(), aVerts[1].Z()));
+  aWireBldrs[3].Add (gp_Pnt (aVerts[3].X(), aVerts[3].Y(), aVerts[3].Z()));
+  aWireBldrs[3].Add (gp_Pnt (aVerts[2].X(), aVerts[2].Y(), aVerts[2].Z()));
+  aWireBldrs[3].Add (gp_Pnt (aVerts[0].X(), aVerts[0].Y(), aVerts[0].Z()));
+
+  TopoDS_Compound aComp;
+  BRep_Builder    aCompBuilder;
+  aCompBuilder.MakeCompound (aComp);
+  for (Standard_Integer aWireIdx = 0; aWireIdx < 4; ++aWireIdx)
+  {
+    aCompBuilder.Add (aComp, aWireBldrs[aWireIdx].Shape());
+  }
+  DBRep::Set ("c", aComp);
+
+  Handle(AIS_InteractiveObject) aCmp = new AIS_Shape (aComp);
+  aCmp->SetColor (Quantity_NOC_GREEN);
+  ViewerTest::Display ("c", aCmp, Standard_True, Standard_True);
+
+  Handle(Geom_CartesianPoint) aPnt1 = new Geom_CartesianPoint (aNearPnt);
+  Handle(Geom_CartesianPoint) aPnt2 = new Geom_CartesianPoint (aFarPnt);
+
+  Handle(AIS_Line) aLine = new AIS_Line (aPnt1, aPnt2);
+  ViewerTest::Display ("l", aLine, Standard_True, Standard_True);
+
+  if (toPrint)
+  {
+    theDI << "Near: " << aNearPnt.X() << " " << aNearPnt.Y() << " " << aNearPnt.Z() << "\n";
+    theDI << "Far: " << aFarPnt.X() << " " << aFarPnt.Y() << " " << aFarPnt.Z() << "\n";
+  }
+
+  return 0;
+}
+
 void QABugs::Commands_19(Draw_Interpretor& theCommands) {
   const char *group = "QABugs";
 
@@ -3938,5 +4050,6 @@ void QABugs::Commands_19(Draw_Interpretor& theCommands) {
   theCommands.Add ("xprojponf", "xprojponf p f", __FILE__, xprojponf, group);
   theCommands.Add ("OCC24923", "OCC24923", __FILE__, OCC24923, group);
   theCommands.Add ("OCC26139", "OCC26139 [-boxsize value] [-boxgrid value] [-compgrid value]", __FILE__, OCC26139, group);
+  theCommands.Add ("OCC26195", "OCC26195 x1_pix y1_pix [x2_pix y2_pix] [toPrintPixelCoord 0|1]", __FILE__, OCC26195, group);
   return;
 }
index ead44d99d303910b4c489595dc952f5d1c92ad12..1a32712efc3cead387de114049391a86438121b2 100644 (file)
@@ -100,7 +100,7 @@ Standard_Boolean Select3D_SensitiveBox::Matches (SelectBasics_SelectingVolumeMan
   }
 
   Standard_Real aDepth;
-  if (!theMgr.Overlaps (myBox, aDepth)) // check for overlap
+  if (!theMgr.Overlaps (myBox.CornerMin(), myBox.CornerMax(), aDepth)) // check for overlap
   {
     return Standard_False;
   }
index 3f8eaa23a59fef373adc825441cd446c11e2e5d1..cff276b50031bbecea9ffadc0bb94031ec534eff 100644 (file)
@@ -108,7 +108,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_Ent
 
   if (mySensType == Select3D_TOS_BOUNDARY)
   {
-    SetSensitivityFactor (6.0);
+    SetSensitivityFactor (6);
   }
 }
 
@@ -166,7 +166,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle (const Handle(SelectBasics_En
 
   if (mySensType == Select3D_TOS_BOUNDARY)
   {
-    SetSensitivityFactor (6.0);
+    SetSensitivityFactor (6);
   }
 }
 
@@ -177,7 +177,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle (const Handle(SelectBasics_En
 Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& theOwnerId,
                                                    const Handle(TColgp_HArray1OfPnt)& thePnts3d,
                                                    const Standard_Boolean theIsFilled)
-: Select3D_SensitivePoly (theOwnerId, thePnts3d, !theIsFilled),
+: Select3D_SensitivePoly (theOwnerId, thePnts3d, static_cast<Standard_Boolean> (!theIsFilled)),
   myStart (0),
   myEnd (0)
 {
@@ -190,7 +190,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_Ent
 
   if (mySensType == Select3D_TOS_BOUNDARY)
   {
-    SetSensitivityFactor (6.0);
+    SetSensitivityFactor (6);
   }
 }
 
@@ -215,7 +215,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_Ent
 
   if (mySensType == Select3D_TOS_BOUNDARY)
   {
-    SetSensitivityFactor (6.0);
+    SetSensitivityFactor (6);
   }
 }
 
@@ -256,9 +256,10 @@ Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolume
     if (!theMgr.IsOverlapAllowed())
     {
       thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
-      if (!theMgr.Overlaps (myBndBox.CornerMin(), myBndBox.CornerMax(), Standard_False))
+      for (Standard_Integer aPntIdx = anArrayOfPnt->Lower(); aPntIdx <= anArrayOfPnt->Upper(); ++aPntIdx)
       {
-        return Standard_False;
+        if (!theMgr.Overlaps (anArrayOfPnt->Value (aPntIdx)))
+          return Standard_False;
       }
       return Standard_True;
     }
index 91951b4c3164324535c3637d0802b6682513d03d..a838f6b5def121f3881af474eadf82f87df5d181 100644 (file)
@@ -32,7 +32,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti
   myCurve (theCurve)
 {
   loadPoints (theCurve, theNbPnts);
-  SetSensitivityFactor (3.0);
+  SetSensitivityFactor (3);
 }
 
 //==================================================
@@ -44,7 +44,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti
 : Select3D_SensitivePoly (theOwnerId, thePoints, Standard_True)
 
 {
-  SetSensitivityFactor (3.0);
+  SetSensitivityFactor (3);
 }
 
 //==================================================
@@ -55,7 +55,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti
                                                   const TColgp_Array1OfPnt& thePoints)
 : Select3D_SensitivePoly (theOwnerId, thePoints, Standard_True)
 {
-  SetSensitivityFactor (3.0);
+  SetSensitivityFactor (3);
 }
 
 //==================================================
index 19f73a5ca558bd3f07263a6bef1cd8a6ca1ce46d..fc19cd939b44bc9be8c404732630414514f8f46c 100644 (file)
@@ -25,10 +25,9 @@ IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveEntity, SelectBasics_SensitiveEntit
 
 //=======================================================================
 //function : Select3D_SensitiveEntity
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-Select3D_SensitiveEntity::Select3D_SensitiveEntity(const Handle(SelectBasics_EntityOwner)& theOwnerId)
+Select3D_SensitiveEntity::Select3D_SensitiveEntity (const Handle(SelectBasics_EntityOwner)& theOwnerId)
 : SelectBasics_SensitiveEntity (theOwnerId) {}
 
 //=======================================================================
@@ -71,3 +70,22 @@ void Select3D_SensitiveEntity::Clear()
 {
   Set (NULL);
 }
+
+//=======================================================================
+// function : HasInitLocation
+// purpose  : Returns true if the shape corresponding to the entity has init location
+//=======================================================================
+Standard_Boolean Select3D_SensitiveEntity::HasInitLocation() const
+{
+  return Standard_False;
+}
+
+//=======================================================================
+// function : InvInitLocation
+// purpose  : Returns inversed location transformation matrix if the shape corresponding
+//            to this entity has init location set. Otherwise, returns identity matrix.
+//=======================================================================
+gp_Trsf Select3D_SensitiveEntity::InvInitLocation() const
+{
+  return gp_Trsf();
+}
index a235f15ad01cccd1738c69bc5b82022c5deafb17..fe2a9e1f495f4c27a8ee72f4d8f689cc5dc94e0d 100644 (file)
@@ -80,6 +80,13 @@ public:
   //! Clears up all resources and memory
   Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
 
+  //! Returns true if the shape corresponding to the entity has init location
+  Standard_EXPORT virtual Standard_Boolean HasInitLocation() const Standard_OVERRIDE;
+
+  //! Returns inversed location transformation matrix if the shape corresponding
+  //! to this entity has init location set. Otherwise, returns identity matrix.
+  Standard_EXPORT virtual gp_Trsf InvInitLocation() const;
+
   DEFINE_STANDARD_RTTI(Select3D_SensitiveEntity)
 
 protected:
index 10bacb5d0f4a1682e5ea9ef2190a4fbd0a57cd90..214a65285cfc90a79e3208897fe4e059f4890cca 100644 (file)
@@ -29,7 +29,7 @@ Select3D_SensitivePoint::Select3D_SensitivePoint (const Handle(SelectBasics_Enti
                                                   const gp_Pnt& thePoint)
 : Select3D_SensitiveEntity (theOwner)
 {
-  SetSensitivityFactor (12.0);
+  SetSensitivityFactor (12);
   myPoint = thePoint;
 }
 
index ee3f9fe149044ef90bcfb6dabd1ddb4b111cd94d..a89217619e810b4dd1f5ad172c8d74b5da897ccd 100644 (file)
@@ -250,9 +250,8 @@ Standard_Boolean Select3D_SensitivePoly::elementIsInside (SelectBasics_Selecting
 {
   const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theElemIdx);
 
-  Standard_Real aDummy;
-  return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0), aDummy)
-      && theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 1), aDummy);
+  return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0))
+      && theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 1));
 }
 
 //==================================================
index 7f43e7f5cf0d466bdb477ee25d2c36a5c2097b5e..eca050a6203f14b8bf356fc77fbfa5b5278b14f9 100644 (file)
@@ -54,10 +54,9 @@ Standard_Boolean Select3D_SensitiveTriangle::Matches (SelectBasics_SelectingVolu
   Standard_Real aDistToCOG = RealLast();
   if (!theMgr.IsOverlapAllowed())
   {
-    Standard_Real aDummy;
-    return theMgr.Overlaps (myPoints[0], aDummy)
-        && theMgr.Overlaps (myPoints[1], aDummy)
-        && theMgr.Overlaps (myPoints[2], aDummy);
+    return theMgr.Overlaps (myPoints[0])
+        && theMgr.Overlaps (myPoints[1])
+        && theMgr.Overlaps (myPoints[2]);
   }
 
   if (!theMgr.Overlaps (myPoints[0], myPoints[1], myPoints[2], mySensType, aDepth))
index c3973af13d0a6398677fafdfda745e947dd8b4a4..acfc0e248e916480f7ad8c129caf1a31f39cc0ac 100644 (file)
@@ -56,6 +56,7 @@ Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(S
   myInitLocation (theInitLoc),
   myDetectedTr (-1)
 {
+  myInvInitLocation = myInitLocation.Transformation().Inverted();
   mySensType = theIsInterior ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
   const Poly_Array1OfTriangle& aTriangles = myTriangul->Triangles();
   const TColgp_Array1OfPnt& aNodes = myTriangul->Nodes();
@@ -148,6 +149,7 @@ Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(S
   myFreeEdges (theFreeEdges),
   myDetectedTr (-1)
 {
+  myInvInitLocation = myInitLocation.Transformation().Inverted();
   mySensType = theIsInterior ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
   myPrimitivesNb = theIsInterior ? theTrg->Triangles().Length() : theFreeEdges->Length() / 2;
   myBVHPrimIndexes = new TColStd_HArray1OfInteger(0, myPrimitivesNb - 1);
@@ -187,19 +189,15 @@ Select3D_BndBox3d Select3D_SensitiveTriangulation::Box (const Standard_Integer t
   Standard_Integer aPrimIdx = myBVHPrimIndexes->Value (theIdx);
   SelectMgr_Vec3 aMinPnt (RealLast());
   SelectMgr_Vec3 aMaxPnt (RealFirst());
-  Standard_Boolean hasInitLoc = HasInitLocation();
 
   if (mySensType == Select3D_TOS_INTERIOR)
   {
     Standard_Integer aNode1, aNode2, aNode3;
     myTriangul->Triangles() (aPrimIdx + 1).Get (aNode1, aNode2, aNode3);
 
-    gp_Pnt aPnt1 = hasInitLoc ? myTriangul->Nodes().Value (aNode1).Transformed (myInitLocation.Transformation())
-                              : myTriangul->Nodes().Value (aNode1);
-    gp_Pnt aPnt2 = hasInitLoc ? myTriangul->Nodes().Value (aNode2).Transformed (myInitLocation.Transformation())
-                              : myTriangul->Nodes().Value (aNode2);
-    gp_Pnt aPnt3 = hasInitLoc ? myTriangul->Nodes().Value (aNode3).Transformed (myInitLocation.Transformation())
-                              : myTriangul->Nodes().Value (aNode3);
+    gp_Pnt aPnt1 = myTriangul->Nodes().Value (aNode1);
+    gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2);
+    gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3);
 
     aMinPnt = SelectMgr_Vec3 (Min (aPnt1.X(), Min (aPnt2.X(), aPnt3.X())),
                               Min (aPnt1.Y(), Min (aPnt2.Y(), aPnt3.Y())),
@@ -212,10 +210,8 @@ Select3D_BndBox3d Select3D_SensitiveTriangulation::Box (const Standard_Integer t
   {
     Standard_Integer aNodeIdx1 = myFreeEdges->Value (myFreeEdges->Lower() + aPrimIdx);
     Standard_Integer aNodeIdx2 = myFreeEdges->Value (myFreeEdges->Lower() + aPrimIdx + 1);
-    gp_Pnt aNode1 = hasInitLoc ? myTriangul->Nodes().Value (aNodeIdx1).Transformed (myInitLocation.Transformation())
-                               : myTriangul->Nodes().Value (aNodeIdx1);
-    gp_Pnt aNode2 = hasInitLoc ? myTriangul->Nodes().Value (aNodeIdx2).Transformed (myInitLocation.Transformation())
-                               : myTriangul->Nodes().Value (aNodeIdx2);
+    gp_Pnt aNode1 = myTriangul->Nodes().Value (aNodeIdx1);
+    gp_Pnt aNode2 = myTriangul->Nodes().Value (aNodeIdx2);
 
     aMinPnt = SelectMgr_Vec3 (Min (aNode1.X(), aNode2.X()),
                               Min (aNode1.Y(), aNode2.Y()),
@@ -266,17 +262,14 @@ Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_
                                                                    Standard_Real& theMatchDepth)
 {
   const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
-  Standard_Boolean hasInitLoc = HasInitLocation();
 
   if (mySensType == Select3D_TOS_BOUNDARY)
   {
     Standard_Integer aSegmStartIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 1);
     Standard_Integer aSegmEndIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 2);
     Handle(TColgp_HArray1OfPnt) anEdgePnts = new TColgp_HArray1OfPnt (1, 2);
-    gp_Pnt aSegmStart = hasInitLoc ? myTriangul->Nodes().Value (aSegmStartIdx).Transformed (myInitLocation.Transformation())
-                                   : myTriangul->Nodes().Value (aSegmStartIdx);
-    gp_Pnt aSegmEnd   = hasInitLoc ? myTriangul->Nodes().Value (aSegmEndIdx).Transformed (myInitLocation.Transformation())
-                                   : myTriangul->Nodes().Value (aSegmEndIdx);
+    gp_Pnt aSegmStart = myTriangul->Nodes().Value (aSegmStartIdx);
+    gp_Pnt aSegmEnd   = myTriangul->Nodes().Value (aSegmEndIdx);
     anEdgePnts->SetValue (1, aSegmStart);
     anEdgePnts->SetValue (2, aSegmEnd);
     Standard_Boolean isMatched = theMgr.Overlaps (anEdgePnts, Select3D_TOS_BOUNDARY, theMatchDepth);
@@ -288,12 +281,9 @@ Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_
     const Poly_Array1OfTriangle& aTriangles = myTriangul->Triangles();
     Standard_Integer aNode1, aNode2, aNode3;
     aTriangles (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
-    gp_Pnt aPnt1 = hasInitLoc ? myTriangul->Nodes().Value (aNode1).Transformed (myInitLocation.Transformation())
-                              : myTriangul->Nodes().Value (aNode1);
-    gp_Pnt aPnt2 = hasInitLoc ? myTriangul->Nodes().Value (aNode2).Transformed (myInitLocation.Transformation())
-                              : myTriangul->Nodes().Value (aNode2);
-    gp_Pnt aPnt3 = hasInitLoc ? myTriangul->Nodes().Value (aNode3).Transformed (myInitLocation.Transformation())
-                              : myTriangul->Nodes().Value (aNode3);
+    gp_Pnt aPnt1 = myTriangul->Nodes().Value (aNode1);
+    gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2);
+    gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3);
     return theMgr.Overlaps (aPnt1, aPnt2, aPnt3, Select3D_TOS_INTERIOR, theMatchDepth);
   }
 }
@@ -305,8 +295,6 @@ Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_
 Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
                                                                    const Standard_Integer               theElemIdx)
 {
-  Standard_Real aDummy;
-
   const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
 
   if (mySensType == Select3D_TOS_BOUNDARY)
@@ -314,13 +302,7 @@ Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_
     gp_Pnt aSegmPnt1 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 1));
     gp_Pnt aSegmPnt2 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 2));
 
-    if (HasInitLocation()) // Note: Should be removed (by transforming frustum)
-    {
-      aSegmPnt1.Transform (myInitLocation.Transformation());
-      aSegmPnt2.Transform (myInitLocation.Transformation());
-    }
-
-    return theMgr.Overlaps (aSegmPnt1, aDummy) && theMgr.Overlaps (aSegmPnt2, aDummy);
+    return theMgr.Overlaps (aSegmPnt1) && theMgr.Overlaps (aSegmPnt2);
   }
   else
   {
@@ -334,16 +316,9 @@ Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_
     gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2);
     gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3);
 
-    if (HasInitLocation()) // Note: Should be removed (by transforming frustum)
-    {
-      aPnt1.Transform (myInitLocation.Transformation());
-      aPnt2.Transform (myInitLocation.Transformation());
-      aPnt3.Transform (myInitLocation.Transformation());
-    }
-
-    return theMgr.Overlaps (aPnt1, aDummy)
-        && theMgr.Overlaps (aPnt2, aDummy)
-        && theMgr.Overlaps (aPnt3, aDummy);
+    return theMgr.Overlaps (aPnt1)
+        && theMgr.Overlaps (aPnt2)
+        && theMgr.Overlaps (aPnt3);
   }
 }
 
@@ -390,7 +365,7 @@ Select3D_BndBox3d Select3D_SensitiveTriangulation::applyTransformation()
         gp_Pnt aVertex = gp_Pnt (aX == 0 ? myBndBox.CornerMin().x() : myBndBox.CornerMax().x(),
                                  aY == 0 ? myBndBox.CornerMin().y() : myBndBox.CornerMax().y(),
                                  aZ == 0 ? myBndBox.CornerMin().z() : myBndBox.CornerMax().z());
-        aVertex.Transform (myInitLocation);
+        aVertex.Transform (myInitLocation.Transformation());
         aBndBox.Add (Select3D_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z()));
       }
     }
@@ -431,7 +406,7 @@ Select3D_BndBox3d Select3D_SensitiveTriangulation::BoundingBox()
 //=======================================================================
 gp_Pnt Select3D_SensitiveTriangulation::CenterOfGeometry() const
 {
-  return HasInitLocation() ? myCDG3D.Transformed (myInitLocation) : myCDG3D;
+  return myCDG3D;
 }
 
 //=======================================================================
@@ -441,4 +416,22 @@ gp_Pnt Select3D_SensitiveTriangulation::CenterOfGeometry() const
 Standard_Integer Select3D_SensitiveTriangulation::NbSubElements()
 {
   return myTriangul->Nodes().Length();
-}
\ No newline at end of file
+}
+
+//=======================================================================
+//function : HasInitLocation
+//purpose  :
+//=======================================================================
+Standard_Boolean Select3D_SensitiveTriangulation::HasInitLocation() const
+{
+  return !myInitLocation.IsIdentity();
+}
+
+//=======================================================================
+//function : InvInitLocation
+//purpose  :
+//=======================================================================
+gp_Trsf Select3D_SensitiveTriangulation::InvInitLocation() const
+{
+  return myInvInitLocation;
+}
index 537e05346fc4077efd67fb1f84c4c27c3cde2c88..f19b57ea741fcf70cecad22958356cc4f9b24cac 100644 (file)
@@ -83,10 +83,6 @@ public:
 
   const Handle_Poly_Triangulation& Triangulation() const;
 
-  Standard_Boolean HasInitLocation() const;
-
-  const TopLoc_Location& GetInitLocation() const;
-
   //! Returns the length of array of triangles or edges
   Standard_EXPORT virtual Standard_Integer Size() const Standard_OVERRIDE;
 
@@ -110,6 +106,15 @@ public:
   //! is set, it will be applied
   Standard_EXPORT virtual gp_Pnt CenterOfGeometry() const Standard_OVERRIDE;
 
+  //! Returns true if the shape corresponding to the entity has init location
+  Standard_EXPORT virtual Standard_Boolean HasInitLocation() const Standard_OVERRIDE;
+
+  //! Returns inversed location transformation matrix if the shape corresponding
+  //! to this entity has init location set. Otherwise, returns identity matrix.
+  Standard_EXPORT virtual gp_Trsf InvInitLocation() const Standard_OVERRIDE;
+
+  inline const TopLoc_Location& GetInitLocation() const;
+
 public:
   DEFINE_STANDARD_RTTI(Select3D_SensitiveTriangulation)
 
@@ -134,20 +139,18 @@ private:
   virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
                                             const Standard_Integer               theElemIdx) Standard_OVERRIDE;
 
-public:
-  Standard_Real myBVHBuildTime;
-
 private:
 
   Handle_Poly_Triangulation       myTriangul;
-  TopLoc_Location                 myInitLocation;
-  gp_Pnt                          myCDG3D;              //!< Center of the whole triangulation
+  TopLoc_Location                  myInitLocation;
+  gp_Pnt                           myCDG3D;              //!< Center of the whole triangulation
   Handle_TColStd_HArray1OfInteger myFreeEdges;
-  Standard_Boolean                mySensType;            //!< Type of sensitivity: boundary or interior
-  Standard_Integer                myDetectedTr;
-  Standard_Integer                myPrimitivesNb;       //!< Amount of free edges or triangles depending on sensitivity type
+  Standard_Boolean                 mySensType;            //!< Type of sensitivity: boundary or interior
+  Standard_Integer                 myDetectedTr;
+  Standard_Integer                 myPrimitivesNb;       //!< Amount of free edges or triangles depending on sensitivity type
   Handle_TColStd_HArray1OfInteger myBVHPrimIndexes;     //!< Indexes of edges or triangles for BVH build
-  mutable Select3D_BndBox3d       myBndBox;             //!< Bounding box of the whole triangulation
+  mutable Select3D_BndBox3d        myBndBox;             //!< Bounding box of the whole triangulation
+  gp_Trsf                          myInvInitLocation;
 };
 
 DEFINE_STANDARD_HANDLE(Select3D_SensitiveTriangulation, Select3D_SensitiveSet)
index 4da21970c62b184d9f4518793000f248ef9d7898..9898e4b1e8fa8463540d7f70787e5fd2d6a06b9f 100644 (file)
@@ -23,15 +23,6 @@ inline const Handle(Poly_Triangulation)& Select3D_SensitiveTriangulation::Triang
   return myTriangul;
 }
 
-//=======================================================================
-//function : HasInitLocation
-//purpose  :
-//=======================================================================
-inline Standard_Boolean Select3D_SensitiveTriangulation::HasInitLocation() const
-{
-  return !myInitLocation.IsIdentity();
-}
-
 //=======================================================================
 //function : GetInitLocation
 //purpose  :
index df795b5e34fbc714767eddfa55a458a3a175349a..480978e77c522b53cacdb163a50f120c4ad130ec 100644 (file)
@@ -17,8 +17,8 @@
 #define _SelectBasics_SelectingVolumeManager_HeaderFile
 
 #include <BVH_Box.hxx>
+#include <gp_Pnt.hxx>
 #include <TColgp_HArray1OfPnt.hxx>
-#include <NCollection_Vec3.hxx>
 
 class Bnd_Box;
 class gp_Pnt;
@@ -44,7 +44,8 @@ public:
   virtual Standard_Integer GetActiveSelectionType() const = 0;
 
   //! Returns true if selecting volume is overlapped by box theBox
-  virtual Standard_Boolean Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
+  virtual Standard_Boolean Overlaps (const NCollection_Vec3<Standard_Real>& theBoxMin,
+                                     const NCollection_Vec3<Standard_Real>& theBoxMax,
                                      Standard_Real& theDepth) = 0;
 
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box with minimum
@@ -53,10 +54,15 @@ public:
                                      const NCollection_Vec3<Standard_Real>& theBoxMax,
                                      Standard_Boolean*                      theInside = NULL) = 0;
 
-  //! Returns true if selecting volume is overlapped by point thePt
-  virtual Standard_Boolean Overlaps (const gp_Pnt& thePt,
+  //! Returns true if selecting volume is overlapped by point thePnt
+  virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt,
                                      Standard_Real& theDepth) = 0;
 
+  //! Returns true if selecting volume is overlapped by point thePnt.
+  //! Does not perform depth calculation, so this method is defined as
+  //! helper function for inclusion test.
+  virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) = 0;
+
   //! Returns true if selecting volume is overlapped by planar convex polygon, which points
   //! are stored in theArrayOfPts, taking into account sensitivity type theSensType
   virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts,
@@ -81,7 +87,7 @@ public:
   //! to the given point theCOG
   virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) = 0;
 
-  virtual NCollection_Vec3<Standard_Real> DetectedPoint (const Standard_Real theDepth) const = 0;
+  virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const = 0;
 
   virtual Standard_Boolean IsOverlapAllowed() const = 0;
 
index 185f60ca7e785e8a1114ef75670dfae80d33a66d..c31e6b8a8b3d2a0fbbc90d788c39f6ef2b162097 100644 (file)
@@ -19,7 +19,8 @@ deferred class SensitiveEntity from SelectBasics inherits TShared from MMgt
   ---Purpose: root class; the inheriting classes will be able to give
   --          sensitive Areas for the dynamic selection algorithms
 
-uses 
+uses
+    Trsf from gp,
     EntityOwner,
     BndBox3d from Select3D,
     PickResult,
@@ -29,7 +30,7 @@ is
 
 
     Initialize (theOwnerId       : EntityOwner;
-                theSensFactor    : Real from Standard = 2.0);
+                theSensFactor    : Integer from Standard = 2);
 
     Set (me : mutable;
          theOwnerId : EntityOwner)
@@ -55,7 +56,7 @@ is
     --          current selecting volume
 
     SensitivityFactor (me)
-      returns Real from Standard;
+      returns Integer from Standard;
     ---C++: inline
     ---Purpose: allows a better sensitivity for
     --          a specific entity in selection algorithms
@@ -78,8 +79,20 @@ is
     Clear (me : mutable) is deferred;
     ---Purpose: Clears up all the resources and memory allocated
 
+    HasInitLocation (me)
+      returns Boolean from Standard
+      is deferred;
+    ---Purpose: Returns true if the shape corresponding to the entity
+    --          has init location.
+
+    InvInitLocation (me)
+      returns Trsf from gp
+      is deferred;
+    ---Purpose: Returns inversed location transformation matrix if the shape corresponding
+    --          to this entity has init location set. Otherwise, returns identity matrix.
+
     SetSensitivityFactor (me : mutable;
-                          theSensFactor :Real from Standard)
+                          theSensFactor : Integer from Standard)
       is protected;
     ---C++: inline
     ---Purpose: Allows to manage the sensitivity of the entity
@@ -88,5 +101,5 @@ is
 fields
     
     myOwnerId       : EntityOwner from SelectBasics is protected;
-    mySFactor       : Real from Standard;
+    mySFactor       : Integer from Standard;
 end SensitiveEntity;
index d69189c9573757cc6a1dee95577eb897891ccd4c..b04aa82066f495088e9df87829922361acf8e16f 100644 (file)
@@ -22,7 +22,7 @@
 // purpose  : Creates new empty sensitive entity instance
 //=======================================================================
 SelectBasics_SensitiveEntity::SelectBasics_SensitiveEntity (const Handle(SelectBasics_EntityOwner)& theOwnerId,
-                                                            const Standard_Real theSensFactor)
+                                                            const Standard_Integer theSensFactor)
 : myOwnerId (theOwnerId),
   mySFactor (theSensFactor) {}
 
index 54df66f6ce59191c7c6c54dd7cb12f602bd8d5e5..380ceb17fc7d135b0b71038c5e98a8389f845070 100644 (file)
@@ -16,7 +16,7 @@
 // function : SetSensitivityFactor
 // purpose  : Allows to manage the sensitivity of the entity
 //=======================================================================
-inline void SelectBasics_SensitiveEntity::SetSensitivityFactor (const Standard_Real theSensFactor)
+inline void SelectBasics_SensitiveEntity::SetSensitivityFactor (const Standard_Integer theSensFactor)
 {
   mySFactor = theSensFactor;
 }
@@ -25,7 +25,7 @@ inline void SelectBasics_SensitiveEntity::SetSensitivityFactor (const Standard_R
 // function : SensitivityFactor
 // purpose  : Gets sensitivity factor for the entity
 //=======================================================================
-inline Standard_Real SelectBasics_SensitiveEntity::SensitivityFactor() const
+inline Standard_Integer SelectBasics_SensitiveEntity::SensitivityFactor() const
 {
   return mySFactor;
 }
index 62d6de3de9996deb8b934202b003b1cb474dcf54..a59c6dabd3e0a47c2eccfab87bff70a7c45993af 100644 (file)
@@ -68,7 +68,7 @@ void SelectMgr_BaseFrustum::SetViewport (const Standard_Real theX,
 // function : SetPixelTolerance
 // purpose  :
 //=======================================================================
-void SelectMgr_BaseFrustum::SetPixelTolerance (const Standard_Real theTol)
+void SelectMgr_BaseFrustum::SetPixelTolerance (const Standard_Integer theTol)
 {
   myPixelTolerance = theTol;
 }
@@ -97,7 +97,8 @@ void SelectMgr_BaseFrustum::SetBuilder (const Handle(SelectMgr_FrustumBuilder)&
 // purpose  : SAT intersection test between defined volume and
 //            given axis-aligned box
 //=======================================================================
-Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const BVH_Box<Standard_Real, 3>& /*theBndBox*/,
+Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const SelectMgr_Vec3& /*theBoxMin*/,
+                                                  const SelectMgr_Vec3& /*theBoxMax*/,
                                                   Standard_Real& /*theDepth*/)
 {
   return Standard_False;
@@ -118,12 +119,21 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const SelectMgr_Vec3& /*theBox
 // function : Overlaps
 // purpose  : Intersection test between defined volume and given point
 //=======================================================================
-Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePt*/,
+Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePnt*/,
                                                   Standard_Real& /*theDepth*/)
 {
   return Standard_False;
 }
 
+//=======================================================================
+// function : Overlaps
+// purpose  : Intersection test between defined volume and given point
+//=======================================================================
+Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePnt*/)
+{
+  return Standard_False;
+}
+
 //=======================================================================
 // function : Overlaps
 // purpose  : SAT intersection test between defined volume and given
@@ -131,7 +141,7 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePt*/,
 //            may be considered of interior part or boundary line defined
 //            by segments depending on given sensitivity type
 //=======================================================================
-Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const Handle(TColgp_HArray1OfPnt)& /*theArrayOfPts*/,
+Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const Handle(TColgp_HArray1OfPnt)& /*theArrayOfPnts*/,
                                                   Select3D_TypeOfSensitivity /*theSensType*/,
                                                   Standard_Real& /*theDepth*/)
 {
@@ -158,8 +168,8 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePt1*/,
 // function : Overlaps
 // purpose  : Checks if line segment overlaps selecting volume
 //=======================================================================
-Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePt1*/,
-                                                  const gp_Pnt& /*thePt2*/,
+Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePnt1*/,
+                                                  const gp_Pnt& /*thePnt2*/,
                                                   Standard_Real& /*theDepth*/)
 {
   return Standard_False;
@@ -175,9 +185,9 @@ Standard_Real SelectMgr_BaseFrustum::DistToGeometryCenter (const gp_Pnt& /*theCO
   return DBL_MAX;
 }
 
-SelectMgr_Vec3 SelectMgr_BaseFrustum::DetectedPoint (const Standard_Real /*theDepth*/) const
+gp_Pnt SelectMgr_BaseFrustum::DetectedPoint (const Standard_Real /*theDepth*/) const
 {
-  return SelectMgr_Vec3 (RealLast());
+  return gp_Pnt (RealLast(), RealLast(), RealLast());
 }
 
 //=======================================================================
index 0efa02be3b4a44907a705af97b996bcd6b59cb52..1b3a5e60872cc5f2ba6343bbd7c4184534ecea4d 100644 (file)
@@ -16,8 +16,6 @@
 #ifndef _SelectMgr_BaseFrustum_HeaderFile
 #define _SelectMgr_BaseFrustum_HeaderFile
 
-#include <Bnd_Box.hxx>
-
 #include <gp_Pnt.hxx>
 #include <gp_Pln.hxx>
 
@@ -56,7 +54,7 @@ public:
                   const Graphic3d_Mat4d& theOrientation,
                   const Standard_Integer theIsOrthographic);
 
-  void SetPixelTolerance (const Standard_Real theTol);
+  void SetPixelTolerance (const Standard_Integer theTol);
 
   void SetWindowSize (const Standard_Integer theWidth, const Standard_Integer theHeight);
 
@@ -85,14 +83,19 @@ public:
   //! Builds selecting volumes set according to polyline points
   virtual void Build (const TColgp_Array1OfPnt2d& /*thePoints*/) {}
 
-  virtual NCollection_Handle<SelectMgr_BaseFrustum> Transform (const gp_Trsf& /*theTrsf*/) { return NULL; }
-
-  //! IMPORTANT: Makes sense only for frustum built on a single point!
+  //! IMPORTANT: Scaling makes sense only for frustum built on a single point!
+  //!            Note that this method does not perform any checks on type of the frustum.
   //! Returns a copy of the frustum resized according to the scale factor given
-  virtual NCollection_Handle<SelectMgr_BaseFrustum> Scale (const Standard_Real /*theScaleFactor*/) { return NULL; }
+  //! and transforms it using the matrix given.
+  //! There are no default parameters, but in case if:
+  //!    - transformation only is needed: @theScaleFactor must be initialized as any negative value;
+  //!    - scale only is needed: @theTrsf must be set to gp_Identity.
+  Standard_EXPORT virtual NCollection_Handle<SelectMgr_BaseFrustum> ScaleAndTransform (const Standard_Integer /*theScaleFactor*/,
+                                                                                       const gp_Trsf& /*theTrsf*/) { return NULL; }
 
   //! SAT intersection test between defined volume and given axis-aligned box
-  virtual Standard_Boolean Overlaps (const BVH_Box<Standard_Real, 3>& theBndBox,
+  virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                     const SelectMgr_Vec3& theBoxMax,
                                      Standard_Real& theDepth);
 
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box
@@ -102,19 +105,25 @@ public:
                                      Standard_Boolean*     theInside = NULL);
 
   //! Intersection test between defined volume and given point
-  virtual Standard_Boolean Overlaps (const gp_Pnt& thePt,
+  virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt,
                                      Standard_Real& theDepth);
 
+  //! Intersection test between defined volume and given point
+  //! Does not perform depth calculation, so this method is defined as
+  //! helper function for inclusion test. Therefore, its implementation
+  //! makes sense only for rectangular frustum with box selection mode activated.
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt);
+
   //! SAT intersection test between defined volume and given ordered set of points,
   //! representing line segments. The test may be considered of interior part or
   //! boundary line defined by segments depending on given sensitivity type
-  virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts,
+  virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
                                      Select3D_TypeOfSensitivity theSensType,
                                      Standard_Real& theDepth);
 
   //! Checks if line segment overlaps selecting frustum
-  virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1,
-                                     const gp_Pnt& thePt2,
+  virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1,
+                                     const gp_Pnt& thePnt2,
                                      Standard_Real& theDepth);
 
   //! SAT intersection test between defined volume and given triangle. The test may
@@ -130,7 +139,7 @@ public:
   //! screen point and given point theCOG
   virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG);
 
-  virtual SelectMgr_Vec3 DetectedPoint (const Standard_Real theDepth) const;
+  virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const;
 
   //! Checks if the point of sensitive in which selection was detected belongs
   //! to the region defined by clipping planes
@@ -138,8 +147,8 @@ public:
                                       const Standard_Real theDepth);
 
 protected:
-  Standard_Real    myPixelTolerance;      //!< Pixel tolerance
-  Standard_Boolean myIsOrthographic;      //!< Defines if current camera is orthographic
+  Standard_Integer    myPixelTolerance;      //!< Pixel tolerance
+  Standard_Boolean    myIsOrthographic;      //!< Defines if current camera is orthographic
 
   Handle(SelectMgr_FrustumBuilder) myBuilder; //!< A tool implementing methods for volume build
 };
index e5f9e1c8f2702044a5d5641fc3976f8366b5e895..b72d6a310d50224ee846bfcb8587c0ccf4608f4f 100644 (file)
@@ -18,6 +18,8 @@
 
 #include <BVH_Box.hxx>
 #include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+#include <gp_XYZ.hxx>
 #include <SelectMgr_BaseFrustum.hxx>
 #include <TColgp_HArray1OfPnt.hxx>
 #include <TColgp_Array1OfPnt2d.hxx>
@@ -75,39 +77,39 @@ protected:
 
   //! SAT intersection test between frustum given and planar convex polygon represented as ordered point set
   Standard_Boolean hasOverlap (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
-                               SelectMgr_Vec3& theNormal);
+                               gp_Vec& theNormal);
 
   //! SAT intersection test between defined volume and given triangle
   Standard_Boolean hasOverlap (const gp_Pnt& thePnt1,
                                const gp_Pnt& thePnt2,
                                const gp_Pnt& thePnt3,
-                               SelectMgr_Vec3& theNormal);
+                               gp_Vec& theNormal);
 
 private:
 
   //! Checks if AABB and frustum are separated along the given axis
   Standard_Boolean isSeparated (const SelectMgr_Vec3& theBoxMin,
                                 const SelectMgr_Vec3& theBoxMax,
-                                const SelectMgr_Vec3& theDirect,
+                                const gp_XYZ&         theDirect,
                                 Standard_Boolean*     theInside) const;
 
   //! Checks if triangle and frustum are separated along the given axis
   Standard_Boolean isSeparated (const gp_Pnt& thePnt1,
                                 const gp_Pnt& thePnt2,
                                 const gp_Pnt& thePnt3,
-                                const SelectMgr_Vec3& theAxis) const;
+                                const gp_XYZ& theAxis) const;
 
 protected:
 
-  SelectMgr_Vec3 myPlanes[N + 2];        //!< Plane equations
-  SelectMgr_Vec3 myVertices[N * 2];      //!< Vertices coordinates
+  gp_Vec myPlanes[N + 2];        //!< Plane equations
+  gp_Pnt myVertices[N * 2];      //!< Vertices coordinates
 
   Standard_Real myMaxVertsProjections[N + 2];      //!< Cached projections of vertices onto frustum plane directions
   Standard_Real myMinVertsProjections[N + 2];      //!< Cached projections of vertices onto frustum plane directions
   Standard_Real myMaxOrthoVertsProjections[3];     //!< Cached projections of vertices onto directions of ortho unit vectors
   Standard_Real myMinOrthoVertsProjections[3];     //!< Cached projections of vertices onto directions of ortho unit vectors
 
-  SelectMgr_Vec3 myEdgeDirs[6];                    //!< Cached edge directions
+  gp_Vec myEdgeDirs[6];                    //!< Cached edge directions
 };
 
 #include <SelectMgr_Frustum.lxx>
index b2455229fbb35c370027e2efba0e5812fc9094a5..2d5af3f56e86a87f2854d591b1948148094c23f0 100644 (file)
@@ -17,9 +17,6 @@
 #include <Poly_Array1OfTriangle.hxx>
 #include <Standard_Assert.hxx>
 
-#define DOT(A, B) (A.x() * B.x() + A.y() * B.y() + A.z() * B.z())
-#define DOTp(A, B) (A.x() * B.X() + A.y() * B.Y() + A.z() * B.Z())
-
 // =======================================================================
 // function : isSeparated
 // purpose  : Checks if AABB and frustum are separated along the given axis.
 template <int N>
 Standard_Boolean SelectMgr_Frustum<N>::isSeparated (const SelectMgr_Vec3& theBoxMin,
                                                     const SelectMgr_Vec3& theBoxMax,
-                                                    const SelectMgr_Vec3& theDirect,
+                                                    const gp_XYZ&         theDirect,
                                                     Standard_Boolean*     theInside) const
 {
   const Standard_Real aMinB =
-    theDirect.x() * (theDirect.x() < 0.0 ? theBoxMax.x() : theBoxMin.x()) +
-    theDirect.y() * (theDirect.y() < 0.0 ? theBoxMax.y() : theBoxMin.y()) +
-    theDirect.z() * (theDirect.z() < 0.0 ? theBoxMax.z() : theBoxMin.z());
+    theDirect.X() * (theDirect.X() < 0.0 ? theBoxMax.x() : theBoxMin.x()) +
+    theDirect.Y() * (theDirect.Y() < 0.0 ? theBoxMax.y() : theBoxMin.y()) +
+    theDirect.Z() * (theDirect.Z() < 0.0 ? theBoxMax.z() : theBoxMin.z());
 
   const Standard_Real aMaxB =
-    theDirect.x() * (theDirect.x() < 0.0 ? theBoxMin.x() : theBoxMax.x()) +
-    theDirect.y() * (theDirect.y() < 0.0 ? theBoxMin.y() : theBoxMax.y()) +
-    theDirect.z() * (theDirect.z() < 0.0 ? theBoxMin.z() : theBoxMax.z());
+    theDirect.X() * (theDirect.X() < 0.0 ? theBoxMin.x() : theBoxMax.x()) +
+    theDirect.Y() * (theDirect.Y() < 0.0 ? theBoxMin.y() : theBoxMax.y()) +
+    theDirect.Z() * (theDirect.Z() < 0.0 ? theBoxMin.z() : theBoxMax.z());
 
   Standard_ASSERT_RAISE (aMaxB >= aMinB, "Error! Failed to project box");
 
@@ -48,7 +45,7 @@ Standard_Boolean SelectMgr_Frustum<N>::isSeparated (const SelectMgr_Vec3& theBox
 
   for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx)
   {
-    const Standard_Real aProj = DOT (myVertices[aVertIdx], theDirect);
+    const Standard_Real aProj = myVertices[aVertIdx].XYZ().Dot (theDirect);
 
     aMinF = Min (aMinF, aProj);
     aMaxF = Max (aMaxF, aProj);
@@ -83,7 +80,7 @@ template <int N>
 Standard_Boolean SelectMgr_Frustum<N>::isSeparated (const gp_Pnt& thePnt1,
                                                     const gp_Pnt& thePnt2,
                                                     const gp_Pnt& thePnt3,
-                                                    const SelectMgr_Vec3& theAxis) const
+                                                    const gp_XYZ& theAxis) const
 {
   // frustum projection
   Standard_Real aMinF = RealLast();
@@ -95,21 +92,21 @@ Standard_Boolean SelectMgr_Frustum<N>::isSeparated (const gp_Pnt& thePnt1,
 
   Standard_Real aTriangleProj;
 
-  aTriangleProj = DOTp (theAxis, thePnt1);
+  aTriangleProj = theAxis.Dot (thePnt1.XYZ());
   aMinTr = Min (aMinTr, aTriangleProj);
   aMaxTr = Max (aMaxTr, aTriangleProj);
 
-  aTriangleProj = DOTp (theAxis, thePnt2);
+  aTriangleProj = theAxis.Dot (thePnt2.XYZ());
   aMinTr = Min (aMinTr, aTriangleProj);
   aMaxTr = Max (aMaxTr, aTriangleProj);
 
-  aTriangleProj = DOTp (theAxis, thePnt3);
+  aTriangleProj = theAxis.Dot (thePnt3.XYZ());
   aMinTr = Min (aMinTr, aTriangleProj);
   aMaxTr = Max (aMaxTr, aTriangleProj);
 
   for (Standard_Integer aVertIter = 0; aVertIter < N * 2; ++aVertIter)
   {
-    const Standard_Real aProj = DOT (myVertices[aVertIter], theAxis);
+    const Standard_Real aProj = myVertices[aVertIter].XYZ().Dot (theAxis);
 
     aMinF = Min (aMinF, aProj);
     aMaxF = Max (aMaxF, aProj);
@@ -152,17 +149,17 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const SelectMgr_Vec3& theMinP
 
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N + 1; aPlaneIdx += anIncFactor)
   {
-    SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
+    const gp_XYZ& aPlane = myPlanes[aPlaneIdx].XYZ();
 
     const Standard_Real aBoxProjMin =
-      aPlane.x() * (aPlane.x() < 0.f ? theMaxPnt.x() : theMinPnt.x()) +
-      aPlane.y() * (aPlane.y() < 0.f ? theMaxPnt.y() : theMinPnt.y()) +
-      aPlane.z() * (aPlane.z() < 0.f ? theMaxPnt.z() : theMinPnt.z());
+      aPlane.X() * (aPlane.X() < 0.f ? theMaxPnt.x() : theMinPnt.x()) +
+      aPlane.Y() * (aPlane.Y() < 0.f ? theMaxPnt.y() : theMinPnt.y()) +
+      aPlane.Z() * (aPlane.Z() < 0.f ? theMaxPnt.z() : theMinPnt.z());
 
     const Standard_Real aBoxProjMax =
-      aPlane.x() * (aPlane.x() < 0.f ? theMinPnt.x() : theMaxPnt.x()) +
-      aPlane.y() * (aPlane.y() < 0.f ? theMinPnt.y() : theMaxPnt.y()) +
-      aPlane.z() * (aPlane.z() < 0.f ? theMinPnt.z() : theMaxPnt.z());
+      aPlane.X() * (aPlane.X() < 0.f ? theMinPnt.x() : theMaxPnt.x()) +
+      aPlane.Y() * (aPlane.Y() < 0.f ? theMinPnt.y() : theMaxPnt.y()) +
+      aPlane.Z() * (aPlane.Z() < 0.f ? theMinPnt.z() : theMaxPnt.z());
 
     Standard_ASSERT_RAISE (aBoxProjMax >= aBoxProjMin, "Error! Failed to project box");
 
@@ -180,13 +177,16 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const SelectMgr_Vec3& theMinP
 
   for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
   {
-    SelectMgr_Vec3 anEdge1 (aDim == 0, aDim == 1, aDim == 2);
-
+    // the following code performs a speedup of cross-product
+    // of vector with 1.0 at the position aDim and myEdgeDirs[aVolDir]
+    const Standard_Integer aNext = (aDim + 1) % 3;
+    const Standard_Integer aNextNext = (aDim + 2) % 3;
     for (Standard_Integer aVolDir = 0, aDirectionsNb = myIsOrthographic ? 4 : 6; aVolDir < aDirectionsNb; ++aVolDir)
     {
-      SelectMgr_Vec3 aDirection (anEdge1.y() * myEdgeDirs[aVolDir].z() - anEdge1.z() * myEdgeDirs[aVolDir].y(),
-                                 anEdge1.z() * myEdgeDirs[aVolDir].x() - anEdge1.x() * myEdgeDirs[aVolDir].z(),
-                                 anEdge1.x() * myEdgeDirs[aVolDir].y() - anEdge1.y() * myEdgeDirs[aVolDir].x());
+      gp_XYZ aDirection (DBL_MAX, DBL_MAX, DBL_MAX);
+      aDirection.Ptr()[aDim]      = 0;
+      aDirection.Ptr()[aNext]     = -myEdgeDirs[aVolDir].XYZ().Ptr()[aNextNext];
+      aDirection.Ptr()[aNextNext] = myEdgeDirs[aVolDir].XYZ().Ptr()[aNext];
 
       if (isSeparated (theMinPnt, theMaxPnt, aDirection, theInside))
       {
@@ -209,11 +209,7 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& thePnt)
 
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N + 1; aPlaneIdx += anIncFactor)
   {
-    const Select3D_Vec3& aPlane = myPlanes[aPlaneIdx];
-
-    const Standard_Real aPointProj = aPlane.x() * thePnt.X() +
-                                     aPlane.y() * thePnt.Y() +
-                                     aPlane.z() * thePnt.Z();
+    const Standard_Real aPointProj = myPlanes[aPlaneIdx].XYZ().Dot (thePnt.XYZ());
 
     if (aPointProj > myMaxVertsProjections[aPlaneIdx]
      || aPointProj < myMinVertsProjections[aPlaneIdx])
@@ -233,10 +229,8 @@ template <int N>
 Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& theStartPnt,
                                                    const gp_Pnt& theEndPnt)
 {
-  const SelectMgr_Vec3& aDir = SelectMgr_Vec3 (theEndPnt.X() - theStartPnt.X(),
-                                               theEndPnt.Y() - theStartPnt.Y(),
-                                               theEndPnt.Z() - theStartPnt.Z());
-  if (std::sqrt (aDir.x() * aDir.x() + aDir.y() * aDir.y() + aDir.z () * aDir.z()) < Precision::Confusion())
+  const gp_XYZ& aDir = theEndPnt.XYZ() - theStartPnt.XYZ();
+  if (aDir.Modulus() < Precision::Confusion())
     return Standard_True;
 
   const Standard_Integer anIncFactor = (myIsOrthographic && N == 4) ? 2 : 1;
@@ -244,10 +238,9 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& theStartPnt,
   {
     Standard_Real aMinSegm = RealLast(), aMaxSegm = RealFirst();
     Standard_Real aMinF    = RealLast(), aMaxF    = RealFirst();
-    SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
 
-    Standard_Real aProj1 = DOTp (aPlane, theStartPnt);
-    Standard_Real aProj2 = DOTp (aPlane, theEndPnt);
+    Standard_Real aProj1 = myPlanes[aPlaneIdx].XYZ().Dot (theStartPnt.XYZ());
+    Standard_Real aProj2 = myPlanes[aPlaneIdx].XYZ().Dot (theEndPnt.XYZ());
     aMinSegm = Min (aProj1, aProj2);
     aMaxSegm = Max (aProj1, aProj2);
 
@@ -265,12 +258,12 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& theStartPnt,
   Standard_Real aMin2 = DBL_MAX, aMax2 = -DBL_MAX;
   for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx)
   {
-    Standard_Real aProjection = DOT (aDir, myVertices[aVertIdx]);
+    Standard_Real aProjection = aDir.Dot (myVertices[aVertIdx].XYZ());
     aMax2 = Max (aMax2, aProjection);
     aMin2 = Min (aMin2, aProjection);
   }
-  Standard_Real aProj1 = DOTp (aDir, theStartPnt);
-  Standard_Real aProj2 = DOTp (aDir, theEndPnt);
+  Standard_Real aProj1 = aDir.Dot (theStartPnt.XYZ());
+  Standard_Real aProj2 = aDir.Dot (theEndPnt.XYZ());
   aMin1 = Min (aProj1, aProj2);
   aMax1 = Max (aProj1, aProj2);
   if (aMin1 > aMax2
@@ -285,18 +278,16 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& theStartPnt,
     Standard_Real aMinSegm = DBL_MAX, aMaxSegm = -DBL_MAX;
     Standard_Real aMinF    = DBL_MAX, aMaxF    = -DBL_MAX;
 
-    SelectMgr_Vec3 aTestDir = SelectMgr_Vec3 (aDir.y() * myEdgeDirs[aEdgeDirIdx].z() - aDir.z() * myEdgeDirs[aEdgeDirIdx].y(),
-      aDir.z() * myEdgeDirs[aEdgeDirIdx].x() - aDir.x() * myEdgeDirs[aEdgeDirIdx].z(),
-      aDir.x() * myEdgeDirs[aEdgeDirIdx].y() - aDir.y() * myEdgeDirs[aEdgeDirIdx].x());
+    const gp_XYZ aTestDir = aDir.Crossed (myEdgeDirs[aEdgeDirIdx].XYZ());
 
-    Standard_Real Proj1 = DOTp (aTestDir, theStartPnt);
-    Standard_Real Proj2 = DOTp (aTestDir, theEndPnt);
+    Standard_Real Proj1 = aTestDir.Dot (theStartPnt.XYZ());
+    Standard_Real Proj2 = aTestDir.Dot (theEndPnt.XYZ());
     aMinSegm = Min (Proj1, Proj2);
     aMaxSegm = Max (Proj1, Proj2);
 
     for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx)
     {
-      Standard_Real aProjection = DOT (aTestDir, myVertices[aVertIdx]);
+      Standard_Real aProjection = aTestDir.Dot (myVertices[aVertIdx].XYZ());
       aMaxF = Max (aMaxF, aProjection);
       aMinF = Min (aMinF, aProjection);
     }
@@ -318,26 +309,25 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& theStartPnt,
 // =======================================================================
 template <int N>
 Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
-                                                   SelectMgr_Vec3& theNormal)
+                                                   gp_Vec& theNormal)
 {
   Standard_Integer aStartIdx = theArrayOfPnts->Lower();
   Standard_Integer anEndIdx = theArrayOfPnts->Upper();
 
-  const gp_Pnt& aPnt1 = theArrayOfPnts->Value (aStartIdx);
-  const gp_Pnt& aPnt2 = theArrayOfPnts->Value (aStartIdx + 1);
-  const gp_Pnt& aPnt3 = theArrayOfPnts->Value (aStartIdx + 2);
-  const gp_XYZ aVec1 = aPnt1.XYZ() - aPnt2.XYZ();
-  const gp_XYZ aVec2 = aPnt3.XYZ() - aPnt2.XYZ();
-  theNormal = SelectMgr_Vec3 (aVec2.Y() * aVec1.Z() - aVec2.Z() * aVec1.Y(),
-                              aVec2.Z() * aVec1.X() - aVec2.X() * aVec1.Z(),
-                              aVec2.X() * aVec1.Y() - aVec2.Y() * aVec1.X());
-  Standard_Real aPolygProjection = DOTp (theNormal, aPnt1);
+  const gp_XYZ& aPnt1 = theArrayOfPnts->Value (aStartIdx).XYZ();
+  const gp_XYZ& aPnt2 = theArrayOfPnts->Value (aStartIdx + 1).XYZ();
+  const gp_XYZ& aPnt3 = theArrayOfPnts->Value (aStartIdx + 2).XYZ();
+  const gp_XYZ aVec1 = aPnt1 - aPnt2;
+  const gp_XYZ aVec2 = aPnt3 - aPnt2;
+  theNormal = aVec2.Crossed (aVec1);
+  const gp_XYZ& aNormal = theNormal.XYZ();
+  Standard_Real aPolygProjection = aNormal.Dot (aPnt1);
 
   Standard_Real aMax = RealFirst();
   Standard_Real aMin = RealLast();
   for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx)
   {
-    Standard_Real aProjection = DOT (theNormal, myVertices[aVertIdx]);
+    Standard_Real aProjection = aNormal.Dot (myVertices[aVertIdx].XYZ());
     aMax = Max (aMax, aProjection);
     aMin = Min (aMin, aProjection);
   }
@@ -347,17 +337,17 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const Handle(TColgp_HArray1Of
     return Standard_False;
   }
 
-  Standard_Integer aPlanesNb = N == 4 ? N + 2 : N + 1;
-  for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < aPlanesNb; ++aPlaneIdx)
+  const Standard_Integer anIncFactor = (myIsOrthographic && N == 4) ? 2 : 1;
+  for (Standard_Integer aPlaneIdx = 0; aPlaneIdx <  N + 1; aPlaneIdx += anIncFactor)
   {
     Standard_Real aMaxF = RealFirst();
     Standard_Real aMinF = RealLast();
     Standard_Real aMaxPolyg = RealFirst();
     Standard_Real aMinPolyg = RealLast();
-    SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
+    const gp_XYZ& aPlane = myPlanes[aPlaneIdx].XYZ();
     for (Standard_Integer aPntIter = aStartIdx; aPntIter <= anEndIdx; ++aPntIter)
     {
-      Standard_Real aProjection = DOTp (aPlane, theArrayOfPnts->Value (aPntIter));
+      Standard_Real aProjection = aPlane.Dot (theArrayOfPnts->Value (aPntIter).XYZ());
       aMaxPolyg = Max (aMaxPolyg, aProjection);
       aMinPolyg = Min (aMinPolyg, aProjection);
     }
@@ -371,30 +361,28 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const Handle(TColgp_HArray1Of
   }
 
   Standard_Integer aDirectionsNb = myIsOrthographic ? 4 : 6;
-  for (Standard_Integer aPntsIter = aStartIdx; aPntsIter <= anEndIdx; ++aPntsIter)
+  for (Standard_Integer aPntsIter = 0, aLastIdx = anEndIdx - aStartIdx, aLen = theArrayOfPnts->Length(); aPntsIter <= aLastIdx; ++aPntsIter)
   {
-    const gp_XYZ aSegmDir = aPntsIter == anEndIdx ? theArrayOfPnts->Value (aStartIdx).XYZ() - theArrayOfPnts->Value (anEndIdx).XYZ()
-                                             : theArrayOfPnts->Value (aPntsIter + 1).XYZ() - theArrayOfPnts->Value (aPntsIter).XYZ();
+    const gp_XYZ aSegmDir = theArrayOfPnts->Value ((aPntsIter + 1) % aLen + aStartIdx).XYZ()
+      - theArrayOfPnts->Value (aPntsIter + aStartIdx).XYZ();
     for (Standard_Integer aVolDir = 0; aVolDir < aDirectionsNb; ++aVolDir)
     {
       Standard_Real aMaxPolyg = RealFirst();
       Standard_Real aMinPolyg = RealLast();
       Standard_Real aMaxF = RealFirst();
       Standard_Real aMinF = RealLast();
-      SelectMgr_Vec3 aTestDir = SelectMgr_Vec3 (aSegmDir.Y() * myEdgeDirs[aVolDir].z() - aSegmDir.Z() * myEdgeDirs[aVolDir].y(),
-                                                aSegmDir.Z() * myEdgeDirs[aVolDir].x() - aSegmDir.X() * myEdgeDirs[aVolDir].z(),
-                                                aSegmDir.X() * myEdgeDirs[aVolDir].y() - aSegmDir.Y() * myEdgeDirs[aVolDir].x());
+      const gp_XYZ aTestDir = aSegmDir.Crossed (myEdgeDirs[aVolDir].XYZ());
 
       for (Standard_Integer aPntIter = aStartIdx; aPntIter <= anEndIdx; ++aPntIter)
       {
-        Standard_Real aProjection = DOTp (aTestDir, theArrayOfPnts->Value (aPntIter));
+        Standard_Real aProjection = aTestDir.Dot (theArrayOfPnts->Value (aPntIter).XYZ());
         aMaxPolyg = Max (aMaxPolyg, aProjection);
         aMinPolyg = Min (aMinPolyg, aProjection);
       }
 
       for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx)
       {
-        Standard_Real aProjection = DOT (aTestDir, myVertices[aVertIdx]);
+        Standard_Real aProjection = aTestDir.Dot (myVertices[aVertIdx].XYZ());
         aMaxF = Max (aMaxF, aProjection);
         aMinF = Min (aMinF, aProjection);
       }
@@ -418,31 +406,27 @@ template <int N>
 Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& thePnt1,
                                                    const gp_Pnt& thePnt2,
                                                    const gp_Pnt& thePnt3,
-                                                   SelectMgr_Vec3& theNormal)
+                                                   gp_Vec& theNormal)
 {
-
-  SelectMgr_Vec3 aPnt1 (thePnt1.X(), thePnt1.Y(), thePnt1.Z());
-  SelectMgr_Vec3 aPnt2 (thePnt2.X(), thePnt2.Y(), thePnt2.Z());
-  SelectMgr_Vec3 aPnt3 (thePnt3.X(), thePnt3.Y(), thePnt3.Z());
-  SelectMgr_Vec3 aTrEdges[3] = { aPnt2 - aPnt1,
-                                 aPnt3 - aPnt2,
-                                 aPnt1 - aPnt3 };
+  const gp_XYZ aTrEdges[3] = { thePnt2.XYZ() - thePnt1.XYZ(),
+                               thePnt3.XYZ() - thePnt2.XYZ(),
+                               thePnt1.XYZ() - thePnt3.XYZ() };
 
   const Standard_Integer anIncFactor = (myIsOrthographic && N == 4) ? 2 : 1;
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N + 1; aPlaneIdx += anIncFactor)
   {
-    SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
+    const gp_XYZ& aPlane = myPlanes[aPlaneIdx].XYZ();
     Standard_Real aTriangleProj;
 
-    aTriangleProj = DOT (aPlane, aPnt1);
+    aTriangleProj = aPlane.Dot (thePnt1.XYZ());
     Standard_Real aTriangleProjMin = aTriangleProj;
     Standard_Real aTriangleProjMax = aTriangleProj;
 
-    aTriangleProj = DOT (aPlane, aPnt2);
+    aTriangleProj = aPlane.Dot (thePnt2.XYZ());
     aTriangleProjMin = Min (aTriangleProjMin, aTriangleProj);
     aTriangleProjMax = Max (aTriangleProjMax, aTriangleProj);
 
-    aTriangleProj = DOT (aPlane, aPnt3);
+    aTriangleProj = aPlane.Dot (thePnt3.XYZ());
     aTriangleProjMin = Min (aTriangleProjMin, aTriangleProj);
     aTriangleProjMax = Max (aTriangleProjMax, aTriangleProj);
 
@@ -455,10 +439,8 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& thePnt1,
     }
   }
 
-  theNormal = SelectMgr_Vec3 (aTrEdges[2].y() * aTrEdges[0].z() - aTrEdges[2].z() * aTrEdges[0].y(),
-                              aTrEdges[2].z() * aTrEdges[0].x() - aTrEdges[2].x() * aTrEdges[0].z(),
-                              aTrEdges[2].x() * aTrEdges[0].y() - aTrEdges[2].y() * aTrEdges[0].x());
-  if (isSeparated (thePnt1, thePnt2, thePnt3, theNormal))
+  theNormal = aTrEdges[2].Crossed (aTrEdges[0]);
+  if (isSeparated (thePnt1, thePnt2, thePnt3, theNormal.XYZ()))
   {
     return Standard_False;
   }
@@ -468,12 +450,7 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& thePnt1,
   {
     for (Standard_Integer aVolDir = 0; aVolDir < aDirectionsNb; ++aVolDir)
     {
-      SelectMgr_Vec3 anEdge1 = myEdgeDirs[aVolDir];
-      SelectMgr_Vec3 anEdge2 = aTrEdges[aTriangleEdgeIdx];
-      SelectMgr_Vec3 aTestDirection = SelectMgr_Vec3 (
-        anEdge1.y() * anEdge2.z() - anEdge1.z() * anEdge2.y(),
-        anEdge1.z() * anEdge2.x() - anEdge1.x() * anEdge2.z(),
-        anEdge1.x() * anEdge2.y() - anEdge1.y() * anEdge2.x());
+      const gp_XYZ& aTestDirection =  myEdgeDirs[aVolDir].XYZ().Crossed (aTrEdges[aTriangleEdgeIdx]);
 
       if (isSeparated (thePnt1, thePnt2, thePnt3, aTestDirection))
       {
@@ -484,6 +461,3 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& thePnt1,
 
   return Standard_True;
 }
-
-#undef DOT
-#undef DOTp
index 91be420ac2851a616a1de2329276fbcb8b413b17..80a11e55eae33fda00ae985d1f93f531272d2cd3 100644 (file)
@@ -127,7 +127,7 @@ static NCollection_Vec4<Standard_Real> safePointCast (const gp_Pnt& thePnt)
 // function : unProject
 // purpose  : Unprojects point from NDC coords to 3d world space
 //=======================================================================
-SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const
+gp_Pnt SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const
 {
   Graphic3d_Mat4d aInvView;
   Graphic3d_Mat4d aInvProj;
@@ -135,7 +135,7 @@ SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const
   // this case should never happen
   if (!myOrientation.Inverted (aInvView) || !myProjection.Inverted (aInvProj))
   {
-    return SelectMgr_Vec3 (0.0, 0.0, 0.0);
+    return gp_Pnt (0.0, 0.0, 0.0);
   }
 
   // use compatible type of point
@@ -146,7 +146,7 @@ SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const
 
   const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
 
-  return SelectMgr_Vec3 (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
+  return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
 }
 
 // =======================================================================
@@ -155,9 +155,9 @@ SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const
 //            theZ = 0 - near plane,
 //            theZ = 1 - far plane
 // =======================================================================
-SelectMgr_Vec3 SelectMgr_FrustumBuilder::ProjectPntOnViewPlane (const Standard_Real& theX,
-                                                                const Standard_Real& theY,
-                                                                const Standard_Real& theZ) const
+gp_Pnt SelectMgr_FrustumBuilder::ProjectPntOnViewPlane (const Standard_Real& theX,
+                                                        const Standard_Real& theY,
+                                                        const Standard_Real& theZ) const
 {
   Standard_Real aX, anY, aZ;
 
index 8480454cea11fefa62699acebef8359ca66e1648..e7ee1d8f5b3fa75049017032779c69a00bf14a13 100644 (file)
@@ -57,16 +57,16 @@ public:
   //! Projects 2d screen point onto view frustum plane:
   //! theZ = 0 - near plane,
   //! theZ = 1 - far plane
-  SelectMgr_Vec3 ProjectPntOnViewPlane (const Standard_Real& theX,
-                                        const Standard_Real& theY,
-                                        const Standard_Real& theZ) const;
+  gp_Pnt ProjectPntOnViewPlane (const Standard_Real& theX,
+                                const Standard_Real& theY,
+                                const Standard_Real& theZ) const;
 
   DEFINE_STANDARD_RTTI(SelectMgr_FrustumBuilder)
 
 private:
 
   //! Unprojects point from NDC coords to 3d world space
-  SelectMgr_Vec3 unProject (const gp_Pnt& thePnt) const;
+  gp_Pnt unProject (const gp_Pnt& thePnt) const;
 
 private:
 
index bf658c96899dfd07fde3e5b748e6c5c0ae2ad793..27b2d08978f3cb1d36e24c58858507978feee91a 100644 (file)
 
 #include <SelectMgr_RectangularFrustum.hxx>
 
-#define DOT(A, B) (A.x() * B.x() + A.y() * B.y() + A.z() * B.z())
-#define DOTp(A, B) (A.x() * B.X() + A.y() * B.Y() + A.z() * B.Z())
-#define DISTANCE(A, B) (std::sqrt ((A.x() - B.x()) * (A.x() - B.x()) + (A.y() - B.y()) * (A.y() - B.y()) + (A.z() - B.z()) * (A.z() - B.z())))
-#define DISTANCEp(A, B) (std::sqrt ((A.x() - B.X()) * (A.x() - B.X()) + (A.y() - B.Y()) * (A.y() - B.Y()) + (A.z() - B.Z()) * (A.z() - B.Z())))
-
 // =======================================================================
 // function : segmentSegmentDistance
 // purpose  :
@@ -31,18 +26,15 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP
                                                            const gp_Pnt& theSegPnt2,
                                                            Standard_Real& theDepth)
 {
-  SelectMgr_Vec3 anU = SelectMgr_Vec3 (theSegPnt2.X() - theSegPnt1.X(),
-                                       theSegPnt2.Y() - theSegPnt1.Y(),
-                                       theSegPnt2.Z() - theSegPnt1.Z());
-  SelectMgr_Vec3 aV = myViewRayDir;
-  SelectMgr_Vec3 aW = SelectMgr_Vec3 (theSegPnt1.X() - myNearPickedPnt.x(),
-                                      theSegPnt1.Y() - myNearPickedPnt.y(),
-                                      theSegPnt1.Z() - myNearPickedPnt.z());
-  Standard_Real anA = DOT (anU, anU);
-  Standard_Real aB = DOT (anU, aV);
-  Standard_Real aC = DOT (aV, aV);
-  Standard_Real aD = DOT (anU, aW);
-  Standard_Real anE = DOT (aV, aW);
+  gp_XYZ anU = theSegPnt2.XYZ() - theSegPnt1.XYZ();
+  gp_XYZ aV = myViewRayDir.XYZ();
+  gp_XYZ aW = theSegPnt1.XYZ() - myNearPickedPnt.XYZ();
+
+  Standard_Real anA = anU.Dot (anU);
+  Standard_Real aB = anU.Dot (aV);
+  Standard_Real aC = aV.Dot (aV);
+  Standard_Real aD = anU.Dot (aW);
+  Standard_Real anE = aV.Dot (aW);
   Standard_Real aCoef = anA * aC - aB * aB;
   Standard_Real aSc, aSn, aSd = aCoef;
   Standard_Real aTc, aTn, aTd = aCoef;
@@ -99,24 +91,22 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP
   aSc = (Abs (aSn) < Precision::Confusion() ? 0.0 : aSn / aSd);
   aTc = (Abs (aTn) < Precision::Confusion() ? 0.0 : aTn / aTd);
 
-  SelectMgr_Vec3 aClosestPnt = myNearPickedPnt + myViewRayDir * aTc;
-  theDepth = DISTANCE (myNearPickedPnt, aClosestPnt);
+  gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTc;
+  theDepth = myNearPickedPnt.Distance (aClosestPnt);
 }
 
 // =======================================================================
 // function : segmentPlaneIntersection
 // purpose  :
 // =======================================================================
-void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const SelectMgr_Vec3& thePlane,
+void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const gp_Vec& thePlane,
                                                              const gp_Pnt& thePntOnPlane,
                                                              Standard_Real& theDepth)
 {
-  SelectMgr_Vec3 anU = myViewRayDir;
-  SelectMgr_Vec3 aW = SelectMgr_Vec3 (myNearPickedPnt.x() - thePntOnPlane.X(),
-                                      myNearPickedPnt.y() - thePntOnPlane.Y(),
-                                      myNearPickedPnt.z() - thePntOnPlane.Z());
-  Standard_Real aD = DOT (thePlane, anU);
-  Standard_Real aN = -DOT (thePlane, aW);
+  gp_XYZ anU = myViewRayDir.XYZ();
+  gp_XYZ aW = myNearPickedPnt.XYZ() - thePntOnPlane.XYZ();
+  Standard_Real aD = thePlane.Dot (anU);
+  Standard_Real aN = -thePlane.Dot (aW);
 
   if (Abs (aD) < Precision::Confusion())
   {
@@ -139,135 +129,173 @@ void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const SelectMgr_Vec
     return;
   }
 
-  SelectMgr_Vec3 aClosestPnt = myNearPickedPnt + anU * aParam;
-  theDepth = DISTANCE (myNearPickedPnt, aClosestPnt);
+  gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + anU * aParam;
+  theDepth = myNearPickedPnt.Distance (aClosestPnt);
 }
 
 namespace
 {
+  // =======================================================================
+  // function : computeFrustum
+  // purpose  : Computes base frustum data: its vertices and edge directions
+  // =======================================================================
+  void computeFrustum (const gp_Pnt2d theMinPnt, const gp_Pnt2d& theMaxPnt,
+                       const Handle(SelectMgr_FrustumBuilder)& theBuilder,
+                       gp_Pnt* theVertices, gp_Vec* theEdges)
+  {
+    // LeftTopNear
+    theVertices[0] = theBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
+                                                        theMaxPnt.Y(),
+                                                        0.0);
+    // LeftTopFar
+    theVertices[1] = theBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
+                                                        theMaxPnt.Y(),
+                                                        1.0);
+    // LeftBottomNear
+    theVertices[2] = theBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
+                                                        theMinPnt.Y(),
+                                                        0.0);
+    // LeftBottomFar
+    theVertices[3] = theBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
+                                                        theMinPnt.Y(),
+                                                        1.0);
+    // RightTopNear
+    theVertices[4] = theBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
+                                                        theMaxPnt.Y(),
+                                                        0.0);
+    // RightTopFar
+    theVertices[5] = theBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
+                                                        theMaxPnt.Y(),
+                                                        1.0);
+    // RightBottomNear
+    theVertices[6] = theBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
+                                                        theMinPnt.Y(),
+                                                        0.0);
+    // RightBottomFar
+    theVertices[7] = theBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
+                                                        theMinPnt.Y(),
+                                                        1.0);
+
+    // Horizontal
+    theEdges[0] = theVertices[4].XYZ() - theVertices[0].XYZ();
+    // Vertical
+    theEdges[1] = theVertices[2].XYZ() - theVertices[0].XYZ();
+    // LeftLower
+    theEdges[2] = theVertices[2].XYZ() - theVertices[3].XYZ();
+    // RightLower
+    theEdges[3] = theVertices[6].XYZ() - theVertices[7].XYZ();
+    // LeftUpper
+    theEdges[4] = theVertices[0].XYZ() - theVertices[1].XYZ();
+    // RightUpper
+    theEdges[5] = theVertices[4].XYZ() - theVertices[5].XYZ();
+  }
+
   // =======================================================================
   // function : computeNormals
   // purpose  : Computes normals to frustum faces
   // =======================================================================
-  void computeNormals (const SelectMgr_Vec3* theVertices, SelectMgr_Vec3* theNormals)
+  void computeNormals (const gp_Vec* theEdges, gp_Vec* theNormals)
   {
     // Top
-    theNormals[0] = SelectMgr_Vec3::Cross (theVertices[1] - theVertices[0],
-                                           theVertices[4] - theVertices[0]);
+    theNormals[0] = theEdges[0].Crossed (theEdges[4]);
     // Bottom
-    theNormals[1] = SelectMgr_Vec3::Cross (theVertices[3] - theVertices[2],
-                                           theVertices[6] - theVertices[2]);
+    theNormals[1] = theEdges[2].Crossed (theEdges[3]);
     // Left
-    theNormals[2] = SelectMgr_Vec3::Cross (theVertices[1] - theVertices[0],
-                                           theVertices[2] - theVertices[0]);
+    theNormals[2] = theEdges[4].Crossed (theEdges[1]);
     // Right
-    theNormals[3] = SelectMgr_Vec3::Cross (theVertices[5] - theVertices[4],
-                                           theVertices[6] - theVertices[4]);
+    theNormals[3] = theEdges[5].Crossed (theEdges[3]);
     // Near
-    theNormals[4] = SelectMgr_Vec3::Cross (theVertices[6] - theVertices[4],
-                                           theVertices[0] - theVertices[4]);
+    theNormals[4] = theEdges[0].Crossed (theEdges[1]);
     // Far
-    theNormals[5] = SelectMgr_Vec3::Cross (theVertices[7] - theVertices[5],
-                                           theVertices[1] - theVertices[5]);
+    theNormals[5] = -theNormals[4];
   }
 }
 
 // =======================================================================
-// function : Build
-// purpose  : Build volume according to the point and given pixel
-//            tolerance
+// function : cacheVertexProjections
+// purpose  : Caches projection of frustum's vertices onto its plane directions
+//            and {i, j, k}
 // =======================================================================
-void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint)
+void SelectMgr_RectangularFrustum::cacheVertexProjections (SelectMgr_RectangularFrustum* theFrustum)
 {
-  myNearPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 0.0);
-  myFarPickedPnt  = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 1.0);
-  myViewRayDir = myFarPickedPnt - myNearPickedPnt;
-  myMousePos = thePoint;
-
-  // LeftTopNear
-  myVertices[0] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0,
-                                                    thePoint.Y() + myPixelTolerance / 2.0,
-                                                    0.0);
-  // LeftTopFar
-  myVertices[1] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0,
-                                                    thePoint.Y() + myPixelTolerance / 2.0,
-                                                    1.0);
-  // LeftBottomNear
-  myVertices[2] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0,
-                                                    thePoint.Y() - myPixelTolerance / 2.0,
-                                                    0.0);
-  // LeftBottomFar
-  myVertices[3] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0,
-                                                    thePoint.Y() - myPixelTolerance / 2.0,
-                                                    1.0);
-  // RightTopNear
-  myVertices[4] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0,
-                                                    thePoint.Y() + myPixelTolerance / 2.0,
-                                                    0.0);
-  // RightTopFar
-  myVertices[5] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0,
-                                                    thePoint.Y() + myPixelTolerance / 2.0,
-                                                    1.0);
-  // RightBottomNear
-  myVertices[6] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0,
-                                                    thePoint.Y() - myPixelTolerance / 2.0,
-                                                    0.0);
-  // RightBottomFar
-  myVertices[7] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0,
-                                                    thePoint.Y() - myPixelTolerance / 2.0,
-                                                    1.0);
-
-  // compute frustum normals
-  computeNormals (myVertices, myPlanes);
-
-  for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
+  if (theFrustum->myIsOrthographic)
   {
-    Standard_Real aMax = -DBL_MAX;
-    Standard_Real aMin =  DBL_MAX;
-    const SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
-    for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
+    // project vertices onto frustum normals
+    // Since orthographic view volume's faces are always a pairwise translation of
+    // one another, only 2 vertices that belong to opposite faces can be projected
+    // to simplify calculations.
+    Standard_Integer aVertIdxs[6] = { LeftTopNear, LeftBottomNear,       // opposite planes in height direction
+                                      LeftBottomNear, RightBottomNear,   // opposite planes in width direcion
+                                      LeftBottomFar, RightBottomNear };  // opposite planes in depth direction
+    for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; aPlaneIdx += 2)
     {
-      Standard_Real aProjection = DOT (aPlane, myVertices[aVertIdx]);
-      aMax = Max (aMax, aProjection);
-      aMin = Min (aMin, aProjection);
+      Standard_Real aProj1 = theFrustum->myPlanes[aPlaneIdx].XYZ().Dot (theFrustum->myVertices[aVertIdxs[aPlaneIdx]].XYZ());
+      Standard_Real aProj2 = theFrustum->myPlanes[aPlaneIdx].XYZ().Dot (theFrustum->myVertices[aVertIdxs[aPlaneIdx + 1]].XYZ());
+      theFrustum->myMinVertsProjections[aPlaneIdx] = Min (aProj1, aProj2);
+      theFrustum->myMaxVertsProjections[aPlaneIdx] = Max (aProj1, aProj2);
     }
-    myMaxVertsProjections[aPlaneIdx] = aMax;
-    myMinVertsProjections[aPlaneIdx] = aMin;
   }
-
-  SelectMgr_Vec3 aDimensions[3] =
+  else
   {
-    SelectMgr_Vec3 (1.0, 0.0, 0.0),
-    SelectMgr_Vec3 (0.0, 1.0, 0.0),
-    SelectMgr_Vec3 (0.0, 0.0, 1.0)
-  };
+    // project all vertices onto frustum normals
+    for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
+    {
+      Standard_Real aMax = -DBL_MAX;
+      Standard_Real aMin = DBL_MAX;
+      const gp_XYZ& aPlane = theFrustum->myPlanes[aPlaneIdx].XYZ();
+      for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
+      {
+        Standard_Real aProjection = aPlane.Dot (theFrustum->myVertices[aVertIdx].XYZ());
+        aMin = Min (aMin, aProjection);
+        aMax = Max (aMax, aProjection);
+      }
+      theFrustum->myMinVertsProjections[aPlaneIdx] = aMin;
+      theFrustum->myMaxVertsProjections[aPlaneIdx] = aMax;
+    }
+  }
 
+  // project vertices onto {i, j, k}
   for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
   {
     Standard_Real aMax = -DBL_MAX;
-    Standard_Real aMin =  DBL_MAX;
+    Standard_Real aMin = DBL_MAX;
     for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
     {
-      Standard_Real aProjection = DOT (aDimensions[aDim], myVertices[aVertIdx]);
-      aMax = Max (aProjection, aMax);
-      aMin = Min (aProjection, aMin);
+      const gp_XYZ& aVert = theFrustum->myVertices[aVertIdx].XYZ();
+      aMax = Max (aVert.Ptr()[aDim], aMax);
+      aMin = Min (aVert.Ptr()[aDim], aMin);
     }
-    myMaxOrthoVertsProjections[aDim] = aMax;
-    myMinOrthoVertsProjections[aDim] = aMin;
+    theFrustum->myMaxOrthoVertsProjections[aDim] = aMax;
+    theFrustum->myMinOrthoVertsProjections[aDim] = aMin;
   }
+}
+
+// =======================================================================
+// function : Build
+// purpose  : Build volume according to the point and given pixel
+//            tolerance
+// =======================================================================
+void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint)
+{
+  myNearPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 0.0);
+  myFarPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 1.0);
+  myViewRayDir = myFarPickedPnt.XYZ() - myNearPickedPnt.XYZ();
+  myMousePos = thePoint;
 
-  // Horizontal
-  myEdgeDirs[0] = myVertices[4] - myVertices[0];
-  // Vertical
-  myEdgeDirs[1] = myVertices[2] - myVertices[0];
-  // LeftLower
-  myEdgeDirs[2] = myVertices[2] - myVertices[3];
-  // RightLower
-  myEdgeDirs[3] = myVertices[6] - myVertices[7];
-  // LeftUpper
-  myEdgeDirs[4] = myVertices[0] - myVertices[1];
-  // RightUpper
-  myEdgeDirs[5] = myVertices[4] - myVertices[5];
+  gp_Pnt2d aMinPnt (thePoint.X() - myPixelTolerance * 0.5,
+                    thePoint.Y() - myPixelTolerance * 0.5);
+  gp_Pnt2d aMaxPnt (thePoint.X() + myPixelTolerance * 0.5,
+                    thePoint.Y() + myPixelTolerance * 0.5);
+
+  // calculate base frustum characteristics: vertices and edge directions
+  computeFrustum (aMinPnt, aMaxPnt, myBuilder, myVertices, myEdgeDirs);
+
+  // compute frustum normals
+  computeNormals (myEdgeDirs, myPlanes);
+
+  // compute vertices projections onto frustum normals and
+  // {i, j, k} vectors and store them to corresponding class fields
+  cacheVertexProjections (this);
 }
 
 // =======================================================================
@@ -283,278 +311,104 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt,
   myFarPickedPnt = myBuilder->ProjectPntOnViewPlane ((theMinPnt.X() + theMaxPnt.X()) * 0.5,
                                                      (theMinPnt.Y() + theMaxPnt.Y()) * 0.5,
                                                      1.0);
-  myViewRayDir = myFarPickedPnt - myNearPickedPnt;
-
-  // LeftTopNear
-  myVertices[0] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
-                                                    theMaxPnt.Y(),
-                                                    0.0);
-  // LeftTopFar
-  myVertices[1] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
-                                                    theMaxPnt.Y(),
-                                                    1.0);
-  // LeftBottomNear
-  myVertices[2] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
-                                                    theMinPnt.Y(),
-                                                    0.0);
-  // LeftBottomFar
-  myVertices[3] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
-                                                    theMinPnt.Y(),
-                                                    1.0);
-  // RightTopNear
-  myVertices[4] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
-                                                    theMaxPnt.Y(),
-                                                    0.0);
-  // RightTopFar
-  myVertices[5] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
-                                                    theMaxPnt.Y(),
-                                                    1.0);
-  // RightBottomNear
-  myVertices[6] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
-                                                    theMinPnt.Y(),
-                                                    0.0);
-  // RightBottomFar
-  myVertices[7] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
-                                                    theMinPnt.Y(),
-                                                    1.0);
+  myViewRayDir = myFarPickedPnt.XYZ() - myNearPickedPnt.XYZ();
 
-  // compute frustum normals
-  computeNormals (myVertices, myPlanes);
+  // calculate base frustum characteristics: vertices and edge directions
+  computeFrustum (theMinPnt, theMaxPnt, myBuilder, myVertices, myEdgeDirs);
 
-  for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
-  {
-    Standard_Real aMax = -DBL_MAX;
-    Standard_Real aMin =  DBL_MAX;
-    const SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
-    for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
-    {
-      Standard_Real aProjection = DOT (aPlane, myVertices[aVertIdx]);
-      aMax = Max (aMax, aProjection);
-      aMin = Min (aMin, aProjection);
-    }
-    myMaxVertsProjections[aPlaneIdx] = aMax;
-    myMinVertsProjections[aPlaneIdx] = aMin;
-  }
-
-  SelectMgr_Vec3 aDimensions[3] =
-  {
-    SelectMgr_Vec3 (1.0, 0.0, 0.0),
-    SelectMgr_Vec3 (0.0, 1.0, 0.0),
-    SelectMgr_Vec3 (0.0, 0.0, 1.0)
-  };
-
-  for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
-  {
-    Standard_Real aMax = -DBL_MAX;
-    Standard_Real aMin =  DBL_MAX;
-    for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
-    {
-      Standard_Real aProjection = DOT (aDimensions[aDim], myVertices[aVertIdx]);
-      aMax = Max (aMax, aProjection);
-      aMin = Min (aMin, aProjection);
-    }
-    myMaxOrthoVertsProjections[aDim] = aMax;
-    myMinOrthoVertsProjections[aDim] = aMin;
-  }
+  // compute frustum normals
+  computeNormals (myEdgeDirs, myPlanes);
 
-  // Horizontal
-  myEdgeDirs[0] = myVertices[4] - myVertices[0];
-  // Vertical
-  myEdgeDirs[1] = myVertices[2] - myVertices[0];
-  // LeftLower
-  myEdgeDirs[2] = myVertices[2] - myVertices[3];
-  // RightLower
-  myEdgeDirs[3] = myVertices[6] - myVertices[7];
-  // LeftUpper
-  myEdgeDirs[4] = myVertices[0] - myVertices[1];
-  // RightUpper
-  myEdgeDirs[5] = myVertices[4] - myVertices[5];
+  // compute vertices projections onto frustum normals and
+  // {i, j, k} vectors and store them to corresponding class fields
+  cacheVertexProjections (this);
 }
 
 // =======================================================================
-// function : Transform
-// purpose  : Returns a copy of the frustum transformed according to the matrix given
+// function : ScaleAndTransform
+// purpose  : IMPORTANT: Scaling makes sense only for frustum built on a single point!
+//            Note that this method does not perform any checks on type of the frustum.
+//            Returns a copy of the frustum resized according to the scale factor given
+//            and transforms it using the matrix given.
+//            There are no default parameters, but in case if:
+//                - transformation only is needed: @theScaleFactor must be initialized
+//                  as any negative value;
+//                - scale only is needed: @theTrsf must be set to gp_Identity.
 // =======================================================================
-NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_RectangularFrustum::Transform (const gp_Trsf& theTrsf)
+NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_RectangularFrustum::ScaleAndTransform (const Standard_Integer theScaleFactor,
+                                                                                           const gp_Trsf& theTrsf)
 {
+  Standard_ASSERT_RAISE (theScaleFactor > 0,
+    "Error! Pixel tolerance for selection should be greater than zero");
+
   SelectMgr_RectangularFrustum* aRes = new SelectMgr_RectangularFrustum();
+  const Standard_Boolean isToScale = theScaleFactor != 1;
+  const Standard_Boolean isToTrsf  = theTrsf.Form() != gp_Identity;
 
-  aRes->myNearPickedPnt = SelectMgr_MatOp::Transform (theTrsf, myNearPickedPnt);
-  aRes->myFarPickedPnt  = SelectMgr_MatOp::Transform (theTrsf, myFarPickedPnt);
-  aRes->myViewRayDir    = aRes->myFarPickedPnt - aRes->myNearPickedPnt;
+  if (!isToScale && !isToTrsf)
+    return aRes;
 
   aRes->myIsOrthographic = myIsOrthographic;
+  SelectMgr_RectangularFrustum* aRef = this;
 
-  // LeftTopNear
-  aRes->myVertices[0] = SelectMgr_MatOp::Transform (theTrsf, myVertices[0]);
-  // LeftTopFar
-  aRes->myVertices[1] = SelectMgr_MatOp::Transform (theTrsf, myVertices[1]);
-  // LeftBottomNear
-  aRes->myVertices[2] = SelectMgr_MatOp::Transform (theTrsf, myVertices[2]);
-  // LeftBottomFar
-  aRes->myVertices[3] = SelectMgr_MatOp::Transform (theTrsf, myVertices[3]);
-  // RightTopNear
-  aRes->myVertices[4] = SelectMgr_MatOp::Transform (theTrsf, myVertices[4]);
-  // RightTopFar
-  aRes->myVertices[5] = SelectMgr_MatOp::Transform (theTrsf, myVertices[5]);
-  // RightBottomNear
-  aRes->myVertices[6] = SelectMgr_MatOp::Transform (theTrsf, myVertices[6]);
-  // RightBottomFar
-  aRes->myVertices[7] = SelectMgr_MatOp::Transform (theTrsf, myVertices[7]);
-
-  // compute frustum normals
-  computeNormals (aRes->myVertices, aRes->myPlanes);
-
-  for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
+  if (isToScale)
   {
-    Standard_Real aMax = -DBL_MAX;
-    Standard_Real aMin =  DBL_MAX;
-    const SelectMgr_Vec3 aPlane = aRes->myPlanes[aPlaneIdx];
-    for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
-    {
-      Standard_Real aProjection = DOT (aPlane, aRes->myVertices[aVertIdx]);
-      aMax = Max (aMax, aProjection);
-      aMin = Min (aMin, aProjection);
-    }
-    aRes->myMaxVertsProjections[aPlaneIdx] = aMax;
-    aRes->myMinVertsProjections[aPlaneIdx] = aMin;
-  }
-
-  SelectMgr_Vec3 aDimensions[3] =
-  {
-    SelectMgr_Vec3 (1.0, 0.0, 0.0),
-    SelectMgr_Vec3 (0.0, 1.0, 0.0),
-    SelectMgr_Vec3 (0.0, 0.0, 1.0)
-  };
-
-  for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
-  {
-    Standard_Real aMax = -DBL_MAX;
-    Standard_Real aMin =  DBL_MAX;
-    for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
-    {
-      Standard_Real aProjection = DOT (aDimensions[aDim], aRes->myVertices[aVertIdx]);
-      aMax = Max (aMax, aProjection);
-      aMin = Min (aMin, aProjection);
-    }
-    aRes->myMaxOrthoVertsProjections[aDim] = aMax;
-    aRes->myMinOrthoVertsProjections[aDim] = aMin;
-  }
-
-  // Horizontal
-  aRes->myEdgeDirs[0] = aRes->myVertices[4] - aRes->myVertices[0];
-  // Vertical
-  aRes->myEdgeDirs[1] = aRes->myVertices[2] - aRes->myVertices[0];
-  // LeftLower
-  aRes->myEdgeDirs[2] = aRes->myVertices[2] - aRes->myVertices[3];
-  // RightLower
-  aRes->myEdgeDirs[3] = aRes->myVertices[6] - aRes->myVertices[7];
-  // LeftUpper
-  aRes->myEdgeDirs[4] = aRes->myVertices[0] - aRes->myVertices[1];
-  // RightUpper
-  aRes->myEdgeDirs[5] = aRes->myVertices[4] - aRes->myVertices[5];
-
-  return NCollection_Handle<SelectMgr_BaseFrustum> (aRes);
-}
-
-// =======================================================================
-// function : Scale
-// purpose  : IMPORTANT: Makes sense only for frustum built on a single point!
-//            Returns a copy of the frustum resized according to the scale factor given
-// =======================================================================
-NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_RectangularFrustum::Scale (const Standard_Real theScaleFactor)
-{
-  SelectMgr_RectangularFrustum* aRes = new SelectMgr_RectangularFrustum();
+    aRes->myNearPickedPnt = myNearPickedPnt;
+    aRes->myFarPickedPnt  = myFarPickedPnt;
+    aRes->myViewRayDir    = myViewRayDir;
 
-  aRes->myNearPickedPnt = myNearPickedPnt;
-  aRes->myFarPickedPnt  = myFarPickedPnt;
-  aRes->myViewRayDir    = myViewRayDir;
-
-  aRes->myIsOrthographic = myIsOrthographic;
+    const gp_Pnt2d aMinPnt (myMousePos.X() - theScaleFactor * 0.5,
+                            myMousePos.Y() - theScaleFactor * 0.5);
+    const gp_Pnt2d aMaxPnt (myMousePos.X() + theScaleFactor * 0.5,
+                            myMousePos.Y() + theScaleFactor * 0.5);
 
-    // LeftTopNear
-  aRes->myVertices[0] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0,
-                                                          myMousePos.Y() + theScaleFactor / 2.0,
-                                                          0.0);
-  // LeftTopFar
-  aRes->myVertices[1] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0,
-                                                          myMousePos.Y() + theScaleFactor / 2.0,
-                                                          1.0);
-  // LeftBottomNear
-  aRes->myVertices[2] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0,
-                                                          myMousePos.Y() - theScaleFactor / 2.0,
-                                                          0.0);
-  // LeftBottomFar
-  aRes->myVertices[3] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0,
-                                                          myMousePos.Y() - theScaleFactor / 2.0,
-                                                          1.0);
-  // RightTopNear
-  aRes->myVertices[4] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0,
-                                                          myMousePos.Y() + theScaleFactor / 2.0,
-                                                          0.0);
-  // RightTopFar
-  aRes->myVertices[5] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0,
-                                                          myMousePos.Y() + theScaleFactor / 2.0,
-                                                          1.0);
-  // RightBottomNear
-  aRes->myVertices[6] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0,
-                                                          myMousePos.Y() - theScaleFactor / 2.0,
-                                                          0.0);
-  // RightBottomFar
-  aRes->myVertices[7] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0,
-                                                          myMousePos.Y() - theScaleFactor / 2.0,
-                                                          1.0);
-  // compute frustum normals
-  computeNormals (aRes->myVertices, aRes->myPlanes);
+    // recompute base frustum characteristics from scratch
+    computeFrustum (aMinPnt, aMaxPnt, myBuilder, aRes->myVertices, aRes->myEdgeDirs);
 
-  for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
-  {
-    Standard_Real aMax = -DBL_MAX;
-    Standard_Real aMin =  DBL_MAX;
-    const SelectMgr_Vec3 aPlane = aRes->myPlanes[aPlaneIdx];
-    for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
-    {
-      Standard_Real aProjection = DOT (aPlane, aRes->myVertices[aVertIdx]);
-      aMax = Max (aMax, aProjection);
-      aMin = Min (aMin, aProjection);
-    }
-    aRes->myMaxVertsProjections[aPlaneIdx] = aMax;
-    aRes->myMinVertsProjections[aPlaneIdx] = aMin;
+    aRef = aRes;
   }
 
-  SelectMgr_Vec3 aDimensions[3] =
+  if (isToTrsf)
   {
-    SelectMgr_Vec3 (1.0, 0.0, 0.0),
-    SelectMgr_Vec3 (0.0, 1.0, 0.0),
-    SelectMgr_Vec3 (0.0, 0.0, 1.0)
-  };
-
-  for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
-  {
-    Standard_Real aMax = -DBL_MAX;
-    Standard_Real aMin =  DBL_MAX;
-    for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
-    {
-      Standard_Real aProjection = DOT (aDimensions[aDim], aRes->myVertices[aVertIdx]);
-      aMax = Max (aMax, aProjection);
-      aMin = Min (aMin, aProjection);
-    }
-    aRes->myMaxOrthoVertsProjections[aDim] = aMax;
-    aRes->myMinOrthoVertsProjections[aDim] = aMin;
+    aRes->myNearPickedPnt = aRef->myNearPickedPnt.Transformed (theTrsf);
+    aRes->myFarPickedPnt  = aRef->myFarPickedPnt.Transformed (theTrsf);
+    aRes->myViewRayDir    = aRes->myFarPickedPnt.XYZ() - aRes->myNearPickedPnt.XYZ();
+
+      // LeftTopNear
+    aRes->myVertices[0] = aRef->myVertices[0].Transformed (theTrsf);
+    // LeftTopFar
+    aRes->myVertices[1] = aRef->myVertices[1].Transformed (theTrsf);
+    // LeftBottomNear
+    aRes->myVertices[2] = aRef->myVertices[2].Transformed (theTrsf);
+    // LeftBottomFar
+    aRes->myVertices[3] = aRef->myVertices[3].Transformed (theTrsf);
+    // RightTopNear
+    aRes->myVertices[4] = aRef->myVertices[4].Transformed (theTrsf);
+    // RightTopFar
+    aRes->myVertices[5] = aRef->myVertices[5].Transformed (theTrsf);
+    // RightBottomNear
+    aRes->myVertices[6] = aRef->myVertices[6].Transformed (theTrsf);
+    // RightBottomFar
+    aRes->myVertices[7] = aRef->myVertices[7].Transformed (theTrsf);
+
+    // Horizontal
+    aRes->myEdgeDirs[0] = aRes->myVertices[4].XYZ() - aRes->myVertices[0].XYZ();
+    // Vertical
+    aRes->myEdgeDirs[1] = aRes->myVertices[2].XYZ() - aRes->myVertices[0].XYZ();
+    // LeftLower
+    aRes->myEdgeDirs[2] = aRes->myVertices[2].XYZ() - aRes->myVertices[3].XYZ();
+    // RightLower
+    aRes->myEdgeDirs[3] = aRes->myVertices[6].XYZ() - aRes->myVertices[7].XYZ();
+    // LeftUpper
+    aRes->myEdgeDirs[4] = aRes->myVertices[0].XYZ() - aRes->myVertices[1].XYZ();
+    // RightUpper
+    aRes->myEdgeDirs[5] = aRes->myVertices[4].XYZ() - aRes->myVertices[5].XYZ();
   }
 
-  // Horizontal
-  aRes->myEdgeDirs[0] = aRes->myVertices[4] - aRes->myVertices[0];
-  // Vertical
-  aRes->myEdgeDirs[1] = aRes->myVertices[2] - aRes->myVertices[0];
-  // LeftLower
-  aRes->myEdgeDirs[2] = aRes->myVertices[2] - aRes->myVertices[3];
-  // RightLower
-  aRes->myEdgeDirs[3] = aRes->myVertices[6] - aRes->myVertices[7];
-  // LeftUpper
-  aRes->myEdgeDirs[4] = aRes->myVertices[0] - aRes->myVertices[1];
-  // RightUpper
-  aRes->myEdgeDirs[5] = aRes->myVertices[4] - aRes->myVertices[5];
+  // compute frustum normals
+  computeNormals (aRes->myEdgeDirs, aRes->myPlanes);
+
+  cacheVertexProjections (aRes);
 
   return NCollection_Handle<SelectMgr_BaseFrustum> (aRes);
 }
@@ -577,20 +431,19 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t
 // purpose  : SAT intersection test between defined volume and
 //            given axis-aligned box
 // =======================================================================
-Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
+Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                                         const SelectMgr_Vec3& theBoxMax,
                                                          Standard_Real& theDepth)
 {
-  const SelectMgr_Vec3& aMinPnt = theBox.CornerMin();
-  const SelectMgr_Vec3& aMaxPnt = theBox.CornerMax();
-  if (!hasOverlap (aMinPnt, aMaxPnt))
+  if (!hasOverlap (theBoxMin, theBoxMax))
     return Standard_False;
 
-  SelectMgr_Vec3 aNearestPnt = SelectMgr_Vec3 (RealLast(), RealLast(), RealLast());
-  aNearestPnt.x() = Max (Min (myNearPickedPnt.x(), aMaxPnt.x()), aMinPnt.x());
-  aNearestPnt.y() = Max (Min (myNearPickedPnt.y(), aMaxPnt.y()), aMinPnt.y());
-  aNearestPnt.z() = Max (Min (myNearPickedPnt.z(), aMaxPnt.z()), aMinPnt.z());
+  gp_Pnt aNearestPnt (RealLast(), RealLast(), RealLast());
+  aNearestPnt.SetX (Max (Min (myNearPickedPnt.X(), theBoxMax.x()), theBoxMin.x()));
+  aNearestPnt.SetY (Max (Min (myNearPickedPnt.Y(), theBoxMax.y()), theBoxMin.y()));
+  aNearestPnt.SetZ (Max (Min (myNearPickedPnt.Z(), theBoxMax.z()), theBoxMin.z()));
 
-  theDepth = DISTANCE (aNearestPnt, myNearPickedPnt);
+  theDepth = aNearestPnt.Distance (myNearPickedPnt);
 
   return Standard_True;
 }
@@ -605,15 +458,24 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt,
   if (!hasOverlap (thePnt))
     return Standard_False;
 
-  SelectMgr_Vec3 aPnt (thePnt.X(), thePnt.Y(), thePnt.Z());
-  SelectMgr_Vec3 aV = aPnt - myNearPickedPnt;
-  SelectMgr_Vec3 aDetectedPnt = myNearPickedPnt + myViewRayDir * (DOT (aV, myViewRayDir) / DOT (myViewRayDir, myViewRayDir));
+  gp_XYZ aV = thePnt.XYZ() - myNearPickedPnt.XYZ();
+  gp_Pnt aDetectedPnt =
+    myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * (aV.Dot (myViewRayDir.XYZ()) / myViewRayDir.Dot (myViewRayDir));
 
-  theDepth = DISTANCE (aDetectedPnt, myNearPickedPnt);
+  theDepth = aDetectedPnt.Distance (myNearPickedPnt);
 
   return Standard_True;
 }
 
+// =======================================================================
+// function : Overlaps
+// purpose  : Intersection test between defined volume and given point
+// =======================================================================
+Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt)
+{
+  return hasOverlap (thePnt);
+}
+
 // =======================================================================
 // function : Overlaps
 // purpose  : Checks if line segment overlaps selecting frustum
@@ -668,7 +530,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const Handle(TColgp_HAr
   }
   else if (theSensType == Select3D_TOS_INTERIOR)
   {
-    SelectMgr_Vec3 aPolyNorm (RealLast());
+    gp_Vec aPolyNorm (gp_XYZ (RealLast(), RealLast(), RealLast()));
     if (!hasOverlap (theArrayOfPnts, aPolyNorm))
       return Standard_False;
 
@@ -704,48 +566,41 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
   }
   else if (theSensType == Select3D_TOS_INTERIOR)
   {
-    SelectMgr_Vec3 aTriangleNormal (RealLast());
+    gp_Vec aTriangleNormal (gp_XYZ (RealLast(), RealLast(), RealLast()));
     if (!hasOverlap (thePnt1, thePnt2, thePnt3, aTriangleNormal))
       return Standard_False;
 
     // check if intersection point belongs to triangle's interior part
-    SelectMgr_Vec3 aPnt1 (thePnt1.X(), thePnt1.Y(), thePnt1.Z());
-    SelectMgr_Vec3 aTrEdges[3] = { SelectMgr_Vec3 (thePnt2.X() - thePnt1.X(), thePnt2.Y() - thePnt1.Y(), thePnt2.Z() - thePnt1.Z()),
-                                   SelectMgr_Vec3 (thePnt3.X() - thePnt2.X(), thePnt3.Y() - thePnt2.Y(), thePnt3.Z() - thePnt2.Z()),
-                                   SelectMgr_Vec3 (thePnt1.X() - thePnt3.X(), thePnt1.Y() - thePnt3.Y(), thePnt1.Z() - thePnt3.Z()) };
-    SelectMgr_Vec3 anEdge = (aPnt1 - myNearPickedPnt) * (1.0 / DOT (aTriangleNormal, myViewRayDir));
+    gp_XYZ aTrEdges[3] = { thePnt2.XYZ() - thePnt1.XYZ(),
+                           thePnt3.XYZ() - thePnt2.XYZ(),
+                           thePnt1.XYZ() - thePnt3.XYZ() };
+    gp_XYZ anEdge = (thePnt1.XYZ() - myNearPickedPnt.XYZ()) * (1.0 / aTriangleNormal.Dot (myViewRayDir));
 
-    Standard_Real aTime = DOT (aTriangleNormal, anEdge);
+    Standard_Real aTime = aTriangleNormal.Dot (anEdge);
 
-    SelectMgr_Vec3 aVec = SelectMgr_Vec3 (myViewRayDir.y() * anEdge.z() - myViewRayDir.z() * anEdge.y(),
-                                          myViewRayDir.z() * anEdge.x() - myViewRayDir.x() * anEdge.z(),
-                                          myViewRayDir.x() * anEdge.y() - myViewRayDir.y() * anEdge.x());
+    gp_XYZ aVec = myViewRayDir.XYZ().Crossed (anEdge);
 
-    Standard_Real anU = DOT (aVec, aTrEdges[2]);
-    Standard_Real aV  = DOT (aVec, aTrEdges[0]);
+    Standard_Real anU = aVec.Dot (aTrEdges[2]);
+    Standard_Real aV  = aVec.Dot (aTrEdges[0]);
 
     Standard_Boolean isInterior = (aTime >= 0.0) && (anU >= 0.0) && (aV >= 0.0) && (anU + aV <= 1.0);
 
     if (isInterior)
     {
-      SelectMgr_Vec3 aDetectedPnt = myNearPickedPnt + myViewRayDir * aTime;
-      theDepth = DISTANCE (myNearPickedPnt, aDetectedPnt);
+      gp_Pnt aDetectedPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime;
+      theDepth = myNearPickedPnt.Distance (aDetectedPnt);
       return Standard_True;
     }
 
     gp_Pnt aPnts[3] = {thePnt1, thePnt2, thePnt3};
     Standard_Real aMinDist = RealLast();
     Standard_Integer aNearestEdgeIdx = -1;
-    SelectMgr_Vec3 aPtOnPlane = myNearPickedPnt + myViewRayDir * aTime;
+    gp_Pnt aPtOnPlane = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime;
     for (Standard_Integer anEdgeIdx = 0; anEdgeIdx < 3; ++anEdgeIdx)
     {
-      SelectMgr_Vec3 aW = SelectMgr_Vec3 (aPtOnPlane.x() - aPnts[anEdgeIdx].X(),
-                                          aPtOnPlane.y() - aPnts[anEdgeIdx].Y(),
-                                          aPtOnPlane.z() - aPnts[anEdgeIdx].Z());
-      Standard_Real aCoef = DOT (aTrEdges[anEdgeIdx], aW) / DOT (aTrEdges[anEdgeIdx], aTrEdges[anEdgeIdx]);
-      Standard_Real aDist = DISTANCE (aPtOnPlane, SelectMgr_Vec3 (aPnts[anEdgeIdx].X() + aCoef * aTrEdges[anEdgeIdx].x(),
-                                                                  aPnts[anEdgeIdx].Y() + aCoef * aTrEdges[anEdgeIdx].y(),
-                                                                  aPnts[anEdgeIdx].Z() + aCoef * aTrEdges[anEdgeIdx].z()));
+      gp_XYZ aW = aPtOnPlane.XYZ() - aPnts[anEdgeIdx].XYZ();
+      Standard_Real aCoef = aTrEdges[anEdgeIdx].Dot (aW) / aTrEdges[anEdgeIdx].Dot (aTrEdges[anEdgeIdx]);
+      Standard_Real aDist = aPtOnPlane.Distance (aPnts[anEdgeIdx].XYZ() + aCoef * aTrEdges[anEdgeIdx]);
       if (aMinDist > aDist)
       {
         aMinDist = aDist;
@@ -765,8 +620,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
 // =======================================================================
 Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG)
 {
-  const SelectMgr_Vec3& aCOG = SelectMgr_Vec3 (theCOG.X(), theCOG.Y(), theCOG.Z());
-  return DISTANCE (aCOG, myNearPickedPnt);
+  return theCOG.Distance (myNearPickedPnt);
 }
 
 // =======================================================================
@@ -774,9 +628,9 @@ Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt&
 // purpose  : Calculates the point on a view ray that was detected during
 //            the run of selection algo by given depth
 // =======================================================================
-SelectMgr_Vec3 SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth) const
+gp_Pnt SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth) const
 {
-  return myNearPickedPnt + myViewRayDir * theDepth;
+  return myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * theDepth;
 }
 
 // =======================================================================
@@ -803,8 +657,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_Sequen
 
     const gp_XYZ& aPlaneDirXYZ = aGeomPlane.Axis().Direction().XYZ();
 
-    Standard_Real aDotProduct = DOTp (myViewRayDir, aPlaneDirXYZ);
-    Standard_Real aDistance = - (DOTp (myNearPickedPnt, aPlaneDirXYZ) + aPlaneD);
+    Standard_Real aDotProduct = myViewRayDir.XYZ().Dot (aPlaneDirXYZ);
+    Standard_Real aDistance = - myNearPickedPnt.XYZ().Dot (aPlaneDirXYZ) +
+                                aPlaneD;
 
     // check whether the pick line is parallel to clip plane
     if (Abs (aDotProduct) < Precision::Angular())
@@ -823,8 +678,8 @@ Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_Sequen
       continue;
     }
 
-    const SelectMgr_Vec3 anIntersectionPt = myNearPickedPnt + myViewRayDir * aParam;
-    const Standard_Real aDistToPln = DISTANCE (anIntersectionPt, myNearPickedPnt);
+    const gp_Pnt anIntersectionPt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aParam;
+    const Standard_Real aDistToPln = anIntersectionPt.Distance (myNearPickedPnt);
 
     // change depth limits for case of opposite and directed planes
     if (aDotProduct < 0.0)
index ef97920ceb2dba6901f6c974540ae5aa4b20a7ec..5570f4db44db810742de3516ef44965bf6925cc7 100644 (file)
@@ -42,18 +42,22 @@ public:
   virtual void Build (const gp_Pnt2d& theMinPnt,
                       const gp_Pnt2d& theMaxPnt) Standard_OVERRIDE;
 
-  //! Returns a copy of the frustum transformed according to the matrix given
-  virtual NCollection_Handle<SelectMgr_BaseFrustum> Transform (const gp_Trsf& theTrsf) Standard_OVERRIDE;
-
-  //! IMPORTANT: Makes sense only for frustum built on a single point!
+  //! IMPORTANT: Scaling makes sense only for frustum built on a single point!
+  //!            Note that this method does not perform any checks on type of the frustum.
   //! Returns a copy of the frustum resized according to the scale factor given
-  virtual NCollection_Handle<SelectMgr_BaseFrustum> Scale (const Standard_Real theScaleFactor) Standard_OVERRIDE;
+  //! and transforms it using the matrix given.
+  //! There are no default parameters, but in case if:
+  //!    - transformation only is needed: @theScaleFactor must be initialized as any negative value;
+  //!    - scale only is needed: @theTrsf must be set to gp_Identity.
+  virtual NCollection_Handle<SelectMgr_BaseFrustum> ScaleAndTransform (const Standard_Integer theScaleFactor,
+                                                                       const gp_Trsf& theTrsf) Standard_OVERRIDE;
 
 
   // SAT Tests for different objects
 
   //! SAT intersection test between defined volume and given axis-aligned box
-  virtual Standard_Boolean Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
+  virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                     const SelectMgr_Vec3& theBoxMax,
                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box
@@ -66,6 +70,9 @@ public:
   virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt,
                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
+  //! Intersection test between defined volume and given point
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) Standard_OVERRIDE;
+
   //! SAT intersection test between defined volume and given ordered set of points,
   //! representing line segments. The test may be considered of interior part or
   //! boundary line defined by segments depending on given sensitivity type
@@ -92,29 +99,45 @@ public:
   virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) Standard_OVERRIDE;
 
   //! Calculates the point on a view ray that was detected during the run of selection algo by given depth
-  virtual SelectMgr_Vec3 DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE;
+  virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE;
 
   //! Checks if the point of sensitive in which selection was detected belongs
   //! to the region defined by clipping planes
   virtual Standard_Boolean IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
                                       const Standard_Real theDepth) Standard_OVERRIDE;
 
+  //! A set of helper functions that return rectangular selecting frustum data
+  inline const gp_Pnt* GetVertices() const { return myVertices; }
+
+  inline gp_Pnt GetNearPnt() const { return myNearPickedPnt; }
+
+  inline gp_Pnt GetFarPnt() const { return myFarPickedPnt; }
 protected:
 
   void segmentSegmentDistance (const gp_Pnt& theSegPnt1,
                                const gp_Pnt& theSegPnt2,
                                Standard_Real& theDepth);
 
-  void segmentPlaneIntersection (const SelectMgr_Vec3& thePlane,
+  void segmentPlaneIntersection (const gp_Vec& thePlane,
                                  const gp_Pnt& thePntOnPlane,
                                  Standard_Real& theDepth);
 
 private:
 
-  SelectMgr_Vec3 myNearPickedPnt;             //!< 3d projection of user-picked selection point onto near view plane
-  SelectMgr_Vec3 myFarPickedPnt;              //!< 3d projection of user-picked selection point onto far view plane
-  SelectMgr_Vec3 myViewRayDir;
-  gp_Pnt2d       myMousePos;                  //!< Mouse coordinates
+  void cacheVertexProjections (SelectMgr_RectangularFrustum* theFrustum);
+
+private:
+  enum { LeftTopNear, LeftTopFar,
+         LeftBottomNear, LeftBottomFar,
+         RightTopNear, RightTopFar,
+         RightBottomNear, RightBottomFar };
+
+private:
+
+  gp_Pnt   myNearPickedPnt;             //!< 3d projection of user-picked selection point onto near view plane
+  gp_Pnt   myFarPickedPnt;              //!< 3d projection of user-picked selection point onto far view plane
+  gp_Vec   myViewRayDir;
+  gp_Pnt2d myMousePos;                  //!< Mouse coordinates
 };
 
 #endif // _SelectMgr_RectangularFrustum_HeaderFile
index 91bc2632f1ba50c47c9cb169803688b2ecfad57d..5018d5789cfba386afccde98878bfb29ded3da76 100644 (file)
@@ -25,7 +25,7 @@
 //=======================================================================
 SelectMgr_SelectableObjectSet::SelectMgr_SelectableObjectSet()
 {
-  myBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 32> (1, 32, Standard_False);
+  myBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (1, 32, Standard_True);
 }
 
 //=======================================================================
index aa1ff3ba70f26f086b8b5d039a18b5b50cdc3c28..64d538a538010b934d1326fe8bdbe627b43b24f5 100644 (file)
@@ -32,10 +32,19 @@ SelectMgr_SelectingVolumeManager::SelectMgr_SelectingVolumeManager (Standard_Boo
 }
 
 //=======================================================================
-// function : Transform
-// purpose  : Returns a copy of active frustum transformed according to the matrix given
-//=======================================================================
-SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::Transform (const gp_Trsf& theTrsf)
+// function : ScaleAndTransform
+// purpose  : IMPORTANT: Scaling makes sense only for frustum built on a single point!
+//            Note that this method does not perform any checks on type of the frustum.
+//
+//            Returns a copy of the frustum resized according to the scale factor given
+//            and transforms it using the matrix given.
+//            There are no default parameters, but in case if:
+//                - transformation only is needed: @theScaleFactor must be initialized
+//                  as any negative value;
+//                - scale only is needed: @theTrsf must be set to gp_Identity.
+//=======================================================================
+SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::ScaleAndTransform (const Standard_Integer theScaleFactor,
+                                                                                      const gp_Trsf& theTrsf)
 {
   SelectMgr_SelectingVolumeManager aMgr (Standard_False);
 
@@ -44,31 +53,13 @@ SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::Transform (co
 
   aMgr.myActiveSelectionType = myActiveSelectionType;
 
-  aMgr.mySelectingVolumes[myActiveSelectionType / 2] = mySelectingVolumes[myActiveSelectionType / 2]->Transform (theTrsf);
+  aMgr.mySelectingVolumes[myActiveSelectionType / 2]
+    = mySelectingVolumes[myActiveSelectionType / 2]->ScaleAndTransform (theScaleFactor, theTrsf);
   aMgr.myToAllowOverlap = myToAllowOverlap;
 
   return aMgr;
 }
 
-//=======================================================================
-// function : Scale
-// purpose  : IMPORTANT: Makes sense only for point selection!
-//            Returns a copy of the frustum resized according to the scale factor given
-//=======================================================================
-SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::Scale (const Standard_Real theScaleFactor)
-{
-  if (myActiveSelectionType != Point)
-    return SelectMgr_SelectingVolumeManager (Standard_False);
-
-  SelectMgr_SelectingVolumeManager aMgr (Standard_False);
-
-  aMgr.myActiveSelectionType = Point;
-
-  aMgr.mySelectingVolumes[Point] = mySelectingVolumes[Point]->Scale (theScaleFactor);
-
-  return aMgr;
-}
-
 //=======================================================================
 // function : GetActiveSelectionType
 // purpose  :
@@ -147,7 +138,7 @@ void SelectMgr_SelectingVolumeManager::SetWindowSize (const Standard_Integer the
 // function : SetPixelTolerance
 // purpose  : Updates pixel tolerance in all selecting volumes
 //=======================================================================
-void SelectMgr_SelectingVolumeManager::SetPixelTolerance (const Standard_Real theTolerance)
+void SelectMgr_SelectingVolumeManager::SetPixelTolerance (const Standard_Integer theTolerance)
 {
   for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
   {
@@ -198,13 +189,14 @@ void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const TColgp_Array1
 // purpose  : SAT intersection test between defined volume and
 //            given axis-aligned box
 //=======================================================================
-Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const BVH_Box<Standard_Real, 3>& theBndBox,
+Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                                             const SelectMgr_Vec3& theBoxMax,
                                                              Standard_Real& theDepth)
 {
   if (myActiveSelectionType == Unknown)
     return Standard_False;
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBndBox, theDepth);
+  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBoxMin, theBoxMax, theDepth);
 }
 
 //=======================================================================
@@ -225,16 +217,28 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec
 // function : Overlaps
 // purpose  : Intersection test between defined volume and given point
 //=======================================================================
-Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt,
+Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePnt,
                                                              Standard_Real& theDepth)
 {
   if (myActiveSelectionType == Unknown)
     return Standard_False;
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePt,
+  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePnt,
                                                                   theDepth);
 }
 
+//=======================================================================
+// function : Overlaps
+// purpose  : Intersection test between defined volume and given point
+//=======================================================================
+Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePnt)
+{
+  if (myActiveSelectionType == Unknown)
+    return Standard_False;
+
+  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePnt);
+}
+
 //=======================================================================
 // function : Overlaps
 // purpose  : SAT intersection test between defined volume and given
@@ -242,14 +246,14 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt
 //            may be considered of interior part or boundary line defined
 //            by segments depending on given sensitivity type
 //=======================================================================
-Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts,
+Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
                                                              Standard_Integer theSensType,
                                                              Standard_Real& theDepth)
 {
   if (myActiveSelectionType == Unknown)
     return Standard_False;
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPts,
+  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPnts,
                                                                   (Select3D_TypeOfSensitivity)theSensType,
                                                                   theDepth);
 }
@@ -310,10 +314,10 @@ Standard_Real SelectMgr_SelectingVolumeManager::DistToGeometryCenter (const gp_P
 //            the run of selection algo by given depth. Is valid for point
 //            selection only
 // =======================================================================
-NCollection_Vec3<Standard_Real> SelectMgr_SelectingVolumeManager::DetectedPoint (const Standard_Real theDepth) const
+gp_Pnt SelectMgr_SelectingVolumeManager::DetectedPoint (const Standard_Real theDepth) const
 {
   if (myActiveSelectionType != Point)
-    return NCollection_Vec3<Standard_Real> (RealLast());
+    return gp_Pnt (RealLast(), RealLast(), RealLast());
 
   return mySelectingVolumes[Frustum]->DetectedPoint (theDepth);
 }
@@ -351,3 +355,45 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::IsOverlapAllowed() const
 {
   return myActiveSelectionType != Box || myToAllowOverlap;
 }
+
+//=======================================================================
+// function : GetVertices
+// purpose  :
+//=======================================================================
+const gp_Pnt* SelectMgr_SelectingVolumeManager::GetVertices() const
+{
+  if (myActiveSelectionType == Polyline)
+    return NULL;
+
+  const SelectMgr_RectangularFrustum* aFr =
+    reinterpret_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].Access());
+  return aFr->GetVertices();
+}
+
+//=======================================================================
+// function : GetNearPnt
+// purpose  :
+//=======================================================================
+gp_Pnt SelectMgr_SelectingVolumeManager::GetNearPnt() const
+{
+  if (myActiveSelectionType == Polyline)
+    return gp_Pnt();
+
+   const SelectMgr_RectangularFrustum* aFr =
+     reinterpret_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].Access());
+  return aFr->GetNearPnt();
+}
+
+//=======================================================================
+// function : GetFarPnt
+// purpose  :
+//=======================================================================
+gp_Pnt SelectMgr_SelectingVolumeManager::GetFarPnt() const
+{
+  if (myActiveSelectionType == Polyline)
+    return gp_Pnt();
+
+   const SelectMgr_RectangularFrustum* aFr =
+     reinterpret_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].Access());
+  return aFr->GetFarPnt();
+}
index 6c6a7d7238b96758b5056f20482bda4ef3eeff25..a14ba9137f8527eaa2ffce42ef840850b5ddaaa0 100644 (file)
@@ -37,12 +37,16 @@ public:
 
   Standard_EXPORT virtual ~SelectMgr_SelectingVolumeManager() {};
 
-  //! Returns a copy of active frustum transformed according to the matrix given
-  Standard_EXPORT virtual SelectMgr_SelectingVolumeManager Transform (const gp_Trsf& theTrsf);
-
-  //! IMPORTANT: Makes sense only for point selection!
+  //! IMPORTANT: Scaling makes sense only for frustum built on a single point!
+  //!            Note that this method does not perform any checks on type of the frustum.
+  //!
   //! Returns a copy of the frustum resized according to the scale factor given
-  Standard_EXPORT virtual SelectMgr_SelectingVolumeManager Scale (const Standard_Real theScaleFactor);
+  //! and transforms it using the matrix given.
+  //! There are no default parameters, but in case if:
+  //!    - transformation only is needed: @theScaleFactor must be initialized as any negative value;
+  //!    - scale only is needed: @theTrsf must be set to gp_Identity.
+  Standard_EXPORT virtual SelectMgr_SelectingVolumeManager ScaleAndTransform (const Standard_Integer theScaleFactor,
+                                                                              const gp_Trsf& theTrsf);
 
   Standard_EXPORT virtual Standard_Integer GetActiveSelectionType() const Standard_OVERRIDE;
 
@@ -63,7 +67,7 @@ public:
                                     const Standard_Real theHeight);
 
   //! Updates pixel tolerance in all selecting volumes
-  Standard_EXPORT void SetPixelTolerance (const Standard_Real theTolerance);
+  Standard_EXPORT void SetPixelTolerance (const Standard_Integer theTolerance);
 
   //! Updates window size in all selecting volumes
   Standard_EXPORT void SetWindowSize (const Standard_Integer theWidth, const Standard_Integer theHeight);
@@ -81,7 +85,8 @@ public:
 
 
   //! SAT intersection test between defined volume and given axis-aligned box
-  Standard_EXPORT virtual Standard_Boolean Overlaps (const BVH_Box<Standard_Real, 3>& theBndBox,
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                                      const SelectMgr_Vec3& theBoxMax,
                                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box
@@ -91,9 +96,12 @@ public:
                                                       Standard_Boolean*     theInside = NULL) Standard_OVERRIDE;
 
   //! Intersection test between defined volume and given point
-  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePt,
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt,
                                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
+  //! Intersection test between defined volume and given point
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) Standard_OVERRIDE;
+
   //! SAT intersection test between defined volume and given ordered set of points,
   //! representing line segments. The test may be considered of interior part or
   //! boundary line defined by segments depending on given sensitivity type
@@ -102,16 +110,16 @@ public:
                                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
   //! Checks if line segment overlaps selecting frustum
-  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1,
-                                                     const gp_Pnt& thePt2,
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1,
+                                                     const gp_Pnt& thePnt2,
                                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
   //! SAT intersection test between defined volume and given triangle. The test may
   //! be considered of interior part or boundary line defined by triangle vertices
   //! depending on given sensitivity type
-  Standard_EXPORT  virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1,
-                                                      const gp_Pnt& thePt2,
-                                                      const gp_Pnt& thePt3,
+  Standard_EXPORT  virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1,
+                                                      const gp_Pnt& thePnt2,
+                                                      const gp_Pnt& thePnt3,
                                                       Standard_Integer theSensType,
                                                       Standard_Real& theDepth) Standard_OVERRIDE;
 
@@ -122,7 +130,7 @@ public:
 
   //! Calculates the point on a view ray that was detected during the run of selection algo by given depth. Is valid for point
   //! selection only
-  Standard_EXPORT virtual NCollection_Vec3<Standard_Real> DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE;
+  Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE;
 
   //! Checks if the point of sensitive in which selection was detected belongs
   //! to the region defined by clipping planes
@@ -136,6 +144,13 @@ public:
 
   Standard_EXPORT virtual Standard_Boolean IsOverlapAllowed() const Standard_OVERRIDE;
 
+  //! A set of helper functions that return rectangular selecting frustum data
+  Standard_EXPORT const gp_Pnt* GetVertices() const;
+
+  Standard_EXPORT gp_Pnt GetNearPnt() const;
+
+  Standard_EXPORT gp_Pnt GetFarPnt() const;
+
 private:
   enum { Frustum, FrustumSet, VolumeTypesNb };       //!< Defines the amount of available selecting volumes
 
index ad5e55eaa882155e2417d4145b5a5ae43a703d63..4bfb2a8dd0fa4d86dfdcf407d6c8c79cf08a222e 100644 (file)
@@ -29,7 +29,7 @@ SelectMgr_Selection::SelectMgr_Selection (const Standard_Integer theModeIdx)
 : myMode (theModeIdx),
   mySelectionState (SelectMgr_SOS_Unknown),
   myBVHUpdateStatus (SelectMgr_TBU_None),
-  mySensFactor (2.0)
+  mySensFactor (2)
 {}
 
 SelectMgr_Selection::~SelectMgr_Selection()
@@ -48,7 +48,7 @@ void SelectMgr_Selection::Destroy()
     Handle(SelectMgr_SensitiveEntity)& anEntity = myEntities.ChangeValue (anEntityIdx);
     anEntity->BaseSensitive()->Set (NULL);
   }
-  mySensFactor = 2.0;
+  mySensFactor = 2;
 }
 
 //==================================================
@@ -134,7 +134,7 @@ void SelectMgr_Selection::SetSelectionState (const SelectMgr_StateOfSelection th
 // function: Sensitivity
 // purpose : Returns sensitivity of the selection
 //==================================================
-Standard_Real SelectMgr_Selection::Sensitivity() const
+Standard_Integer SelectMgr_Selection::Sensitivity() const
 {
   return mySensFactor;
 }
index 8a2c0b4edae9a9668a500a0826189c52dad0afd4..1536b68a36974cfac7c77436a6fcbc376f21321f 100644 (file)
@@ -131,7 +131,7 @@ public:
   Standard_EXPORT void SetSelectionState (const SelectMgr_StateOfSelection theState) const;
 
   //! Returns sensitivity of the selection
-  Standard_EXPORT Standard_Real Sensitivity() const;
+  Standard_EXPORT Standard_Integer Sensitivity() const;
 
   DEFINE_STANDARD_RTTI (SelectMgr_Selection)
 
@@ -148,7 +148,7 @@ private:
   SelectMgr_TypeOfUpdate                                          myUpdateStatus;
   mutable SelectMgr_StateOfSelection                              mySelectionState;
   mutable SelectMgr_TypeOfBVHUpdate                               myBVHUpdateStatus;
-  Standard_Real                                                   mySensFactor;
+  Standard_Integer                                                mySensFactor;
 };
 
 DEFINE_STANDARD_HANDLE(SelectMgr_Selection, MMgt_TShared)
index 696168d121a7282cdc4fc1d5d26c1047fe2a842b..b3c348dc90df5ad3c7451ec36d02e417781f4d3e 100644 (file)
 
 #include <SelectMgr_TriangularFrustum.hxx>
 
-#define DOT(A, B) (A.x() * B.x() + A.y() * B.y() + A.z() * B.z())
-#define DOTp(A, B) (A.x() * B.X() + A.y() * B.Y() + A.z() * B.Z())
-#define LENGTH(A) (std::sqrt (A.x() * A.x() + A.y() * A.y() + A.z() * A.z()))
-
 SelectMgr_TriangularFrustum::~SelectMgr_TriangularFrustum()
 {
   Clear();
@@ -26,174 +22,146 @@ SelectMgr_TriangularFrustum::~SelectMgr_TriangularFrustum()
 
 namespace
 {
-  void computeFrustumNormals (const SelectMgr_Vec3* theVertices, SelectMgr_Vec3* theNormals)
+  void computeFrustumNormals (const gp_Vec* theEdges, gp_Vec* theNormals)
   {
     // V0V1
-    theNormals[0] = SelectMgr_Vec3::Cross (theVertices[3] - theVertices[0],
-                                           theVertices[4] - theVertices[0]);
+    theNormals[0] = theEdges[0].Crossed (theEdges[1]);
     // V1V2
-    theNormals[1] = SelectMgr_Vec3::Cross (theVertices[4] - theVertices[1],
-                                           theVertices[5] - theVertices[1]);
+    theNormals[1] = theEdges[1].Crossed (theEdges[2]);
     // V0V2
-    theNormals[2] = SelectMgr_Vec3::Cross (theVertices[3] - theVertices[0],
-                                           theVertices[5] - theVertices[0]);
+    theNormals[2] = theEdges[0].Crossed (theEdges[2]);
     // Near
-    theNormals[3] = SelectMgr_Vec3::Cross (theVertices[1] - theVertices[0],
-                                           theVertices[2] - theVertices[0]);
+    theNormals[3] = theEdges[3].Crossed (theEdges[5]);
     // Far
-    theNormals[4] = SelectMgr_Vec3::Cross (theVertices[4] - theVertices[3],
-                                           theVertices[5] - theVertices[3]);
+    theNormals[4] = -theNormals[3];
   }
 }
 
-//=======================================================================
-// function : SelectMgr_TriangularFrustum
-// purpose  : Creates new triangular frustum with bases of triangles with
-//            vertices theP1, theP2 and theP3 projections onto near and
-//            far view frustum planes
-//=======================================================================
-void SelectMgr_TriangularFrustum::Build (const gp_Pnt2d& theP1,
-                                         const gp_Pnt2d& theP2,
-                                         const gp_Pnt2d& theP3)
+// =======================================================================
+// function : cacheVertexProjections
+// purpose  : Caches projection of frustum's vertices onto its plane directions
+//            and {i, j, k}
+// =======================================================================
+void SelectMgr_TriangularFrustum::cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum)
 {
-  // V0_Near
-  myVertices[0] = myBuilder->ProjectPntOnViewPlane (theP1.X(), theP1.Y(), 0.0);
-  // V1_Near
-  myVertices[1] = myBuilder->ProjectPntOnViewPlane (theP2.X(), theP2.Y(), 0.0);
-  // V2_Near
-  myVertices[2] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 0.0);
-  // V0_Far
-  myVertices[3] = myBuilder->ProjectPntOnViewPlane (theP1.X(), theP1.Y(), 1.0);
-  // V1_Far
-  myVertices[4] = myBuilder->ProjectPntOnViewPlane (theP2.X(), theP2.Y(), 1.0);
-  // V2_Far
-  myVertices[5] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 1.0);
-
-  computeFrustumNormals (myVertices, myPlanes);
-
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx)
   {
     Standard_Real aMax = -DBL_MAX;
     Standard_Real aMin =  DBL_MAX;
-    const SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
+    const gp_XYZ& aPlane = theFrustum->myPlanes[aPlaneIdx].XYZ();
     for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx)
     {
-      Standard_Real aProjection = DOT (aPlane, myVertices[aVertIdx]);
+      Standard_Real aProjection = aPlane.Dot (theFrustum->myVertices[aVertIdx].XYZ());
       aMax = Max (aMax, aProjection);
       aMin = Min (aMin, aProjection);
     }
-    myMaxVertsProjections[aPlaneIdx] = aMax;
-    myMinVertsProjections[aPlaneIdx] = aMin;
+    theFrustum->myMaxVertsProjections[aPlaneIdx] = aMax;
+    theFrustum->myMinVertsProjections[aPlaneIdx] = aMin;
   }
 
-  SelectMgr_Vec3 aDimensions[3] =
-  {
-    SelectMgr_Vec3 (1.0, 0.0, 0.0),
-    SelectMgr_Vec3 (0.0, 1.0, 0.0),
-    SelectMgr_Vec3 (0.0, 0.0, 1.0)
-  };
-
   for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
   {
     Standard_Real aMax = -DBL_MAX;
     Standard_Real aMin =  DBL_MAX;
     for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx)
     {
-      Standard_Real aProjection = DOT (aDimensions[aDim], myVertices[aVertIdx]);
+      Standard_Real aProjection = theFrustum->myVertices[aVertIdx].XYZ().Ptr()[aDim];
       aMax = Max (aMax, aProjection);
       aMin = Min (aMin, aProjection);
     }
-    myMaxOrthoVertsProjections[aDim] = aMax;
-    myMinOrthoVertsProjections[aDim] = aMin;
+    theFrustum->myMaxOrthoVertsProjections[aDim] = aMax;
+    theFrustum->myMinOrthoVertsProjections[aDim] = aMin;
   }
+}
+
+//=======================================================================
+// function : SelectMgr_TriangularFrustum
+// purpose  : Creates new triangular frustum with bases of triangles with
+//            vertices theP1, theP2 and theP3 projections onto near and
+//            far view frustum planes
+//=======================================================================
+void SelectMgr_TriangularFrustum::Build (const gp_Pnt2d& theP1,
+                                         const gp_Pnt2d& theP2,
+                                         const gp_Pnt2d& theP3)
+{
+  // V0_Near
+  myVertices[0] = myBuilder->ProjectPntOnViewPlane (theP1.X(), theP1.Y(), 0.0);
+  // V1_Near
+  myVertices[1] = myBuilder->ProjectPntOnViewPlane (theP2.X(), theP2.Y(), 0.0);
+  // V2_Near
+  myVertices[2] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 0.0);
+  // V0_Far
+  myVertices[3] = myBuilder->ProjectPntOnViewPlane (theP1.X(), theP1.Y(), 1.0);
+  // V1_Far
+  myVertices[4] = myBuilder->ProjectPntOnViewPlane (theP2.X(), theP2.Y(), 1.0);
+  // V2_Far
+  myVertices[5] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 1.0);
 
   // V0_Near - V0_Far
-  myEdgeDirs[0] = myVertices[0] - myVertices[3];
+  myEdgeDirs[0] = myVertices[0].XYZ() - myVertices[3].XYZ();
   // V1_Near - V1_Far
-  myEdgeDirs[1] = myVertices[1] - myVertices[4];
+  myEdgeDirs[1] = myVertices[1].XYZ() - myVertices[4].XYZ();
   // V2_Near - V1_Far
-  myEdgeDirs[2] = myVertices[2] - myVertices[5];
+  myEdgeDirs[2] = myVertices[2].XYZ() - myVertices[5].XYZ();
   // V1_Near - V0_Near
-  myEdgeDirs[3] = myVertices[1] - myVertices[0];
+  myEdgeDirs[3] = myVertices[1].XYZ() - myVertices[0].XYZ();
   // V2_Near - V1_Near
-  myEdgeDirs[4] = myVertices[2] - myVertices[1];
+  myEdgeDirs[4] = myVertices[2].XYZ() - myVertices[1].XYZ();
   // V1_Near - V0_Near
-  myEdgeDirs[5] = myVertices[2] - myVertices[0];
+  myEdgeDirs[5] = myVertices[2].XYZ() - myVertices[0].XYZ();
+
+  computeFrustumNormals (myEdgeDirs, myPlanes);
+
+  cacheVertexProjections (this);
 }
 
 //=======================================================================
-// function : Transform
-// purpose  : Returns a copy of the frustum transformed according to the matrix given
+// function : ScaleAndTransform
+// purpose  : IMPORTANT: Scaling makes sense only for frustum built on a single point!
+//            Note that this method does not perform any checks on type of the frustum.
+//            Returns a copy of the frustum resized according to the scale factor given
+//            and transforms it using the matrix given.
+//            There are no default parameters, but in case if:
+//                - transformation only is needed: @theScaleFactor must be initialized
+//                  as any negative value;
+//                - scale only is needed: @theTrsf must be set to gp_Identity.
 //=======================================================================
-NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_TriangularFrustum::Transform (const gp_Trsf& theTrsf)
+NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_TriangularFrustum::ScaleAndTransform (const Standard_Integer /*theScale*/,
+                                                                                          const gp_Trsf& theTrsf)
 {
   SelectMgr_TriangularFrustum* aRes = new SelectMgr_TriangularFrustum();
 
   // V0_Near
-  aRes->myVertices[0] = SelectMgr_MatOp::Transform (theTrsf, myVertices[0]);
+  aRes->myVertices[0] = myVertices[0].Transformed (theTrsf);
   // V1_Near
-  aRes->myVertices[1] = SelectMgr_MatOp::Transform (theTrsf, myVertices[1]);
+  aRes->myVertices[1] = myVertices[1].Transformed (theTrsf);
   // V2_Near
-  aRes->myVertices[2] = SelectMgr_MatOp::Transform (theTrsf, myVertices[2]);
+  aRes->myVertices[2] = myVertices[2].Transformed (theTrsf);
   // V0_Far
-  aRes->myVertices[3] = SelectMgr_MatOp::Transform (theTrsf, myVertices[3]);
+  aRes->myVertices[3] = myVertices[3].Transformed (theTrsf);
   // V1_Far
-  aRes->myVertices[4] = SelectMgr_MatOp::Transform (theTrsf, myVertices[4]);
+  aRes->myVertices[4] = myVertices[4].Transformed (theTrsf);
   // V2_Far
-  aRes->myVertices[5] = SelectMgr_MatOp::Transform (theTrsf, myVertices[5]);
+  aRes->myVertices[5] = myVertices[5].Transformed (theTrsf);
 
   aRes->myIsOrthographic = myIsOrthographic;
 
-  computeFrustumNormals (aRes->myVertices, aRes->myPlanes);
-
-  for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx)
-  {
-    Standard_Real aMax = -DBL_MAX;
-    Standard_Real aMin =  DBL_MAX;
-    const SelectMgr_Vec3 aPlane = aRes->myPlanes[aPlaneIdx];
-    for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx)
-    {
-      Standard_Real aProjection = DOT (aPlane, aRes->myVertices[aVertIdx]);
-      aMax = Max (aMax, aProjection);
-      aMin = Min (aMin, aProjection);
-    }
-    aRes->myMaxVertsProjections[aPlaneIdx] = aMax;
-    aRes->myMinVertsProjections[aPlaneIdx] = aMin;
-  }
-
-  SelectMgr_Vec3 aDimensions[3] =
-  {
-    SelectMgr_Vec3 (1.0, 0.0, 0.0),
-    SelectMgr_Vec3 (0.0, 1.0, 0.0),
-    SelectMgr_Vec3 (0.0, 0.0, 1.0)
-  };
-
-  for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
-  {
-    Standard_Real aMax = -DBL_MAX;
-    Standard_Real aMin =  DBL_MAX;
-    for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx)
-    {
-      Standard_Real aProjection = DOT (aDimensions[aDim], aRes->myVertices[aVertIdx]);
-      aMax = Max (aMax, aProjection);
-      aMin = Min (aMin, aProjection);
-    }
-    aRes->myMaxOrthoVertsProjections[aDim] = aMax;
-    aRes->myMinOrthoVertsProjections[aDim] = aMin;
-  }
-
   // V0_Near - V0_Far
-  aRes->myEdgeDirs[0] = aRes->myVertices[0] - aRes->myVertices[3];
+  aRes->myEdgeDirs[0] = aRes->myVertices[0].XYZ() - aRes->myVertices[3].XYZ();
   // V1_Near - V1_Far
-  aRes->myEdgeDirs[1] = aRes->myVertices[1] - aRes->myVertices[4];
+  aRes->myEdgeDirs[1] = aRes->myVertices[1].XYZ() - aRes->myVertices[4].XYZ();
   // V2_Near - V1_Far
-  aRes->myEdgeDirs[2] = aRes->myVertices[2] - aRes->myVertices[5];
+  aRes->myEdgeDirs[2] = aRes->myVertices[2].XYZ() - aRes->myVertices[5].XYZ();
   // V1_Near - V0_Near
-  aRes->myEdgeDirs[3] = aRes->myVertices[1] - aRes->myVertices[0];
+  aRes->myEdgeDirs[3] = aRes->myVertices[1].XYZ() - aRes->myVertices[0].XYZ();
   // V2_Near - V1_Near
-  aRes->myEdgeDirs[4] = aRes->myVertices[2] - aRes->myVertices[1];
+  aRes->myEdgeDirs[4] = aRes->myVertices[2].XYZ() - aRes->myVertices[1].XYZ();
   // V1_Near - V0_Near
-  aRes->myEdgeDirs[5] = aRes->myVertices[2] - aRes->myVertices[0];
+  aRes->myEdgeDirs[5] = aRes->myVertices[2].XYZ() - aRes->myVertices[0].XYZ();
+
+  computeFrustumNormals (aRes->myEdgeDirs, aRes->myPlanes);
+
+  cacheVertexProjections (aRes);
 
   return NCollection_Handle<SelectMgr_BaseFrustum> (aRes);
 }
@@ -203,10 +171,11 @@ NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_TriangularFrustum::Transform
 // purpose  : SAT intersection test between defined volume and
 //            given axis-aligned box
 //=======================================================================
-Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
+Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const SelectMgr_Vec3& theMinPt,
+                                                        const SelectMgr_Vec3& theMaxPt,
                                                         Standard_Real& /*theDepth*/)
 {
-  return hasOverlap (theBox.CornerMin(), theBox.CornerMax());
+  return hasOverlap (theMinPt, theMaxPt);
 }
 
 // =======================================================================
@@ -261,7 +230,7 @@ Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const Handle(TColgp_HArr
   }
   else if (theSensType == Select3D_TOS_INTERIOR)
   {
-    SelectMgr_Vec3 aNorm (RealLast());
+    gp_Vec aNorm (gp_XYZ (RealLast(), RealLast(), RealLast()));
     return hasOverlap (theArrayOfPnts, aNorm);
   }
 
@@ -302,7 +271,7 @@ Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const gp_Pnt& thePnt1,
   }
   else if (theSensType == Select3D_TOS_INTERIOR)
   {
-    SelectMgr_Vec3 aNorm (RealLast());
+    gp_Vec aNorm (gp_XYZ (RealLast(), RealLast(), RealLast()));
     return hasOverlap (thePnt1, thePnt2, thePnt3, aNorm);
   }
 
index a94fc7ec041db71414708167a16741da9a1f602e..e9ced7eb677447becbe082355a7b95ea74609685 100644 (file)
@@ -40,12 +40,14 @@ public:
                       const gp_Pnt2d& theP3) Standard_OVERRIDE;
 
   //! Returns a copy of the frustum transformed according to the matrix given
-  virtual NCollection_Handle<SelectMgr_BaseFrustum> Transform (const gp_Trsf& theTrsf) Standard_OVERRIDE;
+  virtual NCollection_Handle<SelectMgr_BaseFrustum> ScaleAndTransform (const Standard_Integer theScale,
+                                                                       const gp_Trsf& theTrsf) Standard_OVERRIDE;
 
   // SAT Tests for different objects
 
   //! SAT intersection test between defined volume and given axis-aligned box
-  virtual Standard_Boolean Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
+  virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt,
+                                     const SelectMgr_Vec3& theMaxPnt,
                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box
@@ -81,6 +83,10 @@ public:
 
   //! Nullifies the handle to corresponding builder instance to prevent memory leaks
   void Clear();
+
+private:
+
+  void cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum);
 };
 
 #endif // _SelectMgr_TriangularFrustum_HeaderFile
index 2ee203bfb4ed5dca064c00ece2043a991dc8dcfe..dacf33badff3b87cf8d44945d674b45a2dac7830 100644 (file)
@@ -102,17 +102,24 @@ void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoint
 }
 
 // =======================================================================
-// function : Transform
-// purpose  : Returns a copy of the frustum with all sub-volumes transformed
-//            according to the matrix given
-// =======================================================================
-NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_TriangularFrustumSet::Transform (const gp_Trsf& theTrsf)
+// function : ScaleAndTransform
+// purpose  : IMPORTANT: Scaling makes sense only for frustum built on a single point!
+//            Note that this method does not perform any checks on type of the frustum.
+//            Returns a copy of the frustum resized according to the scale factor given
+//            and transforms it using the matrix given.
+//            There are no default parameters, but in case if:
+//                - transformation only is needed: @theScaleFactor must be initialized
+//                  as any negative value;
+//                - scale only is needed: @theTrsf must be set to gp_Identity.
+// =======================================================================
+NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_TriangularFrustumSet::ScaleAndTransform (const Standard_Integer theScale,
+                                                                                             const gp_Trsf& theTrsf)
 {
   SelectMgr_TriangularFrustumSet* aRes = new SelectMgr_TriangularFrustumSet();
 
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
-    aRes->myFrustums.Append (NCollection_Handle<SelectMgr_TriangularFrustum>::DownCast (anIter.Value()->Transform (theTrsf)));
+    aRes->myFrustums.Append (NCollection_Handle<SelectMgr_TriangularFrustum>::DownCast (anIter.Value()->ScaleAndTransform (theScale, theTrsf)));
   }
 
   return NCollection_Handle<SelectMgr_BaseFrustum> (aRes);
@@ -122,12 +129,13 @@ NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_TriangularFrustumSet::Transf
 // function : Overlaps
 // purpose  :
 // =======================================================================
-Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
+Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const SelectMgr_Vec3& theMinPnt,
+                                                           const SelectMgr_Vec3& theMaxPnt,
                                                            Standard_Real& theDepth)
 {
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
-    if (anIter.Value()->Overlaps (theBox, theDepth))
+    if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt, theDepth))
       return Standard_True;
   }
 
index 8003d4f140617719f7734befa21c3dab01e4678d..6b7b97805c2d346d63a835f991770dca9ca11cb6 100644 (file)
@@ -48,29 +48,31 @@ public:
   virtual void Build (const TColgp_Array1OfPnt2d& thePoints) Standard_OVERRIDE;
 
   //! Returns a copy of the frustum with all sub-volumes transformed according to the matrix given
-  virtual NCollection_Handle<SelectMgr_BaseFrustum> Transform (const gp_Trsf& theTrsf) Standard_OVERRIDE;
+  virtual NCollection_Handle<SelectMgr_BaseFrustum> ScaleAndTransform (const Standard_Integer theScale,
+                                                                       const gp_Trsf& theTrsf) Standard_OVERRIDE;
 
-  virtual Standard_Boolean Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
+  virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt,
+                                     const SelectMgr_Vec3& theMaxPnt,
                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
   virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt,
                                      const SelectMgr_Vec3& theMaxPnt,
                                      Standard_Boolean* theInside) Standard_OVERRIDE;
 
-  virtual Standard_Boolean Overlaps (const gp_Pnt& thePt,
+  virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt,
                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
-  virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts,
+  virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
                                      Select3D_TypeOfSensitivity theSensType,
                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
-  virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1,
-                                     const gp_Pnt& thePt2,
+  virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1,
+                                     const gp_Pnt& thePnt2,
                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
-  virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1,
-                                     const gp_Pnt& thePt2,
-                                     const gp_Pnt& thePt3,
+  virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1,
+                                     const gp_Pnt& thePnt2,
+                                     const gp_Pnt& thePnt3,
                                      Select3D_TypeOfSensitivity theSensType,
                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
index 8a5190f7f73e756044dcddb64c292396729210bb..2675b45332cbcdb68a67391c84be607e4977a158 100644 (file)
@@ -45,8 +45,8 @@ IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, MMgt_TShared)
 //=======================================================================
 SelectMgr_ToleranceMap::SelectMgr_ToleranceMap()
 {
-  myLargestKey = -1.0;
-  myCustomTolerance = -1.0;
+  myLargestKey = 2;
+  myCustomTolerance = -1;
 }
 
 //=======================================================================
@@ -63,7 +63,7 @@ SelectMgr_ToleranceMap::~SelectMgr_ToleranceMap()
 // purpose : Adds the value given to map, checks if the current tolerance value
 //           should be replaced by theTolerance
 //=======================================================================
-void SelectMgr_ToleranceMap::Add (const Standard_Real& theTolerance)
+void SelectMgr_ToleranceMap::Add (const Standard_Integer& theTolerance)
 {
   if (myTolerances.IsBound (theTolerance))
   {
@@ -92,7 +92,7 @@ void SelectMgr_ToleranceMap::Add (const Standard_Real& theTolerance)
 // purpose : Decrements a counter of the tolerance given, checks if the current tolerance value
 //           should be recalculated
 //=======================================================================
-void SelectMgr_ToleranceMap::Decrement (const Standard_Real& theTolerance)
+void SelectMgr_ToleranceMap::Decrement (const Standard_Integer& theTolerance)
 {
   if (myTolerances.IsBound (theTolerance))
   {
@@ -101,8 +101,8 @@ void SelectMgr_ToleranceMap::Decrement (const Standard_Real& theTolerance)
 
     if (Abs (theTolerance - myLargestKey) < Precision::Confusion() && aFreq == 0)
     {
-      myLargestKey = 0.0;
-      for (NCollection_DataMap<Standard_Real, Standard_Integer>::Iterator anIter (myTolerances); anIter.More(); anIter.Next())
+      myLargestKey = 0;
+      for (NCollection_DataMap<Standard_Integer, Standard_Integer>::Iterator anIter (myTolerances); anIter.More(); anIter.Next())
       {
         if (anIter.Value() != 0)
           myLargestKey = Max (myLargestKey, anIter.Key());
@@ -115,16 +115,16 @@ void SelectMgr_ToleranceMap::Decrement (const Standard_Real& theTolerance)
 // function: Tolerance
 // purpose : Returns a current tolerance that must be applied
 //=======================================================================
-Standard_Real SelectMgr_ToleranceMap::Tolerance()
+Standard_Integer SelectMgr_ToleranceMap::Tolerance() const
 {
-  return myCustomTolerance < 0.0 ? myLargestKey : myCustomTolerance;
+  return myCustomTolerance < 0 ? myLargestKey : myCustomTolerance;
 }
 
 //=======================================================================
 // function: SetCustomTolerance
 // purpose : Sets tolerance to the given one and disables adaptive checks
 //=======================================================================
-void SelectMgr_ToleranceMap::SetCustomTolerance (const Standard_Real theTolerance)
+void SelectMgr_ToleranceMap::SetCustomTolerance (const Standard_Integer theTolerance)
 {
   myCustomTolerance = theTolerance;
 }
@@ -135,7 +135,7 @@ void SelectMgr_ToleranceMap::SetCustomTolerance (const Standard_Real theToleranc
 //=======================================================================
 void SelectMgr_ToleranceMap::ResetDefaults()
 {
-  myCustomTolerance = -1.0;
+  myCustomTolerance = -1;
 }
 
 //==================================================
@@ -144,7 +144,6 @@ void SelectMgr_ToleranceMap::ResetDefaults()
 //==================================================
 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
 preferclosest(Standard_True),
-mytolerance(2.0),
 myToUpdateTolerance (Standard_True),
 myCurRank (0),
 myIsLeftChildQueuedFirst (Standard_False),
@@ -168,7 +167,6 @@ void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theS
   theSelection->SetSelectionState (SelectMgr_SOS_Activated);
 
   myTolerances.Add (theSelection->Sensitivity());
-  mytolerance = myTolerances.Tolerance();
   myToUpdateTolerance = Standard_True;
 }
 
@@ -187,7 +185,6 @@ void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& th
   theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
 
   myTolerances.Decrement (theSelection->Sensitivity());
-  mytolerance = myTolerances.Tolerance();
   myToUpdateTolerance = Standard_True;
 }
 
@@ -211,29 +208,6 @@ Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select
     && theEntity->SensitivityFactor() < myTolerances.Tolerance();
 }
 
-//=======================================================================
-// function: scaleAndTransform
-// purpose : Applies given scale and transformation matrices to the default selecting volume manager
-//=======================================================================
-SelectMgr_SelectingVolumeManager SelectMgr_ViewerSelector::scaleAndTransform (const Standard_Real theScale,
-                                                                              const gp_Trsf& theTrsf)
-{
-  SelectMgr_SelectingVolumeManager aMgr;
-
-  if (theScale > Precision::Angular())
-  {
-    aMgr = mySelectingVolumeMgr.Scale (theScale);
-  }
-
-  if (theTrsf.Form() != gp_Identity)
-  {
-    aMgr = aMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Unknown ?
-      mySelectingVolumeMgr.Transform (theTrsf) : aMgr.Transform (theTrsf);
-  }
-
-  return aMgr;
-}
-
 //=======================================================================
 // function: checkOverlap
 // purpose : Internal function that checks if a particular sensitive
@@ -261,7 +235,7 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive
 
       Standard_Integer aPriority = anOwner->Priority();
 
-      SelectMgr_SortCriterion aCriterion (aPriority, aPickResult.Depth(), aPickResult.DistToGeomCenter(), theEntity->SensitivityFactor() / 33, preferclosest);
+      SelectMgr_SortCriterion aCriterion (aPriority, aPickResult.Depth(), aPickResult.DistToGeomCenter(), theEntity->SensitivityFactor() / 33.0, preferclosest);
       if (mystored.Contains (anOwner))
       {
         if (theMgr.GetActiveSelectionType() != 1)
@@ -283,6 +257,40 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive
   }
 }
 
+//=======================================================================
+// function: computeFrustum
+// purpose : Internal function that checks if a current selecting frustum
+//           needs to be scaled and transformed for the entity and performs
+//           necessary calculations
+//=======================================================================
+void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt,
+                                               const gp_Trsf&                              theInvTrsf,
+                                               SelectMgr_FrustumCache&                     theCachedMgrs,
+                                               SelectMgr_SelectingVolumeManager&           theResMgr)
+{
+  Standard_Integer aScale = 1;
+  const Standard_Boolean toScale = isToScaleFrustum (theEnt);
+  if (toScale)
+  {
+    aScale = theEnt->SensitivityFactor();
+  }
+  if (theEnt->HasInitLocation())
+  {
+    theResMgr =
+      mySelectingVolumeMgr.ScaleAndTransform (aScale, theEnt->InvInitLocation() * theInvTrsf);
+  }
+  else if (toScale)
+  {
+    if (!theCachedMgrs.IsBound (aScale))
+    {
+      theCachedMgrs.Bind (aScale,
+        mySelectingVolumeMgr.ScaleAndTransform(aScale, theInvTrsf));
+    }
+
+    theResMgr = theCachedMgrs.Find (aScale);
+  }
+}
+
 //=======================================================================
 // function: traverseObject
 // purpose : Internal function that checks if there is possible overlap
@@ -300,9 +308,9 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
   const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
 
   SelectMgr_SelectingVolumeManager aMgr = theObject->HasTransformation() ?
-    mySelectingVolumeMgr.Transform (theObject->InversedTransformation()) : mySelectingVolumeMgr;
+    mySelectingVolumeMgr.ScaleAndTransform (1, theObject->InversedTransformation()) : mySelectingVolumeMgr;
 
-  NCollection_DataMap<Handle(Standard_Type), SelectMgr_SelectingVolumeManager> aScaledTrnsfFrustums;
+  SelectMgr_FrustumCache aScaledTrnsfFrustums;
 
   Standard_Integer aNode = 0; // a root node
   if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
@@ -357,16 +365,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
         {
           const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
           SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
-          if (isToScaleFrustum (anEnt))
-          {
-            if (!aScaledTrnsfFrustums.IsBound (anEnt->DynamicType()))
-            {
-              aScaledTrnsfFrustums.Bind (anEnt->DynamicType(),
-                                         scaleAndTransform (anEnt->SensitivityFactor(), theObject->InversedTransformation()));
-            }
-
-            aTmpMgr = aScaledTrnsfFrustums.Find (anEnt->DynamicType());
-          }
+          computeFrustum (anEnt, theObject->InversedTransformation(), aScaledTrnsfFrustums, aTmpMgr);
           checkOverlap (anEnt, anIdx, aTmpMgr);
         }
       }
index 0d95e77fd319ff03eb2f5c9f877ef556bc194b52..f4b865657ce6a01eefb16536fc8d72eb23558483 100644 (file)
@@ -57,6 +57,8 @@ typedef NCollection_DataMap<Handle(SelectMgr_SelectableObject), NCollection_Hand
 typedef NCollection_DataMap<Handle(SelectMgr_EntityOwner), Standard_Integer> SelectMgr_MapOfOwnerDetectedEntities;
 typedef NCollection_DataMap<Handle(SelectMgr_EntityOwner), Standard_Integer>::Iterator SelectMgr_MapOfOwnerDetectedEntitiesIterator;
 
+typedef NCollection_DataMap<Standard_Integer, SelectMgr_SelectingVolumeManager> SelectMgr_FrustumCache;
+
 //! An internal class for calculation of current largest tolerance value which will be applied
 //! for creation of selecting frustum by default. Each time the selection set is deactivated,
 //! maximum tolerance value will be recalculated. If a user enables custom precision using
@@ -73,25 +75,25 @@ public:
 
   //! Adds the value given to map, checks if the current tolerance value
   //! should be replaced by theTolerance
-  Standard_EXPORT void Add (const Standard_Real& theTolerance);
+  Standard_EXPORT void Add (const Standard_Integer& theTolerance);
 
   //! Decrements a counter of the tolerance given, checks if the current tolerance value
   //! should be recalculated
-  Standard_EXPORT void Decrement (const Standard_Real& theTolerance);
+  Standard_EXPORT void Decrement (const Standard_Integer& theTolerance);
 
   //! Returns a current tolerance that must be applied
-  Standard_EXPORT Standard_Real Tolerance();
+  Standard_EXPORT Standard_Integer Tolerance() const;
 
   //! Sets tolerance to the given one and disables adaptive checks
-  Standard_EXPORT void SetCustomTolerance (const Standard_Real theTolerance);
+  Standard_EXPORT void SetCustomTolerance (const Standard_Integer theTolerance);
 
   //! Unsets a custom tolerance and enables adaptive checks
   Standard_EXPORT void ResetDefaults();
 
 private:
-  NCollection_DataMap<Standard_Real, Standard_Integer> myTolerances;
-  Standard_Real                                        myLargestKey;
-  Standard_Real                                        myCustomTolerance;
+  NCollection_DataMap<Standard_Integer, Standard_Integer> myTolerances;
+  Standard_Integer                                        myLargestKey;
+  Standard_Integer                                        myCustomTolerance;
 };
 
 //! A framework to define finding, sorting the sensitive
@@ -132,7 +134,7 @@ public:
   Standard_EXPORT void Clear();
 
   //! returns the Sensitivity of picking
-  Standard_Real Sensitivity() const;
+  Standard_Integer Sensitivity() const;
 
   //! Sorts the detected entites by priority and distance.
   //!          to be redefined if other criterion are used...
@@ -283,10 +285,6 @@ protected:
   //! Checks if the entity given requires to scale current selecting frustum
   Standard_Boolean isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity);
 
-  //! Applies given scale and transformation matrices to the default selecting volume manager
-  SelectMgr_SelectingVolumeManager scaleAndTransform (const Standard_Real theScale,
-                                                      const gp_Trsf& theTrsf);
-
 private:
 
   void Activate (const Handle(SelectMgr_Selection)& theSelection);
@@ -296,10 +294,17 @@ private:
   //! removes a Selection from the Selector
   void Remove (const Handle(SelectMgr_Selection)& aSelection);
 
+  //! Internal function that checks if a current selecting frustum
+  //! needs to be scaled and transformed for the entity and performs
+  //! necessary calculations
+  void computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt,
+                       const gp_Trsf&                              theInvTrsf,
+                       SelectMgr_FrustumCache&                     theCachedMgrs,
+                       SelectMgr_SelectingVolumeManager&           theResMgr);
+
 protected:
 
   Standard_Boolean preferclosest;
-  Standard_Real mytolerance;
   Standard_Boolean myToUpdateTolerance;
   SelectMgr_IndexedDataMapOfOwnerCriterion mystored;
   SelectMgr_SelectingVolumeManager mySelectingVolumeMgr;
index 3f9c99183a45d83055e8ff0b6782beec353348b2..70c4ab04dec712dfaa817dc31789cf3664bb1579 100644 (file)
@@ -12,9 +12,9 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-inline Standard_Real SelectMgr_ViewerSelector::Sensitivity() const
+inline Standard_Integer SelectMgr_ViewerSelector::Sensitivity() const
 {
-  return mytolerance;
+  return myTolerances.Tolerance();
 }
 
 inline void SelectMgr_ViewerSelector::Init() 
index 3c0967bb07a64e51efc188138a09813544c77cc3..0862b34903a0e55e6b207ba5063661ef4aafdf8e 100644 (file)
@@ -93,15 +93,14 @@ StdSelect_ViewerSelector3d::StdSelect_ViewerSelector3d() {}
 // Function: SetPixelTolerance
 // Purpose :
 //=======================================================================
-void StdSelect_ViewerSelector3d::SetPixelTolerance (const Standard_Real theTolerance)
+void StdSelect_ViewerSelector3d::SetPixelTolerance (const Standard_Integer theTolerance)
 {
-  if (mytolerance != theTolerance)
+  if (myTolerances.Tolerance() != theTolerance)
   {
-    if (theTolerance < 0.0)
+    if (theTolerance < 0)
       myTolerances.ResetDefaults();
     else
       myTolerances.SetCustomTolerance (theTolerance);
-    mytolerance = myTolerances.Tolerance();
     myToUpdateTolerance = Standard_True;
   }
 }
@@ -118,7 +117,7 @@ void StdSelect_ViewerSelector3d::Pick (const Standard_Integer theXPix,
 
   if(myToUpdateTolerance)
   {
-    mySelectingVolumeMgr.SetPixelTolerance (mytolerance);
+    mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance());
     myToUpdateTolerance = Standard_False;
   }
 
index 86407bcfd5ea6fb7a9ef38b250099e269f22e528..1970cd9c423483b64f4c3564714ba35e67b2f278 100644 (file)
@@ -48,10 +48,10 @@ public:
   Standard_EXPORT StdSelect_ViewerSelector3d();
 
   //! Sets the pixel tolerance <theTolerance>.
-  Standard_EXPORT void SetPixelTolerance (const Standard_Real theTolerance);
+  Standard_EXPORT void SetPixelTolerance (const Standard_Integer theTolerance);
 
   //! Returns the pixel tolerance.
-  Standard_Real PixelTolerance() const;
+  inline Standard_Integer PixelTolerance() const;
 
   //! Picks the sensitive entity at the pixel coordinates of
   //! the mouse <theXPix> and <theYPix>. The selector looks for touched areas and owners.
index c29b73307048aa135d1a98b98bc507a2028854e7..6f941d935367b2f269d93ec0f0fb058b24119e4e 100644 (file)
@@ -12,7 +12,7 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-inline Standard_Real StdSelect_ViewerSelector3d::PixelTolerance() const
+inline Standard_Integer StdSelect_ViewerSelector3d::PixelTolerance() const
 {
-  return mytolerance;
+  return myTolerances.Tolerance();
 }
index dc78b59bd2d89ff3ac0a483c42e6a82b0b2b6466..36b0fcb5d7b835a90bb2f50fa62cb7022fbcbe8b 100644 (file)
@@ -768,11 +768,11 @@ static int VSelPrecision(Draw_Interpretor& di, Standard_Integer argc, const char
     anArg.LowerCase();
     if (anArg == "-unset")
     {
-      aContext->SetPixelTolerance (-1.0);
+      aContext->SetPixelTolerance (-1);
     }
     else
     {
-      aContext->SetPixelTolerance (anArg.RealValue());
+      aContext->SetPixelTolerance (anArg.IntegerValue());
     }
   }
 
@@ -4278,11 +4278,12 @@ static Standard_Integer VState (Draw_Interpretor& theDI,
       const Handle(SelectBasics_SensitiveEntity)& anEntity = aSelector->DetectedEntity();
       Handle(SelectMgr_EntityOwner) anOwner    = Handle(SelectMgr_EntityOwner)::DownCast (anEntity->OwnerId());
       Handle(AIS_InteractiveObject) anObj      = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
-      SelectMgr_SelectingVolumeManager aMgr = anObj->HasTransformation() ? aSelector->GetManager().Transform (anObj->InversedTransformation())
-                                                                         : aSelector->GetManager();
+      SelectMgr_SelectingVolumeManager aMgr =
+        anObj->HasTransformation() ? aSelector->GetManager().ScaleAndTransform (1, anObj->InversedTransformation())
+                                   : aSelector->GetManager();
       SelectBasics_PickResult aResult;
       anEntity->Matches (aMgr, aResult);
-      NCollection_Vec3<Standard_Real> aDetectedPnt = aMgr.DetectedPoint (aResult.Depth());
+      gp_Pnt aDetectedPnt = aMgr.DetectedPoint (aResult.Depth());
 
       TCollection_AsciiString aName = GetMapOfAIS().Find1 (anObj);
       aName.LeftJustify (20, ' ');
@@ -4291,7 +4292,7 @@ static Standard_Integer VState (Draw_Interpretor& theDI,
                " Depth: %+.3f Distance: %+.3f Point: %+.3f %+.3f %+.3f",
                aResult.Depth(),
                aResult.DistToGeomCenter(),
-               aDetectedPnt.x(), aDetectedPnt.y(), aDetectedPnt.z());
+               aDetectedPnt.X(), aDetectedPnt.Y(), aDetectedPnt.Z());
       theDI << "  " << aName
             << anInfoStr
             << " (" << anEntity->DynamicType()->Name() << ")"
index a775fdb70a17b3045387bb8e9c41924b96f211c5..6251d4665f57723c1deecc33151274f696e6fcb6 100644 (file)
@@ -101,6 +101,17 @@ is
         ---C++: inline
         ---Purpose: Returns the Z coordinate
 
+  Ptr (me) returns Real
+        --- Purpose : Returns a const ptr to coordinates location.
+        --            Is useful for algorithms, but DOES NOT PERFORM ANY CHECKS!
+        ---C++: return const *
+     is static;
+
+  Ptr (me : in out) returns Real;
+        --- Purpose : Returns a ptr to coordinates location.
+        --            Is useful for algorithms, but DOES NOT PERFORM ANY CHECKS!
+        ---C++: return *
+
   Modulus (me)         returns Real    is static;
         --- Purpose : computes Sqrt (X*X + Y*Y + Z*Z) where X, Y and Z are the three coordinates of this XYZ object.
         ---C++: inline
index 9a9ed2a754ad97746ca47f359bf3ed2b68d1e139..144e3b531d0f0b271f492f71824562d69eae67e1 100644 (file)
@@ -304,8 +304,6 @@ inline gp_XYZ operator* (const Standard_Real Scalar, const gp_XYZ& Coord1) {
   return Coord1.Multiplied (Scalar);
 }
 
+inline const Standard_Real* gp_XYZ::Ptr() const { return (&x); }
 
-
-
-
-
+inline Standard_Real* gp_XYZ::Ptr() { return (&x); }