00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "vtkImagePolyDataSeedConnectivity.h"
00018
00019 #include <vtkPolyData.h>
00020 #include <vtkImageData.h>
00021 #include <vtkMath.h>
00022 #include <vtkPlane.h>
00023 #include <vtkSphere.h>
00024 #include <vtkImplicitBoolean.h>
00025 #include <vtkImplicitFunctionToImageStencil.h>
00026 #include <vtkImageStencil.h>
00027 #include <vtkObjectFactory.h>
00028 #include <vtkImageSeedConnectivity.h>
00029 #include <vtkImageIterator.h>
00030 #include <vtkImageGaussianSmooth.h>
00031 #include <vtkMarchingCubes.h>
00032 #include <vtkPolyDataConnectivityFilter.h>
00033 #include <vtkCleanPolyData.h>
00034 #include <vtkTriangleFilter.h>
00035 #include <vtkPointData.h>
00036 #include <vtkImageContinuousDilate3D.h>
00037
00038 vtkCxxRevisionMacro(vtkImagePolyDataSeedConnectivity, "$Revision: 1.1 $");
00039 vtkStandardNewMacro(vtkImagePolyDataSeedConnectivity);
00040 vtkCxxSetObjectMacro(vtkImagePolyDataSeedConnectivity, Axis,vtkPolyData);
00041
00042
00043 vtkImagePolyDataSeedConnectivity::vtkImagePolyDataSeedConnectivity()
00044 {
00045 this->Axis = NULL;
00046 this->ClipImageData = vtkImageData::New();
00047 this->OuterMold = vtkPolyData::New();
00048 this->ThresholdRatio = 0.45;
00049 }
00050
00051 vtkImagePolyDataSeedConnectivity::~vtkImagePolyDataSeedConnectivity()
00052 {
00053 if(this->Axis)
00054 {
00055 this->Axis->Delete();
00056 }
00057 this->ClipImageData->Delete();
00058 this->ClipImageData = NULL;
00059 this->OuterMold->Delete();
00060 this->OuterMold = NULL;
00061 }
00067
00068 #define PSC_MIN(x,y) ((x)<(y) ? (x) : (y))
00069 #define PSC_MAX(x,y) ((x)>(y) ? (x) : (y))
00070
00071 void vtkImagePolyDataSeedConnectivity::Execute()
00072 {
00073 vtkImageData *input = this->GetInput();
00074 vtkPolyData *output = this->GetOutput();
00075 int intervalle = 2;
00076 int dim[3];
00077
00078 vtkDebugMacro(<< "Executing polydata seed connectivity...");
00079
00080 if (input == NULL)
00081 {
00082 vtkErrorMacro(<<"Input is NULL");
00083 return;
00084 }
00085
00086
00087 if ( input->GetDataDimension() != 3 )
00088 {
00089 vtkErrorMacro("Bad input: only treats 3D structured point datasets");
00090 return;
00091 }
00092
00093 input->GetDimensions(dim);
00094
00095
00096
00097
00098
00099 vtkImageData *imagedata = vtkImageData::New();
00100 imagedata->SetOrigin( input->GetOrigin() );
00101 imagedata->SetSpacing( input->GetSpacing() );
00102 imagedata->SetExtent( input->GetExtent() );
00103 imagedata->SetScalarTypeToUnsignedChar ();
00104 imagedata->AllocateScalars();
00105
00106
00107
00108
00109
00110
00111 vtkImageSeedConnectivity *seed = vtkImageSeedConnectivity::New();
00112 seed->SetInput( imagedata );
00113 seed->SetInputConnectValue( 255 );
00114
00115
00116
00117 this->ClipImageWithAxis();
00118
00119 vtkPoints *points = this->Axis->GetPoints();
00120 vtkDataArray* scalars = this->Axis->GetPointData()->GetScalars();
00121
00122 int numPts = points->GetNumberOfPoints();
00123 double p1[3], p2[3], p3[3], tuple[2];
00124 double radius, signalvalue;
00125 int region[6];
00126 int i_p2;
00127 unsigned short* inSI, *inSIEnd;
00128 unsigned char* outSI,*outSIEnd;
00129
00130 for(int i=0; i<numPts; i+=intervalle)
00131 {
00132 i_p2 = i+intervalle/2;
00133 points->GetPoint(i, p1);
00134 if(numPts <= i+2*intervalle)
00135 {
00136 i_p2 = i+intervalle;
00137 points->GetPoint(numPts - 1, p3);
00138 i = numPts;
00139 }
00140 else
00141 {
00142 points->GetPoint(i+intervalle, p3);
00143 }
00144 points->GetPoint(i_p2, p2);
00145
00146
00147
00148 seed->AddSeed( (int)p2[0], (int)p2[1], (int)p2[2] );
00149
00150
00151
00152 scalars->GetTuple(i_p2, tuple);
00153 radius = tuple[0];
00154 signalvalue = tuple[1];
00155 radius *= 4;
00156
00157 region[0] = (int)PSC_MAX(p2[0] - radius, 0);
00158 region[2] = (int)PSC_MAX(p2[1] - radius, 0);
00159 region[4] = (int)PSC_MAX(p2[2] - radius, 0);
00160
00161 region[1] = (int)PSC_MIN(p2[0] + radius, dim[0] - 1);
00162 region[3] = (int)PSC_MIN(p2[1] + radius, dim[1] - 1);
00163 region[5] = (int)PSC_MIN(p2[2] + radius, dim[2] - 1);
00164
00165
00166
00167 signalvalue *= ThresholdRatio;
00168
00178
00179
00180 vtkImageIterator<unsigned short> inIt(this->ClipImageData, region);
00181 vtkImageIterator<unsigned char> outIt(imagedata, region);
00182
00183
00184
00185 while (!inIt.IsAtEnd())
00186 {
00187 inSI = inIt.BeginSpan(); inSIEnd = inIt.EndSpan();
00188 outSI = outIt.BeginSpan(); outSIEnd = outIt.EndSpan();
00189
00190
00191 while (inSI != inSIEnd)
00192 *outSI++ = (signalvalue <= *inSI++) ? 255 : 0;
00193
00194 inIt.NextSpan(); outIt.NextSpan();
00195 }
00196 }
00197
00198
00199
00200
00201 vtkImageGaussianSmooth *gauss = vtkImageGaussianSmooth::New();
00202 gauss->SetInput( seed->GetOutput() );
00203 gauss->SetDimensionality(3);
00204
00205
00206
00207 vtkMarchingCubes *contour = vtkMarchingCubes::New();
00208 contour->SetInput ( gauss->GetOutput() );
00209 contour->SetNumberOfContours( 1 );
00210 contour->SetValue(0, 128);
00211 contour->ComputeGradientsOn ();
00212 contour->ComputeScalarsOn ();
00213
00214 vtkCleanPolyData *clean = vtkCleanPolyData::New();
00215 clean->SetInput ( contour->GetOutput() );
00216
00217 vtkTriangleFilter *tf = vtkTriangleFilter::New();
00218 tf->SetInput( clean->GetOutput() );
00219 tf->Update();
00220
00221
00222 output->DeepCopy( tf->GetOutput() );
00223
00224
00225
00226
00227
00235
00236 vtkImageContinuousDilate3D *dilate = vtkImageContinuousDilate3D ::New();
00237 dilate->SetInput ( seed->GetOutput() );
00238
00239
00240
00241
00242
00243
00244
00245
00246 int kernelsize[3];
00247 double spacing[3];
00248 seed->GetOutput()->GetSpacing( spacing );
00249 for(int j=0; j<3; j++)
00250 {
00251
00252 kernelsize[j] = 3;
00253
00254
00255 }
00256 dilate->SetKernelSize (kernelsize[0], kernelsize[1], kernelsize[2]);
00257
00258
00259 gauss->SetInput( dilate->GetOutput());
00260 tf->Update();
00261
00262
00263 OuterMold->ShallowCopy( tf->GetOutput() );
00264
00265
00266
00267
00268 imagedata -> Delete();
00269 seed -> Delete();
00270 gauss -> Delete();
00271 contour -> Delete();
00272 clean -> Delete();
00273 tf -> Delete();
00274 dilate -> Delete();
00275
00276
00277
00278 }
00279
00280 #undef PSC_MAX
00281 #undef PSC_MIN
00282
00283
00284
00285 void vtkImagePolyDataSeedConnectivity::ClipImageWithAxis()
00286 {
00287
00288
00299 double normal[3];
00300
00308 this->Axis->Update();
00309 vtkPoints *points = this->Axis->GetPoints();
00310 int numPts = points->GetNumberOfPoints();
00311 double p1[3];
00312 double p2[3];
00313
00314 points->GetPoint( 0, p2 );
00315 points->GetPoint( 1, p1 );
00316
00317 normal[0] = p1[0] - p2[0];
00318 normal[1] = p1[1] - p2[1];
00319 normal[2] = p1[2] - p2[2];
00320 vtkMath::Normalize( normal );
00321
00322 vtkPlane *plane1 = vtkPlane::New();
00323 plane1->SetOrigin( p2[ 0 ], p2[ 1 ], p2[ 2 ] );
00324 plane1->SetNormal( normal[0], normal[1], normal[2]);
00325
00326 vtkDataArray* scalars = this->Axis->GetPointData()->GetScalars();
00327 double tuple[2];
00328 scalars->GetTuple(0, tuple);
00329 double radius = tuple[0];
00330
00331 vtkSphere *sphere1 = vtkSphere::New();
00332 sphere1->SetCenter( p2[ 0 ], p2[ 1 ], p2[ 2 ] );
00333 sphere1->SetRadius( radius + 1);
00334
00335 vtkImplicitBoolean *disk1 = vtkImplicitBoolean::New();
00336 disk1->SetOperationTypeToIntersection();
00337 disk1->AddFunction(sphere1);
00338 disk1->AddFunction(plane1);
00339
00348
00349 points->GetPoint( numPts - 1, p2);
00350
00351 points->GetPoint( numPts - 2, p1);
00352 normal[0] = p1[0] - p2[0];
00353 normal[1] = p1[1] - p2[1];
00354 normal[2] = p1[2] - p2[2];
00355 vtkMath::Normalize( normal );
00356
00357 vtkPlane *plane2 = vtkPlane::New();
00358 plane2->SetOrigin( p2[ 0 ], p2[ 1 ], p2[ 2 ] );
00359 plane2->SetNormal( normal[0], normal[1], normal[2]);
00360
00361 vtkSphere *sphere2 = vtkSphere::New();
00362 sphere2->SetCenter( p2[ 0 ], p2[ 1 ], p2[ 2 ] );
00363 sphere2->SetRadius( radius + 1 );
00364
00365 vtkImplicitBoolean *disk2 = vtkImplicitBoolean::New();
00366 disk2->SetOperationTypeToIntersection();
00367 disk2->AddFunction(sphere2);
00368 disk2->AddFunction(plane2);
00369
00370 vtkImplicitBoolean *disk = vtkImplicitBoolean::New();
00371 disk->SetOperationTypeToUnion();
00372 disk->AddFunction(disk1);
00373 disk->AddFunction(disk2);
00374
00379 vtkImplicitFunctionToImageStencil *functionToStencil = vtkImplicitFunctionToImageStencil::New ();
00380 functionToStencil->SetInput ( disk );
00381
00382 vtkImageStencil *stencil = vtkImageStencil::New();
00383 stencil->SetInput( this->GetInput() );
00384 stencil->SetStencil( functionToStencil->GetOutput() );
00385 stencil->ReverseStencilOn();
00386 stencil->SetBackgroundValue (0);
00387
00388 stencil->Update();
00389
00390 this->ClipImageData->ShallowCopy( stencil->GetOutput() );
00391
00397
00398 plane1 -> Delete();
00399 sphere1 -> Delete();
00400 disk1 -> Delete();
00401 plane2 -> Delete();
00402 sphere2 -> Delete();
00403 disk2 -> Delete();
00404 disk -> Delete();
00405 functionToStencil -> Delete();
00406 stencil -> Delete();
00407 }
00408
00409 void vtkImagePolyDataSeedConnectivity::PrintSelf(ostream& os, vtkIndent indent)
00410 {
00411 this->Superclass::PrintSelf(os,indent);
00412 if ( this->Axis )
00413 {
00414 os << indent << "Axis of " << this->Axis->GetNumberOfPoints()
00415 << "points defined\n";
00416 }
00417 else
00418 {
00419 os << indent << "Axis not defined\n";
00420 }
00421 }
00422
00423