vtkImageAlgorithm.cxx 14.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageAlgorithm.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkImageAlgorithm.h"

Utkarsh Ayachit's avatar
ENH:    
Utkarsh Ayachit committed
17
#include "vtkDataArray.h"
18
#include "vtkObjectFactory.h"
19
#include "vtkCellData.h"
20
#include "vtkPointData.h"
21
22
23
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
24
#include "vtkErrorCode.h"
25
26
27
28
29
30
#include "vtkStreamingDemandDrivenPipeline.h"


//----------------------------------------------------------------------------
vtkImageAlgorithm::vtkImageAlgorithm()
{
Ken Martin's avatar
Ken Martin committed
31
32
  this->SetNumberOfInputPorts(1);
  this->SetNumberOfOutputPorts(1);
33
34
35
36

  // by default process active point scalars
  this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS,
                               vtkDataSetAttributes::SCALARS);
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
}

//----------------------------------------------------------------------------
vtkImageAlgorithm::~vtkImageAlgorithm()
{
}

//----------------------------------------------------------------------------
void vtkImageAlgorithm::PrintSelf(ostream& os, vtkIndent indent)
{  
  this->Superclass::PrintSelf(os,indent);
}

//----------------------------------------------------------------------------
// This is the superclasses style of Execute method.  Convert it into
// an imaging style Execute method.
53
int vtkImageAlgorithm::RequestData(
54
55
56
  vtkInformation* request,
  vtkInformationVector** vtkNotUsed( inputVector ),
  vtkInformationVector* outputVector)
57
{
Ken Martin's avatar
Ken Martin committed
58
59
  // the default implimentation is to do what the old pipeline did find what
  // output is requesting the data, and pass that into ExecuteData
60

Ken Martin's avatar
Ken Martin committed
61
62
63
  // which output port did the request come from
  int outputPort = 
    request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT());
Ken Martin's avatar
Ken Martin committed
64

Ken Martin's avatar
Ken Martin committed
65
66
67
  // if output port is negative then that means this filter is calling the
  // update directly, in that case just assume port 0
  if (outputPort == -1)
68
      {
Ken Martin's avatar
Ken Martin committed
69
      outputPort = 0;
70
      }
Ken Martin's avatar
Ken Martin committed
71
72
73
74
75
  
  // get the data object
  vtkInformation *outInfo = 
    outputVector->GetInformationObject(outputPort);
  // call ExecuteData
76
  this->SetErrorCode( vtkErrorCode::NoError );
77
78
79
80
81
82
83
84
  if (outInfo)
    {
    this->ExecuteData( outInfo->Get(vtkDataObject::DATA_OBJECT()) );
    }
  else
    {
    this->ExecuteData(NULL);
    }
85
86
87
88
89
90
  // Check for any error set by downstream filter (IO in most case)
  if ( this->GetErrorCode() )
    {
    return 0;
    }

91
  return 1;
92
93
}

94
95
//----------------------------------------------------------------------------
int vtkImageAlgorithm::ProcessRequest(vtkInformation* request,
96
                                      vtkInformationVector** inputVector,
97
                                      vtkInformationVector* outputVector)
98
99
100
101
{
  // generate the data
  if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
    {
102
    return this->RequestData(request, inputVector, outputVector);
103
104
105
106
107
    }

  // execute information
  if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
    {
108
    return this->RequestInformation(request, inputVector, outputVector);
109
110
    }

111
112
113
  // propagate update extent
  if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT()))
    {
114
    return this->RequestUpdateExtent(request, inputVector, outputVector);
115
116
117
    }

  return this->Superclass::ProcessRequest(request, inputVector, outputVector);
118
119
}

Ken Martin's avatar
Ken Martin committed
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//----------------------------------------------------------------------------
// Assume that any source that implements ExecuteData 
// can handle an empty extent.
void vtkImageAlgorithm::ExecuteData(vtkDataObject *)
{
  this->Execute();
}

