//! @endcode
//! The last method erases manipulator object.
//! @warning
-//! On construction an instance of AIS_Manipulator object is bound to Graphic3d_ZLayerId_Topmost layer,
-//! so make sure to call for your AIS_InteractiveContext the method MainSelector()->SetPickClosest (Standard_False)
-//! otherwise you may notice issues with activation of modes.
class AIS_Manipulator : public AIS_InteractiveObject
{
public:
SelectMgr_TriangularFrustumSet.cxx
SelectMgr_TriangularFrustumSet.hxx
SelectMgr_TypeOfBVHUpdate.hxx
+SelectMgr_TypeOfDepthTolerance.hxx
SelectMgr_TypeOfUpdate.hxx
SelectMgr_VectorTypes.hxx
SelectMgr_ViewClipRange.cxx
Standard_Integer Priority; //!< selection priority
Standard_Integer ZLayerPosition; //!< ZLayer rendering order index, stronger than a depth
Standard_Integer NbOwnerMatches; //!< overall number of entities collected for the same owner
- Standard_Boolean ToPreferClosest; //!< whether closest object is preferred even if has less priority
public:
DEFINE_STANDARD_ALLOC
MinDist (0.0),
Tolerance(0.0),
Priority (0),
- ZLayerPosition (0),
- NbOwnerMatches (0),
- ToPreferClosest (Standard_True) {}
+ ZLayerPosition (0),
+ NbOwnerMatches (0) {}
- //! Comparison operator.
- bool operator> (const SelectMgr_SortCriterion& theOther) const { return IsGreater (theOther); }
-
- //! Comparison operator.
- bool operator< (const SelectMgr_SortCriterion& theOther) const { return IsLower (theOther); }
-
- //! Compare with another item.
- bool IsGreater (const SelectMgr_SortCriterion& theOther) const
+ //! Compare with another item by depth, priority and minDist.
+ bool IsCloserDepth (const SelectMgr_SortCriterion& theOther) const
{
// the object within different ZLayer groups can not be compared by depth
if (ZLayerPosition != theOther.ZLayerPosition)
return ZLayerPosition > theOther.ZLayerPosition;
}
- if (ToPreferClosest)
+ // closest object is selected unless difference is within tolerance
+ if (Abs (Depth - theOther.Depth) > (Tolerance + theOther.Tolerance))
{
- // closest object is selected unless difference is within tolerance
- if (Abs (Depth - theOther.Depth) > (Tolerance + theOther.Tolerance))
- {
- return Depth < theOther.Depth;
- }
-
- // if two objects have similar depth, select the one with higher priority
- if (Priority > theOther.Priority)
- {
- return true;
- }
-
- // if priorities are equal, one closest to the mouse
- return Priority == theOther.Priority
- && MinDist < theOther.MinDist;
+ return Depth < theOther.Depth;
}
- // old logic (OCCT version <= 6.3.1)
+ // if two objects have similar depth, select the one with higher priority
if (Priority > theOther.Priority)
{
return true;
}
- else if (Priority != theOther.Priority)
- {
- return false;
- }
-
- if (Abs (Depth - theOther.Depth) <= Precision::Confusion())
- {
- return MinDist < theOther.MinDist;
- }
- return Depth < theOther.Depth;
+ // if priorities are equal, one closest to the mouse
+ return Priority == theOther.Priority
+ && MinDist < theOther.MinDist;
}
- //! Compare with another item.
- bool IsLower (const SelectMgr_SortCriterion& theOther) const
+ //! Compare with another item using old logic (OCCT version <= 6.3.1) with priority considered preceding depth.
+ bool IsHigherPriority (const SelectMgr_SortCriterion& theOther) const
{
// the object within different ZLayer groups can not be compared by depth
if (ZLayerPosition != theOther.ZLayerPosition)
{
- return ZLayerPosition < theOther.ZLayerPosition;
- }
-
- if (ToPreferClosest)
- {
- // closest object is selected unless difference is within tolerance
- if (ToPreferClosest
- && Abs (Depth - theOther.Depth) > (Tolerance + theOther.Tolerance))
- {
- return Depth > theOther.Depth;
- }
-
- // if two objects have similar depth, select the one with higher priority
- if (Priority < theOther.Priority)
- {
- return true;
- }
-
- // if priorities are equal, one closest to the mouse
- return Priority == theOther.Priority
- && MinDist > theOther.MinDist;
+ return ZLayerPosition > theOther.ZLayerPosition;
}
- // old logic (OCCT version <= 6.3.1)
if (Priority > theOther.Priority)
{
- return false;
+ return true;
}
else if (Priority != theOther.Priority)
{
- return true;
+ return false;
}
+ //if (Abs (Depth - theOther.Depth) <= (Tolerance + theOther.Tolerance))
if (Abs (Depth - theOther.Depth) <= Precision::Confusion())
{
- return MinDist > theOther.MinDist;
+ return MinDist < theOther.MinDist;
}
- return Depth > theOther.Depth;
+ return Depth < theOther.Depth;
}
};
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _SelectMgr_TypeOfDepthTolerance_HeaderFile
+#define _SelectMgr_TypeOfDepthTolerance_HeaderFile
+
+//! Define the type of depth tolerance for considering picked entities to lie on the same depth (distance from eye to entity).
+//! @sa SelectMgr_SortCriterion, SelectMgr_ViewerSelector
+enum SelectMgr_TypeOfDepthTolerance
+{
+ SelectMgr_TypeOfDepthTolerance_Uniform, //!< use a predefined tolerance value (defined in 3D world scale) to compare any entities
+ SelectMgr_TypeOfDepthTolerance_UniformPixels, //!< use a predefined tolerance value (defined in pixels) to compare any entities
+ SelectMgr_TypeOfDepthTolerance_SensitivityFactor, //!< use sensitivity factor (in pixels) assigned to specific entity
+};
+
+#endif // _SelectMgr_TypeOfDepthTolerance_HeaderFile
{
public:
- CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& theMapOfCriterion)
- : myMapOfCriterion (&theMapOfCriterion)
- {
- }
+ CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& theMapOfCriterion,
+ bool theToPreferClosest)
+ : myMapOfCriterion (&theMapOfCriterion),
+ myToPreferClosest (theToPreferClosest) {}
Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
{
- return myMapOfCriterion->FindFromIndex (theLeft) > myMapOfCriterion->FindFromIndex (theRight);
+ const SelectMgr_SortCriterion& anElemLeft = myMapOfCriterion->FindFromIndex (theLeft);
+ const SelectMgr_SortCriterion& anElemRight = myMapOfCriterion->FindFromIndex (theRight);
+ if (myToPreferClosest)
+ {
+ return anElemLeft.IsCloserDepth (anElemRight);
+ }
+ else
+ {
+ return anElemLeft.IsHigherPriority (anElemRight);
+ }
}
private:
const SelectMgr_IndexedDataMapOfOwnerCriterion* myMapOfCriterion;
+ bool myToPreferClosest;
};
static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
}
}
- if (mySelectingVolumeMgr.Camera().IsNull())
+ const Standard_Real aSensFactor = myDepthTolType == SelectMgr_TypeOfDepthTolerance_SensitivityFactor ? theEntity->SensitivityFactor() : myDepthTolerance;
+ switch (myDepthTolType)
{
- theCriterion.Tolerance = theEntity->SensitivityFactor() / 33.0;
- }
- else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
- {
- theCriterion.Tolerance = myCameraScale * theEntity->SensitivityFactor();
- }
- else
- {
- const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
- theCriterion.Tolerance = aDistFromEye * myCameraScale * theEntity->SensitivityFactor();
+ case SelectMgr_TypeOfDepthTolerance_Uniform:
+ {
+ theCriterion.Tolerance = myDepthTolerance;
+ break;
+ }
+ case SelectMgr_TypeOfDepthTolerance_UniformPixels:
+ case SelectMgr_TypeOfDepthTolerance_SensitivityFactor:
+ {
+ if (mySelectingVolumeMgr.Camera().IsNull())
+ {
+ // fallback for an arbitrary projection matrix
+ theCriterion.Tolerance = aSensFactor / 33.0;
+ }
+ else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
+ {
+ theCriterion.Tolerance = myCameraScale * aSensFactor;
+ }
+ else
+ {
+ const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
+ theCriterion.Tolerance = aDistFromEye * myCameraScale * aSensFactor;
+ }
+ break;
+ }
}
}
// Function: Initialize
// Purpose :
//==================================================
-SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
-preferclosest(Standard_True),
-myToUpdateTolerance (Standard_True),
-myCameraScale (1.0),
-myToPrebuildBVH (Standard_False),
-myCurRank (0),
-myIsLeftChildQueuedFirst (Standard_False),
-myEntityIdx (0)
+SelectMgr_ViewerSelector::SelectMgr_ViewerSelector()
+: myDepthTolerance (0.0),
+ myDepthTolType (SelectMgr_TypeOfDepthTolerance_SensitivityFactor),
+ myToPreferClosest (Standard_True),
+ myToUpdateTolerance (Standard_True),
+ myCameraScale (1.0),
+ myToPrebuildBVH (Standard_False),
+ myCurRank (0),
+ myIsLeftChildQueuedFirst (Standard_False)
{
myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
}
aCriterion.Priority = anOwner->Priority();
aCriterion.Depth = aPickResult.Depth();
aCriterion.MinDist = aPickResult.DistToGeomCenter();
- aCriterion.ToPreferClosest = preferclosest;
if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
{
aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
{
- if (aCriterion > *aPrevCriterion)
+ if (aCriterion.IsCloserDepth (*aPrevCriterion))
{
updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
*aPrevCriterion = aCriterion;
//=======================================================================
//function : SortResult
-//purpose : there is a certain number of entities ranged by criteria
-// (depth, size, priority, mouse distance from borders or
-// CDG of the detected primitive. Parsing :
-// maximum priorities .
-// then a reasonable compromise between depth and distance...
-// finally the ranges are stored in myindexes depending on the parsing.
-// so, it is possible to only read
+//purpose :
//=======================================================================
void SelectMgr_ViewerSelector::SortResult()
{
- if(mystored.IsEmpty()) return;
+ if (mystored.IsEmpty())
+ {
+ return;
+ }
const Standard_Integer anExtent = mystored.Extent();
- if(myIndexes.IsNull() || anExtent != myIndexes->Length())
+ if (myIndexes.IsNull() || anExtent != myIndexes->Length())
+ {
myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
+ }
TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
{
anIndexArray.SetValue (anIndexIter, anIndexIter);
}
- std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored));
+ std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored, myToPreferClosest));
}
//=======================================================================
{
OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
- OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, preferclosest)
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToPreferClosest)
OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToUpdateTolerance)
OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCurRank)
OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsLeftChildQueuedFirst)
- OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myEntityIdx)
OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMapOfObjectSensitives.Extent())
}
#include <SelectMgr_SelectableObjectSet.hxx>
#include <SelectMgr_StateOfSelection.hxx>
#include <SelectMgr_ToleranceMap.hxx>
+#include <SelectMgr_TypeOfDepthTolerance.hxx>
#include <Standard_OStream.hxx>
#include <SelectMgr_BVHThreadPool.hxx>
Standard_Integer PixelTolerance() const { return myTolerances.Tolerance(); }
//! Sorts the detected entites by priority and distance.
- //! to be redefined if other criterion are used...
- Standard_EXPORT void SortResult();
+ Standard_EXPORT virtual void SortResult();
//! Returns the picked element with the highest priority,
//! and which is the closest to the last successful mouse position.
: Picked (1);
}
- //! Set preference of selecting one object for OnePicked() method:
- //! - If True, objects with less depth (distance fron the view plane) are
- //! preferred regardless of priority (priority is used then to choose among
- //! objects with similar depth),
- //! - If False, objects with higher priority are preferred regardless of the
- //! depth which is used to choose among objects of the same priority.
- void SetPickClosest (const Standard_Boolean theToPreferClosest) { preferclosest = theToPreferClosest; }
+ //! Return the flag determining precedence of picked depth (distance from eye to entity) over entity priority in sorted results; TRUE by default.
+ //! When flag is TRUE, priority will be considered only if entities have the same depth within the tolerance.
+ //! When flag is FALSE, entities with higher priority will be in front regardless of their depth (like x-ray).
+ bool ToPickClosest() const { return myToPreferClosest; }
+
+ //! Set flag determining precedence of picked depth over entity priority in sorted results.
+ void SetPickClosest (bool theToPreferClosest) { myToPreferClosest = theToPreferClosest; }
+
+ //! Return the type of tolerance for considering two entities having a similar depth (distance from eye to entity);
+ //! SelectMgr_TypeOfDepthTolerance_SensitivityFactor by default.
+ SelectMgr_TypeOfDepthTolerance DepthToleranceType() const { return myDepthTolType; }
+
+ //! Return the tolerance for considering two entities having a similar depth (distance from eye to entity).
+ Standard_Real DepthTolerance() const { return myDepthTolerance; }
+
+ //! Set the tolerance for considering two entities having a similar depth (distance from eye to entity).
+ //! @param theType [in] type of tolerance value
+ //! @param theTolerance [in] tolerance value in 3D scale (SelectMgr_TypeOfDepthTolerance_Uniform)
+ //! or in pixels (SelectMgr_TypeOfDepthTolerance_UniformPixels);
+ //! value is ignored in case of SelectMgr_TypeOfDepthTolerance_SensitivityFactor
+ void SetDepthTolerance (SelectMgr_TypeOfDepthTolerance theType,
+ Standard_Real theTolerance)
+ {
+ myDepthTolType = theType;
+ myDepthTolerance = theTolerance;
+ }
//! Returns the number of detected owners.
Standard_Integer NbPicked() const { return mystored.Extent(); }
protected:
- Standard_Boolean preferclosest;
+ Standard_Real myDepthTolerance;
+ SelectMgr_TypeOfDepthTolerance myDepthTolType;
+ Standard_Boolean myToPreferClosest;
Standard_Boolean myToUpdateTolerance;
SelectMgr_IndexedDataMapOfOwnerCriterion mystored;
SelectMgr_SelectingVolumeManager mySelectingVolumeMgr;
Standard_Boolean myToPrebuildBVH;
Handle(SelectMgr_BVHThreadPool) myBVHThreadPool;
-private:
-
Handle(TColStd_HArray1OfInteger) myIndexes;
Standard_Integer myCurRank;
Standard_Boolean myIsLeftChildQueuedFirst;
- Standard_Integer myEntityIdx;
SelectMgr_MapOfObjectSensitives myMapOfObjectSensitives;
};
{
aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
}
+ else if (anArg == "-preferclosest")
+ {
+ bool toPreferClosest = true;
+ if (anArgIter + 1 < theArgsNb
+ && Draw::ParseOnOff (theArgVec[anArgIter + 1], toPreferClosest))
+ {
+ ++anArgIter;
+ }
+ aCtx->MainSelector()->SetPickClosest (toPreferClosest);
+ }
+ else if ((anArg == "-depthtol"
+ || anArg == "-depthtolerance")
+ && anArgIter + 1 < theArgsNb)
+ {
+ TCollection_AsciiString aTolType (theArgVec[++anArgIter]);
+ aTolType.LowerCase();
+ if (aTolType == "uniform")
+ {
+ if (anArgIter + 1 >= theArgsNb)
+ {
+ Message::SendFail() << "Syntax error: wrong number of arguments";
+ return 1;
+ }
+ aCtx->MainSelector()->SetDepthTolerance (SelectMgr_TypeOfDepthTolerance_Uniform,
+ Draw::Atof (theArgVec[++anArgIter]));
+ }
+ else if (aTolType == "uniformpx")
+ {
+ if (anArgIter + 1 >= theArgsNb)
+ {
+ Message::SendFail() << "Syntax error: wrong number of arguments";
+ return 1;
+ }
+ aCtx->MainSelector()->SetDepthTolerance (SelectMgr_TypeOfDepthTolerance_UniformPixels,
+ Draw::Atof (theArgVec[++anArgIter]));
+ }
+ else if (aTolType == "sensfactor")
+ {
+ aCtx->MainSelector()->SetDepthTolerance (SelectMgr_TypeOfDepthTolerance_SensitivityFactor, 0.0);
+ }
+ else
+ {
+ Message::SendFail() << "Syntax error at '" << aTolType << "'";
+ return 1;
+ }
+ }
else if ((anArg == "-mode"
|| anArg == "-dispmode")
&& anArgIter + 1 < theArgsNb)
else
{
Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
+ return 1;
}
}
"\n 'first' to pick first acceptable (default)"
"\n 'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
"\n -pixTol value : sets up pixel tolerance"
+ "\n -depthTol {uniform|uniformpx} value : sets tolerance for sorting results by depth"
+ "\n -depthTol {sensfactor} : use sensitive factor for sorting results by depth"
+ "\n -preferClosest {0|1} : sets if depth should take precedence over priority while sorting results"
"\n -dispMode dispMode : sets display mode for highlighting"
"\n -layer ZLayer : sets ZLayer for highlighting"
"\n -color {name|r g b} : sets highlight color"