mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-24 13:50:49 +03:00
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.
This commit is contained in:
@@ -1116,18 +1116,23 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
|
||||
const Standard_Integer theMode)
|
||||
{
|
||||
//Check mode
|
||||
AIS_ManipulatorMode aMode = (AIS_ManipulatorMode) theMode;
|
||||
const AIS_ManipulatorMode aMode = (AIS_ManipulatorMode) theMode;
|
||||
if (aMode == AIS_MM_None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Handle(SelectMgr_EntityOwner) anOwner;
|
||||
if (aMode == AIS_MM_None)
|
||||
{
|
||||
anOwner = new SelectMgr_EntityOwner (this, 5);
|
||||
}
|
||||
|
||||
if (aMode == AIS_MM_Translation || aMode == AIS_MM_None)
|
||||
// Sensitivity calculation for manipulator parts allows to avoid
|
||||
// overlapping of sensitive areas when size of manipulator is small.
|
||||
// Sensitivity is calculated relative to the default size of the manipulator (100.0f).
|
||||
const Standard_ShortReal aSensitivityCoef = myAxes[0].Size() / 100.0f;
|
||||
const Standard_Integer aHighSensitivity = Max (Min (RealToInt (aSensitivityCoef * 15), 15), 3); // clamp sensitivity within range [3, 15]
|
||||
const Standard_Integer aLowSensitivity = Max (Min (RealToInt (aSensitivityCoef * 10), 10), 2); // clamp sensitivity within range [2, 10]
|
||||
|
||||
switch (aMode)
|
||||
{
|
||||
case AIS_MM_Translation:
|
||||
{
|
||||
for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
|
||||
{
|
||||
@@ -1136,23 +1141,21 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
|
||||
continue;
|
||||
}
|
||||
const Axis& anAxis = myAxes[anIt];
|
||||
if (aMode != AIS_MM_None)
|
||||
{
|
||||
anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Translation, 9);
|
||||
}
|
||||
anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Translation, 9);
|
||||
|
||||
// define sensitivity by line
|
||||
Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment (anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
|
||||
aLine->SetSensitivityFactor (15);
|
||||
Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment(anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
|
||||
aLine->SetSensitivityFactor (aHighSensitivity);
|
||||
theSelection->Add (aLine);
|
||||
|
||||
// enlarge sensitivity by triangulation
|
||||
Handle(Select3D_SensitivePrimitiveArray) aTri = new Select3D_SensitivePrimitiveArray (anOwner);
|
||||
Handle(Select3D_SensitivePrimitiveArray) aTri = new Select3D_SensitivePrimitiveArray(anOwner);
|
||||
aTri->InitTriangulation (anAxis.TriangleArray()->Attributes(), anAxis.TriangleArray()->Indices(), TopLoc_Location());
|
||||
theSelection->Add (aTri);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (aMode == AIS_MM_Rotation || aMode == AIS_MM_None)
|
||||
case AIS_MM_Rotation:
|
||||
{
|
||||
for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
|
||||
{
|
||||
@@ -1161,22 +1164,20 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
|
||||
continue;
|
||||
}
|
||||
const Axis& anAxis = myAxes[anIt];
|
||||
if (aMode != AIS_MM_None)
|
||||
{
|
||||
anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Rotation, 9);
|
||||
}
|
||||
anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Rotation, 9);
|
||||
|
||||
// define sensitivity by circle
|
||||
const gp_Circ aGeomCircle (gp_Ax2 (gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
|
||||
Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle (anOwner, aGeomCircle);
|
||||
aCircle->SetSensitivityFactor (15);
|
||||
theSelection->Add (aCircle);
|
||||
const gp_Circ aGeomCircle (gp_Ax2(gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
|
||||
Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle(anOwner, aGeomCircle);
|
||||
aCircle->SetSensitivityFactor (aLowSensitivity);
|
||||
theSelection->Add(aCircle);
|
||||
// enlarge sensitivity by triangulation
|
||||
Handle(Select3D_SensitiveTriangulation) aTri = new ManipSensTriangulation (anOwner, myAxes[anIt].RotatorDisk().Triangulation(), anAxis.ReferenceAxis().Direction());
|
||||
Handle(Select3D_SensitiveTriangulation) aTri = new ManipSensTriangulation(anOwner, myAxes[anIt].RotatorDisk().Triangulation(), anAxis.ReferenceAxis().Direction());
|
||||
theSelection->Add (aTri);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (aMode == AIS_MM_Scaling || aMode == AIS_MM_None)
|
||||
case AIS_MM_Scaling:
|
||||
{
|
||||
for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
|
||||
{
|
||||
@@ -1184,21 +1185,19 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (aMode != AIS_MM_None)
|
||||
{
|
||||
anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Scaling, 9);
|
||||
}
|
||||
anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Scaling, 9);
|
||||
|
||||
// define sensitivity by point
|
||||
Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint (anOwner, myAxes[anIt].ScalerCubePosition());
|
||||
aPnt->SetSensitivityFactor (15);
|
||||
Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint(anOwner, myAxes[anIt].ScalerCubePosition());
|
||||
aPnt->SetSensitivityFactor (aHighSensitivity);
|
||||
theSelection->Add (aPnt);
|
||||
// enlarge sensitivity by triangulation
|
||||
Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].ScalerCube().Triangulation(), TopLoc_Location(), Standard_True);
|
||||
Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation(anOwner, myAxes[anIt].ScalerCube().Triangulation(), TopLoc_Location(), Standard_True);
|
||||
theSelection->Add (aTri);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (aMode == AIS_MM_TranslationPlane || aMode == AIS_MM_None)
|
||||
case AIS_MM_TranslationPlane:
|
||||
{
|
||||
for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
|
||||
{
|
||||
@@ -1206,28 +1205,33 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (aMode != AIS_MM_None)
|
||||
{
|
||||
anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_TranslationPlane, 9);
|
||||
}
|
||||
anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_TranslationPlane, 9);
|
||||
|
||||
// define sensitivity by two crossed lines
|
||||
gp_Pnt aP1, aP2;
|
||||
aP1 = myAxes[((anIt + 1) % 3)].TranslatorTipPosition();
|
||||
aP2 = myAxes[((anIt + 2) % 3)].TranslatorTipPosition();
|
||||
Standard_Real aSensitivityOffset = ZoomPersistence() ? aHighSensitivity * (0.5 + M_SQRT2) : 0.0;
|
||||
gp_Pnt aP1 = myAxes[((anIt + 1) % 3)].TranslatorTipPosition().Translated (myAxes[((anIt + 2) % 3)].ReferenceAxis().Direction().XYZ() * aSensitivityOffset);
|
||||
gp_Pnt aP2 = myAxes[((anIt + 2) % 3)].TranslatorTipPosition().Translated (myAxes[((anIt + 1) % 3)].ReferenceAxis().Direction().XYZ() * aSensitivityOffset);
|
||||
gp_XYZ aMidP = (aP1.XYZ() + aP2.XYZ()) / 2.0;
|
||||
gp_XYZ anOrig = aMidP.Normalized().Multiplied (aSensitivityOffset);
|
||||
|
||||
Handle(Select3D_SensitiveSegment) aLine1 = new Select3D_SensitiveSegment(anOwner, aP1, aP2);
|
||||
aLine1->SetSensitivityFactor(10);
|
||||
theSelection->Add(aLine1);
|
||||
Handle(Select3D_SensitiveSegment) aLine2 = new Select3D_SensitiveSegment(anOwner, gp::Origin(), aMidP);
|
||||
aLine2->SetSensitivityFactor(10);
|
||||
theSelection->Add(aLine2);
|
||||
aLine1->SetSensitivityFactor(aLowSensitivity);
|
||||
theSelection->Add (aLine1);
|
||||
Handle(Select3D_SensitiveSegment) aLine2 = new Select3D_SensitiveSegment(anOwner, anOrig, aMidP);
|
||||
aLine2->SetSensitivityFactor (aLowSensitivity);
|
||||
theSelection->Add (aLine2);
|
||||
|
||||
// enlarge sensitivity by triangulation
|
||||
Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation(anOwner, myAxes[anIt].DraggerSector().Triangulation(), TopLoc_Location(), Standard_True);
|
||||
theSelection->Add(aTri);
|
||||
Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation(anOwner, myAxes[anIt].DraggerSector().Triangulation(), TopLoc_Location(), Standard_True);
|
||||
theSelection->Add (aTri);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
anOwner = new SelectMgr_EntityOwner(this, 5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -869,32 +869,27 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCircleOverlap (const Standard_Real the
|
||||
const gp_Pnt aCenterProject (aCoefA * aTCenter,
|
||||
aCoefB * aTCenter,
|
||||
aCoefC * aTCenter);
|
||||
if (isDotInside (aCenterProject, aVertices))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Standard_Boolean isInside = true;
|
||||
const Standard_Boolean isCenterInside = isDotInside (aCenterProject, aVertices);
|
||||
|
||||
Standard_Boolean isInside = false;
|
||||
for (Standard_Integer anIdx = aVertices.Lower(); anIdx <= aVertices.Upper(); anIdx++)
|
||||
{
|
||||
if (aVertices.Value (anIdx).Distance (aCenterProject) > theRadius)
|
||||
{
|
||||
isInside = false;
|
||||
isInside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (theInside != NULL)
|
||||
{
|
||||
*theInside = false;
|
||||
*theInside = isInside && isCenterInside;
|
||||
}
|
||||
|
||||
if (!theIsFilled && isInside)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return isInside;
|
||||
return theIsFilled
|
||||
? !isInside || (isCenterInside && isInside)
|
||||
: isInside && isCenterInside;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@@ -58,12 +58,33 @@ public:
|
||||
return ZLayerPosition > theOther.ZLayerPosition;
|
||||
}
|
||||
|
||||
// closest object is selected unless difference is within tolerance
|
||||
if (Abs (Depth - theOther.Depth) > (Tolerance + theOther.Tolerance))
|
||||
// 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)
|
||||
{
|
||||
|
@@ -284,9 +284,9 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEnti
|
||||
aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
|
||||
if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box)
|
||||
{
|
||||
updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
|
||||
if (aCriterion.IsCloserDepth (*aPrevCriterion))
|
||||
{
|
||||
updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
|
||||
*aPrevCriterion = aCriterion;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user