anatomist 6.0.4
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>
46#include <aims/mesh/surfaceOperation.h>
47#include <aims/io/writer.h>
48#include <aims/io/reader.h>
49#include <qtranslator.h>
50
51namespace
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
90}
91
92
93namespace anatomist
94{
95
96 template<int D>
97 ASurface<D>::ASurface( const char * )
98 : AGLObject(), _surface( 0 ), _planar( false )
99 {
103template<int D>
105 const anatomist::ViewState& viewState )
107 return anatomist::AObject::render( primitiveList, viewState );
108}
109
111template<int D>
113 const anatomist::GLList& glList ) const
114{
115 return AGLObject::glMakeBodyGLL(viewState, glList);
116}
118 template<int D>
121 cleanup();
125
126 template <int D>
128 {
129 ASurface<D> *s = new ASurface<D>;
130 s->setFileName( fileName() );
131 if( shallow )
132 s->setSurface( surface() );
133 else
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;
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 }
258 setChanged();
259 if( !hasold )
261 }
262
263
264 template<int D>
266 {
267 bool hasold = _surface.get() != 0;
268 freeSurface();
269 _surface.reset( surf );
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 }
289 setChanged();
290 if( !hasold )
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 );
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 {
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>
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>
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 {
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>
597
598
599}
600
601
602#endif
const std::vector< Point3df > & normal() const
const std::vector< AimsVector< uint, D > > & polygon() const
const std::vector< Point3df > & vertex() const
const aims::PythonHeader & header() const
std::map< int, AimsSurface< D, T > >::const_iterator const_iterator
const std::vector< Point3df > & normal() const
std::map< int, AimsSurface< D, T > >::iterator iterator
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 > &)
virtual void glSetChanged(glPart, bool=true) const
Base Anatomist object (abstract)
Definition Object.h:97
void setFileName(const std::string &filename)
virtual std::vector< float > voxelSize() const
Returns at least 4 sizes. For 3D objects, returns (1, 1, 1, 1)
virtual void SetMaterial(const Material &mat)
virtual Tree * optionTree() const
Menu tree for new options, see object/optionMatcher.h.
virtual void storeHeaderOptions()
Store some object properties into the header (.minf), such as material, palette etc before saving the...
virtual bool render(PrimList &, const ViewState &)
rendering (generally 2D or 3D using OpenGL).
virtual std::string objectFullTypeName(void) const
Get Object Full Type Name.
Definition Object.h:419
virtual void cleanup()
must be called by objects destructors - Must be explicitly called by each object destructor since it ...
int _type
Should be static in each object class.
Definition Object.h:502
std::string fileName() const
File name (if any) for loaded objects.
Definition Object.h:168
void setHeaderOptions()
Set some object properties according to the header (.minf), such as material, palette etc.
virtual Material & GetMaterial()
Definition Object.h:235
static void setObjectMenu(std::string type, carto::rc_ptr< ObjectMenu > om)
Definition Object.h:465
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
carto::rc_ptr< TimeSurfaceType > _surface
Definition surface.h:127
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
const carto::rc_ptr< TimeSurfaceType > surface() const
Definition surface.h:76
AimsSurface< D, Void > SurfaceType
Definition surface.h:59
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
AimsTimeSurface< D, Void > TimeSurfaceType
Definition surface.h:60
virtual void setInternalsChanged()
Notifies some underlying lower-level objects have changed.
Definition surface_d.h:590
void setupShader()
create, setup, or remove the shader
@ glGEOMETRY
Geometry is the polygons, normals arrays.
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)
void setChanged() const
Indicates that this object has changed.
Definition Observable.h:184
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:74
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)
AimsVector< float, 3 > Point3df