gdcm/Source/Common/gdcmBoxRegion.cxx

173 lines
4.0 KiB
C++

/*=========================================================================
Program: GDCM (Grassroots DICOM). A DICOM library
Copyright (c) 2006-2011 Mathieu Malaterre
All rights reserved.
See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "gdcmBoxRegion.h"
#include <limits>
#include <algorithm> // req C++11
namespace gdcm
{
class BoxRegionInternals
{
public:
BoxRegionInternals()
{
XMin = YMin = ZMin = std::numeric_limits<unsigned int>::max();
XMax = YMax = ZMax = std::numeric_limits<unsigned int>::min();
}
unsigned int XMin, XMax;
unsigned int YMin, YMax;
unsigned int ZMin, ZMax;
void Print(std::ostream &os) const
{
os << "Min:" << XMin << "," << YMin << "," << ZMin << "\n";
os << "Max:" << XMax << "," << YMax << "," << ZMax;
}
};
BoxRegion::BoxRegion()
{
Internals = new BoxRegionInternals;
}
BoxRegion::~BoxRegion()
{
delete Internals;
}
void BoxRegion::SetDomain(unsigned int xmin, unsigned int xmax,
unsigned int ymin, unsigned int ymax,
unsigned int zmin, unsigned int zmax)
{
Internals->XMin = xmin;
Internals->YMin = ymin;
Internals->ZMin = zmin;
Internals->XMax = xmax;
Internals->YMax = ymax;
Internals->ZMax = zmax;
}
Region *BoxRegion::Clone() const
{
BoxRegion *br = new BoxRegion( *this );
return br;
}
bool BoxRegion::Empty() const
{
assert( 0 );
return false;
}
bool BoxRegion::IsValid() const
{
if (Internals->XMax < Internals->XMin ||
Internals->YMax < Internals->YMin ||
Internals->ZMax < Internals->ZMin )
{
return false;
}
// Some properly crafted DICOM could have bigger values, reject them:
// technically there is no such restrictions for Z direction
if (Internals->XMax >= std::numeric_limits<uint16_t>::max() ||
Internals->YMax >= std::numeric_limits<uint16_t>::max() ||
Internals->ZMax == std::numeric_limits<uint32_t>::max() )
{
return false;
}
return true;
}
size_t BoxRegion::Area() const
{
// on some system size_t is too small:
const uint64_t A = Internals->XMax - Internals->XMin + 1;
const uint64_t B = Internals->YMax - Internals->YMin + 1;
const uint64_t C = Internals->ZMax - Internals->ZMin + 1;
const uint64_t tmp = A * B;
if (tmp != 0 && (std::numeric_limits<size_t>::max() / tmp) < C)
{
// multiplication exceed range of unsigned
return 0;
}
return (size_t)(tmp * C);
}
unsigned int BoxRegion::GetXMin() const
{
return Internals->XMin;
}
unsigned int BoxRegion::GetXMax() const
{
return Internals->XMax;
}
unsigned int BoxRegion::GetYMin() const
{
return Internals->YMin;
}
unsigned int BoxRegion::GetYMax() const
{
return Internals->YMax;
}
unsigned int BoxRegion::GetZMin() const
{
return Internals->ZMin;
}
unsigned int BoxRegion::GetZMax() const
{
return Internals->ZMax;
}
BoxRegion BoxRegion::BoundingBox(BoxRegion const & b1, BoxRegion const & b2 )
{
BoxRegion r;
unsigned int xmin = std::min( b1.GetXMin(), b2.GetXMin() );
unsigned int xmax = std::min( b1.GetXMax(), b2.GetXMax() );
unsigned int ymin = std::min( b1.GetYMin(), b2.GetYMin() );
unsigned int ymax = std::min( b1.GetYMax(), b2.GetYMax() );
unsigned int zmin = std::min( b1.GetZMin(), b2.GetZMin() );
unsigned int zmax = std::min( b1.GetZMax(), b2.GetZMax() );
r.SetDomain(xmin, xmax, ymin, ymax, zmin, zmax);
return r;
}
BoxRegion::BoxRegion(const BoxRegion& b)
{
assert( b.Internals );
Internals = new BoxRegionInternals;
*Internals = *b.Internals;
}
void BoxRegion::operator=(const BoxRegion& b)
{
assert( b.Internals );
*Internals = *b.Internals;
}
BoxRegion BoxRegion::ComputeBoundingBox()
{
return *this;
}
void BoxRegion::Print(std::ostream &os) const
{
Region::Print( os );
os << "Domain:\n";
this->Internals->Print( os );
}
} // end namespace gdcm