vtkSampleFunction.cxx 11.5 KB
Newer Older
Will Schroeder's avatar
Will Schroeder committed
1 2
/*=========================================================================

Ken Martin's avatar
Ken Martin committed
3
  Program:   Visualization Toolkit
Ken Martin's avatar
Ken Martin committed
4
  Module:    vtkSampleFunction.cxx
Will Schroeder's avatar
Will Schroeder committed
5

6
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 8
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
Ken Martin's avatar
Ken Martin committed
9

10 11
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12
     PURPOSE.  See the above copyright notice for more information.
Will Schroeder's avatar
Will Schroeder committed
13 14

=========================================================================*/
Ken Martin's avatar
Ken Martin committed
15
#include "vtkSampleFunction.h"
16

Ken Martin's avatar
Ken Martin committed
17
#include "vtkDoubleArray.h"
18
#include "vtkFloatArray.h"
Ken Martin's avatar
Ken Martin committed
19
#include "vtkGarbageCollector.h"
20
#include "vtkImageData.h"
21
#include "vtkImplicitFunction.h"
22
#include "vtkMath.h"
Ken Martin's avatar
Ken Martin committed
23 24
#include "vtkInformation.h"
#include "vtkInformationVector.h"
25
#include "vtkObjectFactory.h"
Ken Martin's avatar
Ken Martin committed
26
#include "vtkStreamingDemandDrivenPipeline.h"
Andy Cedilnik's avatar
Andy Cedilnik committed
27
#include "vtkPointData.h"
28

Brad King's avatar
Brad King committed
29
vtkStandardNewMacro(vtkSampleFunction);
30
vtkCxxSetObjectMacro(vtkSampleFunction,ImplicitFunction,vtkImplicitFunction);
Will Schroeder's avatar
Will Schroeder committed
31

Ken Martin's avatar
Ken Martin committed
32
vtkSampleFunction::vtkSampleFunction()
Will Schroeder's avatar
Will Schroeder committed
33 34 35 36 37 38 39 40 41 42 43 44
{
  this->ModelBounds[0] = -1.0;
  this->ModelBounds[1] = 1.0;
  this->ModelBounds[2] = -1.0;
  this->ModelBounds[3] = 1.0;
  this->ModelBounds[4] = -1.0;
  this->ModelBounds[5] = 1.0;

  this->SampleDimensions[0] = 50;
  this->SampleDimensions[1] = 50;
  this->SampleDimensions[2] = 50;

Will Schroeder's avatar
Will Schroeder committed
45
  this->Capping = 0;
46
  this->CapValue = VTK_DOUBLE_MAX;
Will Schroeder's avatar
Will Schroeder committed
47 48

  this->ImplicitFunction = NULL;
Will Schroeder's avatar
Will Schroeder committed
49 50

  this->ComputeNormals = 1;
Ken Martin's avatar
Ken Martin committed
51
  this->OutputScalarType = VTK_DOUBLE;
Ken Martin's avatar
Ken Martin committed
52

53
  this->ScalarArrayName=0;
54
  this->SetScalarArrayName("scalars");
55

56
  this->NormalArrayName=0;
57
  this->SetNormalArrayName("normals");
58

59

Ken Martin's avatar
Ken Martin committed
60
  this->SetNumberOfInputPorts(0);
Will Schroeder's avatar
Will Schroeder committed
61
}
Will Schroeder's avatar
Will Schroeder committed
62

63
vtkSampleFunction::~vtkSampleFunction()
64 65
{
  this->SetImplicitFunction(NULL);
66 67
  this->SetScalarArrayName(NULL);
  this->SetNormalArrayName(NULL);
68 69
}

