diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx index 42f3862a84..71d1142b7a 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx @@ -71,7 +71,7 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP aTc = (Abs (aTn) < Precision::Confusion() ? 0.0 : aTn / aTd); gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTc; - theDepth = myNearPickedPnt.Distance (aClosestPnt); + theDepth = myNearPickedPnt.Distance (aClosestPnt) * myScale; } // ======================================================================= @@ -109,7 +109,7 @@ void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const gp_Vec& thePl } gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + anU * aParam; - theDepth = myNearPickedPnt.Distance (aClosestPnt); + theDepth = myNearPickedPnt.Distance (aClosestPnt) * myScale; } namespace @@ -275,6 +275,8 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint) // compute vertices projections onto frustum normals and // {i, j, k} vectors and store them to corresponding class fields cacheVertexProjections (this); + + myScale = 1.0; } // ======================================================================= @@ -301,6 +303,8 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt, // compute vertices projections onto frustum normals and // {i, j, k} vectors and store them to corresponding class fields cacheVertexProjections (this); + + myScale = 1.0; } // ======================================================================= @@ -382,6 +386,8 @@ NCollection_Handle SelectMgr_RectangularFrustum::ScaleAnd aRes->myEdgeDirs[4] = aRes->myVertices[0].XYZ() - aRes->myVertices[1].XYZ(); // RightUpper aRes->myEdgeDirs[5] = aRes->myVertices[4].XYZ() - aRes->myVertices[5].XYZ(); + + aRes->myScale = 1.0 / theTrsf.ScaleFactor(); } // compute frustum normals @@ -441,7 +447,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt, gp_Pnt aDetectedPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * (aV.Dot (myViewRayDir.XYZ()) / myViewRayDir.Dot (myViewRayDir)); - theDepth = aDetectedPnt.Distance (myNearPickedPnt); + theDepth = aDetectedPnt.Distance (myNearPickedPnt) * myScale; return Standard_True; } @@ -567,7 +573,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, // handle the case when triangle normal and selecting frustum direction are orthogonal: for this case, overlap // 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); + theDepth = aTriangleNormal.Dot (aDiff) * myScale; return Standard_True; } @@ -585,7 +591,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, if (isInterior) { gp_Pnt aDetectedPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime; - theDepth = myNearPickedPnt.Distance (aDetectedPnt); + theDepth = myNearPickedPnt.Distance (aDetectedPnt) * myScale; return Standard_True; } @@ -617,7 +623,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, // ======================================================================= Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG) { - return theCOG.Distance (myNearPickedPnt); + return theCOG.Distance (myNearPickedPnt) * myScale; } // ======================================================================= diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx index 1d8ec5a3f8..ba229c0a70 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx @@ -33,7 +33,7 @@ class SelectMgr_RectangularFrustum : public SelectMgr_Frustum<4> { public: - SelectMgr_RectangularFrustum() {}; + 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; @@ -138,6 +138,7 @@ private: 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 }; #endif // _SelectMgr_RectangularFrustum_HeaderFile diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx index 500be63417..551ab88a16 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -269,27 +269,26 @@ void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_Sensiti SelectMgr_FrustumCache& theCachedMgrs, SelectMgr_SelectingVolumeManager& theResMgr) { - Standard_Integer aScale = 1; - const Standard_Boolean toScale = isToScaleFrustum (theEnt); - if (toScale) + Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1; + const gp_Trsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf; + const Standard_Boolean toScale = aScale != 1; + const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity; + if (toScale && toTransform) { - aScale = sensitivity (theEnt); - } - if (theEnt->HasInitLocation()) - { - theResMgr = - mySelectingVolumeMgr.ScaleAndTransform (aScale, theEnt->InvInitLocation() * theInvTrsf); + theResMgr = mySelectingVolumeMgr.ScaleAndTransform (aScale, aTrsfMtr); } else if (toScale) { if (!theCachedMgrs.IsBound (aScale)) { - theCachedMgrs.Bind (aScale, - mySelectingVolumeMgr.ScaleAndTransform(aScale, theInvTrsf)); + theCachedMgrs.Bind (aScale, mySelectingVolumeMgr.ScaleAndTransform (aScale, gp_Trsf())); } - theResMgr = theCachedMgrs.Find (aScale); } + else if (toTransform) + { + theResMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTrsfMtr); + } } //======================================================================= diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index d59dd06ac4..660ed26756 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -4428,17 +4428,42 @@ static Standard_Integer VState (Draw_Interpretor& theDI, { theDI << "Detected entities:\n"; Handle(StdSelect_ViewerSelector3d) aSelector = aCtx->HasOpenedContext() ? aCtx->LocalSelector() : aCtx->MainSelector(); + SelectMgr_SelectingVolumeManager aMgr = aSelector->GetManager(); for (aSelector->InitDetected(); aSelector->MoreDetected(); aSelector->NextDetected()) { const Handle(SelectBasics_SensitiveEntity)& anEntity = aSelector->DetectedEntity(); Handle(SelectMgr_EntityOwner) anOwner = Handle(SelectMgr_EntityOwner)::DownCast (anEntity->OwnerId()); Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable()); - SelectMgr_SelectingVolumeManager aMgr = - anObj->HasTransformation() ? aSelector->GetManager().ScaleAndTransform (1, anObj->InversedTransformation()) - : aSelector->GetManager(); + gp_Trsf anInvTrsf; + if (anObj->TransformPersistence().Flags) + { + const Graphic3d_Mat4d& aProjection = aMgr.ProjectionMatrix(); + const Graphic3d_Mat4d& aWorldView = aMgr.WorldViewMatrix(); + + Graphic3d_Mat4d aMat = anObj->TransformPersistence().Compute (aProjection, aWorldView, 0, 0); + anInvTrsf.SetValues (aMat.GetValue (0, 0), aMat.GetValue (0, 1), aMat.GetValue (0, 2), aMat.GetValue (0, 3), + aMat.GetValue (1, 0), aMat.GetValue (1, 1), aMat.GetValue (1, 2), aMat.GetValue (1, 3), + aMat.GetValue (2, 0), aMat.GetValue (2, 1), aMat.GetValue (2, 2), aMat.GetValue (2, 3)); + anInvTrsf.Invert(); + } + if (anObj->HasTransformation()) + { + anInvTrsf = anObj->InversedTransformation() * anInvTrsf; + } + if (anEntity->HasInitLocation()) + { + anInvTrsf = anEntity->InvInitLocation() * anInvTrsf; + } + const Standard_Integer aScale = anEntity->SensitivityFactor() < aSelector->PixelTolerance() + ? anEntity->SensitivityFactor() : 1; + const Standard_Boolean isToScaleAndTransform = anInvTrsf.Form() != gp_Identity || aScale != 1; + SelectMgr_SelectingVolumeManager anEntMgr = + isToScaleAndTransform ? aMgr.ScaleAndTransform (aScale, anInvTrsf) + : aMgr; SelectBasics_PickResult aResult; - anEntity->Matches (aMgr, aResult); - gp_Pnt aDetectedPnt = aMgr.DetectedPoint (aResult.Depth()); + anEntity->Matches (anEntMgr, aResult); + gp_Pnt aDetectedPnt = anInvTrsf.Form() == gp_Identity ? + anEntMgr.DetectedPoint (aResult.Depth()) : anEntMgr.DetectedPoint (aResult.Depth()).Transformed (anInvTrsf.Inverted()); TCollection_AsciiString aName = GetMapOfAIS().Find1 (anObj); aName.LeftJustify (20, ' '); diff --git a/tests/bugs/vis/bug26719_1 b/tests/bugs/vis/bug26719_1 new file mode 100644 index 0000000000..6cbcce5506 --- /dev/null +++ b/tests/bugs/vis/bug26719_1 @@ -0,0 +1,68 @@ +puts "============" +puts "CR26719" +puts "============" +puts "" + +########################################################################################## +puts "Visualization - cannot pick zoom persistent object" +########################################################################################## + +pload VISUALIZATION MODELING + +vinit +vsetdispmode 1 + +restore $env(CASROOT)/data/occ/face1.brep f +vdisplay f +box b1 50 50 50 +vdisplay b1 -trsfPers zoom -trsfPersPos 0 0 0 + +vviewparams -scale 588.7 -proj 0.69 -0.64 -0.38 +vviewparams -up -0.16 -0.32 0.93 -at -0.47 -0.042 0.4 +vviewparams -eye 0.7 -1.14 -0.17 + +# move cursor to the box and check if is highlighted +# with dynamic highlight color, check that the face is +# not highlighted +vmoveto 280 290 +if {[vreadpixel 290 297 name] != "CYAN1 1"} { + puts "ERROR: zoom persistent box is not highlighted dynamically!" +} +if {[vreadpixel 372 210 name] != "GOLDENROD1 1"} { + puts "ERROR: the shape behind zoom persistent object was highlighted instead!" +} +vdump ${imagedir}/${casename}_1.png + +vmoveto 0 0 + +vviewparams -scale 689.79 -proj 0.78 0.63 -0.00067 +vviewparams -up -0.13 0.16 -0.98 -at -0.36 -0.016 0.31 +vviewparams -eye 0.96 1.053 0.31 + +# check if the depth is calculated correctly on border points +# of the objects + +# move to a point on the box and check if it +# will be highlighted dynamically +vmoveto 264 135 +if {[vreadpixel 276 142 name] != "CYAN1 1"} { + puts "ERROR: zoom persistent box is not highlighted dynamically in precision test!" +} +if {[vreadpixel 243 123 name] != "LIGHTGOLDENROD1 1"} { + puts "ERROR: the shape behind zoom persistent object was highlighted instead in precision test!" +} +vdump ${imagedir}/${casename}_2.png +vmoveto 0 0 + +# move to a point on the face and check if it +# will be highlighted dynamically +vmoveto 263 135 +if {[vreadpixel 276 142 name] != "GOLDENROD2 1"} { + puts "ERROR: zoom persistent box is highlighted instead in precision test!" +} +if {[vreadpixel 243 123 name] != "CYAN1 1"} { + puts "ERROR: the shape behind zoom persistent object was not highlighted dynamically in precision test!" +} +vdump ${imagedir}/${casename}_3.png + +set only_screen 1 diff --git a/tests/bugs/vis/bug26719_2 b/tests/bugs/vis/bug26719_2 new file mode 100644 index 0000000000..9d903f6a39 --- /dev/null +++ b/tests/bugs/vis/bug26719_2 @@ -0,0 +1,79 @@ +puts "============" +puts "CR26719" +puts "============" +puts "" + +########################################################################################## +puts "Visualization - cannot pick zoom persistent object" +########################################################################################## + +proc compareDepth {theInfo} { + set aInfoList [split $theInfo "\n"] + set aEntNb [llength $aInfoList] + set aDepths {} + for {set aEntIdx 0} {$aEntIdx < $aEntNb} {incr aEntIdx} { + set aBuff [lindex $aInfoList $aEntIdx] + set aStringArr [split $aBuff " "] + set aSize [llength $aStringArr] + for {set aIdx 0} {$aIdx < $aSize} {incr aIdx} { + set aItem [lindex $aBuff $aIdx] + if {[string compare $aItem "Depth:"] == 0} { + lappend aDepths [string trim [lindex $aBuff [expr $aIdx + 1]]] + } + } + } + + set aDepth1 [lindex $aDepths 0] + set aDepth2 [lindex $aDepths 1] + set aDiff [expr $aDepth1 - $aDepth2] + if {[expr abs($aDiff)] > 0.55} { + puts "ERROR: the depths diff is bigger than adequate tolerance, see vstate output!" + } +} + +pload VISUALIZATION MODELING + +vinit +vtrihedron tri +vpan 50 50 + +box b1 50 50 50 +box b2 50 50 50 +box b3 150 150 150 100 100 100 + +vpoint p1 200 200 200 + +vdisplay b1 -trsfPers zoom -trsfPersPos 200 200 200 +vdisplay b2 -trsfPers zoom -trsfPersPos 200 200 200 +vsetlocation b2 -50 -50 -50 +vdisplay b3 + +vsetdispmode 1 +vaspects b1 -setColor RED +vaspects b2 -setColor GREEN + +# setup the view in a way that front faces of b2 and b3 lie +# almost on the same plane +vviewparams -scale 0.99 -proj -0.04 -0.99 0.11 +vviewparams -up -0.58 0.16 0.8 -at 8.48 160.93 282.42 +vviewparams -eye -14.63 -379.49 343.06 +# check depth values +vmoveto 230 280 +set anInfo [vstate -entities] +compareDepth $anInfo +vdump ${imagedir}/${casename}_1.png + +vmoveto 0 0 + +# setup the view in a way that front faces of b1 and b3 lie +# almost on the same plane +vviewparams -scale 0.99 -proj -0.17 0.09 0.98 +vviewparams -up -0.1 0.99 -0.1 -at -49.98 231.47 25.2 +vviewparams -eye -142.03 280.17 559.45 +# check depth values +vmoveto 276 110 +set anInfo [vstate -entities] +compareDepth $anInfo +vdump ${imagedir}/${casename}_2.png + +set only_screen 1