1 // Boost.Geometry Index
2 //
3 // R-tree OpenGL drawing visitor implementation
4 //
5 // Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
6 //
7 // Use, modification and distribution is subject to the Boost Software License,
8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 
11 #ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
12 #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
13 
14 #include <boost/mpl/assert.hpp>
15 
16 namespace boost { namespace geometry { namespace index { namespace detail {
17 
18 namespace utilities {
19 
20 namespace dispatch {
21 
22 template <typename Point, size_t Dimension>
23 struct gl_draw_point
24 {};
25 
26 template <typename Point>
27 struct gl_draw_point<Point, 2>
28 {
applyboost::geometry::index::detail::utilities::dispatch::gl_draw_point29     static inline void apply(Point const& p, typename coordinate_type<Point>::type z)
30     {
31         typename coordinate_type<Point>::type const& x = geometry::get<0>(p);
32         typename coordinate_type<Point>::type const& y = geometry::get<1>(p);
33         /*glBegin(GL_POINT);
34         glVertex3f(x, y, z);
35         glEnd();*/
36         glBegin(GL_QUADS);
37         glVertex3f(x+1, y, z);
38         glVertex3f(x, y+1, z);
39         glVertex3f(x-1, y, z);
40         glVertex3f(x, y-1, z);
41         glEnd();
42     }
43 };
44 
45 template <typename Box, size_t Dimension>
46 struct gl_draw_box
47 {};
48 
49 template <typename Box>
50 struct gl_draw_box<Box, 2>
51 {
applyboost::geometry::index::detail::utilities::dispatch::gl_draw_box52     static inline void apply(Box const& b, typename coordinate_type<Box>::type z)
53     {
54         glBegin(GL_LINE_LOOP);
55         glVertex3f(geometry::get<min_corner, 0>(b), geometry::get<min_corner, 1>(b), z);
56         glVertex3f(geometry::get<max_corner, 0>(b), geometry::get<min_corner, 1>(b), z);
57         glVertex3f(geometry::get<max_corner, 0>(b), geometry::get<max_corner, 1>(b), z);
58         glVertex3f(geometry::get<min_corner, 0>(b), geometry::get<max_corner, 1>(b), z);
59         glEnd();
60     }
61 };
62 
63 template <typename Segment, size_t Dimension>
64 struct gl_draw_segment
65 {};
66 
67 template <typename Segment>
68 struct gl_draw_segment<Segment, 2>
69 {
applyboost::geometry::index::detail::utilities::dispatch::gl_draw_segment70     static inline void apply(Segment const& s, typename coordinate_type<Segment>::type z)
71     {
72         glBegin(GL_LINES);
73         glVertex3f(geometry::get<0, 0>(s), geometry::get<0, 1>(s), z);
74         glVertex3f(geometry::get<1, 0>(s), geometry::get<1, 1>(s), z);
75         glEnd();
76     }
77 };
78 
79 template <typename Indexable, typename Tag>
80 struct gl_draw_indexable
81 {
82     BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
83 };
84 
85 template <typename Box>
86 struct gl_draw_indexable<Box, box_tag>
87     : gl_draw_box<Box, geometry::dimension<Box>::value>
88 {};
89 
90 template <typename Point>
91 struct gl_draw_indexable<Point, point_tag>
92     : gl_draw_point<Point, geometry::dimension<Point>::value>
93 {};
94 
95 template <typename Segment>
96 struct gl_draw_indexable<Segment, segment_tag>
97     : gl_draw_segment<Segment, geometry::dimension<Segment>::value>
98 {};
99 
100 } // namespace dispatch
101 
102 template <typename Indexable> inline
gl_draw_indexable(Indexable const & i,typename coordinate_type<Indexable>::type z)103 void gl_draw_indexable(Indexable const& i, typename coordinate_type<Indexable>::type z)
104 {
105     dispatch::gl_draw_indexable<
106         Indexable,
107         typename tag<Indexable>::type
108     >::apply(i, z);
109 }
110 
111 } // namespace utilities
112 
113 namespace rtree { namespace utilities {
114 
115 namespace visitors {
116 
117 template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
118 struct gl_draw : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
119 {
120     typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
121     typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
122 
gl_drawboost::geometry::index::detail::rtree::utilities::visitors::gl_draw123     inline gl_draw(Translator const& t,
124                    size_t level_first = 0,
125                    size_t level_last = (std::numeric_limits<size_t>::max)(),
126                    typename coordinate_type<Box>::type z_coord_level_multiplier = 1
127     )
128         : tr(t)
129         , level_f(level_first)
130         , level_l(level_last)
131         , z_mul(z_coord_level_multiplier)
132         , level(0)
133     {}
134 
operator ()boost::geometry::index::detail::rtree::utilities::visitors::gl_draw135     inline void operator()(internal_node const& n)
136     {
137         typedef typename rtree::elements_type<internal_node>::type elements_type;
138         elements_type const& elements = rtree::elements(n);
139 
140         if ( level_f <= level )
141         {
142             size_t level_rel = level - level_f;
143 
144             if ( level_rel == 0 )
145                 glColor3f(0.75f, 0.0f, 0.0f);
146             else if ( level_rel == 1 )
147                 glColor3f(0.0f, 0.75f, 0.0f);
148             else if ( level_rel == 2 )
149                 glColor3f(0.0f, 0.0f, 0.75f);
150             else if ( level_rel == 3 )
151                 glColor3f(0.75f, 0.75f, 0.0f);
152             else if ( level_rel == 4 )
153                 glColor3f(0.75f, 0.0f, 0.75f);
154             else if ( level_rel == 5 )
155                 glColor3f(0.0f, 0.75f, 0.75f);
156             else
157                 glColor3f(0.5f, 0.5f, 0.5f);
158 
159             for (typename elements_type::const_iterator it = elements.begin();
160                 it != elements.end(); ++it)
161             {
162                 detail::utilities::gl_draw_indexable(it->first, level_rel * z_mul);
163             }
164         }
165 
166         size_t level_backup = level;
167         ++level;
168 
169         if ( level < level_l )
170         {
171             for (typename elements_type::const_iterator it = elements.begin();
172                 it != elements.end(); ++it)
173             {
174                 rtree::apply_visitor(*this, *it->second);
175             }
176         }
177 
178         level = level_backup;
179     }
180 
operator ()boost::geometry::index::detail::rtree::utilities::visitors::gl_draw181     inline void operator()(leaf const& n)
182     {
183         typedef typename rtree::elements_type<leaf>::type elements_type;
184         elements_type const& elements = rtree::elements(n);
185 
186         if ( level_f <= level )
187         {
188             size_t level_rel = level - level_f;
189 
190             glColor3f(0.25f, 0.25f, 0.25f);
191 
192             for (typename elements_type::const_iterator it = elements.begin();
193                 it != elements.end(); ++it)
194             {
195                 detail::utilities::gl_draw_indexable(tr(*it), level_rel * z_mul);
196             }
197         }
198     }
199 
200     Translator const& tr;
201     size_t level_f;
202     size_t level_l;
203     typename coordinate_type<Box>::type z_mul;
204 
205     size_t level;
206 };
207 
208 } // namespace visitors
209 
210 template <typename Rtree> inline
gl_draw(Rtree const & tree,size_t level_first=0,size_t level_last=(std::numeric_limits<size_t>::max)(),typename coordinate_type<typename Rtree::bounds_type>::type z_coord_level_multiplier=1)211 void gl_draw(Rtree const& tree,
212              size_t level_first = 0,
213              size_t level_last = (std::numeric_limits<size_t>::max)(),
214              typename coordinate_type<
215                     typename Rtree::bounds_type
216                 >::type z_coord_level_multiplier = 1
217              )
218 {
219     typedef utilities::view<Rtree> RTV;
220     RTV rtv(tree);
221 
222     if ( !tree.empty() )
223     {
224         glColor3f(0.75f, 0.75f, 0.75f);
225         detail::utilities::gl_draw_indexable(tree.bounds(), 0);
226     }
227 
228     visitors::gl_draw<
229         typename RTV::value_type,
230         typename RTV::options_type,
231         typename RTV::translator_type,
232         typename RTV::box_type,
233         typename RTV::allocators_type
234     > gl_draw_v(rtv.translator(), level_first, level_last, z_coord_level_multiplier);
235 
236     rtv.apply_visitor(gl_draw_v);
237 }
238 
239 }} // namespace rtree::utilities
240 
241 }}}} // namespace boost::geometry::index::detail
242 
243 #endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
244