From: vpa Date: Wed, 16 Dec 2015 09:25:03 +0000 (+0300) Subject: 0026973: Visualization - selection of entities hidden by clipping planes is broken X-Git-Tag: V7_0_0_beta~37 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=e9312c0fc247b3627abaffed1b7fcfacfd2d4409 0026973: Visualization - selection of entities hidden by clipping planes is broken - misprint in distance calculation in SelectMgr_RectangularFrustum::IsClipped is corrected; - selecting volume manager in clipping check in SelectMgr_ViewerSelector::checkOverlap was replaced ; - added view-defined clipping planes check to SelectMgr_RectangularFrustum; - test case for issue #26973. --- diff --git a/src/SelectMgr/FILES b/src/SelectMgr/FILES index cd3af8a2a6..d91a639f93 100755 --- a/src/SelectMgr/FILES +++ b/src/SelectMgr/FILES @@ -58,6 +58,7 @@ SelectMgr_TriangularFrustumSet.hxx SelectMgr_TypeOfBVHUpdate.hxx SelectMgr_TypeOfUpdate.hxx SelectMgr_VectorTypes.hxx +SelectMgr_ViewClipRange.hxx SelectMgr_ViewerSelector.cxx SelectMgr_ViewerSelector.hxx SelectMgr_ViewerSelector.lxx diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.cxx b/src/SelectMgr/SelectMgr_BaseFrustum.cxx index 88ac8d7a5d..aecd3ad365 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.cxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.cxx @@ -220,6 +220,10 @@ Standard_Real SelectMgr_BaseFrustum::DistToGeometryCenter (const gp_Pnt& /*theCO return DBL_MAX; } +//======================================================================= +// function : DetectedPoint +// purpose : +//======================================================================= gp_Pnt SelectMgr_BaseFrustum::DetectedPoint (const Standard_Real /*theDepth*/) const { return gp_Pnt (RealLast(), RealLast(), RealLast()); diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.hxx b/src/SelectMgr/SelectMgr_BaseFrustum.hxx index b1ba2d5bdb..c4adf95080 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.hxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.hxx @@ -158,6 +158,10 @@ public: Standard_EXPORT virtual Standard_Boolean IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes, const Standard_Real theDepth); + //! Valid for point selection only! + //! Computes depth range for global (defined for the whole view) clipping planes. + Standard_EXPORT virtual void SetViewClipping (const Graphic3d_SequenceOfHClipPlane& /*thePlanes*/) {}; + DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseFrustum,Standard_Transient) protected: diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx index 71d1142b7a..ff65aa7cb3 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx @@ -276,6 +276,8 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint) // {i, j, k} vectors and store them to corresponding class fields cacheVertexProjections (this); + myViewClipRange.Clear(); + myScale = 1.0; } @@ -304,6 +306,8 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt, // {i, j, k} vectors and store them to corresponding class fields cacheVertexProjections (this); + myViewClipRange.Clear(); + myScale = 1.0; } @@ -395,6 +399,8 @@ NCollection_Handle SelectMgr_RectangularFrustum::ScaleAnd cacheVertexProjections (aRes); + aRes->myViewClipRange = myViewClipRange; + return NCollection_Handle (aRes); } @@ -430,7 +436,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t theDepth = aNearestPnt.Distance (myNearPickedPnt); - return Standard_True; + return isViewClippingOk (theDepth); } // ======================================================================= @@ -449,7 +455,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt, theDepth = aDetectedPnt.Distance (myNearPickedPnt) * myScale; - return Standard_True; + return isViewClippingOk (theDepth); } // ======================================================================= @@ -474,7 +480,8 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, return Standard_False; segmentSegmentDistance (thePnt1, thePnt2, theDepth); - return Standard_True; + + return isViewClippingOk (theDepth); } // ======================================================================= @@ -524,7 +531,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const Handle(TColgp_HAr theDepth); } - return Standard_True; + return isViewClippingOk (theDepth); } // ======================================================================= @@ -574,7 +581,8 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, // is detected correctly, and distance to triangle's plane can be measured as distance to its arbitrary vertex. const gp_XYZ aDiff = myNearPickedPnt.XYZ() - thePnt1.XYZ(); theDepth = aTriangleNormal.Dot (aDiff) * myScale; - return Standard_True; + + return isViewClippingOk (theDepth); } gp_XYZ anEdge = (thePnt1.XYZ() - myNearPickedPnt.XYZ()) * (1.0 / anAlpha); @@ -592,7 +600,8 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, { gp_Pnt aDetectedPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime; theDepth = myNearPickedPnt.Distance (aDetectedPnt) * myScale; - return Standard_True; + + return isViewClippingOk (theDepth); } gp_Pnt aPnts[3] = {thePnt1, thePnt2, thePnt3}; @@ -613,7 +622,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, segmentSegmentDistance (aPnts[aNearestEdgeIdx], aPnts[(aNearestEdgeIdx + 1) % 3], theDepth); } - return Standard_True; + return isViewClippingOk (theDepth); } // ======================================================================= @@ -637,18 +646,17 @@ gp_Pnt SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth } // ======================================================================= -// function : IsClipped -// purpose : Checks if the point of sensitive in which selection was -// detected belongs to the region defined by clipping planes +// function : computeClippingRange +// purpose : // ======================================================================= -Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes, - const Standard_Real theDepth) +void SelectMgr_RectangularFrustum::computeClippingRange (const Graphic3d_SequenceOfHClipPlane& thePlanes, + Standard_Real& theDepthMin, + Standard_Real& theDepthMax) { - Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes); - Standard_Real aMaxDepth = DBL_MAX; - Standard_Real aMinDepth = -DBL_MAX; + theDepthMax = DBL_MAX; + theDepthMin = -DBL_MAX; Standard_Real aPlaneA, aPlaneB, aPlaneC, aPlaneD; - for ( ; aPlaneIt.More(); aPlaneIt.Next()) + for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes); aPlaneIt.More(); aPlaneIt.Next()) { const Handle(Graphic3d_ClipPlane)& aClipPlane = aPlaneIt.Value(); if (!aClipPlane->IsOn()) @@ -660,9 +668,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_Sequen const gp_XYZ& aPlaneDirXYZ = aGeomPlane.Axis().Direction().XYZ(); - Standard_Real aDotProduct = myViewRayDir.XYZ().Dot (aPlaneDirXYZ); - Standard_Real aDistance = - myNearPickedPnt.XYZ().Dot (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()) @@ -687,13 +695,55 @@ Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_Sequen // change depth limits for case of opposite and directed planes if (aDotProduct < 0.0) { - aMaxDepth = Min (aDistToPln, aMaxDepth); + theDepthMax = Min (aDistToPln, theDepthMax); } - else if (aDistToPln > aMinDepth) + else if (aDistToPln > theDepthMin) { - aMinDepth = Max (aDistToPln, aMinDepth); + theDepthMin = Max (aDistToPln, theDepthMin); } } +} + +// ======================================================================= +// 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) +{ + Standard_Real aMaxDepth, aMinDepth; + computeClippingRange (thePlanes, aMinDepth, aMaxDepth); return (theDepth <= aMinDepth || theDepth >= aMaxDepth); } + +// ======================================================================= +// function : SetViewClipping +// purpose : +// ======================================================================= +void SelectMgr_RectangularFrustum::SetViewClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes) +{ + if (thePlanes.Size() == 0) + { + myViewClipRange.Clear(); + return; + } + + Standard_Real aMaxDepth, aMinDepth; + computeClippingRange (thePlanes, aMinDepth, aMaxDepth); + myViewClipRange.Set (aMinDepth, aMaxDepth); +} + +// ======================================================================= +// function : isViewClippingOk +// purpose : +// ======================================================================= +Standard_Boolean SelectMgr_RectangularFrustum::isViewClippingOk (const Standard_Real theDepth) const +{ + if (!myViewClipRange.IsValid()) + return Standard_True; + + return myViewClipRange.MaxDepth() > theDepth + && myViewClipRange.MinDepth() < theDepth; +} diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx index ba229c0a70..c1d4ca79bd 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx @@ -17,6 +17,7 @@ #define _SelectMgr_RectangularFrustum_HeaderFile #include +#include //! This class contains representation of rectangular selecting frustum, created in case //! of point and box selection, and algorithms for overlap detection between selecting @@ -106,6 +107,10 @@ public: Standard_EXPORT virtual Standard_Boolean IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes, const Standard_Real theDepth) 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 Graphic3d_SequenceOfHClipPlane& thePlanes) Standard_OVERRIDE; + //! A set of helper functions that return rectangular selecting frustum data inline const gp_Pnt* GetVertices() const { return myVertices; } @@ -122,6 +127,14 @@ protected: const gp_Pnt& thePntOnPlane, Standard_Real& theDepth); + //! Computes valid depth range for the given clipping planes + Standard_EXPORT void computeClippingRange (const Graphic3d_SequenceOfHClipPlane& thePlanes, + Standard_Real& theDepthMin, + Standard_Real& theDepthMax); + + //! Returns false if theDepth must be clipped by current view clip range + Standard_EXPORT Standard_Boolean isViewClippingOk (const Standard_Real theDepth) const; + private: void cacheVertexProjections (SelectMgr_RectangularFrustum* theFrustum); @@ -134,11 +147,12 @@ private: 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 - Standard_Real myScale; //!< Scale factor of applied transformation, if there was any + 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 + Standard_Real myScale; //!< Scale factor of applied transformation, if there was any + SelectMgr_ViewClipRange myViewClipRange; }; #endif // _SelectMgr_RectangularFrustum_HeaderFile diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx index d558502e94..69a7ca4c28 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx @@ -361,7 +361,7 @@ gp_Pnt SelectMgr_SelectingVolumeManager::DetectedPoint (const Standard_Real theD Standard_Boolean SelectMgr_SelectingVolumeManager::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes, const Standard_Real& theDepth) { - if (myActiveSelectionType == Point) + if (myActiveSelectionType != Point) return Standard_False; return mySelectingVolumes[Frustum]->IsClipped (thePlanes, theDepth); @@ -428,3 +428,15 @@ gp_Pnt SelectMgr_SelectingVolumeManager::GetFarPnt() const reinterpret_cast (mySelectingVolumes[myActiveSelectionType / 2].get()); return aFr->GetFarPnt(); } + +//======================================================================= +// function : SetViewClipping +// purpose : +//======================================================================= +void SelectMgr_SelectingVolumeManager::SetViewClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes) +{ + if (myActiveSelectionType != Point) + return; + + mySelectingVolumes[Frustum]->SetViewClipping (thePlanes); +} diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx index d4e1dd6a9f..ec63b43e1b 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx @@ -155,6 +155,10 @@ public: Standard_EXPORT virtual Standard_Boolean IsOverlapAllowed() const Standard_OVERRIDE; + //! Valid for point selection only! + //! Computes depth range for global (defined for the whole view) clipping planes. + Standard_EXPORT void SetViewClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes); + //! A set of helper functions that return rectangular selecting frustum data Standard_EXPORT const gp_Pnt* GetVertices() const; diff --git a/src/SelectMgr/SelectMgr_ViewClipRange.hxx b/src/SelectMgr/SelectMgr_ViewClipRange.hxx new file mode 100644 index 0000000000..7fc0931aae --- /dev/null +++ b/src/SelectMgr/SelectMgr_ViewClipRange.hxx @@ -0,0 +1,73 @@ +// Created on: 2015-12-15 +// Created by: Varvara POSKONINA +// Copyright (c) 2005-2014 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_ViewClipRange_HeaderFile +#define _SelectMgr_ViewClipRange_HeaderFile + +#include + +//! Class for handling depth clipping range. +//! It is used to perform checks in case if global (for the whole view) +//! clipping planes are defined inside of SelectMgr_RectangularFrustum +//! class methods. +class SelectMgr_ViewClipRange +{ +public: + //! Creates new empty view clip range + SelectMgr_ViewClipRange() + { + Clear(); + } + + //! Sets boundaries and validates view clipping range + void Set (const Standard_Real theDepthMin, const Standard_Real theDepthMax) + { + myMin = theDepthMin; + myMax = theDepthMax; + myIsValid = Standard_True; + } + + //! Returns true if clip range is set and depth of each matched + //! primitive must be tested for satisfying the defined interval + Standard_Boolean IsValid() const + { + return myIsValid; + } + + //! Returns the upper bound of valid depth range + Standard_Real MaxDepth() const + { + return myMax; + } + + //! Returns the lower bound of valid depth range + Standard_Real MinDepth() const + { + return myMin; + } + + //! Invalidates view clipping range + void Clear() + { + myIsValid = Standard_False; + } + +private: + Standard_Real myMin; //!< Lower bound of valid depth range + Standard_Real myMax; //!< Upper bound of valid depth range + Standard_Boolean myIsValid; //!< The flag is set to true when range boundaries are set and depth check must be performed +}; + +#endif // _SelectMgr_ViewClipRange_HeaderFile diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx index 94c2bf4348..1e2d3d9e2b 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -230,8 +230,8 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive { if (HasDepthClipping (anOwner) && theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point) { - Standard_Boolean isClipped = theMgr.IsClipped (anOwner->Selectable()->GetClipPlanes(), - aPickResult.Depth()); + Standard_Boolean isClipped = mySelectingVolumeMgr.IsClipped (anOwner->Selectable()->GetClipPlanes(), + aPickResult.Depth()); if (isClipped) return; } diff --git a/src/StdSelect/StdSelect_ViewerSelector3d.cxx b/src/StdSelect/StdSelect_ViewerSelector3d.cxx index d9021b30c2..b45f8eba91 100644 --- a/src/StdSelect/StdSelect_ViewerSelector3d.cxx +++ b/src/StdSelect/StdSelect_ViewerSelector3d.cxx @@ -113,8 +113,6 @@ void StdSelect_ViewerSelector3d::Pick (const Standard_Integer theXPix, const Standard_Integer theYPix, const Handle(V3d_View)& theView) { - SetClipping (theView->GetClipPlanes()); - if(myToUpdateTolerance) { mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance()); @@ -129,6 +127,7 @@ void StdSelect_ViewerSelector3d::Pick (const Standard_Integer theXPix, gp_Pnt2d aMousePos (static_cast (theXPix), static_cast (theYPix)); mySelectingVolumeMgr.BuildSelectingVolume (aMousePos); + mySelectingVolumeMgr.SetViewClipping (theView->GetClipPlanes()); TraverseSensitives(); } @@ -650,15 +649,6 @@ void StdSelect_ViewerSelector3d::ComputeSensitivePrs (const Handle(Graphic3d_Str } } -//======================================================================= -//function : SetClipping -//purpose : -//======================================================================= -void StdSelect_ViewerSelector3d::SetClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes) -{ - myClipPlanes = thePlanes; -} - //======================================================================= //function : HasDepthClipping //purpose : diff --git a/src/StdSelect/StdSelect_ViewerSelector3d.hxx b/src/StdSelect/StdSelect_ViewerSelector3d.hxx index d68f95d71a..8659b032c3 100644 --- a/src/StdSelect/StdSelect_ViewerSelector3d.hxx +++ b/src/StdSelect/StdSelect_ViewerSelector3d.hxx @@ -83,12 +83,6 @@ public: DEFINE_STANDARD_RTTIEXT(StdSelect_ViewerSelector3d,SelectMgr_ViewerSelector) -protected: - - //! Set view clipping for the selector. - //! @param thePlanes [in] the view planes. - Standard_EXPORT void SetClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes); - private: void ComputeSensitivePrs (const Handle(Graphic3d_Structure)& theStructure, @@ -97,7 +91,6 @@ private: const Graphic3d_TransformPers& theTransPers); Graphic3d_SequenceOfStructure myStructs; - Graphic3d_SequenceOfHClipPlane myClipPlanes; }; DEFINE_STANDARD_HANDLE(StdSelect_ViewerSelector3d, SelectMgr_ViewerSelector) diff --git a/tests/bugs/vis/bug26973 b/tests/bugs/vis/bug26973 new file mode 100644 index 0000000000..4b3b48e22c --- /dev/null +++ b/tests/bugs/vis/bug26973 @@ -0,0 +1,79 @@ +puts "============" +puts "CR26973" +puts "============" +puts "" + +########################################################################################## +puts "Visualization - selection of entities hidden by clipping planes is broken" +########################################################################################## + +pload MODELING VISUALIZATION + +vinit View1 +vclear +vaxo +vsetdispmode 1 + +proc OCC26973 { toTestViewPlanes toApplyTrsf theImgIdr theCaseName} { + if {$toApplyTrsf == "1"} { + box b -100 -100 -100 1 1 1 + ttranslate b 100 100 100 + } else { + box b 1 1 1 + } + + vdisplay b + vfit + vselmode b 4 1 + + vclipplane create pln + if {$toTestViewPlanes == "1"} { + vclipplane set pln view Driver1/Viewer1/View1 + } else { + vclipplane set pln object b + } + vclipplane change pln equation 0 1 0 -0.5 + + vselect 200 140 + set aTestInfo "Test case: " + append aTestInfo "clipping planes applied to " + set aDumpFileName $theImgIdr/${theCaseName} + if {$toTestViewPlanes == "1"} { + append aTestInfo "view, " + append aDumpFileName "_view" + } else { + append aTestInfo "object, " + append aDumpFileName "_obj" + } + append aTestInfo "object trsf is " + if {$toApplyTrsf == "1"} { + append aTestInfo "on" + append aDumpFileName "_with_trsf.png" + } else { + append aTestInfo "off" + append aDumpFileName "_wo_trsf.png" + } + + if {[vnbselected] != 1} { + puts "ERROR: can not select face." + puts $aTestInfo + } + set aSelectedFace [string trim [lindex [split [vstate] "\n"] 1] ] + if {$aSelectedFace != "Face #1"} { + puts "ERROR: wrong face is selected." + puts "Actually seleced face: $aSelectedFace" + puts $aTestInfo + } + + vdump $aDumpFileName + vremove -all + vclipplane delete pln +} + +# check global clipping planes selection +OCC26973 1 0 $imagedir $casename +OCC26973 1 1 $imagedir $casename + +# check object clipping planes selection +OCC26973 0 0 $imagedir $casename +OCC26973 0 1 $imagedir $casename