1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkTreeMapLayout.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /*-------------------------------------------------------------------------
16   Copyright 2008 Sandia Corporation.
17   Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
18   the U.S. Government retains certain rights in this software.
19 -------------------------------------------------------------------------*/
20 
21 #include "vtkTreeMapLayout.h"
22 
23 #include "vtkAdjacentVertexIterator.h"
24 #include "vtkCellArray.h"
25 #include "vtkCellData.h"
26 #include "vtkDataArray.h"
27 #include "vtkFloatArray.h"
28 #include "vtkInformation.h"
29 #include "vtkInformationVector.h"
30 #include "vtkMath.h"
31 #include "vtkObjectFactory.h"
32 #include "vtkPointData.h"
33 #include "vtkTree.h"
34 #include "vtkTreeMapLayoutStrategy.h"
35 
36 vtkStandardNewMacro(vtkTreeMapLayout);
37 
vtkTreeMapLayout()38 vtkTreeMapLayout::vtkTreeMapLayout()
39 {
40   this->RectanglesFieldName = nullptr;
41   this->LayoutStrategy = nullptr;
42   this->SetRectanglesFieldName("area");
43   this->SetSizeArrayName("size");
44 }
45 
~vtkTreeMapLayout()46 vtkTreeMapLayout::~vtkTreeMapLayout()
47 {
48   this->SetRectanglesFieldName(nullptr);
49   if (this->LayoutStrategy)
50   {
51     this->LayoutStrategy->Delete();
52   }
53 }
54 
55 vtkCxxSetObjectMacro(vtkTreeMapLayout, LayoutStrategy, vtkTreeMapLayoutStrategy);
56 
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)57 int vtkTreeMapLayout::RequestData(vtkInformation* vtkNotUsed(request),
58   vtkInformationVector** inputVector, vtkInformationVector* outputVector)
59 {
60   if (this->LayoutStrategy == nullptr)
61   {
62     vtkErrorMacro(<< "Layout strategy must be non-null.");
63     return 0;
64   }
65   if (this->RectanglesFieldName == nullptr)
66   {
67     vtkErrorMacro(<< "Rectangles field name must be non-null.");
68     return 0;
69   }
70   // get the info objects
71   vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
72   vtkInformation* outInfo = outputVector->GetInformationObject(0);
73 
74   // Storing the inputTree and outputTree handles
75   vtkTree* inputTree = vtkTree::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
76   vtkTree* outputTree = vtkTree::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
77 
78   // Copy the input into the output
79   outputTree->ShallowCopy(inputTree);
80 
81   // Add the 4-tuple array that will store the min,max xy coords
82   vtkFloatArray* coordsArray = vtkFloatArray::New();
83   coordsArray->SetName(this->RectanglesFieldName);
84   coordsArray->SetNumberOfComponents(4);
85   coordsArray->SetNumberOfTuples(inputTree->GetNumberOfVertices());
86   vtkDataSetAttributes* data = outputTree->GetVertexData();
87   data->AddArray(coordsArray);
88   coordsArray->Delete();
89 
90   // Add the 4-tuple array that will store the min,max xy coords
91   vtkDataArray* sizeArray = this->GetInputArrayToProcess(0, inputTree);
92   if (!sizeArray)
93   {
94     vtkErrorMacro("Size array not found.");
95     return 0;
96   }
97 
98   // Okay now layout the tree :)
99   this->LayoutStrategy->Layout(inputTree, coordsArray, sizeArray);
100 
101   return 1;
102 }
103 
PrintSelf(ostream & os,vtkIndent indent)104 void vtkTreeMapLayout::PrintSelf(ostream& os, vtkIndent indent)
105 {
106   this->Superclass::PrintSelf(os, indent);
107   os << indent << "RectanglesFieldName: "
108      << (this->RectanglesFieldName ? this->RectanglesFieldName : "(none)") << endl;
109   os << indent << "LayoutStrategy: " << (this->LayoutStrategy ? "" : "(none)") << endl;
110   if (this->LayoutStrategy)
111   {
112     this->LayoutStrategy->PrintSelf(os, indent.GetNextIndent());
113   }
114 }
115 
FindVertex(float pnt[2],float * binfo)116 vtkIdType vtkTreeMapLayout::FindVertex(float pnt[2], float* binfo)
117 {
118   // Do we have an output?
119   vtkTree* otree = this->GetOutput();
120   if (!otree)
121   {
122     vtkErrorMacro(<< "Could not get output tree.");
123     return -1;
124   }
125 
126   // Get the four tuple array for the points
127   vtkDataArray* array = otree->GetVertexData()->GetArray(this->RectanglesFieldName);
128   if (!array)
129   {
130     // vtkErrorMacro(<< "Output Tree does not have box information.");
131     return -1;
132   }
133 
134   // Check to see that we are in the dataset at all
135   float blimits[4];
136 
137   vtkIdType vertex = otree->GetRoot();
138   vtkFloatArray* boxInfo = vtkArrayDownCast<vtkFloatArray>(array);
139   // Now try to find the vertex that contains the point
140   boxInfo->GetTypedTuple(vertex, blimits); // Get the extents of the root
141   if ((pnt[0] < blimits[0]) || (pnt[0] > blimits[1]) || (pnt[1] < blimits[2]) ||
142     (pnt[1] > blimits[3]))
143   {
144     // Point is not in the tree at all
145     return -1;
146   }
147 
148   // Now traverse the children to try and find
149   // the vertex that contains the point
150   vtkIdType child;
151   if (binfo)
152   {
153     binfo[0] = blimits[0];
154     binfo[1] = blimits[1];
155     binfo[2] = blimits[2];
156     binfo[3] = blimits[3];
157   }
158 
159   vtkAdjacentVertexIterator* it = vtkAdjacentVertexIterator::New();
160   otree->GetAdjacentVertices(vertex, it);
161   while (it->HasNext())
162   {
163     child = it->Next();
164     boxInfo->GetTypedTuple(child, blimits); // Get the extents of the child
165     if ((pnt[0] < blimits[0]) || (pnt[0] > blimits[1]) || (pnt[1] < blimits[2]) ||
166       (pnt[1] > blimits[3]))
167     {
168       continue;
169     }
170     // If we are here then the point is contained by the child
171     // So recurse down the children of this vertex
172     vertex = child;
173     otree->GetAdjacentVertices(vertex, it);
174   }
175   it->Delete();
176 
177   return vertex;
178 }
179 
GetBoundingBox(vtkIdType id,float * binfo)180 void vtkTreeMapLayout::GetBoundingBox(vtkIdType id, float* binfo)
181 {
182   // Do we have an output?
183   vtkTree* otree = this->GetOutput();
184   if (!otree)
185   {
186     vtkErrorMacro(<< "Could not get output tree.");
187     return;
188   }
189 
190   // Get the four tuple array for the points
191   vtkDataArray* array = otree->GetVertexData()->GetArray(this->RectanglesFieldName);
192   if (!array)
193   {
194     // vtkErrorMacro(<< "Output Tree does not have box information.");
195     return;
196   }
197 
198   vtkFloatArray* boxInfo = vtkArrayDownCast<vtkFloatArray>(array);
199   boxInfo->GetTypedTuple(id, binfo);
200 }
201 
GetMTime()202 vtkMTimeType vtkTreeMapLayout::GetMTime()
203 {
204   vtkMTimeType mTime = this->Superclass::GetMTime();
205   vtkMTimeType time;
206 
207   if (this->LayoutStrategy != nullptr)
208   {
209     time = this->LayoutStrategy->GetMTime();
210     mTime = (time > mTime ? time : mTime);
211   }
212   return mTime;
213 }
214