Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
497 lines (444 sloc) 15.2 KB
/*=========================================================================
Program: Visualization Toolkit
Module: vtkBalloonRepresentation.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkBalloonRepresentation.h"
#include "vtkRenderer.h"
#include "vtkTextProperty.h"
#include "vtkTextProperty.h"
#include "vtkProperty2D.h"
#include "vtkTextMapper.h"
#include "vtkTextActor.h"
#include "vtkPoints.h"
#include "vtkCellArray.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper2D.h"
#include "vtkActor2D.h"
#include "vtkImageData.h"
#include "vtkTexture.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper2D.h"
#include "vtkActor2D.h"
#include "vtkFloatArray.h"
#include "vtkPointData.h"
#include "vtkWindow.h"
#include "vtkObjectFactory.h"
#include "vtkInteractorObserver.h"
vtkStandardNewMacro(vtkBalloonRepresentation);
vtkCxxSetObjectMacro(vtkBalloonRepresentation, TextProperty, vtkTextProperty);
vtkCxxSetObjectMacro(vtkBalloonRepresentation, FrameProperty, vtkProperty2D);
vtkCxxSetObjectMacro(vtkBalloonRepresentation, BalloonImage, vtkImageData);
vtkCxxSetObjectMacro(vtkBalloonRepresentation, ImageProperty, vtkProperty2D);
//----------------------------------------------------------------------
vtkBalloonRepresentation::vtkBalloonRepresentation()
{
// Initially we are not visible
this->Visibility = 0;
this->TextVisible = 0;
this->ImageVisible = 0;
// Balloon related
this->BalloonText = NULL;
this->BalloonImage = NULL;
this->BalloonLayout = ImageTop;
// Displaying the image in the balloon using texture. Create a quad polygon
// and apply the texture on top of it.
this->ImageSize[0] = 50;
this->ImageSize[1] = 50;
this->Texture = vtkTexture::New();
this->TexturePolyData = vtkPolyData::New();
this->TexturePoints = vtkPoints::New();
this->TexturePoints->SetNumberOfPoints(4);
this->TexturePolyData->SetPoints(this->TexturePoints);
vtkCellArray* polys = vtkCellArray::New();
polys->InsertNextCell(4);
polys->InsertCellPoint(0);
polys->InsertCellPoint(1);
polys->InsertCellPoint(2);
polys->InsertCellPoint(3);
this->TexturePolyData->SetPolys(polys);
polys->Delete();
vtkFloatArray* tc = vtkFloatArray::New();
tc->SetNumberOfComponents(2);
tc->SetNumberOfTuples(4);
tc->InsertComponent(0,0, 0.0); tc->InsertComponent(0,1, 0.0);
tc->InsertComponent(1,0, 1.0); tc->InsertComponent(1,1, 0.0);
tc->InsertComponent(2,0, 1.0); tc->InsertComponent(2,1, 1.0);
tc->InsertComponent(3,0, 0.0); tc->InsertComponent(3,1, 1.0);
this->TexturePolyData->GetPointData()->SetTCoords(tc);
tc->Delete();
this->TextureMapper = vtkPolyDataMapper2D::New();
this->TextureMapper->SetInput(this->TexturePolyData);
this->TextureActor = vtkActor2D::New();
this->TextureActor->SetMapper(this->TextureMapper);
this->ImageProperty = vtkProperty2D::New();
this->ImageProperty->SetOpacity(1.0);
this->TextureActor->SetProperty(this->ImageProperty);
// Controlling layout
this->Padding = 5;
this->Offset[0] = 15;
this->Offset[1] = -30;
// The text actor
this->TextMapper = vtkTextMapper::New();
this->TextActor = vtkActor2D::New();
this->TextActor->SetMapper(this->TextMapper);
this->TextProperty = vtkTextProperty::New();
this->TextProperty->SetColor(0,0,0);
this->TextProperty->SetFontSize(14);
this->TextProperty->BoldOn();
this->TextMapper->SetTextProperty(this->TextProperty);
// The frame
this->FramePoints = vtkPoints::New();
this->FramePoints->SetNumberOfPoints(4);
this->FramePolygon = vtkCellArray::New();
this->FramePolygon->Allocate(this->FramePolygon->EstimateSize(1,5));
this->FramePolygon->InsertNextCell(4);
this->FramePolygon->InsertCellPoint(0);
this->FramePolygon->InsertCellPoint(1);
this->FramePolygon->InsertCellPoint(2);
this->FramePolygon->InsertCellPoint(3);
this->FramePolyData = vtkPolyData::New();
this->FramePolyData->SetPoints(this->FramePoints);
this->FramePolyData->SetPolys(this->FramePolygon);
this->FrameMapper = vtkPolyDataMapper2D::New();
this->FrameMapper->SetInput(this->FramePolyData);
this->FrameActor = vtkActor2D::New();
this->FrameActor->SetMapper(this->FrameMapper);
this->FrameProperty = vtkProperty2D::New();
this->FrameProperty->SetColor(1,1,.882);
this->FrameProperty->SetOpacity(0.5);
this->FrameActor->SetProperty(this->FrameProperty);
}
//----------------------------------------------------------------------
vtkBalloonRepresentation::~vtkBalloonRepresentation()
{
if ( this->BalloonText )
{
delete [] this->BalloonText;
}
if ( this->BalloonImage )
{
this->BalloonImage->Delete();
}
this->Texture->Delete();
this->TexturePolyData->Delete();
this->TexturePoints->Delete();
this->TextureMapper->Delete();
this->TextureActor->Delete();
this->ImageProperty->Delete();
this->TextMapper->Delete();
this->TextActor->Delete();
this->TextProperty->Delete();
// The frame
this->FramePoints->Delete();
this->FramePolygon->Delete();
this->FramePolyData->Delete();
this->FrameMapper->Delete();
this->FrameActor->Delete();
this->FrameProperty->Delete();
}
//----------------------------------------------------------------------
void vtkBalloonRepresentation::StartWidgetInteraction(double e[2])
{
this->StartEventPosition[0] = e[0];
this->StartEventPosition[1] = e[1];
this->VisibilityOn();
}
//----------------------------------------------------------------------
void vtkBalloonRepresentation::EndWidgetInteraction(double vtkNotUsed(e)[2])
{
this->VisibilityOff();
}
//----------------------------------------------------------------------
inline void vtkBalloonRepresentation::AdjustImageSize(double imageSize[2])
{
double r0 = this->ImageSize[0]/imageSize[0];
double r1 = this->ImageSize[1]/imageSize[1];
if ( r0 > r1 )
{
imageSize[0] *= r1;
imageSize[1] *= r1;
}
else
{
imageSize[0] *= r0;
imageSize[1] *= r0;
}
}
//----------------------------------------------------------------------
inline void vtkBalloonRepresentation::ScaleImage(double imageSize[2],double scale)
{
imageSize[0] *= scale;
imageSize[1] *= scale;
}
//----------------------------------------------------------------------
void vtkBalloonRepresentation::BuildRepresentation()
{
if ( this->GetMTime() > this->BuildTime ||
(this->Renderer && this->Renderer->GetVTKWindow() &&
this->Renderer->GetVTKWindow()->GetMTime() > this->BuildTime) )
{
this->TextVisible = 0;
this->ImageVisible = 0;
int size[2];
size[0] = (this->Renderer->GetSize())[0];
size[1] = (this->Renderer->GetSize())[1];
int stringSize[2]; stringSize[0] = stringSize[1] = 0;
double imageSize[2]; imageSize[0] = imageSize[1] = 0.0;
double frameSize[2]; frameSize[0] = frameSize[1] = 0.0;
double io[2], so[2], fo[2];
io[0] = 0.0;
io[1] = 0.0;
so[0] = 0.0;
so[1] = 0.0;
fo[0] = 0.0;
fo[1] = 0.0;
double e[2];
e[0] = static_cast<double>(this->StartEventPosition[0] + this->Offset[0]);
e[1] = static_cast<double>(this->StartEventPosition[1] + this->Offset[1]);
// Determine the size of the text
if ( this->BalloonText )
{
// Start by getting the size of the text
this->TextMapper->SetInput(this->BalloonText);
this->TextMapper->GetSize(this->Renderer, stringSize);
this->TextVisible = ( (stringSize[0] > 0 && stringSize[1] > 0) ? 1 : 0 );
}
// Determine the size of the image
if ( this->BalloonImage )
{
this->BalloonImage->Update();
if ( this->BalloonImage->GetDataDimension() == 2 )
{
int dims[3];
this->BalloonImage->GetDimensions(dims);
imageSize[0] = static_cast<double>(dims[0]);
imageSize[1] = static_cast<double>(dims[1]);
this->ImageVisible = ( (imageSize[0] > 0.0 && imageSize[1] > 0.0) ? 1 : 0 );
}
}
// Layout the text and image
if ( this->TextVisible || this->ImageVisible )
{
if ( this->TextVisible && !this->ImageVisible ) //just text
{
frameSize[0] = static_cast<double>(stringSize[0] + 2*this->Padding);
frameSize[1] = static_cast<double>(stringSize[1] + 2*this->Padding);
fo[0] = 0.0;
fo[1] = 0.0;
so[0] = static_cast<double>(this->Padding);
so[1] = static_cast<double>(this->Padding);
}
else if ( this->ImageVisible && !this->TextVisible ) //just image
{
this->AdjustImageSize(imageSize);
io[0] = 0.0;
io[1] = 0.0;
}
else //both image and text
{
this->AdjustImageSize(imageSize);
if ( this->BalloonLayout == ImageTop )
{
frameSize[1] = stringSize[1] + 2*this->Padding;
double length = (imageSize[0] > (stringSize[0]+2*this->Padding) ?
imageSize[0] : (stringSize[0]+2*this->Padding));
frameSize[0] = length;
double scale = length/imageSize[0];
this->ScaleImage(imageSize,scale);
io[0] = 0.0;
io[1] = frameSize[1];
fo[0] = 0.0;
fo[1] = 0.0;
so[0] = length/2.0 - stringSize[0]/2.0;
so[1] = this->Padding;
}
else if ( this->BalloonLayout == ImageBottom )
{
frameSize[1] = stringSize[1] + 2*this->Padding;
double length = (imageSize[0] > (stringSize[0]+2*this->Padding) ?
imageSize[0] : (stringSize[0]+2*this->Padding));
frameSize[0] = length;
double scale = length/imageSize[0];
this->ScaleImage(imageSize,scale);
io[0] = 0.0;
io[1] = 0.0;
fo[0] = 0.0;
fo[1] = imageSize[1];
so[0] = length/2.0 - stringSize[0]/2.0;
so[1] = imageSize[1] + this->Padding;
}
else if ( this->BalloonLayout == ImageLeft )
{
frameSize[0] = stringSize[0] + 2*this->Padding;
double length = (imageSize[1] > (stringSize[1]+2*this->Padding) ?
imageSize[1] : (stringSize[1]+2*this->Padding));
frameSize[1] = length;
double scale = length/imageSize[1];
this->ScaleImage(imageSize,scale);
io[0] = 0.0;
io[1] = 0.0;
fo[0] = imageSize[0];
fo[1] = 0.0;
so[0] = imageSize[0] + this->Padding;
so[1] = length/2.0 - stringSize[1]/2.0;
}
else if ( this->BalloonLayout == ImageRight )
{
frameSize[0] = stringSize[0] + 2*this->Padding;
double length = (imageSize[1] > (stringSize[1]+2*this->Padding) ?
imageSize[1] : (stringSize[1]+2*this->Padding));
frameSize[1] = length;
double scale = length/imageSize[1];
this->ScaleImage(imageSize,scale);
io[0] = frameSize[0];
io[1] = 0.0;
fo[0] = 0.0;
fo[1] = 0.0;
so[0] = this->Padding;
so[1] = length/2.0 - stringSize[1]/2.0;
}
}
// Reposition the origin of the balloon if it's off the renderer
if ( e[0] < 0 )
{
e[0] = 0.0;
}
if ( e[1] < 0 )
{
e[1] = 0.0;
}
if ( (e[0]+frameSize[0]+imageSize[0]) > size[0] )
{
e[0] = size[0] - (frameSize[0]+imageSize[0]);
}
if ( (e[1]+frameSize[1]+imageSize[1]) > size[1] )
{
e[1] = size[1] - (frameSize[1]+imageSize[1]);
}
// Draw the text if visible
if ( this->TextVisible )
{
this->FramePoints->SetPoint(0, e[0]+fo[0],e[1]+fo[1],0.0);
this->FramePoints->SetPoint(1, e[0]+fo[0]+frameSize[0],e[1]+fo[1],0.0);
this->FramePoints->SetPoint(2, e[0]+fo[0]+frameSize[0],e[1]+fo[1]+frameSize[1],0.0);
this->FramePoints->SetPoint(3, e[0]+fo[0],e[1]+fo[1]+frameSize[1],0.0);
this->TextActor->SetPosition(e[0]+so[0], e[1]+so[1]);
}
// Place the texture
if ( this->ImageVisible )
{
this->Texture->SetInput(this->BalloonImage);
this->TexturePoints->SetPoint(0, e[0]+io[0],e[1]+io[1],0.0);
this->TexturePoints->SetPoint(1, e[0]+io[0]+imageSize[0],e[1]+io[1],0.0);
this->TexturePoints->SetPoint(2, e[0]+io[0]+imageSize[0],e[1]+io[1]+imageSize[1],0.0);
this->TexturePoints->SetPoint(3, e[0]+io[0],e[1]+io[1]+imageSize[1],0.0);
}
}//if something visible
this->BuildTime.Modified();
}
}
//----------------------------------------------------------------------
void vtkBalloonRepresentation::ReleaseGraphicsResources(vtkWindow *w)
{
this->TextActor->ReleaseGraphicsResources(w);
this->FrameActor->ReleaseGraphicsResources(w);
this->TextureActor->ReleaseGraphicsResources(w);
}
//----------------------------------------------------------------------
int vtkBalloonRepresentation::RenderOverlay(vtkViewport *v)
{
int count = 0;
this->BuildRepresentation();
if ( this->TextVisible )
{
count += this->FrameActor->RenderOverlay(v);
count += this->TextActor->RenderOverlay(v);
}
if ( this->ImageVisible )
{
vtkRenderer* ren = vtkRenderer::SafeDownCast(v);
if (ren)
{
this->Texture->Render(ren);
count += this->TextureActor->RenderOverlay(v);
}
}
return count;
}
//----------------------------------------------------------------------
void vtkBalloonRepresentation::PrintSelf(ostream& os, vtkIndent indent)
{
//Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
this->Superclass::PrintSelf(os,indent);
os << indent << "Balloon Text: ";
if ( this->BalloonText )
{
os << this->BalloonText << "\n";
}
else
{
os << "(none)\n";
}
os << indent << "Balloon Image: ";
if ( this->BalloonImage )
{
os << this->BalloonImage << "\n";
}
else
{
os << "(none)\n";
}
os << indent << "Balloon Layout: ";
switch (this->BalloonLayout)
{
case ImageLeft:
os << "Image Left\n";
break;
case ImageRight:
os << "Image Right\n";
break;
case ImageBottom:
os << "Image Bottom\n";
break;
default:
os << "Image Top\n";
}
os << indent << "Image Size: (" << this->ImageSize[0] << ","
<< this->ImageSize[1] << ")\n";
os << indent << "Padding: " << this->Padding << "\n";
os << indent << "Offset: (" << this->Offset[0] << ","
<< this->Offset[1] << ")\n";
if ( this->FrameProperty )
{
os << indent << "Frame Property:\n";
this->FrameProperty->PrintSelf(os,indent.GetNextIndent());
}
else
{
os << indent << "Frame Property: (none)\n";
}
if ( this->ImageProperty )
{
os << indent << "Image Property:\n";
this->ImageProperty->PrintSelf(os,indent.GetNextIndent());
}
else
{
os << indent << "Image Property: (none)\n";
}
if ( this->TextProperty )
{
os << indent << "Text Property:\n";
this->TextProperty->PrintSelf(os,indent.GetNextIndent());
}
else
{
os << indent << "Text Property: (none)\n";
}
}