Skip to content

Commit

Permalink
Merge pull request InsightSoftwareConsortium#1 from HastingsGreer/Spa…
Browse files Browse the repository at this point in the history
…tialObjectsV5-ImageSpatialObject

BUG: ImageSpatialObject's BoundingBox broken if not axis aligned
  • Loading branch information
aylward authored Feb 8, 2019
2 parents 1eb535a + 80c0b05 commit 7df4975
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class ITK_TEMPLATE_EXPORT ImageMaskSpatialObject:
/** Get the boundaries of a specific object. This function needs to
* be called every time one of the object's components is
* changed. */
bool ComputeObjectBoundingBox() const override;
bool ComputeMyBoundingBox() const override;

protected:
ImageMaskSpatialObject();
Expand Down
32 changes: 15 additions & 17 deletions Modules/Core/SpatialObjects/include/itkImageMaskSpatialObject.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ ImageMaskSpatialObject< TDimension >
::ImageMaskSpatialObject()
{
this->SetTypeName("ImageMaskSpatialObject");
this->ComputeObjectBoundingBox();
}

/** Destructor */
Expand All @@ -51,25 +50,24 @@ ImageMaskSpatialObject< TDimension >
{
if( this->GetObjectBounds()->IsInside(point) )
{
PointType p = this->GetObjectWorldTransform()->GetInverse()->
PointType p = this->GetObjectWorldTransform()->GetInverse()->
TransformPoint(point);

typename Superclass::InterpolatorType::ContinuousIndexType index;
for ( unsigned int i = 0; i < TDimension; i++ )
{
index[i] = p[i];
}

using InterpolatorOutputType = typename InterpolatorType::OutputType;
const bool insideMask = (
Math::NotExactlyEquals(
DefaultConvertPixelTraits<InterpolatorOutputType>::GetScalarValue(
this->m_Interpolator->EvaluateAtContinuousIndex(index)),
NumericTraits<PixelType>::ZeroValue() ) );
if( insideMask )
{
return true;
}
bool inside_image = m_Image->TransformPhysicalPointToIndex( p,
index );
if( inside_image ){
using InterpolatorOutputType = typename InterpolatorType::OutputType;
bool insideMask = (
Math::NotExactlyEquals(
DefaultConvertPixelTraits<InterpolatorOutputType>::GetScalarValue(
this->m_Interpolator->EvaluateAtContinuousIndex(index)),
NumericTraits<PixelType>::ZeroValue() ) );
if( insideMask )
{
return true;
}
}
}
}
if( depth > 0 )
Expand Down
16 changes: 9 additions & 7 deletions Modules/Core/SpatialObjects/include/itkImageSpatialObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,19 @@ class ITK_TEMPLATE_EXPORT ImageSpatialObject:
/** Get a pointer to the image currently attached to the object. */
const ImageType * GetImage() const;

/** Returns the value of the image at the requested point.
* If the point is not inside the object, then an exception is thrown.
* \sa ExceptionObject */
bool ValueAt(const PointType & point, double & value, unsigned int depth = 0,
const std::string & name = "") const override;
/** Compute the boundaries of the image spatial object. */
bool ComputeMyBoundingBox() const override;

/** Returns true if the point is inside, false otherwise. */
bool IsInside(const PointType & point, unsigned int depth=0,
const std::string & name = "") const override;

/** Compute the boundaries of the iamge spatial object. */
bool ComputeObjectBoundingBox() const override;
/** Returns the value of the image at the requested point.
* Returns true if that value is valid */
bool ValueAt(const PointType & point, double & value, unsigned int depth = 0,
const std::string & name = "") const override;



/** Returns the latest modified time of the object and its component. */
ModifiedTimeType GetMTime() const override;
Expand Down Expand Up @@ -120,6 +121,7 @@ class ITK_TEMPLATE_EXPORT ImageSpatialObject:
std::string m_PixelType;

typename InterpolatorType::Pointer m_Interpolator;

