1 /*=========================================================================
2
3 Program: GDCM (Grassroots DICOM). A DICOM library
4
5 Copyright (c) 2006-2011 Mathieu Malaterre
6 All rights reserved.
7 See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notice for more information.
12
13 =========================================================================*/
14 #include "gdcmBoxRegion.h"
15
16 #include <limits>
17 #include <algorithm> // req C++11
18
19 namespace gdcm
20 {
21 class BoxRegionInternals
22 {
23 public:
BoxRegionInternals()24 BoxRegionInternals()
25 {
26 XMin = YMin = ZMin = std::numeric_limits<unsigned int>::max();
27 XMax = YMax = ZMax = std::numeric_limits<unsigned int>::min();
28 }
29 unsigned int XMin, XMax;
30 unsigned int YMin, YMax;
31 unsigned int ZMin, ZMax;
Print(std::ostream & os) const32 void Print(std::ostream &os) const
33 {
34 os << "Min:" << XMin << "," << YMin << "," << ZMin << "\n";
35 os << "Max:" << XMax << "," << YMax << "," << ZMax;
36 }
37
38 };
39
BoxRegion()40 BoxRegion::BoxRegion()
41 {
42 Internals = new BoxRegionInternals;
43 }
44
~BoxRegion()45 BoxRegion::~BoxRegion()
46 {
47 delete Internals;
48 }
49
SetDomain(unsigned int xmin,unsigned int xmax,unsigned int ymin,unsigned int ymax,unsigned int zmin,unsigned int zmax)50 void BoxRegion::SetDomain(unsigned int xmin, unsigned int xmax,
51 unsigned int ymin, unsigned int ymax,
52 unsigned int zmin, unsigned int zmax)
53 {
54 Internals->XMin = xmin;
55 Internals->YMin = ymin;
56 Internals->ZMin = zmin;
57 Internals->XMax = xmax;
58 Internals->YMax = ymax;
59 Internals->ZMax = zmax;
60 }
61
Clone() const62 Region *BoxRegion::Clone() const
63 {
64 BoxRegion *br = new BoxRegion( *this );
65 return br;
66 }
67
Empty() const68 bool BoxRegion::Empty() const
69 {
70 assert( 0 );
71 return false;
72 }
73
IsValid() const74 bool BoxRegion::IsValid() const
75 {
76 if (Internals->XMax < Internals->XMin ||
77 Internals->YMax < Internals->YMin ||
78 Internals->ZMax < Internals->ZMin )
79 {
80 return false;
81 }
82 // Some properly crafted DICOM could have bigger values, reject them:
83 // technically there is no such restrictions for Z direction
84 if (Internals->XMax >= std::numeric_limits<uint16_t>::max() ||
85 Internals->YMax >= std::numeric_limits<uint16_t>::max() ||
86 Internals->ZMax == std::numeric_limits<uint32_t>::max() )
87 {
88 return false;
89 }
90 return true;
91 }
92
Area() const93 size_t BoxRegion::Area() const
94 {
95 // on some system size_t is too small:
96 const uint64_t A = Internals->XMax - Internals->XMin + 1;
97 const uint64_t B = Internals->YMax - Internals->YMin + 1;
98 const uint64_t C = Internals->ZMax - Internals->ZMin + 1;
99 const uint64_t tmp = A * B;
100 if (tmp != 0 && (std::numeric_limits<size_t>::max() / tmp) < C)
101 {
102 // multiplication exceed range of unsigned
103 return 0;
104 }
105 return (size_t)(tmp * C);
106 }
107
GetXMin() const108 unsigned int BoxRegion::GetXMin() const
109 {
110 return Internals->XMin;
111 }
GetXMax() const112 unsigned int BoxRegion::GetXMax() const
113 {
114 return Internals->XMax;
115 }
GetYMin() const116 unsigned int BoxRegion::GetYMin() const
117 {
118 return Internals->YMin;
119 }
GetYMax() const120 unsigned int BoxRegion::GetYMax() const
121 {
122 return Internals->YMax;
123 }
GetZMin() const124 unsigned int BoxRegion::GetZMin() const
125 {
126 return Internals->ZMin;
127 }
GetZMax() const128 unsigned int BoxRegion::GetZMax() const
129 {
130 return Internals->ZMax;
131 }
132
BoundingBox(BoxRegion const & b1,BoxRegion const & b2)133 BoxRegion BoxRegion::BoundingBox(BoxRegion const & b1, BoxRegion const & b2 )
134 {
135 BoxRegion r;
136 unsigned int xmin = std::min( b1.GetXMin(), b2.GetXMin() );
137 unsigned int xmax = std::min( b1.GetXMax(), b2.GetXMax() );
138 unsigned int ymin = std::min( b1.GetYMin(), b2.GetYMin() );
139 unsigned int ymax = std::min( b1.GetYMax(), b2.GetYMax() );
140 unsigned int zmin = std::min( b1.GetZMin(), b2.GetZMin() );
141 unsigned int zmax = std::min( b1.GetZMax(), b2.GetZMax() );
142
143 r.SetDomain(xmin, xmax, ymin, ymax, zmin, zmax);
144 return r;
145 }
146
BoxRegion(const BoxRegion & b)147 BoxRegion::BoxRegion(const BoxRegion& b)
148 {
149 assert( b.Internals );
150 Internals = new BoxRegionInternals;
151 *Internals = *b.Internals;
152 }
153
operator =(const BoxRegion & b)154 void BoxRegion::operator=(const BoxRegion& b)
155 {
156 assert( b.Internals );
157 *Internals = *b.Internals;
158 }
159
ComputeBoundingBox()160 BoxRegion BoxRegion::ComputeBoundingBox()
161 {
162 return *this;
163 }
164
Print(std::ostream & os) const165 void BoxRegion::Print(std::ostream &os) const
166 {
167 Region::Print( os );
168 os << "Domain:\n";
169 this->Internals->Print( os );
170 }
171
172 } // end namespace gdcm
173