//----------------------------------------------------------------------------
void vtkImageAlgorithm::Execute()
{
  vtkErrorMacro(<< "Definition of Execute() method should be in subclass and you should really use the ExecuteData(vtkInformation *request,...) signature instead");
}

134
//----------------------------------------------------------------------------
135
136
137
138
139
140
void vtkImageAlgorithm::CopyInputArrayAttributesToOutput
(vtkInformation* vtkNotUsed( request ),
 vtkInformationVector** inputVector,
 vtkInformationVector* outputVector)
{
  // for image data to image data
141
  if (this->GetNumberOfInputPorts() && this->GetNumberOfOutputPorts())
142
143
144
145
146
    {
    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
    // if the input is image data
    if (vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())))
      {
147
148
149
      vtkInformation *info = 
        this->GetInputArrayFieldInformation(0, inputVector);
      if (info)
150
        {
151
152
153
        int scalarType = info->Get( vtkDataObject::FIELD_ARRAY_TYPE());
        int numComp = info->Get( vtkDataObject::FIELD_NUMBER_OF_COMPONENTS());
        for(int i=0; i < this->GetNumberOfOutputPorts(); ++i)
154
          {
155
156
157
158
159
160
161
162
163
          vtkInformation* outInfo = outputVector->GetInformationObject(i);
          // if the output is image data
          if (vtkImageData::SafeDownCast
              (outInfo->Get(vtkDataObject::DATA_OBJECT())))
            {
            // copy scalar type and scalar number of components
            vtkDataObject::SetPointDataActiveScalarInfo(outInfo, 
                                                        scalarType, numComp);
            }
164
165
166
167
168
169
          }
        }
      }
    }
}  

170
//----------------------------------------------------------------------------
171
int vtkImageAlgorithm::RequestInformation(
172
173
174
  vtkInformation* request,
  vtkInformationVector** inputVector,
  vtkInformationVector* outputVector)
175
{
176
177
  // do nothing except copy scalar type info
  this->CopyInputArrayAttributesToOutput(request,inputVector,outputVector);
178
  return 1;
179
180
}

181
//----------------------------------------------------------------------------
182
int vtkImageAlgorithm::RequestUpdateExtent(
183
184
185
  vtkInformation* vtkNotUsed(request),
  vtkInformationVector** vtkNotUsed(inputVector),
  vtkInformationVector* vtkNotUsed(outputVector))
186
187
{
  // do nothing let subclasses handle it
188
  return 1;
189
190
191
192
193
194
195
196
197
198
199
}

//----------------------------------------------------------------------------
void vtkImageAlgorithm::AllocateOutputData(vtkImageData *output, 
                                           int *uExtent)
{ 
  // set the extent to be the update extent
  output->SetExtent(uExtent);
  output->AllocateScalars();
}

Ken Martin's avatar
Ken Martin committed
200
201
202
203
204
205
206
207
208
209
//----------------------------------------------------------------------------
vtkImageData *vtkImageAlgorithm::AllocateOutputData(vtkDataObject *output)
{ 
  // set the extent to be the update extent
  vtkImageData *out = vtkImageData::SafeDownCast(output);
  if (out)
    {
    // this needs to be fixed -Ken
    vtkStreamingDemandDrivenPipeline *sddp = 
      vtkStreamingDemandDrivenPipeline::SafeDownCast(this->GetExecutive());
210
211
    int numInfoObj = sddp->GetNumberOfOutputPorts();
    if (sddp && numInfoObj == 1)
Ken Martin's avatar
Ken Martin committed
212
213
214
215
216
      {
      int extent[6];
      sddp->GetOutputInformation(0)->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),extent);
      out->SetExtent(extent);
      }
217
218
219
220
221
    else
      {
      vtkWarningMacro( "There are multiple output ports. You cannot use AllocateOutputData" );
      return NULL;
      }
Ken Martin's avatar
Ken Martin committed
222
223
224
225
    out->AllocateScalars();
    }
  return out;
}
226

