1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkDemandDrivenPipeline.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 #include "vtkDemandDrivenPipeline.h"
16
17 #include "vtkAlgorithm.h"
18 #include "vtkAlgorithmOutput.h"
19 #include "vtkCellData.h"
20 #include "vtkCommand.h"
21 #include "vtkDataArray.h"
22 #include "vtkDataObject.h"
23 #include "vtkDataObjectTypes.h"
24 #include "vtkDataSet.h"
25 #include "vtkGarbageCollector.h"
26 #include "vtkInformation.h"
27 #include "vtkInformationExecutivePortKey.h"
28 #include "vtkInformationExecutivePortVectorKey.h"
29 #include "vtkInformationIntegerKey.h"
30 #include "vtkInformationKeyVectorKey.h"
31 #include "vtkInformationRequestKey.h"
32 #include "vtkInformationUnsignedLongKey.h"
33 #include "vtkInformationVector.h"
34 #include "vtkLogger.h"
35 #include "vtkObjectFactory.h"
36 #include "vtkPointData.h"
37
38 #include <vector>
39
40 vtkStandardNewMacro(vtkDemandDrivenPipeline);
41
42 vtkInformationKeyMacro(vtkDemandDrivenPipeline, DATA_NOT_GENERATED, Integer);
43 vtkInformationKeyMacro(vtkDemandDrivenPipeline, RELEASE_DATA, Integer);
44 vtkInformationKeyMacro(vtkDemandDrivenPipeline, REQUEST_DATA, Request);
45 vtkInformationKeyMacro(vtkDemandDrivenPipeline, REQUEST_DATA_NOT_GENERATED, Request);
46 vtkInformationKeyMacro(vtkDemandDrivenPipeline, REQUEST_DATA_OBJECT, Request);
47 vtkInformationKeyMacro(vtkDemandDrivenPipeline, REQUEST_INFORMATION, Request);
48
49 //------------------------------------------------------------------------------
vtkDemandDrivenPipeline()50 vtkDemandDrivenPipeline::vtkDemandDrivenPipeline()
51 {
52 this->InfoRequest = nullptr;
53 this->DataObjectRequest = nullptr;
54 this->DataRequest = nullptr;
55 this->PipelineMTime = 0;
56 }
57
58 //------------------------------------------------------------------------------
~vtkDemandDrivenPipeline()59 vtkDemandDrivenPipeline::~vtkDemandDrivenPipeline()
60 {
61 if (this->InfoRequest)
62 {
63 this->InfoRequest->Delete();
64 }
65 if (this->DataObjectRequest)
66 {
67 this->DataObjectRequest->Delete();
68 }
69 if (this->DataRequest)
70 {
71 this->DataRequest->Delete();
72 }
73 }
74
75 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)76 void vtkDemandDrivenPipeline::PrintSelf(ostream& os, vtkIndent indent)
77 {
78 this->Superclass::PrintSelf(os, indent);
79 os << indent << "PipelineMTime: " << this->PipelineMTime << "\n";
80 }
81
82 //------------------------------------------------------------------------------
ComputePipelineMTime(vtkInformation * request,vtkInformationVector ** inInfoVec,vtkInformationVector * outInfoVec,int requestFromOutputPort,vtkMTimeType * mtime)83 int vtkDemandDrivenPipeline::ComputePipelineMTime(vtkInformation* request,
84 vtkInformationVector** inInfoVec, vtkInformationVector* outInfoVec, int requestFromOutputPort,
85 vtkMTimeType* mtime)
86 {
87 // The pipeline's MTime starts with this algorithm's MTime.
88 // Invoke the request on the algorithm.
89 this->InAlgorithm = 1;
90 int result = this->Algorithm->ComputePipelineMTime(
91 request, inInfoVec, outInfoVec, requestFromOutputPort, &this->PipelineMTime);
92 this->InAlgorithm = 0;
93
94 // If the algorithm failed report it now.
95 if (!result)
96 {
97 if (request)
98 {
99 vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName() << "(" << this->Algorithm
100 << ") returned failure for pipeline"
101 << " modified time request from output port "
102 << requestFromOutputPort << ": " << *request);
103 }
104 else
105 {
106 vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName() << "(" << this->Algorithm
107 << ") returned failure for pipeline"
108 << " modified time request from output port "
109 << requestFromOutputPort << ".");
110 }
111 return 0;
112 }
113
114 // Forward the request upstream if not sharing input information.
115 if (!this->SharedInputInformation)
116 {
117 // We want the maximum PipelineMTime of all inputs.
118 for (int i = 0; i < this->Algorithm->GetNumberOfInputPorts(); ++i)
119 {
120 for (int j = 0; j < inInfoVec[i]->GetNumberOfInformationObjects(); ++j)
121 {
122 vtkInformation* info = inInfoVec[i]->GetInformationObject(j);
123 // call ComputePipelineMTime on the input
124 vtkExecutive* e;
125 int producerPort;
126 vtkExecutive::PRODUCER()->Get(info, e, producerPort);
127 if (e)
128 {
129 vtkMTimeType pmtime;
130 if (!e->ComputePipelineMTime(request, e->GetInputInformation(), e->GetOutputInformation(),
131 producerPort, &pmtime))
132 {
133 return 0;
134 }
135 if (pmtime > this->PipelineMTime)
136 {
137 this->PipelineMTime = pmtime;
138 }
139 }
140 }
141 }
142 }
143 *mtime = this->PipelineMTime;
144 return 1;
145 }
146
147 //------------------------------------------------------------------------------
ProcessRequest(vtkInformation * request,vtkInformationVector ** inInfoVec,vtkInformationVector * outInfoVec)148 vtkTypeBool vtkDemandDrivenPipeline::ProcessRequest(
149 vtkInformation* request, vtkInformationVector** inInfoVec, vtkInformationVector* outInfoVec)
150 {
151 // The algorithm should not invoke anything on the executive.
152 if (!this->CheckAlgorithm("ProcessRequest", request))
153 {
154 return 0;
155 }
156
157 if (this->Algorithm && request->Has(REQUEST_DATA_OBJECT()))
158 {
159 // if we are up to date then short circuit
160 if (this->PipelineMTime < this->DataObjectTime.GetMTime())
161 {
162 return 1;
163 }
164 // Update inputs first if they are out of date
165 if (!this->ForwardUpstream(request))
166 {
167 return 0;
168 }
169
170 // Make sure our output data type is up-to-date.
171 int result = 1;
172 if (this->PipelineMTime > this->DataObjectTime.GetMTime())
173 {
174 // Request data type from the algorithm.
175 vtkLogF(TRACE, "%s execute-data-object", vtkLogIdentifier(this->Algorithm));
176 result = this->ExecuteDataObject(request, inInfoVec, outInfoVec);
177
178 // Make sure the data object exists for all output ports.
179 for (int i = 0; result && i < outInfoVec->GetNumberOfInformationObjects(); ++i)
180 {
181 vtkInformation* info = outInfoVec->GetInformationObject(i);
182 if (!info->Get(vtkDataObject::DATA_OBJECT()))
183 {
184 result = 0;
185 }
186 }
187
188 if (result)
189 {
190 // Data object is now up to date.
191 this->DataObjectTime.Modified();
192 }
193 }
194
195 return result;
196 }
197
198 if (this->Algorithm && request->Has(REQUEST_INFORMATION()))
199 {
200 // if we are up to date then short circuit
201 if (this->PipelineMTime < this->InformationTime.GetMTime())
202 {
203 return 1;
204 }
205 // Update inputs first.
206 if (!this->ForwardUpstream(request))
207 {
208 return 0;
209 }
210
211 // Make sure our output information is up-to-date.
212 int result = 1;
213 if (this->PipelineMTime > this->InformationTime.GetMTime())
214
215 {
216 // Make sure input types are valid before algorithm does anything.
217 if (!this->InputCountIsValid(inInfoVec) || !this->InputTypeIsValid(inInfoVec))
218 {
219 return 0;
220 }
221
222 // Request information from the algorithm.
223 vtkLogF(TRACE, "%s execute-information", vtkLogIdentifier(this->Algorithm));
224 result = this->ExecuteInformation(request, inInfoVec, outInfoVec);
225
226 // Information is now up to date.
227 this->InformationTime.Modified();
228 }
229
230 return result;
231 }
232
233 if (this->Algorithm && request->Has(REQUEST_DATA()))
234 {
235 // Get the output port from which the request was made.
236 int outputPort = -1;
237 if (request->Has(FROM_OUTPUT_PORT()))
238 {
239 outputPort = request->Get(FROM_OUTPUT_PORT());
240 }
241
242 // Make sure our outputs are up-to-date.
243 int result = 1;
244 if (this->NeedToExecuteData(outputPort, inInfoVec, outInfoVec))
245 {
246 // Update inputs first.
247 if (!this->ForwardUpstream(request))
248 {
249 return 0;
250 }
251
252 // Make sure inputs are valid before algorithm does anything.
253 if (!this->InputCountIsValid(inInfoVec) || !this->InputTypeIsValid(inInfoVec) ||
254 !this->InputFieldsAreValid(inInfoVec))
255 {
256 return 0;
257 }
258
259 // Request data from the algorithm.
260 vtkLogF(TRACE, "%s execute-data", vtkLogIdentifier(this->Algorithm));
261 result = this->ExecuteData(request, inInfoVec, outInfoVec);
262
263 // Data are now up to date.
264 this->DataTime.Modified();
265
266 // Some filters may modify themselves while processing
267 // REQUEST_DATA. Since we mark the filter execution end time
268 // here this behavior does not cause re-execution, so it should
269 // be allowed. The filter is now considered up-to-date.
270 // However, we must prevent the REQUEST_DATA_OBJECT and
271 // REQUEST_INFORMATION passes from re-running, so mark them
272 // up-do-date also. It is up to the filter to not modify itself
273 // in a way that would change the result of any pass.
274 this->InformationTime.Modified();
275 this->DataObjectTime.Modified();
276 }
277 return result;
278 }
279
280 // Let the superclass handle other requests.
281 return this->Superclass::ProcessRequest(request, inInfoVec, outInfoVec);
282 }
283
284 //------------------------------------------------------------------------------
ResetPipelineInformation(int,vtkInformation *)285 void vtkDemandDrivenPipeline::ResetPipelineInformation(int, vtkInformation*) {}
286
287 //------------------------------------------------------------------------------
Update()288 vtkTypeBool vtkDemandDrivenPipeline::Update()
289 {
290 return this->Superclass::Update();
291 }
292
293 //------------------------------------------------------------------------------
Update(int port)294 vtkTypeBool vtkDemandDrivenPipeline::Update(int port)
295 {
296 if (!this->UpdateInformation())
297 {
298 return 0;
299 }
300 if (port >= -1 && port < this->Algorithm->GetNumberOfOutputPorts())
301 {
302 return this->UpdateData(port);
303 }
304 else
305 {
306 return 1;
307 }
308 }
309
310 //------------------------------------------------------------------------------
UpdatePipelineMTime()311 int vtkDemandDrivenPipeline::UpdatePipelineMTime()
312 {
313 // The algorithm should not invoke anything on the executive.
314 if (!this->CheckAlgorithm("UpdatePipelineMTime", nullptr))
315 {
316 return 0;
317 }
318
319 // Send the request for pipeline modified time.
320 vtkMTimeType mtime;
321 this->ComputePipelineMTime(
322 nullptr, this->GetInputInformation(), this->GetOutputInformation(), -1, &mtime);
323 return 1;
324 }
325
326 //------------------------------------------------------------------------------
UpdateDataObject()327 int vtkDemandDrivenPipeline::UpdateDataObject()
328 {
329 // The algorithm should not invoke anything on the executive.
330 if (!this->CheckAlgorithm("UpdateDataObject", nullptr))
331 {
332 return 0;
333 }
334
335 // Update the pipeline mtime first.
336 if (!this->UpdatePipelineMTime())
337 {
338 return 0;
339 }
340
341 // Setup the request for data object creation.
342 if (!this->DataObjectRequest)
343 {
344 this->DataObjectRequest = vtkInformation::New();
345 this->DataObjectRequest->Set(REQUEST_DATA_OBJECT());
346 // The request is forwarded upstream through the pipeline.
347 this->DataObjectRequest->Set(vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream);
348 // Algorithms process this request after it is forwarded.
349 this->DataObjectRequest->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1);
350 }
351
352 // Send the request.
353 return this->ProcessRequest(
354 this->DataObjectRequest, this->GetInputInformation(), this->GetOutputInformation());
355 }
356
357 //------------------------------------------------------------------------------
UpdateInformation()358 int vtkDemandDrivenPipeline::UpdateInformation()
359 {
360 // The algorithm should not invoke anything on the executive.
361 if (!this->CheckAlgorithm("UpdateInformation", nullptr))
362 {
363 return 0;
364 }
365
366 // Do the data-object creation pass before the information pass.
367 if (!this->UpdateDataObject())
368 {
369 return 0;
370 }
371
372 // Setup the request for information.
373 if (!this->InfoRequest)
374 {
375 this->InfoRequest = vtkInformation::New();
376 this->InfoRequest->Set(REQUEST_INFORMATION());
377 // The request is forwarded upstream through the pipeline.
378 this->InfoRequest->Set(vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream);
379 // Algorithms process this request after it is forwarded.
380 this->InfoRequest->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1);
381 }
382
383 // Send the request.
384 return this->ProcessRequest(
385 this->InfoRequest, this->GetInputInformation(), this->GetOutputInformation());
386 }
387
388 //------------------------------------------------------------------------------
UpdateData(int outputPort)389 int vtkDemandDrivenPipeline::UpdateData(int outputPort)
390 {
391 // The algorithm should not invoke anything on the executive.
392 if (!this->CheckAlgorithm("UpdateData", nullptr))
393 {
394 return 0;
395 }
396
397 // Range check.
398 if (outputPort < -1 || outputPort >= this->Algorithm->GetNumberOfOutputPorts())
399 {
400 vtkErrorMacro("UpdateData given output port index " << outputPort << " on an algorithm with "
401 << this->Algorithm->GetNumberOfOutputPorts()
402 << " output ports.");
403 return 0;
404 }
405
406 // Setup the request for data.
407 if (!this->DataRequest)
408 {
409 this->DataRequest = vtkInformation::New();
410 this->DataRequest->Set(REQUEST_DATA());
411 // The request is forwarded upstream through the pipeline.
412 this->DataRequest->Set(vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream);
413 // Algorithms process this request after it is forwarded.
414 this->DataRequest->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1);
415 }
416
417 // Send the request.
418 this->DataRequest->Set(FROM_OUTPUT_PORT(), outputPort);
419 return this->ProcessRequest(
420 this->DataRequest, this->GetInputInformation(), this->GetOutputInformation());
421 }
422
423 //------------------------------------------------------------------------------
ExecuteDataObject(vtkInformation * request,vtkInformationVector ** inInfo,vtkInformationVector * outInfo)424 int vtkDemandDrivenPipeline::ExecuteDataObject(
425 vtkInformation* request, vtkInformationVector** inInfo, vtkInformationVector* outInfo)
426 {
427 // Invoke the request on the algorithm.
428 int result = this->CallAlgorithm(request, vtkExecutive::RequestDownstream, inInfo, outInfo);
429
430 // Make sure a valid data object exists for all output ports.
431 for (int i = 0; result && i < this->Algorithm->GetNumberOfOutputPorts(); ++i)
432 {
433 result = this->CheckDataObject(i, outInfo);
434 }
435
436 return result;
437 }
438
439 //------------------------------------------------------------------------------
ExecuteInformation(vtkInformation * request,vtkInformationVector ** inInfoVec,vtkInformationVector * outInfoVec)440 int vtkDemandDrivenPipeline::ExecuteInformation(
441 vtkInformation* request, vtkInformationVector** inInfoVec, vtkInformationVector* outInfoVec)
442 {
443 // Give each output data object a chance to set default values in
444 // its pipeline information. Provide the first input's information
445 // to each output.
446 if (this->GetNumberOfInputPorts() > 0)
447 {
448 inInfoVec[0]->GetInformationObject(0);
449 }
450
451 // Invoke the request on the algorithm.
452 return this->CallAlgorithm(request, vtkExecutive::RequestDownstream, inInfoVec, outInfoVec);
453 }
454
455 //------------------------------------------------------------------------------
ExecuteData(vtkInformation * request,vtkInformationVector ** inInfo,vtkInformationVector * outInfo)456 int vtkDemandDrivenPipeline::ExecuteData(
457 vtkInformation* request, vtkInformationVector** inInfo, vtkInformationVector* outInfo)
458 {
459 this->ExecuteDataStart(request, inInfo, outInfo);
460 // Invoke the request on the algorithm.
461 // vtkMTimeType mTimeBefore = this->Algorithm->GetMTime();
462 int result = this->CallAlgorithm(request, vtkExecutive::RequestDownstream, inInfo, outInfo);
463 // if (mTimeBefore != this->Algorithm->GetMTime())
464 // {
465 // vtkWarningMacro(<< this->Algorithm->GetClassName()
466 // << " modified it's MTime during RequestData(). "
467 // << "This may lead to unnecessary pipeline "
468 // << "executions");
469 // }
470 this->ExecuteDataEnd(request, inInfo, outInfo);
471
472 return result;
473 }
474
475 //------------------------------------------------------------------------------
ExecuteDataStart(vtkInformation * request,vtkInformationVector ** inInfo,vtkInformationVector * outputs)476 void vtkDemandDrivenPipeline::ExecuteDataStart(
477 vtkInformation* request, vtkInformationVector** inInfo, vtkInformationVector* outputs)
478 {
479 int i;
480
481 // Ask the algorithm to mark outputs that it will not generate.
482 request->Remove(REQUEST_DATA());
483 request->Set(REQUEST_DATA_NOT_GENERATED());
484 this->CallAlgorithm(request, vtkExecutive::RequestDownstream, inInfo, outputs);
485 request->Remove(REQUEST_DATA_NOT_GENERATED());
486 request->Set(REQUEST_DATA());
487
488 // Prepare outputs that will be generated to receive new data.
489 for (i = 0; i < outputs->GetNumberOfInformationObjects(); ++i)
490 {
491 vtkInformation* outInfo = outputs->GetInformationObject(i);
492 vtkDataObject* data = outInfo->Get(vtkDataObject::DATA_OBJECT());
493 if (data && !outInfo->Get(DATA_NOT_GENERATED()))
494 {
495 data->PrepareForNewData();
496 data->CopyInformationFromPipeline(outInfo);
497 }
498 }
499
500 // Pass the vtkDataObject's field data from the first input to all
501 // outputs.
502 if (this->GetNumberOfInputPorts() > 0)
503 {
504 vtkDataObject* input = this->GetInputData(0, 0, inInfo);
505 if (input && input->GetFieldData())
506 {
507 for (i = 0; i < outputs->GetNumberOfInformationObjects(); ++i)
508 {
509 vtkInformation* outInfo = outputs->GetInformationObject(i);
510 vtkDataObject* output = outInfo->Get(vtkDataObject::DATA_OBJECT());
511 if (output)
512 {
513 output->GetFieldData()->PassData(input->GetFieldData());
514 }
515 }
516 }
517 }
518
519 // Tell observers the algorithm is about to execute.
520 this->Algorithm->InvokeEvent(vtkCommand::StartEvent, nullptr);
521
522 // The algorithm has not yet made any progress.
523 this->Algorithm->SetAbortExecute(0);
524 this->Algorithm->UpdateProgress(0.0);
525 }
526
527 //------------------------------------------------------------------------------
ExecuteDataEnd(vtkInformation * request,vtkInformationVector ** inInfoVec,vtkInformationVector * outputs)528 void vtkDemandDrivenPipeline::ExecuteDataEnd(
529 vtkInformation* request, vtkInformationVector** inInfoVec, vtkInformationVector* outputs)
530 {
531 // The algorithm has either finished or aborted.
532 if (!this->Algorithm->GetAbortExecute())
533 {
534 this->Algorithm->UpdateProgress(1.0);
535 }
536
537 // Tell observers the algorithm is done executing.
538 this->Algorithm->InvokeEvent(vtkCommand::EndEvent, nullptr);
539
540 // Tell outputs they have been generated.
541 this->MarkOutputsGenerated(request, inInfoVec, outputs);
542
543 // Remove any not-generated mark.
544 int i, j;
545 for (i = 0; i < outputs->GetNumberOfInformationObjects(); ++i)
546 {
547 vtkInformation* outInfo = outputs->GetInformationObject(i);
548 outInfo->Remove(DATA_NOT_GENERATED());
549 }
550
551 // Release input data if requested.
552 for (i = 0; i < this->Algorithm->GetNumberOfInputPorts(); ++i)
553 {
554 for (j = 0; j < inInfoVec[i]->GetNumberOfInformationObjects(); ++j)
555 {
556 vtkInformation* inInfo = inInfoVec[i]->GetInformationObject(j);
557 vtkDataObject* dataObject = inInfo->Get(vtkDataObject::DATA_OBJECT());
558 if (dataObject && (vtkDataObject::GetGlobalReleaseDataFlag() || inInfo->Get(RELEASE_DATA())))
559 {
560 dataObject->ReleaseData();
561 }
562 }
563 }
564 }
565
566 //------------------------------------------------------------------------------
MarkOutputsGenerated(vtkInformation *,vtkInformationVector **,vtkInformationVector * outputs)567 void vtkDemandDrivenPipeline::MarkOutputsGenerated(
568 vtkInformation*, vtkInformationVector** /* inInfoVec */, vtkInformationVector* outputs)
569 {
570 // Tell all generated outputs that they have been generated.
571 for (int i = 0; i < outputs->GetNumberOfInformationObjects(); ++i)
572 {
573 vtkInformation* outInfo = outputs->GetInformationObject(i);
574 vtkDataObject* data = outInfo->Get(vtkDataObject::DATA_OBJECT());
575 if (data && !outInfo->Get(DATA_NOT_GENERATED()))
576 {
577 data->DataHasBeenGenerated();
578 }
579 }
580 }
581
582 //------------------------------------------------------------------------------
CheckDataObject(int port,vtkInformationVector * outInfoVec)583 int vtkDemandDrivenPipeline::CheckDataObject(int port, vtkInformationVector* outInfoVec)
584 {
585 // Check that the given output port has a valid data object.
586 vtkInformation* outInfo = outInfoVec->GetInformationObject(port);
587 vtkDataObject* data = outInfo->Get(vtkDataObject::DATA_OBJECT());
588 vtkInformation* portInfo = this->Algorithm->GetOutputPortInformation(port);
589 if (const char* dt = portInfo->Get(vtkDataObject::DATA_TYPE_NAME()))
590 {
591 int incorrectdata = data && (!data->IsA(dt));
592 // The output port specifies a data type. Make sure the data
593 // object exists and is of the right type.
594 if (!data || incorrectdata)
595 {
596 if (data)
597 {
598 vtkDebugMacro(<< "CHECKDATAOBJECT Replacing " << data->GetClassName());
599 }
600 // Try to create an instance of the correct type.
601 data = vtkDataObjectTypes::NewDataObject(dt);
602 this->SetOutputData(port, data, outInfo);
603 if (data)
604 {
605 vtkDebugMacro(<< "CHECKDATAOBJECT Created " << dt);
606 data->FastDelete();
607 }
608 }
609 if (!data)
610 {
611 // The algorithm has a bug and did not create the data object.
612 vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName() << "(" << this->Algorithm
613 << ") did not create output for port " << port
614 << " when asked by REQUEST_DATA_OBJECT and does not"
615 << " specify a concrete DATA_TYPE_NAME.");
616 return 0;
617 }
618 return 1;
619 }
620 else if (data)
621 {
622 // The algorithm did not specify its output data type. Just assume
623 // the data object is of the correct type.
624 return 1;
625 }
626 else
627 {
628 // The algorithm did not specify its output data type and no
629 // object exists.
630 vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName() << "(" << this->Algorithm
631 << ") did not create output for port " << port
632 << " when asked by REQUEST_DATA_OBJECT and does not"
633 << " specify any DATA_TYPE_NAME.");
634 return 0;
635 }
636 }
637
638 //------------------------------------------------------------------------------
InputCountIsValid(vtkInformationVector ** inInfoVec)639 int vtkDemandDrivenPipeline::InputCountIsValid(vtkInformationVector** inInfoVec)
640 {
641 // Check the number of connections for each port.
642 int result = 1;
643 for (int p = 0; p < this->Algorithm->GetNumberOfInputPorts(); ++p)
644 {
645 if (!this->InputCountIsValid(p, inInfoVec))
646 {
647 result = 0;
648 }
649 }
650 return result;
651 }
652
653 //------------------------------------------------------------------------------
InputCountIsValid(int port,vtkInformationVector ** inInfoVec)654 int vtkDemandDrivenPipeline::InputCountIsValid(int port, vtkInformationVector** inInfoVec)
655 {
656 // Get the number of connections for this port.
657 if (!inInfoVec[port])
658 {
659 return 0;
660 }
661 int connections = inInfoVec[port]->GetNumberOfInformationObjects();
662
663 // If the input port is optional, there may be less than one connection.
664 if (!this->InputIsOptional(port) && (connections < 1))
665 {
666 vtkErrorMacro("Input port " << port << " of algorithm " << this->Algorithm->GetClassName()
667 << "(" << this->Algorithm << ") has " << connections
668 << " connections but is not optional.");
669 return 0;
670 }
671
672 // If the input port is repeatable, there may be more than one connection.
673 if (!this->InputIsRepeatable(port) && (connections > 1))
674 {
675 vtkErrorMacro("Input port " << port << " of algorithm " << this->Algorithm->GetClassName()
676 << "(" << this->Algorithm << ") has " << connections
677 << " connections but is not repeatable.");
678 return 0;
679 }
680 return 1;
681 }
682
683 //------------------------------------------------------------------------------
InputTypeIsValid(vtkInformationVector ** inInfoVec)684 int vtkDemandDrivenPipeline::InputTypeIsValid(vtkInformationVector** inInfoVec)
685 {
686 // Check the connection types for each port.
687 int result = 1;
688 for (int p = 0; p < this->Algorithm->GetNumberOfInputPorts(); ++p)
689 {
690 if (!this->InputTypeIsValid(p, inInfoVec))
691 {
692 result = 0;
693 }
694 }
695 return result;
696 }
697
698 //------------------------------------------------------------------------------
InputTypeIsValid(int port,vtkInformationVector ** inInfoVec)699 int vtkDemandDrivenPipeline::InputTypeIsValid(int port, vtkInformationVector** inInfoVec)
700 {
701 // Check the type of each connection on this port.
702 int result = 1;
703 if (!inInfoVec[port])
704 {
705 return 0;
706 }
707 for (int i = 0; i < inInfoVec[port]->GetNumberOfInformationObjects(); ++i)
708 {
709 if (!this->InputTypeIsValid(port, i, inInfoVec))
710 {
711 result = 0;
712 }
713 }
714 return result;
715 }
716
717 //------------------------------------------------------------------------------
InputTypeIsValid(int port,int index,vtkInformationVector ** inInfoVec)718 int vtkDemandDrivenPipeline::InputTypeIsValid(int port, int index, vtkInformationVector** inInfoVec)
719 {
720 if (!inInfoVec[port])
721 {
722 return 0;
723 }
724 vtkInformation* info = this->Algorithm->GetInputPortInformation(port);
725 vtkDataObject* input = this->GetInputData(port, index, inInfoVec);
726
727 // Enforce required type, if any.
728 if (info->Has(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE()) &&
729 info->Length(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE()) > 0)
730 {
731 // The input cannot be nullptr unless the port is optional.
732 if (!input && !info->Get(vtkAlgorithm::INPUT_IS_OPTIONAL()))
733 {
734 vtkErrorMacro("Input for connection index "
735 << index << " on input port index " << port << " for algorithm "
736 << this->Algorithm->GetClassName() << "(" << this->Algorithm << ") is nullptr, but a "
737 << info->Get(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), 0) << " is required.");
738 return 0;
739 }
740
741 // The input must be one of the required types or nullptr.
742 bool foundMatch = false;
743 if (input)
744 {
745 int size = info->Length(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE());
746 for (int i = 0; i < size; ++i)
747 {
748 if (input->IsA(info->Get(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), i)))
749 {
750 foundMatch = true;
751 }
752 }
753 }
754 if (input && !foundMatch)
755 {
756 vtkErrorMacro("Input for connection index "
757 << index << " on input port index " << port << " for algorithm "
758 << this->Algorithm->GetClassName() << "(" << this->Algorithm << ") is of type "
759 << input->GetClassName() << ", but a "
760 << info->Get(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), 0) << " is required.");
761 return 0;
762 }
763 }
764 return 1;
765 }
766
767 //------------------------------------------------------------------------------
InputFieldsAreValid(vtkInformationVector ** inInfoVec)768 int vtkDemandDrivenPipeline::InputFieldsAreValid(vtkInformationVector** inInfoVec)
769 {
770 // Check the fields for each port.
771 int result = 1;
772 for (int p = 0; p < this->Algorithm->GetNumberOfInputPorts(); ++p)
773 {
774 if (!this->InputFieldsAreValid(p, inInfoVec))
775 {
776 result = 0;
777 }
778 }
779 return result;
780 }
781
782 //------------------------------------------------------------------------------
InputFieldsAreValid(int port,vtkInformationVector ** inInfoVec)783 int vtkDemandDrivenPipeline::InputFieldsAreValid(int port, vtkInformationVector** inInfoVec)
784 {
785 // Check the fields for each connection on this port.
786 if (!inInfoVec[port])
787 {
788 return 0;
789 }
790 int result = 1;
791 for (int i = 0; i < inInfoVec[port]->GetNumberOfInformationObjects(); ++i)
792 {
793 if (!this->InputFieldsAreValid(port, i, inInfoVec))
794 {
795 result = 0;
796 }
797 }
798 return result;
799 }
800
801 //------------------------------------------------------------------------------
InputFieldsAreValid(int port,int index,vtkInformationVector ** inInfoVec)802 int vtkDemandDrivenPipeline::InputFieldsAreValid(
803 int port, int index, vtkInformationVector** inInfoVec)
804 {
805 vtkInformation* info = this->Algorithm->GetInputPortInformation(port);
806 vtkInformationVector* fields = info->Get(vtkAlgorithm::INPUT_REQUIRED_FIELDS());
807
808 // If there are no required fields, there is nothing to check.
809 if (!fields)
810 {
811 return 1;
812 }
813 vtkDataObject* input = this->GetInputData(port, index, inInfoVec);
814
815 // nullptr inputs do not have to have the proper fields.
816 if (!input)
817 {
818 return 1;
819 }
820
821 // Check availability of each required field.
822 int result = 1;
823 for (int i = 0; i < fields->GetNumberOfInformationObjects(); ++i)
824 {
825 vtkInformation* field = fields->GetInformationObject(i);
826
827 // Decide which kinds of fields to check.
828 int checkPoints = 1;
829 int checkCells = 1;
830 int checkFields = 1;
831 if (field->Has(vtkDataObject::FIELD_ASSOCIATION()))
832 {
833 switch (field->Get(vtkDataObject::FIELD_ASSOCIATION()))
834 {
835 case vtkDataObject::FIELD_ASSOCIATION_POINTS:
836 checkCells = 0;
837 checkFields = 0;
838 break;
839 case vtkDataObject::FIELD_ASSOCIATION_CELLS:
840 checkPoints = 0;
841 checkFields = 0;
842 break;
843 case vtkDataObject::FIELD_ASSOCIATION_NONE:
844 checkPoints = 0;
845 checkCells = 0;
846 break;
847 }
848 }
849
850 // Point and cell data arrays only exist in vtkDataSet instances.
851 vtkDataSet* dataSet = vtkDataSet::SafeDownCast(input);
852
853 // Look for a point data, cell data, or field data array matching
854 // the requirements.
855 if (!(checkPoints && dataSet && dataSet->GetPointData() &&
856 this->DataSetAttributeExists(dataSet->GetPointData(), field)) &&
857 !(checkCells && dataSet && dataSet->GetCellData() &&
858 this->DataSetAttributeExists(dataSet->GetCellData(), field)) &&
859 !(checkFields && input && input->GetFieldData() &&
860 this->FieldArrayExists(input->GetFieldData(), field)))
861 {
862 /* TODO: Construct more descriptive error message from field
863 requirements. */
864 vtkErrorMacro("Required field not found in input.");
865 result = 0;
866 }
867 }
868
869 return result;
870 }
871
872 //------------------------------------------------------------------------------
DataSetAttributeExists(vtkDataSetAttributes * dsa,vtkInformation * field)873 int vtkDemandDrivenPipeline::DataSetAttributeExists(
874 vtkDataSetAttributes* dsa, vtkInformation* field)
875 {
876 if (field->Has(vtkDataObject::FIELD_ATTRIBUTE_TYPE()))
877 {
878 // A specific attribute must match the requirements.
879 int attrType = field->Get(vtkDataObject::FIELD_ATTRIBUTE_TYPE());
880 return this->ArrayIsValid(dsa->GetAbstractAttribute(attrType), field);
881 }
882 else
883 {
884 // Search for an array matching the requirements.
885 return this->FieldArrayExists(dsa, field);
886 }
887 }
888
889 //------------------------------------------------------------------------------
FieldArrayExists(vtkFieldData * data,vtkInformation * field)890 int vtkDemandDrivenPipeline::FieldArrayExists(vtkFieldData* data, vtkInformation* field)
891 {
892 // Search the field data instance for an array matching the requirements.
893 for (int a = 0; a < data->GetNumberOfArrays(); ++a)
894 {
895 if (this->ArrayIsValid(data->GetArray(a), field))
896 {
897 return 1;
898 }
899 }
900
901 return 0;
902 }
903
904 //------------------------------------------------------------------------------
ArrayIsValid(vtkAbstractArray * array,vtkInformation * field)905 int vtkDemandDrivenPipeline::ArrayIsValid(vtkAbstractArray* array, vtkInformation* field)
906 {
907 // Enforce existence of the array.
908 if (!array)
909 {
910 return 0;
911 }
912
913 // Enforce name of the array. This should really only be used for
914 // field data (not point or cell data).
915 if (const char* name = field->Get(vtkDataObject::FIELD_NAME()))
916 {
917 if (!array->GetName() || (strcmp(name, array->GetName()) != 0))
918 {
919 return 0;
920 }
921 }
922
923 // Enforce component type for the array.
924 if (field->Has(vtkDataObject::FIELD_ARRAY_TYPE()))
925 {
926 int arrayType = field->Get(vtkDataObject::FIELD_ARRAY_TYPE());
927 if (array->GetDataType() != arrayType)
928 {
929 return 0;
930 }
931 }
932
933 // Enforce number of components for the array.
934 if (field->Has(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()))
935 {
936 int arrayNumComponents = field->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS());
937 if (array->GetNumberOfComponents() != arrayNumComponents)
938 {
939 return 0;
940 }
941 }
942
943 // Enforce number of tuples. This should really only be used for
944 // field data (not point or cell data).
945 if (field->Has(vtkDataObject::FIELD_NUMBER_OF_TUPLES()))
946 {
947 int arrayNumTuples = field->Get(vtkDataObject::FIELD_NUMBER_OF_TUPLES());
948 if (array->GetNumberOfTuples() != arrayNumTuples)
949 {
950 return 0;
951 }
952 }
953
954 return 1;
955 }
956
957 //------------------------------------------------------------------------------
InputIsOptional(int port)958 int vtkDemandDrivenPipeline::InputIsOptional(int port)
959 {
960 if (vtkInformation* info = this->Algorithm->GetInputPortInformation(port))
961 {
962 return info->Get(vtkAlgorithm::INPUT_IS_OPTIONAL());
963 }
964 return 0;
965 }
966
967 //------------------------------------------------------------------------------
InputIsRepeatable(int port)968 int vtkDemandDrivenPipeline::InputIsRepeatable(int port)
969 {
970 if (vtkInformation* info = this->Algorithm->GetInputPortInformation(port))
971 {
972 return info->Get(vtkAlgorithm::INPUT_IS_REPEATABLE());
973 }
974 return 0;
975 }
976
977 //------------------------------------------------------------------------------
NewDataObject(const char * type)978 vtkDataObject* vtkDemandDrivenPipeline::NewDataObject(const char* type)
979 {
980 return vtkDataObjectTypes::NewDataObject(type);
981 }
982
983 //------------------------------------------------------------------------------
NeedToExecuteData(int outputPort,vtkInformationVector ** inInfoVec,vtkInformationVector * outInfoVec)984 int vtkDemandDrivenPipeline ::NeedToExecuteData(
985 int outputPort, vtkInformationVector** inInfoVec, vtkInformationVector* outInfoVec)
986 {
987 // If the filter parameters or input have been modified since the
988 // last execution then we must execute. This is a shortcut for most
989 // filters since all outputs will have the same UpdateTime. This
990 // also handles the case in which there are no outputs.
991 if (this->PipelineMTime > this->DataTime.GetMTime())
992 {
993 return 1;
994 }
995
996 if (outputPort >= 0)
997 {
998 // If the output on the port making the request is out-of-date
999 // then we must execute.
1000 vtkInformation* info = outInfoVec->GetInformationObject(outputPort);
1001 vtkDataObject* data = info->Get(vtkDataObject::DATA_OBJECT());
1002 if (!data || this->PipelineMTime > data->GetUpdateTime())
1003 {
1004 return 1;
1005 }
1006 }
1007 else
1008 {
1009 // No port is specified. Check all ports.
1010 for (int i = 0; i < this->Algorithm->GetNumberOfOutputPorts(); ++i)
1011 {
1012 if (this->NeedToExecuteData(i, inInfoVec, outInfoVec))
1013 {
1014 return 1;
1015 }
1016 }
1017 }
1018
1019 // We do not need to execute.
1020 return 0;
1021 }
1022
1023 //------------------------------------------------------------------------------
SetReleaseDataFlag(int port,int n)1024 int vtkDemandDrivenPipeline::SetReleaseDataFlag(int port, int n)
1025 {
1026 if (!this->OutputPortIndexInRange(port, "set release data flag on"))
1027 {
1028 return 0;
1029 }
1030 vtkInformation* info = this->GetOutputInformation(port);
1031 if (this->GetReleaseDataFlag(port) != n)
1032 {
1033 info->Set(RELEASE_DATA(), n);
1034 return 1;
1035 }
1036 return 0;
1037 }
1038
1039 //------------------------------------------------------------------------------
GetReleaseDataFlag(int port)1040 int vtkDemandDrivenPipeline::GetReleaseDataFlag(int port)
1041 {
1042 if (!this->OutputPortIndexInRange(port, "get release data flag from"))
1043 {
1044 return 0;
1045 }
1046 vtkInformation* info = this->GetOutputInformation(port);
1047 if (!info->Has(RELEASE_DATA()))
1048 {
1049 info->Set(RELEASE_DATA(), 0);
1050 }
1051 return info->Get(RELEASE_DATA());
1052 }
1053