1 // This is core/vgl/algo/vgl_rtree_c.h
2 #ifndef vgl_rtree_c_h_
3 #define vgl_rtree_c_h_
4 //:
5 // \file
6 // \brief C helper classes for vgl_rtree
7 // \author J.L. Mundy
8 // \date November 14, 2008
9 // \verbatim
10 //  Modifications
11 //   <None yet>
12 // \endverbatim
13 //
14 // vgl_rtree stores elements of type V with regions described by
15 // bounds type B. The C helper class implements the bounding predicates
16 // between V and B. Thus V and B remain independent of each other.
17 //
18 #include <vgl/vgl_point_2d.h>
19 #include <vgl/vgl_box_2d.h>
20 #include <vgl/vgl_polygon.h>
21 #include <vgl/vgl_intersection.h>
22 #include <vgl/vgl_area.h>
23 template <class V, class B, class C> class vgl_rtree_probe;
24 
25 //: vgl_rtree Class C for V=vgl_point_2d<T>, B = vgl_box_2d<T>
26 template <class T>
27 class vgl_rtree_point_box_2d
28 {
29   // only static methods
30   vgl_rtree_point_box_2d() = delete;
31   ~vgl_rtree_point_box_2d() = delete;
32 
33  public:
34   typedef vgl_point_2d<T> v_type;
35   typedef vgl_box_2d<T> b_type;
36   typedef T t_type;
37   // Operations------
init(vgl_box_2d<T> & b,vgl_point_2d<T> const & p)38   static void  init  (vgl_box_2d<T>& b, vgl_point_2d<T> const& p)
39   { b = vgl_box_2d<T>();  b.add(p); }
40 
update(vgl_box_2d<T> & b,vgl_point_2d<T> const & p)41   static void  update(vgl_box_2d<T>& b, vgl_point_2d<T> const& p)
42   { b.add(p); }
43 
update(vgl_box_2d<T> & b0,vgl_box_2d<T> const & b1)44   static void  update(vgl_box_2d<T>& b0, vgl_box_2d<T> const &b1)
45   { b0.add(b1.min_point());  b0.add(b1.max_point()); }
46 
meet(vgl_box_2d<T> const & b,vgl_point_2d<T> const & p)47   static bool  meet(vgl_box_2d<T> const& b, vgl_point_2d<T> const& p)
48   { return b.contains(p); }
49 
meet(vgl_box_2d<T> const & b0,vgl_box_2d<T> const & b1)50   static bool  meet(vgl_box_2d<T> const& b0, vgl_box_2d<T> const& b1) {
51     vgl_box_2d<T> bint = vgl_intersection<T>(b0, b1);
52     return !bint.is_empty();
53   }
54 
volume(vgl_box_2d<T> const & b)55   static float volume(vgl_box_2d<T> const& b)
56   { return static_cast<float>(vgl_area(b)); }
57 
58   // point meets for a polygon, used by generic rtree probe
meets(vgl_point_2d<T> const & v,vgl_polygon<T> poly)59   static bool meets(vgl_point_2d<T> const& v, vgl_polygon<T> poly)
60   { return poly.contains(v); }
61 
62   // box meets for a polygon, used by generic rtree probe
meets(vgl_box_2d<T> const & b,vgl_polygon<T> poly)63   static bool meets(vgl_box_2d<T> const& b, vgl_polygon<T> poly)
64   { return vgl_intersection<T>(b, poly); }
65 };
66 
67 
68 //: vgl_rtree Class C for V=vgl_box_2d<T>, B = vgl_rbox_2d<T>
69 //  Need to distinguish bounds type from stored element type,
70 //  so create minimal subclass of vgl_box_2d
71 template <class Type>
72 class vgl_bbox_2d : public vgl_box_2d<Type>
73 {
74  public:
75   //: Default constructor (creates empty box)
76   vgl_bbox_2d() = default;
77 
78   //: Construct using two corner points
vgl_bbox_2d(Type const min_position[2],Type const max_position[2])79   vgl_bbox_2d(Type const min_position[2],
80               Type const max_position[2])
81   : vgl_box_2d<Type>(min_position[2], max_position[2]) {}
82 
83   //: Construct using two corner points
vgl_bbox_2d(vgl_point_2d<Type> const & min_pos,vgl_point_2d<Type> const & max_pos)84   vgl_bbox_2d(vgl_point_2d<Type> const& min_pos,
85               vgl_point_2d<Type> const& max_pos)
86   : vgl_box_2d<Type>(min_pos, max_pos) {}
87 
88   //: Construct using ranges in \a x (first two args) and \a y (last two)
vgl_bbox_2d(Type xmin,Type xmax,Type ymin,Type ymax)89   vgl_bbox_2d(Type xmin, Type xmax, Type ymin, Type ymax)
90   : vgl_box_2d<Type>(xmin, xmax, ymin, ymax) {}
91 
92   //: Equality test
93   inline bool operator==(vgl_bbox_2d<Type> const& b) const {
94     // All empty boxes are equal:
95     if (b.is_empty()) return this->is_empty();
96     return  this->min_x() == b.min_x() && this->min_y() == b.min_y()
97          && this->max_x() == b.max_x() && this->max_y() == b.max_y();
98   }
99 };
100 
101 template <class T>
102 class vgl_rtree_box_box_2d
103 {
104   // only static methods
105   vgl_rtree_box_box_2d() = delete;
106   ~vgl_rtree_box_box_2d() = delete;
107 
108  public:
109   typedef vgl_box_2d<T> v_type;
110   typedef vgl_bbox_2d<T> b_type;
111   typedef T t_type;
112   // Operations------
init(vgl_bbox_2d<T> & b,vgl_box_2d<T> const & v)113   static void  init  (vgl_bbox_2d<T>& b, vgl_box_2d<T> const& v)
114   { b = vgl_bbox_2d<T>();  b.add(v.min_point()); b.add(v.max_point()); }
115 
update(vgl_bbox_2d<T> & b,vgl_box_2d<T> const & v)116   static void  update(vgl_bbox_2d<T>& b, vgl_box_2d<T> const& v)
117   { b.add(v.min_point()); b.add(v.max_point()); }
118 
update(vgl_bbox_2d<T> & b0,vgl_bbox_2d<T> const & b1)119   static void  update(vgl_bbox_2d<T>& b0, vgl_bbox_2d<T> const &b1)
120   { b0.add(b1.min_point());  b0.add(b1.max_point()); }
121 
meet(vgl_bbox_2d<T> const & b0,vgl_box_2d<T> const & v)122   static bool  meet(vgl_bbox_2d<T> const& b0, vgl_box_2d<T> const& v) {
123     bool resultf =(b0.contains(v.min_point()) || b0.contains(v.max_point()));
124     bool resultr =(v.contains(b0.min_point()) || v.contains(b0.max_point()));
125     return resultf||resultr;
126   }
127 
meet(vgl_bbox_2d<T> const & b0,vgl_bbox_2d<T> const & b1)128   static bool  meet(vgl_bbox_2d<T> const& b0, vgl_bbox_2d<T> const& b1) {
129     bool resultf =(b0.contains(b1.min_point()) || b0.contains(b1.max_point()));
130     bool resultr =(b1.contains(b0.min_point()) || b1.contains(b0.max_point()));
131     return resultf||resultr;
132   }
133 
volume(vgl_box_2d<T> const & b)134   static float volume(vgl_box_2d<T> const& b)
135   { return static_cast<float>(vgl_area(b)); }
136 
137   // box_2d meets for a polygon, used by generic rtree probe
meets(vgl_box_2d<T> const & b,vgl_polygon<T> poly)138   static bool meets(vgl_box_2d<T> const& b, vgl_polygon<T> poly)
139   { return vgl_rtree_point_box_2d<T>::meets(b, poly); }
140 
meets(vgl_bbox_2d<T> const & b,vgl_polygon<T> poly)141   static bool meets(vgl_bbox_2d<T> const& b, vgl_polygon<T> poly)
142   { return vgl_rtree_point_box_2d<T>::meets(b, poly); }
143 };
144 
145 template <class V, class B, class C>
146 class vgl_rtree_polygon_probe : public vgl_rtree_probe<V, B, C>
147 {
148   typedef typename C::t_type T;
149   vgl_polygon<T> poly_;
150  public:
vgl_rtree_polygon_probe(vgl_polygon<T> const & poly)151   vgl_rtree_polygon_probe(vgl_polygon<T> const& poly): poly_(poly) {}
152 
153   //: return true if the probe "meets" the given object.
meets(V const & v)154   bool meets(V const &v) const override {return C::meets(v, poly_); }
meets(B const & b)155   bool meets(B const &b) const override {return C::meets(b, poly_); }
156 };
157 
158 #endif // vgl_rtree_c_h_
159