]> OCCT Git - occt.git/commitdiff
0025723: Visualization, TKV3d - the center of rotation should be calculated taking...
authoribs <ibs@opencascade.com>
Thu, 12 Feb 2015 08:59:56 +0000 (11:59 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 12 Feb 2015 09:00:47 +0000 (12:00 +0300)
V3d_View::Gravity() - compute scene bounding box only including highlighted objects, if there are any, to provide context-oriented center of gravity.
Skip hidden objects, if there are any visible.
Do not return any value from this method.

Extend command vrotate with new flags -mouseStart and -mouseMove, to emulate rotation by mouse.

Unused argument theDi of VRotate disabled

src/V3d/V3d_View.cdl
src/V3d/V3d_View.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/bugs/vis/bug25723 [new file with mode: 0644]
tests/bugs/vis/bug25723_1 [new file with mode: 0644]

index 2bc996a5097a1020752b398e791965a0d1ea5501..2e13ad861355debc0a2bf776cf97aa93a1da87da 100644 (file)
@@ -1337,7 +1337,7 @@ is
         --          the objects contained in the view
         is static private;
 
-        Gravity ( me; X,Y,Z : out Coordinate ) returns Integer
+        Gravity ( me; X,Y,Z : out Coordinate )
         ---Purpose: Returns the Objects number and the gravity center
         --          of ALL viewable points in the view
         is static private;
index 5d16ad0e9a1d04f8e9064b4355b62d706e5152e8..d261682333f9090b0b1a4bfd975c2ff826a998fd 100644 (file)
@@ -151,6 +151,11 @@ To solve the problem (for lack of a better solution) I make 2 passes.
 
 #define DEUXPI (2. * M_PI)
 
+namespace
+{
+  static const Standard_Integer THE_NB_BOUND_POINTS = 8;
+}
+
 //=============================================================================
 //function : Constructor
 //purpose  :
@@ -2090,61 +2095,112 @@ Standard_Integer V3d_View::MinMax(Standard_Real& Xmin,
 //function : Gravity
 //purpose  :
 //=======================================================================
-Standard_Integer V3d_View::Gravity(Standard_Real& X, Standard_Real& Y, Standard_Real& Z) const
+void V3d_View::Gravity (Standard_Real& theX,
+                        Standard_Real& theY,
+                        Standard_Real& theZ) const
 {
-  Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax;
-  Standard_Integer Nstruct,Npoint ;
-  Graphic3d_MapOfStructure MySetOfStructures;
+  Graphic3d_MapOfStructure aSetOfStructures;
+  MyView->DisplayedStructures (aSetOfStructures);
+
+  Standard_Boolean hasSelection = Standard_False;
+  for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures);
+       aStructIter.More(); aStructIter.Next())
+  {
+    if (aStructIter.Key()->IsHighlighted()
+     && aStructIter.Key()->IsVisible())
+    {
+      hasSelection = Standard_True;
+      break;
+    }
+  }
 
-  MyView->DisplayedStructures (MySetOfStructures);
-  Nstruct = MySetOfStructures.Extent() ;
+  Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
+  Standard_Integer aNbPoints = 0;
+  gp_XYZ aResult (0.0, 0.0, 0.0);
+  for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures);
+       aStructIter.More(); aStructIter.Next())
+  {
+    const Handle(Graphic3d_Structure)& aStruct = aStructIter.Key();
+    if (!aStruct->IsVisible()
+    || (hasSelection && !aStruct->IsHighlighted())
+    ||  aStruct->IsEmpty())
+    {
+      continue;
+    }
+
+    Bnd_Box aBox = aStruct->MinMaxValues();
+    if (aBox.IsVoid())
+    {
+      continue;
+    }
+
+    // use camera projection to find gravity point
+    aBox.Get (Xmin, Ymin, Zmin,
+              Xmax, Ymax, Zmax);
+    gp_Pnt aPnts[THE_NB_BOUND_POINTS] =
+    {
+      gp_Pnt (Xmin, Ymin, Zmin), gp_Pnt (Xmin, Ymin, Zmax),
+      gp_Pnt (Xmin, Ymax, Zmin), gp_Pnt (Xmin, Ymax, Zmax),
+      gp_Pnt (Xmax, Ymin, Zmin), gp_Pnt (Xmax, Ymin, Zmax),
+      gp_Pnt (Xmax, Ymax, Zmin), gp_Pnt (Xmax, Ymax, Zmax)
+    };
 
-  Graphic3d_MapIteratorOfMapOfStructure MyIterator(MySetOfStructures) ;
+    for (Standard_Integer aPntIt = 0; aPntIt < THE_NB_BOUND_POINTS; ++aPntIt)
+    {
+      const gp_Pnt& aBndPnt    = aPnts[aPntIt];
+      const gp_Pnt  aProjected = myCamera->Project (aBndPnt);
+      if (Abs (aProjected.X()) <= 1.0
+       && Abs (aProjected.Y()) <= 1.0)
+      {
+        aResult += aBndPnt.XYZ();
+        ++aNbPoints;
+      }
+    }
+  }
 