227
//----------------------------------------------------------------------------
228
229
// by default copy the attr from the first input to the first output
void vtkImageAlgorithm::CopyAttributeData(vtkImageData *input,
230
231
                                          vtkImageData *output,
                                          vtkInformationVector **inputVector)
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
{
  if (!input || !output)
    {
    return;
    }
  
  int inExt[6];
  int outExt[6];
  vtkDataArray *inArray;
  vtkDataArray *outArray;

  input->GetExtent(inExt);
  output->GetExtent(outExt);

  // Do not copy the array we will be generating.
247
  inArray = this->GetInputArrayToProcess(0,inputVector);
248
249
250
251
252
253
254
255
256
257
258
259

  // Conditionally copy point and cell data.  Only copy if corresponding
  // indexes refer to identical points.
  double *oIn = input->GetOrigin();
  double *sIn = input->GetSpacing();
  double *oOut = output->GetOrigin();
  double *sOut = output->GetSpacing();
  if (oIn[0] == oOut[0] && oIn[1] == oOut[1] && oIn[2] == oOut[2] &&
      sIn[0] == sOut[0] && sIn[1] == sOut[1] && sIn[2] == sOut[2])   
    {
    output->GetPointData()->CopyAllOn();
    output->GetCellData()->CopyAllOn();
260
    if (inArray && inArray->GetName())
261
262
263
264
265
266
267
      {
      output->GetPointData()->CopyFieldOff(inArray->GetName());
      }
    else if (inArray == input->GetPointData()->GetScalars())
      {
      output->GetPointData()->CopyScalarsOff();
      }
268
269
270
271
272
273
274

    // If the extents are the same, then pass the attribute data for
    // efficiency.
    if (inExt[0] == outExt[0] && inExt[1] == outExt[1] &&
        inExt[2] == outExt[2] && inExt[3] == outExt[3] &&
        inExt[4] == outExt[4] && inExt[5] == outExt[5])
      {// Pass
275
276
277
278
279
280
      // set the name of the output to match the input name
      outArray = output->GetPointData()->GetScalars();
      if (inArray)
        {
        outArray->SetName(inArray->GetName());
        }
281
282
283
284
      // Cache the scalars otherwise it may get overwritten
      // during CopyAttributes()
      outArray->Register(this);
      output->GetPointData()->SetScalars(0);
Will Schroeder's avatar
Will Schroeder committed
285
      output->CopyAttributes(input);
286
287
288
289
290
      // Restore the scalars
      int idx = output->GetPointData()->AddArray(outArray);
      output->GetPointData()->SetActiveAttribute(idx, 
          vtkDataSetAttributes::SCALARS);
      outArray->UnRegister(this);
291
292
293
294
295
296
297
298
299
      }
    else
      {// Copy
       // Since this can be expensive to copy all of these values,
       // lets make sure there are arrays to copy (other than the scalars)
      if (input->GetPointData()->GetNumberOfArrays() > 1)
        {
        // Copy the point data.
        // CopyAllocate frees all arrays.
300
301
302
303
304
        // Cache the scalars otherwise it may get overwritten
        // during CopyAllocate()
        vtkDataArray *tmp = output->GetPointData()->GetScalars();
        // set the name of the output to match the input name
        if (inArray)
305
          {
306
          tmp->SetName(inArray->GetName());
307
          }
308
309
        tmp->Register(this);
        output->GetPointData()->SetScalars(0);
310
311
        output->GetPointData()->CopyAllocate(input->GetPointData(), 
                                             output->GetNumberOfPoints());
312
313
        // Restore the scalars
        int idx = output->GetPointData()->AddArray(tmp);
314
315
        output->GetPointData()->SetActiveAttribute(idx, 
          vtkDataSetAttributes::SCALARS);
316
        tmp->UnRegister(this);
317
318
319
320
321
322
323
324
325
326
        // Now Copy The point data, but only if output is a subextent of the
        // input.
        if (outExt[0] >= inExt[0] && outExt[1] <= inExt[1] &&
            outExt[2] >= inExt[2] && outExt[3] <= inExt[3] &&
            outExt[4] >= inExt[4] && outExt[5] <= inExt[5])
          {
          output->GetPointData()->CopyStructuredData(input->GetPointData(),
                                                     inExt, outExt);
          }
        }
327
328
329
330
331
332
333
334
      else
        {
        if (inArray)
          {
          vtkDataArray* tmp = output->GetPointData()->GetScalars();
          tmp->SetName(inArray->GetName());
          }
        }
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

      if (input->GetCellData()->GetNumberOfArrays() > 0)
        {
        output->GetCellData()->CopyAllocate(input->GetCellData(), 
                                            output->GetNumberOfCells());  
        // Cell extent is one less than point extent.
        // Conditional to handle a colapsed axis (lower dimensional cells).
        if (inExt[0] < inExt[1]) {--inExt[1];}
        if (inExt[2] < inExt[3]) {--inExt[3];}
        if (inExt[4] < inExt[5]) {--inExt[5];}
        // Cell extent is one less than point extent.
        if (outExt[0] < outExt[1]) {--outExt[1];}
        if (outExt[2] < outExt[3]) {--outExt[3];}
        if (outExt[4] < outExt[5]) {--outExt[5];}
        // Now Copy The cell data, but only if output is a subextent of the input.  
        if (outExt[0] >= inExt[0] && outExt[1] <= inExt[1] &&
            outExt[2] >= inExt[2] && outExt[3] <= inExt[3] &&
            outExt[4] >= inExt[4] && outExt[5] <= inExt[5])
          {
          output->GetCellData()->CopyStructuredData(input->GetCellData(),
                                                    inExt, outExt);
          }
        }
      }
    }
}


