0026195: Visualization - optimize selection algorithms
authorvpa <vpa@opencascade.com>
Mon, 31 Aug 2015 07:29:53 +0000 (10:29 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 10 Sep 2015 12:00:04 +0000 (15:00 +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.

50 files changed:
src/AIS/AIS_InteractiveContext.cxx
src/AIS/AIS_InteractiveContext.hxx
src/AIS/AIS_LocalContext.cxx
src/AIS/AIS_LocalContext.hxx
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.cxx
src/SelectBasics/SelectBasics_SensitiveEntity.hxx
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_SelectableObjectSet.hxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx
src/SelectMgr/SelectMgr_Selection.cxx
src/SelectMgr/SelectMgr_Selection.hxx
src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx
src/SelectMgr/SelectMgr_SensitiveEntitySet.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.hxx

index fb959a1..10da2d2 100644 (file)
@@ -2705,7 +2705,7 @@ Standard_Boolean AIS_InteractiveContext::IsoOnTriangulation() const
 //           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())
   {
@@ -2721,7 +2721,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()
@@ -2786,7 +2786,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 443ed2e..bb711b9 100644 (file)
@@ -367,10 +367,10 @@ public:
   //! SelectMgr_ViewerSelector documentation
   //! Warning: When a local context is open the sensitivity is apply on it
   //! instead on the main context.
-  Standard_EXPORT void SetPixelTolerance (const Standard_Real aPrecision = 2.0);
+  Standard_EXPORT void SetPixelTolerance (const Standard_Integer aPrecision = 2);
   
   //! Returns the pixel tolerance.
-  Standard_EXPORT Standard_Real PixelTolerance() const;
+  Standard_EXPORT Standard_Integer PixelTolerance() const;
   
   //! Puts the location aLocation on the initial graphic
   //! representation and the selection for the entity aniobj.
index a296010..6505689 100644 (file)
@@ -1144,12 +1144,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 9632734..6a4c66f 100644 (file)
@@ -313,10 +313,10 @@ public:
   
   //! Define the current selection sensitivity for
   //! this local context according to the view size.
-  Standard_EXPORT void SetPixelTolerance (const Standard_Real aPrecision = 2);
+  Standard_EXPORT void SetPixelTolerance (const Standard_Integer aPrecision = 2);
   
   //! Returns the pixel tolerance.
-  Standard_EXPORT Standard_Real PixelTolerance() const;
+  Standard_EXPORT Standard_Integer PixelTolerance() const;
   
   //! Resets the transient list of presentations previously displayed in immediate mode
   //! and begins accumulation of new list by following AddToImmediateList()/Color()/Highlight() calls.
index 06f4e80..c62efe3 100644 (file)
@@ -69,3 +69,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 f8ab375..f4bf501 100644 (file)
@@ -47,6 +47,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, SelectBasics_SensitiveEntity)
 };
 
index 2b3f6e2..b9a02cb 100644 (file)
@@ -3923,6 +3923,117 @@ static Standard_Integer OCC26553 (Draw_Interpretor& theDI, Standard_Integer theA
   return 0;
 }
 
+//=======================================================================
+//function : OCC26195
+//purpose  :
+//=======================================================================
+#include <SelectMgr_SelectingVolumeManager.hxx>
+#include <BRepBuilderAPI_MakePolygon.hxx>
+#include <Geom_CartesianPoint.hxx>
+#include <AIS_Line.hxx>
+#include <Aspect_Window.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";
 
@@ -3999,5 +4110,13 @@ void QABugs::Commands_19(Draw_Interpretor& theCommands) {
   theCommands.Add ("OCC26407", "OCC26407 result_name", __FILE__, OCC26407, group);
   theCommands.Add ("OCC26485", "OCC26485 shape", __FILE__, OCC26485, group);
   theCommands.Add ("OCC26553", "OCC26553 file_path", __FILE__, OCC26553, group);
+  theCommands.Add ("OCC26195",
+                   "OCC26195: x1_pix y1_pix [x2_pix y2_pix] [toPrintPixelCoord 0|1]"
+                   "\n\t\t: Draws rectangular selecting frustum defined by point selection in pixel coordinates"
+                   "\n\t\t: [x1_pix, y1_pix] or rectangular selection in pixel coordinates [x1_pix, y1_pix,"
+                   "\n\t\t: x2_pix, y2_pix]."
+                   "\n\t\t: [toPrintPixelCoord 0|1] - prints 3d projection of pixel coordinate or center of"
+                   "\n\t\t: selecting rectangle onto near and far view frustum planes",
+                   __FILE__, OCC26195, group);
   return;
 }
index 060fb12..5598d4f 100644 (file)
@@ -98,7 +98,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 cf8623a..77a5cb1 100644 (file)
@@ -106,7 +106,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_Ent
 
   if (mySensType == Select3D_TOS_BOUNDARY)
   {
-    SetSensitivityFactor (6.0);
+    SetSensitivityFactor (6);
   }
 }
 
