[vtkusers] Rubber band zoom and pick on 2d image

rodrigo rodrigo.geof at gmail.com
Tue Dec 7 16:14:24 EST 2010


Hello, I'm new to vtk, what I want to do is to zoom on a 2D image using a
Rubber band box, and to have my mouse coordinates showed up.

I tried to modify one of the wiki examples, but I couldn't make the mouse
coordinates be showed up and have the rubber band  at the same time. Besides
that, I have no idea on how to make the rubber band zoom my image. I really
want to use the coordinates grabbed by the rubber box to zoom the image.

Here is my code:

#include <vtk-5.2/vtkAssemblyPath.h>
#include <vtk-5.2/vtkCell.h>
#include <vtk-5.2/vtkCommand.h>
#include <vtk-5.2/vtkCornerAnnotation.h>
#include <vtk-5.2/vtkImageActor.h>
#include <vtk-5.2/vtkImageData.h>
#include <vtk-5.2/vtkImageViewer2.h>
#include <vtk-5.2/vtkInteractorStyleImage.h>
#include <vtk-5.2/vtkJPEGReader.h>
#include <vtk-5.2/vtkPointData.h>
#include <vtk-5.2/vtkPropPicker.h>
#include <vtk-5.2/vtkRenderer.h>
#include <vtk-5.2/vtkRenderWindow.h>
#include <vtk-5.2/vtkRenderWindowInteractor.h>
#include <vtk-5.2/vtkSmartPointer.h>
#include <vtk-5.2/vtkTextProperty.h>
#include <vtkInteractorStyleRubberBand2D.h>
#include <vtkCallbackCommand.h>

// The mouse motion callback, to pick the image and recover pixel values
class vtkImageInteractionCallback1 : public vtkCommand
{
public:

	static vtkImageInteractionCallback1 *New() 
	{
		return new vtkImageInteractionCallback1; 
	}

	vtkImageInteractionCallback1() 
	{
		this->Viewer = 0;
		this->Picker = 0;
		this->Annotation = 0;
		this->PointData = vtkPointData::New();
	}

	~vtkImageInteractionCallback1()
	{
		this->Viewer = 0;
		this->Picker = 0;
		this->Annotation = 0;
		this->PointData->Delete();
	}

	void SetPicker(vtkPropPicker *picker) 
	{
		this->Picker = picker; 
	}

	void SetAnnotation(vtkCornerAnnotation *annotation) 
	{
		this->Annotation = annotation; 
	}

	void SetViewer(vtkImageViewer2 *viewer) 
	{
		this->Viewer = viewer; 
	}

	virtual void Execute(vtkObject *, unsigned long vtkNotUsed(event), void *)
	{
		//this->Viewer;
		vtkRenderWindowInteractor *interactor =
			this->Viewer->GetRenderWindow()->GetInteractor();
		vtkRenderer* renderer = this->Viewer->GetRenderer();
		vtkImageActor* actor = this->Viewer->GetImageActor();
		vtkImageData* image = this->Viewer->GetInput();
		vtkInteractorStyle *style = vtkInteractorStyle::SafeDownCast(
				interactor->GetInteractorStyle());

		image->Update();

		// Pick at the mouse location provided by the interactor
		this->Picker->Pick( interactor->GetEventPosition()[0],
				    interactor->GetEventPosition()[1],
				    0.0, renderer );

		// There could be other props assigned to this picker, so 
		// make sure we picked the image actor
		vtkAssemblyPath* path = this->Picker->GetPath();
		bool validPick = false;

		if( path )
		{
			vtkCollectionSimpleIterator sit;
			path->InitTraversal( sit );
			vtkAssemblyNode *node;
			for( int i = 0; i < path->GetNumberOfItems() && !validPick; ++i )
			{
				node = path->GetNextNode( sit );
				if( actor == vtkImageActor::SafeDownCast( node->GetViewProp() ) )
				{
					validPick = true;
				}
			}
		}

		if( !validPick )
		{
			this->Annotation->SetText( 0, "Off Image" );
			interactor->Render();
			// Pass the event further on
			style->OnMouseMove();
			return;
		}

		// Get the world coordinates of the pick
		double pos[3];
		this->Picker->GetPickPosition( pos );
		// Fixes some numerical problems with the picking
		double *bounds = actor->GetDisplayBounds();
		int axis = this->Viewer->GetSliceOrientation();
		pos[axis] = bounds[2*axis];

		vtkPointData* pd = image->GetPointData();
		if( !pd )
		{
			return;
		}

		this->PointData->InterpolateAllocate( pd, 1, 1 );

		// Use tolerance as a function of size of source data
		double tol2 = image->GetLength();
		tol2 = tol2 ? tol2*tol2 / 1000.0 : 0.001;

		// Find the cell that contains pos
		int subId;
		double pcoords[3], weights[8];
		vtkCell* cell = image->FindAndGetCell(
				pos, NULL, -1, tol2, subId, pcoords, weights );
		if( cell )
		{
			// Interpolate the point data
			this->PointData->InterpolatePoint( pd, 0, cell->PointIds, weights );
			int components =
				this->PointData->GetScalars()->GetNumberOfComponents();
			double* tuple = this->PointData->GetScalars()->GetTuple( 0 );

			std::string message = "Location: ( ";
			message += vtkVariant( pos[0] ).ToString();
			message += ", ";
			message += vtkVariant( pos[1] ).ToString();
			message += ", ";
			message += vtkVariant( pos[2] ).ToString();
			message += " )\nValue: ( ";

			for( int c = 0; c < components; ++c )
			{
				message += vtkVariant( tuple[ c ] ).ToString();
				if( c != components - 1 ) 
				{
					message += ", ";
				}
			}
			message += " )";
			this->Annotation->SetText( 0, message.c_str() );
			interactor->Render();
			style->OnMouseMove();
		}
	}

private:

