Carna  Version 3.0.1
VolumeGridHelper.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 - 2015 Leonid Kostrykin
3  *
4  * Chair of Medical Engineering (mediTEC)
5  * RWTH Aachen University
6  * Pauwelsstr. 20
7  * 52074 Aachen
8  * Germany
9  *
10  */
11 
12 #ifndef VOLUMEGRIDHELPER_H_6014714286
13 #define VOLUMEGRIDHELPER_H_6014714286
14 
16 #include <Carna/Carna.h>
17 #include <Carna/base/Node.h>
18 #include <Carna/base/math.h>
19 #include <Carna/base/VolumeGrid.h>
21 #include <Carna/base/Geometry.h>
22 #include <Carna/base/BoundingBox.h>
23 #include <memory>
24 #include <cmath>
25 
30 namespace Carna
31 {
32 
33 namespace helpers
34 {
35 
36 
37 
38 // ----------------------------------------------------------------------------------
39 // VolumeGridHelperBase
40 // ----------------------------------------------------------------------------------
41 
48 class CARNA_LIB VolumeGridHelperBase
49 {
50 
51 public:
52 
59  const static std::size_t DEFAULT_MAX_SEGMENT_BYTESIZE = 2 * 300 * 300 * 300;
60 
68  VolumeGridHelperBase( const base::math::Vector3ui& nativeResolution );
69 
74 
78  virtual ~VolumeGridHelperBase();
79 
86  virtual void releaseGeometryFeatures() = 0;
87 
91  struct CARNA_LIB Spacing
92  {
96  explicit Spacing( const base::math::Vector3f& millimeters );
97 
102  };
103 
107  struct CARNA_LIB Dimensions
108  {
112  explicit Dimensions( const base::math::Vector3f& millimeters );
113 
118  };
119 
136  virtual base::Node* createNode( unsigned int geometryType, const Spacing& spacing ) const = 0;
137 
153  virtual base::Node* createNode( unsigned int geometryType, const Dimensions& dimensions ) const = 0;
154 
158  virtual void loadData( const std::function< base::HUV( const base::math::Vector3ui& ) >& data ) = 0;
159 
160 }; // VolumeGridHelperBase
161 
162 
163 
164 // ----------------------------------------------------------------------------------
165 // VolumeGridHelper
166 // ----------------------------------------------------------------------------------
167 
206 template< typename SegmentHUVolumeType, typename SegmentNormalsVolumeType >
207 class VolumeGridHelper
208  : public VolumeGridHelperBase
209  , public details::VolumeGridHelper::HUComponent < SegmentHUVolumeType, SegmentNormalsVolumeType >
210  , public details::VolumeGridHelper::NormalsComponent< SegmentHUVolumeType, SegmentNormalsVolumeType >
211 {
212 
214 
217 
221  std::unique_ptr< base::VolumeGrid< SegmentHUVolumeType, SegmentNormalsVolumeType > > myGrid;
222 
223 public:
224 
225  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
226 
240  VolumeGridHelper( const base::math::Vector3ui& nativeResolution, std::size_t maxSegmentBytesize = DEFAULT_MAX_SEGMENT_BYTESIZE );
241 
245  const std::size_t maxSegmentBytesize;
246 
251 
256 
261 
266 
271 
281  template< typename UnaryVector3uiToHUVFunction >
282  void loadData( const UnaryVector3uiToHUVFunction& data );
283 
286  virtual void loadData( const std::function< base::HUV( const base::math::Vector3ui& ) >& data ) override;
287 
298  virtual void releaseGeometryFeatures() override;
299 
304 
305  virtual base::Node* createNode( unsigned int geometryType, const Spacing& spacing ) const override;
306 
307  virtual base::Node* createNode( unsigned int geometryType, const Dimensions& dimensions ) const override;
308 
309 protected:
310 
311  virtual base::math::Vector3ui gridResolution() const override;
312 
313 private:
314 
316  ( unsigned int geometryType
317  , const Spacing& spacing
318  , const Dimensions& dimensions ) const;
319 
320  static base::math::Vector3ui computeMaxSegmentSize( const base::math::Vector3ui& nativeResolution, std::size_t maxSegmentBytesize );
321 
322 }; // VolumeGridHelper
323 
324 
325 template< typename SegmentHUVolumeType, typename SegmentNormalsVolumeType >
327  ( const base::math::Vector3ui& nativeResolution, std::size_t maxSegmentBytesize )
328 {
329  const float maxSideLengthF = std::pow
330  ( maxSegmentBytesize / static_cast< float >( sizeof( typename SegmentHUVolumeType::Voxel ) ), 1.f / 3 );
331  const unsigned int maxSideLength = base::math::makeEven( base::math::round_ui( maxSideLengthF ), -1 );
332 
333  /* We subtract the redundant texels from effective segment size.
334  * Note that this causes the effective maximum segment size to be odd.
335  */
336  return base::math::Vector3ui( maxSideLength - 1, maxSideLength - 1, maxSideLength - 1 );
337 }
338 
339 
340 template< typename SegmentHUVolumeType, typename SegmentNormalsVolumeType >
342  ( const base::math::Vector3ui& nativeResolution
343  , std::size_t maxSegmentBytesize )
344  : VolumeGridHelperBase( nativeResolution )
345  , maxSegmentBytesize( maxSegmentBytesize )
346  , maxSegmentSize( computeMaxSegmentSize( nativeResolution, maxSegmentBytesize ) )
347  , partitioningX( nativeResolution.x(), maxSegmentSize.x() )
348  , partitioningY( nativeResolution.y(), maxSegmentSize.y() )
349  , partitioningZ( nativeResolution.z(), maxSegmentSize.z() )
350  , resolution( partitioningX.totalSize(), partitioningY.totalSize(), partitioningZ.totalSize() )
351 {
352  const base::math::Vector3ui segmentCounts
353  ( partitioningX.partitionsCount()
354  , partitioningY.partitionsCount()
355  , partitioningZ.partitionsCount() );
356  myGrid.reset( new base::VolumeGrid< SegmentHUVolumeType, SegmentNormalsVolumeType >( maxSegmentSize, segmentCounts ) );
357  NormalsComponent::setGrid( *myGrid );
358 
359  CARNA_FOR_VECTOR3UI( segmentCoord, myGrid->segmentCounts )
360  {
361  /* Here we add the redundant texels to the buffer size considerations.
362  */
363  const base::math::Vector3ui segmentSize
364  ( segmentCoord.x() + 1 == myGrid->segmentCounts.x() ? partitioningX.tailSize : partitioningX.regularPartitionSize + 1
365  , segmentCoord.y() + 1 == myGrid->segmentCounts.y() ? partitioningY.tailSize : partitioningY.regularPartitionSize + 1
366  , segmentCoord.z() + 1 == myGrid->segmentCounts.z() ? partitioningZ.tailSize : partitioningZ.regularPartitionSize + 1 );
367 
368  HUComponent ::initializeSegment( myGrid->segmentAt( segmentCoord ), segmentSize );
369  NormalsComponent::initializeSegment( myGrid->segmentAt( segmentCoord ), segmentSize );
370  }
371 }
372 
373 
374 template< typename SegmentHUVolumeType, typename SegmentNormalsVolumeType >
376 {
377  HUComponent ::releaseGeometryFeatures();
378  NormalsComponent::releaseGeometryFeatures();
379 }
380 
381 
382 template< typename SegmentHUVolumeType, typename SegmentNormalsVolumeType >
383 template< typename UnaryVector3uiToHUVFunction >
385  ( const UnaryVector3uiToHUVFunction& data )
386 {
387  releaseGeometryFeatures();
388  CARNA_FOR_VECTOR3UI( coord, resolution )
389  {
390  const bool outOfNativeBounds
391  = coord.x() >= nativeResolution.x()
392  || coord.y() >= nativeResolution.y()
393  || coord.z() >= nativeResolution.z();
394  const base::HUV huv = outOfNativeBounds ? -1024 : data( coord );
395  myGrid->template setVoxel< typename base::VolumeGrid< SegmentHUVolumeType, SegmentNormalsVolumeType >::HUVSelector >( coord, huv );
396  }
397  NormalsComponent::computeNormals();
398 }
399 
400 
401 template< typename SegmentHUVolumeType, typename SegmentNormalsVolumeType >
403  ( const std::function< base::HUV( const base::math::Vector3ui& ) >& data )
404 {
405  loadData< std::function< base::HUV( const base::math::Vector3ui& ) > >( data );
406 }
407 
408 
409 template< typename SegmentHUVolumeType, typename SegmentNormalsVolumeType >
412 {
413  return *myGrid;
414 }
415 
416 
417 template< typename SegmentHUVolumeType, typename SegmentNormalsVolumeType >
419  ( unsigned int geometryType, const Spacing& spacing, const Dimensions& dimensions ) const
420 {
421  /* Compute dimensions of a regular grid segment,
422  * taking the redundant texels into account.
423  */
424  const base::math::Vector3f regularSegmentDimensions = dimensions.millimeters.cwiseMin( base::math::Vector3f
425  ( spacing.millimeters.x() * partitioningX.regularPartitionSize
426  , spacing.millimeters.y() * partitioningY.regularPartitionSize
427  , spacing.millimeters.z() * partitioningZ.regularPartitionSize ) );
428 
429  /* Create pivot node that shifts it's children to a corner.
430  */
431  base::Node* const pivot = new base::Node();
432  pivot->localTransform = base::math::translation4f( ( regularSegmentDimensions - dimensions.millimeters ) / 2 );
433  pivot->setMovable( false );
434 
435  /* Create geometry nodes for all grid segments.
436  */
437  CARNA_FOR_VECTOR3UI( segmentCoord, myGrid->segmentCounts )
438  {
439  const base::VolumeSegment< SegmentHUVolumeType, SegmentNormalsVolumeType >& segment = myGrid->segmentAt( segmentCoord );
440 
441  /* Compute dimensions of particular grid segment.
442  */
443  const bool isTail =
444  segmentCoord.x() + 1 == myGrid->segmentCounts.x()
445  || segmentCoord.y() + 1 == myGrid->segmentCounts.y()
446  || segmentCoord.z() + 1 == myGrid->segmentCounts.z();
447  const base::math::Vector3ui& volumeSize = segment.huVolume().size;
448  const base::math::Vector3f dimensions = !isTail ? regularSegmentDimensions
449  : ( ( volumeSize.cast< int >() - base::math::Vector3i( 1, 1, 1 ) )
450  .cast< float >().cwiseProduct( spacing.millimeters ) );
451 
452  /* Create geometry node for particular grid segment.
453  */
454  base::Geometry* const geom = new base::Geometry( geometryType );
455  pivot->attachChild( geom );
456  HUComponent ::attachTexture( *geom, segment );
457  NormalsComponent::attachTexture( *geom, segment );
458  geom->setMovable( false );
459  geom->setBoundingVolume( new base::BoundingBox( 1, 1, 1 ) );
460  geom->localTransform
461  = base::math::translation4f( segmentCoord.cast< float >().cwiseProduct( regularSegmentDimensions )
462  - ( !isTail
463  ? base::math::Vector3f( 0, 0, 0 )
464  : ( regularSegmentDimensions - dimensions ) / 2 ) )
465  * base::math::scaling4f( dimensions );
466  }
467 
468  /* We're done.
469  */
470  return pivot;
471 }
472 
473 
474 template< typename SegmentHUVolumeType, typename SegmentNormalsVolumeType >
476  ( unsigned int geometryType, const Spacing& spacing ) const
477 {
478  const base::math::Vector3f dimensions
479  = ( resolution.cast< int >() - base::math::Vector3i( 1, 1, 1 ) ).cast< float >().cwiseProduct( spacing.millimeters );
480  return createNode( geometryType, spacing, Dimensions( dimensions ) );
481 }
482 
483 
484 template< typename SegmentHUVolumeType, typename SegmentNormalsVolumeType >
486  ( unsigned int geometryType, const Dimensions& dimensions ) const
487 {
488  const base::math::Vector3f& mmDimensions = dimensions.millimeters;
489  const base::math::Vector3f spacing
490  = mmDimensions.cast< float >().cwiseQuotient( ( resolution.cast< int >() - base::math::Vector3i( 1, 1, 1 ) ).cast< float >() );
491  return createNode( geometryType, Spacing( spacing ), dimensions );
492 }
493 
494 
495 template< typename SegmentHUVolumeType, typename SegmentNormalsVolumeType >
497 {
498  return resolution;
499 }
500 
501 
502 
503 } // namespace Carna :: helpers
504 
505 } // namespace Carna
506 
507 #endif // VOLUMEGRIDHELPER_H_6014714286
base::VolumeGrid< SegmentHUVolumeType, SegmentNormalsVolumeType > & grid() const
References the underlying grid.
Defines Carna::base::math namespace and CARNA_FOR_VECTOR3UI.
const details::VolumeGridHelper::Partionining partitioningX
Describes the partitioning along the x-axis.
unsigned int round_ui(ScalarType x)
Rounds x to the closest . Either the data type of must be unsigned or .
Definition: math.h:578
ScalarType makeEven(ScalarType x, int s)
Returns if is even and if is odd, where . The data type of must be integral. ...
Definition: math.h:606
Defines Carna::helpers::details::VolumeGridHelper.
std::size_t totalSize() const
Computes the effective total resolution.
Matrix4f scaling4f(float x, float y, float z)
Creates scaling matrix for homogeneous coordinates.
Definition: math.h:292
Defines scene graph leafs. Instances of this class represent visible geometry that can be rendered...
Definition: Geometry.h:59
void attachChild(Spatial *child)
Attaches child to this node in and takes it's possession.
Defines Carna::base::Node.
Defines type-parameters-independent VolumeGridHelper base interface.
std::size_t partitionsCount() const
Tells the total partitions number.
Eigen::Matrix< unsigned int, 3, 1 > Vector3ui
Defines vector.
Definition: math.h:199
Represents a single volumetric data partition.
const details::VolumeGridHelper::Partionining partitioningZ
Describes the partitioning along the z-axis.
NormalsComponent()
Sets the role to use for attaching textures to base::Geometry nodes to DEFAULT_ROLE_NORMALS.
SegmentHUVolumeType & huVolume()
References the HU volume data of this partition.
virtual void releaseGeometryFeatures() override
Releases all previously acquired textures. Invoke this method when the volume data changes...
Defines a Geometry minimal boundary box.
Definition: BoundingBox.h:40
HUComponent()
Sets the role to use for attaching textures to base::Geometry nodes to DEFAULT_ROLE_HU_VOLUME.
virtual base::Node * createNode(unsigned int geometryType, const Spacing &spacing) const override
Creates renderable representation of the underlying grid, that can be put anywhere in the scene graph...
Eigen::Matrix< float, 3, 1 > Vector3f
Defines vector.
Definition: math.h:196
Matrix4f translation4f(float x, float y, float z)
Returns matrix that translates homogeneous coordinates.
Definition: math.h:271
Defines the inner node of a scene graph. Implements a spatial scene element that is allowed to have c...
Definition: Node.h:44
#define CARNA_FOR_VECTOR3UI(vecName, vecLimit)
Loops vecName over all where is vecLimit.
Definition: math.h:728
base::math::Vector3f millimeters
Holds the dimensions of the whole dataset in millimeters.
Defines Carna::base::VolumeGrid.
base::math::Vector3f millimeters
Holds the spacing between two succeeding voxel centers in millimeters.
virtual base::math::Vector3ui gridResolution() const override
Tells the effective grid resolution.
const base::math::Vector3ui maxSegmentSize
The maximum effective resolution of a single grid segment.
const std::size_t maxSegmentBytesize
Maximum memory size of a single segment volume.
const base::math::Vector3ui resolution
Holds the effective resolution, i.e. the resolution covered by the grid.
void setMovable(bool movable)
Sets whether this spatial may be displaced w.r.t. it's parent through user interaction. Usually this will be false when this spatial represents a component of it's parent, like the shaft of an arrow.
Defines the helpers::VolumeGridHelper component that maintains HU volume data.
Specifies the spacing between two succeeding voxel centers in millimeters.
std::size_t tailSize
Holds the resolution of the last partition that may also be 0.
Defines the helpers::VolumeGridHelper component that computes and maintains normal maps...
Defines Carna::base::VolumeSegment.
Computes the partitioning of volumetric data and the corresponding normal map. Also creates scene nod...
Definition: Carna.h:199
signed short HUV
Represents values in .
Definition: Carna.h:56
const base::math::Vector3ui nativeResolution
Holds the original resolution of the loaded data.
const details::VolumeGridHelper::Partionining partitioningY
Describes the partitioning along the y-axis.
Defines Carna::base::BoundingBox.
void loadData(const UnaryVector3uiToHUVFunction &data)
Alters the volume data.
Specifies the dimensions of the whole dataset in millimeters.
Computes the partitioning that VolumeGridHelper uses along one dimension.
#define NON_COPYABLE
Features class it is placed in as non-copyable.
Definition: noncopyable.h:109
std::size_t regularPartitionSize
Holds the always odd, effective resolution of a single regular partition.
Defines Carna::base::Geometry.
Represents a particular partitioning of volumetric data.
Definition: VolumeGrid.h:63
Eigen::Matrix< signed int, 3, 1 > Vector3i
Defines vector.
Definition: math.h:198
void setBoundingVolume(BoundingVolume *boundingVolume)
Sets boundingVolume as the minimum boundary volume of this node. Supply nullptr for boundingVolume to...
VolumeGridHelper(const base::math::Vector3ui &nativeResolution, std::size_t maxSegmentBytesize=DEFAULT_MAX_SEGMENT_BYTESIZE)
Creates new base::VolumeGrid object. Initializes its' segments s.t. the totally covered resolution is...
math::Matrix4f localTransform
Defines the location, rotation and scale of this spatial in relation to it's parent. If this spatial has no parent, the value has no meaning.
Definition: Spatial.h:132