@@ -164,7 +164,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle (const Handle(SelectBasics_En
 
   if (mySensType == Select3D_TOS_BOUNDARY)
   {
-    SetSensitivityFactor (6.0);
+    SetSensitivityFactor (6);
   }
 }
 
@@ -175,7 +175,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, (Standard_Boolean )!theIsFilled),
+: Select3D_SensitivePoly (theOwnerId, thePnts3d, static_cast<Standard_Boolean> (!theIsFilled)),
   myStart (0),
   myEnd (0)
 {
@@ -188,7 +188,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_Ent
 
   if (mySensType == Select3D_TOS_BOUNDARY)
   {
-    SetSensitivityFactor (6.0);
+    SetSensitivityFactor (6);
   }
 }
 
@@ -213,7 +213,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_Ent
 
   if (mySensType == Select3D_TOS_BOUNDARY)
   {
-    SetSensitivityFactor (6.0);
+    SetSensitivityFactor (6);
   }
 }
 
@@ -256,8 +256,7 @@ Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolume
       thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
       for (Standard_Integer aPntIdx = anArrayOfPnt->Lower(); aPntIdx <= anArrayOfPnt->Upper(); ++aPntIdx)
       {
-        Standard_Real aDummy;
-        if (!theMgr.Overlaps (anArrayOfPnt->Value (aPntIdx), aDummy))
+        if (!theMgr.Overlaps (anArrayOfPnt->Value (aPntIdx)))
           return Standard_False;
       }
       return Standard_True;
index 639e2de..eb9d6b6 100644 (file)
@@ -30,7 +30,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti
   myCurve (theCurve)
 {
   loadPoints (theCurve, theNbPnts);
-  SetSensitivityFactor (3.0);
+  SetSensitivityFactor (3);
 }
 
 //==================================================
@@ -42,7 +42,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti
 : Select3D_SensitivePoly (theOwnerId, thePoints, Standard_True)
 
 {
-  SetSensitivityFactor (3.0);
+  SetSensitivityFactor (3);
 }
 
 //==================================================
@@ -53,7 +53,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 75c99e2..c421f70 100644 (file)
 
 //=======================================================================
 //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) {}
 
 //=======================================================================
@@ -69,3 +68,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 9d6f312..8228d49 100644 (file)
@@ -78,6 +78,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, SelectBasics_SensitiveEntity)
 
 protected:
index 4a6377d..758b7b9 100644 (file)
@@ -27,7 +27,7 @@ Select3D_SensitivePoint::Select3D_SensitivePoint (const Handle(SelectBasics_Enti
                                                   const gp_Pnt& thePoint)
 : Select3D_SensitiveEntity (theOwner)
 {
-  SetSensitivityFactor (12.0);
+  SetSensitivityFactor (12);
   myPoint = thePoint;
 }
 
index d4733ba..3652bbd 100644 (file)
@@ -248,9 +248,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 9e6dfb7..c3dd5c2 100644 (file)
@@ -52,10 +52,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 3f8f32b..914d3de 100644 (file)
@@ -54,6 +54,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();
@@ -146,6 +147,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);
@@ -185,19 +187,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())),
@@ -210,10 +208,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()),
@@ -264,17 +260,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);
@@ -286,12 +279,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);
   }
 }
@@ -303,8 +293,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)
@@ -312,13 +300,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
   {
@@ -332,16 +314,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);
   }
 }
 
@@ -388,7 +363,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()));
       }
     }
@@ -429,7 +404,7 @@ Select3D_BndBox3d Select3D_SensitiveTriangulation::BoundingBox()
 //=======================================================================
 gp_Pnt Select3D_SensitiveTriangulation::CenterOfGeometry() const
 {
-  return HasInitLocation() ? myCDG3D.Transformed (myInitLocation) : myCDG3D;
+  return myCDG3D;
 }
 
 //=======================================================================