Will Schroeder's avatar
Will Schroeder committed
70 71
// Specify the dimensions of the data on which to sample.
void vtkSampleFunction::SetSampleDimensions(int i, int j, int k)
Will Schroeder's avatar
Will Schroeder committed
72
{
Will Schroeder's avatar
Will Schroeder committed
73
  int dim[3];
Will Schroeder's avatar
Will Schroeder committed
74

Will Schroeder's avatar
Will Schroeder committed
75 76 77 78 79
  dim[0] = i;
  dim[1] = j;
  dim[2] = k;

  this->SetSampleDimensions(dim);
Will Schroeder's avatar
Will Schroeder committed
80 81
}

Will Schroeder's avatar
Will Schroeder committed
82 83 84 85 86
// Specify the dimensions of the data on which to sample.
void vtkSampleFunction::SetSampleDimensions(int dim[3])
{
  vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")");

Bill Lorensen's avatar
Bill Lorensen committed
87 88 89
  if ( dim[0] != this->SampleDimensions[0] ||
       dim[1] != this->SampleDimensions[1] ||
       dim[2] != this->SampleDimensions[2] )
Will Schroeder's avatar
Will Schroeder committed
90
    {
91
    for ( int i=0; i<3; i++)
Bill Lorensen's avatar
Bill Lorensen committed
92
      {
Will Schroeder's avatar
Will Schroeder committed
93
      this->SampleDimensions[i] = (dim[i] > 0 ? dim[i] : 1);
Bill Lorensen's avatar
Bill Lorensen committed
94
      }
Will Schroeder's avatar
Will Schroeder committed
95 96 97 98
    this->Modified();
    }
}

99
// Set the bounds of the model
100
void vtkSampleFunction::SetModelBounds(const double bounds[6])
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
{
  this->SetModelBounds(bounds[0], bounds[1],
                       bounds[2], bounds[3],
                       bounds[4], bounds[5]);

}
void vtkSampleFunction::SetModelBounds(double xMin, double xMax,
                                       double yMin, double yMax,
                                       double zMin, double zMax)
{
  vtkDebugMacro(<< " setting ModelBounds to ("
                << "(" << xMin << "," << xMax << "), "
                << "(" << yMin << "," << yMax << "), "
                << "(" << zMin << "," << zMax << "), ");
  if ((xMin > xMax) ||
      (yMin > yMax) ||
      (zMin > zMax))
    {
    vtkErrorMacro("Invalid bounds: "
                  << "(" << xMin << "," << xMax << "), "
                  << "(" << yMin << "," << yMax << "), "
                  << "(" << zMin << "," << zMax << ")"
                  << " Bound mins cannot be larger that bound maxs");
    return;
    }
  if (xMin != this->ModelBounds[0] ||
      xMax != this->ModelBounds[1] ||
      yMin != this->ModelBounds[2] ||
      yMax != this->ModelBounds[3] ||
      zMin != this->ModelBounds[4] ||
      zMax != this->ModelBounds[5])
    {
    this->ModelBounds[0] = xMin;
    this->ModelBounds[1] = xMax;
    this->ModelBounds[2] = yMin;
    this->ModelBounds[3] = yMax;
    this->ModelBounds[4] = zMin;
    this->ModelBounds[5] = zMax;
    this->Modified();
    }
}

143
int vtkSampleFunction::RequestInformation (
Ken Martin's avatar
Ken Martin committed
144 145 146
  vtkInformation * vtkNotUsed(request),
  vtkInformationVector ** vtkNotUsed( inputVector ),
  vtkInformationVector *outputVector)
147
{
Ken Martin's avatar
Ken Martin committed
148 149 150
  // get the info objects
  vtkInformation* outInfo = outputVector->GetInformationObject(0);

151
  int i;
Ken Martin's avatar
Ken Martin committed
152
  double ar[3], origin[3];
153

Ken Martin's avatar
Ken Martin committed
154 155 156 157 158
  int wExt[6];
  wExt[0] = 0; wExt[2] = 0; wExt[4] = 0;
  wExt[1] = this->SampleDimensions[0]-1;
  wExt[3] = this->SampleDimensions[1]-1;
  wExt[5] = this->SampleDimensions[2]-1;
159

Ken Martin's avatar
Ken Martin committed
160
  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExt, 6);
