Carna Version 3.3.3
Loading...
Searching...
No Matches
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>
21#include <Carna/base/Geometry.h>
23#include <memory>
24#include <cmath>
25
30namespace Carna
31{
32
33namespace helpers
34{
35
36
37
38// ----------------------------------------------------------------------------------
39// VolumeGridHelperBase
40// ----------------------------------------------------------------------------------
41
48class CARNA_LIB VolumeGridHelperBase
49{
50
51public:
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
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
160 virtual void loadIntensities( const std::function< float( const base::math::Vector3ui& ) >& intensityData ) = 0;
161
164 template< typename LoadIntensitiesFunction >
165 void loadIntensities( const LoadIntensitiesFunction& intensityData );
166
172 void loadHUData( const std::function< base::HUV( const base::math::Vector3ui& ) >& huData );
173
176 template< typename LoadHUDataFunction >
177 void loadHUData( const LoadHUDataFunction& huData );
178
179}; // VolumeGridHelperBase
180
181
182template< typename LoadIntensitiesFunction >
183void VolumeGridHelperBase::loadIntensities( const LoadIntensitiesFunction& intensityData )
184{
185 loadIntensities( static_cast< const std::function< float( const base::math::Vector3ui& ) >& >
186 (
187 [&intensityData]( const base::math::Vector3ui& loc ) -> float
188 {
189 return intensityData( loc );
190 }
191 )
192 );
193}
194
195
196template< typename LoadHUDataFunction >
197void VolumeGridHelperBase::loadHUData( const LoadHUDataFunction& huData )
198{
199 loadHUData( static_cast< const std::function< base::HUV( const base::math::Vector3ui& ) >& >
200 (
201 [&huData]( const base::math::Vector3ui& loc )
202 {
203 return huData( loc );
204 }
205 )
206 );
207}
208
209
210
211// ----------------------------------------------------------------------------------
212// VolumeGridHelper
213// ----------------------------------------------------------------------------------
214
253template< typename SegmentIntensityVolumeType, typename SegmentNormalsVolumeType >
255 : public VolumeGridHelperBase
256 , public details::VolumeGridHelper::IntensityComponent< SegmentIntensityVolumeType, SegmentNormalsVolumeType >
257 , public details::VolumeGridHelper:: NormalsComponent< SegmentIntensityVolumeType, SegmentNormalsVolumeType >
258{
259
261
263 typedef details::VolumeGridHelper:: NormalsComponent< SegmentIntensityVolumeType, SegmentNormalsVolumeType > NormalsComponent;
264
268 std::unique_ptr< base::VolumeGrid< SegmentIntensityVolumeType, SegmentNormalsVolumeType > > myGrid;
269
270public:
271
272 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
273
288
292 const std::size_t maxSegmentBytesize;
293
298
303
308
313
318
330 virtual void loadIntensities( const std::function< float( const base::math::Vector3ui& ) >& intensityData ) override;
331
342 virtual void releaseGeometryFeatures() override;
343
348
349 virtual base::Node* createNode( unsigned int geometryType, const Spacing& spacing ) const override;
350
351 virtual base::Node* createNode( unsigned int geometryType, const Dimensions& dimensions ) const override;
352
353protected:
354
355 virtual base::math::Vector3ui gridResolution() const override;
356
357private:
358
360 ( unsigned int geometryType
361 , const Spacing& spacing
362 , const Dimensions& dimensions ) const;
363
364 static base::math::Vector3ui computeMaxSegmentSize( const base::math::Vector3ui& nativeResolution, std::size_t maxSegmentBytesize );
365
366}; // VolumeGridHelper
367
368
369template< typename SegmentIntensityVolumeType, typename SegmentNormalsVolumeType >
371 ( const base::math::Vector3ui& nativeResolution, std::size_t maxSegmentBytesize )
372{
373 const float maxSideLengthF = std::pow
374 ( maxSegmentBytesize / static_cast< float >( sizeof( typename SegmentIntensityVolumeType::Voxel ) ), 1.f / 3 );
375 const unsigned int maxSideLength = base::math::makeEven( base::math::round_ui( maxSideLengthF ), -1 );
376
377 /* We subtract the redundant texels from effective segment size.
378 * Note that this causes the effective maximum segment size to be odd.
379 */
380 return base::math::Vector3ui( maxSideLength - 1, maxSideLength - 1, maxSideLength - 1 );
381}
382
383
384template< typename SegmentIntensityVolumeType, typename SegmentNormalsVolumeType >
386 ( const base::math::Vector3ui& nativeResolution
387 , std::size_t maxSegmentBytesize )
388 : VolumeGridHelperBase( nativeResolution )
389 , maxSegmentBytesize( maxSegmentBytesize )
390 , maxSegmentSize( computeMaxSegmentSize( nativeResolution, maxSegmentBytesize ) )
391 , partitioningX( nativeResolution.x(), maxSegmentSize.x() )
392 , partitioningY( nativeResolution.y(), maxSegmentSize.y() )
393 , partitioningZ( nativeResolution.z(), maxSegmentSize.z() )
394 , resolution( partitioningX.totalSize(), partitioningY.totalSize(), partitioningZ.totalSize() )
395{
396 const base::math::Vector3ui segmentCounts
401 NormalsComponent::setGrid( *myGrid );
402
403 CARNA_FOR_VECTOR3UI( segmentCoord, myGrid->segmentCounts )
404 {
405 /* Here we add the redundant texels to the buffer size considerations.
406 */
407 const base::math::Vector3ui segmentSize
408 ( segmentCoord.x() + 1 == myGrid->segmentCounts.x() ? partitioningX.tailSize : partitioningX.regularPartitionSize + 1
409 , segmentCoord.y() + 1 == myGrid->segmentCounts.y() ? partitioningY.tailSize : partitioningY.regularPartitionSize + 1
410 , segmentCoord.z() + 1 == myGrid->segmentCounts.z() ? partitioningZ.tailSize : partitioningZ.regularPartitionSize + 1 );
411
412 IntensityComponent::initializeSegment( myGrid->segmentAt( segmentCoord ), segmentSize );
413 NormalsComponent ::initializeSegment( myGrid->segmentAt( segmentCoord ), segmentSize );
414 }
415}
416
417
418template< typename SegmentIntensityVolumeType, typename SegmentNormalsVolumeType >
420{
421 IntensityComponent::releaseGeometryFeatures();
422 NormalsComponent ::releaseGeometryFeatures();
423}
424
425
426template< typename SegmentIntensityVolumeType, typename SegmentNormalsVolumeType >
428 ( const std::function< float( const base::math::Vector3ui& ) >& data )
429{
430 releaseGeometryFeatures();
431 CARNA_FOR_VECTOR3UI( coord, resolution )
432 {
433 const bool outOfNativeBounds
434 = coord.x() >= nativeResolution.x()
435 || coord.y() >= nativeResolution.y()
436 || coord.z() >= nativeResolution.z();
437 const float intensity = outOfNativeBounds ? 0 : data( coord );
438 myGrid->template setVoxel< typename base::VolumeGrid< SegmentIntensityVolumeType, SegmentNormalsVolumeType >::IntensitySelector >( coord, intensity );
439 }
440 NormalsComponent::computeNormals();
441}
442
443
444template< typename SegmentIntensityVolumeType, typename SegmentNormalsVolumeType >
450
451
452template< typename SegmentIntensityVolumeType, typename SegmentNormalsVolumeType >
454 ( unsigned int geometryType, const Spacing& spacing, const Dimensions& dimensions ) const
455{
456 /* Compute dimensions of a regular grid segment, taking the redundant texels into
457 * account. Regular segments have `regularPartitionSize + 1` texels per dimension
458 * which is due to the redundant pixels.
459 */
460 const base::math::Vector3f regularSegmentDimensions = dimensions.millimeters.cwiseMin( base::math::Vector3f
461 ( spacing.millimeters.x() * partitioningX.regularPartitionSize
462 , spacing.millimeters.y() * partitioningY.regularPartitionSize
463 , spacing.millimeters.z() * partitioningZ.regularPartitionSize ) );
464
465 /* Create pivot node that centers its children.
466 *
467 * Suppose the following example grid layout, where p is the absolute center and
468 * q is the center of the first segment:
469 *
470 * o-------o-------o---o
471 * | q | | |
472 * o-------o-------o---o
473 * | | p | |
474 * o-------o-------o---o
475 * | | | |
476 * o-------o-------o---o
477 *
478 * Each segment is rendered around its local center. Thus, the translation T
479 * required to center the volume geometry in the origin, corresponds to:
480 *
481 * T = -p + q
482 */
483 base::Node* const pivot = new base::Node();
484 pivot->localTransform = base::math::translation4f( ( regularSegmentDimensions - dimensions.millimeters ) / 2 );
485 pivot->setMovable( false );
486
487 /* Create geometry nodes for all grid segments.
488 */
489 CARNA_FOR_VECTOR3UI( segmentCoord, myGrid->segmentCounts )
490 {
491 const base::VolumeSegment< SegmentIntensityVolumeType, SegmentNormalsVolumeType >& segment = myGrid->segmentAt( segmentCoord );
492
493 /* Compute dimensions of particular grid segment.
494 */
495 const bool isTailX = segmentCoord.x() + 1 == myGrid->segmentCounts.x();
496 const bool isTailY = segmentCoord.y() + 1 == myGrid->segmentCounts.y();
497 const bool isTailZ = segmentCoord.z() + 1 == myGrid->segmentCounts.z();
498 const base::math::Vector3ui& volumeSize = segment.intensities().size; // includes redundant pixels (only along non-tail dimensions)
499 const base::math::Vector3f segmentDimensions
500 ( isTailX ? ( volumeSize.x() - 1 ) * spacing.millimeters.x() : regularSegmentDimensions.x()
501 , isTailY ? ( volumeSize.y() - 1 ) * spacing.millimeters.y() : regularSegmentDimensions.y()
502 , isTailZ ? ( volumeSize.z() - 1 ) * spacing.millimeters.z() : regularSegmentDimensions.z() );
503
504 /* Create geometry node for particular grid segment.
505 */
506 base::Geometry* const geom = new base::Geometry( geometryType );
507 pivot->attachChild( geom );
508 IntensityComponent::attachTexture( *geom, segment );
509 NormalsComponent ::attachTexture( *geom, segment );
510 geom->setMovable( false );
511 geom->setBoundingVolume( new base::BoundingBox( 1, 1, 1 ) );
512 geom->localTransform
514 ( segmentCoord.x() * regularSegmentDimensions.x() - ( isTailX ? ( regularSegmentDimensions.x() - segmentDimensions.x() ) / 2 : 0 )
515 , segmentCoord.y() * regularSegmentDimensions.y() - ( isTailY ? ( regularSegmentDimensions.y() - segmentDimensions.y() ) / 2 : 0 )
516 , segmentCoord.z() * regularSegmentDimensions.z() - ( isTailZ ? ( regularSegmentDimensions.z() - segmentDimensions.z() ) / 2 : 0 ) )
517 * base::math::scaling4f( segmentDimensions );
518 }
519
520 /* We're done.
521 */
523 , "VolumeGridHelper computed "
524 + base::text::lexical_cast< std::string >( 8 * sizeof( typename SegmentIntensityVolumeType::Voxel ) )
525 + "bit grid data using "
526 + base::text::lexical_cast< std::string >( myGrid->segmentCounts.x() ) + "×"
527 + base::text::lexical_cast< std::string >( myGrid->segmentCounts.y() ) + "×"
528 + base::text::lexical_cast< std::string >( myGrid->segmentCounts.z() ) + " segments" );
529 return pivot;
530}
531
532
533template< typename SegmentIntensityVolumeType, typename SegmentNormalsVolumeType >
535 ( unsigned int geometryType, const Spacing& spacing ) const
536{
537 const base::math::Vector3f dimensions
538 = ( nativeResolution.cast< int >() - base::math::Vector3i( 1, 1, 1 ) ).cast< float >().cwiseProduct( spacing.millimeters );
539 return createNode( geometryType, spacing, Dimensions( dimensions ) );
540}
541
542
543template< typename SegmentIntensityVolumeType, typename SegmentNormalsVolumeType >
545 ( unsigned int geometryType, const Dimensions& dimensions ) const
546{
547 const base::math::Vector3f& mmDimensions = dimensions.millimeters;
548 const base::math::Vector3f spacing
549 = mmDimensions.cast< float >().cwiseQuotient( ( nativeResolution.cast< int >() - base::math::Vector3i( 1, 1, 1 ) ).cast< float >() );
550 return createNode( geometryType, Spacing( spacing ), dimensions );
551}
552
553
554template< typename SegmentIntensityVolumeType, typename SegmentNormalsVolumeType >
556{
557 return resolution;
558}
559
560
561
562} // namespace Carna :: helpers
563
564} // namespace Carna
565
566#endif // VOLUMEGRIDHELPER_H_6014714286
Defines Carna::base::BoundingBox.
Defines Carna::base::Geometry.
Defines Carna::base::Node.
Defines Carna::helpers::details::VolumeGridHelper.
Defines Carna::base::VolumeGrid.
Defines Carna::base::VolumeSegment.
Represents an association.
Definition Association.h:45
Defines a Geometry minimal boundary box.
Definition BoundingBox.h:41
Defines scene graph leafs. Instances of this class represent visible geometry that can be rendered....
Definition Geometry.h:60
void setBoundingVolume(BoundingVolume *boundingVolume)
Sets boundingVolume as the minimum boundary volume of this node. Supply nullptr for boundingVolume to...
@ debug
Indicates messages that might be of interest when searching bugs.
Definition Log.h:88
Defines the inner node of a scene graph. Implements a spatial scene element that is allowed to have c...
Definition Node.h:45
void attachChild(Spatial *child)
Attaches child to this node in and takes it's possession.
static Log & instance()
Returns the only instance from class InstanceType.
Definition Singleton.h:109
void setMovable(bool movable)
Sets whether this spatial may be displaced w.r.t. it's parent through user interaction....
math::Matrix4f localTransform
Defines the location, rotation and scale of this spatial in relation to it's parent....
Definition Spatial.h:132
Defines type-parameters-independent VolumeGridHelper base interface.
VolumeGridHelperBase(const base::math::Vector3ui &nativeResolution)
Instantiates.
virtual void releaseGeometryFeatures()=0
Releases all previously acquired textures. Invoke this method when the volume data changes.
virtual base::Node * createNode(unsigned int geometryType, const Dimensions &dimensions) const =0
Creates renderable representation of the underlying grid, that can be put anywhere in the scene graph...
static const std::size_t DEFAULT_MAX_SEGMENT_BYTESIZE
Default maximum memory size of a single segment volume, 50 megabytes approximately....
void loadHUData(const std::function< base::HUV(const base::math::Vector3ui &) > &huData)
Updates the data of the volume grid.
virtual ~VolumeGridHelperBase()
Does nothing.
virtual void loadIntensities(const std::function< float(const base::math::Vector3ui &) > &intensityData)=0
Updates the data of the volume grid.
virtual base::Node * createNode(unsigned int geometryType, const Spacing &spacing) const =0
Creates renderable representation of the underlying grid, that can be put anywhere in the scene graph...
const base::math::Vector3ui nativeResolution
Holds the original resolution of the loaded data.
Computes the partitioning of volumetric data and the corresponding normal map. Also creates scene nod...
const base::math::Vector3ui resolution
Holds the effective resolution, i.e. the resolution covered by the grid.
virtual void loadIntensities(const std::function< float(const base::math::Vector3ui &) > &intensityData) override
Updates the data of the volume grid.
const base::math::Vector3ui maxSegmentSize
The maximum effective resolution of a single grid segment.
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...
virtual void releaseGeometryFeatures() override
Releases all previously acquired textures. Invoke this method when the volume data changes,...
const details::VolumeGridHelper::Partionining partitioningZ
Describes the partitioning along the z-axis.
base::VolumeGrid< SegmentIntensityVolumeType, SegmentNormalsVolumeType > & grid() const
References the underlying grid.
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...
const std::size_t maxSegmentBytesize
Maximum memory size of a single segment volume.
const details::VolumeGridHelper::Partionining partitioningX
Describes the partitioning along the x-axis.
const details::VolumeGridHelper::Partionining partitioningY
Describes the partitioning along the y-axis.
Defines the helpers::VolumeGridHelper component that maintains intensity volume data.
Defines the helpers::VolumeGridHelper component that computes and maintains normal maps.
void setGrid(base::VolumeGrid< SegmentIntensityVolumeType, SegmentNormalsVolumeType > &grid)
Sets the grid that computeNormals operates on.
Defines Carna::base::math namespace and CARNA_FOR_VECTOR3UI.
#define CARNA_FOR_VECTOR3UI(vecName, vecLimit)
Loops vecName over all where is vecLimit.
Definition math.h:747
Eigen::Matrix< float, 3, 1 > Vector3f
Defines vector.
Definition math.h:196
Eigen::Matrix< unsigned int, 3, 1 > Vector3ui
Defines vector.
Definition math.h:199
Eigen::Matrix< signed int, 3, 1 > Vector3i
Defines vector.
Definition math.h:198
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:625
unsigned int round_ui(ScalarType x)
Rounds x to the closest . Either the data type of must be unsigned or .
Definition math.h:597
Matrix4f translation4f(float x, float y, float z)
Returns matrix that translates homogeneous coordinates.
Definition math.h:271
#define NON_COPYABLE
Features class it is placed in as non-copyable.
Represents values in .
Definition HUV.h:35
Specifies the dimensions of the whole dataset in millimeters.
base::math::Vector3f millimeters
Holds the dimensions of the whole dataset in millimeters.
Dimensions(const base::math::Vector3f &millimeters)
Instantiates.
Specifies the spacing between two succeeding voxel centers in millimeters.
base::math::Vector3f millimeters
Holds the spacing between two succeeding voxel centers in millimeters.
Spacing(const base::math::Vector3f &millimeters)
Instantiates.
Computes the partitioning that VolumeGridHelper uses along one dimension.
std::size_t partitionsCount() const
Tells the total partitions number.
std::size_t tailSize
Holds the resolution of the last partition that may also be 0.
std::size_t regularPartitionSize
Holds the always odd, effective resolution of a single regular partition.