@@ -439,4 +414,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 a6b2741..d2cdcb4 100644 (file)
@@ -78,10 +78,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;
 
@@ -105,6 +101,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, Select3D_SensitiveSet)
 
@@ -129,20 +134,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 4da2197..9898e4b 100644 (file)
@@ -24,15 +24,6 @@ inline const Handle(Poly_Triangulation)& Select3D_SensitiveTriangulation::Triang
 }
 
 //=======================================================================
-//function : HasInitLocation
-//purpose  :
-//=======================================================================
-inline Standard_Boolean Select3D_SensitiveTriangulation::HasInitLocation() const
-{
-  return !myInitLocation.IsIdentity();
-}
-
-//=======================================================================
 //function : GetInitLocation
 //purpose  :
 //=======================================================================
index 316714f..bb17a15 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;
@@ -43,7 +43,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
@@ -52,10 +53,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,
@@ -80,7 +86,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 7674be7..eea5694 100644 (file)
 // function : SelectBasics_SensitiveEntity
 // purpose  : Creates new empty sensitive entity instance
 //=======================================================================
-SelectBasics_SensitiveEntity::SelectBasics_SensitiveEntity (const Handle(SelectBasics_EntityOwner)& theOwnerId,
-                                                            const Standard_Real theSensFactor)
+SelectBasics_SensitiveEntity::SelectBasics_SensitiveEntity (const Handle(SelectBasics_EntityOwner)& theOwnerId)
 : myOwnerId (theOwnerId),
-  mySFactor (theSensFactor) {}
+  mySFactor (2) {}
 
 //=======================================================================
 // function : Set
index 567d055..75897ad 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef _SelectBasics_SensitiveEntity_HeaderFile
 #define _SelectBasics_SensitiveEntity_HeaderFile
 
+#include <gp_Trsf.hxx>
+
 #include <Standard.hxx>
 #include <Standard_Type.hxx>
 
@@ -27,6 +29,7 @@
 #include <SelectBasics_PickResult.hxx>
 #include <Standard_Integer.hxx>
 #include <Select3D_BndBox3d.hxx>
+
 class SelectBasics_EntityOwner;
 
 
@@ -49,51 +52,51 @@ public:
   
   //! Checks whether the sensitive entity is overlapped by
   //! current selecting volume
-  Standard_EXPORT virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr, SelectBasics_PickResult& thePickResult) = 0;
+  virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr, SelectBasics_PickResult& thePickResult) = 0;
   
   //! allows a better sensitivity for
   //! a specific entity in selection algorithms
   //! useful for small sized entities.
-  Standard_EXPORT Standard_Real SensitivityFactor() const;
+  Standard_EXPORT Standard_Integer SensitivityFactor() const;
   
   //! Returns the number of sub-entities or elements in
   //! sensitive entity. Is used to determine if entity is
   //! complex and needs to pre-build BVH at the creation of
   //! sensitive entity step or is light-weighted so the tree
   //! can be build on demand with unnoticeable delay
-  Standard_EXPORT virtual Standard_Integer NbSubElements() = 0;
+  virtual Standard_Integer NbSubElements() = 0;
   
   //! Returns bounding box of sensitive entity
-  Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() = 0;
+  virtual Select3D_BndBox3d BoundingBox() = 0;
   
   //! Builds BVH tree for sensitive if it is needed
-  Standard_EXPORT virtual void BVH() = 0;
+  virtual void BVH() = 0;
   
   //! Clears up all the resources and memory allocated
-  Standard_EXPORT virtual void Clear() = 0;
-
+  virtual void Clear() = 0;
 
+  //! Returns true if the shape corresponding to the entity has init location
+  virtual Standard_Boolean HasInitLocation() const = 0;
 
+  //! Returns inversed location transformation matrix if the shape corresponding
+  //! to this entity has init location set. Otherwise, returns identity matrix.
+  virtual gp_Trsf InvInitLocation() const = 0;
 
   DEFINE_STANDARD_RTTI(SelectBasics_SensitiveEntity,MMgt_TShared)
 
 protected:
 
