#include <gp_Pnt.hxx>
#include <OSD_Environment.hxx>
#include <Precision.hxx>
-#include <SelectBasics_EntityOwner.hxx>
-#include <SelectBasics_SensitiveEntity.hxx>
+#include <Select3D_SensitiveEntity.hxx>
#include <SelectBasics_PickResult.hxx>
#include <SelectMgr_EntityOwner.hxx>
#include <SelectMgr_SortCriterion.hxx>
#include <algorithm>
-IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector,MMgt_TShared)
+IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
-namespace {
- // Comparison operator for sorting selection results
+namespace
+{
+ //! Comparison operator for sorting selection results
class CompareResults
{
public:
-
- CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& aMapOfCriterion)
- : myMapOfCriterion (aMapOfCriterion)
+
+ CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& theMapOfCriterion)
+ : myMapOfCriterion (&theMapOfCriterion)
{
}
Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
{
- return myMapOfCriterion.FindFromIndex(theLeft) > myMapOfCriterion.FindFromIndex(theRight);
+ return myMapOfCriterion->FindFromIndex (theLeft) > myMapOfCriterion->FindFromIndex (theRight);
}
private:
- void operator = (const CompareResults&);
-
- private:
- const SelectMgr_IndexedDataMapOfOwnerCriterion& myMapOfCriterion;
+ const SelectMgr_IndexedDataMapOfOwnerCriterion* myMapOfCriterion;
};
- //! Compute 3d position for detected entity.
- inline void updatePoint3d (SelectMgr_SortCriterion& theCriterion,
- const gp_GTrsf& theInversedTrsf,
- SelectMgr_SelectingVolumeManager& theMgr)
+ static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
+}
+
+//=======================================================================
+// function : updatePoint3d
+// purpose :
+//=======================================================================
+void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
+ const SelectBasics_PickResult& thePickResult,
+ const Handle(Select3D_SensitiveEntity)& theEntity,
+ const gp_GTrsf& theInversedTrsf,
+ const SelectMgr_SelectingVolumeManager& theMgr) const
+{
+ if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
{
- if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
- {
- return;
- }
+ return;
+ }
- theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
- gp_GTrsf anInvTrsf = theInversedTrsf;
- if (theCriterion.Entity->HasInitLocation())
+ bool hasNormal = false;
+ if (thePickResult.HasPickedPoint())
+ {
+ theCriterion.Point = thePickResult.PickedPoint();
+ theCriterion.Normal = thePickResult.SurfaceNormal();
+ const float aNormLen2 = theCriterion.Normal.SquareModulus();
+ if (aNormLen2 > ShortRealEpsilon())
{
- anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
+ hasNormal = true;
+ theCriterion.Normal *= 1.0f / sqrtf (aNormLen2);
}
- if (anInvTrsf.Form() != gp_Identity)
+ }
+ else if (!thePickResult.IsValid())
+ {
+ theCriterion.Point = thePickResult.PickedPoint();
+ return;
+ }
+ else
+ {
+ theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
+ }
+
+ gp_GTrsf anInvTrsf = theInversedTrsf;
+ if (theCriterion.Entity->HasInitLocation())
+ {
+ anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
+ }
+ if (anInvTrsf.Form() != gp_Identity)
+ {
+ const gp_GTrsf anInvInvTrsd = anInvTrsf.Inverted();
+ anInvInvTrsd.Transforms (theCriterion.Point.ChangeCoord());
+ if (hasNormal)
{
- anInvTrsf.Inverted().Transforms (theCriterion.Point.ChangeCoord());
+ Graphic3d_Mat4d aMat4;
+ anInvInvTrsd.GetMat4 (aMat4);
+ const Graphic3d_Vec4d aNormRes = aMat4 * Graphic3d_Vec4d (Graphic3d_Vec3d (theCriterion.Normal), 0.0);
+ theCriterion.Normal = Graphic3d_Vec3 (aNormRes.xyz());
}
}
- static const Graphic3d_Mat4d THE_IDENTITY_MAT;
+ if (mySelectingVolumeMgr.Camera().IsNull())
+ {
+ 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();
+ }
}
//==================================================
SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
preferclosest(Standard_True),
myToUpdateTolerance (Standard_True),
+myCameraScale (1.0),
myCurRank (0),
myIsLeftChildQueuedFirst (Standard_False),
myEntityIdx (0)
{
+ myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
+}
+
+//=======================================================================
+// Function: SetPixelTolerance
+// Purpose :
+//=======================================================================
+void SelectMgr_ViewerSelector::SetPixelTolerance (const Standard_Integer theTolerance)
+{
+ if (myTolerances.Tolerance() == theTolerance)
+ {
+ return;
+ }
+
+ myToUpdateTolerance = Standard_True;
+ if (theTolerance < 0)
+ {
+ myTolerances.ResetDefaults();
+ }
+ else
+ {
+ myTolerances.SetCustomTolerance (theTolerance);
+ }
}
//==================================================
//==================================================
void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
{
- for (theSelection->Init(); theSelection->More(); theSelection->Next())
+ for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
{
- theSelection->Sensitive()->SetActiveForSelection();
+ aSelEntIter.Value()->SetActiveForSelection();
}
- theSelection->SetSelectionState (SelectMgr_SOS_Activated);
+ if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
+ {
+ theSelection->SetSelectionState (SelectMgr_SOS_Activated);
- myTolerances.Add (theSelection->Sensitivity());
- myToUpdateTolerance = Standard_True;
+ myTolerances.Add (theSelection->Sensitivity());
+ myToUpdateTolerance = Standard_True;
+ }
}
//==================================================
//==================================================
void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
{
- for (theSelection->Init(); theSelection->More(); theSelection->Next())
+ for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
{
- theSelection->Sensitive()->ResetSelectionActiveStatus();
+ aSelEntIter.Value()->ResetSelectionActiveStatus();
}
- theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
+ if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
+ {
+ theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
- myTolerances.Decrement (theSelection->Sensitivity());
- myToUpdateTolerance = Standard_True;
+ myTolerances.Decrement (theSelection->Sensitivity());
+ myToUpdateTolerance = Standard_True;
+ }
}
//==================================================
// function: isToScaleFrustum
// purpose : Checks if the entity given requires to scale current selecting frustum
//=======================================================================
-Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity)
+Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
{
return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
&& sensitivity (theEntity) < myTolerances.Tolerance();
// purpose : In case if custom tolerance is set, this method will return sum of entity
// sensitivity and custom tolerance.
//=======================================================================
-Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const
+Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(Select3D_SensitiveEntity)& theEntity) const
{
return myTolerances.IsCustomTolSet() ?
theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
// purpose : Internal function that checks if a particular sensitive
// entity theEntity overlaps current selecting volume precisely
//=======================================================================
-void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_SensitiveEntity)& theEntity,
+void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEntity)& theEntity,
const gp_GTrsf& theInversedTrsf,
SelectMgr_SelectingVolumeManager& theMgr)
{
- Handle(SelectMgr_EntityOwner) anOwner (Handle(SelectMgr_EntityOwner)::DownCast (theEntity->OwnerId()));
- Handle(SelectMgr_SelectableObject) aSelectable;
- Standard_Boolean toRestoresViewClipEnabled = Standard_False;
- if (!anOwner.IsNull())
- {
- aSelectable = anOwner->Selectable();
- if (!aSelectable->ClipPlanes().IsNull()
- && aSelectable->ClipPlanes()->ToOverrideGlobal())
- {
- theMgr.SetViewClippingEnabled (Standard_False);
- toRestoresViewClipEnabled = Standard_True;
- }
- else if (!aSelectable->TransformPersistence().IsNull())
- {
- if (aSelectable->TransformPersistence()->IsZoomOrRotate()
- && !theMgr.ViewClipping().IsNull())
- {
- // Zoom/rotate persistence object lives in two worlds at the same time.
- // Global clipping planes can not be trivially applied without being converted
- // into local space of transformation persistence object.
- // As more simple alternative - just clip entire object by its anchor point defined in the world space.
- const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
-
- const gp_Pnt anAnchor = aSelectable->TransformPersistence()->AnchorPoint();
- for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
- {
- const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
- if (!aPlane->IsOn())
- {
- continue;
- }
-
- const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
- const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
- if (aPlaneEquation.Dot (aCheckPnt) < 0.0) // vertex is outside the half-space
- {
- return;
- }
- }
- }
-
- theMgr.SetViewClippingEnabled (Standard_False);
- toRestoresViewClipEnabled = Standard_True;
- }
- }
-
+ const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
+ Handle(SelectMgr_SelectableObject) aSelectable = !anOwner.IsNull() ? anOwner->Selectable() : Handle(SelectMgr_SelectableObject)();
SelectBasics_PickResult aPickResult;
const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
- if (toRestoresViewClipEnabled)
- {
- theMgr.SetViewClippingEnabled (Standard_True);
- }
-
if (!isMatched
|| anOwner.IsNull())
{
return;
}
- if (HasDepthClipping (anOwner)
- && theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
- {
- Standard_Boolean isClipped = mySelectingVolumeMgr.IsClipped (*aSelectable->ClipPlanes(),
- aPickResult.Depth());
- if (isClipped)
- return;
- }
-
SelectMgr_SortCriterion aCriterion;
- myZLayerOrderMap.Find (aSelectable->ZLayer(), aCriterion.ZLayerPosition);
+ myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
aCriterion.Entity = theEntity;
aCriterion.Priority = anOwner->Priority();
aCriterion.Depth = aPickResult.Depth();
aCriterion.MinDist = aPickResult.DistToGeomCenter();
- aCriterion.Tolerance = theEntity->SensitivityFactor() / 33.0;
aCriterion.ToPreferClosest = preferclosest;
- const Standard_Integer aPrevStoredIndex = mystored.FindIndex (anOwner);
- if (aPrevStoredIndex != 0)
+ if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
{
+ ++aPrevCriterion->NbOwnerMatches;
+ aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
{
- SelectMgr_SortCriterion& aPrevCriterion = mystored.ChangeFromIndex (aPrevStoredIndex);
- if (aCriterion > aPrevCriterion)
+ if (aCriterion > *aPrevCriterion)
{
- updatePoint3d (aCriterion, theInversedTrsf, theMgr);
- aPrevCriterion = aCriterion;
+ updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
+ *aPrevCriterion = aCriterion;
}
}
}
else
{
- updatePoint3d (aCriterion, theInversedTrsf, theMgr);
+ aCriterion.NbOwnerMatches = 1;
+ updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
mystored.Add (anOwner, aCriterion);
}
}
//=======================================================================
// 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
+// purpose :
//=======================================================================
-void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt,
- const SelectMgr_SelectingVolumeManager& theMgr,
- const gp_GTrsf& theInvTrsf,
- SelectMgr_FrustumCache& theCachedMgrs,
- SelectMgr_SelectingVolumeManager& theResMgr)
+void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
+ const SelectMgr_SelectingVolumeManager& theMgrGlobal,
+ const SelectMgr_SelectingVolumeManager& theMgrObject,
+ const gp_GTrsf& theInvTrsf,
+ SelectMgr_FrustumCache& theCachedMgrs,
+ SelectMgr_SelectingVolumeManager& theResMgr)
{
Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
if (toScale && toTransform)
{
- theResMgr = theMgr.ScaleAndTransform (aScale, aTrsfMtr, NULL);
+ theResMgr = theMgrGlobal.ScaleAndTransform (aScale, aTrsfMtr, NULL);
+ theResMgr.SetViewClipping (theMgrObject);
}
else if (toScale)
{
- if (!theCachedMgrs.IsBound (aScale))
+ if (!theCachedMgrs.Find (aScale, theResMgr))
{
- theCachedMgrs.Bind (aScale, theMgr.ScaleAndTransform (aScale, gp_Trsf(), NULL));
+ theResMgr = theMgrGlobal.ScaleAndTransform (aScale, gp_Trsf(), NULL);
+ theCachedMgrs.Bind (aScale, theResMgr);
}
- theResMgr = theCachedMgrs.Find (aScale);
+ theResMgr.SetViewClipping (theMgrObject);
}
else if (toTransform)
{
- theResMgr = theMgr.ScaleAndTransform (1, aTrsfMtr, NULL);
+ theResMgr = theMgrGlobal.ScaleAndTransform (1, aTrsfMtr, NULL);
+ theResMgr.SetViewClipping (theMgrObject);
+ }
+ else
+ {
+ theResMgr = theMgrObject;
}
}
const Standard_Integer theViewportWidth,
const Standard_Integer theViewportHeight)
{
- NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
- myMapOfObjectSensitives.ChangeFind (theObject);
-
+ Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
if (anEntitySet->Size() == 0)
+ {
return;
+ }
- const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
-
+ const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
gp_GTrsf aInversedTrsf;
-
if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
{
if (theObject->TransformPersistence().IsNull())
SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
: theMgr;
-
- SelectMgr_FrustumCache aScaledTrnsfFrustums;
-
- Standard_Integer aNode = 0; // a root node
if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
aSensitivesTree->MaxPoint (0)))
{
return;
}
- Standard_Integer aStack[32];
+
+ if (!theObject->ClipPlanes().IsNull()
+ && theObject->ClipPlanes()->ToOverrideGlobal())
+ {
+ aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
+ }
+ else if (!theObject->TransformPersistence().IsNull())
+ {
+ if (theObject->TransformPersistence()->IsZoomOrRotate()
+ && !theMgr.ViewClipping().IsNull())
+ {
+ // Zoom/rotate persistence object lives in two worlds at the same time.
+ // Global clipping planes can not be trivially applied without being converted
+ // into local space of transformation persistence object.
+ // As more simple alternative - just clip entire object by its anchor point defined in the world space.
+ const gp_Pnt anAnchor = theObject->TransformPersistence()->AnchorPoint();
+ for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*theMgr.ViewClipping()); aPlaneIt.More(); aPlaneIt.Next())
+ {
+ const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
+ if (!aPlane->IsOn())
+ {
+ continue;
+ }
+
+ const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
+ if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
+ {
+ return;
+ }
+ }
+ }
+
+ aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
+ }
+ else if (!theObject->ClipPlanes().IsNull()
+ && !theObject->ClipPlanes()->IsEmpty())
+ {
+ aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes(), &theMgr);
+ }
+
+ if (!theMgr.ViewClipping().IsNull() &&
+ theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
+ {
+ Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0));
+ // If box selection is active, and the whole sensitive tree is out of the clip planes
+ // selection is empty for this object
+ const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
+
+ for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
+ {
+ const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
+ if (!aPlane->IsOn())
+ {
+ continue;
+ }
+
+ Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
+ if (aState == Graphic3d_ClipState_Out) // do not process only whole trees, next check on the tree node
+ {
+ return;
+ }
+ }
+ }
+
+ const Standard_Integer aFirstStored = mystored.Extent() + 1;
+
+ Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
Standard_Integer aHead = -1;
+ Standard_Integer aNode = 0; // a root node
+ SelectMgr_FrustumCache aScaledTrnsfFrustums;
+ SelectMgr_SelectingVolumeManager aTmpMgr (false);
for (;;)
{
if (!aSensitivesTree->IsOuter (aNode))
}
else
{
- Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
- Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
- for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
+ bool aClipped = false;
+ if (!theMgr.ViewClipping().IsNull() &&
+ theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
+ {
+ Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode));
+ // If box selection is active, and the whole sensitive tree is out of the clip planes
+ // selection is empty for this object
+ const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
+
+ for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
+ {
+ const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
+ if (!aPlane->IsOn())
+ {
+ continue;
+ }
+ Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
+ if (aState == Graphic3d_ClipState_Out)
+ {
+ aClipped = true;
+ break;
+ }
+ if (aState == Graphic3d_ClipState_On && !mySelectingVolumeMgr.IsOverlapAllowed()) // partially clipped
+ {
+ if (aPlane->ProbeBoxTouch (aBBox))
+ continue;
+ aClipped = true;
+ break;
+ }
+ }
+ }
+ if (!aClipped)
{
- const Handle(SelectMgr_SensitiveEntity)& aSensitive =
- anEntitySet->GetSensitiveById (anIdx);
- if (aSensitive->IsActiveForSelection())
+ Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
+ Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
+ for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
{
- const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
- SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
- computeFrustum (anEnt, theMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
- checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
+ const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
+ if (aSensitive->IsActiveForSelection())
+ {
+ const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
+ computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
+ checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
+ }
}
}
if (aHead < 0)
--aHead;
}
}
+
+ // in case of Box/Polyline selection - keep only Owners having all Entities detected
+ if (mySelectingVolumeMgr.IsOverlapAllowed()
+ || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box
+ && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline))
+ {
+ return;
+ }
+
+ for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
+ {
+ const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
+ const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
+ Standard_Integer aNbOwnerEntities = 0;
+ for (SelectMgr_IndexedMapOfHSensitive::Iterator aSensIter (anEntitySet->Sensitives()); aSensIter.More(); aSensIter.Next())
+ {
+ if (aSensIter.Value()->BaseSensitive()->OwnerId() == anOwner)
+ {
+ if (++aNbOwnerEntities > aCriterion.NbOwnerMatches)
+ {
+ // Remove from index map.
+ // Considering NCollection_IndexedDataMap implementation, the values for lower indexes will not be modified.
+ // Hence, just keep iterating in backward direction.
+ mystored.RemoveFromIndex (aStoredIter);
+ break;
+ }
+ }
+ }
+ }
}
//=======================================================================
mySelectingVolumeMgr.WorldViewMatrix(),
mySelectingVolumeMgr.WorldViewProjState(),
aWidth, aHeight);
+ const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
+ if (!aCamera.IsNull())
+ {
+ myCameraEye = aCamera->Eye().XYZ();
+ myCameraDir = aCamera->Direction().XYZ();
+ myCameraScale = aCamera->IsOrthographic()
+ ? aCamera->Scale()
+ : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
+ const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
+ myCameraScale *= aPixelSize;
+ }
for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
{
// define corresponding frustum builder parameters
Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
- aBuilder->SetWorldViewMatrix (THE_IDENTITY_MAT);
+ aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
aBuilder->SetWindowSize (aWidth, aHeight);
aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
}
aMgr = mySelectingVolumeMgr;
}
- const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
const Graphic3d_Mat4d& aProjectionMat = mySelectingVolumeMgr.ProjectionMatrix();
const Graphic3d_Mat4d& aWorldViewMat = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
? mySelectingVolumeMgr.WorldViewMatrix()
- : THE_IDENTITY_MAT;
+ : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
- const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
+ const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
Standard_Integer aNode = 0;
if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
continue;
}
- Standard_Integer aStack[32];
+ Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
Standard_Integer aHead = -1;
for (;;)
{
SortResult();
}
+//==================================================
+// Function: ClearPicked
+// Purpose :
+//==================================================
+void SelectMgr_ViewerSelector::ClearPicked()
+{
+ mystored.Clear();
+}
+
//==================================================
// Function: Picked
// Purpose :
//==================================================
-Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
-::Picked() const
+Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked() const
{
- Standard_Integer RankInMap = myIndexes->Value (myCurRank);
- const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
- Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto);
- return Ownr;
+ const Standard_Integer aRankInMap = myIndexes->Value (myCurRank);
+ const Handle(SelectMgr_EntityOwner)& anOwner = mystored.FindKey (aRankInMap);
+ return anOwner;
}
//=======================================================================
//=======================================================================
Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
{
- Handle(SelectMgr_EntityOwner) anOwner;
if (theRank < 1 || theRank > NbPicked())
{
- return anOwner;
+ return Handle(SelectMgr_EntityOwner)();
}
const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
- const Handle(SelectBasics_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
- anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aStoredOwner);
- return anOwner;
+ const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
+ return aStoredOwner;
}
//=======================================================================
//
//==================================================
+//==================================================
+// Function: SetEntitySetBuilder
+// Purpose :
+//==================================================
+void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
+{
+ myEntitySetBuilder = theBuilder;
+ for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
+ {
+ aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
+ }
+}
+
//==================================================
// Function: Contains
// Purpose :
const SelectMgr_StateOfSelection theWantedState) const
{
Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
- for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
+ for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
{
- if (theWantedState == SelectMgr_SOS_Any)
- {
- theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
- }
- else if (theWantedState == theSelectableObject->CurrentSelection()->GetSelectionState())
- {
- theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
- }
+ if (theWantedState == SelectMgr_SOS_Any)
+ {
+ theModeList.Append (aSelIter.Value()->Mode());
+ }
+ else if (theWantedState == aSelIter.Value()->GetSelectionState())
+ {
+ theModeList.Append (aSelIter.Value()->Mode());
+ }
}
return hasActivatedStates;
if (!Contains (theSelectableObject))
return Standard_False;
- for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
- {
- if (theMode == theSelectableObject->CurrentSelection()->Mode())
- {
- return theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated;
- }
- }
-
- return Standard_False;
+ const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
+ return !aSel.IsNull()
+ && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
}
//==================================================
if (!Contains (theSelectableObject))
return Standard_False;
- for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
- {
- if (theMode == theSelectableObject->CurrentSelection()->Mode())
- {
- return theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown;
- }
- }
-
- return Standard_False;
+ const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
+ return !aSel.IsNull()
+ && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
}
TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
{
TCollection_AsciiString aStatus ("Status Object :\n\t");
-
- for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
+ for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
{
- if (theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown)
+ if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
{
- aStatus = aStatus + "Mode " +
- TCollection_AsciiString (theSelectableObject->CurrentSelection()->Mode()) +
- " present - ";
- if (theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated)
- {
- aStatus = aStatus + " Active \n\t";
- }
- else
- {
- aStatus = aStatus + " Inactive \n\t";
- }
+ aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
+ + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
}
}
if(myIndexes.IsNull() || anExtent != myIndexes->Length())
myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
- // to work faster...
- TColStd_Array1OfInteger& thearr = myIndexes->ChangeArray1();
-
- // indices from 1 to N are loaded
- Standard_Integer I ;
- for (I=1; I <= anExtent; I++)
- thearr(I)=I;
-
- std::sort (thearr.begin(), thearr.end(), CompareResults (mystored));
-
-}
-
-//=======================================================================
-//function : HasDepthClipping
-//purpose : Stub
-//=======================================================================
-Standard_Boolean SelectMgr_ViewerSelector::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& /*theOwner*/) const
-{
- return Standard_False;
+ 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));
}
//=======================================================================
if (!myMapOfObjectSensitives.IsBound (theObject))
{
mySelectableObjects.Append (theObject);
- NCollection_Handle<SelectMgr_SensitiveEntitySet> anEntitySet = new SelectMgr_SensitiveEntitySet();
+ Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
myMapOfObjectSensitives.Bind (theObject, anEntitySet);
}
}
void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
const Handle(SelectMgr_Selection)& theSelection)
{
- if (myMapOfObjectSensitives.IsBound (theObject))
+ if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
{
- NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
- myMapOfObjectSensitives.ChangeFind (theObject);
- anEntitySet->Append (theSelection);
- anEntitySet->BVH();
+ (*anEntitySet)->Append (theSelection);
+ (*anEntitySet)->BVH();
}
else
{
//=======================================================================
void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
{
- if (myMapOfObjectSensitives.IsBound (theObject))
+ Handle(SelectMgr_SelectableObject) anObj = theObject;
+ if (myMapOfObjectSensitives.UnBind (theObject))
{
mySelectableObjects.Remove (theObject);
- myMapOfObjectSensitives.UnBind (theObject);
}
}
void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
const Handle(SelectMgr_Selection)& theSelection)
{
- if (myMapOfObjectSensitives.IsBound (theObject))
+ if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
{
- NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
- myMapOfObjectSensitives.ChangeFind (theObject);
- anEntitySet->Remove (theSelection);
+ (*anEntitySet)->Remove (theSelection);
}
}
if (!Contains (theObject))
return;
- NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
+ Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
anEntitySet->MarkDirty();
if (theIsForce)
//=======================================================================
void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
{
- SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives);
- for ( ; aSensitivesIter.More(); aSensitivesIter.Next())
+ for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
{
- NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
- aSensitivesIter.ChangeValue();
- Standard_Integer anEntitiesNb = anEntitySet->Size();
+ Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
+ const Standard_Integer anEntitiesNb = anEntitySet->Size();
for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
{
anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
// purpose : Returns sensitive entity that was detected during the
// previous run of selection algorithm
//=======================================================================
-const Handle(SelectBasics_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
+const Handle(Select3D_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
{
const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
return mystored.FindFromIndex (aRankInMap).Entity;
// function : ActiveOwners
// purpose : Returns the list of active entity owners
//=======================================================================
-void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectBasics_EntityOwner)>& theOwners) const
+void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
{
for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
{
- const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = anIter.Value();
- Standard_Integer anEntitiesNb = anEntitySet->Size();
+ const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
+ const Standard_Integer anEntitiesNb = anEntitySet->Size();
for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
{
- if (anEntitySet->GetSensitiveById (anIdx)->IsActiveForSelection())
+ const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
+ if (aSensitive->IsActiveForSelection())
{
- theOwners.Append (anEntitySet->GetSensitiveById (anIdx)->BaseSensitive()->OwnerId());
+ theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
}
}
}
{
mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, preferclosest)
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToUpdateTolerance)
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
+
+ OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectingVolumeMgr)
+ OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectableObjects)
+
+ Standard_Integer aNbOfSelectableObjects = 0;
+ for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
+ {
+ aNbOfSelectableObjects++;
+ }
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aNbOfSelectableObjects)
+
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.Tolerance())
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.CustomTolerance())
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerOrderMap.Extent())
+
+ OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myEntitySetBuilder.get())
+ OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraEye)
+ OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraDir)
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCameraScale)
+
+ if (!myIndexes.IsNull())
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexes->Size())
+
+ 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())
+}