Files
OCCT/src/SelectMgr/SelectMgr_SortCriterion.hxx
mzernova b0afa94d10 0027848: Visualization - sensitivity of lines is too high
Improved objects sorting by depth.

The sensitivity calculation for the manipulator has been changed.
Now the sensitivity of the elements of the manipulator depends on its size.

Also fixed the problem of erroneous selection of unfilled circles (SelectMgr_Frustum<N>::hasCircleOverlap() function).

Test case vselect/bugs/bug27848 added.
2023-02-04 09:17:58 +00:00

129 lines
4.5 KiB
C++

// Created on: 1998-03-26
// Created by: Robert COUBLANC
// Copyright (c) 1998-1999 Matra Datavision
// Copyright (c) 1999-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_SortCriterion_HeaderFile
#define _SelectMgr_SortCriterion_HeaderFile
#include <Graphic3d_Vec3.hxx>
#include <Precision.hxx>
#include <Select3D_SensitiveEntity.hxx>
//! This class provides data and criterion for sorting candidate
//! entities in the process of interactive selection by mouse click
class SelectMgr_SortCriterion
{
public:
Handle(Select3D_SensitiveEntity) Entity; //!< detected entity
gp_Pnt Point; //!< 3D point
Graphic3d_Vec3 Normal; //!< surface normal or 0 vector if undefined
Standard_Real Depth; //!< distance from the view plane to the entity
Standard_Real MinDist; //!< distance from the clicked point to the entity on the view plane
Standard_Real Tolerance; //!< tolerance used for selecting candidates
Standard_Integer Priority; //!< selection priority
Standard_Integer ZLayerPosition; //!< ZLayer rendering order index, stronger than a depth
Standard_Integer NbOwnerMatches; //!< overall number of entities collected for the same owner
public:
DEFINE_STANDARD_ALLOC
//! Empty constructor.
SelectMgr_SortCriterion()
: Depth (0.0),
MinDist (0.0),
Tolerance(0.0),
Priority (0),
ZLayerPosition (0),
NbOwnerMatches (0) {}
//! Compare with another item by depth, priority and minDist.
bool IsCloserDepth (const SelectMgr_SortCriterion& theOther) const
{
// the object within different ZLayer groups can not be compared by depth
if (ZLayerPosition != theOther.ZLayerPosition)
{
return ZLayerPosition > theOther.ZLayerPosition;
}
// closest object is selected if their depths are not equal within tolerance
if (Abs (Depth - theOther.Depth) > Tolerance + theOther.Tolerance)
{
return Depth < theOther.Depth;
}
Standard_Real aCos = 1.0;
if (Normal.Modulus() > 0 && theOther.Normal.Modulus() > 0)
{
gp_Dir aNormal (Normal.x(), Normal.y(), Normal.z());
gp_Dir anOtherNormal (theOther.Normal.x(), theOther.Normal.y(), theOther.Normal.z());
aCos = Abs (Cos (aNormal.Angle (anOtherNormal)));
}
Standard_Real aDepth = Depth - Tolerance;
Standard_Real anOtherDepth = theOther.Depth - theOther.Tolerance;
// Comparison depths taking into account tolerances occurs when the surfaces are parallel
// or have the same sensitivity and the angle between them is less than 60 degrees.
if (Abs (aDepth - anOtherDepth) > Precision::Confusion())
{
if ((aCos > 0.5 && Abs (Tolerance - theOther.Tolerance) < Precision::Confusion())
|| Abs (aCos - 1.0) < Precision::Confusion())
{
return aDepth < anOtherDepth;
}
}
// if two objects have similar depth, select the one with higher priority
if (Priority > theOther.Priority)
{
return true;
}
// if priorities are equal, one closest to the mouse
return Priority == theOther.Priority
&& MinDist < theOther.MinDist;
}
//! Compare with another item using old logic (OCCT version <= 6.3.1) with priority considered preceding depth.
bool IsHigherPriority (const SelectMgr_SortCriterion& theOther) const
{
// the object within different ZLayer groups can not be compared by depth
if (ZLayerPosition != theOther.ZLayerPosition)
{
return ZLayerPosition > theOther.ZLayerPosition;
}
if (Priority > theOther.Priority)
{
return true;
}
else if (Priority != theOther.Priority)
{
return false;
}
//if (Abs (Depth - theOther.Depth) <= (Tolerance + theOther.Tolerance))
if (Abs (Depth - theOther.Depth) <= Precision::Confusion())
{
return MinDist < theOther.MinDist;
}
return Depth < theOther.Depth;
}
};
#endif // _SelectMgr_SortCriterion_HeaderFile