Files
ThirdParty-6/ParaView-5.0.1/VTK/Rendering/Label/vtkLabeledTreeMapDataMapper.cxx

1003 lines
29 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkLabeledTreeMapDataMapper.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.
=========================================================================*/
/*-------------------------------------------------------------------------
Copyright 2008 Sandia Corporation.
Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/
#include "vtkActor2D.h"
#include "vtkCoordinate.h"
#include "vtkDataArray.h"
#include "vtkDataSet.h"
#include "vtkExecutive.h"
#include "vtkFloatArray.h"
#include "vtkIdList.h"
#include "vtkInformation.h"
#include "vtkLabeledTreeMapDataMapper.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkStringArray.h"
#include "vtkTextMapper.h"
#include "vtkTextProperty.h"
#include "vtkTree.h"
#include "vtkTreeDFSIterator.h"
#include "vtkViewport.h"
#include "vtkWindow.h"
vtkStandardNewMacro(vtkLabeledTreeMapDataMapper);
vtkLabeledTreeMapDataMapper::vtkLabeledTreeMapDataMapper()
: CurrentViewPort(0), FontHeights(0), FontWidths(0), MaxFontLevel(0),
MaxTreeLevels(100), ClipTextMode(0), ChildMotion(0),
StartLevel(0), EndLevel(-1), DynamicLevel(0)
{
this->BoxTrans[0][0] = this->BoxTrans[1][0] = 0.0;
this->BoxTrans[0][1] = this->BoxTrans[1][1] = 1.0;
this->WindowLimits[0][0] = this->WindowLimits[1][0] = 0.0;
this->WindowLimits[0][1] = this->WindowLimits[1][1] = 1.0;
this->VCoord = vtkCoordinate::New();
this->VertexList = vtkIdList::New();
this->VertexList->SetNumberOfIds(this->NumberOfLabelsAllocated);
this->TextPoints = vtkPoints::New();
this->TextPoints->Allocate(this->NumberOfLabelsAllocated);
this->VerticalLabelProperty = vtkTextProperty::New();
this->VerticalLabelProperty->SetFontSize(12);
this->VerticalLabelProperty->SetBold(1);
this->VerticalLabelProperty->SetItalic(1);
this->VerticalLabelProperty->SetShadow(1);
this->VerticalLabelProperty->SetFontFamilyToArial();
this->VerticalLabelProperty->SetJustificationToCentered();
this->GetLabelTextProperty()->SetJustificationToCentered();
this->VerticalLabelProperty->SetVerticalJustificationToCentered();
this->GetLabelTextProperty()->SetVerticalJustificationToCentered();
this->VerticalLabelProperty->SetOrientation(90.0);
this->VerticalLabelProperty->SetColor(1, 1, 1);
this->GetLabelTextProperty()->SetColor(1, 1, 1);
this->GetLabelTextProperty()->SetFontSize(12);
this->SetFontSizeRange(24, 10);
this->ChildrenCount = new int[this->MaxTreeLevels+1];
this->LabelMasks = new float[this->MaxTreeLevels+1][4];
this->SetRectanglesArrayName("area");
this->SetLabelFormat("%s");
// Take control of the TextMappers array.
// The superclass just created new TextMapper instances
// up to the currently allocated amount (default 50).
// Instead, we will store NULL values until we need them.
// This class will manage the maintenance and deletion of
// this array.
for (int i = 0; i < this->NumberOfLabelsAllocated; i++)
{
this->TextMappers[i]->Delete();
this->TextMappers[i] = NULL;
}
}
vtkLabeledTreeMapDataMapper::~vtkLabeledTreeMapDataMapper()
{
this->VCoord->Delete();
this->TextPoints->Delete();
this->VertexList->Delete();
this->VerticalLabelProperty->Delete();
int i;
for (i = 0; i <= this->MaxFontLevel; i++)
{
delete [] this->FontWidths[i];
this->HLabelProperties[i]->Delete();
}
delete [] this->FontWidths;
delete [] this->FontHeights;
delete [] this->HLabelProperties;
delete [] this->ChildrenCount;
delete [] this->LabelMasks;
if (this->TextMappers)
{
for (i=0; i < this->NumberOfLabelsAllocated; i++)
{
if (this->TextMappers[i])
{
this->TextMappers[i]->Delete();
}
}
delete [] this->TextMappers;
this->TextMappers = NULL;
}
}
//----------------------------------------------------------------------------
void vtkLabeledTreeMapDataMapper::SetRectanglesArrayName(const char* name)
{
this->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_VERTICES, name);
}
//----------------------------------------------------------------------------
// Release any graphics resources that are being consumed by this mapper.
void vtkLabeledTreeMapDataMapper::ReleaseGraphicsResources(vtkWindow *win)
{
if (this->TextMappers != NULL )
{
for (int i=0; i < this->NumberOfLabelsAllocated; i++)
{
if (this->TextMappers[i])
{
this->TextMappers[i]->ReleaseGraphicsResources(win);
}
}
}
}
vtkTree *vtkLabeledTreeMapDataMapper::GetInputTree()
{
return vtkTree::SafeDownCast(this->GetExecutive()->GetInputData(0, 0));
}
void vtkLabeledTreeMapDataMapper::UpdateFontSizes()
{
char test[2];
test[1] = '\0';
int tSize[2], i;
// Make sure that there is a text mapper at index 0
if (!this->TextMappers[0])
{
this->TextMappers[0] = vtkTextMapper::New();
this->NumberOfLabels = 1;
}
for (i = 0; i <= this->MaxFontLevel; i++)
{
this->TextMappers[0]->SetTextProperty(this->HLabelProperties[i]);
this->FontHeights[i] = 0;
for (test[0] = 32; test[0] < 127; test[0]++)
{
this->TextMappers[0]->SetInput(test);
this->TextMappers[0]->GetSize(this->CurrentViewPort, tSize);
this->FontWidths[i][test[0]-32] = tSize[0];
if (this->FontHeights[i] < tSize[1])
{
this->FontHeights[i] = tSize[1];
}
}
}
}
void vtkLabeledTreeMapDataMapper::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "ClipTextMode: " << this->ClipTextMode << endl;
os << indent << "ChildMotion: " << this->ChildMotion << endl;
os << indent << "DynamicLevel: " << this->DynamicLevel << endl;
int i;
os << "Font Sizes: ";
for (i = 0; i <= this->MaxFontLevel; i++)
{
os << this->HLabelProperties[i]->GetFontSize() << " ";
}
os << endl;
os << indent << "Level Range: [" << this->StartLevel
<< ", " << this->EndLevel << "]" << endl;
}
int vtkLabeledTreeMapDataMapper::UpdateWindowInfo(vtkViewport *viewport)
{
// Assumes that the view is not rotated w/r to the tree map!
int *dc;
float p[2][2];
this->VCoord->SetViewport(viewport);
// Transform 0,0 and 1,1 into screen coordinates
this->VCoord->SetValue(0.0, 0.0, 0.0);
dc = VCoord->GetComputedDisplayValue(0);
p[0][0] = dc[0];
p[0][1] = dc[1];
this->VCoord->SetValue(1.0, 1.0, 0.0);
dc = this->VCoord->GetComputedDisplayValue(0);
p[1][0] = dc[0];
p[1][1] = dc[1];
// The translation is defined by 0,0's new position
this->BoxTrans[0][0] = p[0][0];
this->BoxTrans[1][0] = p[0][1];
// The scales are defined as p[1] - p[0]
this->BoxTrans[0][1] = p[1][0] - p[0][0];
this->BoxTrans[1][1] = p[1][1] - p[0][1];
// Get the window extents
vtkWindow * win = viewport->GetVTKWindow();
int *winPos = win->GetPosition();
this->WindowLimits[0][0] = winPos[0];
this->WindowLimits[1][0] = winPos[1];
int *winSize = win->GetSize();
this->WindowLimits[0][1] = this->WindowLimits[0][0] + winSize[0];
this->WindowLimits[1][1] = this->WindowLimits[1][0] + winSize[1];
// We are done with the coordinate, so release the viewport
this->VCoord->SetViewport(NULL);
// Ideally we can compare the new scales with the original and
// see if the change has exceeded some threshold - in that case
// we could return 0
return 1;
}
void vtkLabeledTreeMapDataMapper::GetVertexLabel(vtkIdType vertex,
vtkDataArray *numericData,
vtkStringArray *stringData,
int activeComp, int numComp,
char *string)
{
char format[1024];
double val;
int j;
if ( numericData )
{
if ( numComp == 1 )
{
if (numericData->GetDataType() == VTK_CHAR)
{
if (strcmp(this->LabelFormat,"%c") != 0)
{
vtkErrorMacro(<<"Label format must be %c to use with char");
string[0] = '\0';
return;
}
sprintf(string, this->LabelFormat,
static_cast<char>(numericData->GetComponent(vertex, activeComp)));
}
else
{
sprintf(string, this->LabelFormat,
numericData->GetComponent(vertex, activeComp));
}
}
else
{
strcpy(format, "("); strcat(format, this->LabelFormat);
for (j=0; j<(numComp-1); j++)
{
sprintf(string, format, numericData->GetComponent(vertex, j));
strcpy(format,string); strcat(format,", ");
strcat(format, this->LabelFormat);
}
sprintf(string, format, numericData->GetComponent(vertex, numComp-1));
strcat(string, ")");
}
}
else if (stringData)// rendering string data
{
if (strcmp(this->LabelFormat,"%s") != 0)
{
vtkErrorMacro(<<"Label format must be %s to use with strings");
string[0] = '\0';
return;
}
sprintf(string, this->LabelFormat,
stringData->GetValue(vertex).c_str());
}
else // Use the vertex id
{
val = static_cast<double>(vertex);
sprintf(string, this->LabelFormat, val);
}
}
//----------------------------------------------------------------------------
void vtkLabeledTreeMapDataMapper::RenderOverlay(vtkViewport *viewport,
vtkActor2D *actor)
{
int i;
double x[3];
for (i=0; i<this->NumberOfLabels; i++)
{
this->TextPoints->GetPoint(i,x);
actor->GetPositionCoordinate()->SetCoordinateSystemToWorld();
actor->GetPositionCoordinate()->SetValue(x);
this->TextMappers[i]->RenderOverlay(viewport, actor);
}
}
//----------------------------------------------------------------------------
void vtkLabeledTreeMapDataMapper::RenderOpaqueGeometry(vtkViewport *viewport,
vtkActor2D *actor)
{
int i, numComp = 0, pointIdLabels, activeComp = 0;
int numVertices;
double x[3];
vtkAbstractArray *abstractData;
vtkDataArray *numericData, *tempData;
vtkStringArray *stringData;
vtkTree *input=this->GetInputTree();
if ( ! input )
{
vtkErrorMacro(<<"Need input tree to render labels (2)");
return;
}
vtkTextProperty *tprop = this->GetLabelTextProperty();
if (!tprop)
{
vtkErrorMacro(<<"Need text property to render labels");
return;
}
this->GetInputAlgorithm()->Update();
// Input might have changed
input = this->GetInputTree();
vtkDataSetAttributes *pd = input->GetVertexData();
// Get the treeMap info
tempData = this->GetInputArrayToProcess(0, input);
if (!tempData)
{
vtkErrorMacro(<< "Input Tree does not have box information.");
return;
}
vtkFloatArray *boxInfo = vtkFloatArray::SafeDownCast(tempData);
// Check to see whether we have to rebuild everything
if ( this->UpdateWindowInfo(viewport) ||
this->CurrentViewPort != viewport ||
this->GetMTime() > this->BuildTime ||
input->GetMTime() > this->BuildTime ||
tprop->GetMTime() > this->BuildTime)
{
vtkDebugMacro(<<"Rebuilding labels");
// See if we have to recalculate fonts sizes
if (this->CurrentViewPort != viewport)
{
this->CurrentViewPort = viewport;
this->UpdateFontSizes();
}
// figure out what to label, and if we can label it
pointIdLabels = 0;
abstractData = NULL;
numericData = NULL;
stringData = NULL;
switch (this->LabelMode)
{
case VTK_LABEL_IDS:
pointIdLabels = 1;
break;
case VTK_LABEL_SCALARS:
if ( pd->GetScalars() )
{
numericData = pd->GetScalars();
}
break;
case VTK_LABEL_VECTORS:
if ( pd->GetVectors() )
{
numericData = pd->GetVectors();
}
break;
case VTK_LABEL_NORMALS:
if ( pd->GetNormals() )
{
numericData = pd->GetNormals();
}
break;
case VTK_LABEL_TCOORDS:
if ( pd->GetTCoords() )
{
numericData = pd->GetTCoords();
}
break;
case VTK_LABEL_TENSORS:
if ( pd->GetTensors() )
{
numericData = pd->GetTensors();
}
break;
case VTK_LABEL_FIELD_DATA:
{
int arrayNum;
if (this->FieldDataName != NULL)
{
abstractData = pd->GetAbstractArray(this->FieldDataName, arrayNum);
}
else
{
arrayNum = (this->FieldDataArray < pd->GetNumberOfArrays() ?
this->FieldDataArray : pd->GetNumberOfArrays() - 1);
abstractData = pd->GetAbstractArray(arrayNum);
}
numericData = vtkDataArray::SafeDownCast(abstractData);
stringData = vtkStringArray::SafeDownCast(abstractData);
}; break;
}
// determine number of components and check input
if ( pointIdLabels )
{
;
}
else if ( numericData )
{
numComp = numericData->GetNumberOfComponents();
activeComp = 0;
if ( this->LabeledComponent >= 0 )
{
activeComp = (this->LabeledComponent < numComp ?
this->LabeledComponent : numComp - 1);
numComp = 1;
}
}
else if ( !stringData )
{
vtkErrorMacro(<<"Need input data to render labels (3)");
return;
}
// Make sure that the array of TextMappers can accommodate
// the number of vertices in the tree - Note that we may
// not create the actual mappers
numVertices = input->GetNumberOfVertices();
if ( numVertices > this->NumberOfLabelsAllocated )
{
// delete old stuff
for (i=0; i < this->NumberOfLabelsAllocated; i++)
{
if (this->TextMappers[i])
{
this->TextMappers[i]->Delete();
}
}
delete [] this->TextMappers;
this->NumberOfLabelsAllocated = numVertices;
this->TextMappers = new vtkTextMapper * [numVertices];
this->VertexList->SetNumberOfIds(numVertices);
this->TextPoints->Allocate(numVertices);
for (i = 0; i < numVertices; i++)
{
this->TextMappers[i] = 0;
}
}
this->LabelTree(input, boxInfo, numericData, stringData,
activeComp, numComp);
}
for (i=0; i<this->NumberOfLabels; i++)
{
this->TextPoints->GetPoint(i,x);
actor->GetPositionCoordinate()->SetCoordinateSystemToWorld();
actor->GetPositionCoordinate()->SetValue(x);
this->TextMappers[i]->RenderOpaqueGeometry(viewport, actor);
}
}
void vtkLabeledTreeMapDataMapper::LabelTree(vtkTree *tree,
vtkFloatArray *boxInfo,
vtkDataArray *numericData,
vtkStringArray *stringData,
int activeComp,
int numComps)
{
float blimits[4], blimitsDC[4], textPosWC[3];
char string[1024];
int results;
vtkTextProperty *tprop = NULL;
vtkIdType vertex, level, root = tree->GetRoot();
if (root < 0)
{
vtkErrorMacro(<< "Input Tree does not have a root.");
return;
}
this->NumberOfLabels = 0;
vtkTreeDFSIterator* dfs = vtkTreeDFSIterator::New();
dfs->SetTree(tree);
while (dfs->HasNext())
{
// Are we suppose to display this vertex?
vertex = dfs->Next();
level = tree->GetLevel(vertex);
if (level >= this->StartLevel && (this->EndLevel == -1 || level <= this->EndLevel))
{
boxInfo->GetTupleValue(vertex, blimits); // Get the extents of the vertex
if (this->ConvertToDC(blimits, blimitsDC))
{
continue;
}
this->GetVertexLabel(vertex, numericData, stringData, activeComp, numComps,
string);
results = this->AnalyseLabel(string, level, blimitsDC, textPosWC, &tprop);
if (results == 1)
{
// Label doesn't fit in its box - don't both processing children
continue;
}
}
else
{
// results == 2 from AnalyseLabel means that the label can't be
// displayed due to reasons other than size - well in this
// case we can't display due to the level limit we
// also have to deactive the maks for this level
this->LabelMasks[level][0] = -1.0;
results = 2;
}
if (!results)
{
if (!this->TextMappers[this->NumberOfLabels])
{
this->TextMappers[this->NumberOfLabels] = vtkTextMapper::New();
}
this->TextMappers[this->NumberOfLabels]->SetInput(string);
this->TextMappers[this->NumberOfLabels]->
SetTextProperty(tprop);
this->TextPoints->SetPoint(this->NumberOfLabels, textPosWC);
++(this->NumberOfLabels);
}
// Is this level the deepest we can display?
if (this->EndLevel == level)
{
continue;
}
}
dfs->Delete();
this->BuildTime.Modified();
}
int vtkLabeledTreeMapDataMapper::GetStringSize(char *string, int level)
{
if (level > this->MaxFontLevel)
{
level = this->MaxFontLevel;
}
int size = 0, i;
for(i = 0; string[i] != '\0'; i++)
{
if (string[i] < 32)
{
continue;
}
if (string[i] > 126)
{
continue;
}
size += this->FontWidths[level][string[i]-32];
}
return size;
}
int vtkLabeledTreeMapDataMapper::ConvertToDC(float *binfo, float *newBinfo)
{
newBinfo[0] = this->BoxTrans[0][0] + (binfo[0]*this->BoxTrans[0][1]);
newBinfo[1] = this->BoxTrans[0][0] + (binfo[1]*this->BoxTrans[0][1]);
newBinfo[2] = this->BoxTrans[1][0] + (binfo[2]*this->BoxTrans[1][1]);
newBinfo[3] = this->BoxTrans[1][0] + (binfo[3]*this->BoxTrans[1][1]);
// See the comments in AnalyseLabel for why we're comparing against
// these numbers.
double windowWidth = this->WindowLimits[0][1] - this->WindowLimits[0][0];
double windowHeight = this->WindowLimits[1][1] - this->WindowLimits[1][0];
if (newBinfo[0] >= windowWidth)
{
return 1;
}
if (newBinfo[1] <= 0)
{
return 1;
}
if (newBinfo[2] >= windowHeight)
{
return 1;
}
if (newBinfo[3] <= 0)
{
return 1;
}
if (!this->ClipTextMode)
{
return 0;
}
if (newBinfo[0] < 0)
{
newBinfo[0] = 0;
}
if (newBinfo[1] > windowWidth)
{
newBinfo[1] = windowWidth;
}
if (newBinfo[2] < 0)
{
newBinfo[2] = 0;
}
if (newBinfo[3] > windowHeight)
{
newBinfo[3] = windowHeight;
}
return 0;
}
void vtkLabeledTreeMapDataMapper::SetFontSizeRange(int maxSize, int minSize,
int delta)
{
int nLevels = (maxSize - minSize) / delta;
int i, s;
if (nLevels < 0)
{
vtkErrorMacro(<<"maxSize is smaller than minSize");
return;
}
if ((maxSize - (nLevels * delta)) > minSize)
{
++nLevels;
}
if (this->MaxFontLevel != nLevels)
{
if (this->MaxFontLevel)
{
delete [] this->FontHeights;
for (i = 0; i <= this->MaxFontLevel; i++)
{
delete [] this->FontWidths[i];
this->HLabelProperties[i]->Delete();
}
delete [] this->FontWidths;
delete [] this->HLabelProperties;
}
this->MaxFontLevel = nLevels;
this->FontHeights = new int[this->MaxFontLevel+1];
this->FontWidths = new int *[this->MaxFontLevel+1];
this->HLabelProperties = new vtkTextProperty *[this->MaxFontLevel+1];
for(i = 0; i <= this->MaxFontLevel; i++)
{
this->FontWidths[i] = new int[95];
this->HLabelProperties[i] = vtkTextProperty::New();
this->HLabelProperties[i]->SetFontSize(12);
this->HLabelProperties[i]->SetBold(1);
this->HLabelProperties[i]->SetItalic(1);
this->HLabelProperties[i]->SetShadow(1);
this->HLabelProperties[i]->SetFontFamilyToArial();
this->HLabelProperties[i]->SetJustificationToCentered();
this->HLabelProperties[i]->SetVerticalJustificationToCentered();
this->HLabelProperties[i]->SetColor(1, 1, 1);
}
}
for(i = 0, s = maxSize; i < this->MaxFontLevel; i++, s -= delta)
{
this->HLabelProperties[i]->SetFontSize(s);
}
this->HLabelProperties[i]->SetFontSize(minSize);
this->CurrentViewPort = 0;
}
void vtkLabeledTreeMapDataMapper::GetFontSizeRange(int range[3])
{
range[0] = this->HLabelProperties[0]->GetFontSize();
range[1] = this->HLabelProperties[this->MaxFontLevel - 1]->GetFontSize();
range[2] = (range[0] - range[1]) / (this->MaxFontLevel - 1);
}
int vtkLabeledTreeMapDataMapper::AnalyseLabel(char * string, int level,
float *blimitsDC,
float *textPosWC,
vtkTextProperty **tprop)
{
float sizes[2], tPosDC[2], delta, flimits[4];
int fsize, trueLevel, oDir; // oDir is the text orientation
// Calculate the size of the box in DC
sizes[0] = blimitsDC[1] - blimitsDC[0];
sizes[1] = blimitsDC[3] - blimitsDC[2];
trueLevel = level - this->StartLevel;
if (trueLevel < 0)
{
vtkErrorMacro(<< "Invalid level.");
trueLevel = 0;
}
trueLevel =
(trueLevel > this->MaxFontLevel) ? this->MaxFontLevel : trueLevel;
fsize = this->GetStringSize(string, trueLevel);
// Horizontal label.
// (Vertical labels don't work due to issues with vtkTextActor.)
oDir = 0;
*tprop = this->HLabelProperties[trueLevel];
// Is this level dynamic or static?
if (level >= this->DynamicLevel)
{
// See if the text will not even fit in the box
if (sizes[!oDir] < this->FontHeights[trueLevel])
{
// Text will not fit
return 1;
}
if (sizes[oDir] < fsize)
{
// Text will not fit
return 1;
}
}
// Calculate the bounding box of the text
// Determine where to place the text
tPosDC[0] = 0.5 *(blimitsDC[0] + blimitsDC[1]);
tPosDC[1] = 0.5 *(blimitsDC[2] + blimitsDC[3]);
// Compute mask for this level
delta = 0.5 * 1.05 * (!oDir?fsize:this->FontHeights[trueLevel]);
flimits[0] = tPosDC[0] - delta;
flimits[1] = tPosDC[0] + delta;
delta = 0.5 * 1.05 * (oDir?fsize:this->FontHeights[trueLevel]);
flimits[2] = tPosDC[1] - delta;
flimits[3] = tPosDC[1] + delta;
// If the label is not to be centered based on the clipped form of the
// vertex's box see if it has been clipped away
if (!this->ClipTextMode)
{
// The 'flimits' variable contains the bounding box of the label
// in coordinates relative to (0, 0) in the window -- that is, the
// lower left corner of the window. These next few lines test to
// make sure the label is not entirely outside the window. The
// coordinates in WindowLimits are actually in the space of the
// entire screen, not just this application or its OpenGL window.
double windowWidth = this->WindowLimits[0][1] - this->WindowLimits[0][0];
double windowHeight = this->WindowLimits[1][1] - this->WindowLimits[0][0];
if ((flimits[0] >= windowWidth) ||
(flimits[1] <= 0) ||
(flimits[2] >= windowHeight) ||
(flimits[3] <= 0))
{
this->LabelMasks[level][0] = -1.0;
return 2;
}
}
// Apply Masks
if (level && (level > this->DynamicLevel))
{
if (this->ApplyMasks(level, flimits, blimitsDC))
{
// This label does not fit based on the masks
// Since device coordinate can not be < 0 set
// the first component of the mask to be -1
// to indicate the mask is not to be used
this->LabelMasks[level][0] = -1.0;
return 2;
}
}
this->LabelMasks[level][0] = flimits[0];
this->LabelMasks[level][1] = flimits[1];
this->LabelMasks[level][2] = flimits[2];
this->LabelMasks[level][3] = flimits[3];
// since applying the masks can shift the label calculate the
// new position
tPosDC[0] = 0.5 *(flimits[0] + flimits[1]);
tPosDC[1] = 0.5 *(flimits[2] + flimits[3]);
textPosWC[0] = (tPosDC[0] - this->BoxTrans[0][0])/ this->BoxTrans[0][1];
textPosWC[1] = (tPosDC[1] - this->BoxTrans[1][0])/ this->BoxTrans[1][1];
textPosWC[2] = 1.0;
return 0;
}
int vtkLabeledTreeMapDataMapper::ApplyMasks(int level, float flimits[4],
float blimits[4])
{
// Note that all limits and mask information is in Device Coordinates
float dy = 0.0;
int changed = 1, dir = 0, l;
int status = 1;
if (!this->ChildMotion)
{
// If any of the masks intersect the label don't display it
for (l = 0; l < level; l++)
{
// Skip all masks that refer to labels that are not displayed
// (i.e. that the first component < 0)
if (this->LabelMasks[l][0] < 0.0)
{
continue;
}
if (this->LabelMasks[l][0] > flimits[1])
{
continue;
}
if (this->LabelMasks[l][1] < flimits[0])
{
continue;
}
if (this->LabelMasks[l][2] > flimits[3])
{
continue;
}
if (this->LabelMasks[l][3] < flimits[2])
{
continue;
}
// If we are here the label intersects the mask
return 1;
}
return 0;
}
// dir == 0 indicates we are dropping the label and 1 means we are raising it
while (changed)
{
changed = 0;
for (l = 0; l < level; l++)
{
// Skip all masks that refer to labels that are not displayed
// (i.e. that the first component < 0)
// or do not interfere in the y-direction
// (i.e. the second component < 0)
// or has been already fixed in the y-direction
// (.i.e the third component < 0)
if ((this->LabelMasks[l][0] < 0.0) ||
(this->LabelMasks[l][1] < 0.0) ||
(this->LabelMasks[l][2] < 0.0))
{
continue;
}
// If the label passes either x-check it will never
// interfere with a horizontal label
if (this->LabelMasks[l][0] > flimits[1])
{
// Set the second component to be -(value + 1) - the reason
// for the offset is to take of the case the original value is 0
this->LabelMasks[l][1] = -1.0 * (this->LabelMasks[l][1] + 1.0);
continue;
}
if (this->LabelMasks[l][1] < flimits[0])
{
this->LabelMasks[l][1] = -1.0 * (this->LabelMasks[l][1] + 1.0);
continue;
}
if (this->LabelMasks[l][2] > (flimits[3]+dy))
{
// If dy < 0 then this condition will always be true and
// this check can be turned off
if (dy < 0.0)
{
this->LabelMasks[l][2] = -1.0 * (this->LabelMasks[l][2] + 1.0);
}
continue;
}
if (this->LabelMasks[l][3] < (flimits[2]+dy))
{
// If dy > 0 then this condition will always be true and
// this check can be turned off
if (dy > 0.0)
{
this->LabelMasks[l][2] = -1.0 * (this->LabelMasks[l][2] + 1.0);
}
continue;
}
// If we are here then the mask does clip the label
// see which direction we are going it - added a cushion of 5 pixels
if (dir)
{
dy = 5 + this->LabelMasks[l][3] - flimits[2];
}
else
{
dy = this->LabelMasks[l][2] - (5 + flimits[3]);
}
// Indicate that we changed something
changed = 1;
}
// See if anything changed - if it did then repeat the mask loop
if (changed)
{
continue;
}
// See if the current label position will not fit on the screen
if ((blimits[2] > (flimits[2] + dy)) || (blimits[3] < (flimits[3] + dy)))
{
// Have we been dropping the label?
if (!dir)
{
// Try raising it - we will need to reset all the masks with
// negative third components
dir = 1;
changed = 1;
for (l = 0; l < level; l++)
{
if (this->LabelMasks[l][2] < 0.0)
{
this->LabelMasks[l][2] = - 1.0 * (this->LabelMasks[l][2]+ 1.0);
}
}
}
// in this case there was no way to display the label
status = 1;
}
else
{
// Success
status = 0;
flimits[2] += dy;
flimits[3] += dy;
}
}
// Reset masks that were deactivated
for (l = 0; l < level; l++)
{
if (this->LabelMasks[l][1] < 0.0)
{
this->LabelMasks[l][1] = - 1.0 * (this->LabelMasks[l][1]+ 1.0);
continue;
}
if (this->LabelMasks[l][2] < 0.0)
{
this->LabelMasks[l][2] = - 1.0 * (this->LabelMasks[l][2]+ 1.0);
continue;
}
}
return status;
}
void vtkLabeledTreeMapDataMapper::SetLevelRange(int start, int end)
{
if (((end != -1) && (start > end)) || (start < 0))
{
vtkErrorMacro(<<"Invalid level range specified.");
return;
}
this->StartLevel = start;
this->EndLevel = end;
this->BuildTime.Modified();
}
void vtkLabeledTreeMapDataMapper::GetLevelRange(int range[2])
{
range[0] = this->StartLevel;
range[1] = this->EndLevel;
}