]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
3 | // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | ||
5 | // This file was modified by Oracle on 2014. | |
6 | // Modifications copyright (c) 2014 Oracle and/or its affiliates. | |
7 | ||
8 | // Use, modification and distribution is subject to the Boost Software License, | |
9 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
10 | // http://www.boost.org/LICENSE_1_0.txt) | |
11 | ||
12 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle | |
13 | ||
14 | #ifndef BOOST_GEOMETRY_TEST_TO_SVG_HPP | |
15 | #define BOOST_GEOMETRY_TEST_TO_SVG_HPP | |
16 | ||
17 | #include <fstream> | |
18 | ||
19 | #include <boost/geometry/io/wkt/read.hpp> | |
20 | #include <boost/geometry/io/svg/svg_mapper.hpp> | |
21 | #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp> | |
22 | #include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp> | |
23 | #include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp> | |
24 | #include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp> | |
25 | #include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp> | |
26 | #include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp> | |
27 | #include <boost/foreach.hpp> | |
28 | ||
29 | #include <boost/geometry/algorithms/detail/relate/turns.hpp> | |
30 | ||
31 | template <typename G, typename Turns, typename Mapper> | |
32 | inline void turns_to_svg(Turns const& turns, Mapper & mapper, bool /*enrich*/ = false) | |
33 | { | |
34 | namespace bg = boost::geometry; | |
35 | ||
36 | // turn points in orange, + enrichment/traversal info | |
37 | typedef typename bg::coordinate_type<G>::type coordinate_type; | |
38 | typedef typename boost::range_value<Turns>::type turn_info; | |
39 | ||
40 | // Simple map to avoid two texts at same place (note that can still overlap!) | |
41 | std::map<std::pair<int, int>, int> offsets; | |
42 | int index = 0; | |
43 | int const margin = 5; | |
44 | ||
45 | BOOST_FOREACH(turn_info const& turn, turns) | |
46 | { | |
47 | int lineheight = 10; | |
48 | mapper.map(turn.point, "fill:rgb(255,128,0);" | |
49 | "stroke:rgb(0,0,0);stroke-width:1", 3); | |
50 | ||
51 | { | |
52 | coordinate_type half = 0.5; | |
53 | coordinate_type ten = 10; | |
54 | // Map characteristics | |
55 | // Create a rounded off point | |
56 | std::pair<int, int> p | |
57 | = std::make_pair( | |
58 | boost::numeric_cast<int>(half | |
59 | + ten * bg::get<0>(turn.point)), | |
60 | boost::numeric_cast<int>(half | |
61 | + ten * bg::get<1>(turn.point)) | |
62 | ); | |
63 | std::string style = "fill:rgb(0,0,0);font-family:Arial;font-size:12px"; | |
64 | ||
65 | if (turn.discarded) | |
66 | { | |
67 | style = "fill:rgb(92,92,92);font-family:Arial;font-size:10px"; | |
68 | lineheight = 6; | |
69 | } | |
70 | ||
71 | //if (! turn.discarded && ! turn.blocked() && ! turn.both(bg::detail::overlay::operation_union)) | |
72 | //if (! turn.discarded) | |
73 | { | |
74 | std::ostringstream out; | |
75 | out << index | |
76 | << ": " << bg::method_char(turn.method); | |
77 | ||
78 | if ( turn.discarded ) | |
79 | out << " (discarded)\n"; | |
80 | else if ( turn.blocked() ) | |
81 | out << " (blocked)\n"; | |
82 | else | |
83 | out << '\n'; | |
84 | ||
85 | out << bg::operation_char(turn.operations[0].operation) | |
86 | <<": seg: " << turn.operations[0].seg_id.source_index | |
87 | << ' ' << turn.operations[0].seg_id.multi_index | |
88 | << ' ' << turn.operations[0].seg_id.ring_index | |
89 | << ' ' << turn.operations[0].seg_id.segment_index << ", "; | |
90 | out << "other: " << turn.operations[1].seg_id.source_index | |
91 | << ' ' << turn.operations[1].seg_id.multi_index | |
92 | << ' ' << turn.operations[1].seg_id.ring_index | |
93 | << ' ' << turn.operations[1].seg_id.segment_index; | |
94 | ||
95 | /*if ( enrich ) | |
96 | { | |
97 | out << ", "; | |
98 | if (turn.operations[0].enriched.next_ip_index != -1) | |
99 | { | |
100 | out << "ip: " << turn.operations[0].enriched.next_ip_index; | |
101 | } | |
102 | else | |
103 | { | |
104 | out << "vx: " << turn.operations[0].enriched.travels_to_vertex_index | |
105 | << " -> ip: " << turn.operations[0].enriched.travels_to_ip_index; | |
106 | } | |
107 | }*/ | |
108 | ||
109 | out << '\n'; | |
110 | ||
111 | out << bg::operation_char(turn.operations[1].operation) | |
112 | << ": seg: " << turn.operations[1].seg_id.source_index | |
113 | << ' ' << turn.operations[1].seg_id.multi_index | |
114 | << ' ' << turn.operations[1].seg_id.ring_index | |
115 | << ' ' << turn.operations[1].seg_id.segment_index << ", "; | |
116 | out << "other: " << turn.operations[0].seg_id.source_index | |
117 | << ' ' << turn.operations[0].seg_id.multi_index | |
118 | << ' ' << turn.operations[0].seg_id.ring_index | |
119 | << ' ' << turn.operations[0].seg_id.segment_index; | |
120 | ||
121 | /*if ( enrich ) | |
122 | { | |
123 | out << ", "; | |
124 | if (turn.operations[1].enriched.next_ip_index != -1) | |
125 | { | |
126 | out << "ip: " << turn.operations[1].enriched.next_ip_index; | |
127 | } | |
128 | else | |
129 | { | |
130 | out << "vx: " << turn.operations[1].enriched.travels_to_vertex_index | |
131 | << " -> ip: " << turn.operations[1].enriched.travels_to_ip_index; | |
132 | } | |
133 | }*/ | |
134 | ||
135 | //out << std::endl; | |
136 | ||
137 | /*out | |
138 | ||
139 | << std::setprecision(3) | |
140 | << "dist: " << boost::numeric_cast<double>(turn.operations[0].enriched.distance) | |
141 | << " / " << boost::numeric_cast<double>(turn.operations[1].enriched.distance) | |
142 | << std::endl | |
143 | << "vis: " << bg::visited_char(turn.operations[0].visited) | |
144 | << " / " << bg::visited_char(turn.operations[1].visited); | |
145 | */ | |
146 | ||
147 | /* | |
148 | out << index | |
149 | << ": " << bg::operation_char(turn.operations[0].operation) | |
150 | << " " << bg::operation_char(turn.operations[1].operation) | |
151 | << " (" << bg::method_char(turn.method) << ")" | |
152 | << (turn.ignore() ? " (ignore) " : " ") | |
153 | << std::endl | |
154 | ||
155 | << "ip: " << turn.operations[0].enriched.travels_to_ip_index | |
156 | << "/" << turn.operations[1].enriched.travels_to_ip_index; | |
157 | ||
158 | if (turn.operations[0].enriched.next_ip_index != -1 | |
159 | || turn.operations[1].enriched.next_ip_index != -1) | |
160 | { | |
161 | out << " [" << turn.operations[0].enriched.next_ip_index | |
162 | << "/" << turn.operations[1].enriched.next_ip_index | |
163 | << "]" | |
164 | ; | |
165 | } | |
166 | out << std::endl; | |
167 | ||
168 | ||
169 | out | |
170 | << "vx:" << turn.operations[0].enriched.travels_to_vertex_index | |
171 | << "/" << turn.operations[1].enriched.travels_to_vertex_index | |
172 | << std::endl | |
173 | ||
174 | << std::setprecision(3) | |
175 | << "dist: " << turn.operations[0].enriched.distance | |
176 | << " / " << turn.operations[1].enriched.distance | |
177 | << std::endl | |
178 | */ | |
179 | ||
180 | ||
181 | ||
182 | offsets[p] += lineheight; | |
183 | int offset = offsets[p]; | |
184 | offsets[p] += lineheight * 3; | |
185 | mapper.text(turn.point, out.str(), style, margin, offset, lineheight); | |
186 | } | |
187 | index++; | |
188 | } | |
189 | } | |
190 | } | |
191 | ||
192 | template <typename G1, typename P> | |
193 | inline void geom_to_svg(G1 const& g1, | |
194 | boost::geometry::svg_mapper<P> & mapper) | |
195 | { | |
196 | mapper.add(g1); | |
197 | ||
198 | mapper.map(g1, "fill-opacity:0.5;fill:rgb(153,204,0);" | |
199 | "stroke:rgb(153,204,0);stroke-width:3"); | |
200 | } | |
201 | ||
202 | template <typename G1, typename G2, typename P> | |
203 | inline void geom_to_svg(G1 const& g1, G2 const& g2, | |
204 | boost::geometry::svg_mapper<P> & mapper) | |
205 | { | |
206 | mapper.add(g1); | |
207 | mapper.add(g2); | |
208 | ||
209 | mapper.map(g1, "fill-opacity:0.5;fill:rgb(153,204,0);" | |
210 | "stroke:rgb(153,204,0);stroke-width:3"); | |
211 | mapper.map(g2, "fill-opacity:0.3;fill:rgb(51,51,153);" | |
212 | "stroke:rgb(51,51,153);stroke-width:3"); | |
213 | } | |
214 | ||
215 | template <typename G1> | |
216 | inline void geom_to_svg(G1 const& g1, std::string const& filename) | |
217 | { | |
218 | namespace bg = boost::geometry; | |
219 | typedef typename bg::point_type<G1>::type mapper_point_type; | |
220 | ||
221 | std::ofstream svg(filename.c_str(), std::ios::trunc); | |
222 | bg::svg_mapper<mapper_point_type> mapper(svg, 500, 500); | |
223 | ||
224 | geom_to_svg(g1, mapper); | |
225 | } | |
226 | ||
227 | template <typename G1, typename G2> | |
228 | inline void geom_to_svg(G1 const& g1, G2 const& g2, std::string const& filename) | |
229 | { | |
230 | namespace bg = boost::geometry; | |
231 | typedef typename bg::point_type<G1>::type mapper_point_type; | |
232 | ||
233 | std::ofstream svg(filename.c_str(), std::ios::trunc); | |
234 | bg::svg_mapper<mapper_point_type> mapper(svg, 500, 500); | |
235 | ||
236 | geom_to_svg(g1, g2, mapper); | |
237 | } | |
238 | ||
239 | template <typename G1> | |
240 | inline void geom_to_svg(std::string const& wkt1, std::string const& filename) | |
241 | { | |
242 | namespace bg = boost::geometry; | |
243 | ||
244 | G1 g1; | |
245 | bg::read_wkt(wkt1, g1); | |
246 | geom_to_svg(g1, filename); | |
247 | } | |
248 | ||
249 | template <typename G1, typename G2> | |
250 | inline void geom_to_svg(std::string const& wkt1, std::string const& wkt2, std::string const& filename) | |
251 | { | |
252 | namespace bg = boost::geometry; | |
253 | ||
254 | G1 g1; | |
255 | G2 g2; | |
256 | bg::read_wkt(wkt1, g1); | |
257 | bg::read_wkt(wkt2, g2); | |
258 | geom_to_svg(g1, g2, filename); | |
259 | } | |
260 | ||
261 | struct to_svg_assign_policy | |
262 | : boost::geometry::detail::overlay::assign_null_policy | |
263 | { | |
264 | static bool const include_no_turn = false; | |
265 | static bool const include_degenerate = false; | |
266 | static bool const include_opposite = false; | |
267 | }; | |
268 | ||
269 | template <typename G> | |
270 | inline void to_svg(G const& g, std::string const& filename, bool /*sort*/ = true) | |
271 | { | |
272 | namespace bg = boost::geometry; | |
273 | ||
274 | typedef typename bg::point_type<G>::type P; | |
275 | ||
276 | std::ofstream svg(filename.c_str(), std::ios::trunc); | |
277 | ||
278 | bg::svg_mapper<P> mapper(svg, 500, 500); | |
279 | ||
280 | mapper.add(g); | |
281 | ||
282 | mapper.map(g, "fill-opacity:0.5;fill:rgb(153,204,0);" | |
283 | "stroke:rgb(153,204,0);stroke-width:3"); | |
284 | ||
285 | // GET TURNS | |
286 | ||
287 | typedef bg::segment_ratio<double> sr; | |
288 | typedef bg::detail::overlay::traversal_turn_info<P, sr> turn_info; | |
289 | typedef bg::detail::overlay::assign_null_policy AssignPolicy; | |
290 | //typedef to_svg_assign_policy AssignPolicy; | |
291 | ||
292 | typedef std::deque<turn_info> Turns; | |
293 | typedef bg::detail::self_get_turn_points::no_interrupt_policy InterruptPolicy; | |
294 | ||
295 | Turns turns; | |
296 | InterruptPolicy interrupt_policy; | |
297 | ||
298 | typedef bg::detail::overlay::get_turn_info<AssignPolicy> TurnPolicy; | |
299 | ||
300 | bg::detail::self_get_turn_points::get_turns | |
301 | < | |
b32b8144 | 302 | false, TurnPolicy |
7c673cae FG |
303 | >::apply(g, bg::detail::no_rescale_policy(), turns, interrupt_policy); |
304 | ||
305 | turns_to_svg<G>(turns, mapper); | |
306 | } | |
307 | ||
308 | template <typename G1, typename G2> | |
309 | inline void to_svg(G1 const& g1, G2 const& g2, std::string const& filename, bool sort = true, bool use_old_turns_policy = false, bool enrich = false) | |
310 | { | |
311 | namespace bg = boost::geometry; | |
312 | ||
313 | typedef typename bg::point_type<G1>::type mapper_point_type; | |
314 | ||
315 | std::ofstream svg(filename.c_str(), std::ios::trunc); | |
316 | ||
317 | bg::svg_mapper<mapper_point_type> mapper(svg, 500, 500); | |
318 | ||
319 | mapper.add(g1); | |
320 | mapper.add(g2); | |
321 | ||
322 | mapper.map(g1, "fill-opacity:0.5;fill:rgb(153,204,0);" | |
323 | "stroke:rgb(153,204,0);stroke-width:3"); | |
324 | mapper.map(g2, "fill-opacity:0.3;fill:rgb(51,51,153);" | |
325 | "stroke:rgb(51,51,153);stroke-width:3"); | |
326 | ||
327 | // GET TURNS | |
328 | ||
329 | typedef typename bg::detail::relate::turns::get_turns<G1, G2>::turn_info turn_info; | |
330 | //typedef bg::detail::overlay::traversal_turn_info<P1> turn_info; | |
331 | //typedef bg::detail::overlay::assign_null_policy AssignPolicy; | |
332 | typedef to_svg_assign_policy AssignPolicy; | |
333 | ||
334 | typedef std::deque<turn_info> Turns; | |
335 | typedef bg::detail::get_turns::no_interrupt_policy InterruptPolicy; | |
336 | static const bool Reverse1 = bg::detail::overlay::do_reverse<bg::point_order<G1>::value>::value; | |
337 | static const bool Reverse2 = bg::detail::overlay::do_reverse<bg::point_order<G2>::value>::value; | |
338 | ||
339 | Turns turns; | |
340 | InterruptPolicy interrupt_policy; | |
341 | ||
342 | if ( use_old_turns_policy ) | |
343 | { | |
344 | boost::geometry::get_turns | |
345 | < | |
346 | Reverse1, Reverse2, AssignPolicy | |
347 | >(g1, g2, bg::detail::no_rescale_policy(), turns, interrupt_policy); | |
348 | } | |
349 | else | |
350 | { | |
351 | typedef bg::detail::get_turns::get_turn_info_type | |
352 | < | |
353 | G1, G2, AssignPolicy | |
354 | > TurnPolicy; | |
355 | ||
356 | bg::detail::relate::turns::get_turns | |
357 | < | |
358 | G1, G2, TurnPolicy | |
359 | >::apply(turns, g1, g2); | |
360 | } | |
361 | ||
362 | if ( sort ) | |
363 | { | |
92f5a8d4 TL |
364 | typedef bg::detail::relate::turns::less |
365 | < | |
366 | 0, | |
367 | bg::detail::relate::turns::less_op_xxx_linear | |
368 | < | |
369 | 0, bg::detail::relate::turns::op_to_int<> | |
370 | >, | |
371 | typename bg::cs_tag<G1>::type | |
372 | > less; | |
7c673cae FG |
373 | std::sort(boost::begin(turns), boost::end(turns), less()); |
374 | } | |
375 | ||
376 | /*if ( enrich ) | |
377 | { | |
378 | typedef typename bg::strategy::side::services::default_strategy | |
379 | < | |
380 | typename bg::cs_tag<G1>::type | |
381 | >::type side_strategy_type; | |
382 | ||
383 | bg::enrich_intersection_points<bg::detail::overlay::do_reverse<bg::point_order<G1>::value>::value, | |
384 | bg::detail::overlay::do_reverse<bg::point_order<G2>::value>::value> | |
385 | (turns, bg::detail::overlay::operation_union, | |
386 | g1, g1, | |
387 | bg::detail::no_rescale_policy(), | |
388 | side_strategy_type()); | |
389 | }*/ | |
390 | ||
391 | turns_to_svg<G1>(turns, mapper, enrich); | |
392 | } | |
393 | ||
394 | template <typename G> | |
395 | inline void to_svg(std::string const& wkt, std::string const& filename) | |
396 | { | |
397 | G g; | |
398 | boost::geometry::read_wkt(wkt, g); | |
399 | to_svg(g, filename); | |
400 | } | |
401 | ||
402 | template <typename G1, typename G2> | |
403 | inline void to_svg(std::string const& wkt1, std::string const& wkt2, std::string const& filename, bool sort = true, bool reverse_by_geometry_id = false, bool enrich = false) | |
404 | { | |
405 | G1 g1; | |
406 | G2 g2; | |
407 | boost::geometry::read_wkt(wkt1, g1); | |
408 | boost::geometry::read_wkt(wkt2, g2); | |
409 | to_svg(g1, g2, filename, sort, reverse_by_geometry_id, enrich); | |
410 | } | |
411 | ||
412 | #endif // BOOST_GEOMETRY_TEST_TO_SVG_HPP |