-  
-  Standard_EXPORT SelectBasics_SensitiveEntity(const Handle(SelectBasics_EntityOwner)& theOwnerId, const Standard_Real theSensFactor = 2.0);
-  
+  Standard_EXPORT SelectBasics_SensitiveEntity (const Handle(SelectBasics_EntityOwner)& theOwnerId);
+
   //! Allows to manage the sensitivity of the entity
-    void SetSensitivityFactor (const Standard_Real theSensFactor);
+    void SetSensitivityFactor (const Standard_Integer theSensFactor);
 
   Handle(SelectBasics_EntityOwner) myOwnerId;
 
 
 private:
 
-
-  Standard_Real mySFactor;
-
-
+  Standard_Integer mySFactor;
 };
 
 
index 54df66f..380ceb1 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 6d22437..0adc049 100644 (file)
@@ -101,7 +101,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;
 }
@@ -130,7 +130,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;
@@ -151,7 +152,7 @@ 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;
@@ -159,12 +160,21 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePt*/,
 
 //=======================================================================
 // 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
 //            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
 //=======================================================================
-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*/)
 {
@@ -191,8 +201,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;
@@ -208,9 +218,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 96e9a59..4a12323 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>
 
@@ -67,7 +65,7 @@ public:
   //! @return current camera world view projection transformation state
   Standard_EXPORT const Graphic3d_WorldViewProjState& WorldViewProjState() const;
 
-  Standard_EXPORT void SetPixelTolerance (const Standard_Real theTol);
+  Standard_EXPORT void SetPixelTolerance (const Standard_Integer theTol);
 
   Standard_EXPORT void SetWindowSize (const Standard_Integer theWidth, 
                                       const Standard_Integer theHeight);
@@ -97,14 +95,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
-  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);
 
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box
@@ -114,19 +117,25 @@ public:
                                                      Standard_Boolean*     theInside = NULL);
 
   //! 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);
 
+  //! 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
-  Standard_EXPORT virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts,
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
                                                      Select3D_TypeOfSensitivity theSensType,
                                                      Standard_Real& theDepth);
 
   //! 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);
 
   //! SAT intersection test between defined volume and given triangle. The test may
@@ -142,7 +151,7 @@ public:
   //! screen point and given point theCOG
   Standard_EXPORT virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG);
 
-  Standard_EXPORT virtual SelectMgr_Vec3 DetectedPoint (const Standard_Real theDepth) const;
+  Standard_EXPORT 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
@@ -152,8 +161,8 @@ public:
   DEFINE_STANDARD_RTTI(SelectMgr_BaseFrustum, Standard_Transient)
 
 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 a2b5c36..e73aef8 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_EXPORT Standard_Boolean hasOverlap (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
-                                               SelectMgr_Vec3& theNormal);
+                                               gp_Vec& theNormal);
 
   //! SAT intersection test between defined volume and given triangle
   Standard_EXPORT 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 b245522..cc7e134 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.ChangeData()[aDim]      = 0;
+      aDirection.ChangeData()[aNext]     = -myEdgeDirs[aVolDir].XYZ().GetData()[aNextNext];
+      aDirection.ChangeData()[aNextNext] = myEdgeDirs[aVolDir].XYZ().GetData()[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 09fa644..b33d16d 100644 (file)
@@ -165,7 +165,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;
@@ -173,7 +173,7 @@ SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const
   // this case should never happen
   if (!myWorldView.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
@@ -184,7 +184,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);
 }
 
 // =======================================================================
@@ -193,9 +193,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 26135c8..ecf45b8 100644 (file)
@@ -70,16 +70,16 @@ public:
   //! Projects 2d screen point onto view frustum plane:
   //! theZ = 0 - near plane,
   //! theZ = 1 - far plane
-  Standard_EXPORT SelectMgr_Vec3 ProjectPntOnViewPlane (const Standard_Real& theX,
-                                                        const Standard_Real& theY,
-                                                        const Standard_Real& theZ) const;
+  Standard_EXPORT gp_Pnt ProjectPntOnViewPlane (const Standard_Real& theX,
+                                                const Standard_Real& theY,
+                                                const Standard_Real& theZ) const;
 
   DEFINE_STANDARD_RTTI(SelectMgr_FrustumBuilder, Standard_Transient)
 
 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 b98d41d..42f3862 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 aSn = aCoef;
   Standard_Real aTc, aTn, aTd = aCoef;
@@ -78,24 +70,22 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP
   }
   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())
   {
@@ -118,135 +108,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.GetData()[aDim], aMax);
+      aMin = Min (aVert.GetData()[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);
 }
 
 // =======================================================================