-  Npoint = 0 ; X = Y = Z = 0. ;
-  for (; MyIterator.More(); MyIterator.Next())
+  if (aNbPoints == 0)
   {
-    const Handle(Graphic3d_Structure)& aStruct = MyIterator.Key();
-    if (!aStruct->IsEmpty())
+    for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures);
+         aStructIter.More(); aStructIter.Next())
     {
-      Bnd_Box aBox = aStruct->MinMaxValues();
+      const Handle(Graphic3d_Structure)& aStruct = aStructIter.Key();
+      if (aStruct->IsEmpty())
+      {
+        continue;
+      }
 
-      // Check bounding box for validness
+      Bnd_Box aBox = aStruct->MinMaxValues();
       if (aBox.IsVoid())
       {
         continue;
       }
 
-      // use camera projection to find gravity point
-      aBox.Get (Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
-      gp_Pnt aPnts[8] = { 
+      aBox.Get (Xmin, Ymin, Zmin,
+                Xmax, Ymax, Zmax);
+      gp_Pnt aPnts[THE_NB_BOUND_POINTS] =
+      {
         gp_Pnt (Xmin, Ymin, Zmin), gp_Pnt (Xmin, Ymin, Zmax),
         gp_Pnt (Xmin, Ymax, Zmin), gp_Pnt (Xmin, Ymax, Zmax),
         gp_Pnt (Xmax, Ymin, Zmin), gp_Pnt (Xmax, Ymin, Zmax),
-        gp_Pnt (Xmax, Ymax, Zmin), gp_Pnt (Xmax, Ymax, Zmax) };
+        gp_Pnt (Xmax, Ymax, Zmin), gp_Pnt (Xmax, Ymax, Zmax)
+      };
 
-      for (Standard_Integer aPntIt = 0; aPntIt < 8; ++aPntIt)
+      for (Standard_Integer aPntIt = 0; aPntIt < THE_NB_BOUND_POINTS; ++aPntIt)
       {
         const gp_Pnt& aBndPnt = aPnts[aPntIt];
-
-        gp_Pnt aProjected = myCamera->Project (aBndPnt);
-        const Standard_Real& U = aProjected.X();
-        const Standard_Real& V = aProjected.Y();
-        if (Abs(U) <= 1.0 && Abs(V) <= 1.0)
-        {
-          Npoint++;
-          X += aBndPnt.X();
-          Y += aBndPnt.Y();
-          Z += aBndPnt.Z();
-        }
+        aResult += aBndPnt.XYZ();
+        ++aNbPoints;
       }
     }
   }
-  if( Npoint > 0 ) {
-    X /= Npoint ; Y /= Npoint ; Z /= Npoint ;
-  }
 
-  return Nstruct ;
+  if (aNbPoints > 0)
+  {
+    aResult /= aNbPoints;
+  }
+  theX = aResult.X();
+  theY = aResult.Y();
+  theZ = aResult.Z();
 }
 
 //=======================================================================