161

162 163 164 165 166 167 168 169 170 171
  for (i=0; i < 3; i++)
    {
    origin[i] = this->ModelBounds[2*i];
    if ( this->SampleDimensions[i] <= 1 )
      {
      ar[i] = 1;
      }
    else
      {
      ar[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i])
Ken Martin's avatar
Ken Martin committed
172
        / (this->SampleDimensions[i] - 1);
173 174
      }
    }
Ken Martin's avatar
Ken Martin committed
175 176
  outInfo->Set(vtkDataObject::ORIGIN(),origin,3);
  outInfo->Set(vtkDataObject::SPACING(),ar,3);
177

178 179
  vtkDataObject::SetPointDataActiveScalarInfo(outInfo,this->OutputScalarType,
                                              1);
180

181
  return 1;
182 183 184
}


185
void vtkSampleFunction::ExecuteDataWithInformation(vtkDataObject *outp, vtkInformation *outInfo)
Will Schroeder's avatar
Will Schroeder committed
186
{
Ken Martin's avatar
Ken Martin committed
187
  vtkIdType idx, i, j, k;
188
  vtkFloatArray *newNormals=NULL;
Amy Squillacote's avatar
Amy Squillacote committed
189
  vtkIdType numPts;
Ken Martin's avatar
Ken Martin committed
190
  double p[3], s;
Ken Martin's avatar
Ken Martin committed
191
  vtkImageData *output=this->GetOutput();
192 193 194
  int* extent =
    this->GetExecutive()->GetOutputInformation(0)->Get(
      vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT());
Ken Martin's avatar
Ken Martin committed
195

196
  output->SetExtent(extent);
197
  output = this->AllocateOutputData(outp, outInfo);
198
  vtkDataArray *newScalars =output->GetPointData()->GetScalars();
Will Schroeder's avatar
Will Schroeder committed
199

Ken Martin's avatar
Ken Martin committed
200
  vtkDebugMacro(<< "Sampling implicit function");
Ken Martin's avatar
Ken Martin committed
201

202 203
  // Initialize self; create output objects
  //
Will Schroeder's avatar
Will Schroeder committed
204 205
  if ( !this->ImplicitFunction )
    {
Ken Martin's avatar
Ken Martin committed
206
    vtkErrorMacro(<<"No implicit function specified");
Will Schroeder's avatar
Will Schroeder committed
207 208 209
    return;
    }

Ken Martin's avatar
Ken Martin committed
210
  numPts = newScalars->GetNumberOfTuples();
Will Schroeder's avatar
Will Schroeder committed
211

212 213
  // Traverse all points evaluating implicit function at each point
  //
Ken Martin's avatar
Ken Martin committed
214
  double spacing[3];
Ken Martin's avatar
Ken Martin committed
215 216 217
  output->GetSpacing(spacing);

  for ( idx=0, k=extent[4]; k <= extent[5]; k++ )
Will Schroeder's avatar
Will Schroeder committed
218
    {
Ken Martin's avatar
Ken Martin committed
219 220 221 222 223 224 225 226 227 228 229
    p[2] = this->ModelBounds[4] + k*spacing[2];
    for ( j=extent[2]; j <= extent[3]; j++ )
      {
      p[1] = this->ModelBounds[2] + j*spacing[1];
      for ( i=extent[0]; i <= extent[1]; i++ )
        {
        p[0] = this->ModelBounds[0] + i*spacing[0];
        s = this->ImplicitFunction->FunctionValue(p);
        newScalars->SetTuple1(idx++,s);
        }
      }
Will Schroeder's avatar
Will Schroeder committed
230
    }
Ken Martin's avatar
Ken Martin committed
231

232 233
  // If normal computation turned on, compute them
  //
Will Schroeder's avatar
Will Schroeder committed
234 235
  if ( this->ComputeNormals )
    {
Ken Martin's avatar
Ken Martin committed
236
    double n[3];
237
    newNormals = vtkFloatArray::New();
238 239
    newNormals->SetNumberOfComponents(3);
    newNormals->SetNumberOfTuples(numPts);
Ken Martin's avatar
Ken Martin committed
240
    for ( idx=0, k=extent[4]; k <= extent[5]; k++ )
Will Schroeder's avatar
Will Schroeder committed
241
      {
Ken Martin's avatar
Ken Martin committed
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
      p[2] = this->ModelBounds[4] + k*spacing[2];
      for ( j=extent[2]; j <= extent[3]; j++ )
        {
        p[1] = this->ModelBounds[2] + j*spacing[1];
        for ( i=extent[0]; i <= extent[1]; i++ )
          {
          p[0] = this->ModelBounds[0] + i*spacing[0];
          this->ImplicitFunction->FunctionGradient(p, n);
          n[0] *= -1;
          n[1] *= -1;
          n[2] *= -1;
          vtkMath::Normalize(n);
          newNormals->SetTuple(idx++,n);
          }
        }
Will Schroeder's avatar
Will Schroeder committed
257 258
      }
    }
259

260
  newScalars->SetName(this->ScalarArrayName);
261 262


263 264 265
  // If capping is turned on, set the distances of the outside of the volume
  // to the CapValue.
  //
Will Schroeder's avatar
Will Schroeder committed
266 267
  if ( this->Capping )
    {
Ken Martin's avatar
Ken Martin committed
268
    this->Cap(newScalars);
Will Schroeder's avatar
Will Schroeder committed
269
    }
Ken Martin's avatar
Ken Martin committed
270

271
  // Update self
272
  //
Will Schroeder's avatar
Will Schroeder committed
273 274
  if (newNormals)
    {
275 276 277
    // For an unknown reason yet, if the following line is not commented out,
    // it will make ImplicitSum, TestBoxFunction and TestDiscreteMarchingCubes
    // to fail.
278
    newNormals->SetName(this->NormalArrayName);
279

Ken Martin's avatar
Ken Martin committed
280
    output->GetPointData()->SetNormals(newNormals);
Will Schroeder's avatar
Will Schroeder committed
281 282
    newNormals->Delete();
    }
Will Schroeder's avatar
Will Schroeder committed
283 284 285
}


