GOFIGURE2  0.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TrackStructure.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 
35 #include "TrackStructure.h"
36 
37 #include <iostream>
38 #include "vtkPolyData.h"
39 #include "vtkActor.h"
40 
41 #include "vtkDoubleArray.h"
42 #include "vtkPointData.h"
43 
44 #include "vtkProperty.h"
45 
46 #include "vtkSphereSource.h"
47 #include "vtkGlyph3D.h"
48 #include "vtkTubeFilter.h"
49 #include "vtkAppendPolyData.h"
50 #include "vtkMath.h"
51 
52 //--------------------------------------------------------------------------
54 {
55 }
56 
57 //--------------------------------------------------------------------------
58 
59 //--------------------------------------------------------------------------
61  TraceStructure(iE), TreeNode(iE.TreeNode), PointsMap(iE.PointsMap),
62  m_AverageVolume(iE.m_AverageVolume)
63 {
64 }
65 
66 //--------------------------------------------------------------------------
67 
68 //--------------------------------------------------------------------------
71 {
72 }
73 
74 //--------------------------------------------------------------------------
75 
76 //--------------------------------------------------------------------------
77 bool
78 TrackStructure::InsertElement(const unsigned int & iTime, double *iPoint)
79 {
80  // if there is no point, insert it and return true
81  DeleteElement(iTime);
82  this->PointsMap.insert(
83  std::pair< unsigned int, double * >(iTime, iPoint) );
84 
85  return true;
86 }
87 
88 //--------------------------------------------------------------------------
89 
90 //--------------------------------------------------------------------------
91 bool
92 TrackStructure::DeleteElement(const unsigned int & iTime)
93 {
94  // check if there is something at the iTime time point
95  PointsMapIterator pointsMapIterator = this->PointsMap.find(iTime);
96 
97  // if there is a point, delete it and return true
98  if ( pointsMapIterator != this->PointsMap.end() )
99  {
100  // free memory
101  delete[] pointsMapIterator->second;
102  // clear map
103  this->PointsMap.erase(pointsMapIterator);
104  return true;
105  }
106 
107  // else do nothing and return false
108  return false;
109 }
110 
111 //--------------------------------------------------------------------------
112 
113 //--------------------------------------------------------------------------
114 void
116 {
118 
119  PointsMapConstIterator begin = this->PointsMap.begin();
120  PointsMapConstIterator end = this->PointsMap.end();
121 
122  while ( begin != end )
123  {
124  delete[] begin->second;
125  ++begin;
126  }
127 
128  TrackStructure* structure = const_cast<TrackStructure*>(this);
129  structure->TreeNode.ReleaseData();
130 }
131 //--------------------------------------------------------------------------
132 
133 //--------------------------------------------------------------------------
134 void
136 UpdateLineWidth(const double &iWidth) const
137 {
138  if( this->ActorXY )
139  {
140  vtkProperty* property = this->ActorXY->GetProperty();
141 
142  if( property )
143  {
144  property->SetLineWidth( iWidth );
145  }
146  }
147  if( this->ActorXZ )
148  {
149  vtkProperty* property = this->ActorXZ->GetProperty();
150 
151  if( property )
152  {
153  property->SetLineWidth( iWidth );
154  }
155  }
156  if( this->ActorYZ )
157  {
158  vtkProperty* property = this->ActorYZ->GetProperty();
159 
160  if( property )
161  {
162  property->SetLineWidth( iWidth );
163  }
164  }
165  if( this->ActorXYZ )
166  {
167  vtkProperty* property = this->ActorXYZ->GetProperty();
168 
169  if( property )
170  {
171  property->SetLineWidth( iWidth );
172  }
173  }
174 }
175 //--------------------------------------------------------------------------
176 
177 //--------------------------------------------------------------------------
178 void
180 UpdateTracksRepresentation(const double& iRadius,
181  const double& iRadius2) const
182 {
183  vtkSmartPointer< vtkAppendPolyData > apd =
184  vtkSmartPointer< vtkAppendPolyData >::New();
185  apd->AddInput(this->Nodes);
186 
187  if ( iRadius )
188  {
189  vtkSmartPointer< vtkSphereSource > sphere =
190  vtkSmartPointer< vtkSphereSource >::New();
191  sphere->SetThetaResolution(8);
192  sphere->SetPhiResolution(8);
193  sphere->SetRadius(iRadius);
194 
195  vtkSmartPointer< vtkGlyph3D > glyph =
196  vtkSmartPointer< vtkGlyph3D >::New();
197  glyph->SetInput(this->Nodes);
198  glyph->SetSource( sphere->GetOutput() );
199  glyph->Update();
200 
201  apd->AddInput( glyph->GetOutput() );
202  }
203 
204  if ( iRadius2 )
205  {
206  vtkSmartPointer< vtkTubeFilter > tube =
207  vtkSmartPointer< vtkTubeFilter >::New();
208  tube->SetNumberOfSides(8);
209  tube->SetInput(this->Nodes);
210  tube->SetRadius(iRadius2);
211  tube->Update();
212 
213  apd->AddInput( tube->GetOutput() );
214  }
215 
216  apd->Update();
217 
218  this->Nodes->DeepCopy( apd->GetOutput() );
219 }
220 
221 //--------------------------------------------------------------------------
222 
223 //--------------------------------------------------------------------------
226 {
227  GoFigureTrackAttributes oAttributes;
228 
229  // check if there are no points in the map
230  if( PointsMap.empty() )
231  {
232  return oAttributes;
233  }
234 
235  PointsMapConstIterator it = this->PointsMap.begin();
236 
237  unsigned int tmin = it->first;
238  unsigned int t0 = tmin;
239  unsigned int t1 = tmin;
240  double *org = it->second;
241  double *p = it->second;
242  double *q = it->second; // if we only have one point in the map
243 
244  ++it;
245 
246  // reset the array
247  vtkDoubleArray *newArray =
248  dynamic_cast< vtkDoubleArray * >( this->Nodes->GetPointData()->GetArray("SpeedInformation") );
249  newArray->Reset();
250  newArray->InsertNextValue(0.0);
251 
252  while ( it != this->PointsMap.end() )
253  {
254  t1 = it->first;
255  q = it->second;
256  oAttributes.distance = sqrt( vtkMath::Distance2BetweenPoints(p, q) );
257  oAttributes.total_length += oAttributes.distance;
258  oAttributes.max_speed = std::max( oAttributes.max_speed,
259  oAttributes.distance / ( static_cast< double >( t1 - t0 ) ) );
260 
261  double speed = oAttributes.distance / ( static_cast< double >( t1 - t0 ) );
262  newArray->InsertNextValue(speed);
263 
264  p = q;
265  t0 = t1;
266 
267  ++it;
268  }
269 
270  if ( t1 == tmin )
271  {
272  oAttributes.avg_speed = 0.;
273  }
274  else
275  {
276  oAttributes.avg_speed = oAttributes.total_length
277  / static_cast< double >( t1 - tmin );
278  }
279 
280  oAttributes.distance = sqrt( vtkMath::Distance2BetweenPoints(org, q) );
281 
282  if ( oAttributes.distance )
283  {
284  oAttributes.theta = vtkMath::DegreesFromRadians( atan2( ( q[1] - org[1] ),
285  ( q[0] - org[0] ) ) );
286  oAttributes.phi = vtkMath::DegreesFromRadians( acos( ( q[2] - org[2] )
287  / oAttributes.distance ) );
288  }
289 
290  oAttributes.number_meshes = static_cast< unsigned int >( PointsMap.size() );
291 
292  oAttributes.temporal_extent = ( t1 - tmin );
293 
294  oAttributes.avg_volume = this->m_AverageVolume/( static_cast< double >( PointsMap.size() ) );
295 
296  return oAttributes;
297 }
298 
299 //--------------------------------------------------------------------------
300 
301 //--------------------------------------------------------------------------
302 void
304 ModifyDivisionVisibility( const bool& iVisibility )
305 {
306  /*
307  * \todo Nicolas- should we add/remove the actors from the view
308  */
309  this->TreeNode.Visible = iVisibility;
310  this->TreeNode.SetActorVisibility( iVisibility );
311 }
312 //--------------------------------------------------------------------------
313 
314 //--------------------------------------------------------------------------
315 void
317 ModifyDivisionHighlight( vtkProperty* iProperty, const bool& iHighlight )
318 {
319  this->TreeNode.SetActorProperties(iProperty);
320  this->TreeNode.Highlighted = iHighlight;
321 }
322 //--------------------------------------------------------------------------
323 
324 //--------------------------------------------------------------------------
325 void
327 ModifyDivisionColorData( const double* iColor )
328 {
329  this->TreeNode.rgba[0] = iColor[0];
330  this->TreeNode.rgba[1] = iColor[1];
331  this->TreeNode.rgba[2] = iColor[2];
332  this->TreeNode.rgba[3] = iColor[3];
333 }
334 //--------------------------------------------------------------------------
335 
336 //--------------------------------------------------------------------------
337 void
339 ModifyDivisionColorActor( const double* iColor )
340 {
341  if( this->TreeNode.ActorXY )
342  {
343  this->TreeNode.ActorXY->GetProperty()->SetColor(const_cast<double*>(iColor));
344  }
345  if( this->TreeNode.ActorXZ )
346  {
347  this->TreeNode.ActorXZ->GetProperty()->SetColor(const_cast<double*>(iColor));
348  }
349  if( this->TreeNode.ActorYZ )
350  {
351  this->TreeNode.ActorYZ->GetProperty()->SetColor(const_cast<double*>(iColor));
352  }
353  if( this->TreeNode.ActorXYZ )
354  {
355  this->TreeNode.ActorXYZ->GetProperty()->SetColor(const_cast<double*>(iColor));
356  }
357 }
358 //--------------------------------------------------------------------------
359 
360 //--------------------------------------------------------------------------
361 void
363 AddDivisionArray( vtkIntArray* iArray )
364 {
365  /*
366  * \todo Nicolas-Shouldnt be necessary, missing IsLeaf update??
367  */
368  if(this->TreeNode.Nodes)
369  {
370  this->TreeNode.Nodes->GetPointData()->AddArray(iArray);
371  }
372 }
373 //--------------------------------------------------------------------------
374 
375 //--------------------------------------------------------------------------
376 void
378 CreateDivisionNode( vtkPolyData* iNode)
379 {
380  if( !this->TreeNode.Nodes )
381  {
382  this->TreeNode.Nodes = vtkPolyData::New();
383  }
384  this->TreeNode.Nodes->DeepCopy( iNode );
385 }
386 //--------------------------------------------------------------------------
387 
388 //--------------------------------------------------------------------------
389 const bool
391 IsRoot() const
392 {
393  return this->TreeNode.IsRoot();
394 }
395 //--------------------------------------------------------------------------
396 
397 //--------------------------------------------------------------------------
398 const bool
400 IsLeaf() const
401 {
402  return this->TreeNode.IsLeaf();
403 }
404 //--------------------------------------------------------------------------
405 
406 //--------------------------------------------------------------------------
407 void
409 AddVolume(const double& iVolume)
410 {
411  m_AverageVolume += iVolume;
412 
413  // useful for the track editing widget...
414  // temp solution?
415  if(m_AverageVolume < 0)
416  {
417  m_AverageVolume = 0;
418  }
419 }
420 //--------------------------------------------------------------------------
virtual void ReleaseData() const
bool DeleteElement(const unsigned int &iTime)
Delete the point at the current time point.
GoFigureTrackAttributes ComputeAttributes() const
PointsMapType::const_iterator PointsMapConstIterator
void ModifyDivisionHighlight(vtkProperty *iProperty, const bool &iHighlight)
void UpdateTracksRepresentation(const double &iRadius, const double &iRadius2) const
vtkActor * ActorXYZ
void AddVolume(const double &iVolume)
const bool IsLeaf() const
void ReleaseData() const
double m_AverageVolume
void CreateDivisionNode(vtkPolyData *iNode)
TreeNodeStructure< Self > TreeNode
PointsMapType PointsMap
Structure which represent a track, and used for interaction between Visualization and TableWidget...
void ModifyDivisionColorData(const double *iColor)
PointsMapType::iterator PointsMapIterator
void ModifyDivisionVisibility(const bool &iVisibility)
bool InsertElement(const unsigned int &iTime, double *iPoint)
Insert a point at the current time point.
vtkActor * ActorYZ
vtkPolyData * Nodes
void UpdateLineWidth(const double &iWidth) const
vtkActor * ActorXY
void AddDivisionArray(vtkIntArray *iArray)
vtkActor * ActorXZ
void ModifyDivisionColorActor(const double *iColor)
const bool IsRoot() const
Structure which represent a trace (contour, mesh, track, lineage), and used for interaction between V...