0026719: Visualization - cannot pick zoom persistent object
authorvpa <vpa@opencascade.com>
Thu, 8 Oct 2015 11:02:39 +0000 (14:02 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 15 Oct 2015 09:25:24 +0000 (12:25 +0300)
- trsf matrix scale factor is now taken into account in depth and distance calculation in selection;
- fixed trsf matrix application error in frustum cache in SelectMgr_ViewerSelector;
- fixed multiple errors in vstate output;
- test cases for issue #26719.

src/SelectMgr/SelectMgr_RectangularFrustum.cxx
src/SelectMgr/SelectMgr_RectangularFrustum.hxx
src/SelectMgr/SelectMgr_ViewerSelector.cxx
src/ViewerTest/ViewerTest.cxx
tests/bugs/vis/bug26719_1 [new file with mode: 0644]
tests/bugs/vis/bug26719_2 [new file with mode: 0644]

index 42f3862..71d1142 100644 (file)
@@ -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_BaseFrustum> 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;
 }
 
 // =======================================================================
index 1d8ec5a..ba229c0 100644 (file)
@@ -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
index 500be63..551ab88 100644 (file)
@@ -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);
+  }
 }
 
 //=======================================================================
index d59dd06..660ed26 100644 (file)
@@ -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 (file)
index 0000000..6cbcce5
--- /dev/null
@@ -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 (file)
index 0000000..9d903f6
--- /dev/null
@@ -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