index 395e3d99b881045684108d7f94cfb27b4a235b4b..42012a0c9b9a2add6ebcb88aa376f8eedef30b09 100644 (file)
@@ -2950,22 +2950,84 @@ static int VTestZBuffTrihedron(Draw_Interpretor& di, Standard_Integer argc, cons
 //purpose  : Camera Rotating
 //==============================================================================
 
-static int VRotate( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
-  Handle(V3d_View) V3dView = ViewerTest::CurrentView();
-  if ( V3dView.IsNull() ) {
+static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
+{
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cout << "No active view!\n";
     return 1;
   }
 
-  if ( argc == 4 ) {
-    V3dView->Rotate( Draw::Atof(argv[1]), Draw::Atof(argv[2]), Draw::Atof(argv[3]) );
+  Standard_Boolean hasFlags = Standard_False;
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+  {
+    Standard_CString        anArg (theArgVec[anArgIter]);
+    TCollection_AsciiString aFlag (anArg);
+    aFlag.LowerCase();
+    if (aFlag == "-mousestart"
+     || aFlag == "-mousefrom")
+    {
+      hasFlags = Standard_True;
+      if (anArgIter + 2 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
+
+      Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
+      Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
+      aView->StartRotation (anX, anY);
+    }
+    else if (aFlag == "-mousemove")
+    {
+      hasFlags = Standard_True;
+      if (anArgIter + 2 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
+
+      Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
+      Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
+      aView->Rotation (anX, anY);
+    }
+    else if (theArgNb != 4
+          && theArgNb != 7)
+    {
+      std::cout << "Error: wrong syntax at '" << anArg << "'\n";
+      return 1;
+    }
+  }
+
+  if (hasFlags)
+  {
     return 0;
-  } else if ( argc == 7 ) {
-    V3dView->Rotate( Draw::Atof(argv[1]), Draw::Atof(argv[2]), Draw::Atof(argv[3]), Draw::Atof(argv[4]), Draw::Atof(argv[5]), Draw::Atof(argv[6]) );
+  }
+  else if (theArgNb == 4)
+  {
+    Standard_Real anAX = Draw::Atof (theArgVec[1]);
+    Standard_Real anAY = Draw::Atof (theArgVec[2]);
+    Standard_Real anAZ = Draw::Atof (theArgVec[3]);
+    aView->Rotate (anAX, anAY, anAZ);
+    return 0;
+  }
+  else if (theArgNb == 7)
+  {
+    Standard_Real anAX = Draw::Atof (theArgVec[1]);
+    Standard_Real anAY = Draw::Atof (theArgVec[2]);
+    Standard_Real anAZ = Draw::Atof (theArgVec[3]);
+
+    Standard_Real anX = Draw::Atof (theArgVec[4]);
+    Standard_Real anY = Draw::Atof (theArgVec[5]);
+    Standard_Real anZ = Draw::Atof (theArgVec[6]);
+
+    aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
     return 0;
-  } else {
-    di << argv[0] << " Invalid number of arguments" << "\n";
-    return 1;
   }
+
+  std::cout << "Error: Invalid number of arguments\n";
+  return 1;
 }
 
 //==============================================================================
@@ -7249,7 +7311,11 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     " : Displays a V3d_ZBUFFER'ed or V3d_WIREFRAME'd trihedron",
     __FILE__,VTestZBuffTrihedron,group);
   theCommands.Add("vrotate",
-    "vrotate         : vrotate AX AY AZ [X Y Z]",
+    "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
+    "\n                : Option -mouseStart starts rotation according to the mouse position"
+    "\n                : Option -mouseMove continues rotation with angle computed"
+    "\n                : from last and new mouse position."
+    "\n                : vrotate AX AY AZ [X Y Z]",
     __FILE__,VRotate,group);
   theCommands.Add("vzoom",
     "vzoom           : vzoom coef",
diff --git a/tests/bugs/vis/bug25723 b/tests/bugs/vis/bug25723
new file mode 100644 (file)
index 0000000..f725c5e
--- /dev/null
@@ -0,0 +1,50 @@
+puts "============"
+puts "OCC25723"
+puts "Calculate the center of rotation taking into account structure visibility"
+puts "============"
+puts ""
+
+set x_start_sel_coord 100
+set y_start_sel_coord 100
+
+set x_end_sel_coord 400
+set y_end_sel_coord 400
+
+set x_mouse_start_coord 100
+set y_mouse_start_coord 100
+
+set x_mouse_move_coord 300
+set y_mouse_move_coord 300
+
+set x_check_coord 220
+set y_check_coord 50
+
+box b1 0 0   0 10 10 10
+box b2 0 0  20 10 10 10
+box b3 0 0 -20 10 10 10
+box b4 0 0  40 10 10 10
+
+vinit View1
+vclear
+vaxo
+vsetdispmode 1
+
+# turn on solid selection
+vselmode 6 1
+vdisplay b1 b2 b3 b4
+vfit
+
+# select solid
+vselect ${x_start_sel_coord} ${y_start_sel_coord} ${x_end_sel_coord} ${y_end_sel_coord}
+
+# hide selected solids
+verase
+
+# rotation
+vrotate -mouseStart ${x_mouse_start_coord} ${y_mouse_start_coord} -mouseMove ${x_mouse_move_coord} ${y_mouse_move_coord}
+
+if {"[vreadpixel ${x_check_coord} ${y_check_coord} rgb name]" != "GOLDENROD2"} {
+  puts "Error: Rotation is not correct"
+}
+
+set only_screen 1
diff --git a/tests/bugs/vis/bug25723_1 b/tests/bugs/vis/bug25723_1
new file mode 100644 (file)
index 0000000..ef12838
--- /dev/null
@@ -0,0 +1,48 @@
+puts "============"
+puts "OCC25723"
+puts "Calculate the center of rotation taking into account active selection"
+puts "============"
+puts ""
+
+set x_sel_coord 220
+set y_sel_coord 50
+
+set x_mouse_start_coord 100
+set y_mouse_start_coord 100
+
+set x_mouse_move_coord 300
+set y_mouse_move_coord 300
+
+set x_check_coord 220
+set y_check_coord 50
+
+box b1 0 0   0 10 10 10
+box b2 0 0  20 10 10 10
+box b3 0 0 -20 10 10 10
+box b4 0 0  40 10 10 10
+
+vinit View1
+vclear
+vaxo
+vsetdispmode 1
+
+# turn on solid selection
+vselmode 6 1
+vdisplay b1 b2 b3 b4
+vfit
+
+# select one (red) solid
+vselect ${x_sel_coord} ${y_sel_coord}
+
+# start rotation
+vrotate -mouseStart ${x_mouse_start_coord} ${y_mouse_start_coord} -mouseMove ${x_mouse_move_coord} ${y_mouse_move_coord}
+
+# unselect
+vselect 0 0
+
+# check color
+if {"[vreadpixel ${x_check_coord} ${y_check_coord} rgb name]" != "GOLDENROD2"} {
+  puts "Error : Rotation is not correct"
+}
+
+set only_screen 1