Cloned library of VTK-5.0.0 with extra build files for internal package management.
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.
 
 
 
 
 
 

460 lines
12 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkImageMandelbrotSource.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 "vtkImageMandelbrotSource.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkPointData.h"
vtkCxxRevisionMacro(vtkImageMandelbrotSource, "$Revision: 1.43 $");
vtkStandardNewMacro(vtkImageMandelbrotSource);
//----------------------------------------------------------------------------
vtkImageMandelbrotSource::vtkImageMandelbrotSource()
{
this->MaximumNumberOfIterations = 100;
this->WholeExtent[0] = 0;
this->WholeExtent[1] = 250;
this->WholeExtent[2] = 0;
this->WholeExtent[3] = 250;
this->WholeExtent[4] = 0;
this->WholeExtent[5] = 0;
this->SampleCX[0] = 0.01;
this->SampleCX[1] = 0.01;
this->SampleCX[2] = 0.01;
this->SampleCX[3] = 0.01;
this->SizeCX[0] = 2.5;
this->SizeCX[1] = 2.5;
this->SizeCX[2] = 2.0;
this->SizeCX[3] = 1.5;
this->ConstantSize = 1;
this->OriginCX[0] = -1.75;
this->OriginCX[1] = -1.25;
this->OriginCX[2] = 0.0;
this->OriginCX[3] = 0.0;
this->ProjectionAxes[0] = 0;
this->ProjectionAxes[1] = 1;
this->ProjectionAxes[2] = 2;
this->SetNumberOfInputPorts(0);
}
//----------------------------------------------------------------------------
vtkImageMandelbrotSource::~vtkImageMandelbrotSource()
{
}
//----------------------------------------------------------------------------
void vtkImageMandelbrotSource::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "OriginC: (" << this->OriginCX[0] << ", "
<< this->OriginCX[1] << ")\n";
os << indent << "OriginX: (" << this->OriginCX[2] << ", "
<< this->OriginCX[3] << ")\n";
os << indent << "SampleC: (" << this->SampleCX[0] << ", "
<< this->SampleCX[1] << ")\n";
os << indent << "SampleX: (" << this->SampleCX[2] << ", "
<< this->SampleCX[3] << ")\n";
double *size = this->GetSizeCX();
os << indent << "SizeC: (" << size[0] << ", " << size[1] << ")\n";
os << indent << "SizeX: (" << size[2] << ", " << size[3] << ")\n";
if (this->ConstantSize)
{
os << indent << "ConstantSize\n";
}
else
{
os << indent << "ConstantSpacing\n";
}
os << indent << "WholeExtent: (" << this->WholeExtent[0] << ", "
<< this->WholeExtent[1] << ", " << this->WholeExtent[2] << ", "
<< this->WholeExtent[3] << ", " << this->WholeExtent[4] << ", "
<< this->WholeExtent[5] << ")\n";
os << "MaximumNumberOfIterations: " << this->MaximumNumberOfIterations << endl;
os << indent << "ProjectionAxes: (" << this->ProjectionAxes[0] << ", "
<< this->ProjectionAxes[1] << this->ProjectionAxes[2] << ")\n";
}
//----------------------------------------------------------------------------
void vtkImageMandelbrotSource::SetWholeExtent(int extent[6])
{
int idx, modified = 0;
double saveSize[4];
this->GetSizeCX(saveSize);
for (idx = 0; idx < 6; ++idx)
{
if (this->WholeExtent[idx] != extent[idx])
{
this->WholeExtent[idx] = extent[idx];
modified = 1;
}
}
if (modified)
{
this->Modified();
if (this->ConstantSize)
{
this->SetSizeCX(saveSize[0], saveSize[1], saveSize[2], saveSize[3]);
}
}
}
//----------------------------------------------------------------------------
void vtkImageMandelbrotSource::SetProjectionAxes(int x, int y, int z)
{
double saveSize[4];
if (this->ProjectionAxes[0] == x && this->ProjectionAxes[1] == y &&
this->ProjectionAxes[2] == z)
{
return;
}
this->Modified();
this->GetSizeCX(saveSize);
this->ProjectionAxes[0] = x;
this->ProjectionAxes[1] = y;
this->ProjectionAxes[2] = z;
if (this->ConstantSize)
{
this->SetSizeCX(saveSize[0], saveSize[1], saveSize[2], saveSize[3]);
}
}
//----------------------------------------------------------------------------
void vtkImageMandelbrotSource::SetWholeExtent(int minX, int maxX,
int minY, int maxY,
int minZ, int maxZ)
{
int extent[6];
extent[0] = minX; extent[1] = maxX;
extent[2] = minY; extent[3] = maxY;
extent[4] = minZ; extent[5] = maxZ;
this->SetWholeExtent(extent);
}
//----------------------------------------------------------------------------
void vtkImageMandelbrotSource::SetSizeCX(double cReal, double cImag,
double xReal, double xImag)
{
int axis;
int idx;
int d;
double *s = this->GetSizeCX();
if (s[0] == cReal && s[1] == cImag && s[2] == xReal && s[3] == xImag)
{
return;
}
this->Modified();
// Set this because information can be carried over for collapsed axes.
this->SizeCX[0] = cReal;
this->SizeCX[1] = cImag;
this->SizeCX[2] = xReal;
this->SizeCX[3] = xImag;
// Now compute the gold standard (for non collapsed axes.
for (idx = 0; idx < 3; ++idx)
{
d = this->WholeExtent[idx*2+1] - this->WholeExtent[idx*2];
if (d > 0)
{
axis = this->ProjectionAxes[idx];
this->SampleCX[axis] = this->SizeCX[axis] / ((double) d);
}
}
}
//----------------------------------------------------------------------------
double* vtkImageMandelbrotSource::GetSizeCX()
{
int axis;
int idx;
int d;
// Recompute the size for the spacing (gold standard).
for (idx = 0; idx < 3; ++idx)
{
d = this->WholeExtent[idx*2+1] - this->WholeExtent[idx*2];
if (d > 0)
{
axis = this->ProjectionAxes[idx];
this->SizeCX[axis] = this->SampleCX[axis] * ((double) d);
}
}
return this->SizeCX;
}
//----------------------------------------------------------------------------
void vtkImageMandelbrotSource::GetSizeCX(double s[4])
{
double *p = this->GetSizeCX();
s[0] = p[0];
s[1] = p[1];
s[2] = p[2];
s[3] = p[3];
}
//----------------------------------------------------------------------------
int vtkImageMandelbrotSource::RequestInformation (
vtkInformation * vtkNotUsed(request),
vtkInformationVector** vtkNotUsed( inputVector ),
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation* outInfo = outputVector->GetInformationObject(0);
int idx, axis;
double origin[3];
double spacing[3];
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
this->WholeExtent,6);
for (idx = 0; idx < 3; ++idx)
{
axis = this->ProjectionAxes[idx];
if (axis >= 0 && axis < 4)
{
origin[idx] = this->OriginCX[axis];
spacing[idx] = this->SampleCX[axis];
}
else
{
vtkErrorMacro("Bad projection axis.");
origin[idx] = 0.0;
spacing[idx] = 1.0;
}
}
outInfo->Set(vtkDataObject::SPACING(),spacing,3);
outInfo->Set(vtkDataObject::ORIGIN(),origin,3);
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1);
return 1;
}
//----------------------------------------------------------------------------
// We may want separate zooms for mandelbrot and julia.
void vtkImageMandelbrotSource::Zoom(double factor)
{
if (factor == 1.0)
{
return;
}
this->Modified();
this->SampleCX[0] *= factor;
this->SampleCX[1] *= factor;
this->SampleCX[2] *= factor;
this->SampleCX[3] *= factor;
}
//----------------------------------------------------------------------------
void vtkImageMandelbrotSource::Pan(double x, double y, double z)
{
int idx, axis;
double pan[3];
if (x == 0.0 && y == 0.0 && z == 0.0)
{
return;
}
this->Modified();
pan[0]=x; pan[1]=y; pan[2]=z;
for (idx = 0; idx < 3; ++idx)
{
axis = this->ProjectionAxes[idx];
if (axis >= 0 && axis < 4)
{
this->OriginCX[axis] += this->SampleCX[axis] * pan[idx];
}
}
}
//----------------------------------------------------------------------------
void
vtkImageMandelbrotSource::CopyOriginAndSample(vtkImageMandelbrotSource *source)
{
int idx;
for (idx = 0; idx < 4; ++idx)
{
this->OriginCX[idx] = source->OriginCX[idx];
this->SampleCX[idx] = source->SampleCX[idx];
}
this->Modified();
}
//----------------------------------------------------------------------------
int vtkImageMandelbrotSource::RequestData(
vtkInformation* vtkNotUsed( request ),
vtkInformationVector** vtkNotUsed(inputVector),
vtkInformationVector* outputVector)
{
// get the output
vtkInformation *outInfo = outputVector->GetInformationObject(0);
vtkImageData *data = vtkImageData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
// We need to allocate our own scalars since we are overriding
// the superclasses "Execute()" method.
int *ext = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT());
data->SetExtent(ext);
data->AllocateScalars();
int a0, a1, a2;
float *ptr;
int min0, max0;
int idx0, idx1, idx2;
vtkIdType inc0, inc1, inc2;
double *origin, *sample;
double p[4];
unsigned long count = 0;
unsigned long target;
// Name the array appropriately.
data->GetPointData()->GetScalars()->SetName("Iterations");
if (data->GetNumberOfPoints() <= 0)
{
return 1;
}
// Copy origin into pixel
for (idx0 = 0; idx0 < 4; ++idx0)
{
p[idx0] = this->OriginCX[idx0];
}
ptr = (float *)(data->GetScalarPointerForExtent(ext));
vtkDebugMacro("Generating Extent: " << ext[0] << " -> " << ext[1] << ", "
<< ext[2] << " -> " << ext[3]);
// Get min and max of axis 0 because it is the innermost loop.
min0 = ext[0];
max0 = ext[1];
data->GetContinuousIncrements(ext, inc0, inc1, inc2);
target = (unsigned long)((ext[5]-ext[4]+1)*(ext[3]-ext[2]+1)/50.0);
target++;
a0 = this->ProjectionAxes[0];
a1 = this->ProjectionAxes[1];
a2 = this->ProjectionAxes[2];
origin = this->OriginCX;
sample = this->SampleCX;
if (a0<0 || a1<0 || a2<0 || a0>3 || a1>3 || a2>3)
{
vtkErrorMacro("Bad projection axis");
return 0;
}
for (idx2 = ext[4]; idx2 <= ext[5]; ++idx2)
{
p[a2] = (double)(origin[a2]) + (double)(idx2)*(sample[a2]);
for (idx1 = ext[2]; !this->AbortExecute && idx1 <= ext[3]; ++idx1)
{
if (!(count%target))
{
this->UpdateProgress(count/(50.0*target));
}
count++;
p[a1] = (double)(origin[a1]) + (double)(idx1)*(sample[a1]);
for (idx0 = min0; idx0 <= max0; ++idx0)
{
p[a0] = (double)(origin[a0]) + (double)(idx0)*(sample[a0]);
*ptr = (float)(this->EvaluateSet(p));
++ptr;
// inc0 is 0
}
ptr += inc1;
}
ptr += inc2;
}
return 1;
}
//----------------------------------------------------------------------------
double vtkImageMandelbrotSource::EvaluateSet(double p[4])
{
unsigned short count = 0;
double v0, v1;
double cReal, cImag, zReal, zImag;
double zReal2, zImag2;
cReal = p[0];
cImag = p[1];
zReal = p[2];
zImag = p[3];
zReal2 = zReal * zReal;
zImag2 = zImag * zImag;
v0 = 0.0;
v1 = (zReal2 + zImag2);
while ( v1 < 4.0 && count < this->MaximumNumberOfIterations)
{
zImag = 2.0 * zReal * zImag + cImag;
zReal = zReal2 - zImag2 + cReal;
zReal2 = zReal * zReal;
zImag2 = zImag * zImag;
++count;
v0 = v1;
v1 = (zReal2 + zImag2);
}
if (count == this->MaximumNumberOfIterations)
{
return (double)count;
}
return (double)count + (4.0 - v0)/(v1 - v0);
}