@@ -262,278 +290,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);
 }
@@ -556,20 +410,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;
 }
@@ -584,17 +437,26 @@ 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
 // =======================================================================
 Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
@@ -647,7 +509,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;
 
@@ -683,21 +545,20 @@ 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()) };
+    gp_XYZ aTrEdges[3] = { thePnt2.XYZ() - thePnt1.XYZ(),
+                           thePnt3.XYZ() - thePnt2.XYZ(),
+                           thePnt1.XYZ() - thePnt3.XYZ() };
 
-    Standard_Real anAlpha = DOT (aTriangleNormal, myViewRayDir);
+    Standard_Real anAlpha = aTriangleNormal.Dot (myViewRayDir);
     if (Abs (anAlpha) < gp::Resolution())
     {
       // handle degenerated triangles: in this case, there is no possible way to detect overlap correctly.
-      if (aTriangleNormal.SquareModulus() < gp::Resolution())
+      if (aTriangleNormal.SquareMagnitude() < gp::Resolution())
       {
         theDepth = std::numeric_limits<Standard_Real>::max();
         return Standard_False;
@@ -705,44 +566,38 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
 
       // handle the case when triangle normal and selecting frustum direction are orthogonal: for this case, overlap
       // is detected correctly, and distance to triangle's plane can be measured as distance to its arbitrary vertex.
-      const SelectMgr_Vec3 aDiff = myNearPickedPnt - aPnt1;
-      theDepth = DOT (aTriangleNormal, aDiff);
+      const gp_XYZ aDiff = myNearPickedPnt.XYZ() - thePnt1.XYZ();
+      theDepth = aTriangleNormal.Dot (aDiff);
       return Standard_True;
     }
 
-    SelectMgr_Vec3 anEdge = (aPnt1 - myNearPickedPnt) * (1.0 / anAlpha);
+    gp_XYZ anEdge = (thePnt1.XYZ() - myNearPickedPnt.XYZ()) * (1.0 / anAlpha);
 
-    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;
@@ -762,8 +617,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);
 }
 
 // =======================================================================
@@ -771,9 +625,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.Normalized() * theDepth;
+  return myNearPickedPnt.XYZ() + myViewRayDir.Normalized().XYZ() * theDepth;
 }
 
 // =======================================================================
@@ -800,8 +654,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())
@@ -820,8 +675,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 9c1984d..1d8ec5a 100644 (file)
@@ -42,18 +42,22 @@ public:
   Standard_EXPORT 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
-  Standard_EXPORT 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
-  Standard_EXPORT 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.
+  Standard_EXPORT 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
-  Standard_EXPORT virtual Standard_Boolean Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
+  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
@@ -66,6 +70,9 @@ public:
   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
@@ -92,29 +99,45 @@ public:
   Standard_EXPORT 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
-  Standard_EXPORT virtual SelectMgr_Vec3 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
   Standard_EXPORT 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:
 
   Standard_EXPORT void segmentSegmentDistance (const gp_Pnt& theSegPnt1,
                                                const gp_Pnt& theSegPnt2,
                                                Standard_Real& theDepth);
 
-  Standard_EXPORT void segmentPlaneIntersection (const SelectMgr_Vec3& thePlane,
+  Standard_EXPORT 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 b9c5cbd..5bc3f8f 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);
 }
 
 //=======================================================================
@@ -109,15 +109,7 @@ Standard_Real SelectMgr_SelectableObjectSet::Center (const Standard_Integer theI
 void SelectMgr_SelectableObjectSet::Swap (const Standard_Integer theIndex1,
                                           const Standard_Integer theIndex2)
 {
-  const Standard_Integer aIndex1 = theIndex1 + 1;
-  const Standard_Integer aIndex2 = theIndex2 + 1;
-
-  Handle(SelectMgr_SelectableObject) anObject1 = myObjects.FindKey (aIndex1);
-  Handle(SelectMgr_SelectableObject) anObject2 = myObjects.FindKey (aIndex2);
-
-  myObjects.Substitute (aIndex1, EMPTY_OBJ);
-  myObjects.Substitute (aIndex2, anObject1);
-  myObjects.Substitute (aIndex1, anObject2);
+  myObjects.Swap (theIndex1 + 1, theIndex2 + 1);
 }
 
 //=======================================================================
index dd8c570..210edfd 100644 (file)
@@ -29,8 +29,6 @@
 //! binned BVH builder is used with 32 bins and 1 element per leaf.
 class SelectMgr_SelectableObjectSet : public BVH_PrimitiveSet<Standard_Real, 3>
 {
-  Handle(SelectMgr_SelectableObject) EMPTY_OBJ;
-
 public:
 
   //! Creates new empty objects set and initializes BVH tree
index a7bb82f..d558502 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,32 +53,14 @@ 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  :
 //=======================================================================
@@ -178,7 +169,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)
   {
@@ -229,13 +220,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);
 }
 
 //=======================================================================
