Chris@16
|
1 // Boost.Geometry Index
|
Chris@16
|
2 //
|
Chris@101
|
3 // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
Chris@16
|
4 //
|
Chris@16
|
5 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8
|
Chris@16
|
9 #ifndef BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
|
Chris@16
|
10 #define BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
|
Chris@16
|
11
|
Chris@16
|
12 //#include <boost/serialization/serialization.hpp>
|
Chris@16
|
13 #include <boost/serialization/split_member.hpp>
|
Chris@16
|
14 #include <boost/serialization/version.hpp>
|
Chris@16
|
15 //#include <boost/serialization/nvp.hpp>
|
Chris@16
|
16
|
Chris@16
|
17 // TODO
|
Chris@16
|
18 // how about using the unsigned type capable of storing Max in compile-time versions?
|
Chris@16
|
19
|
Chris@16
|
20 // TODO
|
Chris@16
|
21 // - add wrappers for Point and Box and implement serialize for those wrappers instead of
|
Chris@16
|
22 // raw geometries
|
Chris@16
|
23 // PROBLEM: after implementing this, how Values would be set?
|
Chris@16
|
24 // - store the name of the parameters to know how to load and detect errors
|
Chris@16
|
25 // - in the header, once store info about the Indexable and Bounds types (geometry type, point CS, Dim, etc.)
|
Chris@16
|
26 // each geometry save without this info
|
Chris@16
|
27
|
Chris@16
|
28 // TODO - move to index/detail/serialization.hpp
|
Chris@16
|
29 namespace boost { namespace geometry { namespace index { namespace detail {
|
Chris@16
|
30
|
Chris@16
|
31 // TODO - use boost::move?
|
Chris@16
|
32 template<typename T>
|
Chris@16
|
33 class serialization_storage
|
Chris@16
|
34 {
|
Chris@16
|
35 public:
|
Chris@16
|
36 template <typename Archive>
|
Chris@16
|
37 serialization_storage(Archive & ar, unsigned int version)
|
Chris@16
|
38 {
|
Chris@16
|
39 boost::serialization::load_construct_data_adl(ar, this->address(), version);
|
Chris@16
|
40 }
|
Chris@16
|
41 ~serialization_storage()
|
Chris@16
|
42 {
|
Chris@16
|
43 this->address()->~T();
|
Chris@16
|
44 }
|
Chris@16
|
45 T * address()
|
Chris@16
|
46 {
|
Chris@16
|
47 return static_cast<T*>(m_storage.address());
|
Chris@16
|
48 }
|
Chris@16
|
49 private:
|
Chris@16
|
50 boost::aligned_storage<sizeof(T), boost::alignment_of<T>::value> m_storage;
|
Chris@16
|
51 };
|
Chris@16
|
52
|
Chris@16
|
53 // TODO - save and load item_version? see: collections_load_imp and collections_save_imp
|
Chris@16
|
54 // this should be done once for the whole container
|
Chris@16
|
55 // versions of all used types should be stored
|
Chris@16
|
56
|
Chris@16
|
57 template <typename T, typename Archive> inline
|
Chris@16
|
58 T serialization_load(const char * name, Archive & ar)
|
Chris@16
|
59 {
|
Chris@16
|
60 namespace bs = boost::serialization;
|
Chris@16
|
61 serialization_storage<T> storage(ar, bs::version<T>::value); // load_construct_data
|
Chris@16
|
62 ar >> boost::serialization::make_nvp(name, *storage.address()); // serialize
|
Chris@16
|
63 //ar >> *storage.address(); // serialize
|
Chris@16
|
64 return *storage.address();
|
Chris@16
|
65 }
|
Chris@16
|
66
|
Chris@16
|
67 template <typename T, typename Archive> inline
|
Chris@16
|
68 void serialization_save(T const& t, const char * name, Archive & ar)
|
Chris@16
|
69 {
|
Chris@16
|
70 namespace bs = boost::serialization;
|
Chris@16
|
71 bs::save_construct_data_adl(ar, boost::addressof(t), bs::version<T>::value); // save_construct_data
|
Chris@16
|
72 ar << boost::serialization::make_nvp(name, t); // serialize
|
Chris@16
|
73 //ar << t; // serialize
|
Chris@16
|
74 }
|
Chris@16
|
75
|
Chris@16
|
76 }}}}
|
Chris@16
|
77
|
Chris@16
|
78 // TODO - move to index/serialization/rtree.hpp
|
Chris@16
|
79 namespace boost { namespace serialization {
|
Chris@16
|
80
|
Chris@16
|
81 // boost::geometry::index::linear
|
Chris@16
|
82
|
Chris@16
|
83 template<class Archive, size_t Max, size_t Min>
|
Chris@16
|
84 void save_construct_data(Archive & ar, const boost::geometry::index::linear<Max, Min> * params, unsigned int )
|
Chris@16
|
85 {
|
Chris@16
|
86 size_t max = params->get_max_elements(), min = params->get_min_elements();
|
Chris@16
|
87 ar << boost::serialization::make_nvp("max", max);
|
Chris@16
|
88 ar << boost::serialization::make_nvp("min", min);
|
Chris@16
|
89 }
|
Chris@16
|
90 template<class Archive, size_t Max, size_t Min>
|
Chris@16
|
91 void load_construct_data(Archive & ar, boost::geometry::index::linear<Max, Min> * params, unsigned int )
|
Chris@16
|
92 {
|
Chris@16
|
93 size_t max, min;
|
Chris@16
|
94 ar >> boost::serialization::make_nvp("max", max);
|
Chris@16
|
95 ar >> boost::serialization::make_nvp("min", min);
|
Chris@16
|
96 if ( max != params->get_max_elements() || min != params->get_min_elements() )
|
Chris@16
|
97 // TODO change exception type
|
Chris@16
|
98 BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
|
Chris@16
|
99 // the constructor musn't be called for this type
|
Chris@16
|
100 //::new(params)boost::geometry::index::linear<Max, Min>();
|
Chris@16
|
101 }
|
Chris@16
|
102 template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::linear<Max, Min> &, unsigned int) {}
|
Chris@16
|
103
|
Chris@16
|
104 // boost::geometry::index::quadratic
|
Chris@16
|
105
|
Chris@16
|
106 template<class Archive, size_t Max, size_t Min>
|
Chris@16
|
107 void save_construct_data(Archive & ar, const boost::geometry::index::quadratic<Max, Min> * params, unsigned int )
|
Chris@16
|
108 {
|
Chris@16
|
109 size_t max = params->get_max_elements(), min = params->get_min_elements();
|
Chris@16
|
110 ar << boost::serialization::make_nvp("max", max);
|
Chris@16
|
111 ar << boost::serialization::make_nvp("min", min);
|
Chris@16
|
112 }
|
Chris@16
|
113 template<class Archive, size_t Max, size_t Min>
|
Chris@16
|
114 void load_construct_data(Archive & ar, boost::geometry::index::quadratic<Max, Min> * params, unsigned int )
|
Chris@16
|
115 {
|
Chris@16
|
116 size_t max, min;
|
Chris@16
|
117 ar >> boost::serialization::make_nvp("max", max);
|
Chris@16
|
118 ar >> boost::serialization::make_nvp("min", min);
|
Chris@16
|
119 if ( max != params->get_max_elements() || min != params->get_min_elements() )
|
Chris@16
|
120 // TODO change exception type
|
Chris@16
|
121 BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
|
Chris@16
|
122 // the constructor musn't be called for this type
|
Chris@16
|
123 //::new(params)boost::geometry::index::quadratic<Max, Min>();
|
Chris@16
|
124 }
|
Chris@16
|
125 template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::quadratic<Max, Min> &, unsigned int) {}
|
Chris@16
|
126
|
Chris@16
|
127 // boost::geometry::index::rstar
|
Chris@16
|
128
|
Chris@16
|
129 template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
|
Chris@16
|
130 void save_construct_data(Archive & ar, const boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )
|
Chris@16
|
131 {
|
Chris@16
|
132 size_t max = params->get_max_elements()
|
Chris@16
|
133 , min = params->get_min_elements()
|
Chris@16
|
134 , re = params->get_reinserted_elements()
|
Chris@16
|
135 , oct = params->get_overlap_cost_threshold();
|
Chris@16
|
136 ar << boost::serialization::make_nvp("max", max);
|
Chris@16
|
137 ar << boost::serialization::make_nvp("min", min);
|
Chris@16
|
138 ar << boost::serialization::make_nvp("re", re);
|
Chris@16
|
139 ar << boost::serialization::make_nvp("oct", oct);
|
Chris@16
|
140 }
|
Chris@16
|
141 template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
|
Chris@16
|
142 void load_construct_data(Archive & ar, boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )
|
Chris@16
|
143 {
|
Chris@16
|
144 size_t max, min, re, oct;
|
Chris@16
|
145 ar >> boost::serialization::make_nvp("max", max);
|
Chris@16
|
146 ar >> boost::serialization::make_nvp("min", min);
|
Chris@16
|
147 ar >> boost::serialization::make_nvp("re", re);
|
Chris@16
|
148 ar >> boost::serialization::make_nvp("oct", oct);
|
Chris@16
|
149 if ( max != params->get_max_elements() || min != params->get_min_elements() ||
|
Chris@16
|
150 re != params->get_reinserted_elements() || oct != params->get_overlap_cost_threshold() )
|
Chris@16
|
151 // TODO change exception type
|
Chris@16
|
152 BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
|
Chris@16
|
153 // the constructor musn't be called for this type
|
Chris@16
|
154 //::new(params)boost::geometry::index::rstar<Max, Min, RE, OCT>();
|
Chris@16
|
155 }
|
Chris@16
|
156 template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
|
Chris@16
|
157 void serialize(Archive &, boost::geometry::index::rstar<Max, Min, RE, OCT> &, unsigned int) {}
|
Chris@16
|
158
|
Chris@16
|
159 // boost::geometry::index::dynamic_linear
|
Chris@16
|
160
|
Chris@16
|
161 template<class Archive>
|
Chris@16
|
162 inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_linear * params, unsigned int )
|
Chris@16
|
163 {
|
Chris@16
|
164 size_t max = params->get_max_elements(), min = params->get_min_elements();
|
Chris@16
|
165 ar << boost::serialization::make_nvp("max", max);
|
Chris@16
|
166 ar << boost::serialization::make_nvp("min", min);
|
Chris@16
|
167 }
|
Chris@16
|
168 template<class Archive>
|
Chris@16
|
169 inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_linear * params, unsigned int )
|
Chris@16
|
170 {
|
Chris@16
|
171 size_t max, min;
|
Chris@16
|
172 ar >> boost::serialization::make_nvp("max", max);
|
Chris@16
|
173 ar >> boost::serialization::make_nvp("min", min);
|
Chris@16
|
174 ::new(params)boost::geometry::index::dynamic_linear(max, min);
|
Chris@16
|
175 }
|
Chris@16
|
176 template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_linear &, unsigned int) {}
|
Chris@16
|
177
|
Chris@16
|
178 // boost::geometry::index::dynamic_quadratic
|
Chris@16
|
179
|
Chris@16
|
180 template<class Archive>
|
Chris@16
|
181 inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_quadratic * params, unsigned int )
|
Chris@16
|
182 {
|
Chris@16
|
183 size_t max = params->get_max_elements(), min = params->get_min_elements();
|
Chris@16
|
184 ar << boost::serialization::make_nvp("max", max);
|
Chris@16
|
185 ar << boost::serialization::make_nvp("min", min);
|
Chris@16
|
186 }
|
Chris@16
|
187 template<class Archive>
|
Chris@16
|
188 inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_quadratic * params, unsigned int )
|
Chris@16
|
189 {
|
Chris@16
|
190 size_t max, min;
|
Chris@16
|
191 ar >> boost::serialization::make_nvp("max", max);
|
Chris@16
|
192 ar >> boost::serialization::make_nvp("min", min);
|
Chris@16
|
193 ::new(params)boost::geometry::index::dynamic_quadratic(max, min);
|
Chris@16
|
194 }
|
Chris@16
|
195 template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_quadratic &, unsigned int) {}
|
Chris@16
|
196
|
Chris@16
|
197 // boost::geometry::index::dynamic_rstar
|
Chris@16
|
198
|
Chris@16
|
199 template<class Archive>
|
Chris@16
|
200 inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_rstar * params, unsigned int )
|
Chris@16
|
201 {
|
Chris@16
|
202 size_t max = params->get_max_elements()
|
Chris@16
|
203 , min = params->get_min_elements()
|
Chris@16
|
204 , re = params->get_reinserted_elements()
|
Chris@16
|
205 , oct = params->get_overlap_cost_threshold();
|
Chris@16
|
206 ar << boost::serialization::make_nvp("max", max);
|
Chris@16
|
207 ar << boost::serialization::make_nvp("min", min);
|
Chris@16
|
208 ar << boost::serialization::make_nvp("re", re);
|
Chris@16
|
209 ar << boost::serialization::make_nvp("oct", oct);
|
Chris@16
|
210 }
|
Chris@16
|
211 template<class Archive>
|
Chris@16
|
212 inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_rstar * params, unsigned int )
|
Chris@16
|
213 {
|
Chris@16
|
214 size_t max, min, re, oct;
|
Chris@16
|
215 ar >> boost::serialization::make_nvp("max", max);
|
Chris@16
|
216 ar >> boost::serialization::make_nvp("min", min);
|
Chris@16
|
217 ar >> boost::serialization::make_nvp("re", re);
|
Chris@16
|
218 ar >> boost::serialization::make_nvp("oct", oct);
|
Chris@16
|
219 ::new(params)boost::geometry::index::dynamic_rstar(max, min, re, oct);
|
Chris@16
|
220 }
|
Chris@16
|
221 template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_rstar &, unsigned int) {}
|
Chris@16
|
222
|
Chris@16
|
223 }} // boost::serialization
|
Chris@16
|
224
|
Chris@16
|
225 // TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp
|
Chris@16
|
226 namespace boost { namespace geometry { namespace index { namespace detail {
|
Chris@16
|
227
|
Chris@101
|
228 template <typename P, size_t I = 0, size_t D = geometry::dimension<P>::value>
|
Chris@16
|
229 struct serialize_point
|
Chris@16
|
230 {
|
Chris@16
|
231 template <typename Archive>
|
Chris@16
|
232 static inline void save(Archive & ar, P const& p, unsigned int version)
|
Chris@16
|
233 {
|
Chris@16
|
234 typename coordinate_type<P>::type c = get<I>(p);
|
Chris@16
|
235 ar << boost::serialization::make_nvp("c", c);
|
Chris@16
|
236 serialize_point<P, I+1, D>::save(ar, p, version);
|
Chris@16
|
237 }
|
Chris@16
|
238
|
Chris@16
|
239 template <typename Archive>
|
Chris@16
|
240 static inline void load(Archive & ar, P & p, unsigned int version)
|
Chris@16
|
241 {
|
Chris@101
|
242 typename geometry::coordinate_type<P>::type c;
|
Chris@16
|
243 ar >> boost::serialization::make_nvp("c", c);
|
Chris@16
|
244 set<I>(p, c);
|
Chris@16
|
245 serialize_point<P, I+1, D>::load(ar, p, version);
|
Chris@16
|
246 }
|
Chris@16
|
247 };
|
Chris@16
|
248
|
Chris@16
|
249 template <typename P, size_t D>
|
Chris@16
|
250 struct serialize_point<P, D, D>
|
Chris@16
|
251 {
|
Chris@16
|
252 template <typename Archive> static inline void save(Archive &, P const&, unsigned int) {}
|
Chris@16
|
253 template <typename Archive> static inline void load(Archive &, P &, unsigned int) {}
|
Chris@16
|
254 };
|
Chris@16
|
255
|
Chris@16
|
256 }}}}
|
Chris@16
|
257
|
Chris@16
|
258 // TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp
|
Chris@16
|
259 namespace boost { namespace serialization {
|
Chris@16
|
260
|
Chris@16
|
261 template<class Archive, typename T, size_t D, typename C>
|
Chris@16
|
262 void save(Archive & ar, boost::geometry::model::point<T, D, C> const& p, unsigned int version)
|
Chris@16
|
263 {
|
Chris@16
|
264 boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::save(ar, p, version);
|
Chris@16
|
265 }
|
Chris@16
|
266 template<class Archive, typename T, size_t D, typename C>
|
Chris@16
|
267 void load(Archive & ar, boost::geometry::model::point<T, D, C> & p, unsigned int version)
|
Chris@16
|
268 {
|
Chris@16
|
269 boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::load(ar, p, version);
|
Chris@16
|
270 }
|
Chris@16
|
271 template<class Archive, typename T, size_t D, typename C>
|
Chris@16
|
272 inline void serialize(Archive & ar, boost::geometry::model::point<T, D, C> & o, const unsigned int version) { split_free(ar, o, version); }
|
Chris@16
|
273
|
Chris@16
|
274 template<class Archive, typename P>
|
Chris@16
|
275 inline void serialize(Archive & ar, boost::geometry::model::box<P> & b, const unsigned int)
|
Chris@16
|
276 {
|
Chris@16
|
277 ar & boost::serialization::make_nvp("min", b.min_corner());
|
Chris@16
|
278 ar & boost::serialization::make_nvp("max", b.max_corner());
|
Chris@16
|
279 }
|
Chris@16
|
280
|
Chris@16
|
281 }} // boost::serialization
|
Chris@16
|
282
|
Chris@16
|
283 // TODO - move to index/detail/rtree/visitors/save.hpp
|
Chris@16
|
284 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace visitors {
|
Chris@16
|
285
|
Chris@16
|
286 // TODO move saving and loading of the rtree outside the rtree, this will require adding some kind of members_view
|
Chris@16
|
287
|
Chris@16
|
288 template <typename Archive, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
Chris@16
|
289 class save
|
Chris@16
|
290 : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
|
Chris@16
|
291 {
|
Chris@16
|
292 public:
|
Chris@16
|
293 typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
Chris@16
|
294 typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
Chris@16
|
295 typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
Chris@16
|
296
|
Chris@16
|
297 save(Archive & archive, unsigned int version)
|
Chris@16
|
298 : m_archive(archive), m_version(version)
|
Chris@16
|
299 {}
|
Chris@16
|
300
|
Chris@16
|
301 inline void operator()(internal_node const& n)
|
Chris@16
|
302 {
|
Chris@16
|
303 typedef typename rtree::elements_type<internal_node>::type elements_type;
|
Chris@16
|
304 elements_type const& elements = rtree::elements(n);
|
Chris@16
|
305
|
Chris@101
|
306 // CONSIDER: change to elements_type::size_type or size_type
|
Chris@101
|
307 // or use fixed-size type like uint32 or even uint16?
|
Chris@16
|
308 size_t s = elements.size();
|
Chris@16
|
309 m_archive << boost::serialization::make_nvp("s", s);
|
Chris@16
|
310
|
Chris@16
|
311 for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
|
Chris@16
|
312 {
|
Chris@16
|
313 serialization_save(it->first, "b", m_archive);
|
Chris@16
|
314
|
Chris@16
|
315 rtree::apply_visitor(*this, *it->second);
|
Chris@16
|
316 }
|
Chris@16
|
317 }
|
Chris@16
|
318
|
Chris@16
|
319 inline void operator()(leaf const& l)
|
Chris@16
|
320 {
|
Chris@16
|
321 typedef typename rtree::elements_type<leaf>::type elements_type;
|
Chris@101
|
322 //typedef typename elements_type::size_type elements_size;
|
Chris@16
|
323 elements_type const& elements = rtree::elements(l);
|
Chris@16
|
324
|
Chris@101
|
325 // CONSIDER: change to elements_type::size_type or size_type
|
Chris@101
|
326 // or use fixed-size type like uint32 or even uint16?
|
Chris@16
|
327 size_t s = elements.size();
|
Chris@16
|
328 m_archive << boost::serialization::make_nvp("s", s);
|
Chris@16
|
329
|
Chris@16
|
330 for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
|
Chris@16
|
331 {
|
Chris@16
|
332 serialization_save(*it, "v", m_archive);
|
Chris@16
|
333 }
|
Chris@16
|
334 }
|
Chris@16
|
335
|
Chris@16
|
336 private:
|
Chris@16
|
337 Archive & m_archive;
|
Chris@16
|
338 unsigned int m_version;
|
Chris@16
|
339 };
|
Chris@16
|
340
|
Chris@16
|
341 }}}}}} // boost::geometry::index::detail::rtree::visitors
|
Chris@16
|
342
|
Chris@16
|
343 // TODO - move to index/detail/rtree/load.hpp
|
Chris@16
|
344 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
|
Chris@16
|
345
|
Chris@16
|
346 template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
|
Chris@16
|
347 class load
|
Chris@16
|
348 {
|
Chris@16
|
349 typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
|
Chris@16
|
350 typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
|
Chris@16
|
351 typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
|
Chris@16
|
352
|
Chris@16
|
353 typedef typename Options::parameters_type parameters_type;
|
Chris@16
|
354
|
Chris@16
|
355 typedef typename Allocators::node_pointer node_pointer;
|
Chris@101
|
356 typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
|
Chris@16
|
357 typedef typename Allocators::size_type size_type;
|
Chris@16
|
358
|
Chris@16
|
359 public:
|
Chris@16
|
360 template <typename Archive> inline static
|
Chris@16
|
361 node_pointer apply(Archive & ar, unsigned int version, size_type leafs_level, size_type & values_count, parameters_type const& parameters, Translator const& translator, Allocators & allocators)
|
Chris@16
|
362 {
|
Chris@16
|
363 values_count = 0;
|
Chris@16
|
364 return raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators);
|
Chris@16
|
365 }
|
Chris@16
|
366
|
Chris@16
|
367 private:
|
Chris@16
|
368 template <typename Archive> inline static
|
Chris@16
|
369 node_pointer raw_apply(Archive & ar, unsigned int version, size_type leafs_level, size_type & values_count, parameters_type const& parameters, Translator const& translator, Allocators & allocators, size_type current_level = 0)
|
Chris@16
|
370 {
|
Chris@16
|
371 //BOOST_GEOMETRY_INDEX_ASSERT(current_level <= leafs_level, "invalid parameter");
|
Chris@16
|
372
|
Chris@101
|
373 typedef typename rtree::elements_type<internal_node>::type elements_type;
|
Chris@101
|
374 typedef typename elements_type::value_type element_type;
|
Chris@101
|
375 //typedef typename elements_type::size_type elements_size;
|
Chris@101
|
376
|
Chris@101
|
377 // CONSIDER: change to elements_type::size_type or size_type
|
Chris@101
|
378 // or use fixed-size type like uint32 or even uint16?
|
Chris@16
|
379 size_t elements_count;
|
Chris@16
|
380 ar >> boost::serialization::make_nvp("s", elements_count);
|
Chris@16
|
381
|
Chris@16
|
382 if ( elements_count < parameters.get_min_elements() || parameters.get_max_elements() < elements_count )
|
Chris@16
|
383 BOOST_THROW_EXCEPTION(std::runtime_error("rtree loading error"));
|
Chris@16
|
384
|
Chris@16
|
385 if ( current_level < leafs_level )
|
Chris@16
|
386 {
|
Chris@16
|
387 node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators); // MAY THROW (A)
|
Chris@101
|
388 subtree_destroyer auto_remover(n, allocators);
|
Chris@16
|
389 internal_node & in = rtree::get<internal_node>(*n);
|
Chris@16
|
390
|
Chris@16
|
391 elements_type & elements = rtree::elements(in);
|
Chris@16
|
392
|
Chris@16
|
393 elements.reserve(elements_count); // MAY THROW (A)
|
Chris@16
|
394
|
Chris@16
|
395 for ( size_t i = 0 ; i < elements_count ; ++i )
|
Chris@16
|
396 {
|
Chris@16
|
397 typedef typename elements_type::value_type::first_type box_type;
|
Chris@16
|
398 box_type b = serialization_load<box_type>("b", ar);
|
Chris@16
|
399 node_pointer n = raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators, current_level+1); // recursive call
|
Chris@16
|
400 elements.push_back(element_type(b, n));
|
Chris@16
|
401 }
|
Chris@16
|
402
|
Chris@16
|
403 auto_remover.release();
|
Chris@16
|
404 return n;
|
Chris@16
|
405 }
|
Chris@16
|
406 else
|
Chris@16
|
407 {
|
Chris@16
|
408 BOOST_GEOMETRY_INDEX_ASSERT(current_level == leafs_level, "unexpected value");
|
Chris@16
|
409
|
Chris@16
|
410 node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators); // MAY THROW (A)
|
Chris@101
|
411 subtree_destroyer auto_remover(n, allocators);
|
Chris@16
|
412 leaf & l = rtree::get<leaf>(*n);
|
Chris@16
|
413
|
Chris@16
|
414 typedef typename rtree::elements_type<leaf>::type elements_type;
|
Chris@16
|
415 typedef typename elements_type::value_type element_type;
|
Chris@16
|
416 elements_type & elements = rtree::elements(l);
|
Chris@16
|
417
|
Chris@16
|
418 values_count += elements_count;
|
Chris@16
|
419
|
Chris@16
|
420 elements.reserve(elements_count); // MAY THROW (A)
|
Chris@16
|
421
|
Chris@16
|
422 for ( size_t i = 0 ; i < elements_count ; ++i )
|
Chris@16
|
423 {
|
Chris@16
|
424 element_type el = serialization_load<element_type>("v", ar); // MAY THROW (C)
|
Chris@16
|
425 elements.push_back(el); // MAY THROW (C)
|
Chris@16
|
426 }
|
Chris@16
|
427
|
Chris@16
|
428 auto_remover.release();
|
Chris@16
|
429 return n;
|
Chris@16
|
430 }
|
Chris@16
|
431 }
|
Chris@16
|
432 };
|
Chris@16
|
433
|
Chris@16
|
434 }}}}} // boost::geometry::index::detail::rtree
|
Chris@16
|
435
|
Chris@16
|
436 // TODO - move to index/detail/rtree/private_view.hpp
|
Chris@16
|
437 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
|
Chris@16
|
438
|
Chris@16
|
439 template <typename Rtree>
|
Chris@16
|
440 class const_private_view
|
Chris@16
|
441 {
|
Chris@16
|
442 public:
|
Chris@16
|
443 typedef typename Rtree::size_type size_type;
|
Chris@16
|
444
|
Chris@16
|
445 typedef typename Rtree::translator_type translator_type;
|
Chris@16
|
446 typedef typename Rtree::value_type value_type;
|
Chris@16
|
447 typedef typename Rtree::options_type options_type;
|
Chris@16
|
448 typedef typename Rtree::box_type box_type;
|
Chris@16
|
449 typedef typename Rtree::allocators_type allocators_type;
|
Chris@16
|
450
|
Chris@16
|
451 const_private_view(Rtree const& rt) : m_rtree(rt) {}
|
Chris@16
|
452
|
Chris@16
|
453 typedef typename Rtree::members_holder members_holder;
|
Chris@16
|
454
|
Chris@16
|
455 members_holder const& members() const { return m_rtree.m_members; }
|
Chris@16
|
456
|
Chris@16
|
457 private:
|
Chris@16
|
458 const_private_view(const_private_view const&);
|
Chris@16
|
459 const_private_view & operator=(const_private_view const&);
|
Chris@16
|
460
|
Chris@16
|
461 Rtree const& m_rtree;
|
Chris@16
|
462 };
|
Chris@16
|
463
|
Chris@16
|
464 template <typename Rtree>
|
Chris@16
|
465 class private_view
|
Chris@16
|
466 {
|
Chris@16
|
467 public:
|
Chris@16
|
468 typedef typename Rtree::size_type size_type;
|
Chris@16
|
469
|
Chris@16
|
470 typedef typename Rtree::translator_type translator_type;
|
Chris@16
|
471 typedef typename Rtree::value_type value_type;
|
Chris@16
|
472 typedef typename Rtree::options_type options_type;
|
Chris@16
|
473 typedef typename Rtree::box_type box_type;
|
Chris@16
|
474 typedef typename Rtree::allocators_type allocators_type;
|
Chris@16
|
475
|
Chris@16
|
476 private_view(Rtree & rt) : m_rtree(rt) {}
|
Chris@16
|
477
|
Chris@16
|
478 typedef typename Rtree::members_holder members_holder;
|
Chris@16
|
479
|
Chris@16
|
480 members_holder & members() { return m_rtree.m_members; }
|
Chris@16
|
481 members_holder const& members() const { return m_rtree.m_members; }
|
Chris@16
|
482
|
Chris@16
|
483 private:
|
Chris@16
|
484 private_view(private_view const&);
|
Chris@16
|
485 private_view & operator=(private_view const&);
|
Chris@16
|
486
|
Chris@16
|
487 Rtree & m_rtree;
|
Chris@16
|
488 };
|
Chris@16
|
489
|
Chris@16
|
490 }}}}} // namespace boost::geometry::index::detail::rtree
|
Chris@16
|
491
|
Chris@16
|
492 // TODO - move to index/serialization/rtree.hpp
|
Chris@16
|
493 namespace boost { namespace serialization {
|
Chris@16
|
494
|
Chris@16
|
495 template<class Archive, typename V, typename P, typename I, typename E, typename A>
|
Chris@16
|
496 void save(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)
|
Chris@16
|
497 {
|
Chris@16
|
498 namespace detail = boost::geometry::index::detail;
|
Chris@16
|
499
|
Chris@16
|
500 typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;
|
Chris@16
|
501 typedef detail::rtree::const_private_view<rtree> view;
|
Chris@16
|
502 typedef typename view::translator_type translator_type;
|
Chris@16
|
503 typedef typename view::value_type value_type;
|
Chris@16
|
504 typedef typename view::options_type options_type;
|
Chris@16
|
505 typedef typename view::box_type box_type;
|
Chris@16
|
506 typedef typename view::allocators_type allocators_type;
|
Chris@16
|
507
|
Chris@16
|
508 view tree(rt);
|
Chris@16
|
509
|
Chris@16
|
510 detail::serialization_save(tree.members().parameters(), "parameters", ar);
|
Chris@16
|
511
|
Chris@16
|
512 ar << boost::serialization::make_nvp("values_count", tree.members().values_count);
|
Chris@16
|
513 ar << boost::serialization::make_nvp("leafs_level", tree.members().leafs_level);
|
Chris@16
|
514
|
Chris@16
|
515 if ( tree.members().values_count )
|
Chris@16
|
516 {
|
Chris@16
|
517 BOOST_GEOMETRY_INDEX_ASSERT(tree.members().root, "root shouldn't be null_ptr");
|
Chris@16
|
518
|
Chris@16
|
519 detail::rtree::visitors::save<Archive, value_type, options_type, translator_type, box_type, allocators_type> save_v(ar, version);
|
Chris@16
|
520 detail::rtree::apply_visitor(save_v, *tree.members().root);
|
Chris@16
|
521 }
|
Chris@16
|
522 }
|
Chris@16
|
523
|
Chris@16
|
524 template<class Archive, typename V, typename P, typename I, typename E, typename A>
|
Chris@16
|
525 void load(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)
|
Chris@16
|
526 {
|
Chris@16
|
527 namespace detail = boost::geometry::index::detail;
|
Chris@16
|
528
|
Chris@16
|
529 typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;
|
Chris@16
|
530 typedef detail::rtree::private_view<rtree> view;
|
Chris@16
|
531 typedef typename view::size_type size_type;
|
Chris@16
|
532 typedef typename view::translator_type translator_type;
|
Chris@16
|
533 typedef typename view::value_type value_type;
|
Chris@16
|
534 typedef typename view::options_type options_type;
|
Chris@16
|
535 typedef typename view::box_type box_type;
|
Chris@16
|
536 typedef typename view::allocators_type allocators_type;
|
Chris@16
|
537
|
Chris@16
|
538 typedef typename options_type::parameters_type parameters_type;
|
Chris@16
|
539 typedef typename allocators_type::node_pointer node_pointer;
|
Chris@101
|
540 typedef detail::rtree::subtree_destroyer<value_type, options_type, translator_type, box_type, allocators_type> subtree_destroyer;
|
Chris@16
|
541
|
Chris@16
|
542 view tree(rt);
|
Chris@16
|
543
|
Chris@16
|
544 parameters_type params = detail::serialization_load<parameters_type>("parameters", ar);
|
Chris@16
|
545
|
Chris@16
|
546 size_type values_count, leafs_level;
|
Chris@16
|
547 ar >> boost::serialization::make_nvp("values_count", values_count);
|
Chris@16
|
548 ar >> boost::serialization::make_nvp("leafs_level", leafs_level);
|
Chris@16
|
549
|
Chris@16
|
550 node_pointer n(0);
|
Chris@16
|
551 if ( 0 < values_count )
|
Chris@16
|
552 {
|
Chris@16
|
553 size_type loaded_values_count = 0;
|
Chris@16
|
554 n = detail::rtree::load<value_type, options_type, translator_type, box_type, allocators_type>
|
Chris@16
|
555 ::apply(ar, version, leafs_level, loaded_values_count, params, tree.members().translator(), tree.members().allocators()); // MAY THROW
|
Chris@16
|
556
|
Chris@101
|
557 subtree_destroyer remover(n, tree.members().allocators());
|
Chris@16
|
558 if ( loaded_values_count != values_count )
|
Chris@16
|
559 BOOST_THROW_EXCEPTION(std::runtime_error("unexpected number of values")); // TODO change exception type
|
Chris@16
|
560 remover.release();
|
Chris@16
|
561 }
|
Chris@16
|
562
|
Chris@16
|
563 tree.members().parameters() = params;
|
Chris@16
|
564 tree.members().values_count = values_count;
|
Chris@16
|
565 tree.members().leafs_level = leafs_level;
|
Chris@16
|
566
|
Chris@101
|
567 subtree_destroyer remover(tree.members().root, tree.members().allocators());
|
Chris@16
|
568 tree.members().root = n;
|
Chris@16
|
569 }
|
Chris@16
|
570
|
Chris@16
|
571 template<class Archive, typename V, typename P, typename I, typename E, typename A> inline
|
Chris@16
|
572 void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)
|
Chris@16
|
573 {
|
Chris@16
|
574 split_free(ar, rt, version);
|
Chris@16
|
575 }
|
Chris@16
|
576
|
Chris@16
|
577 template<class Archive, typename V, typename P, typename I, typename E, typename A> inline
|
Chris@16
|
578 void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)
|
Chris@16
|
579 {
|
Chris@16
|
580 split_free(ar, rt, version);
|
Chris@16
|
581 }
|
Chris@16
|
582
|
Chris@16
|
583 }} // boost::serialization
|
Chris@16
|
584
|
Chris@16
|
585 #endif // BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
|