vgl_orient_box_3d.hxx
Go to the documentation of this file.
1 // This is core/vgl/algo/vgl_orient_box_3d.hxx
2 #ifndef vgl_orient_box_3d_hxx_
3 #define vgl_orient_box_3d_hxx_
4 //:
5 // \file
6 
7 #include <iostream>
8 #include "vgl_orient_box_3d.h"
9 #include <vgl/vgl_vector_3d.h>
10 #include <vgl/vgl_tolerance.h>
11 #include <vnl/vnl_det.h>
12 #ifdef _MSC_VER
13 # include <vcl_msvc_warnings.h>
14 #endif
15 
16 //: constructor from four corner points.
17 // The three directions from the first of these to the three other points must be mutually orthogonal.
18 template <class Type>
20  vgl_point_3d<Type> const& px,
21  vgl_point_3d<Type> const& py,
22  vgl_point_3d<Type> const& pz)
23 {
24  // The normalized main axes of the box:
25  vgl_vector_3d<Type> vx = px - p0, vy = py - p0, vz = pz - p0;
26  assert(vx.x() * vy.x() + vx.y() * vy.y() + vx.z() * vy.z() < 0.001 );
27  assert(vz.x() * vy.x() + vz.y() * vy.y() + vz.z() * vy.z() < 0.001 );
28 
29  double lx = vx.length(), ly = vy.length(), lz = vz.length();
30  // the quaternion rotation matrix:
31  vnl_matrix_fixed<double,3,3> rotation;
32  // first row: coordinates of first orthonormal basis vector (etc):
33  rotation(0,0) = vx.x()/lx; rotation(0,1) = vx.y()/lx; rotation(0,2) = vx.z()/lx;
34  rotation(1,0) = vy.x()/ly; rotation(1,1) = vy.y()/ly; rotation(1,2) = vy.z()/ly;
35  rotation(2,0) = vz.x()/lz; rotation(2,1) = vz.y()/lz; rotation(2,2) = vz.z()/lz;
36  // If the transformation matrix has negative determinant, invert px and py:
37  double det = vnl_det(rotation);
38  if (det < 0) {
39  double t = rotation(0,0); rotation(0,0) = rotation(1,0); rotation(1,0) = t;
40  t = rotation(0,1); rotation(0,1) = rotation(1,1); rotation(1,1) = t;
41  t = rotation(0,2); rotation(0,2) = rotation(1,2); rotation(1,2) = t;
42  }
43  orient_ = vnl_quaternion<double>(rotation);
44 
45  // And finally the vgl_box_3d: it is the inversely rotated version of the given 4 points around the centroid:
46  vnl_vector_fixed<double,3> centroid(-0.5*p0.x()+0.5*px.x()+0.5*py.x()+0.5*pz.x(),
47  -0.5*p0.y()+0.5*px.y()+0.5*py.y()+0.5*pz.y(),
48  -0.5*p0.z()+0.5*px.z()+0.5*py.z()+0.5*pz.z());
49  vnl_vector_fixed<double,3> p0_to_centroid = vnl_vector_fixed<double,3>(p0.x(),p0.y(),p0.z()) - centroid;
50  vnl_vector_fixed<double,3> corner_0 = centroid + rotation * p0_to_centroid;
51  vgl_point_3d<Type> corner0((Type)(corner_0[0]), (Type)(corner_0[1]), (Type)(corner_0[2])); // explicitly cast back from double
52  vnl_vector_fixed<double,3> corner_1 = centroid - rotation * p0_to_centroid;
53  vgl_point_3d<Type> corner1((Type)(corner_1[0]), (Type)(corner_1[1]), (Type)(corner_1[2])); // explicitly cast back from double
54  box_ = vgl_box_3d<Type>(corner0, corner1);
55 }
56 
57 //: returns the 8 corner points of the box
58 template <class Type>
59 std::vector<vgl_point_3d<Type> > vgl_orient_box_3d<Type>::corners() const
60 {
61  std::vector<vgl_point_3d<Type> > corner_points(8);
62 
63  //get the min and max of the aab and find the other corners
64  corner_points[0] = box_.min_point();
65  corner_points[7] = box_.max_point();
66 
67  corner_points[1] = vgl_point_3d<Type> (corner_points[0].x()+width(),
68  corner_points[0].y(),
69  corner_points[0].z());
70  corner_points[2] = vgl_point_3d<Type> (corner_points[0].x(),
71  corner_points[0].y(),
72  corner_points[0].z()+depth());
73  corner_points[3] = vgl_point_3d<Type> (corner_points[1].x(),
74  corner_points[1].y(),
75  corner_points[1].z()+depth());
76  corner_points[4] = vgl_point_3d<Type> (corner_points[0].x(),
77  corner_points[0].y()+height(),
78  corner_points[0].z());
79  corner_points[5] = vgl_point_3d<Type> (corner_points[1].x(),
80  corner_points[1].y()+height(),
81  corner_points[1].z());
82  corner_points[6] = vgl_point_3d<Type> (corner_points[2].x(),
83  corner_points[2].y()+height(),
84  corner_points[2].z());
85  // rotate the corner points
86  for (unsigned int i=0; i < corner_points.size(); i++) {
87  vnl_vector_fixed<double,3> p;
88  p[0] = corner_points[i].x() - box_.centroid_x();
89  p[1] = corner_points[i].y() - box_.centroid_y();
90  p[2] = corner_points[i].z() - box_.centroid_z();
91  p = orient_.rotate(p);
92  corner_points[i] = vgl_point_3d<Type> (Type(p[0]) + box_.centroid_x(),
93  Type(p[1]) + box_.centroid_y(),
94  Type(p[2]) + box_.centroid_z());
95  }
96  return corner_points;
97 }
98 
99 template <class Type>
101  std::vector<vgl_point_3d<Type> > crns = this->corners();
102  vgl_box_3d<Type> ret;
103  for(typename std::vector<vgl_point_3d<Type> >::iterator cit = crns.begin();
104  cit != crns.end(); ++cit)
105  ret.add(*cit);
106  return ret;
107 }
108 
109 //: Return true if \a (x,y,z) is inside this box
110 template <class Type>
112  Type const& y,
113  Type const& z) const
114 {
115  // first transform the point to the coordinate system of AABB
116  vnl_quaternion<double> reverse_rot = orient_.inverse();
117 
118  vnl_vector_fixed<double,3> p;
119  p[0] = x - box_.centroid_x();
120  p[1] = y - box_.centroid_y();
121  p[2] = z - box_.centroid_z();
122  p = reverse_rot.rotate(p);
123  Type xt = static_cast<Type>(p[0] + box_.centroid_x());
124  Type yt = static_cast<Type>(p[1] + box_.centroid_y());
125  Type zt = static_cast<Type>(p[2] + box_.centroid_z());
126  return box_.contains(xt, yt, zt);
127 }
128 
129 template <class Type>
130 std::ostream& vgl_orient_box_3d<Type>::print(std::ostream& s) const
131 {
132  return s << "<vgl_orient_box_3d " << box_ << " dir=" << orient_ << '>' << std::endl;
133 }
134 
135 template <class Type>
136 std::istream& vgl_orient_box_3d<Type>::read(std::istream& s)
137 {
138  return s >> box_ >> orient_ ;
139 }
140 
141 //: Write box to stream
142 template <class Type>
143 std::ostream& operator<<(std::ostream& s, vgl_orient_box_3d<Type> const& p)
144 {
145  return p.print(s);
146 }
147 
148 //: Read box from stream
149 template <class Type>
150 std::istream& operator>>(std::istream& is, vgl_orient_box_3d<Type>& p)
151 {
152  return p.read(is);
153 }
154 
155 #undef VGL_ORIENT_BOX_3D_INSTANTIATE
156 #define VGL_ORIENT_BOX_3D_INSTANTIATE(T) \
157 template class vgl_orient_box_3d<T >;\
158 template std::ostream& operator<<(std::ostream&, vgl_orient_box_3d<T > const& p);\
159 template std::istream& operator>>(std::istream&, vgl_orient_box_3d<T >& p)
160 
161 #endif // vgl_orient_box_3d_hxx_
vgl_orient_box_3d()=default
bool contains(Type const &x, Type const &y, Type const &z) const
Return true if (x,y,z) is inside this box.
direction vector in Euclidean 3D space
Represents a cartesian 3D point.
Definition: vgl_fwd.h:11
Type & z()
Definition: vgl_point_3d.h:73
std::vector< vgl_point_3d< Type > > corners() const
returns the 8 corner points of the box.
void add(vgl_point_3d< Type > const &p)
Add a point to this box.
Definition: vgl_box_3d.hxx:373
double length() const
Return the length of this vector.
A bounding oriented box.
T y() const
Definition: vgl_vector_3d.h:37
T x() const
Definition: vgl_vector_3d.h:36
T z() const
Definition: vgl_vector_3d.h:38
Type & x()
Definition: vgl_point_3d.h:71
vgl_box_3d< Type > enclosing_box() const
The axis-aligned box that encloses the oriented box.
std::ostream & print(std::ostream &s) const
Represents a cartesian 3D box.
Definition: vgl_box_3d.h:65
Type & y()
Definition: vgl_point_3d.h:72