anatomist  5.1.2
3D neuroimaging data viewer
surface_d.h
Go to the documentation of this file.
1 /* This software and supporting documentation are distributed by
2  * Institut Federatif de Recherche 49
3  * CEA/NeuroSpin, Batiment 145,
4  * 91191 Gif-sur-Yvette cedex
5  * France
6  *
7  * This software is governed by the CeCILL-B license under
8  * French law and abiding by the rules of distribution of free software.
9  * You can use, modify and/or redistribute the software under the
10  * terms of the CeCILL-B license as circulated by CEA, CNRS
11  * and INRIA at the following URL "http://www.cecill.info".
12  *
13  * As a counterpart to the access to the source code and rights to copy,
14  * modify and redistribute granted by the license, users are provided only
15  * with a limited warranty and the software's author, the holder of the
16  * economic rights, and the successive licensors have only limited
17  * liability.
18  *
19  * In this respect, the user's attention is drawn to the risks associated
20  * with loading, using, modifying and/or developing or reproducing the
21  * software by the user in light of its specific status of free software,
22  * that may mean that it is complicated to manipulate, and that also
23  * therefore means that it is reserved for developers and experienced
24  * professionals having in-depth computer knowledge. Users are therefore
25  * encouraged to load and test the software's suitability as regards their
26  * requirements in conditions enabling the security of their systems and/or
27  * data to be ensured and, more generally, to use and operate it in the
28  * same conditions as regards security.
29  *
30  * The fact that you are presently reading this means that you have had
31  * knowledge of the CeCILL-B license and that you accept its terms.
32  */
33 
34 #ifndef ANA_SURFACE_SURFACE_D_H
35 #define ANA_SURFACE_SURFACE_D_H
36 
37 
38 #include <cstdlib>
45 #include <graph/tree/tree.h>
47 #include <aims/io/writer.h>
48 #include <aims/io/reader.h>
49 #include <qtranslator.h>
50 
51 namespace
52 {
53 
54  template <int D> inline
55  void _completeMeshDirections( AimsTimeSurface<D, Void> & )
56  {
57  }
58 
59 
60  template <> inline
61  void _completeMeshDirections( AimsTimeSurface<2, Void> & surf )
62  {
63  if( surf.normal().empty() )
64  {
65  try
66  {
67  carto::Object mat = surf.header().getProperty( "material" );
68  carto::Object cnorm = mat->getProperty( "shader_color_normals" );
69  if( cnorm->getScalar() )
70  {
71  carto::Object nisd = mat->getProperty( "normal_is_direction" );
72  if( nisd->getScalar() )
73  {
74  std::cout << "normal_is_direction ON\n";
75  std::vector<AimsVector<float, 3> > *dirs
77  std::cout << "generate dirs: " << dirs->size() << std::endl;
78  surf.normal() = *dirs;
79  delete dirs;
80  }
81  }
82  }
83  catch( ... )
84  {
85  }
86  }
87  }
88 
89 
90 }
91 
92 
93 namespace anatomist
94 {
95 
96  template<int D>
97  ASurface<D>::ASurface( const char * )
98  : AGLObject(), _surface( 0 ), _planar( false )
99  {
101  }
102 
103 template<int D>
105  const anatomist::ViewState& viewState )
106 {
107  return anatomist::AObject::render( primitiveList, viewState );
108 }
109 
110 
111 template<int D>
113  const anatomist::GLList& glList ) const
114 {
115  return AGLObject::glMakeBodyGLL(viewState, glList);
116 }
117 
118  template<int D>
120  {
121  cleanup();
122  freeSurface();
123  }
124 
125 
126  template <int D>
127  AObject* ASurface<D>::clone( bool shallow )
128  {
129  ASurface<D> *s = new ASurface<D>;
130  s->setFileName( fileName() );
131  if( shallow )
132  s->setSurface( surface() );
133  else
134  s->setSurface( new TimeSurfaceType( *surface() ) );
135  return s;
136  }
137 
138 
139  template<int D>
141  {
142  _surface.reset( 0 );
143  }
144 
145 
146  template<int D>
147  const typename ASurface<D>::SurfaceType*
148  ASurface<D>::surfaceOfTime( float time ) const
149  {
150  if( !_surface )
151  return 0;
152 
153  unsigned t = (unsigned) ( time / voxelSize()[3] );
154  typename TimeSurfaceType::const_iterator is = _surface->lower_bound( t );
155 
156  if( is == _surface->end() )
157  {
158  if( is != _surface->begin() )
159  --is;
160  }
161  return( &(*is).second );
162  }
163 
164 
165  template<int D>
167  {
168  if( !_surface )
169  return 0;
170 
171  unsigned t = (unsigned) ( time / voxelSize()[3] );
172 
173  if( _surface->empty() )
174  return( &(*_surface)[t] );
175 
176  typename TimeSurfaceType::iterator is = _surface->lower_bound( t );
177 
178  if( is == _surface->end() )
179  {
180  if( is != _surface->begin() )
181  --is;
182  }
183  return( &(*is).second );
184  }
185 
186 
187  template<int D>
189  {
190  _surface->setMini();
191  _surface->setMaxi();
192  _planar = true;
193 
194  const std::vector<Point3df> & norm = _surface->normal();
195  std::vector<Point3df>::size_type i, n = norm.size();
196  if( n < _surface->vertex().size() )
197  _surface->updateNormals();
198  if( n < 2 )
199  return;
200  Point3df nref = norm[0];
201  const float eps = 1e-5;
202 
203  for( i=1; i<n; ++i )
204  if( fabs( norm[i][0] - nref[0] ) > eps
205  || fabs( norm[i][1] - nref[1] ) > eps
206  || fabs( norm[i][2] - nref[2] ) > eps )
207  {
208  _planar = false;
209  break;
210  }
211  //cout << name() << " - planar: " << _planar << endl;
212  }
213 
214 
215  template<int D>
216  float ASurface<D>::MaxT() const
217  {
218  if( !_surface || _surface->size() == 0 )
219  return( 0. );
220  return( voxelSize()[3] * (*_surface->rbegin()).first );
221  }
222 
223 
224  template<int D>
225  float ASurface<D>::MinT() const
226  {
227  if( !_surface || _surface->size() == 0 )
228  return( 0. );
229  return( voxelSize()[3] * (*_surface->begin()).first );
230  }
231 
232 
233  template<int D>
235  {
236  bool hasold = _surface.get() != 0;
237  freeSurface();
238  _surface = surf;
239  UpdateMinAndMax();
240  _completeMeshDirections( *surf );
241  if( D == 2 && !_surface->normal().empty() )
242  {
243  GetMaterial().setRenderProperty( Material::UseShader, 1 );
244  GetMaterial().setRenderProperty( Material::NormalIsDirection, 1 );
245  setupShader();
246  }
247  try
248  {
249  carto::Object omat = _surface->header().getProperty( "material" );
250  Material & mat = GetMaterial();
251  mat.set( *omat );
252  SetMaterial( mat );
253  }
254  catch( ... )
255  {
256  }
257  glSetChanged( glGEOMETRY );
258  setChanged();
259  if( !hasold )
260  setHeaderOptions();
261  }
262 
263 
264  template<int D>
266  {
267  bool hasold = _surface.get() != 0;
268  freeSurface();
269  _surface.reset( surf );
270  UpdateMinAndMax();
271  _completeMeshDirections( *surf );
272  if( D == 2 && !_surface->normal().empty() )
273  {
274  GetMaterial().setRenderProperty( Material::UseShader, 1 );
275  GetMaterial().setRenderProperty( Material::NormalIsDirection, 1 );
276  setupShader();
277  }
278  try
279  {
280  carto::Object omat = _surface->header().getProperty( "material" );
281  Material & mat = GetMaterial();
282  mat.set( *omat );
283  SetMaterial( mat );
284  }
285  catch( ... )
286  {
287  }
288  glSetChanged( glGEOMETRY );
289  setChanged();
290  if( !hasold )
291  setHeaderOptions();
292  }
293 
294 
295  template<int D>
296  unsigned ASurface<D>::glNumVertex( const ViewState & s ) const
297  {
298  const SurfaceType *surf = surfaceOfTime( s.timedims[0] );
299 
300  if( !surf )
301  return 0;
302  return surf->vertex().size();
303  }
304 
305 
306  template<int D>
307  const GLfloat* ASurface<D>::glVertexArray( const ViewState & s ) const
308  {
309  const SurfaceType *surf = surfaceOfTime( s.timedims[0] );
310 
311  if( !surf )
312  return 0;
313  return &surf->vertex()[0][0];
314  }
315 
316 
317  template<int D>
318  unsigned ASurface<D>::glNumNormal( const ViewState & s ) const
319  {
320  const SurfaceType *surf = surfaceOfTime( s.timedims[0] );
321 
322  if( !surf )
323  return 0;
324  return surf->normal().size();
325  }
326 
327 
328  template<int D>
329  const GLfloat* ASurface<D>::glNormalArray( const ViewState & s ) const
330  {
331  const SurfaceType *surf = surfaceOfTime( s.timedims[0] );
332 
333  if( !surf )
334  return( 0 );
335  const std::vector<Point3df> & n = surf->normal();
336  if( n.size() < surf->vertex().size() )
337  return 0;
338  return( &n[0][0] );
339  }
340 
341 
342  template<int D>
343  const GLuint* ASurface<D>::glPolygonArray( const ViewState & s ) const
344  {
345  const SurfaceType *surf = surfaceOfTime( s.timedims[0] );
346 
347  if( !surf )
348  return( 0 );
349  return( (GLuint *) &surf->polygon()[0][0] );
350  }
351 
352 
353  template<int D>
354  unsigned ASurface<D>::glNumPolygon( const ViewState & s ) const
355  {
356  const SurfaceType *surf = surfaceOfTime( s.timedims[0] );
357 
358  if( !surf )
359  return( 0 );
360  return( surf->polygon().size() );
361  }
362 
363 
364  template<int D>
366  {
367  static Tree* _optionTree = 0;
368 
369  if( !_optionTree )
370  {
371  Tree *t, *t2;
372  _optionTree = new Tree( true, "option tree" );
373  t = new Tree( true, QT_TRANSLATE_NOOP( "QSelectMenu", "File" ) );
374  _optionTree->insert( t );
375  t2 = new Tree( true, QT_TRANSLATE_NOOP( "QSelectMenu", "Reload" ) );
376  t2->setProperty( "callback", &ObjectActions::fileReload );
377  t->insert( t2 );
378  t2 = new Tree( true, QT_TRANSLATE_NOOP( "QSelectMenu", "Save" ) );
379  t2->setProperty( "callback", &ObjectActions::saveStatic );
380  t->insert( t2 );
381  t2 = new Tree( true, QT_TRANSLATE_NOOP( "QSelectMenu",
382  "Rename object" ) );
383  t2->setProperty( "callback", &ObjectActions::renameObject );
384  t->insert( t2 );
385  t2 = new Tree( true,
386  QT_TRANSLATE_NOOP( "QSelectMenu",
387  "Create generated 1D texture" ) );
388  t2->setProperty( "callback", &ObjectActions::generateTexture1D );
389  t->insert( t2 );
390  t2 = new Tree( true,
391  QT_TRANSLATE_NOOP( "QSelectMenu",
392  "Create generated 2D texture" ) );
393  t2->setProperty( "callback", &ObjectActions::generateTexture2D );
394  t->insert( t2 );
395 
396  t = new Tree( true, QT_TRANSLATE_NOOP( "QSelectMenu", "Color" ) );
397  _optionTree->insert( t );
398  t2 = new Tree( true, QT_TRANSLATE_NOOP( "QSelectMenu", "Material" ) );
399  t2->setProperty( "callback", &ObjectActions::colorMaterial );
400  t->insert( t2 );
401  t2 = new Tree( true, QT_TRANSLATE_NOOP( "QSelectMenu", "Rendering" ) );
402  t2->setProperty( "callback", &ObjectActions::colorRendering);
403  t->insert( t2 );
404  t = new Tree( true, QT_TRANSLATE_NOOP( "QSelectMenu",
405  "Referential" ) );
406  _optionTree->insert( t );
407  t2 = new Tree( true, QT_TRANSLATE_NOOP( "QSelectMenu", "Load" ) );
408  t2->setProperty( "callback", &ObjectActions::referentialLoad );
409  t->insert( t2 );
410  t2 = new Tree( true, QT_TRANSLATE_NOOP( "QSelectMenu",
411  "Load information from file header") );
412  t2->setProperty( "callback", &ObjectActions::setAutomaticReferential );
413  t->insert( t2 );
414  t = new Tree( true, QT_TRANSLATE_NOOP( "QSelectMenu", "Geometry" ) );
415  _optionTree->insert( t );
416  t2 = new Tree( true,
417  QT_TRANSLATE_NOOP( "QSelectMenu",
418  "Invert polygon orientation" ) );
419  t2->setProperty( "callback", &invertPolygonsStatic );
420  t->insert( t2 );
421  setObjectMenu( objectFullTypeName(),
423  ( new ObjectMenu( *_optionTree ) ));
424  }
425  return AObject::optionTree();
426  }
427 
428 
429  template<int D>
430  AObject* ASurface<D>::objectAt( const std::vector<float> &, float )
431  {
432  return 0;
433  }
434 
435 
436  template<int D>
437  bool ASurface<D>::save( const std::string & filename )
438  {
439  if( !_surface )
440  return false;
441 
442  try
443  {
444  storeHeaderOptions();
445  aims::Writer<TimeSurfaceType> sw( filename );
446  sw << *_surface;
447  }
448  catch( std::exception & e )
449  {
450  std::cerr << e.what() << "\nsave aborted\n";
451  return false;
452  }
453  return true;
454  }
455 
456 
457  template<int D>
458  bool ASurface<D>::reload( const std::string & filename )
459  {
460  aims::Reader<TimeSurfaceType> reader( filename );
462  if( !reader.read( *obj ) )
463  return false;
464 
465  setSurface( obj );
466  return true;
467  }
468 
469 
470  template<int D>
471  void ASurface<D>::invertPolygonsStatic( const std::set<AObject *> & obj )
472  {
473  std::set<AObject *>::const_iterator io, fo=obj.end();
474 
475  for( io=obj.begin(); io!=fo; ++io )
476  ((ASurface<D> *) *io)->invertPolygons();
477  }
478 
479 
480  template<int D>
482  {
484  glSetChanged( glGEOMETRY );
485  setChanged();
486  notifyObservers( this );
487  }
488 
489 
490  template<int D>
491  bool ASurface<D>::boundingBox( std::vector<float> & bmin,
492  std::vector<float> & bmax ) const
493  {
494  if( !_surface )
495  return( false );
496 
497  bmin.resize( 4 );
498  bmax.resize( 4 );
499  Point3df bminp = _surface->minimum();
500  Point3df bmaxp = _surface->maximum();
501  if( bminp == Point3df( 1e38, 1e38, 1e38 )
502  && bmaxp == Point3df( -1e38, -1e38, -1e38) )
503  {
504  // empty meshes return a crappy bounding box...
505  bmin[3] = 0.f;
506  bmax[3] = 0.f;
507  return false;
508  }
509  bmin[0] = bminp[0];
510  bmin[1] = bminp[1];
511  bmin[2] = bminp[2];
512  bmax[0] = bmaxp[0];
513  bmax[1] = bmaxp[1];
514  bmax[2] = bmaxp[2];
515  if( _surface->empty() )
516  {
517  bmin[3] = 0.f;
518  bmax[3] = 0.f;
519  }
520  else
521  {
522  float timestep = voxelSize()[3];
523  bmin[3] = _surface->begin()->first * timestep;
524  bmax[3] = _surface->rbegin()->first * timestep;
525  }
526  return true;
527  }
528 
529 
530  template<int D>
531  float ASurface<D>::actualTime( float time ) const
532  {
533  if( !_surface )
534  return( 0 );
535 
536  float ts = voxelSize()[3];
537  unsigned t = (unsigned) ( time / ts );
538  typename TimeSurfaceType::const_iterator is = _surface->lower_bound( t );
539 
540  if( is == _surface->end() )
541  is = _surface->begin();
542  return( is->first * ts );
543  }
544 
545 
546  template<int D>
547  void ASurface<D>::notifyObservers( void * arg )
548  {
550  glSetChanged( glGEOMETRY, false );
551  }
552 
553 
554  template<int D>
555  unsigned ASurface<D>::glPolygonSize( const ViewState & ) const
556  {
557  return D;
558  }
559 
560 
561  template<int D>
563  {
564  if( _surface )
565  {
566  aims::PythonHeader *ah
567  = dynamic_cast<aims::PythonHeader *>( &_surface->header() );
568  if( ah )
569  return ah;
570  }
571  return 0;
572  }
573 
574 
575  template<int D>
577  {
578  if( _surface )
579  {
580  const aims::PythonHeader *ah
581  = dynamic_cast<const aims::PythonHeader *>( &_surface->header() );
582  if( ah )
583  return ah;
584  }
585  return 0;
586  }
587 
588 
589  template <int D>
591  {
592  UpdateMinAndMax();
593  glSetChanged( glGEOMETRY );
594  setChanged();
595  setHeaderOptions();
596  }
597 
598 
599 }
600 
601 
602 #endif
const std::vector< Point3df > & normal() const
const std::vector< Point3df > & vertex() const
const std::vector< AimsVector< uint, D > > & polygon() const
std::map< int, AimsSurface< D, T > >::iterator iterator
const aims::PythonHeader & header() const
std::map< int, AimsSurface< D, T > >::const_iterator const_iterator
const std::vector< Point3df > & normal() const
iterator begin()
void insert(BaseTree *child, int index=-1)
virtual bool read(T &obj, int border=0, const std::string *format=0, int frame=-1)
static void invertSurfacePolygons(AimsTimeSurface< D, T > &surface)
static std::vector< Point3df > * lineDirections(const AimsTimeSurface< 2, Void > &)
Base Anatomist object (abstract)
Definition: Object.h:96
void setFileName(const std::string &filename)
virtual Tree * optionTree() const
Menu tree for new options, see object/optionMatcher.h.
virtual bool render(PrimList &, const ViewState &)
rendering (generally 2D or 3D using OpenGL).
int _type
Should be static in each object class.
Definition: Object.h:453
Template surface type.
Definition: surface.h:55
virtual void notifyObservers(void *=0)
If this object has changed, as indicated by the hasChanged method, then notify all of its observers.
Definition: surface_d.h:547
virtual bool render(anatomist::PrimList &primitiveList, const anatomist::ViewState &viewState)
rendering (generally 2D or 3D using OpenGL).
Definition: surface_d.h:104
virtual unsigned glNumPolygon(const ViewState &) const
Definition: surface_d.h:354
virtual bool glMakeBodyGLL(const anatomist::ViewState &viewState, const anatomist::GLList &glList) const
If you want to make a non-standard GL display list for the body geometry, overload this function to f...
Definition: surface_d.h:112
virtual bool save(const std::string &filename)
Definition: surface_d.h:437
virtual Tree * optionTree() const
Menu tree for new options, see object/optionMatcher.h.
Definition: surface_d.h:365
void setSurface(carto::rc_ptr< TimeSurfaceType > surf)
Definition: surface_d.h:234
virtual unsigned glPolygonSize(const ViewState &) const
number of vertices per polygon (default = 3: triangles)
Definition: surface_d.h:555
const SurfaceType * surfaceOfTime(float time) const
Definition: surface_d.h:148
virtual const GLfloat * glVertexArray(const ViewState &) const
Definition: surface_d.h:307
virtual const GLuint * glPolygonArray(const ViewState &) const
Definition: surface_d.h:343
ASurface(const char *filename="")
Definition: surface_d.h:97
virtual carto::GenericObject * attributed()
Definition: surface_d.h:562
virtual float MinT() const
Obsolete, deprecated.
Definition: surface_d.h:225
virtual bool reload(const std::string &filename)
Re-reads objects from disk.
Definition: surface_d.h:458
virtual unsigned glNumNormal(const ViewState &) const
Definition: surface_d.h:318
virtual AObject * clone(bool shallow=true)
Makes a copy of the object, with a duplicated object structure, palette and material,...
Definition: surface_d.h:127
virtual bool boundingBox(std::vector< float > &bmin, std::vector< float > &bmax) const
Fills bmin and bmax with the N-D bounding box extrema in the object's referential coordinates.
Definition: surface_d.h:491
virtual float MaxT() const
Obsolete, deprecated.
Definition: surface_d.h:216
virtual AObject * objectAt(const std::vector< float > &pos, float tol=0)
selection is disabled for surfaces
Definition: surface_d.h:430
static void invertPolygonsStatic(const std::set< AObject * > &obj)
Definition: surface_d.h:471
float actualTime(float time) const
Definition: surface_d.h:531
virtual unsigned glNumVertex(const ViewState &) const
Definition: surface_d.h:296
virtual void UpdateMinAndMax()
Definition: surface_d.h:188
virtual const GLfloat * glNormalArray(const ViewState &) const
normals array (optional), default=0 (no normals, flat shaded faces)
Definition: surface_d.h:329
virtual void setInternalsChanged()
Notifies some underlying lower-level objects have changed.
Definition: surface_d.h:590
virtual bool glMakeBodyGLL(const ViewState &state, const GLList &gllist) const
If you want to make a non-standard GL display list for the body geometry, overload this function to f...
This class has to be rewritten, it's really really a shame.......
Definition: Material.h:48
void set(const carto::GenericObject &)
@ NormalIsDirection
if set, the normal in a mesh is actually its wireframe direction, and interpreted as if the wireframe...
Definition: Material.h:77
static void referentialLoad(const std::set< AObject * > &obj)
static void setAutomaticReferential(const std::set< AObject * > &obj)
static void renameObject(const std::set< AObject * > &obj)
static void fileReload(const std::set< AObject * > &obj)
static void generateTexture1D(const std::set< AObject * > &obj)
static void generateTexture2D(const std::set< AObject * > &obj)
static void colorMaterial(const std::set< AObject * > &obj)
static void saveStatic(const std::set< AObject * > &obj)
static void colorRendering(const std::set< AObject * > &obj)
virtual void notifyObservers(void *arg=0)
If this object has changed, as indicated by the hasChanged method, then notify all of its observers.
virtual bool getProperty(const std::string &, Object &) const
std::list< carto::rc_ptr< GLItem > > PrimList
Definition: Object.h:72
ViewState holds information about how a view wants to see an object.
Definition: viewstate.h:67
std::vector< float > timedims
Definition: viewstate.h:89
AIMSDATA_API float norm(const Tensor &thing)