Plane.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2016 Imperial College London
5  * Copyright 2016 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_Plane_H
21 #define MIRTK_Plane_H
22 
23 #include "mirtk/Object.h"
24 
25 #include "mirtk/Vector3.h"
26 #include "mirtk/Point.h"
27 #include "mirtk/PointSet.h"
28 
29 
30 namespace mirtk {
31 
32 
33 /**
34  * Plane in 3D space.
35  *
36  * The plane is stored in Hessian normal form. Additionally, the two orthonormal
37  * tangent vectors to the plane normal are stored which are used for projecting
38  * points onto the plane and expressing these as 2D (u, v) coordinates along these
39  * in-plane axes. The vectors Plane::Tangent1, Plane::Tangent2, and Plane::Normal
40  * form a right-handed coordinate system.
41  */
42 class Plane : public Object
43 {
44  mirtkObjectMacro(Plane);
45 
46  // ---------------------------------------------------------------------------
47  // Attributes
48 
49  /// Distance of plane from origin
50  mirtkPublicAttributeMacro(double, Offset);
51 
52  /// First in-plane axis
53  mirtkReadOnlyAttributeMacro(Vector3, Tangent1);
54 
55  /// Second in-plane axis
56  mirtkReadOnlyAttributeMacro(Vector3, Tangent2);
57 
58  /// Plane normal vector
59  mirtkReadOnlyAttributeMacro(Vector3, Normal);
60 
61  /// Origin of plane coordinate system
62  ///
63  /// When a plane is fit to a set of points, the origin is the centroid of the
64  /// point cloud. Otherwise, the origin is the point on the plane that is
65  /// closest to the world origin, i.e., the vector pointing from plane origin
66  /// to the world origin is orthogonal to the plane normal.
67  mirtkReadOnlyAttributeMacro(Point, Origin);
68 
69  /// Copy attributes of this class from another instance
70  void CopyAttributes(const Plane &);
71 
72 protected:
73 
74  /// Update origin after change of plane normal
75  void UpdateOrigin();
76 
77  /// Update tangent vectors after change of plane normal
78  void UpdateTangents();
79 
80  // ---------------------------------------------------------------------------
81  // Construction/Destruction
82 public:
83 
84  /// Default constructor
85  Plane();
86 
87  /// Construct plane given its Hessian normal form parameters
88  ///
89  /// \param[in] n Normal vector.
90  /// \param[in] b Distance of plane to origin.
91  Plane(const Vector3 &n, double b);
92 
93  /// Construct plane given its Hessian normal form parameters
94  ///
95  /// \param[in] n Normal vector.
96  /// \param[in] b Distance of plane to origin.
97  Plane(double n[3], double b);
98 
99  /// Construct plane given its Hessian normal form parameters
100  ///
101  /// \param[in] nx First component of normal vector.
102  /// \param[in] ny Second component of normal vector.
103  /// \param[in] nz Third component of normal vector.
104  /// \param[in] b Distance of plane to origin.
105  Plane(double nx, double ny, double nz, double b);
106 
107  /// Copy constructor
108  Plane(const Plane &);
109 
110  /// Assignment operator
111  Plane &operator =(const Plane &);
112 
113  /// Destructor
114  virtual ~Plane();
115 
116  /// Set normal vector
117  void Normal(const Vector3 &n);
118 
119  /// Set normal vector
120  ///
121  /// \param[in] n Normal vector.
122  void Normal(double n[3]);
123 
124  /// Set normal vector
125  ///
126  /// \param[in] nx First component of normal vector.
127  /// \param[in] ny Second component of normal vector.
128  /// \param[in] nz Third component of normal vector.
129  void Normal(double nx, double ny, double nz);
130 
131  // ---------------------------------------------------------------------------
132  // Model fitting
133 public:
134 
135  /// Fit plane to a set of points
136  ///
137  /// \param[in] points Point cloud.
138  ///
139  /// \returns RMS error of the regression.
140  double Fit(const PointSet &points);
141 
142  // ---------------------------------------------------------------------------
143  // Evaluation
144 
145  /// Evaluates plane equation for a given point
146  ///
147  /// \param[in] p Point.
148  ///
149  /// \returns Signed distance of point to plane.
150  double Evaluate(const Point &p) const;
151 
152  /// Evaluates plane equation for a given point
153  ///
154  /// \param[in] p Point.
155  ///
156  /// \returns Signed distance of point to plane.
157  double Evaluate(const double p[3]) const;
158 
159  /// Evaluates plane equation for a given point
160  ///
161  /// \param[in] x First coordinate of point.
162  /// \param[in] y Second coordinate of point.
163  /// \param[in] z Third coordinate of point.
164  ///
165  /// \returns Signed distance of point to plane.
166  double Evaluate(double x, double y, double z) const;
167 
168  /// Evaluates plane equation for a given point
169  ///
170  /// \param[in] p Point.
171  ///
172  /// \returns Signed distance of point to plane.
173  double Distance(const Point &p) const;
174 
175  /// Evaluates plane equation for a given point
176  ///
177  /// \param[in] p Point.
178  ///
179  /// \returns Signed distance of point to plane.
180  double Distance(const double p[3]) const;
181 
182  /// Evaluates plane equation for a given point
183  ///
184  /// \param[in] x First coordinate of point.
185  /// \param[in] y Second coordinate of point.
186  /// \param[in] z Third coordinate of point.
187  ///
188  /// \returns Signed distance of point to plane.
189  double Distance(double x, double y, double z) const;
190 
191  // ---------------------------------------------------------------------------
192  // Projection
193 
194  /// Project point onto plane
195  ///
196  /// \param[in] p Point.
197  /// \param[out] u Coordinate of projected point along Tangent1.
198  /// \param[out] v Coordinate of projected point along Tangent2.
199  void Project(const Point &p, double &u, double &v) const;
200 
201  /// Project point onto plane
202  ///
203  /// \param[in] p Point.
204  /// \param[out] u Coordinate of projected point along Tangent1.
205  /// \param[out] v Coordinate of projected point along Tangent2.
206  void Project(const double p[3], double &u, double &v) const;
207 
208  /// Project point onto plane
209  ///
210  /// \param[in] x First coordinate of point.
211  /// \param[in] y Second coordinate of point.
212  /// \param[in] z Third coordinate of point.
213  /// \param[out] u Coordinate of projected point along Tangent1.
214  /// \param[out] v Coordinate of projected point along Tangent2.
215  void Project(double x, double y, double z, double &u, double &v) const;
216 
217  // ---------------------------------------------------------------------------
218  // Debugging
219 
220  /// Print plane equation
221  ostream &Print(ostream &os, Indent = 0) const;
222 
223  /// Print plane equation to standard output stream
224  void Print(Indent = 0) const;
225 
226 };
227 
228 ////////////////////////////////////////////////////////////////////////////////
229 // Inline definitions
230 ////////////////////////////////////////////////////////////////////////////////
231 
232 // =============================================================================
233 // Construction/Destruction
234 // =============================================================================
235 
236 // -----------------------------------------------------------------------------
237 inline Plane::Plane()
238 :
239  _Offset(.0),
240  _Tangent1(1.0, .0, .0),
241  _Tangent2(.0, 1.0, .0),
242  _Normal (.0, .0, 1.0),
243  _Origin (.0, .0, .0)
244 {
245 }
246 
247 // -----------------------------------------------------------------------------
248 inline Plane::Plane(const Vector3 &n, double b)
249 :
250  _Offset(b),
251  _Normal(n)
252 {
253  UpdateOrigin();
254  UpdateTangents();
255 }
256 
257 // -----------------------------------------------------------------------------
258 inline Plane::Plane(double n[3], double b)
259 :
260  _Offset(b),
261  _Normal(n[0], n[1], n[2])
262 {
263  UpdateOrigin();
264  UpdateTangents();
265 }
266 
267 // -----------------------------------------------------------------------------
268 inline Plane::Plane(double nx, double ny, double nz, double b)
269 :
270  _Offset(b),
271  _Normal(nx, ny, nz)
272 {
273  UpdateOrigin();
274  UpdateTangents();
275 }
276 
277 // -----------------------------------------------------------------------------
278 inline void Plane::CopyAttributes(const Plane &other)
279 {
280  _Offset = other._Offset;
281  _Normal = other._Normal;
282  _Tangent1 = other._Tangent1;
283  _Tangent2 = other._Tangent2;
284  _Origin = other._Origin;
285 }
286 
287 // -----------------------------------------------------------------------------
288 inline Plane::Plane(const Plane &other)
289 {
290  CopyAttributes(other);
291 }
292 
293 // -----------------------------------------------------------------------------
294 inline Plane &Plane::operator =(const Plane &other)
295 {
296  if (this != &other) {
297  Object::operator =(other);
298  CopyAttributes(other);
299  }
300  return *this;
301 }
302 
303 // -----------------------------------------------------------------------------
305 {
306 }
307 
308 // -----------------------------------------------------------------------------
309 inline void Plane::Normal(const Vector3 &n)
310 {
311  _Normal = n;
312  UpdateOrigin();
313  UpdateTangents();
314 }
315 
316 // -----------------------------------------------------------------------------
317 inline void Plane::Normal(double n[3])
318 {
319  _Normal[0] = n[0];
320  _Normal[1] = n[1];
321  _Normal[2] = n[2];
322  UpdateOrigin();
323  UpdateTangents();
324 }
325 
326 // -----------------------------------------------------------------------------
327 inline void Plane::Normal(double nx, double ny, double nz)
328 {
329  _Normal[0] = nx;
330  _Normal[1] = ny;
331  _Normal[2] = nz;
332  UpdateOrigin();
333  UpdateTangents();
334 }
335 
336 // =============================================================================
337 // Evaluation
338 // =============================================================================
339 
340 // -----------------------------------------------------------------------------
341 inline double Plane::Evaluate(const Point &p) const
342 {
343  return p._x * _Normal[0] + p._y * _Normal[1] + p._z * _Normal[2] - _Offset;
344 }
345 
346 // -----------------------------------------------------------------------------
347 inline double Plane::Evaluate(const double p[3]) const
348 {
349  return p[0] * _Normal[0] + p[1] * _Normal[1] + p[2] * _Normal[2] - _Offset;
350 }
351 
352 // -----------------------------------------------------------------------------
353 inline double Plane::Evaluate(double x, double y, double z) const
354 {
355  return x * _Normal[0] + y * _Normal[1] + z * _Normal[2] - _Offset;
356 }
357 
358 // -----------------------------------------------------------------------------
359 inline double Plane::Distance(const Point &p) const
360 {
361  return Evaluate(p);
362 }
363 
364 // -----------------------------------------------------------------------------
365 inline double Plane::Distance(const double p[3]) const
366 {
367  return Evaluate(p);
368 }
369 
370 // -----------------------------------------------------------------------------
371 inline double Plane::Distance(double x, double y, double z) const
372 {
373  return Evaluate(x, y, z);
374 }
375 
376 // =============================================================================
377 // Projection
378 // =============================================================================
379 
380 // -----------------------------------------------------------------------------
381 inline void Plane::Project(const Point &p, double &u, double &v) const
382 {
383  Vector3 d(p._x - _Origin._x, p._y - _Origin._y, p._z - _Origin._z);
384  u = _Tangent1.Dot(d);
385  v = _Tangent2.Dot(d);
386 }
387 
388 // -----------------------------------------------------------------------------
389 inline void Plane::Project(const double p[3], double &u, double &v) const
390 {
391  Vector3 d(p[0] - _Origin._x, p[1] - _Origin._y, p[2] - _Origin._z);
392  u = _Tangent1.Dot(d);
393  v = _Tangent2.Dot(d);
394 }
395 
396 // -----------------------------------------------------------------------------
397 inline void Plane::Project(double x, double y, double z, double &u, double &v) const
398 {
399  Vector3 d(x - _Origin._x, y - _Origin._y, z - _Origin._z);
400  u = _Tangent1.Dot(d);
401  v = _Tangent2.Dot(d);
402 }
403 
404 // =============================================================================
405 // Debugging
406 // =============================================================================
407 
408 // -----------------------------------------------------------------------------
409 inline void Plane::Print(Indent indent) const
410 {
411  Print(cout, indent);
412 }
413 
414 
415 } // namespace mirtk
416 
417 #endif // MIRTK_Plane_H
Plane()
Default constructor.
Definition: Plane.h:237
double Distance(const Point &p) const
Definition: Plane.h:359
double _x
x coordinate of Point
Definition: Point.h:46
void Project(const Point &p, double &u, double &v) const
Definition: Plane.h:381
Definition: IOConfig.h:41
void UpdateOrigin()
Update origin after change of plane normal.
virtual ~Plane()
Destructor.
Definition: Plane.h:304
ostream & Print(ostream &os, Indent=0) const
Print plane equation.
double Fit(const PointSet &points)
double Evaluate(const Point &p) const
Definition: Plane.h:341
Plane & operator=(const Plane &)
Assignment operator.
Definition: Plane.h:294
void Normal(const Vector3 &n)
Set normal vector.
Definition: Plane.h:309
double _z
z coordinate of Point
Definition: Point.h:48
double _y
y coordinate of Point
Definition: Point.h:47
void UpdateTangents()
Update tangent vectors after change of plane normal.