Mercurial > hg > orthanc-stone
annotate Framework/Toolbox/OrientedBoundingBox.cpp @ 194:7a031ac16b2d wasm
rename Enumerations.h to StoneEnumerations.h to avoid clashes with Orthanc
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 20 Mar 2018 14:46:58 +0100 |
parents | 0a73d76333db |
children | e9c7a78a3e77 |
rev | line source |
---|---|
140 | 1 /** |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 | |
22 #include "OrientedBoundingBox.h" | |
23 | |
159
0a73d76333db
populating LinearAlgebra
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
158
diff
changeset
|
24 #include "GeometryToolbox.h" |
0a73d76333db
populating LinearAlgebra
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
158
diff
changeset
|
25 |
140 | 26 #include <Core/OrthancException.h> |
27 | |
28 #include <cassert> | |
29 | |
30 namespace OrthancStone | |
31 { | |
32 OrientedBoundingBox::OrientedBoundingBox(const ImageBuffer3D& image) | |
33 { | |
34 unsigned int n = image.GetDepth(); | |
35 if (n < 1) | |
36 { | |
37 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); | |
38 } | |
39 | |
40 const CoordinateSystem3D& geometry = image.GetAxialGeometry(); | |
41 Vector dim = image.GetVoxelDimensions(VolumeProjection_Axial); | |
42 | |
43 u_ = geometry.GetAxisX(); | |
44 v_ = geometry.GetAxisY(); | |
45 w_ = geometry.GetNormal(); | |
46 | |
47 hu_ = static_cast<double>(image.GetWidth() * dim[0] / 2.0); | |
48 hv_ = static_cast<double>(image.GetHeight() * dim[1] / 2.0); | |
49 hw_ = static_cast<double>(image.GetDepth() * dim[2] / 2.0); | |
50 | |
51 c_ = (geometry.GetOrigin() + | |
52 (hu_ - dim[0] / 2.0) * u_ + | |
53 (hv_ - dim[1] / 2.0) * v_ + | |
54 (hw_ - dim[2] / 2.0) * w_); | |
55 } | |
56 | |
57 | |
58 bool OrientedBoundingBox::HasIntersectionWithPlane(std::vector<Vector>& points, | |
59 const Vector& normal, | |
60 double d) const | |
61 { | |
62 assert(normal.size() == 3); | |
63 | |
64 double r = (hu_ * fabs(boost::numeric::ublas::inner_prod(normal, u_)) + | |
65 hv_ * fabs(boost::numeric::ublas::inner_prod(normal, v_)) + | |
66 hw_ * fabs(boost::numeric::ublas::inner_prod(normal, w_))); | |
67 | |
68 double s = boost::numeric::ublas::inner_prod(normal, c_) + d; | |
69 | |
70 if (fabs(s) >= r) | |
71 { | |
72 // No intersection, or intersection is reduced to a single point | |
73 return false; | |
74 } | |
75 else | |
76 { | |
77 Vector p; | |
78 | |
79 // Loop over all the 12 edges (segments) of the oriented | |
80 // bounding box, and check whether they intersect the plane | |
81 | |
82 // X-aligned edges | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
83 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
84 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
85 c_ - u_ * hu_ - v_ * hv_ - w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
86 c_ + u_ * hu_ - v_ * hv_ - w_ * hw_)) |
140 | 87 { |
88 points.push_back(p); | |
89 } | |
90 | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
91 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
92 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
93 c_ - u_ * hu_ + v_ * hv_ - w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
94 c_ + u_ * hu_ + v_ * hv_ - w_ * hw_)) |
140 | 95 { |
96 points.push_back(p); | |
97 } | |
98 | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
99 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
100 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
101 c_ - u_ * hu_ - v_ * hv_ + w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
102 c_ + u_ * hu_ - v_ * hv_ + w_ * hw_)) |
140 | 103 { |
104 points.push_back(p); | |
105 } | |
106 | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
107 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
108 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
109 c_ - u_ * hu_ + v_ * hv_ + w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
110 c_ + u_ * hu_ + v_ * hv_ + w_ * hw_)) |
140 | 111 { |
112 points.push_back(p); | |
113 } | |
114 | |
115 // Y-aligned edges | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
116 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
117 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
118 c_ - u_ * hu_ - v_ * hv_ - w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
119 c_ - u_ * hu_ + v_ * hv_ - w_ * hw_)) |
140 | 120 { |
121 points.push_back(p); | |
122 } | |
123 | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
124 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
125 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
126 c_ + u_ * hu_ - v_ * hv_ - w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
127 c_ + u_ * hu_ + v_ * hv_ - w_ * hw_)) |
140 | 128 { |
129 points.push_back(p); | |
130 } | |
131 | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
132 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
133 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
134 c_ - u_ * hu_ - v_ * hv_ + w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
135 c_ - u_ * hu_ + v_ * hv_ + w_ * hw_)) |
140 | 136 { |
137 points.push_back(p); | |
138 } | |
139 | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
140 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
141 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
142 c_ + u_ * hu_ - v_ * hv_ + w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
143 c_ + u_ * hu_ + v_ * hv_ + w_ * hw_)) |
140 | 144 { |
145 points.push_back(p); | |
146 } | |
147 | |
148 // Z-aligned edges | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
149 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
150 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
151 c_ - u_ * hu_ - v_ * hv_ - w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
152 c_ - u_ * hu_ - v_ * hv_ + w_ * hw_)) |
140 | 153 { |
154 points.push_back(p); | |
155 } | |
156 | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
157 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
158 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
159 c_ + u_ * hu_ - v_ * hv_ - w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
160 c_ + u_ * hu_ - v_ * hv_ + w_ * hw_)) |
140 | 161 { |
162 points.push_back(p); | |
163 } | |
164 | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
165 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
166 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
167 c_ - u_ * hu_ + v_ * hv_ - w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
168 c_ - u_ * hu_ + v_ * hv_ + w_ * hw_)) |
140 | 169 { |
170 points.push_back(p); | |
171 } | |
172 | |
151
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
173 if (GeometryToolbox::IntersectPlaneAndSegment |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
174 (p, normal, d, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
175 c_ + u_ * hu_ + v_ * hv_ - w_ * hw_, |
c5044bbfc303
CoordinateSystem3D::IntersectSegment()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
146
diff
changeset
|
176 c_ + u_ * hu_ + v_ * hv_ + w_ * hw_)) |
140 | 177 { |
178 points.push_back(p); | |
179 } | |
180 | |
181 return true; | |
182 } | |
183 } | |
184 | |
185 | |
186 bool OrientedBoundingBox::HasIntersection(std::vector<Vector>& points, | |
187 const CoordinateSystem3D& plane) const | |
188 { | |
189 // From the vector equation of a 3D plane (specified by origin | |
190 // and normal), to the general equation of a 3D plane (which | |
191 // looses information about the origin of the coordinate system) | |
192 const Vector& normal = plane.GetNormal(); | |
193 const Vector& origin = plane.GetOrigin(); | |
194 double d = -(normal[0] * origin[0] + normal[1] * origin[1] + normal[2] * origin[2]); | |
195 | |
196 return HasIntersectionWithPlane(points, normal, d); | |
197 } | |
198 | |
199 | |
200 bool OrientedBoundingBox::Contains(const Vector& p) const | |
201 { | |
202 assert(p.size() == 3); | |
203 | |
204 const Vector q = p - c_; | |
205 | |
206 return (fabs(boost::numeric::ublas::inner_prod(q, u_)) <= hu_ && | |
207 fabs(boost::numeric::ublas::inner_prod(q, v_)) <= hv_ && | |
208 fabs(boost::numeric::ublas::inner_prod(q, w_)) <= hw_); | |
209 } | |
210 | |
211 | |
212 void OrientedBoundingBox::FromInternalCoordinates(Vector& target, | |
213 double x, | |
214 double y, | |
215 double z) const | |
216 { | |
217 target = (c_ + | |
218 u_ * 2.0 * hu_ * (x - 0.5) + | |
219 v_ * 2.0 * hv_ * (y - 0.5) + | |
220 w_ * 2.0 * hw_ * (z - 0.5)); | |
221 } | |
222 | |
223 | |
224 void OrientedBoundingBox::FromInternalCoordinates(Vector& target, | |
225 const Vector& source) const | |
226 { | |
227 assert(source.size() == 3); | |
228 FromInternalCoordinates(target, source[0], source[1], source[2]); | |
229 } | |
230 | |
231 | |
232 void OrientedBoundingBox::ToInternalCoordinates(Vector& target, | |
233 const Vector& source) const | |
234 { | |
235 assert(source.size() == 3); | |
236 const Vector q = source - c_; | |
237 | |
238 double x = boost::numeric::ublas::inner_prod(q, u_) / (2.0 * hu_) + 0.5; | |
239 double y = boost::numeric::ublas::inner_prod(q, v_) / (2.0 * hv_) + 0.5; | |
240 double z = boost::numeric::ublas::inner_prod(q, w_) / (2.0 * hw_) + 0.5; | |
241 | |
158
a053ca7fa5c6
LinearAlgebra toolbox
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
151
diff
changeset
|
242 LinearAlgebra::AssignVector(target, x, y, z); |
140 | 243 } |
146
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
244 |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
245 |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
246 bool OrientedBoundingBox::ComputeExtent(Extent2D& extent, |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
247 const CoordinateSystem3D& plane) const |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
248 { |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
249 extent.Reset(); |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
250 |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
251 std::vector<Vector> points; |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
252 if (HasIntersection(points, plane)) |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
253 { |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
254 for (size_t i = 0; i < points.size(); i++) |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
255 { |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
256 double x, y; |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
257 plane.ProjectPoint(x, y, points[i]); |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
258 extent.AddPoint(x, y); |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
259 } |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
260 |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
261 return true; |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
262 } |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
263 else |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
264 { |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
265 return false; |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
266 } |
fb7d602e7025
OrientedBoundingBox::ComputeExtent
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
140
diff
changeset
|
267 } |
140 | 268 } |