GOFIGURE2  0.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
QGoFilterShape.cxx
Go to the documentation of this file.
1 /*=========================================================================
2  Authors: The GoFigure Dev. Team.
3  at Megason Lab, Systems biology, Harvard Medical school, 2009-11
4 
5  Copyright (c) 2009-11, President and Fellows of Harvard College.
6  All rights reserved.
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions are met:
10 
11  Redistributions of source code must retain the above copyright notice,
12  this list of conditions and the following disclaimer.
13  Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16  Neither the name of the President and Fellows of Harvard College
17  nor the names of its contributors may be used to endorse or promote
18  products derived from this software without specific prior written
19  permission.
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
26  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 =========================================================================*/
34 #include "QGoFilterShape.h"
35 
36 #include "QGoGUILibConfigure.h"
37 
38 // Shapes to be generated
39 #include "vtkPolyData.h"
40 #include "vtkPointData.h"
41 #include "vtkPlane.h"
42 // To deal with borders is mesh is on a border
43 #include "vtkClipPolyData.h"
44 // To extract 2D contours
45 #include "vtkCutter.h"
46 #include "vtkBox.h"
47 //Sphere
48 #include "vtkSphereSource.h"
49 //Cube
50 #include "vtkCubeSource.h"
51 #include "vtkTriangleFilter.h"
52 //cylinder
53 #include "vtkCylinderSource.h"
54 //#include "vtkTriangleFilter.h"
55 
56 #include "GoImageProcessor.h"
57 
58 //--------------------------------------------------------------------------
59 QGoFilterShape::QGoFilterShape(QObject *iParent, int iDimension) :
60  QGoFilterSemiAutoBase(iParent)
61 {
62  m_Dimension = iDimension;
63 
64  QString name = "Shape ";
65  if ( m_Dimension < 2 )
66  {
67  name.append( QString::number(m_Dimension + 2, 10) );
68  name.append("D");
69  }
70  else
71  {
72  name = "2D Shapes in 1 mesh";
73  }
74 
75  //setName(name);
76  //QGoContourSemiAutoShapeWidget *widget =
77  // new QGoContourSemiAutoShapeWidget(NULL);
78  //setWidget(widget);
79 
80  m_Shape = 0;
81 }
82 
83 //--------------------------------------------------------------------------
84 
85 //--------------------------------------------------------------------------
88 {
89 }
90 
91 //--------------------------------------------------------------------------
92 
93 //--------------------------------------------------------------------------
94 vtkPolyData *
96 {
97  // Radius has to be > 0
98  if ( getRadius() <= 0 )
99  {
100  std::cerr << "Radius should be > 0 " << std::endl;
101  return NULL;
102  }
103 
104  double *center2 = new double[3];
105 
106  // update the pointed value of the seeds
107  emit UpdateSeeds();
108 
109  // LOOP FOR EACH SEED
110  for ( int i = 0; i < getPoints()->GetNumberOfPoints(); i++ )
111  {
112  getPoints()->GetPoint(i, center2);
113 
114  // useful to translate the polydata afterwards
115  setCenter(center2);
116 
117  // need a switch depending on shape
118  vtkPolyData *testing = NULL;
119 
120  switch ( m_Shape )
121  {
122  case 0:
123  testing = GenerateSphere( getCenter(), getRadius(), this->getInput() );
124  break;
125  case 1:
126  testing = GenerateCube( getCenter(), getRadius(), this->getInput() );
127  break;
128  //case 2:
129  // testing = GenerateCylinder(getCenter());
130  // break;
131  default:
132  break;
133  }
134 
135  if ( m_Dimension == 0 )
136  {
137  // Extract each slice according top the sampling
138  vtkPlane *implicitFunction = vtkPlane::New();
139  implicitFunction->SetNormal(0, 0, 1);
140  implicitFunction->SetOrigin(center2[0], center2[1], center2[2]);
141 
142  vtkCutter *cutter = vtkCutter::New();
143  cutter->SetInput(testing);
144  cutter->SetCutFunction(implicitFunction);
145  cutter->Update();
146 
147  vtkPolyData *output = ReorganizeContour( cutter->GetOutput() );
148  emit ContourCreated(output);
149 
150  implicitFunction->Delete();
151  cutter->Delete();
152  testing->Delete();
153  }
154  else // if dimension == 1, create a mesh
155  {
156  if ( m_Dimension == 1 )
157  {
158  emit MeshCreated(testing, this->getChannel() - 1);
159  }
160  else
161  {
162  //emit CreateEmptyMesh();
163  // Extract each slice according top the sampling
164  vtkPlane *implicitFunction = vtkPlane::New();
165  implicitFunction->SetNormal(0, 0, 1);
166 
167  vtkCutter *cutter = vtkCutter::New();
168  cutter->SetInput(testing);
169  cutter->SetCutFunction(implicitFunction);
170 
171  double step = 2. * getRadius() / static_cast< double >( getSampling() + 1 );
172 
173  for ( int j = 0; j < getSampling(); ++j )
174  {
175  implicitFunction
176  ->SetOrigin(
177  ( center2[0] - getRadius() + static_cast< double >( j + 1 ) * step ),
178  ( center2[1] - getRadius() + static_cast< double >( j + 1 ) * step ),
179  ( center2[2] - getRadius() + static_cast< double >( j + 1 ) * step ) );
180  cutter->Update();
181  vtkPolyData *output = ReorganizeContour( cutter->GetOutput() );
182  emit AddContourForMeshToContours(output);
183  }
184 
185  implicitFunction->Delete();
186  cutter->Delete();
187  testing->Delete();
189  }
190  }
191  }
192  emit SegmentationFinished();
193 
194  delete[] center2;
195 
196  return NULL;
197 }
198 
199 //--------------------------------------------------------------------------
200 
201 //--------------------------------------------------------------------------
202 void
204 {
206 
207  // connect specific
208  QObject::connect( getWidget(), SIGNAL( Shape(int) ),
209  this, SLOT( setShape(int) ) );
210 }
211 
212 //--------------------------------------------------------------------------
213 
214 //--------------------------------------------------------------------------
215 void
217 {
218  m_Shape = iShape;
219 }
220 
221 //--------------------------------------------------------------------------
222 
223 //--------------------------------------------------------------------------
224 vtkPolyData *
225 QGoFilterShape::GenerateSphere(double *iCenter, double iRadius,
226  vtkSmartPointer< vtkImageData > iImage)
227 {
228  // create sphere geometry
229  vtkSphereSource *sphere = vtkSphereSource::New();
230 
231  sphere->SetRadius( iRadius );
232  sphere->SetCenter(iCenter);
233  sphere->Update();
234  sphere->GetOutput()->GetPointData()->SetNormals(NULL);
235 
236  // Deal with borders
237  vtkBox *implicitFunction = vtkBox::New();
238  //implicitFunction->SetBounds( this->getInput()->GetBounds() );
239  implicitFunction->SetBounds( iImage->GetBounds() );
240 
241  vtkClipPolyData *cutter = vtkClipPolyData::New();
242  cutter->SetInput( sphere->GetOutput() );
243  cutter->InsideOutOn();
244  cutter->SetClipFunction(implicitFunction);
245  cutter->Update();
246 
247  vtkPolyData *output = vtkPolyData::New();
248  output->DeepCopy( cutter->GetOutput() );
249 
250  implicitFunction->Delete();
251  cutter->Delete();
252  sphere->Delete();
253 
254  return output;
255 }
256 
257 //--------------------------------------------------------------------------
258 
259 //--------------------------------------------------------------------------
260 vtkPolyData *
261 QGoFilterShape::GenerateCube(double *iCenter, double iRadius,
262  vtkSmartPointer< vtkImageData > iImage)
263 {
264  // time consuming
265  /*
266  double* bounds = this->getInput()->GetBounds();
267  double radius = this->getRadius();
268 
269  double xmin = iCenter[0] - radius;
270  double xmax = iCenter[0] + radius;
271  double ymin = iCenter[1] - radius;
272  double ymax = iCenter[1] + radius;
273  double zmin = iCenter[2] - radius;
274  double zmax = iCenter[2] + radius;
275 
276  // Check Borders
277  if( xmin < bounds[0])
278  {
279  xmin = bounds[0];
280  }
281  if( ymin < bounds[2])
282  {
283  ymin = bounds[2];
284  }
285  if( zmin < bounds[4])
286  {
287  zmin = bounds[4];
288  }
289  if( xmax > bounds[1])
290  {
291  xmax = bounds[1];
292  }
293  if( ymax > bounds[3])
294  {
295  ymax = bounds[3];
296  }
297  if( zmax > bounds[5])
298  {
299  zmax = bounds[5];
300  }
301 */
302 
303  // create cube geometry
304  vtkCubeSource *cube = vtkCubeSource::New();
305 
306  cube->SetCenter(iCenter);
307  cube->SetXLength( 2 * iRadius);
308  cube->SetYLength( 2 * iRadius);
309  cube->SetZLength( 2 * iRadius);
310  cube->Update();
311  cube->GetOutput()->GetPointData()->SetNormals(NULL);
312 
313  vtkTriangleFilter *triangle = vtkTriangleFilter::New();
314  triangle->SetInput( cube->GetOutput() );
315  triangle->Update();
316 
317  // Deal with borders
318  vtkBox *implicitFunction = vtkBox::New();
319  implicitFunction->SetBounds( iImage->GetBounds() );
320 
321  vtkClipPolyData *cutter = vtkClipPolyData::New();
322  cutter->SetInput( triangle->GetOutput() );
323  cutter->InsideOutOn();
324  cutter->SetClipFunction(implicitFunction);
325  cutter->Update();
326 
327  vtkPolyData *output = vtkPolyData::New();
328  output->DeepCopy( cutter->GetOutput() );
329 
330  implicitFunction->Delete();
331  cutter->Delete();
332  triangle->Delete();
333  cube->Delete();
334 
335  return output;
336 }
337 
338 //--------------------------------------------------------------------------
339 
340 //--------------------------------------------------------------------------
341 vtkPolyData *
343 {
344  // create cube geometry
345  vtkCylinderSource *cylinder = vtkCylinderSource::New();
346 
347  cylinder->SetHeight( 2 * getRadius() );
348  cylinder->SetRadius( getRadius() );
349  cylinder->SetCenter(iCenter);
350  cylinder->SetResolution(10);
351  cylinder->Update();
352  cylinder->GetOutput()->GetPointData()->SetNormals(NULL);
353 
354  vtkTriangleFilter *triangle = vtkTriangleFilter::New();
355  triangle->SetInput( cylinder->GetOutput() );
356 
357  vtkPolyData *output = vtkPolyData::New();
358  output->DeepCopy( triangle->GetOutput() );
359 
360  triangle->Delete();
361  cylinder->Delete();
362 
363  return output;
364 }
365 //--------------------------------------------------------------------------
366 
367 //--------------------------------------------------------------------------
368 std::vector<vtkPolyData *> QGoFilterShape::ApplyFilter3D(
369  double iRadius, std::vector< vtkPoints* >* iPoints, std::string iShape,
370  GoImageProcessor* iImages,
371  int iChannel)
372 {
373  std::vector<vtkPolyData*> oMeshes = std::vector<vtkPolyData*>();
374  if ( iRadius <= 0 )
375  {
376  std::cerr << "Radius should be > 0 " << std::endl;
377  return oMeshes;
378  }
379 
380  vtkImageData* temp_image = iImages->getImageBW(iChannel);
381 
382  double center2[3];
383 
384  for ( size_t id = 0; id < iPoints->size(); id++ )
385  {
386  // LOOP FOR EACH SEED
387  for ( vtkIdType i = 0; i < (*iPoints)[id]->GetNumberOfPoints(); i++ )
388  {
389  (*iPoints)[id]->GetPoint(i, center2);
390 
391  // useful to translate the polydata afterwards
392  setCenter(center2);
393 
394  vtkPolyData * MeshPolydata = NULL;
395 
396  if (iShape == "Sphere")
397  {
398  MeshPolydata = GenerateSphere( center2, iRadius, temp_image );
399  }
400  else
401  {
402  if (iShape == "Cube")
403  {
404  MeshPolydata = GenerateCube( center2, iRadius, temp_image );
405  }
406  else
407  {
408  std::cout<<"doesn't know the chosen shape ";
409  std::cout << "Debug: In " << __FILE__ << ", line " << __LINE__;
410  std::cout << std::endl;
411  }
412  }
413  oMeshes.push_back(MeshPolydata);
414  }
415  }
416  return oMeshes;
417 }
418 //--------------------------------------------------------------------------
419 
420 //--------------------------------------------------------------------------
421 std::vector<std::vector<vtkPolyData*> > QGoFilterShape::
422  ApplyFilterSetOf2D(double iRadius,
423  std::string iShape, int iSampling,
424  std::vector< vtkPoints* >* iPoints,
425  GoImageProcessor* iImages, int iChannel)
426 {
427  std::vector<std::vector<vtkPolyData*> > oSetOfContours =
428  std::vector<std::vector<vtkPolyData*> >();
429 
430 
431  return oSetOfContours;
432 }
vtkPolyData * GenerateCylinder(double *iCenter)
QString & append(QChar ch)
double * getCenter()
Get the center of the area to be segmented.
void CreateCorrespondingMesh(int)
vtkSmartPointer< vtkImageData > getInput()
virtual void ConnectSignals(int iFilterNumber)
void MeshCreated(vtkPolyData *, int timePoint=0)
void ContourCreated(vtkPolyData *)
int getChannel()
Get the channel to be segmented.
vtkPolyData * ReorganizeContour(vtkPolyData *iInputImage=NULL, bool iDecimate=true)
vtkSmartPointer< vtkImageData > getImageBW(const std::string &iName)
get raw (not colored) image given index
virtual void ConnectSignals(int iFilterNumber)
const char * name() const
QString number(int n, int base)
vtkPolyData * GenerateCube(double *iCenter, double iRadius, vtkSmartPointer< vtkImageData > iImage)
~QGoFilterShape()
Destructor.
QGoFilterShape(QObject *iParent=NULL, int iDimension=2)
Constructor.
void AddContourForMeshToContours(vtkPolyData *)
QWidget * getWidget()
Get the widget associated to the filter.
vtkPolyData * GenerateSphere(double *iCenter, double iRadius, vtkSmartPointer< vtkImageData > iImage)
void setCenter(double *iCenter)
std::vector< vtkPolyData * > ApplyFilter3D(double iRadius, std::vector< vtkPoints * > *iPoints, std::string iShape, GoImageProcessor *iImages, int iChannel)
return the polydatas corresponding to the new created Shapes
Connects the common signals regarding the seeds segmentation Provides methods to convert images from ...
Interface between image reader and vtkImageData.
virtual vtkPolyData * Apply()
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
double getRadius()
Get the radius of the area to be segmented.
std::vector< std::vector< vtkPolyData * > > ApplyFilterSetOf2D(double iRadius, std::string iShape, int iSampling, std::vector< vtkPoints * > *iPoints, GoImageProcessor *iImages, int iChannel)