1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +03:00

0030777: Visualization - Incorrect selection/highlighting of clipped objects

SelectMgr_ViewerSelector::traverseObject() now handles Object clipping planes in the same way as View clipping planes.
This commit is contained in:
kgv 2019-06-16 17:09:14 +03:00 committed by bugmaster
parent 3b739e69c9
commit fe525c6f7c
13 changed files with 124 additions and 214 deletions

View File

@ -310,6 +310,23 @@ proc checkreal {name value expected tol_abs tol_rel} {
return
}
# Procedure to check equality of two 3D points with tolerance
help checkpoint {
Compare two 3D points with given tolerance
Use: checkpoint name {valueX valueY valueZ} {expectedX expectedY expectedZ} tolerance
}
proc checkpoint {theName theValue theExpected theTolerance} {
set e 0.0001
foreach i {0 1 2} {
if { [expr abs([lindex $theValue $i] - [lindex $theExpected $i])] > $theTolerance } {
puts "Error: $theName, ($theValue) is not equal to expected ($theExpected)"
return
}
}
puts "Check of $theName OK: value = ($theValue), expected = ($theExpected)"
return
}
help checkfreebounds {
Compare number of free edges with ref_value

View File

@ -240,14 +240,3 @@ gp_Pnt SelectMgr_BaseFrustum::DetectedPoint (const Standard_Real /*theDepth*/) c
{
return gp_Pnt (RealLast(), RealLast(), RealLast());
}
//=======================================================================
// function : IsClipped
// purpose : Checks if the point of sensitive in which selection was
// detected belongs to the region defined by clipping planes
//=======================================================================
Standard_Boolean SelectMgr_BaseFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& /*thePlanes*/,
const Standard_Real /*theDepth*/) const
{
return Standard_True;
}

View File

@ -165,18 +165,16 @@ public:
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
Standard_EXPORT virtual Standard_Boolean IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
const Standard_Real theDepth) const;
//! Valid for point selection only!
//! Computes depth range for global (defined for the whole view) clipping planes.
virtual void SetViewClipping (const Handle(Graphic3d_SequenceOfHClipPlane)& /*thePlanes*/) {};
//! Set if view clipping plane is enabled or not.
//! @return previous value of the flag
virtual Standard_Boolean SetViewClippingEnabled (const Standard_Boolean /*theToEnable*/) { return Standard_False; }
//! Computes depth range for clipping planes.
//! @param theViewPlanes global view planes
//! @param theObjPlanes object planes
virtual void SetViewClipping (const Handle(Graphic3d_SequenceOfHClipPlane)& theViewPlanes,
const Handle(Graphic3d_SequenceOfHClipPlane)& theObjPlanes)
{
(void )theViewPlanes;
(void )theObjPlanes;
}
//! Stores plane equation coefficients (in the following form:
//! Ax + By + Cz + D = 0) to the given vector

View File