@@ -256,31 +248,43 @@ 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
 //            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
 //=======================================================================
-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);
 }
@@ -341,10 +345,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);
 }
@@ -382,3 +386,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].get());
+  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].get());
+  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].get());
+  return aFr->GetFarPnt();
+}
index 34e514a..d4e1dd6 100644 (file)
@@ -38,12 +38,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;
 
@@ -74,7 +78,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);
@@ -92,7 +96,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
@@ -102,9 +107,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
@@ -113,16 +121,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;
 
@@ -133,7 +141,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
@@ -147,6 +155,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 7cff225..1ed7f78 100644 (file)
@@ -27,7 +27,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()
@@ -46,7 +46,7 @@ void SelectMgr_Selection::Destroy()
     Handle(SelectMgr_SensitiveEntity)& anEntity = myEntities.ChangeValue (anEntityIdx);
     anEntity->BaseSensitive()->Set (NULL);
   }
-  mySensFactor = 2.0;
+  mySensFactor = 2;
 }
 
 //==================================================
@@ -132,7 +132,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 d519935..1eaa243 100644 (file)
@@ -130,7 +130,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, MMgt_TShared)
 
@@ -147,7 +147,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 0b8bfd3..26f186a 100644 (file)
@@ -122,12 +122,7 @@ Standard_Real SelectMgr_SensitiveEntitySet::Center (const Standard_Integer theIn
 void SelectMgr_SensitiveEntitySet::Swap (const Standard_Integer theIndex1,
                                          const Standard_Integer theIndex2)
 {
-  const Handle(SelectMgr_SensitiveEntity) anEntity1 = GetSensitiveById (theIndex1);
-  const Handle(SelectMgr_SensitiveEntity) anEntity2 = GetSensitiveById (theIndex2);
-
-  mySensitives.Substitute (theIndex1 + 1, EMPTY_ENT);
-  mySensitives.Substitute (theIndex2 + 1, anEntity1);
-  mySensitives.Substitute (theIndex1 + 1, anEntity2);
+  mySensitives.Swap (theIndex1 + 1, theIndex2 + 1);
 }
 
 //=======================================================================
index 8c712af..e170848 100644 (file)
@@ -33,8 +33,6 @@ typedef NCollection_IndexedMap<Handle(SelectMgr_SensitiveEntity)> SelectMgr_Inde
 //! the performance of searching for overlap among sensitives of one selectable object
 class SelectMgr_SensitiveEntitySet : public BVH_PrimitiveSet<Standard_Real, 3>
 {
-  Handle(SelectMgr_SensitiveEntity) EMPTY_ENT;
-
 public:
 
   Standard_EXPORT SelectMgr_SensitiveEntitySet();
index 696168d..a815a48 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().GetData()[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 dd47711..c8c37dc 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
-  Standard_EXPORT virtual NCollection_Handle<SelectMgr_BaseFrustum> Transform (const gp_Trsf& theTrsf) Standard_OVERRIDE;
+  Standard_EXPORT 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
-  Standard_EXPORT virtual Standard_Boolean Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
+  Standard_EXPORT 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
@@ -82,6 +84,10 @@ public:
   //! Nullifies the handle to corresponding builder instance to prevent memory leaks
   Standard_EXPORT void Clear();
 
+private:
+
+  void cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum);
+
   DEFINE_STANDARD_RTTI(SelectMgr_TriangularFrustum,Standard_Transient)
 };
 
index d0b4104..6a4684a 100644 (file)
@@ -97,17 +97,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 (Handle(SelectMgr_TriangularFrustum)::DownCast (anIter.Value()->Transform (theTrsf)));
+    aRes->myFrustums.Append (Handle(SelectMgr_TriangularFrustum)::DownCast (anIter.Value()->ScaleAndTransform (theScale, theTrsf)));
   }
 
   return NCollection_Handle<SelectMgr_BaseFrustum> (aRes);
