You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
355 lines
9.2 KiB
355 lines
9.2 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkSampleFunction.cxx,v $
|
|
|
|
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 "vtkSampleFunction.h"
|
|
|
|
#include "vtkDoubleArray.h"
|
|
#include "vtkFloatArray.h"
|
|
#include "vtkGarbageCollector.h"
|
|
#include "vtkImageData.h"
|
|
#include "vtkImplicitFunction.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
#include "vtkPointData.h"
|
|
|
|
vtkCxxRevisionMacro(vtkSampleFunction, "$Revision: 1.74 $");
|
|
vtkStandardNewMacro(vtkSampleFunction);
|
|
vtkCxxSetObjectMacro(vtkSampleFunction,ImplicitFunction,vtkImplicitFunction);
|
|
|
|
// Construct with ModelBounds=(-1,1,-1,1,-1,1), SampleDimensions=(50,50,50),
|
|
// Capping turned off, and normal generation on.
|
|
vtkSampleFunction::vtkSampleFunction()
|
|
{
|
|
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;
|
|
|
|
this->Capping = 0;
|
|
this->CapValue = VTK_LARGE_FLOAT;
|
|
|
|
this->ImplicitFunction = NULL;
|
|
|
|
this->ComputeNormals = 1;
|
|
this->OutputScalarType = VTK_DOUBLE;
|
|
|
|
this->SetNumberOfInputPorts(0);
|
|
}
|
|
|
|
vtkSampleFunction::~vtkSampleFunction()
|
|
{
|
|
this->SetImplicitFunction(NULL);
|
|
}
|
|
|
|
|
|
// Specify the dimensions of the data on which to sample.
|
|
void vtkSampleFunction::SetSampleDimensions(int i, int j, int k)
|
|
{
|
|
int dim[3];
|
|
|
|
dim[0] = i;
|
|
dim[1] = j;
|
|
dim[2] = k;
|
|
|
|
this->SetSampleDimensions(dim);
|
|
}
|
|
|
|
// 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] << ")");
|
|
|
|
if ( dim[0] != this->SampleDimensions[0] ||
|
|
dim[1] != this->SampleDimensions[1] ||
|
|
dim[2] != this->SampleDimensions[2] )
|
|
{
|
|
for ( int i=0; i<3; i++)
|
|
{
|
|
this->SampleDimensions[i] = (dim[i] > 0 ? dim[i] : 1);
|
|
}
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
int vtkSampleFunction::RequestInformation (
|
|
vtkInformation * vtkNotUsed(request),
|
|
vtkInformationVector ** vtkNotUsed( inputVector ),
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
// get the info objects
|
|
vtkInformation* outInfo = outputVector->GetInformationObject(0);
|
|
|
|
int i;
|
|
double ar[3], origin[3];
|
|
|
|
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;
|
|
|
|
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExt, 6);
|
|
|
|
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])
|
|
/ (this->SampleDimensions[i] - 1);
|
|
}
|
|
}
|
|
outInfo->Set(vtkDataObject::ORIGIN(),origin,3);
|
|
outInfo->Set(vtkDataObject::SPACING(),ar,3);
|
|
|
|
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, 1);
|
|
return 1;
|
|
}
|
|
|
|
|
|
void vtkSampleFunction::ExecuteData(vtkDataObject *outp)
|
|
{
|
|
vtkIdType idx, i, j, k;
|
|
vtkFloatArray *newNormals=NULL;
|
|
vtkIdType numPts;
|
|
double p[3], s;
|
|
vtkImageData *output=this->GetOutput();
|
|
|
|
output->SetExtent(output->GetUpdateExtent());
|
|
output = this->AllocateOutputData(outp);
|
|
vtkDoubleArray *newScalars =
|
|
vtkDoubleArray::SafeDownCast(output->GetPointData()->GetScalars());
|
|
|
|
vtkDebugMacro(<< "Sampling implicit function");
|
|
|
|
// Initialize self; create output objects
|
|
//
|
|
if ( !this->ImplicitFunction )
|
|
{
|
|
vtkErrorMacro(<<"No implicit function specified");
|
|
return;
|
|
}
|
|
|
|
numPts = newScalars->GetNumberOfTuples();
|
|
|
|
// Traverse all points evaluating implicit function at each point
|
|
//
|
|
int extent[6];
|
|
output->GetUpdateExtent(extent);
|
|
double spacing[3];
|
|
output->GetSpacing(spacing);
|
|
|
|
for ( idx=0, k=extent[4]; k <= extent[5]; k++ )
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If normal computation turned on, compute them
|
|
//
|
|
if ( this->ComputeNormals )
|
|
{
|
|
double n[3];
|
|
newNormals = vtkFloatArray::New();
|
|
newNormals->SetNumberOfComponents(3);
|
|
newNormals->SetNumberOfTuples(numPts);
|
|
for ( idx=0, k=extent[4]; k <= extent[5]; k++ )
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If capping is turned on, set the distances of the outside of the volume
|
|
// to the CapValue.
|
|
//
|
|
if ( this->Capping )
|
|
{
|
|
this->Cap(newScalars);
|
|
}
|
|
|
|
// Update self
|
|
//
|
|
if (newNormals)
|
|
{
|
|
output->GetPointData()->SetNormals(newNormals);
|
|
newNormals->Delete();
|
|
}
|
|
}
|
|
|
|
|
|
unsigned long vtkSampleFunction::GetMTime()
|
|
{
|
|
unsigned long mTime=this->Superclass::GetMTime();
|
|
unsigned long impFuncMTime;
|
|
|
|
if ( this->ImplicitFunction != NULL )
|
|
{
|
|
impFuncMTime = this->ImplicitFunction->GetMTime();
|
|
mTime = ( impFuncMTime > mTime ? impFuncMTime : mTime );
|
|
}
|
|
|
|
return mTime;
|
|
}
|
|
|
|
void vtkSampleFunction::Cap(vtkDataArray *s)
|
|
{
|
|
int i,j,k,extent[6];
|
|
vtkIdType idx;
|
|
int d01=this->SampleDimensions[0]*this->SampleDimensions[1];
|
|
vtkImageData *output = this->GetOutput();
|
|
output->GetUpdateExtent(extent);
|
|
|
|
// i-j planes
|
|
//k = extent[4];
|
|
for (j=extent[2]; j<=extent[3]; j++)
|
|
{
|
|
for (i=extent[0]; i<=extent[1]; i++)
|
|
{
|
|
s->SetComponent(i+j*this->SampleDimensions[0], 0, this->CapValue);
|
|
}
|
|
}
|
|
|
|
k = extent[5];
|
|
idx = k*d01;
|
|
for (j=extent[2]; j<=extent[3]; j++)
|
|
{
|
|
for (i=extent[0]; i<=extent[1]; i++)
|
|
{
|
|
s->SetComponent(idx+i+j*this->SampleDimensions[0], 0, this->CapValue);
|
|
}
|
|
}
|
|
|
|
// j-k planes
|
|
//i = extent[0];
|
|
for (k=extent[4]; k<=extent[5]; k++)
|
|
{
|
|
for (j=extent[2]; j<=extent[3]; j++)
|
|
{
|
|
s->SetComponent(j*this->SampleDimensions[0]+k*d01, 0, this->CapValue);
|
|
}
|
|
}
|
|
|
|
i = extent[1];
|
|
for (k=extent[4]; k<=extent[5]; k++)
|
|
{
|
|
for (j=extent[2]; j<=extent[3]; j++)
|
|
{
|
|
s->SetComponent(i+j*this->SampleDimensions[0]+k*d01, 0, this->CapValue);
|
|
}
|
|
}
|
|
|
|
// i-k planes
|
|
//j = extent[2];
|
|
for (k=extent[4]; k<=extent[5]; k++)
|
|
{
|
|
for (i=extent[0]; i<=extent[1]; i++)
|
|
{
|
|
s->SetComponent(i+k*d01, 0, this->CapValue);
|
|
}
|
|
}
|
|
|
|
j = extent[3];
|
|
idx = j*this->SampleDimensions[0];
|
|
for (k=extent[4]; k<=extent[5]; k++)
|
|
{
|
|
for (i=extent[0]; i<=extent[1]; i++)
|
|
{
|
|
s->SetComponent(idx+i+k*d01, 0, this->CapValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkSampleFunction::SetScalars(vtkDataArray *da)
|
|
{
|
|
if (da)
|
|
{
|
|
this->SetOutputScalarType(da->GetDataType());
|
|
}
|
|
}
|
|
|
|
void vtkSampleFunction::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", "
|
|
<< this->SampleDimensions[1] << ", "
|
|
<< this->SampleDimensions[2] << ")\n";
|
|
os << indent << "ModelBounds: \n";
|
|
os << indent << " Xmin,Xmax: (" << this->ModelBounds[0]
|
|
<< ", " << this->ModelBounds[1] << ")\n";
|
|
os << indent << " Ymin,Ymax: (" << this->ModelBounds[2]
|
|
<< ", " << this->ModelBounds[3] << ")\n";
|
|
os << indent << " Zmin,Zmax: (" << this->ModelBounds[4]
|
|
<< ", " << this->ModelBounds[5] << ")\n";
|
|
|
|
os << indent << "OutputScalarType: " << this->OutputScalarType << "\n";
|
|
|
|
if ( this->ImplicitFunction )
|
|
{
|
|
os << indent << "Implicit Function: " << this->ImplicitFunction << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "No Implicit function defined\n";
|
|
}
|
|
|
|
os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
|
|
os << indent << "Cap Value: " << this->CapValue << "\n";
|
|
|
|
os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSampleFunction::ReportReferences(vtkGarbageCollector* collector)
|
|
{
|
|
this->Superclass::ReportReferences(collector);
|
|
vtkGarbageCollectorReport(collector, this->ImplicitFunction,
|
|
"ImplicitFunction");
|
|
}
|
|
|