@ -465,7 +465,6 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_RectangularFrustum::ScaleAndTransform (c
cacheVertexProjections (aRes.get());
aRes->myViewClipRange = myViewClipRange;
aRes->myIsViewClipEnabled = myIsViewClipEnabled;
aRes->myMousePos = myMousePos;
return aRes;
@ -516,7 +515,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t
return isViewClippingOk (thePickResult);
}
if (myIsViewClipEnabled && !myViewClipRange.GetNearestDepth (aRange, aDepth))
if (!myViewClipRange.GetNearestDepth (aRange, aDepth))
{
return Standard_False;
}
@ -815,33 +814,24 @@ void SelectMgr_RectangularFrustum::computeClippingRange (const Graphic3d_Sequenc
}
}
// =======================================================================
// function : IsClipped
// purpose : Checks if the point of sensitive in which selection was
// detected belongs to the region defined by clipping planes
// =======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
const Standard_Real theDepth) const
{
SelectMgr_ViewClipRange aRange;
computeClippingRange (thePlanes, aRange);
return aRange.IsClipped (theDepth);
}
// =======================================================================
// function : SetViewClipping
// purpose :
// =======================================================================
void SelectMgr_RectangularFrustum::SetViewClipping (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
void SelectMgr_RectangularFrustum::SetViewClipping (const Handle(Graphic3d_SequenceOfHClipPlane)& theViewPlanes,
const Handle(Graphic3d_SequenceOfHClipPlane)& theObjPlanes)
{
if (thePlanes.IsNull()
|| thePlanes->IsEmpty())
myViewClipRange.SetVoid();
if (!theViewPlanes.IsNull()
&& !theViewPlanes->IsEmpty())
{
myViewClipRange.SetVoid();
return;
computeClippingRange (*theViewPlanes, myViewClipRange);
}
if (!theObjPlanes.IsNull()
&& !theObjPlanes->IsEmpty())
{
computeClippingRange (*theObjPlanes, myViewClipRange);
}
computeClippingRange (*thePlanes, myViewClipRange);
}
// =======================================================================
@ -850,8 +840,7 @@ void SelectMgr_RectangularFrustum::SetViewClipping (const Handle(Graphic3d_Seque
// =======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::isViewClippingOk (const SelectBasics_PickResult& thePickResult) const
{
return !myIsViewClipEnabled
|| !myViewClipRange.IsClipped (thePickResult.Depth());
return !myViewClipRange.IsClipped (thePickResult.Depth());
}
// =======================================================================

View File

@ -34,7 +34,7 @@ class SelectMgr_RectangularFrustum : public SelectMgr_Frustum<4>
{
public:
SelectMgr_RectangularFrustum() : myScale (1.0), myIsViewClipEnabled (Standard_True) {};
SelectMgr_RectangularFrustum() : myScale (1.0) {};
//! Builds volume according to the point and given pixel tolerance
Standard_EXPORT virtual void Build (const gp_Pnt2d& thePoint) Standard_OVERRIDE;
@ -102,23 +102,12 @@ public:
//! Calculates the point on a view ray that was detected during the run of selection algo by given depth
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) const Standard_OVERRIDE;
//! Valid for point selection only!
//! Computes depth range for global (defined for the whole view) clipping planes.
Standard_EXPORT virtual void SetViewClipping (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes) Standard_OVERRIDE;
//! Set if view clipping plane is enabled or not.
//! @return previous value of the flag
virtual Standard_Boolean SetViewClippingEnabled (const Standard_Boolean theToEnable) Standard_OVERRIDE
{
Standard_Boolean aPrevValue = myIsViewClipEnabled;
myIsViewClipEnabled = theToEnable;
return aPrevValue;
}
//! Computes depth range for clipping planes.
//! @param theViewPlanes global view planes
//! @param theObjPlanes object planes
Standard_EXPORT virtual void SetViewClipping (const Handle(Graphic3d_SequenceOfHClipPlane)& theViewPlanes,
const Handle(Graphic3d_SequenceOfHClipPlane)& theObjPlanes) Standard_OVERRIDE;
//! A set of helper functions that return rectangular selecting frustum data
inline const gp_Pnt* GetVertices() const { return myVertices; }
@ -175,7 +164,6 @@ private:
gp_Pnt2d myMousePos; //!< Mouse coordinates
Standard_Real myScale; //!< Scale factor of applied transformation, if there was any
SelectMgr_ViewClipRange myViewClipRange;
Standard_Boolean myIsViewClipEnabled; //!< view clipping enabled state
};

View File

@ -61,6 +61,7 @@ SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::ScaleAndTrans
aMgr.myToAllowOverlap = myToAllowOverlap;
aMgr.mySelectingVolumes[myActiveSelectionType / 2]->SetBuilder (theBuilder);
aMgr.myViewClipPlanes = myViewClipPlanes;
aMgr.myObjectClipPlanes = myObjectClipPlanes;
return aMgr;
}
@ -388,20 +389,6 @@ gp_Pnt SelectMgr_SelectingVolumeManager::DetectedPoint (const Standard_Real theD
return mySelectingVolumes[Frustum]->DetectedPoint (theDepth);
}
//=======================================================================
// function : IsClipped
// purpose : Checks if the point of sensitive in which selection was
// detected belongs to the region defined by clipping planes
//=======================================================================
Standard_Boolean SelectMgr_SelectingVolumeManager::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
const Standard_Real& theDepth) const
{
if (myActiveSelectionType != Point)
return Standard_False;
return mySelectingVolumes[Frustum]->IsClipped (thePlanes, theDepth);
}
//=======================================================================
// function : AllowOverlapDetection
// purpose : If theIsToAllow is false, only fully included sensitives will
@ -468,23 +455,13 @@ gp_Pnt SelectMgr_SelectingVolumeManager::GetFarPickedPnt() const
// function : SetViewClipping
// purpose :
//=======================================================================
void SelectMgr_SelectingVolumeManager::SetViewClipping (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
void SelectMgr_SelectingVolumeManager::SetViewClipping (const Handle(Graphic3d_SequenceOfHClipPlane)& theViewPlanes,
const Handle(Graphic3d_SequenceOfHClipPlane)& theObjPlanes)
{
myViewClipPlanes = thePlanes;
myViewClipPlanes = theViewPlanes;
myObjectClipPlanes = theObjPlanes;
if (myActiveSelectionType != Point)
return;
mySelectingVolumes[Frustum]->SetViewClipping (thePlanes);
}
//=======================================================================
// function : SetViewClippingEnabled
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_SelectingVolumeManager::SetViewClippingEnabled (const Standard_Boolean theToEnable)
{
if (myActiveSelectionType != Point)
return Standard_False;
return mySelectingVolumes[Frustum]->SetViewClippingEnabled (theToEnable);
mySelectingVolumes[Frustum]->SetViewClipping (theViewPlanes, theObjPlanes);
}

View File

@ -158,11 +158,6 @@ public:
//! Throws exception if active selection type is not Point.
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) const;
//! Is used for rectangular selection only
//! If theIsToAllow is false, only fully included sensitives will be detected, otherwise the algorithm will
//! mark both included and overlapped entities as matched
@ -173,13 +168,15 @@ public:
//! Return view clipping planes.
const Handle(Graphic3d_SequenceOfHClipPlane)& ViewClipping() const { return myViewClipPlanes; }
//! Valid for point selection only!
//! Computes depth range for global (defined for the whole view) clipping planes.
Standard_EXPORT void SetViewClipping (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes);
//! Return object clipping planes.
const Handle(Graphic3d_SequenceOfHClipPlane)& ObjectClipping() const { return myObjectClipPlanes; }
//! Set if view clipping plane is enabled or not.
//! @return previous flag value
Standard_EXPORT Standard_Boolean SetViewClippingEnabled (const Standard_Boolean theToEnable);
//! Valid for point selection only!
//! Computes depth range for clipping planes.
//! @param theViewPlanes global view planes
//! @param theObjPlanes object planes
Standard_EXPORT void SetViewClipping (const Handle(Graphic3d_SequenceOfHClipPlane)& theViewPlanes,
const Handle(Graphic3d_SequenceOfHClipPlane)& theObjPlanes);
//! A set of helper functions that return rectangular selecting frustum data
Standard_EXPORT const gp_Pnt* GetVertices() const;
@ -235,6 +232,7 @@ private:
Handle(SelectMgr_BaseFrustum) mySelectingVolumes[VolumeTypesNb]; //!< Array of selecting volumes
Handle(Graphic3d_SequenceOfHClipPlane) myViewClipPlanes; //!< view clipping planes
Handle(Graphic3d_SequenceOfHClipPlane) myObjectClipPlanes; //!< object clipping planes
Standard_Boolean myToAllowOverlap; //!< Defines if partially overlapped entities will me detected or not
};