Ken Martin's avatar
Ken Martin committed
286
unsigned long vtkSampleFunction::GetMTime()
Will Schroeder's avatar
Will Schroeder committed
287
{
Ken Martin's avatar
Ken Martin committed
288
  unsigned long mTime=this->Superclass::GetMTime();
Will Schroeder's avatar
Will Schroeder committed
289 290 291 292 293 294 295 296 297 298 299
  unsigned long impFuncMTime;

  if ( this->ImplicitFunction != NULL )
    {
    impFuncMTime = this->ImplicitFunction->GetMTime();
    mTime = ( impFuncMTime > mTime ? impFuncMTime : mTime );
    }

  return mTime;
}

300
void vtkSampleFunction::Cap(vtkDataArray *s)
Will Schroeder's avatar
Will Schroeder committed
301
{
302
  int i,j,k;
Amy Squillacote's avatar
Amy Squillacote committed
303
  vtkIdType idx;
Will Schroeder's avatar
Will Schroeder committed
304
  int d01=this->SampleDimensions[0]*this->SampleDimensions[1];
305 306 307
  const int* extent =
    this->GetExecutive()->GetOutputInformation(0)->Get(
      vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT());
Will Schroeder's avatar
Will Schroeder committed
308

Ken Martin's avatar
Ken Martin committed
309
  // i-j planes
310
  //k = extent[4];
Ken Martin's avatar
Ken Martin committed
311
  for (j=extent[2]; j<=extent[3]; j++)
Bill Lorensen's avatar
Bill Lorensen committed
312
    {
Ken Martin's avatar
Ken Martin committed
313
    for (i=extent[0]; i<=extent[1]; i++)
Bill Lorensen's avatar
Bill Lorensen committed
314
      {
315
      s->SetComponent(i+j*this->SampleDimensions[0], 0, this->CapValue);
Bill Lorensen's avatar
Bill Lorensen committed
316 317
      }
    }
Will Schroeder's avatar
Will Schroeder committed
318

Ken Martin's avatar
Ken Martin committed
319
  k = extent[5];
Will Schroeder's avatar
Will Schroeder committed
320
  idx = k*d01;
Ken Martin's avatar
Ken Martin committed
321
  for (j=extent[2]; j<=extent[3]; j++)
Bill Lorensen's avatar
Bill Lorensen committed
322
    {
Ken Martin's avatar
Ken Martin committed
323
    for (i=extent[0]; i<=extent[1]; i++)
Bill Lorensen's avatar
Bill Lorensen committed
324
      {
325
      s->SetComponent(idx+i+j*this->SampleDimensions[0], 0, this->CapValue);
Bill Lorensen's avatar
Bill Lorensen committed
326 327
      }
    }
Will Schroeder's avatar
Will Schroeder committed
328

Ken Martin's avatar
Ken Martin committed
329
  // j-k planes
330
  //i = extent[0];
Ken Martin's avatar
Ken Martin committed
331
  for (k=extent[4]; k<=extent[5]; k++)
Bill Lorensen's avatar
Bill Lorensen committed
332
    {
Ken Martin's avatar
Ken Martin committed
333
    for (j=extent[2]; j<=extent[3]; j++)
Bill Lorensen's avatar
Bill Lorensen committed
334
      {
335
      s->SetComponent(j*this->SampleDimensions[0]+k*d01, 0, this->CapValue);
Bill Lorensen's avatar
Bill Lorensen committed
336 337
      }
    }
Will Schroeder's avatar
Will Schroeder committed
338

Ken Martin's avatar
Ken Martin committed
339 340
  i = extent[1];
  for (k=extent[4]; k<=extent[5]; k++)
Bill Lorensen's avatar
Bill Lorensen committed
341
    {
Ken Martin's avatar
Ken Martin committed
342
    for (j=extent[2]; j<=extent[3]; j++)
Bill Lorensen's avatar
Bill Lorensen committed
343
      {
344
      s->SetComponent(i+j*this->SampleDimensions[0]+k*d01, 0, this->CapValue);
Bill Lorensen's avatar
Bill Lorensen committed
345 346
      }
    }
Will Schroeder's avatar
Will Schroeder committed
347

Ken Martin's avatar
Ken Martin committed
348
  // i-k planes
349
  //j = extent[2];
Ken Martin's avatar
Ken Martin committed
350
  for (k=extent[4]; k<=extent[5]; k++)
Bill Lorensen's avatar
Bill Lorensen committed
351
    {
Ken Martin's avatar
Ken Martin committed
352
    for (i=extent[0]; i<=extent[1]; i++)
Bill Lorensen's avatar
Bill Lorensen committed
353
      {
354
      s->SetComponent(i+k*d01, 0, this->CapValue);
Bill Lorensen's avatar
Bill Lorensen committed
355 356
      }
    }
Will Schroeder's avatar
Will Schroeder committed
357

Ken Martin's avatar
Ken Martin committed
358
  j = extent[3];
Will Schroeder's avatar
Will Schroeder committed
359
  idx = j*this->SampleDimensions[0];
Ken Martin's avatar
Ken Martin committed
360
  for (k=extent[4]; k<=extent[5]; k++)
Bill Lorensen's avatar
Bill Lorensen committed
361
    {
Ken Martin's avatar
Ken Martin committed
362
    for (i=extent[0]; i<=extent[1]; i++)
Bill Lorensen's avatar
Bill Lorensen committed
363
      {
364
      s->SetComponent(idx+i+k*d01, 0, this->CapValue);
Bill Lorensen's avatar
Bill Lorensen committed
365 366
      }
    }
Will Schroeder's avatar
Will Schroeder committed
367 368
}

