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