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