@@ -117,12 +124,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 e41e78d..71f0b36 100644 (file)
@@ -47,29 +47,31 @@ public:
   Standard_EXPORT 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
-  Standard_EXPORT virtual NCollection_Handle<SelectMgr_BaseFrustum> Transform (const gp_Trsf& theTrsf) Standard_OVERRIDE;
+  Standard_EXPORT virtual NCollection_Handle<SelectMgr_BaseFrustum> ScaleAndTransform (const Standard_Integer theScale,
+                                                                                       const gp_Trsf& theTrsf) Standard_OVERRIDE;
 
-  Standard_EXPORT virtual Standard_Boolean Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt,
+                                                     const SelectMgr_Vec3& theMaxPnt,
                                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
   Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt,
                                                      const SelectMgr_Vec3& theMaxPnt,
                                                      Standard_Boolean* theInside) Standard_OVERRIDE;
 
-  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;
 
-  Standard_EXPORT virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts,
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
                                                      Select3D_TypeOfSensitivity theSensType,
                                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
-  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;
 
-  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,
                                                      Select3D_TypeOfSensitivity theSensType,
                                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
index 69f479d..500be63 100644 (file)
@@ -66,8 +66,8 @@ namespace {
 //=======================================================================
 SelectMgr_ToleranceMap::SelectMgr_ToleranceMap()
 {
-  myLargestKey = -1.0;
-  myCustomTolerance = -1.0;
+  myLargestKey = -1;
+  myCustomTolerance = -1;
 }
 
 //=======================================================================
@@ -84,7 +84,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))
   {
@@ -113,7 +113,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))
   {
@@ -122,8 +122,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());
@@ -200,34 +200,11 @@ Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select
 }
 
 //=======================================================================
-// 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: sensitivity
 // purpose : In case if custom tolerance is set, this method will return sum of entity
 //           sensitivity and custom tolerance.
 //=======================================================================
-Standard_Real SelectMgr_ViewerSelector::sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const
+Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const
 {
   return myTolerances.IsCustomTolSet() ?
     theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
@@ -259,7 +236,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)
@@ -282,6 +259,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 = sensitivity (theEnt);
+  }
+  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
 //           between some entity of selectable object theObject and
@@ -321,10 +332,10 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
   }
 
   SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
-                                        ? mySelectingVolumeMgr.Transform (aInversedTrsf)
+                                        ? mySelectingVolumeMgr.ScaleAndTransform (1, aInversedTrsf)
                                         : 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),
@@ -379,16 +390,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 (sensitivity (anEnt), aInversedTrsf));
-            }
-
-            aTmpMgr = aScaledTrnsfFrustums.Find (anEnt->DynamicType());
-          }
+          computeFrustum (anEnt, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
           checkOverlap (anEnt, anIdx, aTmpMgr);
         }
       }
index 5d51237..ccf5c9d 100644 (file)
@@ -54,6 +54,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
@@ -70,31 +72,31 @@ 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
-  inline Standard_Real Tolerance() const;
+  inline Standard_Integer Tolerance() const;
 
   //! Sets tolerance to the given one and disables adaptive checks
-  inline void SetCustomTolerance (const Standard_Real theTolerance);
+  inline void SetCustomTolerance (const Standard_Integer theTolerance);
 
   //! Unsets a custom tolerance and enables adaptive checks
   inline void ResetDefaults();
 
   //! Returns the value of custom tolerance regardless of it validity
-  inline Standard_Real CustomTolerance() const;
+  inline Standard_Integer CustomTolerance() const;
 
   //! Returns true if custom tolerance value is greater than zero
   inline Standard_Boolean IsCustomTolSet() const;
 
 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
@@ -295,11 +297,7 @@ private:
 
   //! In case if custom tolerance is set, this method will return sum of entity sensitivity and
   //! custom tolerance. Otherwise, pure entity sensitivity factor will be returned.
-  Standard_Real sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const;
-
-  //! Applies given scale and transformation matrices to the default selecting volume manager
-  SelectMgr_SelectingVolumeManager scaleAndTransform (const Standard_Real theScale,
-                                                      const gp_Trsf& theTrsf);
+  Standard_Integer sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const;
 
   void Activate (const Handle(SelectMgr_Selection)& theSelection);
 
