1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkConvertSelectionDomain.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 #include "vtkConvertSelectionDomain.h"
21
22 #include "vtkAbstractArray.h"
23 #include "vtkAnnotation.h"
24 #include "vtkAnnotationLayers.h"
25 #include "vtkCellData.h"
26 #include "vtkDataSet.h"
27 #include "vtkDataSetAttributes.h"
28 #include "vtkGraph.h"
29 #include "vtkIdList.h"
30 #include "vtkIdTypeArray.h"
31 #include "vtkInformation.h"
32 #include "vtkInformationVector.h"
33 #include "vtkMultiBlockDataSet.h"
34 #include "vtkObjectFactory.h"
35 #include "vtkPointData.h"
36 #include "vtkSelection.h"
37 #include "vtkSelectionNode.h"
38 #include "vtkSmartPointer.h"
39 #include "vtkStringArray.h"
40 #include "vtkTable.h"
41
42 #include <set>
43
44 vtkStandardNewMacro(vtkConvertSelectionDomain);
45 //------------------------------------------------------------------------------
vtkConvertSelectionDomain()46 vtkConvertSelectionDomain::vtkConvertSelectionDomain()
47 {
48 this->SetNumberOfInputPorts(3);
49 this->SetNumberOfOutputPorts(2);
50 }
51
52 //------------------------------------------------------------------------------
53 vtkConvertSelectionDomain::~vtkConvertSelectionDomain() = default;
54
55 //------------------------------------------------------------------------------
vtkConvertSelectionDomainFindDomains(vtkDataSetAttributes * dsa,std::set<vtkStdString> & domains)56 static void vtkConvertSelectionDomainFindDomains(
57 vtkDataSetAttributes* dsa, std::set<vtkStdString>& domains)
58 {
59 if (dsa->GetAbstractArray("domain"))
60 {
61 vtkStringArray* domainArr = vtkArrayDownCast<vtkStringArray>(dsa->GetAbstractArray("domain"));
62 if (!domainArr)
63 {
64 return; // Do nothing if the array isn't a string array
65 }
66 vtkIdType numTuples = domainArr->GetNumberOfTuples();
67 for (vtkIdType i = 0; i < numTuples; ++i)
68 {
69 vtkStdString d = domainArr->GetValue(i);
70 if (domains.count(d) == 0)
71 {
72 domains.insert(d);
73 }
74 }
75 }
76 else if (dsa->GetPedigreeIds() && dsa->GetPedigreeIds()->GetName())
77 {
78 domains.insert(dsa->GetPedigreeIds()->GetName());
79 }
80 }
81
vtkConvertSelectionDomainConvertAnnotationDomain(vtkAnnotation * annIn,vtkAnnotation * annOut,std::set<vtkStdString> & domains1,std::set<vtkStdString> & domains2,vtkDataSetAttributes * dsa1,vtkDataSetAttributes * dsa2,int fieldType1,int fieldType2,vtkMultiBlockDataSet * maps)82 static void vtkConvertSelectionDomainConvertAnnotationDomain(vtkAnnotation* annIn,
83 vtkAnnotation* annOut, std::set<vtkStdString>& domains1, std::set<vtkStdString>& domains2,
84 vtkDataSetAttributes* dsa1, vtkDataSetAttributes* dsa2, int fieldType1, int fieldType2,
85 vtkMultiBlockDataSet* maps)
86 {
87 vtkSelection* inputSel = annIn->GetSelection();
88 vtkSmartPointer<vtkSelection> outputSel = vtkSmartPointer<vtkSelection>::New();
89 // Iterate over all input selections
90 for (unsigned int c = 0; c < inputSel->GetNumberOfNodes(); ++c)
91 {
92 vtkSelectionNode* curInput = inputSel->GetNode(c);
93 vtkSmartPointer<vtkSelectionNode> curOutput = vtkSmartPointer<vtkSelectionNode>::New();
94 vtkAbstractArray* inArr = curInput->GetSelectionList();
95
96 // Start with a shallow copy of the input selection.
97 curOutput->ShallowCopy(curInput);
98
99 // I don't know how to handle this type of selection,
100 // so pass it through.
101 if (!inArr || !inArr->GetName() || curInput->GetContentType() != vtkSelectionNode::PEDIGREEIDS)
102 {
103 outputSel->AddNode(curOutput);
104 continue;
105 }
106
107 // If the selection already matches, we are done.
108 if (domains1.count(inArr->GetName()) > 0)
109 {
110 curOutput->SetFieldType(fieldType1);
111 outputSel->AddNode(curOutput);
112 continue;
113 }
114 if (domains2.count(inArr->GetName()) > 0)
115 {
116 curOutput->SetFieldType(fieldType2);
117 outputSel->AddNode(curOutput);
118 continue;
119 }
120
121 // Select the correct source and destination mapping arrays.
122 vtkAbstractArray* fromArr = nullptr;
123 vtkAbstractArray* toArr = nullptr;
124 unsigned int numMaps = maps->GetNumberOfBlocks();
125 for (unsigned int i = 0; i < numMaps; ++i)
126 {
127 fromArr = nullptr;
128 toArr = nullptr;
129 vtkTable* table = vtkTable::SafeDownCast(maps->GetBlock(i));
130 if (table)
131 {
132 fromArr = table->GetColumnByName(inArr->GetName());
133 std::set<vtkStdString>::iterator it, itEnd;
134 if (dsa1)
135 {
136 it = domains1.begin();
137 itEnd = domains1.end();
138 for (; it != itEnd; ++it)
139 {
140 toArr = table->GetColumnByName(it->c_str());
141 if (toArr)
142 {
143 curOutput->SetFieldType(fieldType1);
144 break;
145 }
146 }
147 }
148 if (!toArr && dsa2)
149 {
150 it = domains2.begin();
151 itEnd = domains2.end();
152 for (; it != itEnd; ++it)
153 {
154 toArr = table->GetColumnByName(it->c_str());
155 if (toArr)
156 {
157 curOutput->SetFieldType(fieldType2);
158 break;
159 }
160 }
161 }
162 }
163 if (fromArr && toArr)
164 {
165 break;
166 }
167 }
168
169 // Cannot do the conversion, so don't pass this selection
170 // to the output.
171 if (!fromArr || !toArr)
172 {
173 continue;
174 }
175
176 // Lookup values in the input selection and map them
177 // through the table to the output selection.
178 vtkIdType numTuples = inArr->GetNumberOfTuples();
179 vtkSmartPointer<vtkAbstractArray> outArr;
180 outArr.TakeReference(vtkAbstractArray::CreateArray(toArr->GetDataType()));
181 outArr->SetName(toArr->GetName());
182 vtkSmartPointer<vtkIdList> ids = vtkSmartPointer<vtkIdList>::New();
183 for (vtkIdType i = 0; i < numTuples; ++i)
184 {
185 fromArr->LookupValue(inArr->GetVariantValue(i), ids);
186 vtkIdType numIds = ids->GetNumberOfIds();
187 for (vtkIdType j = 0; j < numIds; ++j)
188 {
189 outArr->InsertNextTuple(ids->GetId(j), toArr);
190 }
191 }
192 curOutput->SetSelectionList(outArr);
193 outputSel->AddNode(curOutput);
194 }
195 // Make sure there is at least something in the output selection.
196 if (outputSel->GetNumberOfNodes() == 0)
197 {
198 vtkSmartPointer<vtkSelectionNode> node = vtkSmartPointer<vtkSelectionNode>::New();
199 node->SetContentType(vtkSelectionNode::INDICES);
200 vtkSmartPointer<vtkIdTypeArray> inds = vtkSmartPointer<vtkIdTypeArray>::New();
201 node->SetSelectionList(inds);
202 outputSel->AddNode(node);
203 }
204
205 annOut->ShallowCopy(annIn);
206 annOut->SetSelection(outputSel);
207 }
208
209 //------------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)210 int vtkConvertSelectionDomain::RequestData(vtkInformation* vtkNotUsed(request),
211 vtkInformationVector** inputVector, vtkInformationVector* outputVector)
212 {
213 // Retrieve the input and output.
214 vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
215 vtkDataObject* input = inInfo->Get(vtkDataObject::DATA_OBJECT());
216 vtkAnnotationLayers* inputAnn = vtkAnnotationLayers::SafeDownCast(input);
217
218 vtkInformation* outInfo = outputVector->GetInformationObject(0);
219 vtkDataObject* output = outInfo->Get(vtkDataObject::DATA_OBJECT());
220 vtkAnnotationLayers* outputAnn = vtkAnnotationLayers::SafeDownCast(output);
221
222 outInfo = outputVector->GetInformationObject(1);
223 vtkSelection* outputCurrentSel =
224 vtkSelection::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
225
226 // If we have no mapping table, we are done.
227 vtkInformation* mapInfo = inputVector[1]->GetInformationObject(0);
228 vtkInformation* dataInfo = inputVector[2]->GetInformationObject(0);
229 if (!dataInfo || !mapInfo)
230 {
231 output->ShallowCopy(input);
232 return 1;
233 }
234
235 // If the input is instead a vtkSelection, wrap it in a vtkAnnotationLayers
236 // object so it can be used uniformly in the function.
237 bool createdInput = false;
238 if (!inputAnn)
239 {
240 vtkSelection* inputSel = vtkSelection::SafeDownCast(input);
241 inputAnn = vtkAnnotationLayers::New();
242 inputAnn->SetCurrentSelection(inputSel);
243 vtkSelection* outputSel = vtkSelection::SafeDownCast(output);
244 outputAnn = vtkAnnotationLayers::New();
245 outputAnn->SetCurrentSelection(outputSel);
246 createdInput = true;
247 }
248
249 vtkMultiBlockDataSet* maps =
250 vtkMultiBlockDataSet::SafeDownCast(mapInfo->Get(vtkDataObject::DATA_OBJECT()));
251 vtkDataObject* data = dataInfo->Get(vtkDataObject::DATA_OBJECT());
252
253 vtkDataSetAttributes* dsa1 = nullptr;
254 int fieldType1 = 0;
255 vtkDataSetAttributes* dsa2 = nullptr;
256 int fieldType2 = 0;
257 if (vtkDataSet::SafeDownCast(data))
258 {
259 dsa1 = vtkDataSet::SafeDownCast(data)->GetPointData();
260 fieldType1 = vtkSelectionNode::POINT;
261 dsa2 = vtkDataSet::SafeDownCast(data)->GetCellData();
262 fieldType2 = vtkSelectionNode::CELL;
263 }
264 else if (vtkGraph::SafeDownCast(data))
265 {
266 dsa1 = vtkGraph::SafeDownCast(data)->GetVertexData();
267 fieldType1 = vtkSelectionNode::VERTEX;
268 dsa2 = vtkGraph::SafeDownCast(data)->GetEdgeData();
269 fieldType2 = vtkSelectionNode::EDGE;
270 }
271 else if (vtkTable::SafeDownCast(data))
272 {
273 dsa1 = vtkDataSetAttributes::SafeDownCast(vtkTable::SafeDownCast(data)->GetRowData());
274 fieldType1 = vtkSelectionNode::ROW;
275 }
276
277 std::set<vtkStdString> domains1;
278 std::set<vtkStdString> domains2;
279 if (dsa1)
280 {
281 vtkConvertSelectionDomainFindDomains(dsa1, domains1);
282 }
283 if (dsa2)
284 {
285 vtkConvertSelectionDomainFindDomains(dsa2, domains2);
286 }
287
288 for (unsigned int a = 0; a < inputAnn->GetNumberOfAnnotations(); ++a)
289 {
290 vtkSmartPointer<vtkAnnotation> ann = vtkSmartPointer<vtkAnnotation>::New();
291 vtkConvertSelectionDomainConvertAnnotationDomain(inputAnn->GetAnnotation(a), ann, domains1,
292 domains2, dsa1, dsa2, fieldType1, fieldType2, maps);
293 outputAnn->AddAnnotation(ann);
294 }
295
296 if (inputAnn->GetCurrentAnnotation())
297 {
298 vtkSmartPointer<vtkAnnotation> ann = vtkSmartPointer<vtkAnnotation>::New();
299 vtkConvertSelectionDomainConvertAnnotationDomain(inputAnn->GetCurrentAnnotation(), ann,
300 domains1, domains2, dsa1, dsa2, fieldType1, fieldType2, maps);
301 outputAnn->SetCurrentAnnotation(ann);
302 }
303 else
304 {
305 outputAnn->SetCurrentAnnotation(nullptr);
306 }
307
308 // Copy current selection to the second output
309 if (outputAnn->GetCurrentSelection())
310 {
311 outputCurrentSel->ShallowCopy(outputAnn->GetCurrentSelection());
312 }
313
314 if (createdInput)
315 {
316 inputAnn->Delete();
317 outputAnn->Delete();
318 }
319 return 1;
320 }
321
322 //------------------------------------------------------------------------------
FillInputPortInformation(int port,vtkInformation * info)323 int vtkConvertSelectionDomain::FillInputPortInformation(int port, vtkInformation* info)
324 {
325 if (port == 0)
326 {
327 info->Remove(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE());
328 info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkSelection");
329 info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkAnnotationLayers");
330 }
331 else if (port == 1)
332 {
333 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet");
334 }
335 else if (port == 2)
336 {
337 info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
338 info->Remove(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE());
339 info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
340 info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable");
341 info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGraph");
342 }
343 return 1;
344 }
345
346 //------------------------------------------------------------------------------
FillOutputPortInformation(int port,vtkInformation * info)347 int vtkConvertSelectionDomain::FillOutputPortInformation(int port, vtkInformation* info)
348 {
349 this->Superclass::FillOutputPortInformation(port, info);
350 if (port == 1)
351 {
352 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkSelection");
353 }
354 return 1;
355 }
356
357 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)358 void vtkConvertSelectionDomain::PrintSelf(ostream& os, vtkIndent indent)
359 {
360 this->Superclass::PrintSelf(os, indent);
361 }
362