vgl_frustum_3d.hxx
Go to the documentation of this file.
1 #ifndef vgl_frustum_3d_hxx_
2 #define vgl_frustum_3d_hxx_
3 
4 #include <iostream>
5 #include <cmath>
6 #include <vgl/vgl_frustum_3d.h>
7 #include <vgl/vgl_ray_3d.h>
8 #include <vgl/vgl_plane_3d.h>
9 #include <vgl/vgl_tolerance.h>
10 #include <vgl/vgl_intersection.h>
11 #ifdef _MSC_VER
12 # include <vcl_msvc_warnings.h>
13 #endif
14 //:
15 template <class Type>
17 vgl_frustum_3d(std::vector<vgl_ray_3d<Type> > const& corner_rays,
18  vgl_vector_3d<Type> const& norm, Type d0, Type d1){
19 
20  //Construct cone bounding planes. Their surface normals point outward from
21  //the interior of the frustum. It is assumed the rays are in order
22  //around the boundaries of the parallel faces, so that adjacent rays
23  //define the cone surface planes with outward pointing normals
24  int nc = static_cast<int>(corner_rays.size());
25  assert(nc>=3);//need to enclose a volume
26  n_top_bot_face_verts_= nc;
27  norm_ = norm;
28  // contruct the near plane
29  vgl_ray_3d<Type> r0 = corner_rays[0];
30  apex_ = r0.origin();
31  // find a point on the near plane
32  vgl_vector_3d<Type> dir = r0.direction();
33  // ray shouldn't be perpendicular to near plane normal
34  double er = std::fabs(cos_angle(norm, dir));
36  double dp = dot_product(norm, dir);
37  // the normal to the near parallel face must point to the apex
38  // since the apex is, by defintion, outside the frustum volume
39  vgl_vector_3d<Type> snorm = norm;
40  if(dp>0) snorm = -norm;
41  double dp_mag = std::fabs(dp);
42  double tau_near = d0/dp_mag;
43  vgl_point_3d<Type> p_near = apex_ + (tau_near*dir);
44  vgl_plane_3d<Type> pln_near(snorm, p_near);
45  near_plane_ = static_cast<int>(surface_planes_.size());
46  surface_planes_.push_back(pln_near);
47 
48  //define the verts on the near plane
49  verts_.push_back(p_near);
50  for(int i = 1; i<nc; ++i){
51  // find the intersection point of ri, i>0, with the top plane
52  vgl_point_3d<Type> pint;
53  bool good = vgl_intersection<Type>(corner_rays[i], pln_near, pint);
54  assert(good);
55  verts_.push_back(pint);
56  }
57  // check order
58  vgl_vector_3d<Type> v01 = verts_[1]-verts_[0];
59  vgl_vector_3d<Type> v12 = verts_[2]-verts_[1];
60  vgl_vector_3d<Type> out = cross_product(v01, v12);
61  bool rays_ccw_top = dot_product(norm, out) > 0;
62  if(rays_ccw_top)
63  for(int i = 0; i<nc; ++i)
64  faces_[near_plane_].push_back(i);
65  else
66  for(int i = nc-1; i>=0; --i)
67  faces_[near_plane_].push_back(i);
68  // for now, the test for inside assumes a convex frustum FIX_ME
69  assert(this->is_convex());
70  // define the far plane
71  double tau_far = d1/dp_mag;
72  vgl_point_3d<Type> p_far = apex_ + (tau_far*dir);
73  int far_indx = static_cast<int>(verts_.size());
74  verts_.push_back(p_far);
75  // the normal to the far parallel face must point away from the apex
76  vgl_plane_3d<Type> pln_far(-snorm, p_far);
77  far_plane_ = static_cast<int>(surface_planes_.size());
78  surface_planes_.push_back(pln_far);
79  // compute the verts on the far plane
80  for(int i = 1; i<nc; ++i){
81  // find the intersection point of ri, i>0, with the top plane
83  bool good = vgl_intersection<Type>(corner_rays[i], pln_far, pi);
84  assert(good);
85  verts_.push_back(pi);
86  }
87  // form the far face. order is reversed on far face so normal is pointing out
88  if(rays_ccw_top)
89  for(int i = nc-1; i>=0; --i)
90  faces_[far_plane_].push_back(i+far_indx);
91  else
92  for(int i = 0; i<nc; ++i)
93  faces_[near_plane_].push_back(i+far_indx);
94 
95  // find the side cone planes and associated face verts
96  // each side face has four vertices, two on the near face and two
97  // on the far face
98  std::vector<int>& top_verts = faces_[near_plane_];
99  for(int i = 0; i<nc; ++i){
100  int j = top_verts[i];
101  int j_next = top_verts[(i+1)%nc];
102  const vgl_ray_3d<Type>& ra = corner_rays[j];
103  const vgl_ray_3d<Type>& rb = corner_rays[j_next];
104  vgl_plane_3d<Type> pln(ra, rb);
105  int pln_index = static_cast<int>(surface_planes_.size());
106  surface_planes_.push_back(pln);
107  faces_[pln_index].push_back(j); faces_[pln_index].push_back(j_next);
108  faces_[pln_index].push_back(j_next+far_indx);
109  faces_[pln_index].push_back(j+far_indx);
110  }
111 }
112 
113 template <class Type>
115  // check addresses
116  if(this == &other)
117  return true;
118  // check apex
119  if(!(apex_ == other.apex()))
120  return false;
121  int n = static_cast<int>(verts_.size());
122  const std::vector<vgl_point_3d<Type> >& o_verts = other.verts();
123  // could be round off error
124  for(int i = 0; i<n; ++i){
125  double dif = (verts_[i] - o_verts[i]).length();
127  return false;
128  }
129  return true;
130 }
131 template <class Type>
133  vgl_box_3d<Type> box;
134  int n = static_cast<int>(verts_.size());
135  for(int i = 0; i<n; ++i)
136  box.add(verts_[i]);
137  return box;
138 }
139 template <class Type>
141  int n = static_cast<int>(verts_.size());
142  double x_sum = 0.0, y_sum = 0.0, z_sum = 0.0;
143  for(int i = 0; i<n; ++i){
144  x_sum += static_cast<double>(verts_[i].x());
145  y_sum += static_cast<double>(verts_[i].y());
146  z_sum += static_cast<double>(verts_[i].z());
147  }
148  x_sum /= n; y_sum /= n; z_sum /= n;
149  Type x = static_cast<Type>(x_sum);
150  Type y = static_cast<Type>(y_sum);
151  Type z = static_cast<Type>(z_sum);
152  return vgl_point_3d<Type>(x, y, z);
153 }
154 // traverse the top face and compute the cross product of sequential
155 // face edges
156 template <class Type>
158  int n = n_top_bot_face_verts_;
159  if(n<3) return false;
160  if(n==3) return true;
161  // n > 3
162  // get the vertex map for the top face
163  std::map<int, std::vector<int> >::const_iterator vit;
164  vit = faces_.find(near_plane_);//use find since [] is non-const
165  if(vit==faces_.end()) return false;
166  const std::vector<int>& vindx = (*vit).second;
167  vgl_vector_3d<Type> v = verts_[vindx[1]]-verts_[vindx[0]];
168  vgl_vector_3d<Type> v_pre = verts_[vindx[2]]-verts_[vindx[1]];
169  vgl_vector_3d<Type> cr = cross_product(v, v_pre);
170  Type dp = dot_product(cr, norm_);
171  bool pos = dp > vgl_tolerance<Type>::position;
172  for(int i = 2; i<n; ++i){
173  int j = (vindx[i]+1)%n;
174  vgl_vector_3d<Type> v_nxt = verts_[j]-verts_[vindx[i]];
175  cr = cross_product(v_pre, v_nxt);
176  dp = dot_product(cr, norm_);
177  bool pos_i = dp > vgl_tolerance<Type>::position;
178  if(pos_i != pos) return false;
179  v_pre = v_nxt;
180  }
181  return true;
182 }
183 
184 template <class Type>
186 contains(Type const& x, Type const& y, Type const& z) const{
187 
188  // the point must be on the inside of all the faces,
189  // assuming that the fustrum is a convex solid.
190  int n = static_cast<int>(surface_planes_.size());
191  bool inside = true;
192  for(int i = 0; i<n&&inside; ++i){
193  Type a = surface_planes_[i].a(), b = surface_planes_[i].b();
194  Type c = surface_planes_[i].c(), d = surface_planes_[i].d();
195  Type sign = a*x + b*y + c*z +d;
196  inside = sign < vgl_tolerance<Type>::position;
197  }
198  return inside;
199 }
200 
201 template <class Type>
203  return contains(p.x(), p.y(), p.z());
204 }
205 
206 template <class Type>
207 std::ostream& operator<<(std::ostream& s, vgl_frustum_3d<Type> const& f){
208  s << "<vgl_frustum_3d [\n";
209  const std::vector<vgl_point_3d<Type> >& verts = f.verts();
210  int n = static_cast<int>(verts.size());
211  for(int i = 0; i<n; ++i)
212  s << verts[i] << '\n';
213  s << "] >\n";
214  return s;
215 }
216 #undef VGL_FRUSTUM_3D_INSTANTIATE
217 #define VGL_FRUSTUM_3D_INSTANTIATE(Type) \
218 template class vgl_frustum_3d<Type >;\
219 template std::ostream& operator<<(std::ostream&, vgl_frustum_3d<Type > const& f)
220 
221 #endif //vgl_frustum_3d_hxx_
Set of intersection functions.
T dot_product(v const &a, v const &b)
dot product or inner product of two vectors.
A 3D frustum is the portion of a solid (normally a cone or pyramid).
bool contains(vgl_point_3d< Type > const &p) const
Return true iff the point p is inside this frustum.
Represents a cartesian 3D point.
Definition: vgl_fwd.h:11
std::ostream & operator<<(std::ostream &s, vgl_orient_box_3d< Type > const &p)
Write box to stream.
A 3-d ray defined by an origin and a direction vector.
double length(v const &a)
Return the length of a vector.
Definition: vgl_vector_2d.h:94
Type & z()
Definition: vgl_point_3d.h:73
#define v
Definition: vgl_vector_2d.h:74
void add(vgl_point_3d< Type > const &p)
Add a point to this box.
Definition: vgl_box_3d.hxx:373
vgl_box_3d< Type > bounding_box() const
bool operator==(vgl_frustum_3d< Type > const &other) const
Equality test.
const std::vector< vgl_point_3d< Type > > & verts() const
T cross_product(v const &a, v const &b)
cross product of two vectors (area of enclosed parallellogram).
Represents a Euclidean 3D plane.
Definition: vgl_fwd.h:23
const vgl_point_3d< Type > & apex() const
Represents a 3-d ray.
Definition: vgl_fwd.h:21
bool is_convex() const
test if the frustum is convex.
vgl_point_3d< Type > origin() const
Accessors.
Definition: vgl_ray_3d.h:66
Type & x()
Definition: vgl_point_3d.h:71
vgl_point_3d< Type > centroid() const
Get the centroid point.
vgl_frustum_3d()
default constructor.
a plane in 3D nonhomogeneous space
Represents a cartesian 3D box.
Definition: vgl_box_3d.h:65
double cos_angle(v const &a, v const &b)
cosine of the angle between two vectors.
vgl_vector_3d< Type > direction() const
Definition: vgl_ray_3d.h:68
A polygonal cone truncated by parallel planes.
Type & y()
Definition: vgl_point_3d.h:72