View File

@ -210,76 +210,15 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEnti
SelectMgr_SelectingVolumeManager& theMgr)
{
const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
Handle(SelectMgr_SelectableObject) aSelectable;
Standard_Boolean toRestoresViewClipEnabled = Standard_False;
if (!anOwner.IsNull())
{
aSelectable = anOwner->Selectable();
}
if (!aSelectable.IsNull())
{
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 aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
{
return;
}
}
}
theMgr.SetViewClippingEnabled (Standard_False);
toRestoresViewClipEnabled = Standard_True;
}
}
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)
&& !aSelectable.IsNull()
&& theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
{
Standard_Boolean isClipped = mySelectingVolumeMgr.IsClipped (*aSelectable->ClipPlanes(),
aPickResult.Depth());
if (isClipped)
return;
}
SelectMgr_SortCriterion aCriterion;
myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
aCriterion.Entity = theEntity;
@ -394,20 +333,57 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
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;
}
if (!theObject->ClipPlanes().IsNull()
&& theObject->ClipPlanes()->ToOverrideGlobal())
{
aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes());
}
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());
}
else if (!theObject->ClipPlanes().IsNull()
&& !theObject->ClipPlanes()->IsEmpty())
{
aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes());
}
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;
for (;;)
{
if (!aSensitivesTree->IsOuter (aNode))
@ -832,15 +808,6 @@ void SelectMgr_ViewerSelector::SortResult()
std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored));
}
//=======================================================================
//function : HasDepthClipping
//purpose : Stub
//=======================================================================
Standard_Boolean SelectMgr_ViewerSelector::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& /*theOwner*/) const
{
return Standard_False;
}
//=======================================================================
// function : AddSelectableObject
// purpose : Adds new object to the map of selectable objects

