to_svg.hpp 14 KB

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