@@ -308,6 +306,14 @@ 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;
index 4a8efc7..f26b33d 100644 (file)
 // function: Tolerance
 // purpose : Returns a current tolerance that must be applied
 //=======================================================================
-inline Standard_Real SelectMgr_ToleranceMap::Tolerance() const
+inline Standard_Integer SelectMgr_ToleranceMap::Tolerance() const
 {
   if (myLargestKey < Precision::Confusion())
-    return 2.0; // default tolerance value
+    return 2; // default tolerance value
 
-  return myCustomTolerance < 0.0 ? myLargestKey : myLargestKey + myCustomTolerance;
+  return myCustomTolerance < 0 ? myLargestKey : myLargestKey + myCustomTolerance;
 }
 
 //=======================================================================
 // function: SetCustomTolerance
 // purpose : Sets tolerance to the given one and disables adaptive checks
 //=======================================================================
-inline void SelectMgr_ToleranceMap::SetCustomTolerance (const Standard_Real theTolerance)
+inline void SelectMgr_ToleranceMap::SetCustomTolerance (const Standard_Integer theTolerance)
 {
   myCustomTolerance = theTolerance;
 }
@@ -37,7 +37,7 @@ inline void SelectMgr_ToleranceMap::SetCustomTolerance (const Standard_Real theT
 // function: CustomTolerance
 // purpose : Returns current value of custom tolerance regardless of it is set or not
 //=======================================================================
-inline Standard_Real SelectMgr_ToleranceMap::CustomTolerance() const
+inline Standard_Integer SelectMgr_ToleranceMap::CustomTolerance() const
 {
   return myCustomTolerance;
 }
@@ -48,7 +48,7 @@ inline Standard_Real SelectMgr_ToleranceMap::CustomTolerance() const
 //=======================================================================
 inline Standard_Boolean SelectMgr_ToleranceMap::IsCustomTolSet() const
 {
-  return myCustomTolerance > 0.0;
+  return myCustomTolerance > 0;
 }
 
 //=======================================================================
@@ -57,7 +57,7 @@ inline Standard_Boolean SelectMgr_ToleranceMap::IsCustomTolSet() const
 //=======================================================================
 inline void SelectMgr_ToleranceMap::ResetDefaults()
 {
-  myCustomTolerance = -1.0;
+  myCustomTolerance = -1;
 }
 
 inline Standard_Real SelectMgr_ViewerSelector::Sensitivity() const
index ba52120..593f421 100644 (file)
@@ -91,11 +91,11 @@ StdSelect_ViewerSelector3d::StdSelect_ViewerSelector3d() {}
 // Function: SetPixelTolerance
 // Purpose :
 //=======================================================================
-void StdSelect_ViewerSelector3d::SetPixelTolerance (const Standard_Real theTolerance)
+void StdSelect_ViewerSelector3d::SetPixelTolerance (const Standard_Integer theTolerance)
 {
   if (myTolerances.Tolerance() != theTolerance)
   {
-    if (theTolerance < 0.0)
+    if (theTolerance < 0)
       myTolerances.ResetDefaults();
     else
       myTolerances.SetCustomTolerance (theTolerance);
index 41e4c03..6af71f5 100644 (file)
@@ -45,10 +45,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 41a8106..6f941d9 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 myTolerances.Tolerance();
 }
index 2461cb9..47242fe 100644 (file)
@@ -749,11 +749,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());
     }
   }
 
@@ -4365,11 +4365,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, ' ');
@@ -4378,7 +4379,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 c07bea3..ccb0373 100644 (file)
@@ -80,6 +80,16 @@ public:
     Standard_Real& ChangeCoord (const Standard_Integer theIndex);
   
     void Coord (Standard_Real& X, Standard_Real& Y, Standard_Real& Z) const;
+
+    //! Returns a const ptr to coordinates location.
+    //! Is useful for algorithms, but DOES NOT PERFORM
+    //! ANY CHECKS!
+    inline const Standard_Real* GetData() const { return (&x); }
+
+    //! Returns a ptr to coordinates location.
+    //! Is useful for algorithms, but DOES NOT PERFORM
+    //! ANY CHECKS!
+    inline Standard_Real* ChangeData() { return (&x); }
   
   //! Returns the X coordinate
     Standard_Real X() const;