View File

@ -253,14 +253,6 @@ protected:
//! finds candidates for further search of overlap
Standard_EXPORT void TraverseSensitives();
//! Returns True if the owner provides clipping by depth
//! for its sensitives. Override this method to tell the selector
//! to use the DepthClipping method for the owner.
//! Default implementation returns False for every owner.
//! @param theOwner [in] the onwer to check.
//! @return True if owner provides depth limits for sensitive clipping.
Standard_EXPORT virtual Standard_Boolean HasDepthClipping (const Handle(SelectMgr_EntityOwner)& theOwner) const;
//! Internal function that checks if there is possible overlap between some entity of selectable object theObject and
//! current selecting volume.
//! @param theObject [in] the selectable object for traversal.

View File

@ -132,7 +132,7 @@ void StdSelect_ViewerSelector3d::Pick (const Standard_Integer theXPix,
gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix),
static_cast<Standard_Real> (theYPix));
mySelectingVolumeMgr.BuildSelectingVolume (aMousePos);
mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes());
mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)());
TraverseSensitives();
}
@ -624,22 +624,6 @@ void StdSelect_ViewerSelector3d::computeSensitivePrs (const Handle(Graphic3d_Str
}
}
//=======================================================================
//function : HasDepthClipping
//purpose :
//=======================================================================
Standard_Boolean StdSelect_ViewerSelector3d::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& theOwner) const
{
if (!theOwner->HasSelectable())
{
return Standard_False;
}
const Handle(SelectMgr_SelectableObject)& aSelectable = theOwner->Selectable();
return !aSelectable->ClipPlanes().IsNull()
&& !aSelectable->ClipPlanes()->IsEmpty();
}
//=======================================================================
// Function: updateZLayers
// Purpose :

View File

@ -93,8 +93,6 @@ public:
const Handle(V3d_View)& theView,
const Standard_Boolean theToClearOthers = Standard_True);
Standard_EXPORT virtual Standard_Boolean HasDepthClipping (const Handle(SelectMgr_EntityOwner)& theOwner) const Standard_OVERRIDE;
DEFINE_STANDARD_RTTIEXT(StdSelect_ViewerSelector3d,SelectMgr_ViewerSelector)
protected:

19
tests/bugs/vis/bug30777 Normal file
View File

@ -0,0 +1,19 @@
puts "============="
puts "0030777: Visualization - Incorrect selection/highlighting of clipped objects"
puts "============="
pload MODELING VISUALIZATION
vclear
vinit View1
vaxo
psphere s 10
vdisplay -dispMode 1 s
vfit
vfront
vclipplane p1 -set s -equation 0 1 0 0
set p [vmoveto 200 200]
vpoint pp {*}$p
vsetcolor pp RED
checkpoint p $p {-0.34896 9.94397 0.27411} 0.0001
vdump ${imagedir}/${casename}.png

View File

@ -2,12 +2,6 @@ puts "========"
puts "Sensitive box selection"
puts "========"
proc checkPoint {theName theValue theExpected} {
set e 0.0001
foreach i {0 1 2} { if { [expr abs([lindex $theValue $i] - [lindex $theExpected $i])] > $e } { puts "Error: wrong picked point $theName" } }
return
}
# create sphere
sphere ss 10
mkface s ss
@ -28,7 +22,7 @@ if {[string first "e+308" $p1] != -1} {
puts "Faulty : Selection 1"
}
vpoint pp1 {*}$p1
checkPoint pp1 $p1 {-1.7763568394002505e-15 -0.51078486684208357 0.59985611160264973}
checkpoint pp1 $p1 {-1.7763568394002505e-15 -0.51078486684208357 0.59985611160264973} 0.0001
vdump $::imagedir/${::casename}_clip1_selection_axo.png
vtop
vdump $::imagedir/${::casename}_clip1_selection_top.png
@ -45,7 +39,7 @@ if {[string first "e+308" $p2] != -1} {
puts "Faulty : Selection 2"
}
vpoint pp2 {*}$p2
checkPoint pp2 $p2 {2.9999999999999991 -3.5107848668420845 3.5998561116026506}
checkpoint pp2 $p2 {2.9999999999999991 -3.5107848668420845 3.5998561116026506} 0.0001
vdump $::imagedir/${::casename}_clip2_selection_axo.png
vtop
vdump $::imagedir/${::casename}_clip2_selection_top.png