02_linestring_example.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  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. //
  9. // Linestring Example
  10. #include <algorithm> // for reverse, unique
  11. #include <iostream>
  12. #include <iterator>
  13. #include <utility>
  14. #include <vector>
  15. #include <boost/geometry/geometry.hpp>
  16. #include <boost/geometry/geometries/linestring.hpp>
  17. #include <boost/geometry/geometries/point_xy.hpp>
  18. #include <boost/geometry/geometries/polygon.hpp>
  19. // Optional includes and defines to handle c-arrays as points, std::vectors as linestrings
  20. #include <boost/geometry/geometries/register/linestring.hpp>
  21. #include <boost/geometry/geometries/adapted/c_array.hpp>
  22. BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian)
  23. BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::vector)
  24. BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::deque)
  25. template<typename P>
  26. inline void translate_function(P& p)
  27. {
  28. p.x(p.x() + 100.0);
  29. }
  30. template<typename P>
  31. struct scale_functor
  32. {
  33. inline void operator()(P& p)
  34. {
  35. p.x(p.x() * 1000.0);
  36. p.y(p.y() * 1000.0);
  37. }
  38. };
  39. template<typename Point>
  40. struct round_coordinates
  41. {
  42. typedef typename boost::geometry::coordinate_type<Point>::type coordinate_type;
  43. coordinate_type m_factor;
  44. inline round_coordinates(coordinate_type const& factor)
  45. : m_factor(factor)
  46. {}
  47. template <int Dimension>
  48. inline void round(Point& p)
  49. {
  50. coordinate_type c = boost::geometry::get<Dimension>(p) / m_factor;
  51. int rounded = c;
  52. boost::geometry::set<Dimension>(p, coordinate_type(rounded) * m_factor);
  53. }
  54. inline void operator()(Point& p)
  55. {
  56. round<0>(p);
  57. round<1>(p);
  58. }
  59. };
  60. int main(void)
  61. {
  62. using namespace boost::geometry;
  63. // Define a linestring, which is a vector of points, and add some points
  64. // (we add them deliberately in different ways)
  65. typedef model::d2::point_xy<double> point_2d;
  66. typedef model::linestring<point_2d> linestring_2d;
  67. linestring_2d ls;
  68. // points can be created using "make" and added to a linestring using the std:: "push_back"
  69. ls.push_back(make<point_2d>(1.1, 1.1));
  70. // points can also be assigned using "assign_values" and added to a linestring using "append"
  71. point_2d lp;
  72. assign_values(lp, 2.5, 2.1);
  73. append(ls, lp);
  74. // Lines can be streamed using DSV (delimiter separated values)
  75. std::cout << dsv(ls) << std::endl;
  76. // The bounding box of linestrings can be calculated
  77. typedef model::box<point_2d> box_2d;
  78. box_2d b;
  79. envelope(ls, b);
  80. std::cout << dsv(b) << std::endl;
  81. // The length of the line can be calulated
  82. std::cout << "length: " << length(ls) << std::endl;
  83. // All things from std::vector can be called, because a linestring is a vector
  84. std::cout << "number of points 1: " << ls.size() << std::endl;
  85. // All things from boost ranges can be called because a linestring is considered as a range
  86. std::cout << "number of points 2: " << boost::size(ls) << std::endl;
  87. // Generic function from geometry/OGC delivers the same value
  88. std::cout << "number of points 3: " << num_points(ls) << std::endl;
  89. // The distance from a point to a linestring can be calculated
  90. point_2d p(1.9, 1.2);
  91. std::cout << "distance of " << dsv(p)
  92. << " to line: " << distance(p, ls) << std::endl;
  93. // A linestring is a vector. However, some algorithms consider "segments",
  94. // which are the line pieces between two points of a linestring.
  95. double d = distance(p, model::segment<point_2d >(ls.front(), ls.back()));
  96. std::cout << "distance: " << d << std::endl;
  97. // Add some three points more, let's do it using a classic array.
  98. // (See documentation for picture of this linestring)
  99. const double c[][2] = { {3.1, 3.1}, {4.9, 1.1}, {3.1, 1.9} };
  100. append(ls, c);
  101. std::cout << "appended: " << dsv(ls) << std::endl;
  102. // Output as iterator-pair on a vector
  103. {
  104. std::vector<point_2d> v;
  105. std::copy(ls.begin(), ls.end(), std::back_inserter(v));
  106. std::cout
  107. << "as vector: "
  108. << dsv(v)
  109. << std::endl;
  110. }
  111. // All algorithms from std can be used: a linestring is a vector
  112. std::reverse(ls.begin(), ls.end());
  113. std::cout << "reversed: " << dsv(ls) << std::endl;
  114. std::reverse(boost::begin(ls), boost::end(ls));
  115. // The other way, using a vector instead of a linestring, is also possible
  116. std::vector<point_2d> pv(ls.begin(), ls.end());
  117. std::cout << "length: " << length(pv) << std::endl;
  118. // If there are double points in the line, you can use unique to remove them
  119. // So we add the last point, print, make a unique copy and print
  120. {
  121. // (sidenote, we have to make copies, because
  122. // ls.push_back(ls.back()) often succeeds but
  123. // IS dangerous and erroneous!
  124. point_2d last = ls.back(), first = ls.front();
  125. ls.push_back(last);
  126. ls.insert(ls.begin(), first);
  127. }
  128. std::cout << "extra duplicate points: " << dsv(ls) << std::endl;
  129. {
  130. linestring_2d ls_copy;
  131. std::unique_copy(ls.begin(), ls.end(), std::back_inserter(ls_copy),
  132. boost::geometry::equal_to<point_2d>());
  133. ls = ls_copy;
  134. std::cout << "uniquecopy: " << dsv(ls) << std::endl;
  135. }
  136. // Lines can be simplified. This removes points, but preserves the shape
  137. linestring_2d ls_simplified;
  138. simplify(ls, ls_simplified, 0.5);
  139. std::cout << "simplified: " << dsv(ls_simplified) << std::endl;
  140. // for_each:
  141. // 1) Lines can be visited with std::for_each
  142. // 2) for_each_point is also defined for all geometries
  143. // 3) for_each_segment is defined for all geometries to all segments
  144. // 4) loop is defined for geometries to visit segments
  145. // with state apart, and to be able to break out (not shown here)
  146. {
  147. linestring_2d lscopy = ls;
  148. std::for_each(lscopy.begin(), lscopy.end(), translate_function<point_2d>);
  149. for_each_point(lscopy, scale_functor<point_2d>());
  150. for_each_point(lscopy, translate_function<point_2d>);
  151. std::cout << "modified line: " << dsv(lscopy) << std::endl;
  152. }
  153. // Lines can be clipped using a clipping box. Clipped lines are added to the output iterator
  154. box_2d cb(point_2d(1.5, 1.5), point_2d(4.5, 2.5));
  155. std::vector<linestring_2d> clipped;
  156. intersection(cb, ls, clipped);
  157. // Also possible: clip-output to a vector of vectors
  158. std::vector<std::vector<point_2d> > vector_out;
  159. intersection(cb, ls, vector_out);
  160. std::cout << "clipped output as vector:" << std::endl;
  161. for (std::vector<std::vector<point_2d> >::const_iterator it
  162. = vector_out.begin(); it != vector_out.end(); ++it)
  163. {
  164. std::cout << dsv(*it) << std::endl;
  165. }
  166. // Calculate the convex hull of the linestring
  167. model::polygon<point_2d> hull;
  168. convex_hull(ls, hull);
  169. std::cout << "Convex hull:" << dsv(hull) << std::endl;
  170. // All the above assumed 2D Cartesian linestrings. 3D is possible as well
  171. // Let's define a 3D point ourselves, this time using 'float'
  172. typedef model::point<float, 3, cs::cartesian> point_3d;
  173. model::linestring<point_3d> line3;
  174. line3.push_back(make<point_3d>(1,2,3));
  175. line3.push_back(make<point_3d>(4,5,6));
  176. line3.push_back(make<point_3d>(7,8,9));
  177. // Not all algorithms work on 3d lines. For example convex hull does NOT.
  178. // But, for example, length, distance, simplify, envelope and stream do.
  179. std::cout << "3D: length: " << length(line3) << " line: " << dsv(line3) << std::endl;
  180. // With DSV you can also use other delimiters, e.g. JSON style
  181. std::cout << "JSON: "
  182. << dsv(ls, ", ", "[", "]", ", ", "[ ", " ]")
  183. << std::endl;
  184. return 0;
  185. }