7cb0ae96fd
[SVN r76390]
233 lines
7.9 KiB
C++
233 lines
7.9 KiB
C++
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
|
|
|
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
|
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
|
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
|
|
|
// Use, modification and distribution is subject to the Boost Software License,
|
|
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
// Linestring Example
|
|
|
|
#include <algorithm> // for reverse, unique
|
|
#include <iostream>
|
|
#include <iterator>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <boost/geometry/geometry.hpp>
|
|
#include <boost/geometry/geometries/linestring.hpp>
|
|
#include <boost/geometry/geometries/point_xy.hpp>
|
|
#include <boost/geometry/geometries/polygon.hpp>
|
|
|
|
// Optional includes and defines to handle c-arrays as points, std::vectors as linestrings
|
|
#include <boost/geometry/geometries/register/linestring.hpp>
|
|
#include <boost/geometry/geometries/adapted/c_array.hpp>
|
|
|
|
BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian)
|
|
|
|
BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::vector)
|
|
BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::deque)
|
|
|
|
|
|
template<typename P>
|
|
inline void translate_function(P& p)
|
|
{
|
|
p.x(p.x() + 100.0);
|
|
}
|
|
|
|
template<typename P>
|
|
struct scale_functor
|
|
{
|
|
inline void operator()(P& p)
|
|
{
|
|
p.x(p.x() * 1000.0);
|
|
p.y(p.y() * 1000.0);
|
|
}
|
|
};
|
|
|
|
|
|
template<typename Point>
|
|
struct round_coordinates
|
|
{
|
|
typedef typename boost::geometry::coordinate_type<Point>::type coordinate_type;
|
|
coordinate_type m_factor;
|
|
|
|
inline round_coordinates(coordinate_type const& factor)
|
|
: m_factor(factor)
|
|
{}
|
|
|
|
template <int Dimension>
|
|
inline void round(Point& p)
|
|
{
|
|
coordinate_type c = boost::geometry::get<Dimension>(p) / m_factor;
|
|
int rounded = c;
|
|
boost::geometry::set<Dimension>(p, coordinate_type(rounded) * m_factor);
|
|
}
|
|
|
|
inline void operator()(Point& p)
|
|
{
|
|
round<0>(p);
|
|
round<1>(p);
|
|
}
|
|
};
|
|
|
|
|
|
int main(void)
|
|
{
|
|
using namespace boost::geometry;
|
|
|
|
// Define a linestring, which is a vector of points, and add some points
|
|
// (we add them deliberately in different ways)
|
|
typedef model::d2::point_xy<double> point_2d;
|
|
typedef model::linestring<point_2d> linestring_2d;
|
|
linestring_2d ls;
|
|
|
|
// points can be created using "make" and added to a linestring using the std:: "push_back"
|
|
ls.push_back(make<point_2d>(1.1, 1.1));
|
|
|
|
// points can also be assigned using "assign_values" and added to a linestring using "append"
|
|
point_2d lp;
|
|
assign_values(lp, 2.5, 2.1);
|
|
append(ls, lp);
|
|
|
|
// Lines can be streamed using DSV (delimiter separated values)
|
|
std::cout << dsv(ls) << std::endl;
|
|
|
|
// The bounding box of linestrings can be calculated
|
|
typedef model::box<point_2d> box_2d;
|
|
box_2d b;
|
|
envelope(ls, b);
|
|
std::cout << dsv(b) << std::endl;
|
|
|
|
// The length of the line can be calulated
|
|
std::cout << "length: " << length(ls) << std::endl;
|
|
|
|
// All things from std::vector can be called, because a linestring is a vector
|
|
std::cout << "number of points 1: " << ls.size() << std::endl;
|
|
|
|
// All things from boost ranges can be called because a linestring is considered as a range
|
|
std::cout << "number of points 2: " << boost::size(ls) << std::endl;
|
|
|
|
// Generic function from geometry/OGC delivers the same value
|
|
std::cout << "number of points 3: " << num_points(ls) << std::endl;
|
|
|
|
// The distance from a point to a linestring can be calculated
|
|
point_2d p(1.9, 1.2);
|
|
std::cout << "distance of " << dsv(p)
|
|
<< " to line: " << distance(p, ls) << std::endl;
|
|
|
|
// A linestring is a vector. However, some algorithms consider "segments",
|
|
// which are the line pieces between two points of a linestring.
|
|
double d = distance(p, model::segment<point_2d >(ls.front(), ls.back()));
|
|
std::cout << "distance: " << d << std::endl;
|
|
|
|
// Add some three points more, let's do it using a classic array.
|
|
// (See documentation for picture of this linestring)
|
|
const double c[][2] = { {3.1, 3.1}, {4.9, 1.1}, {3.1, 1.9} };
|
|
append(ls, c);
|
|
std::cout << "appended: " << dsv(ls) << std::endl;
|
|
|
|
// Output as iterator-pair on a vector
|
|
{
|
|
std::vector<point_2d> v;
|
|
std::copy(ls.begin(), ls.end(), std::back_inserter(v));
|
|
|
|
std::cout
|
|
<< "as vector: "
|
|
<< dsv(v)
|
|
<< std::endl;
|
|
}
|
|
|
|
// All algorithms from std can be used: a linestring is a vector
|
|
std::reverse(ls.begin(), ls.end());
|
|
std::cout << "reversed: " << dsv(ls) << std::endl;
|
|
std::reverse(boost::begin(ls), boost::end(ls));
|
|
|
|
// The other way, using a vector instead of a linestring, is also possible
|
|
std::vector<point_2d> pv(ls.begin(), ls.end());
|
|
std::cout << "length: " << length(pv) << std::endl;
|
|
|
|
// If there are double points in the line, you can use unique to remove them
|
|
// So we add the last point, print, make a unique copy and print
|
|
{
|
|
// (sidenote, we have to make copies, because
|
|
// ls.push_back(ls.back()) often succeeds but
|
|
// IS dangerous and erroneous!
|
|
point_2d last = ls.back(), first = ls.front();
|
|
ls.push_back(last);
|
|
ls.insert(ls.begin(), first);
|
|
}
|
|
std::cout << "extra duplicate points: " << dsv(ls) << std::endl;
|
|
|
|
{
|
|
linestring_2d ls_copy;
|
|
std::unique_copy(ls.begin(), ls.end(), std::back_inserter(ls_copy),
|
|
boost::geometry::equal_to<point_2d>());
|
|
ls = ls_copy;
|
|
std::cout << "uniquecopy: " << dsv(ls) << std::endl;
|
|
}
|
|
|
|
// Lines can be simplified. This removes points, but preserves the shape
|
|
linestring_2d ls_simplified;
|
|
simplify(ls, ls_simplified, 0.5);
|
|
std::cout << "simplified: " << dsv(ls_simplified) << std::endl;
|
|
|
|
|
|
// for_each:
|
|
// 1) Lines can be visited with std::for_each
|
|
// 2) for_each_point is also defined for all geometries
|
|
// 3) for_each_segment is defined for all geometries to all segments
|
|
// 4) loop is defined for geometries to visit segments
|
|
// with state apart, and to be able to break out (not shown here)
|
|
{
|
|
linestring_2d lscopy = ls;
|
|
std::for_each(lscopy.begin(), lscopy.end(), translate_function<point_2d>);
|
|
for_each_point(lscopy, scale_functor<point_2d>());
|
|
for_each_point(lscopy, translate_function<point_2d>);
|
|
std::cout << "modified line: " << dsv(lscopy) << std::endl;
|
|
}
|
|
|
|
// Lines can be clipped using a clipping box. Clipped lines are added to the output iterator
|
|
box_2d cb(point_2d(1.5, 1.5), point_2d(4.5, 2.5));
|
|
|
|
std::vector<linestring_2d> clipped;
|
|
intersection(cb, ls, clipped);
|
|
|
|
// Also possible: clip-output to a vector of vectors
|
|
std::vector<std::vector<point_2d> > vector_out;
|
|
intersection(cb, ls, vector_out);
|
|
|
|
std::cout << "clipped output as vector:" << std::endl;
|
|
for (std::vector<std::vector<point_2d> >::const_iterator it
|
|
= vector_out.begin(); it != vector_out.end(); ++it)
|
|
{
|
|
std::cout << dsv(*it) << std::endl;
|
|
}
|
|
|
|
// Calculate the convex hull of the linestring
|
|
model::polygon<point_2d> hull;
|
|
convex_hull(ls, hull);
|
|
std::cout << "Convex hull:" << dsv(hull) << std::endl;
|
|
|
|
// All the above assumed 2D Cartesian linestrings. 3D is possible as well
|
|
// Let's define a 3D point ourselves, this time using 'float'
|
|
typedef model::point<float, 3, cs::cartesian> point_3d;
|
|
model::linestring<point_3d> line3;
|
|
line3.push_back(make<point_3d>(1,2,3));
|
|
line3.push_back(make<point_3d>(4,5,6));
|
|
line3.push_back(make<point_3d>(7,8,9));
|
|
|
|
// Not all algorithms work on 3d lines. For example convex hull does NOT.
|
|
// But, for example, length, distance, simplify, envelope and stream do.
|
|
std::cout << "3D: length: " << length(line3) << " line: " << dsv(line3) << std::endl;
|
|
|
|
// With DSV you can also use other delimiters, e.g. JSON style
|
|
std::cout << "JSON: "
|
|
<< dsv(ls, ", ", "[", "]", ", ", "[ ", " ]")
|
|
<< std::endl;
|
|
|
|
return 0;
|
|
}
|