Sean McBride's avatar
Sean McBride committed
369
#ifndef VTK_LEGACY_REMOVE
370 371
void vtkSampleFunction::SetScalars(vtkDataArray *da)
{
Sean McBride's avatar
Sean McBride committed
372
  VTK_LEGACY_BODY(vtkSampleFunction::SetScalars, "VTK 6.0");
373 374 375 376
  if (da)
    {
    this->SetOutputScalarType(da->GetDataType());
    }
377
}
Sean McBride's avatar
Sean McBride committed
378
#endif
Will Schroeder's avatar
Will Schroeder committed
379

380
void vtkSampleFunction::PrintSelf(ostream& os, vtkIndent indent)
Will Schroeder's avatar
Will Schroeder committed
381
{
Brad King's avatar
Brad King committed
382
  this->Superclass::PrintSelf(os,indent);
383

Will Schroeder's avatar
Will Schroeder committed
384 385 386 387
  os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", "
               << this->SampleDimensions[1] << ", "
               << this->SampleDimensions[2] << ")\n";
  os << indent << "ModelBounds: \n";
388
  os << indent << "  Xmin,Xmax: (" << this->ModelBounds[0]
Will Schroeder's avatar
Will Schroeder committed
389
     << ", " << this->ModelBounds[1] << ")\n";
390
  os << indent << "  Ymin,Ymax: (" << this->ModelBounds[2]
Will Schroeder's avatar
Will Schroeder committed
391
     << ", " << this->ModelBounds[3] << ")\n";
392
  os << indent << "  Zmin,Zmax: (" << this->ModelBounds[4]
Will Schroeder's avatar
Will Schroeder committed
393
     << ", " << this->ModelBounds[5] << ")\n";
394

Ken Martin's avatar
Ken Martin committed
395
  os << indent << "OutputScalarType: " << this->OutputScalarType << "\n";
396

Will Schroeder's avatar
Will Schroeder committed
397
  if ( this->ImplicitFunction )
Bill Lorensen's avatar
Bill Lorensen committed
398
    {
Will Schroeder's avatar
Will Schroeder committed
399
    os << indent << "Implicit Function: " << this->ImplicitFunction << "\n";
Bill Lorensen's avatar
Bill Lorensen committed
400
    }
Will Schroeder's avatar
Will Schroeder committed
401
  else
Bill Lorensen's avatar
Bill Lorensen committed
402
    {
Will Schroeder's avatar
Will Schroeder committed
403
    os << indent << "No Implicit function defined\n";
Bill Lorensen's avatar
Bill Lorensen committed
404
    }
Will Schroeder's avatar
Will Schroeder committed
405

406
  os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
Will Schroeder's avatar
Will Schroeder committed
407 408 409
  os << indent << "Cap Value: " << this->CapValue << "\n";

  os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n");
410

411 412 413 414 415 416 417 418 419
  os << indent << "ScalarArrayName: ";
  if(this->ScalarArrayName!=0)
    {
    os  << this->ScalarArrayName << endl;
    }
  else
    {
    os  << "(none)" << endl;
    }
420

421 422 423 424 425 426 427 428 429
  os << indent << "NormalArrayName: ";
  if(this->NormalArrayName!=0)
    {
    os  << this->NormalArrayName << endl;
    }
  else
    {
    os  << "(none)" << endl;
    }
Will Schroeder's avatar
Will Schroeder committed
430 431
}

Ken Martin's avatar
Ken Martin committed
432 433 434 435
//----------------------------------------------------------------------------
void vtkSampleFunction::ReportReferences(vtkGarbageCollector* collector)
{
  this->Superclass::ReportReferences(collector);
436 437
  vtkGarbageCollectorReport(collector, this->ImplicitFunction,
                            "ImplicitFunction");
Ken Martin's avatar
Ken Martin committed
438
}