1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
7 // Use, modification and distribution is subject to the Boost Software License,
8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
13 #include <algorithm> // for reverse, unique
19 #include <boost/geometry/geometry.hpp>
20 #include <boost/geometry/geometries/linestring.hpp>
21 #include <boost/geometry/geometries/point_xy.hpp>
22 #include <boost/geometry/geometries/polygon.hpp>
24 // Optional includes and defines to handle c-arrays as points, std::vectors as linestrings
25 #include <boost/geometry/geometries/register/linestring.hpp>
26 #include <boost/geometry/geometries/adapted/c_array.hpp>
28 BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian
)
30 BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::vector
)
31 BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::deque
)
35 inline void translate_function(P
& p
)
43 inline void operator()(P
& p
)
51 template<typename Point
>
52 struct round_coordinates
54 typedef typename
boost::geometry::coordinate_type
<Point
>::type coordinate_type
;
55 coordinate_type m_factor
;
57 inline round_coordinates(coordinate_type
const& factor
)
61 template <int Dimension
>
62 inline void round(Point
& p
)
64 coordinate_type c
= boost::geometry::get
<Dimension
>(p
) / m_factor
;
66 boost::geometry::set
<Dimension
>(p
, coordinate_type(rounded
) * m_factor
);
69 inline void operator()(Point
& p
)
79 using namespace boost::geometry
;
81 // Define a linestring, which is a vector of points, and add some points
82 // (we add them deliberately in different ways)
83 typedef model::d2::point_xy
<double> point_2d
;
84 typedef model::linestring
<point_2d
> linestring_2d
;
87 // points can be created using "make" and added to a linestring using the std:: "push_back"
88 ls
.push_back(make
<point_2d
>(1.1, 1.1));
90 // points can also be assigned using "assign_values" and added to a linestring using "append"
92 assign_values(lp
, 2.5, 2.1);
95 // Lines can be streamed using DSV (delimiter separated values)
96 std::cout
<< dsv(ls
) << std::endl
;
98 // The bounding box of linestrings can be calculated
99 typedef model::box
<point_2d
> box_2d
;
102 std::cout
<< dsv(b
) << std::endl
;
104 // The length of the line can be calulated
105 std::cout
<< "length: " << length(ls
) << std::endl
;
107 // All things from std::vector can be called, because a linestring is a vector
108 std::cout
<< "number of points 1: " << ls
.size() << std::endl
;
110 // All things from boost ranges can be called because a linestring is considered as a range
111 std::cout
<< "number of points 2: " << boost::size(ls
) << std::endl
;
113 // Generic function from geometry/OGC delivers the same value
114 std::cout
<< "number of points 3: " << num_points(ls
) << std::endl
;
116 // The distance from a point to a linestring can be calculated
117 point_2d
p(1.9, 1.2);
118 std::cout
<< "distance of " << dsv(p
)
119 << " to line: " << distance(p
, ls
) << std::endl
;
121 // A linestring is a vector. However, some algorithms consider "segments",
122 // which are the line pieces between two points of a linestring.
123 double d
= distance(p
, model::segment
<point_2d
>(ls
.front(), ls
.back()));
124 std::cout
<< "distance: " << d
<< std::endl
;
126 // Add some three points more, let's do it using a classic array.
127 // (See documentation for picture of this linestring)
128 const double c
[][2] = { {3.1, 3.1}, {4.9, 1.1}, {3.1, 1.9} };
130 std::cout
<< "appended: " << dsv(ls
) << std::endl
;
132 // Output as iterator-pair on a vector
134 std::vector
<point_2d
> v
;
135 std::copy(ls
.begin(), ls
.end(), std::back_inserter(v
));
143 // All algorithms from std can be used: a linestring is a vector
144 std::reverse(ls
.begin(), ls
.end());
145 std::cout
<< "reversed: " << dsv(ls
) << std::endl
;
146 std::reverse(boost::begin(ls
), boost::end(ls
));
148 // The other way, using a vector instead of a linestring, is also possible
149 std::vector
<point_2d
> pv(ls
.begin(), ls
.end());
150 std::cout
<< "length: " << length(pv
) << std::endl
;
152 // If there are double points in the line, you can use unique to remove them
153 // So we add the last point, print, make a unique copy and print
155 // (sidenote, we have to make copies, because
156 // ls.push_back(ls.back()) often succeeds but
157 // IS dangerous and erroneous!
158 point_2d last
= ls
.back(), first
= ls
.front();
160 ls
.insert(ls
.begin(), first
);
162 std::cout
<< "extra duplicate points: " << dsv(ls
) << std::endl
;
165 linestring_2d ls_copy
;
166 std::unique_copy(ls
.begin(), ls
.end(), std::back_inserter(ls_copy
),
167 boost::geometry::equal_to
<point_2d
>());
169 std::cout
<< "uniquecopy: " << dsv(ls
) << std::endl
;
172 // Lines can be simplified. This removes points, but preserves the shape
173 linestring_2d ls_simplified
;
174 simplify(ls
, ls_simplified
, 0.5);
175 std::cout
<< "simplified: " << dsv(ls_simplified
) << std::endl
;
179 // 1) Lines can be visited with std::for_each
180 // 2) for_each_point is also defined for all geometries
181 // 3) for_each_segment is defined for all geometries to all segments
182 // 4) loop is defined for geometries to visit segments
183 // with state apart, and to be able to break out (not shown here)
185 linestring_2d lscopy
= ls
;
186 std::for_each(lscopy
.begin(), lscopy
.end(), translate_function
<point_2d
>);
187 for_each_point(lscopy
, scale_functor
<point_2d
>());
188 for_each_point(lscopy
, translate_function
<point_2d
>);
189 std::cout
<< "modified line: " << dsv(lscopy
) << std::endl
;
192 // Lines can be clipped using a clipping box. Clipped lines are added to the output iterator
193 box_2d
cb(point_2d(1.5, 1.5), point_2d(4.5, 2.5));
195 std::vector
<linestring_2d
> clipped
;
196 intersection(cb
, ls
, clipped
);
198 // Also possible: clip-output to a vector of vectors
199 std::vector
<std::vector
<point_2d
> > vector_out
;
200 intersection(cb
, ls
, vector_out
);
202 std::cout
<< "clipped output as vector:" << std::endl
;
203 for (std::vector
<std::vector
<point_2d
> >::const_iterator it
204 = vector_out
.begin(); it
!= vector_out
.end(); ++it
)
206 std::cout
<< dsv(*it
) << std::endl
;
209 // Calculate the convex hull of the linestring
210 model::polygon
<point_2d
> hull
;
211 convex_hull(ls
, hull
);
212 std::cout
<< "Convex hull:" << dsv(hull
) << std::endl
;
214 // All the above assumed 2D Cartesian linestrings. 3D is possible as well
215 // Let's define a 3D point ourselves, this time using 'float'
216 typedef model::point
<float, 3, cs::cartesian
> point_3d
;
217 model::linestring
<point_3d
> line3
;
218 line3
.push_back(make
<point_3d
>(1,2,3));
219 line3
.push_back(make
<point_3d
>(4,5,6));
220 line3
.push_back(make
<point_3d
>(7,8,9));
222 // Not all algorithms work on 3d lines. For example convex hull does NOT.
223 // But, for example, length, distance, simplify, envelope and stream do.
224 std::cout
<< "3D: length: " << length(line3
) << " line: " << dsv(line3
) << std::endl
;
226 // With DSV you can also use other delimiters, e.g. JSON style
227 std::cout
<< "JSON: "
228 << dsv(ls
, ", ", "[", "]", ", ", "[ ", " ]")