1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // This file was modified by Oracle on 2014.
6 // Modifications copyright (c) 2014 Oracle and/or its affiliates.
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)
12 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
14 #ifndef BOOST_GEOMETRY_TEST_TO_SVG_HPP
15 #define BOOST_GEOMETRY_TEST_TO_SVG_HPP
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>
29 #include <boost/geometry/algorithms/detail/relate/turns.hpp>
31 template <typename G, typename Turns, typename Mapper>
32 inline void turns_to_svg(Turns const& turns, Mapper & mapper, bool /*enrich*/ = false)
34 namespace bg = boost::geometry;
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;
40 // Simple map to avoid two texts at same place (note that can still overlap!)
41 std::map<std::pair<int, int>, int> offsets;
45 BOOST_FOREACH(turn_info const& turn, turns)
48 mapper.map(turn.point, "fill:rgb(255,128,0);"
49 "stroke:rgb(0,0,0);stroke-width:1", 3);
52 coordinate_type half = 0.5;
53 coordinate_type ten = 10;
54 // Map characteristics
55 // Create a rounded off point
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))
63 std::string style = "fill:rgb(0,0,0);font-family:Arial;font-size:12px";
67 style = "fill:rgb(92,92,92);font-family:Arial;font-size:10px";
71 //if (! turn.discarded && ! turn.blocked() && ! turn.both(bg::detail::overlay::operation_union))
72 //if (! turn.discarded)
74 std::ostringstream out;
76 << ": " << bg::method_char(turn.method);
79 out << " (discarded)\n";
80 else if ( turn.blocked() )
81 out << " (blocked)\n";
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;
98 if (turn.operations[0].enriched.next_ip_index != -1)
100 out << "ip: " << turn.operations[0].enriched.next_ip_index;
104 out << "vx: " << turn.operations[0].enriched.travels_to_vertex_index
105 << " -> ip: " << turn.operations[0].enriched.travels_to_ip_index;
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;
124 if (turn.operations[1].enriched.next_ip_index != -1)
126 out << "ip: " << turn.operations[1].enriched.next_ip_index;
130 out << "vx: " << turn.operations[1].enriched.travels_to_vertex_index
131 << " -> ip: " << turn.operations[1].enriched.travels_to_ip_index;
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)
143 << "vis: " << bg::visited_char(turn.operations[0].visited)
144 << " / " << bg::visited_char(turn.operations[1].visited);
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) " : " ")
155 << "ip: " << turn.operations[0].enriched.travels_to_ip_index
156 << "/" << turn.operations[1].enriched.travels_to_ip_index;
158 if (turn.operations[0].enriched.next_ip_index != -1
159 || turn.operations[1].enriched.next_ip_index != -1)
161 out << " [" << turn.operations[0].enriched.next_ip_index
162 << "/" << turn.operations[1].enriched.next_ip_index
170 << "vx:" << turn.operations[0].enriched.travels_to_vertex_index
171 << "/" << turn.operations[1].enriched.travels_to_vertex_index
174 << std::setprecision(3)
175 << "dist: " << turn.operations[0].enriched.distance
176 << " / " << turn.operations[1].enriched.distance
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);
192 template <typename G1, typename P>
193 inline void geom_to_svg(G1 const& g1,
194 boost::geometry::svg_mapper<P> & mapper)
198 mapper.map(g1, "fill-opacity:0.5;fill:rgb(153,204,0);"
199 "stroke:rgb(153,204,0);stroke-width:3");
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)
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");
215 template <typename G1>
216 inline void geom_to_svg(G1 const& g1, std::string const& filename)
218 namespace bg = boost::geometry;
219 typedef typename bg::point_type<G1>::type mapper_point_type;
221 std::ofstream svg(filename.c_str(), std::ios::trunc);
222 bg::svg_mapper<mapper_point_type> mapper(svg, 500, 500);
224 geom_to_svg(g1, mapper);
227 template <typename G1, typename G2>
228 inline void geom_to_svg(G1 const& g1, G2 const& g2, std::string const& filename)
230 namespace bg = boost::geometry;
231 typedef typename bg::point_type<G1>::type mapper_point_type;
233 std::ofstream svg(filename.c_str(), std::ios::trunc);
234 bg::svg_mapper<mapper_point_type> mapper(svg, 500, 500);
236 geom_to_svg(g1, g2, mapper);
239 template <typename G1>
240 inline void geom_to_svg(std::string const& wkt1, std::string const& filename)
242 namespace bg = boost::geometry;
245 bg::read_wkt(wkt1, g1);
246 geom_to_svg(g1, filename);
249 template <typename G1, typename G2>
250 inline void geom_to_svg(std::string const& wkt1, std::string const& wkt2, std::string const& filename)
252 namespace bg = boost::geometry;
256 bg::read_wkt(wkt1, g1);
257 bg::read_wkt(wkt2, g2);
258 geom_to_svg(g1, g2, filename);
261 struct to_svg_assign_policy
262 : boost::geometry::detail::overlay::assign_null_policy
264 static bool const include_no_turn = false;
265 static bool const include_degenerate = false;
266 static bool const include_opposite = false;
269 template <typename G>
270 inline void to_svg(G const& g, std::string const& filename, bool /*sort*/ = true)
272 namespace bg = boost::geometry;
274 typedef typename bg::point_type<G>::type P;
276 std::ofstream svg(filename.c_str(), std::ios::trunc);
278 bg::svg_mapper<P> mapper(svg, 500, 500);
282 mapper.map(g, "fill-opacity:0.5;fill:rgb(153,204,0);"
283 "stroke:rgb(153,204,0);stroke-width:3");
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;
292 typedef std::deque<turn_info> Turns;
293 typedef bg::detail::self_get_turn_points::no_interrupt_policy InterruptPolicy;
296 InterruptPolicy interrupt_policy;
298 typedef bg::detail::overlay::get_turn_info<AssignPolicy> TurnPolicy;
300 bg::detail::self_get_turn_points::get_turns
303 >::apply(g, bg::detail::no_rescale_policy(), turns, interrupt_policy);
305 turns_to_svg<G>(turns, mapper);
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)
311 namespace bg = boost::geometry;
313 typedef typename bg::point_type<G1>::type mapper_point_type;
315 std::ofstream svg(filename.c_str(), std::ios::trunc);
317 bg::svg_mapper<mapper_point_type> mapper(svg, 500, 500);
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");
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;
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;
340 InterruptPolicy interrupt_policy;
342 if ( use_old_turns_policy )
344 boost::geometry::get_turns
346 Reverse1, Reverse2, AssignPolicy
347 >(g1, g2, bg::detail::no_rescale_policy(), turns, interrupt_policy);
351 typedef bg::detail::get_turns::get_turn_info_type
356 bg::detail::relate::turns::get_turns
359 >::apply(turns, g1, g2);
364 typedef bg::detail::relate::turns::less
367 bg::detail::relate::turns::less_op_xxx_linear
369 0, bg::detail::relate::turns::op_to_int<>
371 typename bg::cs_tag<G1>::type
373 std::sort(boost::begin(turns), boost::end(turns), less());
378 typedef typename bg::strategy::side::services::default_strategy
380 typename bg::cs_tag<G1>::type
381 >::type side_strategy_type;
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,
387 bg::detail::no_rescale_policy(),
388 side_strategy_type());
391 turns_to_svg<G1>(turns, mapper, enrich);
394 template <typename G>
395 inline void to_svg(std::string const& wkt, std::string const& filename)
398 boost::geometry::read_wkt(wkt, g);
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)
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);
412 #endif // BOOST_GEOMETRY_TEST_TO_SVG_HPP