mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-06 18:26:22 +03:00
0025723: Visualization, TKV3d - the center of rotation should be calculated taking into account structure visibility and selection flags
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
This commit is contained in:
parent
0090ae85ab
commit
4af098bab9
@ -1337,7 +1337,7 @@ is
|
|||||||
-- the objects contained in the view
|
-- the objects contained in the view
|
||||||
is static private;
|
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
|
---Purpose: Returns the Objects number and the gravity center
|
||||||
-- of ALL viewable points in the view
|
-- of ALL viewable points in the view
|
||||||
is static private;
|
is static private;
|
||||||
|
@ -151,6 +151,11 @@ To solve the problem (for lack of a better solution) I make 2 passes.
|
|||||||
|
|
||||||
#define DEUXPI (2. * M_PI)
|
#define DEUXPI (2. * M_PI)
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
static const Standard_Integer THE_NB_BOUND_POINTS = 8;
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//function : Constructor
|
//function : Constructor
|
||||||
//purpose :
|
//purpose :
|
||||||
@ -2090,61 +2095,112 @@ Standard_Integer V3d_View::MinMax(Standard_Real& Xmin,
|
|||||||
//function : Gravity
|
//function : Gravity
|
||||||
//purpose :
|
//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;
|
Graphic3d_MapOfStructure aSetOfStructures;
|
||||||
Standard_Integer Nstruct,Npoint ;
|
MyView->DisplayedStructures (aSetOfStructures);
|
||||||
Graphic3d_MapOfStructure MySetOfStructures;
|
|
||||||
|
|
||||||
MyView->DisplayedStructures (MySetOfStructures);
|
Standard_Boolean hasSelection = Standard_False;
|
||||||
Nstruct = MySetOfStructures.Extent() ;
|
for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures);
|
||||||
|
aStructIter.More(); aStructIter.Next())
|
||||||
Graphic3d_MapIteratorOfMapOfStructure MyIterator(MySetOfStructures) ;
|
|
||||||
|
|
||||||
Npoint = 0 ; X = Y = Z = 0. ;
|
|
||||||
for (; MyIterator.More(); MyIterator.Next())
|
|
||||||
{
|
{
|
||||||
const Handle(Graphic3d_Structure)& aStruct = MyIterator.Key();
|
if (aStructIter.Key()->IsHighlighted()
|
||||||
if (!aStruct->IsEmpty())
|
&& aStructIter.Key()->IsVisible())
|
||||||
{
|
{
|
||||||
Bnd_Box aBox = aStruct->MinMaxValues();
|
hasSelection = Standard_True;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check bounding box for validness
|
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)
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aNbPoints == 0)
|
||||||
|
{
|
||||||
|
for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures);
|
||||||
|
aStructIter.More(); aStructIter.Next())
|
||||||
|
{
|
||||||
|
const Handle(Graphic3d_Structure)& aStruct = aStructIter.Key();
|
||||||
|
if (aStruct->IsEmpty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bnd_Box aBox = aStruct->MinMaxValues();
|
||||||
if (aBox.IsVoid())
|
if (aBox.IsVoid())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// use camera projection to find gravity point
|
aBox.Get (Xmin, Ymin, Zmin,
|
||||||
aBox.Get (Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
|
Xmax, Ymax, Zmax);
|
||||||
gp_Pnt aPnts[8] = {
|
gp_Pnt aPnts[THE_NB_BOUND_POINTS] =
|
||||||
|
{
|
||||||
gp_Pnt (Xmin, Ymin, Zmin), gp_Pnt (Xmin, Ymin, Zmax),
|
gp_Pnt (Xmin, Ymin, Zmin), gp_Pnt (Xmin, Ymin, Zmax),
|
||||||
gp_Pnt (Xmin, Ymax, Zmin), gp_Pnt (Xmin, Ymax, Zmax),
|
gp_Pnt (Xmin, Ymax, Zmin), gp_Pnt (Xmin, Ymax, Zmax),
|
||||||
gp_Pnt (Xmax, Ymin, Zmin), gp_Pnt (Xmax, Ymin, 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];
|
const gp_Pnt& aBndPnt = aPnts[aPntIt];
|
||||||
|
aResult += aBndPnt.XYZ();
|
||||||
gp_Pnt aProjected = myCamera->Project (aBndPnt);
|
++aNbPoints;
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
|
@ -2950,22 +2950,84 @@ static int VTestZBuffTrihedron(Draw_Interpretor& di, Standard_Integer argc, cons
|
|||||||
//purpose : Camera Rotating
|
//purpose : Camera Rotating
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
static int VRotate( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
|
static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
|
||||||
Handle(V3d_View) V3dView = ViewerTest::CurrentView();
|
{
|
||||||
if ( V3dView.IsNull() ) {
|
Handle(V3d_View) aView = ViewerTest::CurrentView();
|
||||||
|
if (aView.IsNull())
|
||||||
|
{
|
||||||
|
std::cout << "No active view!\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( argc == 4 ) {
|
Standard_Boolean hasFlags = Standard_False;
|
||||||
V3dView->Rotate( Draw::Atof(argv[1]), Draw::Atof(argv[2]), Draw::Atof(argv[3]) );
|
for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
|
||||||
return 0;
|
{
|
||||||
} else if ( argc == 7 ) {
|
Standard_CString anArg (theArgVec[anArgIter]);
|
||||||
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]) );
|
TCollection_AsciiString aFlag (anArg);
|
||||||
return 0;
|
aFlag.LowerCase();
|
||||||
} else {
|
if (aFlag == "-mousestart"
|
||||||
di << argv[0] << " Invalid number of arguments" << "\n";
|
|| aFlag == "-mousefrom")
|
||||||
return 1;
|
{
|
||||||
|
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 (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
" : Displays a V3d_ZBUFFER'ed or V3d_WIREFRAME'd trihedron",
|
||||||
__FILE__,VTestZBuffTrihedron,group);
|
__FILE__,VTestZBuffTrihedron,group);
|
||||||
theCommands.Add("vrotate",
|
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);
|
__FILE__,VRotate,group);
|
||||||
theCommands.Add("vzoom",
|
theCommands.Add("vzoom",
|
||||||
"vzoom : vzoom coef",
|
"vzoom : vzoom coef",
|
||||||
|
50
tests/bugs/vis/bug25723
Normal file
50
tests/bugs/vis/bug25723
Normal file
@ -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
|
48
tests/bugs/vis/bug25723_1
Normal file
48
tests/bugs/vis/bug25723_1
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user