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