	// Pointer to the viewer
	vtkImageViewer2 *Viewer;

	// Pointer to the picker
	vtkPropPicker *Picker;

	// Pointer to the annotation
	vtkCornerAnnotation *Annotation;

	// Interpolator
	vtkPointData* PointData;
};

 
void SelectionChangedCallbackFunction ( vtkObject* vtkNotUsed(caller), 
					long unsigned int vtkNotUsed(eventId), void* vtkNotUsed(clientData),
void* callData )
{
	std::cout << "SelectionChanged callback" << std::endl;

	unsigned int* rect = reinterpret_cast<unsigned int*> ( callData );
	unsigned int pos1X = rect[0];
	unsigned int pos1Y = rect[1];
	unsigned int pos2X = rect[2];
	unsigned int pos2Y = rect[3];

	std::cout << "Start x: " << pos1X << " Start y: " << pos1Y 
		<< " End x: " << pos2X << " End y: " << pos2Y << std::endl;
}

int main ( int argc, char* argv[] )
{
	//Verify input arguments
	if ( argc != 2 )
	{
		std::cout << "Usage: " << argv[0] 
			<< " Filename(jpeg)" << std::endl;
		return EXIT_FAILURE;
	}

	//Parse input argument
	std::string inputFilename = argv[1];

	//Read the image
	vtkSmartPointer<vtkJPEGReader> jpegReader =
		vtkSmartPointer<vtkJPEGReader>::New();
	if( !jpegReader->CanReadFile( inputFilename.c_str() ) )
	{
		std::cout << argv[0] << ": Error reading file "
			<< inputFilename << endl << "Exiting..." << endl;
		return EXIT_FAILURE;
	}
	jpegReader->SetFileName ( inputFilename.c_str() );

	// Picker to pick pixels
	vtkSmartPointer<vtkPropPicker> propPicker =
		vtkSmartPointer<vtkPropPicker>::New();
	propPicker->PickFromListOn();

	// Give the picker a prop to pick
	vtkSmartPointer<vtkImageViewer2> imageViewer =
		vtkSmartPointer<vtkImageViewer2>::New();
	propPicker->AddPickList( imageViewer->GetImageActor() );

	// Visualize
	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	imageViewer->SetInputConnection( jpegReader->GetOutputPort() );
	imageViewer->SetupInteractor( renderWindowInteractor );
	imageViewer->SetSize( 600, 600 );

	vtkRenderer* renderer = imageViewer->GetRenderer();
	renderer->ResetCamera();
	renderer->GradientBackgroundOn();
	renderer->SetBackground(0,0,0);
	renderer->SetBackground2(1,1,1);

	// Annotate the image with window/level and mouse over pixel information
	vtkSmartPointer<vtkCornerAnnotation> cornerAnnotation =
		vtkSmartPointer<vtkCornerAnnotation>::New();
	cornerAnnotation->SetLinearFontScaleFactor( 2 );
	cornerAnnotation->SetNonlinearFontScaleFactor( 1 );
	cornerAnnotation->SetMaximumFontSize( 20 );
	cornerAnnotation->SetText( 0, "Off Image" );
	cornerAnnotation->SetText( 3, "<window>\n<level>" );
	cornerAnnotation->GetTextProperty()->SetColor( 1,0,0);

	imageViewer->GetRenderer()->AddViewProp( cornerAnnotation );

	// Callback listens to MouseMoveEvents invoked by the interactor's style
	vtkSmartPointer<vtkImageInteractionCallback1> callback =
		vtkSmartPointer<vtkImageInteractionCallback1>::New();
	callback->SetViewer( imageViewer );
	callback->SetAnnotation( cornerAnnotation );
	callback->SetPicker( propPicker );

	// InteractorStyleImage allows for the following controls:
	// 1) middle mouse + move = camera pan
	// 2) left mouse + move = window/level
	// 3) right mouse + move = camera zoom
	// 4) middle mouse wheel scroll = zoom
	// 5) 'r' = reset window/level
	// 6) shift + 'r' = reset camera
	vtkInteractorStyleImage* imageStyle = imageViewer->GetInteractorStyle();
	imageStyle->AddObserver( vtkCommand::MouseMoveEvent, callback );
	
	vtkSmartPointer<vtkCallbackCommand> selectionChangedCallback = 
		vtkSmartPointer<vtkCallbackCommand>::New();
	selectionChangedCallback->SetCallback ( SelectionChangedCallbackFunction );

	vtkSmartPointer<vtkInteractorStyleRubberBand2D> style = 
		vtkSmartPointer<vtkInteractorStyleRubberBand2D>::New();
	style->AddObserver ( vtkCommand::SelectionChangedEvent,
selectionChangedCallback );
	renderWindowInteractor->SetInteractorStyle( style );

	renderWindowInteractor->Initialize();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

-- 
View this message in context: http://vtk.1045678.n5.nabble.com/Rubber-band-zoom-and-pick-on-2d-image-tp3296495p3296495.html
Sent from the VTK - Users mailing list archive at Nabble.com.



More information about the vtkusers mailing list