From 58ffed6408b2b4c95f5a7d5c27c0740bc260ab1e Mon Sep 17 00:00:00 2001 From: Sujin Philip Date: Tue, 14 Jun 2016 17:19:34 -0400 Subject: [PATCH] Update implicit plane/cylinder representations fix This fixes a few thing that were missed in the previous commits 7d7c27da130127725aa50a0351d436ab66c276e3 and 00e9d126c755ccdc9d07d370b03f5a8f41a4f7e7 * Updates the way old VTK behaviour is maintained. * Removes checks done in SetCenter and SetRadius in vtkImplicitCylinderRepresenation. The checks are now done in BuildRepresentation. * Fix a bug in TestHanldeWidget that was exposed because of this change. --- .../Widgets/Testing/Cxx/TestHandleWidget.cxx | 5 +- .../Cxx/TestImplicitCylinderWidget2.cxx | 6 +- .../Testing/Cxx/TestImplicitPlaneWidget3.cxx | 6 +- .../vtkImplicitCylinderRepresentation.cxx | 89 +++++++++---------- .../vtkImplicitCylinderRepresentation.h | 20 +++-- .../vtkImplicitPlaneRepresentation.cxx | 65 +++++++------- .../Widgets/vtkImplicitPlaneRepresentation.h | 13 +-- 7 files changed, 104 insertions(+), 100 deletions(-) diff --git a/Interaction/Widgets/Testing/Cxx/TestHandleWidget.cxx b/Interaction/Widgets/Testing/Cxx/TestHandleWidget.cxx index 0aa3e036f4a..3f027d4d71c 100644 --- a/Interaction/Widgets/Testing/Cxx/TestHandleWidget.cxx +++ b/Interaction/Widgets/Testing/Cxx/TestHandleWidget.cxx @@ -624,12 +624,13 @@ int TestHandleWidget( int argc, char *argv[] ) vtkSmartPointer::New(); outlineActor->SetMapper( outlineMapper); + double repBounds[6] = { -0.7, 0.7, -0.7, 0.7, -0.7, 0.7 }; vtkSmartPointer rep = vtkSmartPointer::New(); - rep->SetPlaceFactor(0.7); + rep->SetPlaceFactor(1.0); rep->GetPlaneProperty()->SetAmbientColor(0.0, 0.5, 0.5); rep->GetPlaneProperty()->SetOpacity(0.3); - rep->PlaceWidget(outline->GetOutput()->GetBounds()); + rep->PlaceWidget(repBounds); vtkSmartPointer planeWidget = vtkSmartPointer::New(); planeWidget->SetRepresentation(rep); diff --git a/Interaction/Widgets/Testing/Cxx/TestImplicitCylinderWidget2.cxx b/Interaction/Widgets/Testing/Cxx/TestImplicitCylinderWidget2.cxx index 8c2d0c6e7d8..41785fdc1c0 100644 --- a/Interaction/Widgets/Testing/Cxx/TestImplicitCylinderWidget2.cxx +++ b/Interaction/Widgets/Testing/Cxx/TestImplicitCylinderWidget2.cxx @@ -400,7 +400,7 @@ int TestImplicitCylinderWidget2(int vtkNotUsed(argc), char *vtkNotUsed(argv)[]) rep->GetCenter(center); // #1: With ConstrainCenter on, center SHOULD NOT be settable outside widget bounds - rep->ConstrainCenterOn(); + rep->ConstrainToWidgetBoundsOn(); rep->GetWidgetBounds(wbounds); rep->SetCenter(wbounds[1] + 1.0, wbounds[3] + 1.0, wbounds[5] + 1.0); rep->GetCenter(center1); @@ -416,7 +416,7 @@ int TestImplicitCylinderWidget2(int vtkNotUsed(argc), char *vtkNotUsed(argv)[]) } // #2: With ConstrainCenter off, center SHOULD be settable outside current widget bounds. - rep->ConstrainCenterOff(); + rep->ConstrainToWidgetBoundsOff(); center1[0] = wbounds[1] + 1.0; center1[1] = wbounds[3] + 1.0; center1[2] = wbounds[5] + 1.0; @@ -438,7 +438,7 @@ int TestImplicitCylinderWidget2(int vtkNotUsed(argc), char *vtkNotUsed(argv)[]) // #3: With ConstrainCenter on and OutsideBounds off, the translation of the // widget should be limited rep->OutsideBoundsOff(); - rep->ConstrainCenterOn(); + rep->ConstrainToWidgetBoundsOn(); vtkSmartPointer recorder = vtkSmartPointer::New(); diff --git a/Interaction/Widgets/Testing/Cxx/TestImplicitPlaneWidget3.cxx b/Interaction/Widgets/Testing/Cxx/TestImplicitPlaneWidget3.cxx index c83092b477d..a56e91d8a4f 100644 --- a/Interaction/Widgets/Testing/Cxx/TestImplicitPlaneWidget3.cxx +++ b/Interaction/Widgets/Testing/Cxx/TestImplicitPlaneWidget3.cxx @@ -265,7 +265,7 @@ int TestImplicitPlaneWidget3(int vtkNotUsed(argc), char *vtkNotUsed(argv)[]) rep->GetOrigin(origin); // #1: With ConstrainOrigin on, origin SHOULD NOT be settable outside widget bounds - rep->ConstrainOriginOn(); + rep->ConstrainToWidgetBoundsOn(); rep->GetWidgetBounds(wbounds); rep->SetOrigin(wbounds[1] + 1.0, wbounds[3] + 1.0, wbounds[5] + 1.0); rep->GetOrigin(origin1); @@ -281,7 +281,7 @@ int TestImplicitPlaneWidget3(int vtkNotUsed(argc), char *vtkNotUsed(argv)[]) } // #2: With ConstrainOrigin off, origin SHOULD be settable outside current widget bounds. - rep->ConstrainOriginOff(); + rep->ConstrainToWidgetBoundsOff(); origin1[0] = wbounds[1] + 1.0; origin1[1] = wbounds[3] + 1.0; origin1[2] = wbounds[5] + 1.0; @@ -303,7 +303,7 @@ int TestImplicitPlaneWidget3(int vtkNotUsed(argc), char *vtkNotUsed(argv)[]) // #3: With ConstrainOrigin on and OutsideBounds off, the translation of the // widget should be limited rep->OutsideBoundsOff(); - rep->ConstrainOriginOn(); + rep->ConstrainToWidgetBoundsOn(); vtkSmartPointer recorder = vtkSmartPointer::New(); diff --git a/Interaction/Widgets/vtkImplicitCylinderRepresentation.cxx b/Interaction/Widgets/vtkImplicitCylinderRepresentation.cxx index 03a061d1abd..b40fcaacfc0 100644 --- a/Interaction/Widgets/vtkImplicitCylinderRepresentation.cxx +++ b/Interaction/Widgets/vtkImplicitCylinderRepresentation.cxx @@ -92,7 +92,7 @@ vtkImplicitCylinderRepresentation::vtkImplicitCylinderRepresentation() this->OutlineTranslation = 1; this->ScaleEnabled = 1; this->OutsideBounds = 1; - this->ConstrainCenter = 1; + this->ConstrainToWidgetBounds = 1; this->Cyl = vtkPolyData::New(); vtkPoints *pts = vtkPoints::New(); @@ -669,8 +669,8 @@ void vtkImplicitCylinderRepresentation::PrintSelf(ostream& os, vtkIndent indent) << (this->OutlineTranslation ? "On" : "Off") << "\n"; os << indent << "Outside Bounds: " << (this->OutsideBounds ? "On" : "Off") << "\n"; - os << indent << "Constrain Center: " - << (this->ConstrainCenter ? "On" : "Off") << "\n"; + os << indent << "Constrain to Widget Bounds: " + << (this->ConstrainToWidgetBounds ? "On" : "Off") << "\n"; os << indent << "Scale Enabled: " << (this->ScaleEnabled ? "On" : "Off") << "\n"; os << indent << "Draw Cylinder: " << (this->DrawCylinder ? "On" : "Off") << "\n"; @@ -1091,18 +1091,6 @@ void vtkImplicitCylinderRepresentation::SetCenter(double x, double y, double z) // the bounding box or the cylinder tends to disappear as it hits the boundary. void vtkImplicitCylinderRepresentation::SetCenter(double x[3]) { - double *bounds = this->Outline->GetOutput()->GetBounds(); - for (int i=0; i<3; i++) - { - if ( x[i] <= bounds[2*i] ) - { - x[i] = bounds[2*i] + FLT_EPSILON; - } - else if ( x[i] >= bounds[2*i+1] ) - { - x[i] = bounds[2*i+1] - FLT_EPSILON; - } - } this->Cylinder->SetCenter(x); this->BuildRepresentation(); } @@ -1162,12 +1150,13 @@ void vtkImplicitCylinderRepresentation::GetAxis(double xyz[3]) // Set the radius the cylinder. The radius must be a positive number. void vtkImplicitCylinderRepresentation::SetRadius(double radius) { - double minRadius = this->Outline->GetOutput()->GetLength() * this->MinRadius; - double maxRadius = this->Outline->GetOutput()->GetLength() * this->MaxRadius; - - radius = ( radius < minRadius ? minRadius : - (radius > maxRadius ? maxRadius : radius) ); + if (this->ConstrainToWidgetBounds) + { + double minRadius = this->Outline->GetOutput()->GetLength() * this->MinRadius; + double maxRadius = this->Outline->GetOutput()->GetLength() * this->MaxRadius; + radius = std::min(maxRadius, std::max(minRadius, radius)); + } this->Cylinder->SetRadius(radius); this->BuildRepresentation(); } @@ -1318,24 +1307,34 @@ void vtkImplicitCylinderRepresentation::BuildRepresentation() double *center = this->Cylinder->GetCenter(); double *axis = this->Cylinder->GetAxis(); + + double bounds[6]; + std::copy(this->WidgetBounds, this->WidgetBounds + 6, bounds); + double p2[3]; if ( !this->OutsideBounds ) { - double *bounds = this->InitialBounds; + // restrict the center inside InitialBounds + double *ibounds = this->InitialBounds; for (int i=0; i<3; i++) { - if ( center[i] < bounds[2*i] ) + if ( center[i] < ibounds[2*i] ) { - center[i] = bounds[2*i]; + center[i] = ibounds[2*i]; } - else if ( center[i] > bounds[2*i+1] ) + else if ( center[i] > ibounds[2*i+1] ) { - center[i] = bounds[2*i+1]; + center[i] = ibounds[2*i+1]; } } - if ( this->ConstrainCenter ) + } + + if ( this->ConstrainToWidgetBounds ) + { + if ( !this->OutsideBounds ) { - bounds = this->Box->GetBounds(); + // center cannot move outside InitialBounds. Therefore, restrict + // movement of the Box. double v[3] = { 0.0, 0.0, 0.0 }; for (int i = 0; i < 3; ++i) { @@ -1350,28 +1349,9 @@ void vtkImplicitCylinderRepresentation::BuildRepresentation() bounds[2*i] += v[i]; bounds[2*i + 1] += v[i]; } - this->Box->SetOrigin(bounds[0], bounds[2], bounds[4]); - this->Outline->Update(); } - } - if ( !this->ConstrainCenter ) - { - double offset = this->Cylinder->GetRadius() * 1.2; - double boxBounds[6]; - for (int i = 0; i < 3; ++i) - { - boxBounds[2*i] = vtkMath::Min(center[i] - offset, this->WidgetBounds[2*i]); - boxBounds[2*i + 1] = vtkMath::Max(center[i] + offset, this->WidgetBounds[2*i + 1]); - } - this->Box->SetOrigin(boxBounds[0], boxBounds[2], boxBounds[4]); - this->Box->SetSpacing(boxBounds[1]-boxBounds[0], boxBounds[3]-boxBounds[2], - boxBounds[5]-boxBounds[4]); - this->Outline->Update(); - } - else - { - double *bounds = this->Box->GetBounds(); + // restrict center inside bounds for (int i = 0; i < 3; ++i) { if (center[i] <= bounds[2*i]) @@ -1384,6 +1364,21 @@ void vtkImplicitCylinderRepresentation::BuildRepresentation() } } } + else // cylinder can move freely, adjust the bounds to change with it + { + double offset = this->Cylinder->GetRadius() * 1.2; + for (int i = 0; i < 3; ++i) + { + bounds[2*i] = vtkMath::Min(center[i] - offset, this->WidgetBounds[2*i]); + bounds[2*i + 1] = vtkMath::Max(center[i] + offset, this->WidgetBounds[2*i + 1]); + } + } + + this->Box->SetOrigin(bounds[0],bounds[2],bounds[4]); + this->Box->SetSpacing((bounds[1]-bounds[0]),(bounds[3]-bounds[2]), + (bounds[5]-bounds[4])); + this->Outline->Update(); + // Setup the cylinder axis double d = this->Outline->GetOutput()->GetLength(); diff --git a/Interaction/Widgets/vtkImplicitCylinderRepresentation.h b/Interaction/Widgets/vtkImplicitCylinderRepresentation.h index 003d40aef6a..8b44418fdff 100644 --- a/Interaction/Widgets/vtkImplicitCylinderRepresentation.h +++ b/Interaction/Widgets/vtkImplicitCylinderRepresentation.h @@ -155,7 +155,7 @@ class VTKINTERACTIONWIDGETS_EXPORT vtkImplicitCylinderRepresentation : public vt // Description: // Turn on/off the ability to move the widget outside of the bounds - // specified in the initial PlaceWidget() invocation. + // specified in the PlaceWidget() invocation. vtkSetMacro(OutsideBounds,int); vtkGetMacro(OutsideBounds,int); vtkBooleanMacro(OutsideBounds,int); @@ -169,13 +169,15 @@ class VTKINTERACTIONWIDGETS_EXPORT vtkImplicitCylinderRepresentation : public vt vtkGetVector6Macro(WidgetBounds, double); // Description: - // Turn on/off whether the center should be constrained to the widget bounds. - // If on, the center will not be allowed to move outside the set widget bounds. - // If off, the center can be freely moved and the widget outline will change - // accordingly. The default is on. - vtkSetMacro(ConstrainCenter, int); - vtkGetMacro(ConstrainCenter, int); - vtkBooleanMacro(ConstrainCenter, int); + // Turn on/off whether the cylinder should be constrained to the widget bounds. + // If on, the center will not be allowed to move outside the set widget bounds + // and the radius will be limited by MinRadius and MaxRadius. This is the + // default behaviour. + // If off, the center can be freely moved and the radius can be set to + // arbitrary values. The widget outline will change accordingly. + vtkSetMacro(ConstrainToWidgetBounds, int); + vtkGetMacro(ConstrainToWidgetBounds, int); + vtkBooleanMacro(ConstrainToWidgetBounds, int); // Description: // Turn on/off the ability to scale the widget with the mouse. @@ -332,7 +334,7 @@ class VTKINTERACTIONWIDGETS_EXPORT vtkImplicitCylinderRepresentation : public vt int ScaleEnabled; //whether the widget can be scaled int OutsideBounds; //whether the widget can be moved outside input's bounds double WidgetBounds[6]; - int ConstrainCenter; + int ConstrainToWidgetBounds; // The cut cylinder is produced with a vtkCutter vtkPolyData *Cyl; diff --git a/Interaction/Widgets/vtkImplicitPlaneRepresentation.cxx b/Interaction/Widgets/vtkImplicitPlaneRepresentation.cxx index 3038042ad06..5c12edf102d 100644 --- a/Interaction/Widgets/vtkImplicitPlaneRepresentation.cxx +++ b/Interaction/Widgets/vtkImplicitPlaneRepresentation.cxx @@ -83,7 +83,7 @@ vtkImplicitPlaneRepresentation::vtkImplicitPlaneRepresentation() this->OutlineTranslation = 1; this->ScaleEnabled = 1; this->OutsideBounds = 1; - this->ConstrainOrigin = 1; + this->ConstrainToWidgetBounds = 1; this->Cutter = vtkCutter::New(); this->Cutter->SetInputData(this->Box); @@ -680,8 +680,8 @@ void vtkImplicitPlaneRepresentation::PrintSelf(ostream& os, vtkIndent indent) << (this->OutlineTranslation ? "On" : "Off") << "\n"; os << indent << "Outside Bounds: " << (this->OutsideBounds ? "On" : "Off") << "\n"; - os << indent << "Constrain Origin: " - << (this->ConstrainOrigin ? "On" : "Off") << "\n"; + os << indent << "Constrain to Widget Bounds: " + << (this->ConstrainToWidgetBounds ? "On" : "Off") << "\n"; os << indent << "Scale Enabled: " << (this->ScaleEnabled ? "On" : "Off") << "\n"; os << indent << "Draw Plane: " << (this->DrawPlane ? "On" : "Off") << "\n"; @@ -1251,24 +1251,33 @@ void vtkImplicitPlaneRepresentation::BuildRepresentation() double *origin = this->Plane->GetOrigin(); double *normal = this->Plane->GetNormal(); + double bounds[6]; + std::copy(this->WidgetBounds, this->WidgetBounds + 6, bounds); + double p2[3]; if ( !this->OutsideBounds ) { - double *bounds = this->InitialBounds; + // restrict the origin inside InitialBounds + double *ibounds = this->InitialBounds; for (int i=0; i<3; i++) { - if ( origin[i] < bounds[2*i] ) + if ( origin[i] < ibounds[2*i] ) { - origin[i] = bounds[2*i]; + origin[i] = ibounds[2*i]; } - else if ( origin[i] > bounds[2*i+1] ) + else if ( origin[i] > ibounds[2*i+1] ) { - origin[i] = bounds[2*i+1]; + origin[i] = ibounds[2*i+1]; } } - if ( this->ConstrainOrigin ) + } + + if ( this->ConstrainToWidgetBounds ) + { + if ( !this->OutsideBounds ) { - bounds = this->Box->GetBounds(); + // origin cannot move outside InitialBounds. Therefore, restrict + // movement of the Box. double v[3] = { 0.0, 0.0, 0.0 }; for (int i = 0; i < 3; ++i) { @@ -1283,28 +1292,9 @@ void vtkImplicitPlaneRepresentation::BuildRepresentation() bounds[2*i] += v[i]; bounds[2*i + 1] += v[i]; } - this->Box->SetOrigin(bounds[0], bounds[2], bounds[4]); - this->Outline->Update(); } - } - if ( !this->ConstrainOrigin ) - { - double offset = this->Box->GetLength() * 0.02; - double boxBounds[6]; - for (int i = 0; i < 3; ++i) - { - boxBounds[2*i] = vtkMath::Min(origin[i] - offset, this->WidgetBounds[2*i]); - boxBounds[2*i + 1] = vtkMath::Max(origin[i] + offset, this->WidgetBounds[2*i + 1]); - } - this->Box->SetOrigin(boxBounds[0], boxBounds[2], boxBounds[4]); - this->Box->SetSpacing(boxBounds[1]-boxBounds[0], boxBounds[3]-boxBounds[2], - boxBounds[5]-boxBounds[4]); - this->Outline->Update(); - } - else - { - double *bounds = this->Box->GetBounds(); + // restrict origin inside bounds for (int i = 0; i < 3; ++i) { if (origin[i] <= bounds[2*i]) @@ -1317,6 +1307,21 @@ void vtkImplicitPlaneRepresentation::BuildRepresentation() } } } + else // plane can move freely, adjust the bounds to change with it + { + double offset = this->Box->GetLength() * 0.02; + for (int i = 0; i < 3; ++i) + { + bounds[2*i] = vtkMath::Min(origin[i] - offset, this->WidgetBounds[2*i]); + bounds[2*i + 1] = vtkMath::Max(origin[i] + offset, this->WidgetBounds[2*i + 1]); + } + } + + this->Box->SetOrigin(bounds[0],bounds[2],bounds[4]); + this->Box->SetSpacing((bounds[1]-bounds[0]),(bounds[3]-bounds[2]), + (bounds[5]-bounds[4])); + this->Outline->Update(); + // Setup the plane normal double d = this->Outline->GetOutput()->GetLength(); diff --git a/Interaction/Widgets/vtkImplicitPlaneRepresentation.h b/Interaction/Widgets/vtkImplicitPlaneRepresentation.h index 7f9b509c7bd..52643776aaf 100644 --- a/Interaction/Widgets/vtkImplicitPlaneRepresentation.h +++ b/Interaction/Widgets/vtkImplicitPlaneRepresentation.h @@ -148,13 +148,14 @@ class VTKINTERACTIONWIDGETS_EXPORT vtkImplicitPlaneRepresentation : public vtkWi vtkGetVector6Macro(WidgetBounds, double); // Description: - // Turn on/off whether the origin should be constrained to the widget bounds. + // Turn on/off whether the plane should be constrained to the widget bounds. // If on, the origin will not be allowed to move outside the set widget bounds. + // This is the default behaviour. // If off, the origin can be freely moved and the widget outline will change - // accordingly. The default is on. - vtkSetMacro(ConstrainOrigin,int); - vtkGetMacro(ConstrainOrigin,int); - vtkBooleanMacro(ConstrainOrigin,int); + // accordingly. + vtkSetMacro(ConstrainToWidgetBounds,int); + vtkGetMacro(ConstrainToWidgetBounds,int); + vtkBooleanMacro(ConstrainToWidgetBounds,int); // Description: // Turn on/off the ability to scale the widget with the mouse. @@ -318,7 +319,7 @@ class VTKINTERACTIONWIDGETS_EXPORT vtkImplicitPlaneRepresentation : public vtkWi int ScaleEnabled; //whether the widget can be scaled int OutsideBounds; //whether the widget can be moved outside input's bounds double WidgetBounds[6]; - int ConstrainOrigin; + int ConstrainToWidgetBounds; // The cut plane is produced with a vtkCutter vtkCutter *Cutter;