• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
turns_to_svg(Turns const & turns,Mapper & mapper,bool=false)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>
geom_to_svg(G1 const & g1,boost::geometry::svg_mapper<P> & mapper)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>
geom_to_svg(G1 const & g1,G2 const & g2,boost::geometry::svg_mapper<P> & mapper)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>
geom_to_svg(G1 const & g1,std::string const & filename)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>
geom_to_svg(G1 const & g1,G2 const & g2,std::string const & filename)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>
geom_to_svg(std::string const & wkt1,std::string const & filename)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>
geom_to_svg(std::string const & wkt1,std::string const & wkt2,std::string const & filename)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>
to_svg(G const & g,std::string const & filename,bool=true)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         <
302             false, TurnPolicy
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>
to_svg(G1 const & g1,G2 const & g2,std::string const & filename,bool sort=true,bool use_old_turns_policy=false,bool enrich=false)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     {
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;
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>
to_svg(std::string const & wkt,std::string const & filename)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>
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)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
413