template <typename T>
void SetPixelTypeName(const T *)
{
Expand Down
41 changes: 23 additions & 18 deletions Modules/Core/SpatialObjects/include/itkImageSpatialObject.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -138,46 +138,49 @@ ImageSpatialObject< TDimension, PixelType >
template< unsigned int TDimension, typename PixelType >
bool
ImageSpatialObject< TDimension, PixelType >
::ComputeObjectBoundingBox() const
::ComputeMyBoundingBox() const
{
itkDebugMacro("Computing ImageSpatialObject bounding box");

// First we compute the bounding box in the object space
typename BoundingBoxType::Pointer bb = BoundingBoxType::New();
// First we compute the bounding box in the index space
typename BoundingBoxType::Pointer indexSpaceBB = BoundingBoxType::New();

IndexType index = m_Image->GetLargestPossibleRegion().GetIndex();
SizeType size = m_Image->GetLargestPossibleRegion().GetSize();
IndexType tmpIndex1;
IndexType tmpIndex2;

PointType pnt1;
PointType pnt2;
for ( unsigned int i = 0; i < TDimension; i++ )
{
tmpIndex1[i] = index[i];
tmpIndex2[i] = index[i] + size[i];
pnt1[i] = index[i];
pnt2[i] = index[i] + size[i];
}
m_Image->TransformIndexToPhysicalSpace( tmpIndex1, pnt1 );
m_Image->TransformIndexToPhysicalSpace( tmpIndex2, pnt2 );

bb->SetMinimum(pnt1);
bb->SetMaximum(pnt1);
bb->ConsiderPoint(pnt2);
bb->ComputeBoundingBox();
indexSpaceBB->SetMinimum(pnt1);
indexSpaceBB->SetMaximum(pnt1);
indexSpaceBB->ConsiderPoint(pnt2);
indexSpaceBB->ComputeBoundingBox();

// Next Transform the corners of the bounding box
using PointsContainer = typename BoundingBoxType::PointsContainer;
const PointsContainer *corners = bb->GetCorners();
const PointsContainer *indexSpaceCorners = indexSpaceBB->GetCorners();
typename PointsContainer::Pointer transformedCorners =
PointsContainer::New();
transformedCorners->Reserve(
static_cast<typename PointsContainer::ElementIdentifier>(
corners->size() ) );
indexSpaceCorners->size() ) );

auto it = corners->begin();
auto it = indexSpaceCorners->begin();
auto itTrans = transformedCorners->begin();
while ( it != corners->end() )
while ( it != indexSpaceCorners->end() )
{
PointType pnt = this->GetObjectToWorldTransform()->TransformPoint(*it);
IndexType ind;
for (unsigned int i = 0; i < TDimensions; i++){
ind[i] = (*it)[i];
}
PointType objectSpacePoint;
m_Image->TransformIndexToPhysicalSpace(ind, objectSpacePoint);
PointType pnt = this->GetObjectToWorldTransform()->TransformPoint(objectSpacePoint);
*itTrans = pnt;
++it;
++itTrans;
Expand All @@ -191,6 +194,7 @@ ImageSpatialObject< TDimension, PixelType >
return true;
}


/** Set the image in the spatial object */
template< unsigned int TDimension, typename PixelType >
void
Expand All @@ -199,6 +203,7 @@ ImageSpatialObject< TDimension, PixelType >
{
if ( !image )
{
itkDebugMacro("Image passed to ImageSpatialObject was null");
return;
}

Expand Down
4 changes: 2 additions & 2 deletions Modules/Core/SpatialObjects/include/itkSpatialObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ class ITK_TEMPLATE_EXPORT SpatialObject:
* * Update
* Optionally, a subclass may also wish to overwrite
* * ValueAt
* * IsEvaluableAt - if the extend is beyond IsInisde.
* * IsEvaluableAt - if the extent is beyond IsInisde.
*/
/**********************************************************************/

Expand All @@ -203,7 +203,7 @@ class ITK_TEMPLATE_EXPORT SpatialObject:
void Update() override;


/** Returns the value at a point */
/** Returns the value at a point. Returns true if that value is valid */
virtual bool ValueAt(const PointType & point, double & value,
unsigned int depth = 0,
const std::string & name = "") const;
Expand Down

0 comments on commit 7df4975

Please sign in to comment.