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.
1617 lines
41 KiB
1617 lines
41 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkImageCanvasSource2D.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 "vtkImageCanvasSource2D.h"
|
|
|
|
#include "vtkImageCast.h"
|
|
#include "vtkImageClip.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkImageData.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
|
|
#include <math.h>
|
|
|
|
//
|
|
// Special classes for manipulating data
|
|
//
|
|
// For the fill functionality (use connector ??)
|
|
class vtkImageCanvasSource2DPixel { //;prevent man page generation
|
|
public:
|
|
static vtkImageCanvasSource2DPixel *New()
|
|
{ return new vtkImageCanvasSource2DPixel ;}
|
|
int X;
|
|
int Y;
|
|
void *Pointer;
|
|
vtkImageCanvasSource2DPixel *Next;
|
|
};
|
|
|
|
|
|
|
|
vtkCxxRevisionMacro(vtkImageCanvasSource2D, "$Revision: 1.44.4.1 $");
|
|
vtkStandardNewMacro(vtkImageCanvasSource2D);
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Construct an instance of vtkImageCanvasSource2D with no data.
|
|
vtkImageCanvasSource2D::vtkImageCanvasSource2D()
|
|
{
|
|
this->SetNumberOfInputPorts(0);
|
|
|
|
this->ImageData = vtkImageData::New();
|
|
this->ImageData->SetScalarType(VTK_DOUBLE);
|
|
|
|
this->WholeExtent[0] = 0;
|
|
this->WholeExtent[1] = 0;
|
|
this->WholeExtent[2] = 0;
|
|
this->WholeExtent[3] = 0;
|
|
this->WholeExtent[4] = 0;
|
|
this->WholeExtent[5] = 0;
|
|
|
|
this->DrawColor[0] = this->DrawColor[1] =
|
|
this->DrawColor[2] = this->DrawColor[3] = 0.0;
|
|
|
|
this->DefaultZ = 0;
|
|
|
|
this->Ratio[0] = this->Ratio[1] = this->Ratio[2] = 1.0;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Destructor: Deleting a vtkImageCanvasSource2D automatically
|
|
// deletes the associated
|
|
// vtkImageData. However, since the data is reference counted, it may not
|
|
// actually be deleted.
|
|
vtkImageCanvasSource2D::~vtkImageCanvasSource2D()
|
|
{
|
|
this->ImageData->Delete();
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageCanvasSource2D::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
int idx;
|
|
|
|
os << indent << "ImageData: (" << this->ImageData << ")\n";
|
|
os << indent << "DefaultZ: " << this->DefaultZ << endl;
|
|
os << indent << "DrawColor: (" << this->DrawColor[0];
|
|
for (idx = 1; idx < 4; ++idx)
|
|
{
|
|
os << ", " << this->DrawColor[idx];
|
|
}
|
|
os << ")\n";
|
|
os << indent << "Ratio: ("
|
|
<< this->Ratio[0] << ", " << this->Ratio[1] << ", " << this->Ratio[2]
|
|
<< ")\n";
|
|
}
|
|
|
|
|
|
#define vtkMAX(x, y) (((x)>(y))?(x):(y))
|
|
#define vtkMIN(x, y) (((x)<(y))?(x):(y))
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw a data. Only implentented for 2D extents.
|
|
template <class T>
|
|
void vtkImageCanvasSource2DDrawImage(vtkImageData *image, vtkImageData *simage,
|
|
T *ptr, T *sptr,
|
|
int min0, int max0, int min1, int max1)
|
|
{
|
|
T *ptr0, *ptr1, *ptrV;
|
|
T *sptr0, *sptr1, *sptrV;
|
|
int idx0, idx1, idxV;
|
|
vtkIdType inc0, inc1, inc2;
|
|
vtkIdType sinc0, sinc1, sinc2;
|
|
int maxV, smaxV;
|
|
int sinc;
|
|
|
|
image->GetIncrements(inc0, inc1, inc2);
|
|
simage->GetIncrements(sinc0, sinc1, sinc2);
|
|
|
|
maxV = image->GetNumberOfScalarComponents() - 1;
|
|
smaxV = simage->GetNumberOfScalarComponents() - 1;
|
|
|
|
ptr1 = ptr;
|
|
sptr1 = sptr;
|
|
for (idx1 = min1; idx1 <= max1; ++idx1)
|
|
{
|
|
ptr0 = ptr1;
|
|
sptr0 = sptr1;
|
|
for (idx0 = min0; idx0 <= max0; ++idx0)
|
|
{
|
|
ptrV = ptr0;
|
|
sptrV = sptr0;
|
|
|
|
sinc = 0;
|
|
|
|
// Assign color to pixel.
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = *(sptrV + sinc);
|
|
ptrV++;
|
|
if ( sinc < smaxV )
|
|
{
|
|
sinc++;
|
|
}
|
|
}
|
|
//sptrV += smaxV;
|
|
|
|
ptr0 += inc0;
|
|
sptr0 += sinc0;
|
|
}
|
|
ptr1 += inc1;
|
|
sptr1 += sinc1;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageCanvasSource2D::DrawImage(int x0, int y0,
|
|
vtkImageData* image, int sx, int sy,
|
|
int width, int height)
|
|
{
|
|
if ( !image )
|
|
{
|
|
return;
|
|
}
|
|
|
|
vtkImageClip* clip = vtkImageClip::New();
|
|
clip->SetInput(image);
|
|
|
|
int *extent;
|
|
int ext[6];
|
|
// int z = this->DefaultZ;
|
|
image->GetWholeExtent(ext);
|
|
if ( sx < 0 )
|
|
{
|
|
sx = ext[0];
|
|
}
|
|
if ( sy < 0 )
|
|
{
|
|
sy = ext[2];
|
|
}
|
|
if ( width < 0 )
|
|
{
|
|
width = ext[1] - ext[0] + 1;
|
|
}
|
|
else
|
|
{
|
|
width = vtkMIN(width, ext[1] - ext[0] + 1);
|
|
}
|
|
if ( height < 0 )
|
|
{
|
|
height = ext[3] - ext[2] + 1;
|
|
}
|
|
else
|
|
{
|
|
height = vtkMIN(height, ext[3] - ext[2] + 1);
|
|
}
|
|
ext[0] = vtkMAX(sx, ext[0]);
|
|
ext[1] = vtkMAX(sx+width-1, ext[1]);
|
|
ext[2] = vtkMAX(sy, ext[2]);
|
|
ext[3] = vtkMAX(sy+height-1, ext[3]);
|
|
clip->SetOutputWholeExtent(ext);
|
|
|
|
vtkImageCast* ic = vtkImageCast::New();
|
|
ic->SetInputConnection(clip->GetOutputPort());
|
|
ic->SetOutputScalarType(this->ImageData->GetScalarType());
|
|
ic->Update();
|
|
int min0, max0, min1, max1;
|
|
min0 = x0;
|
|
min1 = y0;
|
|
|
|
max0 = x0 + width -1;
|
|
max1 = y0 + height -1;
|
|
|
|
// Pre-multiply coords if needed
|
|
if (this->Ratio[0] != 1.0)
|
|
{
|
|
min0 = int(double(min0) * this->Ratio[0]);
|
|
max0 = int(double(max0) * this->Ratio[0]);
|
|
}
|
|
if (this->Ratio[1] != 1.0)
|
|
{
|
|
min1 = int(double(min1) * this->Ratio[1]);
|
|
max1 = int(double(max1) * this->Ratio[1]);
|
|
}
|
|
// if (this->Ratio[2] != 1.0)
|
|
// {
|
|
// z = int(double(z) * this->Ratio[2]);
|
|
// }
|
|
// Clip the data to keep in in bounds
|
|
extent = this->ImageData->GetExtent();
|
|
min0 = (min0 < extent[0]) ? extent[0] : min0;
|
|
max0 = (max0 < extent[0]) ? extent[0] : max0;
|
|
min0 = (min0 > extent[1]) ? extent[1] : min0;
|
|
max0 = (max0 > extent[1]) ? extent[1] : max0;
|
|
min1 = (min1 < extent[2]) ? extent[2] : min1;
|
|
max1 = (max1 < extent[2]) ? extent[2] : max1;
|
|
min1 = (min1 > extent[3]) ? extent[3] : min1;
|
|
max1 = (max1 > extent[3]) ? extent[3] : max1;
|
|
//z = (z < extent[4]) ? extent[4] : z;
|
|
//z = (z > extent[5]) ? extent[5] : z;
|
|
void *ptr;
|
|
void *sptr;
|
|
ptr = this->ImageData->GetScalarPointer(min0, min1, 0);
|
|
sptr = ic->GetOutput()->GetScalarPointer(ext[0], ext[2], 0);
|
|
switch (this->ImageData->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(vtkImageCanvasSource2DDrawImage(this->ImageData,
|
|
ic->GetOutput(),
|
|
(VTK_TT *)(ptr),
|
|
(VTK_TT *)(sptr),
|
|
min0,max0, min1,max1));
|
|
default:
|
|
vtkErrorMacro(<< "FillBox: Cannot handle ScalarType.");
|
|
}
|
|
ic->Delete();
|
|
clip->Delete();
|
|
this->Modified();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw a data. Only implentented for 2D extents.
|
|
template <class T>
|
|
void vtkImageCanvasSource2DFillBox(vtkImageData *image,
|
|
double *drawColor, T *ptr,
|
|
int min0, int max0, int min1, int max1)
|
|
{
|
|
T *ptr0, *ptr1, *ptrV;
|
|
int idx0, idx1, idxV;
|
|
vtkIdType inc0, inc1, inc2;
|
|
int maxV;
|
|
double *pf;
|
|
|
|
image->GetIncrements(inc0, inc1, inc2);
|
|
maxV = image->GetNumberOfScalarComponents() - 1;
|
|
|
|
ptr1 = ptr;
|
|
for (idx1 = min1; idx1 <= max1; ++idx1)
|
|
{
|
|
ptr0 = ptr1;
|
|
for (idx0 = min0; idx0 <= max0; ++idx0)
|
|
{
|
|
ptrV = ptr0;
|
|
pf = drawColor;
|
|
|
|
// Assign color to pixel.
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = (T)(*pf++);
|
|
ptrV++;
|
|
}
|
|
|
|
ptr0 += inc0;
|
|
}
|
|
ptr1 += inc1;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw a data. Only implentented for 2D extents.
|
|
void vtkImageCanvasSource2D::FillBox(int min0, int max0, int min1, int max1)
|
|
{
|
|
int *extent;
|
|
void *ptr;
|
|
int z = this->DefaultZ;
|
|
|
|
// Pre-multiply coords if needed
|
|
if (this->Ratio[0] != 1.0)
|
|
{
|
|
min0 = int(double(min0) * this->Ratio[0]);
|
|
max0 = int(double(max0) * this->Ratio[0]);
|
|
}
|
|
if (this->Ratio[1] != 1.0)
|
|
{
|
|
min1 = int(double(min1) * this->Ratio[1]);
|
|
max1 = int(double(max1) * this->Ratio[1]);
|
|
}
|
|
if (this->Ratio[2] != 1.0)
|
|
{
|
|
z = int(double(z) * this->Ratio[2]);
|
|
}
|
|
|
|
// Clip the data to keep in in bounds
|
|
extent = this->ImageData->GetExtent();
|
|
min0 = (min0 < extent[0]) ? extent[0] : min0;
|
|
max0 = (max0 < extent[0]) ? extent[0] : max0;
|
|
min0 = (min0 > extent[1]) ? extent[1] : min0;
|
|
max0 = (max0 > extent[1]) ? extent[1] : max0;
|
|
min1 = (min1 < extent[2]) ? extent[2] : min1;
|
|
max1 = (max1 < extent[2]) ? extent[2] : max1;
|
|
min1 = (min1 > extent[3]) ? extent[3] : min1;
|
|
max1 = (max1 > extent[3]) ? extent[3] : max1;
|
|
z = (z < extent[4]) ? extent[4] : z;
|
|
z = (z > extent[5]) ? extent[5] : z;
|
|
|
|
ptr = this->ImageData->GetScalarPointer(min0, min1, z);
|
|
switch (this->ImageData->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(vtkImageCanvasSource2DFillBox(this->ImageData,
|
|
this->DrawColor,
|
|
(VTK_TT *)(ptr),
|
|
min0,max0, min1,max1));
|
|
default:
|
|
vtkErrorMacro(<< "FillBox: Cannot handle ScalarType.");
|
|
}
|
|
this->Modified();
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Fill a tube (thick line for initial 2D implementation.
|
|
template <class T>
|
|
void vtkImageCanvasSource2DFillTube(vtkImageData *image,
|
|
double *drawColor, T *ptr,
|
|
int a0, int a1, int b0, int b1,
|
|
double radius)
|
|
{
|
|
T *ptr0, *ptr1, *ptrV;
|
|
int idx0, idx1, idxV;
|
|
vtkIdType inc0, inc1, inc2;
|
|
int min0, max0, min1, max1, min2, max2, maxV;
|
|
double *pf;
|
|
int n0, n1;
|
|
int ak, bk, k;
|
|
double fract;
|
|
double v0, v1;
|
|
|
|
// Compute vector of tube.
|
|
n0 = a0 - b0;
|
|
n1 = a1 - b1;
|
|
// compute the projects of the two points a and b on this vector.
|
|
ak = n0 * a0 + n1 * a1;
|
|
bk = n0 * b0 + n1 * b1;
|
|
// Make sure the vector is pointing in the correct direction.
|
|
if (ak < bk)
|
|
{
|
|
ak = -ak;
|
|
bk = -bk;
|
|
n0 = -n0;
|
|
n1 = -n1;
|
|
}
|
|
|
|
image->GetExtent(min0, max0, min1, max1, min2, max2);
|
|
maxV = image->GetNumberOfScalarComponents() - 1;
|
|
// Loop trough whole extent.
|
|
image->GetIncrements(inc0, inc1, inc2);
|
|
ptr1 = ptr;
|
|
for (idx1 = min1; idx1 <= max1; ++idx1)
|
|
{
|
|
ptr0 = ptr1;
|
|
for (idx0 = min0; idx0 <= max0; ++idx0)
|
|
{
|
|
// check to see if pixel is in the tube.
|
|
// project point onto normal vector.
|
|
k = n0 * idx0 + n1 * idx1;
|
|
// Check that point is inbetween end points.
|
|
if ( k >= bk && k <= ak)
|
|
{
|
|
// Compute actual projection point.
|
|
fract = (double)(k - bk) / (double)(ak - bk);
|
|
v0 = b0 + fract * (double)(a0 - b0);
|
|
v1 = b1 + fract * (double)(a1 - b1);
|
|
// Compute distance to tube
|
|
v0 -= (double)(idx0);
|
|
v1 -= (double)(idx1);
|
|
if (radius >= sqrt(v0*v0 + v1*v1))
|
|
{
|
|
ptrV = ptr0;
|
|
pf = drawColor;
|
|
// Assign color to pixel.
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = (T)(*pf++);
|
|
ptrV++;
|
|
}
|
|
}
|
|
}
|
|
|
|
ptr0 += inc0;
|
|
}
|
|
ptr1 += inc1;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Fill a tube (thick line for initial 2D implementation).
|
|
void vtkImageCanvasSource2D::FillTube(int a0, int a1,
|
|
int b0, int b1, double radius)
|
|
{
|
|
void *ptr;
|
|
int z = this->DefaultZ;
|
|
int *extent = this->ImageData->GetExtent();
|
|
|
|
// Pre-multiply coords if needed
|
|
if (this->Ratio[0] != 1.0)
|
|
{
|
|
a0 = int(double(a0) * this->Ratio[0]);
|
|
b0 = int(double(b0) * this->Ratio[0]);
|
|
radius = int(double(radius) * this->Ratio[0]);
|
|
}
|
|
if (this->Ratio[1] != 1.0)
|
|
{
|
|
a1 = int(double(a1) * this->Ratio[1]);
|
|
b1 = int(double(b1) * this->Ratio[1]);
|
|
}
|
|
if (this->Ratio[2] != 1.0)
|
|
{
|
|
z = int(double(z) * this->Ratio[2]);
|
|
}
|
|
|
|
z = (z < extent[4]) ? extent[4] : z;
|
|
z = (z > extent[5]) ? extent[5] : z;
|
|
|
|
ptr = this->ImageData->GetScalarPointer(extent[0], extent[2], z);
|
|
switch (this->ImageData->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(
|
|
vtkImageCanvasSource2DFillTube(this->ImageData,
|
|
this->DrawColor,
|
|
(VTK_TT *)(ptr),
|
|
a0,a1, b0,b1,
|
|
radius));
|
|
default:
|
|
vtkErrorMacro(<< "FillTube: Cannot handle ScalarType.");
|
|
}
|
|
this->Modified();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Fill a triangle (rasterize)
|
|
template <class T>
|
|
void vtkImageCanvasSource2DFillTriangle(vtkImageData *image,
|
|
double *drawColor, T *ptr,
|
|
int a0, int a1, int b0, int b1,
|
|
int c0, int c1, int z)
|
|
{
|
|
int temp;
|
|
double longT, shortT; // end points of intersection of trainge and row.
|
|
double longStep, shortStep;
|
|
int left, right;
|
|
int idx0, idx1, idxV;
|
|
int min0, max0, min1, max1, min2, max2;
|
|
int maxV;
|
|
double *pf;
|
|
|
|
maxV = image->GetNumberOfScalarComponents() - 1;
|
|
|
|
// index1 of b must be between a, and c
|
|
if((b1 < a1 && a1 < c1) || (b1 > a1 && a1 > c1))
|
|
{ // swap b and a
|
|
temp = b0; b0 = a0; a0 = temp;
|
|
temp = b1; b1 = a1; a1 = temp;
|
|
}
|
|
if((b1 < c1 && c1 < a1) || (b1 > c1 && c1 > a1))
|
|
{ // swap b and c
|
|
temp = b0; b0 = c0; c0 = temp;
|
|
temp = b1; b1 = c1; c1 = temp;
|
|
}
|
|
// Make life easier and order points so that ay < by < cy
|
|
if(c1 < a1)
|
|
{ // swap c and a
|
|
temp = a0; a0 = c0; c0 = temp;
|
|
temp = a1; a1 = c1; c1 = temp;
|
|
}
|
|
|
|
image->GetExtent(min0, max0, min1, max1, min2, max2);
|
|
z = (z < min2) ? min2 : z;
|
|
z = (z > max2) ? max2 : z;
|
|
|
|
// for all rows: compute 2 points, intersection of triangle edges and row
|
|
longStep = (double)(c0 - a0) / (double)(c1 - a1 + 1);
|
|
longT = (double)(a0) + (0.5 * longStep);
|
|
shortStep = (double)(b0 - a0) / (double)(b1 - a1 + 1);
|
|
shortT = (double)(a0) + (0.5 * shortStep);
|
|
for (idx1 = a1; idx1 < b1; ++idx1)
|
|
{
|
|
// Fill row long to short (y = idx1)
|
|
left = (int)(shortT + 0.5);
|
|
right = (int)(longT + 0.5);
|
|
if (left > right)
|
|
{
|
|
temp = left; left = right; right = temp;
|
|
}
|
|
for (idx0 = left; idx0 <= right; ++idx0)
|
|
{
|
|
if (idx0 >= min0 && idx0 <= max0 && idx1 >= min1 && idx1 <= max1)
|
|
{
|
|
ptr = (T *)(image->GetScalarPointer(idx0, idx1, z));
|
|
if (ptr)
|
|
{
|
|
pf = drawColor;
|
|
// Assign color to pixel.
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptr = (T)(*pf++);
|
|
ptr++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
longT += longStep;
|
|
shortT += shortStep;
|
|
}
|
|
|
|
// fill the second half of the triangle
|
|
shortStep = (double)(c0 - b0) / (double)(c1 - b1 + 1);
|
|
shortT = (double)(b0) + (0.5 * shortStep);
|
|
for (idx1 = b1; idx1 < c1; ++idx1)
|
|
{
|
|
// Fill row long to short (y = idx1)
|
|
left = (int)(shortT + 0.5);
|
|
right = (int)(longT + 0.5);
|
|
if (left > right)
|
|
{
|
|
temp = left; left = right; right = temp;
|
|
}
|
|
for (idx0 = left; idx0 <= right; ++idx0)
|
|
{
|
|
if (idx0 >= min0 && idx0 <= max0 && idx1 >= min1 && idx1 <= max1)
|
|
{
|
|
ptr = (T *)(image->GetScalarPointer(idx0, idx1, z));
|
|
if (ptr)
|
|
{
|
|
pf = drawColor;
|
|
// Assign color to pixel.
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptr = (T)(*pf++);
|
|
ptr++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
longT += longStep;
|
|
shortT += shortStep;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Fill a tube (thick line for initial 2D implementation).
|
|
void vtkImageCanvasSource2D::FillTriangle(int a0,int a1, int b0,int b1,
|
|
int c0,int c1)
|
|
{
|
|
void *ptr;
|
|
int z = this->DefaultZ;
|
|
|
|
// Pre-multiply coords if needed
|
|
if (this->Ratio[0] != 1.0)
|
|
{
|
|
a0 = int(double(a0) * this->Ratio[0]);
|
|
b0 = int(double(b0) * this->Ratio[0]);
|
|
c0 = int(double(c0) * this->Ratio[0]);
|
|
}
|
|
if (this->Ratio[1] != 1.0)
|
|
{
|
|
a1 = int(double(a1) * this->Ratio[1]);
|
|
b1 = int(double(b1) * this->Ratio[1]);
|
|
c1 = int(double(c1) * this->Ratio[1]);
|
|
}
|
|
if (this->Ratio[2] != 1.0)
|
|
{
|
|
z = int(double(z) * this->Ratio[2]);
|
|
}
|
|
|
|
ptr = this->ImageData->GetScalarPointer();
|
|
switch (this->ImageData->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(
|
|
vtkImageCanvasSource2DFillTriangle(this->ImageData,
|
|
this->DrawColor, (VTK_TT *)(ptr),
|
|
a0,a1, b0,b1, c0,c1, z));
|
|
default:
|
|
vtkErrorMacro(<< "FillTriangle: Cannot handle ScalarType.");
|
|
}
|
|
this->Modified();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw a point. Only implentented for 2D images.
|
|
template <class T>
|
|
void vtkImageCanvasSource2DDrawPoint(vtkImageData *image,
|
|
double *drawColor, T *ptr,
|
|
int p0, int p1, int z)
|
|
{
|
|
int min0, max0, min1, max1, min2, max2, maxV;
|
|
int idxV;
|
|
double *pf;
|
|
|
|
image->GetExtent(min0, max0, min1, max1, min2, max2);
|
|
z = (z < min2) ? min2 : z;
|
|
z = (z > max2) ? max2 : z;
|
|
maxV = image->GetNumberOfScalarComponents() - 1;
|
|
|
|
if (p0 >= min0 && p0 <= max0 && p1 >= min1 && p1 <= max1)
|
|
{
|
|
ptr = (T *)(image->GetScalarPointer(p0, p1, z));
|
|
|
|
pf = drawColor;
|
|
// Assign color to pixel.
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptr = (T)(*pf++);
|
|
ptr++;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw a circle
|
|
void vtkImageCanvasSource2D::DrawPoint(int p0, int p1)
|
|
{
|
|
void *ptr = NULL;
|
|
int z = this->DefaultZ;
|
|
|
|
vtkDebugMacro(<< "Drawing a point: (" << p0 << ", " << p1 << ")");
|
|
|
|
// Pre-multiply coords if needed
|
|
if (this->Ratio[0] != 1.0)
|
|
{
|
|
p0 = int(double(p0) * this->Ratio[0]);
|
|
}
|
|
if (this->Ratio[1] != 1.0)
|
|
{
|
|
p1 = int(double(p1) * this->Ratio[1]);
|
|
}
|
|
if (this->Ratio[2] != 1.0)
|
|
{
|
|
z = int(double(z) * this->Ratio[2]);
|
|
}
|
|
|
|
switch (this->ImageData->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(
|
|
vtkImageCanvasSource2DDrawPoint(this->ImageData,
|
|
this->DrawColor,
|
|
(VTK_TT *)(ptr),
|
|
p0, p1,
|
|
z));
|
|
default:
|
|
vtkErrorMacro(<< "DrawPoint: Cannot handle ScalarType.");
|
|
}
|
|
this->Modified();
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw a circle. Only implentented for 2D images.
|
|
template <class T>
|
|
void vtkImageCanvasSource2DDrawCircle(vtkImageData *image,
|
|
double *drawColor, T *ptr,
|
|
int c0, int c1, double radius, int z)
|
|
{
|
|
int min0, max0, min1, max1, min2, max2, maxV;
|
|
int idxV;
|
|
double *pf;
|
|
int numberOfSteps;
|
|
double thetaCos, thetaSin;
|
|
double x, y, temp;
|
|
int p0, p1;
|
|
int idx;
|
|
|
|
radius += 0.1;
|
|
image->GetExtent(min0, max0, min1, max1, min2, max2);
|
|
z = (z < min2) ? min2 : z;
|
|
z = (z > max2) ? max2 : z;
|
|
maxV = image->GetNumberOfScalarComponents() - 1;
|
|
|
|
numberOfSteps = (int)(ceil(6.2831853 * radius));
|
|
thetaCos = cos(1.0 / radius);
|
|
thetaSin = sin(1.0 / radius);
|
|
x = radius;
|
|
y = 0.0;
|
|
|
|
for (idx = 0; idx < numberOfSteps; ++idx)
|
|
{
|
|
p0 = c0+(int)(x);
|
|
p1 = c1+(int)(y);
|
|
if (p0 >= min0 && p0 <= max0 && p1 >= min1 && p1 <= max1)
|
|
{
|
|
ptr = (T *)(image->GetScalarPointer(p0, p1, z));
|
|
|
|
pf = drawColor;
|
|
// Assign color to pixel.
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptr = (T)(*pf++);
|
|
ptr++;
|
|
}
|
|
|
|
}
|
|
|
|
// rotate the point
|
|
temp = thetaCos * x + thetaSin * y;
|
|
y = thetaCos * y - thetaSin * x;
|
|
x = temp;
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw a circle
|
|
void vtkImageCanvasSource2D::DrawCircle(int c0, int c1, double radius)
|
|
{
|
|
void *ptr = NULL;
|
|
int z = this->DefaultZ;
|
|
|
|
vtkDebugMacro(<< "Drawing a circle: center = (" << c0 << ", " << c1
|
|
<< "), radius = " << radius);
|
|
|
|
// Pre-multiply coords if needed
|
|
if (this->Ratio[0] != 1.0)
|
|
{
|
|
c0 = int(double(c0) * this->Ratio[0]);
|
|
radius = int(double(radius) * this->Ratio[0]);
|
|
}
|
|
if (this->Ratio[1] != 1.0)
|
|
{
|
|
c1 = int(double(c1) * this->Ratio[1]);
|
|
}
|
|
if (this->Ratio[2] != 1.0)
|
|
{
|
|
z = int(double(z) * this->Ratio[2]);
|
|
}
|
|
|
|
switch (this->ImageData->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(
|
|
vtkImageCanvasSource2DDrawCircle(this->ImageData,
|
|
this->DrawColor,
|
|
(VTK_TT *)(ptr),
|
|
c0, c1,
|
|
radius,
|
|
z));
|
|
default:
|
|
vtkErrorMacro(<< "DrawCircle: Cannot handle ScalarType.");
|
|
}
|
|
this->Modified();
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw a line. Only implentented for 2D images.
|
|
// First point is already shifted to origin.
|
|
template <class T>
|
|
void vtkImageCanvasSource2DDrawSegment(vtkImageData *image,
|
|
double *drawColor, T *ptr,
|
|
int p0, int p1)
|
|
{
|
|
double f0, f1;
|
|
double s0, s1;
|
|
int numberOfSteps;
|
|
int maxV;
|
|
int idx, idxV;
|
|
vtkIdType inc0, inc1, inc2;
|
|
double *pf;
|
|
T *ptrV;
|
|
|
|
|
|
image->GetIncrements(inc0, inc1, inc2);
|
|
maxV = image->GetNumberOfScalarComponents() - 1;
|
|
|
|
// make sure we are stepping in the positive direction.
|
|
if (p0 < 0)
|
|
{
|
|
p0 = -p0;
|
|
inc0 = -inc0;
|
|
}
|
|
if (p1 < 0)
|
|
{
|
|
p1 = -p1;
|
|
inc1 = -inc1;
|
|
}
|
|
|
|
// Compute the number of steps needed.
|
|
if (p0 > p1)
|
|
{
|
|
numberOfSteps = p0;
|
|
}
|
|
else
|
|
{
|
|
numberOfSteps = p1;
|
|
}
|
|
|
|
// Compute the step vector.
|
|
s0 = (double)(p0) / (double)(numberOfSteps);
|
|
s1 = (double)(p1) / (double)(numberOfSteps);
|
|
|
|
f0 = f1 = 0.5;
|
|
|
|
ptrV = ptr;
|
|
pf = drawColor;
|
|
// Assign color to pixel.
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = (T)(*pf++);
|
|
ptrV++;
|
|
}
|
|
|
|
|
|
for (idx = 0; idx < numberOfSteps; ++idx)
|
|
{
|
|
f0 += s0;
|
|
if (f0 > 1.0)
|
|
{
|
|
ptr += inc0;
|
|
f0 -= 1.0;
|
|
}
|
|
f1 += s1;
|
|
if (f1 > 1.0)
|
|
{
|
|
ptr += inc1;
|
|
f1 -= 1.0;
|
|
}
|
|
|
|
ptrV = ptr;
|
|
pf = drawColor;
|
|
|
|
// Assign color to pixel.
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = (T)(*pf++);
|
|
ptrV++;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw a Segment from point a to point b.
|
|
void vtkImageCanvasSource2D::DrawSegment(int a0, int a1, int b0, int b1)
|
|
{
|
|
int *extent;
|
|
void *ptr;
|
|
int z = this->DefaultZ;
|
|
|
|
vtkDebugMacro(<< "Drawing a segment: " << a0 << ", " << a1 << " to "
|
|
<< b0 << ", " << b1);
|
|
|
|
// Pre-multiply coords if needed
|
|
if (this->Ratio[0] != 1.0)
|
|
{
|
|
a0 = int(double(a0) * this->Ratio[0]);
|
|
b0 = int(double(b0) * this->Ratio[0]);
|
|
}
|
|
if (this->Ratio[1] != 1.0)
|
|
{
|
|
a1 = int(double(a1) * this->Ratio[1]);
|
|
b1 = int(double(b1) * this->Ratio[1]);
|
|
}
|
|
if (this->Ratio[2] != 1.0)
|
|
{
|
|
z = int(double(z) * this->Ratio[2]);
|
|
}
|
|
|
|
// check to make sure line segment is in bounds.
|
|
extent = this->ImageData->GetExtent();
|
|
z = (z < extent[4]) ? extent[4] : z;
|
|
z = (z > extent[5]) ? extent[5] : z;
|
|
if (a0 < extent[0] || a0 > extent[1] || b0 < extent[0] || b0 > extent[1] ||
|
|
a1 < extent[2] || a1 > extent[3] || b1 < extent[2] || b1 > extent[3])
|
|
{
|
|
if ( ! this->ClipSegment(a0,a1,b0,b1))
|
|
{
|
|
// non of the segment is in the data.
|
|
return;
|
|
}
|
|
}
|
|
|
|
ptr = this->ImageData->GetScalarPointer(b0, b1, z);
|
|
a0 -= b0;
|
|
a1 -= b1;
|
|
switch (this->ImageData->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(
|
|
vtkImageCanvasSource2DDrawSegment(this->ImageData,
|
|
this->DrawColor,
|
|
(VTK_TT *)(ptr),
|
|
a0, a1));
|
|
default:
|
|
vtkErrorMacro(<< "DrawSegment: Cannot handle ScalarType.");
|
|
}
|
|
this->Modified();
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Clips a line segment so it will be in bounds.
|
|
// If the entire segment is out of bounds, the method returns 0.
|
|
int vtkImageCanvasSource2D::ClipSegment(int &a0, int &a1, int &b0, int &b1)
|
|
{
|
|
int min0, max0, min1, max1, min2, max2;
|
|
double fract;
|
|
|
|
|
|
this->ImageData->GetExtent(min0, max0, min1, max1, min2, max2);
|
|
|
|
// Check planes
|
|
// Both out of bounds
|
|
if (a0 < min0 && b0 < min0)
|
|
{
|
|
return 0;
|
|
}
|
|
// first out of bounds.
|
|
if (a0 < min0 && b0 >= min0)
|
|
{
|
|
// interpolate to find point on bounding plane.
|
|
fract = (double)(b0 - min0) / (double)(b0 - a0);
|
|
a0 = min0;
|
|
a1 = b1 + (int)(fract * (double)(a1 - b1));
|
|
}
|
|
// second out of bounds.
|
|
if (b0 < min0 && a0 >= min0)
|
|
{
|
|
// interpolate to find point on bounding plane.
|
|
fract = (double)(a0 - min0) / (double)(a0 - b0);
|
|
b0 = min0;
|
|
b1 = a1 + (int)(fract * (double)(b1 - a1));
|
|
}
|
|
|
|
// Both out of bounds
|
|
if (a0 > max0 && b0 > max0)
|
|
{
|
|
return 0;
|
|
}
|
|
// first out of bounds.
|
|
if (a0 > max0 && b0 <= max0)
|
|
{
|
|
// interpolate to find point on bounding plane.
|
|
fract = (double)(b0 - max0) / (double)(b0 - a0);
|
|
a0 = max0;
|
|
a1 = b1 + (int)(fract * (double)(a1 - b1));
|
|
}
|
|
// second out of bounds.
|
|
if (b0 > max0 && a0 <= max0)
|
|
{
|
|
// interpolate to find point on bounding plane.
|
|
fract = (double)(a0 - max0) / (double)(a0 - b0);
|
|
b0 = max0;
|
|
b1 = a1 + (int)(fract * (double)(b1 - a1));
|
|
}
|
|
|
|
|
|
// Both out of bounds
|
|
if (a1 < min1 && b1 < min1)
|
|
{
|
|
return 0;
|
|
}
|
|
// first out of bounds.
|
|
if (a1 < min1 && b1 >= min1)
|
|
{
|
|
// interpolate to find point on bounding plane.
|
|
fract = (double)(b1 - min1) / (double)(b1 - a1);
|
|
a1 = min1;
|
|
a0 = b0 + (int)(fract * (double)(a0 - b0));
|
|
}
|
|
// second out of bounds.
|
|
if (b1 < min1 && a1 >= min1)
|
|
{
|
|
// interpolate to find point on bounding plane.
|
|
fract = (double)(a1 - min1) / (double)(a1 - b1);
|
|
b1 = min1;
|
|
b0 = a0 + (int)(fract * (double)(b0 - a0));
|
|
}
|
|
|
|
// Both out of bounds
|
|
if (a1 > max1 && b1 > max1)
|
|
{
|
|
return 0;
|
|
}
|
|
// first out of bounds.
|
|
if (a1 > max1 && b1 <= max1)
|
|
{
|
|
// interpolate to find point on bounding plane.
|
|
fract = (double)(b1 - max1) / (double)(b1 - a1);
|
|
a1 = max1;
|
|
a0 = b0 + (int)(fract * (double)(a0 - b0));
|
|
}
|
|
// second out of bounds.
|
|
if (b1 > max1 && a1 <= max1)
|
|
{
|
|
// interpolate to find point on bounding plane.
|
|
fract = (double)(a1 - max1) / (double)(a1 - b1);
|
|
b1 = max1;
|
|
b0 = a0 + (int)(fract * (double)(b0 - a0));
|
|
}
|
|
|
|
this->Modified();
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw a line. Only implentented for 3D images.
|
|
// First point is already shifted to origin.
|
|
template <class T>
|
|
void vtkImageCanvasSource2DDrawSegment3D(vtkImageData *image,
|
|
double *drawColor,
|
|
T *ptr, int p0, int p1, int p2)
|
|
{
|
|
double f0, f1, f2;
|
|
double s0, s1, s2;
|
|
int numberOfSteps;
|
|
int idx, idxV, maxV;
|
|
vtkIdType inc0, inc1, inc2;
|
|
double *pf;
|
|
T *ptrV;
|
|
|
|
|
|
image->GetIncrements(inc0, inc1, inc2);
|
|
maxV = image->GetNumberOfScalarComponents() - 1;
|
|
|
|
// make sure we are stepping in the positive direction.
|
|
if (p0 < 0)
|
|
{
|
|
p0 = -p0;
|
|
inc0 = -inc0;
|
|
}
|
|
if (p1 < 0)
|
|
{
|
|
p1 = -p1;
|
|
inc1 = -inc1;
|
|
}
|
|
if (p2 < 0)
|
|
{
|
|
p2 = -p2;
|
|
inc2 = -inc2;
|
|
}
|
|
|
|
// Compute the number of steps needed.
|
|
numberOfSteps = (p0 > p1) ? p0 : p1;
|
|
numberOfSteps = (numberOfSteps > p2) ? numberOfSteps : p2;
|
|
|
|
// Compute the step vector.
|
|
s0 = (double)(p0) / (double)(numberOfSteps);
|
|
s1 = (double)(p1) / (double)(numberOfSteps);
|
|
s2 = (double)(p2) / (double)(numberOfSteps);
|
|
|
|
f0 = f1 = f2 = 0.5;
|
|
|
|
|
|
ptrV = ptr;
|
|
pf = drawColor;
|
|
// Assign color to pixel.
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = (T)(*pf++);
|
|
ptrV++;
|
|
}
|
|
|
|
for (idx = 0; idx < numberOfSteps; ++idx)
|
|
{
|
|
f0 += s0;
|
|
if (f0 > 1.0)
|
|
{
|
|
ptr += inc0;
|
|
f0 -= 1.0;
|
|
}
|
|
f1 += s1;
|
|
if (f1 > 1.0)
|
|
{
|
|
ptr += inc1;
|
|
f1 -= 1.0;
|
|
}
|
|
f2 += s2;
|
|
if (f2 > 1.0)
|
|
{
|
|
ptr += inc2;
|
|
f2 -= 1.0;
|
|
}
|
|
|
|
ptrV = ptr;
|
|
pf = drawColor;
|
|
// Assign color to pixel.
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = (T)(*pf++);
|
|
ptrV++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw a Segment from point a to point b.
|
|
// No clipping or bounds checking.
|
|
void vtkImageCanvasSource2D::DrawSegment3D(double *a, double *b)
|
|
{
|
|
void *ptr;
|
|
int a0, a1, a2;
|
|
|
|
// Pre-multiply coords if needed
|
|
if (this->Ratio[0] != 1.0)
|
|
{
|
|
a[0] = int(double(a[0]) * this->Ratio[0]);
|
|
b[0] = int(double(b[0]) * this->Ratio[0]);
|
|
}
|
|
if (this->Ratio[1] != 1.0)
|
|
{
|
|
a[1] = int(double(a[1]) * this->Ratio[1]);
|
|
b[1] = int(double(b[1]) * this->Ratio[1]);
|
|
}
|
|
if (this->Ratio[2] != 1.0)
|
|
{
|
|
a[2] = int(double(a[2]) * this->Ratio[2]);
|
|
b[2] = int(double(b[2]) * this->Ratio[2]);
|
|
}
|
|
|
|
ptr = this->ImageData->GetScalarPointer((int)(b[0] + 0.5),
|
|
(int)(b[1] + 0.5),
|
|
(int)(b[2] + 0.5));
|
|
a0 = (int)(a[0] - b[0] + 0.5);
|
|
a1 = (int)(a[1] - b[1] + 0.5);
|
|
a2 = (int)(a[2] - b[2] + 0.5);
|
|
switch (this->ImageData->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(
|
|
vtkImageCanvasSource2DDrawSegment3D(this->ImageData,
|
|
this->DrawColor,
|
|
(VTK_TT *)(ptr),
|
|
a0, a1, a2));
|
|
default:
|
|
vtkErrorMacro(<< "DrawSegment3D: Cannot handle ScalarType.");
|
|
}
|
|
this->Modified();
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class T>
|
|
void vtkImageCanvasSource2DFill(vtkImageData *image, double *color,
|
|
T *ptr, int x, int y)
|
|
{
|
|
vtkImageCanvasSource2DPixel *pixel;
|
|
vtkImageCanvasSource2DPixel *first, *last;
|
|
vtkImageCanvasSource2DPixel *heap = NULL;
|
|
int min0, max0, min1, max1, min2, max2, maxV;
|
|
int idxV;
|
|
vtkIdType inc0, inc1, inc2;
|
|
T fillColor[10];
|
|
T drawColor[10];
|
|
T *ptrV, *ptrC;
|
|
int temp;
|
|
|
|
image->GetExtent(min0, max0, min1, max1, min2, max2);
|
|
maxV = image->GetNumberOfScalarComponents() - 1;
|
|
image->GetIncrements(inc0, inc1, inc2);
|
|
|
|
// Copy the fill color and make sure it differs from drawColor.
|
|
ptrV = ptr;
|
|
temp = 1;
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
// Save the fill color
|
|
fillColor[idxV] = *ptrV;
|
|
drawColor[idxV] = (T)(color[idxV]);
|
|
if (*ptrV != drawColor[idxV])
|
|
{
|
|
temp = 0;
|
|
}
|
|
ptrV++;
|
|
}
|
|
if (temp)
|
|
{ // fill the same as draw
|
|
cerr << "Fill: Cannot handle draw color same as fill color\n";
|
|
return;
|
|
}
|
|
|
|
// Create the seed
|
|
pixel = vtkImageCanvasSource2DPixel::New();
|
|
pixel->X = x;
|
|
pixel->Y = y;
|
|
pixel->Pointer = (void *)(ptr);
|
|
pixel->Next = NULL;
|
|
first = last = pixel;
|
|
// change the seeds color
|
|
ptrV = (T *)(last->Pointer);
|
|
ptrC = drawColor;
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = *ptrC++;
|
|
ptrV++;
|
|
}
|
|
|
|
|
|
while (first)
|
|
{
|
|
ptr = (T *)(first->Pointer);
|
|
|
|
// check bounds for -x neighbor
|
|
if (first->X > min0)
|
|
{
|
|
// Get the neighbor
|
|
ptrV = ptr - inc0;
|
|
// compare color
|
|
ptrC = fillColor;
|
|
temp = 1;
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
if (*ptrV != *ptrC++)
|
|
{
|
|
temp = 0;
|
|
break;
|
|
}
|
|
ptrV++;
|
|
}
|
|
if (temp)
|
|
{ // color match add a new seed to end of list
|
|
if (heap)
|
|
{
|
|
pixel = heap;
|
|
heap = heap->Next;
|
|
}
|
|
else
|
|
{
|
|
pixel = vtkImageCanvasSource2DPixel::New();
|
|
}
|
|
pixel->X = first->X-1;
|
|
pixel->Y = first->Y;
|
|
pixel->Pointer = (void *)(ptr - inc0);
|
|
pixel->Next = NULL;
|
|
last->Next = pixel;
|
|
last = pixel;
|
|
// change the seeds color
|
|
ptrV = (T *)(last->Pointer);
|
|
ptrC = drawColor;
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = *ptrC++;
|
|
ptrV++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check bounds for +x neighbor
|
|
if (first->X < max0)
|
|
{
|
|
// Get the neighbor
|
|
ptrV = ptr + inc0;
|
|
// compare color
|
|
ptrC = fillColor;
|
|
temp = 1;
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
if (*ptrV != *ptrC++)
|
|
{
|
|
temp = 0;
|
|
break;
|
|
}
|
|
ptrV++;
|
|
}
|
|
if (temp)
|
|
{ // color match add a new seed to end of list
|
|
if (heap)
|
|
{
|
|
pixel = heap;
|
|
heap = heap->Next;
|
|
}
|
|
else
|
|
{
|
|
pixel = vtkImageCanvasSource2DPixel::New();
|
|
}
|
|
pixel->X = first->X+1;
|
|
pixel->Y = first->Y;
|
|
pixel->Pointer = (void *)(ptr + inc0);
|
|
pixel->Next = NULL;
|
|
last->Next = pixel;
|
|
last = pixel;
|
|
// change the seeds color
|
|
ptrV = (T *)(last->Pointer);
|
|
ptrC = drawColor;
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = *ptrC++;
|
|
ptrV++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check bounds for -y neighbor
|
|
if (first->Y > min1)
|
|
{
|
|
// Get the neighbor
|
|
ptrV = ptr - inc1;
|
|
// compare color
|
|
ptrC = fillColor;
|
|
temp = 1;
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
if (*ptrV != *ptrC++)
|
|
{
|
|
temp = 0;
|
|
break;
|
|
}
|
|
ptrV++;
|
|
}
|
|
if (temp)
|
|
{ // color match add a new seed to end of list
|
|
if (heap)
|
|
{
|
|
pixel = heap;
|
|
heap = heap->Next;
|
|
}
|
|
else
|
|
{
|
|
pixel = vtkImageCanvasSource2DPixel::New();
|
|
}
|
|
pixel->X = first->X;
|
|
pixel->Y = first->Y-1;
|
|
pixel->Pointer = (void *)(ptr - inc1);
|
|
pixel->Next = NULL;
|
|
last->Next = pixel;
|
|
last = pixel;
|
|
// change the seeds color
|
|
ptrV = (T *)(last->Pointer);
|
|
ptrC = drawColor;
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = *ptrC++;
|
|
ptrV++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check bounds for +y neighbor
|
|
if (first->Y < max1)
|
|
{
|
|
// Get the neighbor
|
|
ptrV = ptr + inc1;
|
|
// compare color
|
|
ptrC = fillColor;
|
|
temp = 1;
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
if (*ptrV != *ptrC++)
|
|
{
|
|
temp = 0;
|
|
break;
|
|
}
|
|
ptrV++;
|
|
}
|
|
if (temp)
|
|
{ // color match add a new seed to end of list
|
|
if (heap)
|
|
{
|
|
pixel = heap;
|
|
heap = heap->Next;
|
|
}
|
|
else
|
|
{
|
|
pixel = vtkImageCanvasSource2DPixel::New();
|
|
}
|
|
pixel->X = first->X;
|
|
pixel->Y = first->Y+1;
|
|
pixel->Pointer = (void *)(ptr + inc1);
|
|
pixel->Next = NULL;
|
|
last->Next = pixel;
|
|
last = pixel;
|
|
// change the seeds color
|
|
ptrV = (T *)(last->Pointer);
|
|
ptrC = drawColor;
|
|
for (idxV = 0; idxV <= maxV; ++idxV)
|
|
{
|
|
*ptrV = *ptrC++;
|
|
ptrV++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// remove the first from the list.
|
|
pixel = first;
|
|
first = first->Next;
|
|
pixel->Next = heap;
|
|
heap = pixel;
|
|
}
|
|
|
|
// free the heap
|
|
while (heap)
|
|
{
|
|
pixel = heap;
|
|
heap = heap->Next;
|
|
delete pixel;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Fill a colored area with another color. (like connectivity)
|
|
// All pixels connected to pixel (x, y) get replaced by draw color.
|
|
void vtkImageCanvasSource2D::FillPixel(int x, int y)
|
|
{
|
|
void *ptr;
|
|
int *ext = this->ImageData->GetExtent();
|
|
int z = this->DefaultZ;
|
|
|
|
// Pre-multiply coords if needed
|
|
if (this->Ratio[0] != 1.0)
|
|
{
|
|
x = int(double(x) * this->Ratio[0]);
|
|
}
|
|
if (this->Ratio[1] != 1.0)
|
|
{
|
|
y = int(double(y) * this->Ratio[1]);
|
|
}
|
|
if (this->Ratio[2] != 1.0)
|
|
{
|
|
z = int(double(z) * this->Ratio[2]);
|
|
}
|
|
|
|
z = (z < ext[4]) ? ext[4] : z;
|
|
z = (z > ext[5]) ? ext[5] : z;
|
|
|
|
ptr = this->ImageData->GetScalarPointer(x, y, z);
|
|
|
|
switch (this->ImageData->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(
|
|
vtkImageCanvasSource2DFill(this->ImageData,
|
|
this->DrawColor,
|
|
(VTK_TT *)(ptr),
|
|
x, y));
|
|
default:
|
|
vtkErrorMacro(<< "Fill: Cannot handle ScalarType.");
|
|
}
|
|
this->Modified();
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageCanvasSource2D::SetExtent(int *extent)
|
|
{
|
|
this->SetExtent(extent[0], extent[1],
|
|
extent[2], extent[3],
|
|
extent[4], extent[5]);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageCanvasSource2D::SetExtent(int xMin, int xMax,
|
|
int yMin, int yMax,
|
|
int zMin, int zMax)
|
|
{
|
|
int modified = 0;
|
|
|
|
if (this->WholeExtent[0] != xMin)
|
|
{
|
|
modified = 1;
|
|
this->WholeExtent[0] = xMin ;
|
|
}
|
|
if (this->WholeExtent[1] != xMax)
|
|
{
|
|
modified = 1;
|
|
this->WholeExtent[1] = xMax ;
|
|
}
|
|
if (this->WholeExtent[2] != yMin)
|
|
{
|
|
modified = 1;
|
|
this->WholeExtent[2] = yMin ;
|
|
}
|
|
if (this->WholeExtent[3] != yMax)
|
|
{
|
|
modified = 1;
|
|
this->WholeExtent[3] = yMax ;
|
|
}
|
|
if (this->WholeExtent[4] != zMin)
|
|
{
|
|
modified = 1;
|
|
this->WholeExtent[4] = zMin ;
|
|
}
|
|
if (this->WholeExtent[5] != zMax)
|
|
{
|
|
modified = 1;
|
|
this->WholeExtent[5] = zMax ;
|
|
}
|
|
if (modified)
|
|
{
|
|
this->Modified();
|
|
this->ImageData->SetExtent(this->WholeExtent);
|
|
this->ImageData->AllocateScalars();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageCanvasSource2D::SetScalarType(int t)
|
|
{
|
|
if (this->ImageData->GetScalarType() != t)
|
|
{
|
|
this->Modified();
|
|
this->ImageData->SetScalarType(t);
|
|
this->ImageData->AllocateScalars();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageCanvasSource2D::SetNumberOfScalarComponents(int t)
|
|
{
|
|
if (this->ImageData->GetNumberOfScalarComponents() != t)
|
|
{
|
|
this->Modified();
|
|
this->ImageData->SetNumberOfScalarComponents(t);
|
|
this->ImageData->AllocateScalars();
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkImageCanvasSource2D::RequestInformation (
|
|
vtkInformation * vtkNotUsed(request),
|
|
vtkInformationVector** vtkNotUsed( inputVector ),
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
// get the info objects
|
|
vtkInformation* outInfo = outputVector->GetInformationObject(0);
|
|
|
|
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
|
|
this->WholeExtent,6);
|
|
|
|
vtkDataObject::SetPointDataActiveScalarInfo
|
|
(outInfo, this->ImageData->GetScalarType(),
|
|
this->ImageData->GetNumberOfScalarComponents());
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkImageCanvasSource2D::RequestData (
|
|
vtkInformation * vtkNotUsed(request),
|
|
vtkInformationVector** vtkNotUsed( inputVector ),
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
// get the data object
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
vtkImageData *output = vtkImageData::SafeDownCast
|
|
(outInfo->Get(vtkDataObject::DATA_OBJECT()) );
|
|
|
|
output->ShallowCopy(this->ImageData);
|
|
|
|
return 1;
|
|
}
|
|
|