//----------------------------------------------------------------------------
vtkImageData* vtkImageAlgorithm::GetOutput()
{
  return this->GetOutput(0);
}

//----------------------------------------------------------------------------
vtkImageData* vtkImageAlgorithm::GetOutput(int port)
{
  return vtkImageData::SafeDownCast(this->GetOutputDataObject(port));
}

375
376
377
378
379
//----------------------------------------------------------------------------
void vtkImageAlgorithm::SetOutput(vtkDataObject* d)
{
  this->GetExecutive()->SetOutputData(0, d);
}
Ken Martin's avatar
Ken Martin committed
380

381
//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
382
383
384
385
386
387
388
389
390
int vtkImageAlgorithm::FillOutputPortInformation(
  int vtkNotUsed(port), vtkInformation* info)
{
  // now add our info
  info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData");
  
  return 1;
}

391
//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
392
393
394
395
396
397
398
int vtkImageAlgorithm::FillInputPortInformation(
  int vtkNotUsed(port), vtkInformation* info)
{
  info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData");
  return 1;
}

399
//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
400
void vtkImageAlgorithm::SetInput(vtkDataObject* input)
401
402
403
404
405
{
  this->SetInput(0, input);
}

//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
406
void vtkImageAlgorithm::SetInput(int index, vtkDataObject* input)
407
408
409
{
  if(input)
    {
410
    this->SetInputConnection(index, input->GetProducerPort());
411
412
413
414
415
416
417
418
    }
  else
    {
    // Setting a NULL input removes the connection.
    this->SetInputConnection(index, 0);
    }
}

419
420
421
422
423
//----------------------------------------------------------------------------
vtkDataObject* vtkImageAlgorithm::GetInput(int port)
{
  return this->GetExecutive()->GetInputData(port, 0);
}
424

425
426
427
428
429
430
//----------------------------------------------------------------------------
vtkImageData* vtkImageAlgorithm::GetImageDataInput(int port)
{
  return vtkImageData::SafeDownCast(this->GetInput(port));
}

431
//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
432
void vtkImageAlgorithm::AddInput(vtkDataObject* input)
433
434
435
436
437
{
  this->AddInput(0, input);
}

//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
438
void vtkImageAlgorithm::AddInput(int index, vtkDataObject* input)
439
440
441
{
  if(input)
    {
442
    this->AddInputConnection(index, input->GetProducerPort());
443
444
    }
}