1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

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.
This commit is contained in:
vpa
2015-12-16 12:25:03 +03:00
committed by bugmaster
parent 4ff92abe44
commit e9312c0fc2
12 changed files with 272 additions and 48 deletions

View File

@@ -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

View File

@@ -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());

View File

@@ -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:

View File

@@ -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_BaseFrustum> SelectMgr_RectangularFrustum::ScaleAnd
cacheVertexProjections (aRes);
aRes->myViewClipRange = myViewClipRange;
return NCollection_Handle<SelectMgr_BaseFrustum> (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;
}

View File

@@ -17,6 +17,7 @@
#define _SelectMgr_RectangularFrustum_HeaderFile
#include <SelectMgr_Frustum.hxx>
#include <SelectMgr_ViewClipRange.hxx>
//! 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

View File

@@ -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<const SelectMgr_RectangularFrustum*> (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);
}

View File

@@ -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;

View File

@@ -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 <Standard_TypeDef.hxx>
//! 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

View File

@@ -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;
}