diff --git a/extensions/example/Jamfile.v2 b/extensions/example/Jamfile.v2 index 8110621689..3c28f5e4fa 100644 --- a/extensions/example/Jamfile.v2 +++ b/extensions/example/Jamfile.v2 @@ -13,3 +13,4 @@ project boost-geometry-examples-extensions ; build-project gis ; +build-project random ; diff --git a/extensions/example/random/Jamfile.v2 b/extensions/example/random/Jamfile.v2 new file mode 100644 index 0000000000..6347a8eca0 --- /dev/null +++ b/extensions/example/random/Jamfile.v2 @@ -0,0 +1,16 @@ +# 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) + + +project boost-geometry-example-extensions-random + : # requirements + ; + +exe random_example : random_example.cpp ; diff --git a/extensions/example/random/random_example.cpp b/extensions/example/random/random_example.cpp new file mode 100644 index 0000000000..d3ecd8cdbb --- /dev/null +++ b/extensions/example/random/random_example.cpp @@ -0,0 +1,88 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +// Random Example - showing random sampling in various geometries + +#include +#include +#include + +#include +#include + +const int samples = 100; + +template +void draw_samples(Distribution& d, Generator& g, Mapper& m) { + for (int i = 0 ; i < samples ; ++i) + { + m.map(d(g), "fill-opacity:1;fill:rgb(255,0,0);stroke:rgb(255,0,0);stroke-width:1", 1); + } +} + +int main() +{ + namespace bg = boost::geometry; + typedef bg::model::point point; + typedef bg::model::segment segment; + typedef bg::model::box box; + typedef bg::model::multi_point multi_point; + typedef bg::model::polygon polygon; + + std::default_random_engine generator(1); + polygon poly; + boost::geometry::read_wkt("POLYGON((16 21,17.1226 17.5451,20.7553 17.5451," + "17.8164 15.4098,18.9389 11.9549,16 14.0902,13.0611 11.9549," + "14.1836 15.4098,11.2447 17.5451,14.8774 17.5451,16 21))", + poly); + box b(point(0, 0), point(10, 10)); + segment s(point(11, 0), point(21, 10)); + multi_point mp; + for (double y = 11.0 ; y <= 21.0 ; y += 0.5) + { + for(double x = 0.0 ; x <= 10.0 ; x += 0.5) + { + bg::append(mp, point(x, y)); + } + } + bg::random::uniform_point_distribution box_dist(b); + bg::random::uniform_point_distribution mp_dist(mp); + bg::random::uniform_point_distribution seg_dist(s); + bg::random::uniform_point_distribution poly_dist(poly); + std::ofstream svg("random.svg"); + bg::svg_mapper mapper(svg, 720, 720); + mapper.add(poly); + mapper.add(b); + mapper.add(mp); + mapper.add(s); + mapper.add(box(point(0, 22), point(22, 35))); + mapper.map(b, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:2"); + mapper.map(s, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:2"); + mapper.map(mp, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:2", 2); + mapper.map(poly, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:2"); + draw_samples(box_dist, generator, mapper); + draw_samples(mp_dist, generator, mapper); + draw_samples(seg_dist, generator, mapper); + draw_samples(poly_dist, generator, mapper); + + typedef bg::model::point> point_spherical; + typedef bg::model::box box_spherical; + box_spherical sb(point_spherical(0, 0), point_spherical(90, 90)); + bg::random::uniform_point_distribution sb_dist(sb); + for (int i = 0 ; i < 10*samples ; ++i) + { + point_spherical p = sb_dist(generator); + double x = bg::get<0>(p) / 90 * 22; + double y = 32 - bg::get<1>(p) / 90 * 10; + mapper.map(point(x,y), "fill-opacity:1;fill:rgb(255,0,0);stroke:rgb(255,0,0);stroke-width:1", 1); + } + return 0; +} diff --git a/extensions/test/Jamfile.v2 b/extensions/test/Jamfile.v2 index f35b9a1f95..31a228cba8 100644 --- a/extensions/test/Jamfile.v2 +++ b/extensions/test/Jamfile.v2 @@ -27,4 +27,4 @@ build-project algorithms ; build-project gis ; build-project iterators ; build-project nsphere ; - +build-project random ; diff --git a/extensions/test/random/Jamfile.v2 b/extensions/test/random/Jamfile.v2 new file mode 100644 index 0000000000..fcd3e40938 --- /dev/null +++ b/extensions/test/random/Jamfile.v2 @@ -0,0 +1,11 @@ +# Boost.Geometry (aka GGL, Generic Geometry Library) +# +# 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) + +test-suite boost-geometry-extensions-random + : + [ run random.cpp ] + ; + diff --git a/extensions/test/random/random.cpp b/extensions/test/random/random.cpp new file mode 100644 index 0000000000..29bcca49b9 --- /dev/null +++ b/extensions/test/random/random.cpp @@ -0,0 +1,149 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#include +#include +#include + +#include + +#include +#include + +typedef bg::model::point point2d_cart; +typedef bg::model::point point3d_cart; +typedef bg::model::point> point2d_geog; + +void test_geographic() +{ + //We check whether the generated points lie roughly along + //the great circle segment (<2 km distance on a sphere with + //the radius of earth) and are distributed uniformly with respect + //to great circle arc length. + typedef bg::model::linestring linestring; + linestring ls {{ 0.0, 0.0 }, { 45.0, 45.0 }, { 60.0, 60.0 }}; + bg::random::uniform_point_distribution l_dist(ls); + std::mt19937 generator(0); + int sample_count = 2000; + int count_below_45 = 0; + for (int i = 0 ; i < sample_count ; ++i) + { + point2d_geog sample = l_dist(generator); + BOOST_CHECK( bg::distance(sample, ls) < 2000 ); + if(bg::get<0>(sample) < 45.0) count_below_45++; + } + double length_ratio = bg::distance(ls[0], ls[1]) / + ( bg::distance(ls[0], ls[1]) + bg::distance(ls[1], ls[2]) ); + double sample_ratio = ((double) count_below_45) / sample_count; + bool in_range = sample_ratio * 0.95 < length_ratio + && sample_ratio * 1.05 > length_ratio; + BOOST_CHECK( in_range ); + + //We check whether the generated points lie in the spherical box + //(which is actually a triangle in this case) and whether the latitude + //is distributed as expected for uniform spherical distribution, using + //known area ratios of spherical caps. + typedef bg::model::box box; + box b {{ 0.0, 0.0 }, { 90.0, 90.0 }}; + bg::random::uniform_point_distribution b_dist(b); + int under_60 = 0; + for (int i = 0 ; i < sample_count ; ++i) + { + point2d_geog sample = b_dist(generator); + BOOST_CHECK( bg::within(sample, b) ); + if(bg::get<1>(sample) < 60.0) ++under_60; + } + BOOST_CHECK_GT(under_60, 0.5 * 0.95 * sample_count); + BOOST_CHECK_LT(under_60, 0.5 * 1.05 * sample_count); +} + +void test_polygon() +{ + //This test will test uniform sampling in polygon, which also checks + //uniform sampling in boxes. We check whether two equal distributions + //(copied using operator<< and operator>>) generate the same sequence + //of points and whether those points are uniformly distributed with + //respect to cartesian area. + typedef bg::model::polygon polygon; + polygon poly; + bg::read_wkt( + "POLYGON((16 21,17.1226 17.5451,20.7553 17.5451, 17.8164 15.4098," + "18.9389 11.9549,16 14.0902,13.0611 11.9549, 14.1836 15.4098," + "11.2447 17.5451,14.8774 17.5451,16 21))", + poly); + bg::random::uniform_point_distribution poly_dist(poly); + bg::random::uniform_point_distribution poly_dist2; + BOOST_CHECK( !(poly_dist == poly_dist2) ); + std::stringstream ss; + ss << poly_dist; + ss >> poly_dist2; + BOOST_CHECK( poly_dist == poly_dist2 ); + std::mt19937 generator(0), generator2(0); + for (int i = 0 ; i < 100 ; ++i) + { + point2d_cart sample1 = poly_dist(generator); + BOOST_CHECK( bg::equals(sample1, poly_dist2(generator2)) ); + BOOST_CHECK( bg::within(sample1, poly) ); + } + std::vector randoms; + const int uniformity_test_samples = 2000; + for (int i = 0 ; i < uniformity_test_samples ; ++i) + { + randoms.push_back(poly_dist(generator)); + } + typedef bg::model::box box; + box env, lhalf; + bg::envelope(poly, env); + bg::set(lhalf, bg::get(env)); + bg::set(lhalf, bg::get(env)); + bg::set(lhalf, bg::get(env)); + bg::set(lhalf, + (bg::get(env) + bg::get(env)) / 2); + std::vector lower; + bg::intersection(lhalf, poly, lower); + double area_ratio = bg::area(lower[0])/bg::area(poly); + int in_lower = 0; + for (int i = 0 ; i < uniformity_test_samples ; ++i) + { + if(bg::within(randoms[i], lhalf)) + ++in_lower; + } + double sample_ratio = ((double) in_lower ) / uniformity_test_samples; + BOOST_CHECK_GT( sample_ratio * 1.05, area_ratio ); + BOOST_CHECK_LT( sample_ratio * 0.95, area_ratio ); +} + +void test_multipoint() +{ + typedef bg::model::multi_point multipoint; + multipoint mp {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}; + int first = 0; + bg::random::uniform_point_distribution mp_dist(mp); + std::mt19937 generator(0); + int sample_count = 1000; + for (int i = 0 ; i < sample_count ; ++i) + { + point3d_cart sample = mp_dist(generator); + BOOST_CHECK( bg::within(sample, mp) ); + if(bg::equals(sample, mp[0])) ++first; + } + BOOST_CHECK_GT(first * 1.05, sample_count / 3); + BOOST_CHECK_LT(first * 0.95, sample_count / 3); +} + +int test_main(int, char* []) +{ + test_polygon(); + test_geographic(); + test_multipoint(); + return 0; +} diff --git a/include/boost/geometry/extensions/random/policies/uniform_box.hpp b/include/boost/geometry/extensions/random/policies/uniform_box.hpp new file mode 100644 index 0000000000..5e390abf06 --- /dev/null +++ b/include/boost/geometry/extensions/random/policies/uniform_box.hpp @@ -0,0 +1,121 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2020 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_BOX_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_BOX_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +namespace boost { namespace geometry +{ + +namespace policy { namespace uniform_point_distribution +{ + +template +< + typename Point, + typename DomainGeometry, + typename BoxStrategy = void, + typename CalculationType = void +> +struct box +{ +private: + typedef typename boost::mpl::if_ + < + boost::is_void, + typename boost::geometry::strategy::uniform_point_distribution::services:: + default_box_strategy + < + Point, + DomainGeometry + >::type, + BoxStrategy + >::type box_strategy; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename select_most_precise + < + typename coordinate_type::type, + double + >::type, + CalculationType + >::type ct; + box_strategy m_box_strategy; +public: + box(DomainGeometry const& d, box_strategy const& b = box_strategy()) : m_box_strategy(b) {} + bool equals(DomainGeometry const& l_domain, + DomainGeometry const& r_domain, + box const& r_policy) const + { + return boost::geometry::equals(l_domain, r_domain); + } + template + Point apply(Generator& g, DomainGeometry const& d) + { + typedef typename point_type::type domain_point; + domain_point p; + std::array::value> fractions; + std::uniform_real_distribution dist(0, 1); + std::generate(fractions.begin(), fractions.end(), std::bind(dist, std::ref(g))); + p = m_box_strategy.template apply<>(d, fractions); + Point r; + boost::geometry::transform(p, r); + return r; + } + void reset(DomainGeometry const&) {}; +}; + +namespace services +{ + +template +< + typename Point, + typename DomainGeometry, + int Dim, + typename CsTag +> +struct default_policy +< + Point, + DomainGeometry, + box_tag, + single_tag, + Dim, + CsTag +> +{ + typedef box type; +}; + +} // namespace services + +}} // namespace policy::uniform_point_distribution + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_BOX_HPP diff --git a/include/boost/geometry/extensions/random/policies/uniform_convex_hull_rejection.hpp b/include/boost/geometry/extensions/random/policies/uniform_convex_hull_rejection.hpp new file mode 100644 index 0000000000..1ba3510c10 --- /dev/null +++ b/include/boost/geometry/extensions/random/policies/uniform_convex_hull_rejection.hpp @@ -0,0 +1,129 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2020 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_CONVEX_HULL_REJECTION_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_CONVEX_HULL_REJECTION_HPP + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace boost { namespace geometry +{ + +namespace policy { namespace uniform_point_distribution +{ + +// The following strategy is suitable for geometries for which +// a Triangle sampling strategy can be provided +// a SideStrategy that computes the triangle area can be provided. +template +< + typename Point, + typename DomainGeometry, + typename TriangleStrategy = void, + typename AreaStrategy = void, +// typename ConvexHullStrategy + typename WithinStrategy = void +> +struct convex_hull_rejection +{ +private: + typedef typename boost::mpl::if_ + < + boost::is_void, + typename boost::geometry::strategy::uniform_point_distribution::services + ::default_triangle_strategy + < + Point, typename point_type::type + >::type, + TriangleStrategy + >::type triangle_strategy; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename boost::geometry::strategy::area::services::default_strategy + < + typename cs_tag::type + >::type, + AreaStrategy + >::type area_strategy; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename boost::geometry::strategy::within::services::default_strategy + < + Point, + DomainGeometry + >::type, + WithinStrategy + >::type within_strategy; + typedef typename point_type::type domain_point_type; + typedef boost::geometry::model::ring ring; + ring m_hull; + convex_polygon m_policy; + within_strategy m_within_strategy; +public: + convex_hull_rejection(DomainGeometry const& d, + triangle_strategy const& t = triangle_strategy(), + area_strategy const& a = area_strategy(), + within_strategy const& w = within_strategy()) : m_within_strategy(w) + + { + boost::geometry::convex_hull(d, m_hull); + m_policy = convex_polygon + < + Point, + ring, + triangle_strategy, + area_strategy + >(m_hull, t, a); + } + bool equals(DomainGeometry const& l_domain, + DomainGeometry const& r_domain, + convex_hull_rejection const& r_policy) const + { + return boost::geometry::equals(l_domain, r_domain) + && m_policy.equals(l_domain, r_domain, r_policy.m_policy); + } + template + Point apply(Generator& g, DomainGeometry const& d) + { + Point p; + do { + p = m_policy.apply(g, m_hull); + } while( !boost::geometry::within(p, d, m_within_strategy) ); + return p; + } + void reset(DomainGeometry const&) {}; +}; + +}} // namespace policy::uniform_point_distribution + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_AGNOSTIC_UNIFORM_CONVEX_HULL_REJECTION_HPP diff --git a/include/boost/geometry/extensions/random/policies/uniform_convex_polygon.hpp b/include/boost/geometry/extensions/random/policies/uniform_convex_polygon.hpp new file mode 100644 index 0000000000..05d6220b0e --- /dev/null +++ b/include/boost/geometry/extensions/random/policies/uniform_convex_polygon.hpp @@ -0,0 +1,155 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2020 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_CONVEX_POLYGON_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_CONVEX_POLYGON_HPP + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + +namespace policy { namespace uniform_point_distribution +{ + +// The following policy is suitable for convex rings and polygons with +// non-empty interior. +template +< + typename Point, + typename DomainGeometry, + typename TriangleStrategy = void, + typename AreaStrategy = void, + typename CalculationType = void +> +struct convex_polygon +{ +private: + typedef typename boost::mpl::if_ + < + boost::is_void, + typename select_most_precise + < + typename coordinate_type::type, + double + >::type, + CalculationType + >::type ct; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename boost::geometry::strategy::area::services::default_strategy + < + typename cs_tag::type + >::type, + AreaStrategy + >::type area_strategy; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename boost::geometry::strategy::uniform_point_distribution::services + ::default_triangle_strategy + < + Point, typename point_type::type + >::type, + TriangleStrategy + >::type triangle_strategy; + typedef typename area_strategy::template state area_state; + typedef typename area_strategy::template result_type area_result; + std::vector m_accumulated_areas; + triangle_strategy m_triangle; + // It is hard to see a reason not to use double here. If a triangle's + // relative size is smaller than doubles epsilon, it is too unlikely to + // realistically occur in a random sample. +public: + convex_polygon() {} + convex_polygon(DomainGeometry const& d, + triangle_strategy const& t = triangle_strategy(), + area_strategy const& a = area_strategy()) : + m_triangle(t) + { + m_accumulated_areas.reserve(boost::size(d) - 1); + m_accumulated_areas.push_back(0); + for (std::size_t i = 2 ; i < boost::size(d) ; ++i) { + area_state state; + a.apply(*d.begin(), *(d.begin() + i - 1), state); + a.apply(*(d.begin() + i - 1), *(d.begin() + i), state); + a.apply(*(d.begin() + i), *d.begin(), state); + ct s; + if(boost::geometry::point_order::value == boost::geometry::clockwise) + { + s = area_strategy::result(state); + } else { + s = -area_strategy::result(state); + } + m_accumulated_areas.push_back(m_accumulated_areas.back() + s); + } + } + bool equals(DomainGeometry const& l_domain, + DomainGeometry const& r_domain, + convex_polygon const& r_strategy) const + { + if( boost::size(l_domain) != boost::size(r_domain) ) + { + return false; + } + for (std::size_t i = 0; i < boost::size(l_domain); ++i) + { + if( !boost::geometry::equals(*(l_domain.begin() + i), + *(r_domain.begin() + i))) + { + return false; + } + } + return true; + } + template + Point apply(Generator& g, DomainGeometry const& d) + { + std::uniform_real_distribution dist(0, 1); + ct r = dist(g) * m_accumulated_areas.back(); + ct s = dist(g); + std::size_t i = std::distance( + m_accumulated_areas.begin(), + std::lower_bound(m_accumulated_areas.begin(), + m_accumulated_areas.end(), + r)); + return m_triangle.template apply + < + ct + >(* d.begin(), + *(d.begin() + i), + *(d.begin() + i + 1), + ( r - m_accumulated_areas[ i - 1 ]) / + ( m_accumulated_areas[ i ] - m_accumulated_areas[ i - 1 ] ), + s); + } + void reset(DomainGeometry const&) {}; +}; + +}} // namespace policy::uniform_point_distribution + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_CONVEX_POLYGON_HPP diff --git a/include/boost/geometry/extensions/random/policies/uniform_default_policy.hpp b/include/boost/geometry/extensions/random/policies/uniform_default_policy.hpp new file mode 100644 index 0000000000..d5a1fd0acd --- /dev/null +++ b/include/boost/geometry/extensions/random/policies/uniform_default_policy.hpp @@ -0,0 +1,68 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2020 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_DEFAULT_POLICY_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_DEFAULT_POLICY_HPP + +#include +#include +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + +namespace policy { namespace uniform_point_distribution { namespace services +{ + +template +< + typename Point, + typename DomainGeometry, + typename Tag = typename tag_cast + < + typename tag::type, + segment_tag, + box_tag, + linear_tag, + areal_tag, + pointlike_tag + >::type, + typename SingleOrMulti = typename tag_cast + < + typename tag::type, + single_tag, + multi_tag + >::type, + int Dim = dimension::value, + typename CsTag = typename tag_cast + < + typename cs_tag::type, + spherical_tag + >::type +> +struct default_policy +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_TYPE + , (types, CsTag>) + ); +}; + +}}} // namespace policy::uniform_point_distribution::services + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_DEFAULT_POLICY_HPP diff --git a/include/boost/geometry/extensions/random/policies/uniform_envelope_rejection.hpp b/include/boost/geometry/extensions/random/policies/uniform_envelope_rejection.hpp new file mode 100644 index 0000000000..3e4e9d3809 --- /dev/null +++ b/include/boost/geometry/extensions/random/policies/uniform_envelope_rejection.hpp @@ -0,0 +1,175 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2020 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_ENVELOPE_REJECTION_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_ENVELOPE_REJECTION_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace boost { namespace geometry +{ + +namespace policy { namespace uniform_point_distribution +{ + +template +< + typename Point, + typename DomainGeometry, + typename BoxStrategy = void, + typename EnvelopeStrategy = void, + typename WithinStrategy = void, + typename CalculationType = void +> +struct envelope_rejection +{ +private: + typedef model::box::type> envelope_type; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename boost::geometry::strategy::uniform_point_distribution::services:: + default_box_strategy + < + Point, + envelope_type + >::type, + BoxStrategy + >::type box_strategy; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename boost::geometry::strategy::envelope::services::default_strategy + < + typename tag::type, + typename cs_tag::type + >::type, + EnvelopeStrategy + >::type envelope_strategy; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename boost::geometry::strategy::within::services::default_strategy + < + Point, + DomainGeometry + >::type, + WithinStrategy + >::type within_strategy; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename select_most_precise + < + typename coordinate_type::type, + double + >::type, + CalculationType + >::type ct; + box_strategy m_box_strategy; + within_strategy m_within_strategy; + envelope_type m_env; +public: + envelope_rejection(DomainGeometry const& d, + box_strategy const& b = box_strategy(), + envelope_strategy const& e = envelope_strategy(), + within_strategy const& w = within_strategy()) : + m_box_strategy(b), + m_within_strategy(w), + m_env(return_envelope(d, e)) {} + bool equals(DomainGeometry const& l_domain, + DomainGeometry const& r_domain, + envelope_rejection const&) const + { + return boost::geometry::equals(l_domain, r_domain); + } + template + Point apply(Generator& g, DomainGeometry const& d) + { + typedef typename point_type::type domain_point; + domain_point p; + do { + std::array::value> fractions; + std::uniform_real_distribution dist(0, 1); + std::generate(fractions.begin(), fractions.end(), std::bind(dist, std::ref(g))); + p = m_box_strategy.template apply(m_env, fractions); + } while( ! ::boost::geometry::within(p, d, m_within_strategy) ); + Point r; + boost::geometry::transform(p, r); + return r; + } + void reset(DomainGeometry const&) {}; +}; + +namespace services +{ + +template +< + typename Point, + typename DomainGeometry, + typename MultiOrSingle, + typename CsTag +> +struct default_policy +< + Point, + DomainGeometry, + areal_tag, + MultiOrSingle, + 2, + CsTag +> +{ + typedef envelope_rejection type; +}; + +template +< + typename Point, + typename DomainGeometry, + typename MultiOrSingle, + typename CsTag +> +struct default_policy +< + Point, + DomainGeometry, + volumetric_tag, + MultiOrSingle, + 3, + CsTag +> +{ + typedef envelope_rejection type; +}; + +} // namespace services + +}} // namespace policy::uniform_point_distribution + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_ENVELOPE_REJECTION_HPP diff --git a/include/boost/geometry/extensions/random/policies/uniform_linear.hpp b/include/boost/geometry/extensions/random/policies/uniform_linear.hpp new file mode 100644 index 0000000000..4caf052538 --- /dev/null +++ b/include/boost/geometry/extensions/random/policies/uniform_linear.hpp @@ -0,0 +1,249 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2020 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_LINEAR_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_LINEAR_HPP + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + +namespace policy { namespace uniform_point_distribution { + +template +< + typename Point, + typename DomainGeometry, + typename InterpolationStrategy = void, + typename DistanceStrategy = void +> +struct linear_single +{ +private: + typedef typename boost::mpl::if_ + < + boost::is_void, + typename strategy::line_interpolate::services::default_strategy + < + typename cs_tag::type + >::type, + InterpolationStrategy + >::type interpolation_strategy; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename strategy::distance::services::default_strategy + < + point_tag, point_tag, Point + >::type, + DistanceStrategy + >::type distance_strategy; + interpolation_strategy m_interpolation_strategy; + distance_strategy m_distance_strategy; +public: + linear_single(DomainGeometry const& d, + interpolation_strategy const& s = interpolation_strategy(), + distance_strategy const& l = distance_strategy()) : + m_interpolation_strategy(s), + m_distance_strategy(l) {} + bool equals(DomainGeometry const& l_domain, + DomainGeometry const& r_domain, + linear_single const&) const + { + return boost::geometry::equals(l_domain, r_domain); + } + template + Point apply(Generator& g, DomainGeometry const& d) + { + typedef typename select_most_precise + < + double, + typename coordinate_type::type + >::type sample_type; + std::uniform_real_distribution dist(0, length(d, m_distance_strategy)); + sample_type r = dist(g); + Point p; + boost::geometry::line_interpolate(d, r, p, m_interpolation_strategy); + return p; + } + void reset(DomainGeometry const&) {}; +}; + +template +< + typename Point, + typename DomainGeometry, + typename InterpolationStrategy = void, + typename DistanceStrategy = void +> +class linear_multi +{ +private: + typedef typename default_length_result::type length_type; + typedef typename point_type::type domain_point_type; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename strategy::line_interpolate::services::default_strategy + < + typename cs_tag::type + >::type, + InterpolationStrategy + >::type interpolation_strategy; + typedef typename boost::mpl::if_ + < + boost::is_void, + typename strategy::distance::services::default_strategy + < + point_tag, point_tag, Point + >::type, + DistanceStrategy + >::type distance_strategy; + std::vector skip_list; + std::vector point_cache; + std::vector m_accumulated_lengths; + interpolation_strategy m_interpolation_strategy; +public: + linear_multi(DomainGeometry const& d, + interpolation_strategy const& in = interpolation_strategy(), + distance_strategy const& l = distance_strategy()) : + m_interpolation_strategy(in) + { + std::size_t i = 0; + point_cache.push_back(*segments_begin(d)->first); + m_accumulated_lengths.push_back(0); + for (auto it = segments_begin(d) ; it != segments_end(d) ; ++it) + { + m_accumulated_lengths.push_back( + m_accumulated_lengths.back() + length(*it, l)); + if (!boost::geometry::equals(point_cache.back(), *it->first)) + { + point_cache.push_back(*it->first); + skip_list.push_back(i); + } + point_cache.push_back(*it->second); + ++i; + } + } + bool equals(DomainGeometry const& l_domain, + DomainGeometry const& r_domain, + linear_multi const& r_policy) const + { + if(r_policy.skip_list.size() != skip_list.size() + || r_policy.point_cache.size() != point_cache.size()) + return false; + for (std::size_t i = 0; i < skip_list.size(); ++i) + { + if (skip_list[i] != r_policy.skip_list[i]) return false; + } + for (std::size_t i = 0; i < point_cache.size(); ++i) + { + if (!boost::geometry::equals(point_cache[i], r_policy.point_cache[i])) return false; + } + return true; + } + template + Point apply(Generator& g, DomainGeometry const& d) + { + typedef typename select_most_precise + < + double, + typename coordinate_type::type + >::type sample_type; + typedef model::segment segment; + std::uniform_real_distribution dist(0, m_accumulated_lengths.back()); + sample_type r = dist(g); + std::size_t i = std::distance( + m_accumulated_lengths.begin(), + std::lower_bound(m_accumulated_lengths.begin(), + m_accumulated_lengths.end(), + r)); + std::size_t offset = std::distance( + skip_list.begin(), + std::lower_bound(skip_list.begin(), skip_list.end(), i)); + Point p; + boost::geometry::line_interpolate( + segment(point_cache[ i + offset - 1], point_cache[ i + offset ]), + r - m_accumulated_lengths[ i - 1 ], + p, + m_interpolation_strategy); + return p; + } + void reset(DomainGeometry const&) {}; +}; + +namespace services { + +template +< + typename Point, + typename DomainGeometry, + int Dim, + typename CsTag +> +struct default_policy +< + Point, + DomainGeometry, + segment_tag, + single_tag, + Dim, + CsTag +> +{ + typedef linear_single type; +}; + +template +< + typename Point, + typename DomainGeometry, + typename MultiOrSingle, + int Dim, + typename CsTag +> +struct default_policy +< + Point, + DomainGeometry, + linear_tag, + MultiOrSingle, + Dim, + CsTag +> +{ + typedef linear_multi type; +}; + +} // namespace services + +}} // namespace policy::uniform_point_distribution + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_LINEAR_HPP diff --git a/include/boost/geometry/extensions/random/policies/uniform_point_discrete.hpp b/include/boost/geometry/extensions/random/policies/uniform_point_discrete.hpp new file mode 100644 index 0000000000..9bde4e90c6 --- /dev/null +++ b/include/boost/geometry/extensions/random/policies/uniform_point_discrete.hpp @@ -0,0 +1,135 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2020 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_POINT_DISCRETE_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_POINT_DISCRETE_HPP + +#include +#include + +#include +#include + +#include + +namespace boost { namespace geometry +{ + +namespace policy { namespace uniform_point_distribution { + +template +< + typename Point, + typename DomainGeometry +> +struct single_point +{ + single_point(DomainGeometry const& d) {} + template + bool equals(DomainGeometry const& l_domain, + DomainGeometry const& r_domain, + Policy const&) const + { + return boost::geometry::equals(l_domain.domain(), r_domain.domain()); + } + template + Point apply(Generator& g, DomainGeometry const& d) + { + Point r; + boost::geometry::transform(d, r); + return r; + } + void reset(DomainGeometry const&) {}; +}; + +template +< + typename Point, + typename DomainGeometry +> +struct multi_point +{ + multi_point(DomainGeometry const& p) {} + bool equals(DomainGeometry const& l_domain, + DomainGeometry const& r_domain, + multi_point const&) const + { + if(boost::size(l_domain) != boost::size(r_domain)) return false; + for (std::size_t i = 0; i < boost::size(l_domain); ++i) + if( !boost::geometry::equals( *(std::begin(l_domain) + i), + *(std::begin(r_domain) + i)) ) + { + return false; + } + return true; + } + template + Point apply(Generator& g, DomainGeometry const& d) + { + Point r; + if(boost::size(d) == 0) return r; + std::uniform_int_distribution + int_dist(0, boost::size(d) - 1); + boost::geometry::transform(*(std::begin(d) + int_dist(g)), r); + return r; + } + void reset(DomainGeometry const&) {} +}; + +namespace services { + +template +< + typename Point, + typename DomainGeometry, + int Dim, + typename CsTag +> +struct default_policy +< + Point, + DomainGeometry, + pointlike_tag, + single_tag, + Dim, + CsTag +> +{ + typedef single_point type; +}; + +template +< + typename Point, + typename DomainGeometry, + int Dim, + typename CsTag +> +struct default_policy +< + Point, + DomainGeometry, + pointlike_tag, + multi_tag, + Dim, + CsTag +> +{ + typedef multi_point type; +}; + +} // namespace services + +}} // namespace policy::uniform_point_distribution + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_POLICIES_UNIFORM_POINT_DISCRETE_HPP diff --git a/include/boost/geometry/extensions/random/strategies/cartesian/uniform_point_distribution_box.hpp b/include/boost/geometry/extensions/random/strategies/cartesian/uniform_point_distribution_box.hpp new file mode 100644 index 0000000000..4ea835797f --- /dev/null +++ b/include/boost/geometry/extensions/random/strategies/cartesian/uniform_point_distribution_box.hpp @@ -0,0 +1,95 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_CARTESIAN_UNIFORM_POINT_DISTRIBUTION_BOX_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_CARTESIAN_UNIFORM_POINT_DISTRIBUTION_BOX_HPP + +#include +#include + +#include +#include + +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace uniform_point_distribution +{ + +namespace detail +{ + +template +struct interval_product +{ + Box const& m_b; + std::array const& m_fractions; + inline interval_product(Box const& b, std::array const& f) : + m_b(b), m_fractions(f) {} + + template + inline void apply(PointDst& point_dst) const + { + set(point_dst, + get(m_b) + + m_fractions[Index] + * (get(m_b) - get(m_b)) ); + } +}; + +} // namespace detail + +template +< + typename Point, + typename DomainGeometry, + int Dim +> +struct cartesian_box +{ + template + static Point apply(DomainGeometry const& d, std::array const& f) + { + Point r; + for_each_coordinate(r, + detail::interval_product(d, f)); + return r; + } +}; + +namespace services { + +template +< + typename Point, + typename DomainGeometry, + int Dim +> +struct default_box_strategy +< + Point, + DomainGeometry, + Dim, + cartesian_tag +> +{ + typedef cartesian_box type; +}; + +} // namespace services + +}} // namespace strategy::uniform_point_distribution + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_CARTESIAN_UNIFORM_POINT_DISTRIBUTION_BOX_HPP diff --git a/include/boost/geometry/extensions/random/strategies/cartesian/uniform_point_distribution_triangle.hpp b/include/boost/geometry/extensions/random/strategies/cartesian/uniform_point_distribution_triangle.hpp new file mode 100644 index 0000000000..d425a3ed90 --- /dev/null +++ b/include/boost/geometry/extensions/random/strategies/cartesian/uniform_point_distribution_triangle.hpp @@ -0,0 +1,83 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_CARTESIAN_UNIFORM_POINT_DISTRIBUTION_TRIANGLE_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_CARTESIAN_UNIFORM_POINT_DISTRIBUTION_TRIANGLE_HPP + +#include +#include + +#include +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace uniform_point_distribution +{ + +template +< + typename Point, + typename DomainPoint +> +struct cartesian_triangle +{ +private: +public: + template + static Point apply(DomainPoint const& p1, + DomainPoint const& p2, + DomainPoint const& p3, + CalculationType const& s1, + CalculationType const& s2) + { + Point out; + CalculationType r1 = std::sqrt(s1); + set<0>(out, (1 - r1) * get<0>(p1) + + ( r1 * (1 - s2) ) * get<0>(p2) + + ( s2 * r1 * get<0>(p3))); + set<1>(out, (1 - r1) * get<1>(p1) + + ( r1 * (1 - s2) ) * get<1>(p2) + + ( s2 * r1 * get<1>(p3))); + return out; + } +}; + +namespace services +{ + +template +< + typename Point, + typename DomainPoint +> +struct default_triangle_strategy +< + Point, + DomainPoint, + cartesian_tag +> +{ + typedef cartesian_triangle type; +}; + +} // namespace services + +}} // namespace strategy::uniform_point_distribution + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_CARTESIAN_UNIFORM_POINT_DISTRIBUTION_TRIANGLE_HPP diff --git a/include/boost/geometry/extensions/random/strategies/spherical/uniform_point_distribution_box.hpp b/include/boost/geometry/extensions/random/strategies/spherical/uniform_point_distribution_box.hpp new file mode 100644 index 0000000000..f64f0bdb60 --- /dev/null +++ b/include/boost/geometry/extensions/random/strategies/spherical/uniform_point_distribution_box.hpp @@ -0,0 +1,130 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_SPHERICAL_UNIFORM_POINT_DISTRIBUTION_BOX_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_SPHERICAL_UNIFORM_POINT_DISTRIBUTION_BOX_HPP + +#include + +#include +#include + +#include + +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace uniform_point_distribution +{ + +template +< + typename Point, + typename DomainGeometry, + std::size_t Dim +> +struct spherical_box +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_TYPE + , (types>) + ); +}; + +template +< + typename Point, + typename DomainGeometry +> +struct spherical_box +{ + template + static Point apply(DomainGeometry const& d, std::array const& f) + { + Point out; + set_from_radian<0>(out, get_as_radian<0, 0>(d) + + f[0] * ( get_as_radian<1, 0>(d) - get_as_radian<0, 0>(d) )); + CalculationType lat1 = get_as_radian<0, 1>(d); + CalculationType lat2 = get_as_radian<1, 1>(d); + CalculationType x1 = (1.0 - std::cos(lat1)) / 2; + CalculationType x2 = (1.0 - std::cos(lat2)) / 2; + CalculationType lo = std::min(x1, x2); + CalculationType hi = std::max(x1, x2); + CalculationType x = lo + f[1] * (hi - lo); + set_from_radian<1>(out, std::acos(1.0 - 2.0 * x)); + return out; + } +}; + +template +< + typename Point, + typename DomainGeometry +> +struct spherical_box +{ + template + static Point apply(DomainGeometry const& d, std::array const& f) + { + Point out = spherical_box::apply(d, {{f[0], f[1]}}); + CalculationType r1 = get<0, 2>(d); + CalculationType r2 = get<1, 2>(d); + CalculationType lo = r1 * r1 * r1; + CalculationType hi = r2 * r2 * r2; + set<2>(out, std::cbrt( lo + f[2] * ( hi - lo ) )); + return out; + } +}; + +namespace services { + +template +< + typename Point, + typename DomainGeometry +> +struct default_box_strategy +< + Point, + DomainGeometry, + 2, + spherical_tag +> +{ + typedef spherical_box type; +}; + +template +< + typename Point, + typename DomainGeometry +> +struct default_box_strategy +< + Point, + DomainGeometry, + 3, + spherical_tag +> +{ + typedef spherical_box type; +}; + +} // namespace services + +}} // namespace strategy::uniform_point_distribution + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_SPHERICAL_UNIFORM_POINT_DISTRIBUTION_BOX_HPP diff --git a/include/boost/geometry/extensions/random/strategies/uniform_point_distribution_box.hpp b/include/boost/geometry/extensions/random/strategies/uniform_point_distribution_box.hpp new file mode 100644 index 0000000000..280cc52253 --- /dev/null +++ b/include/boost/geometry/extensions/random/strategies/uniform_point_distribution_box.hpp @@ -0,0 +1,54 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_UNIFORM_POINT_DISTRIBUTION_BOX_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_UNIFORM_POINT_DISTRIBUTION_BOX_HPP + +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace uniform_point_distribution { namespace services +{ + +template +< + typename Point, + typename DomainGeometry, + int Dim = dimension::value, + typename CsTag = typename tag_cast + < + typename cs_tag::type, + spherical_tag + >::type +> +struct default_box_strategy +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_TYPE + , (types>) + ); +}; + +}}} // namespace strategy::uniform_point_distribution::services + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_UNIFORM_POINT_DISTRIBUTION_BOX_HPP diff --git a/include/boost/geometry/extensions/random/strategies/uniform_point_distribution_triangle.hpp b/include/boost/geometry/extensions/random/strategies/uniform_point_distribution_triangle.hpp new file mode 100644 index 0000000000..fa4607d33c --- /dev/null +++ b/include/boost/geometry/extensions/random/strategies/uniform_point_distribution_triangle.hpp @@ -0,0 +1,52 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_UNIFORM_POINT_DISTRIBUTION_TRIANGLE_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_UNIFORM_POINT_DISTRIBUTION_TRIANGLE_HPP + +#include + +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace uniform_point_distribution { namespace services +{ + +template +< + typename Point, + typename DomainPoint, + typename CsTag = typename tag_cast + < + typename cs_tag::type, + spherical_tag + >::type +> +struct default_triangle_strategy +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_TYPE + , (types) + ); +}; + +}}} // namespace strategy::uniform_point_distribution::services + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_STRATEGIES_UNIFORM_POINT_DISTRIBUTION_TRIANGLE_HPP diff --git a/include/boost/geometry/extensions/random/uniform_point_distribution.hpp b/include/boost/geometry/extensions/random/uniform_point_distribution.hpp new file mode 100644 index 0000000000..32527f83d9 --- /dev/null +++ b/include/boost/geometry/extensions/random/uniform_point_distribution.hpp @@ -0,0 +1,160 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_RANDOM_UNIFORM_POINT_DISTRIBUTION_HPP +#define BOOST_GEOMETRY_EXTENSIONS_RANDOM_UNIFORM_POINT_DISTRIBUTION_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace geometry { namespace random +{ + +template +< + typename DomainGeometry, + typename Point = typename geometry::point_type::type, + typename Policy = + typename policy::uniform_point_distribution::services::default_policy + < + Point, + DomainGeometry + >::type +> +class uniform_point_distribution +{ +public: + typedef Point result_type; + typedef DomainGeometry domain_type; + class param_type { + public: + param_type(DomainGeometry const& domain) : m_domain(domain) {} + param_type(param_type const& p) : m_domain(p.m_domain) {} + DomainGeometry const& domain() const { return m_domain; } + bool operator==(param_type const& rhs) const + { + return equals(m_domain, rhs.m_domain); + } + private: + DomainGeometry m_domain; + }; + uniform_point_distribution(DomainGeometry const& domain, + Policy const& policy) + : m_policy(policy), + m_param(domain) {} + uniform_point_distribution(DomainGeometry const& domain) + : m_policy(domain), + m_param(domain) {} + uniform_point_distribution() + : m_policy(DomainGeometry()), + m_param(DomainGeometry()) {} + uniform_point_distribution(param_type const& param) + : m_policy(param.domain()), + m_param(param) {} + void reset() { m_policy.reset(); } + param_type param() const { return m_param; } + void param(param_type const& p) + { + m_param = p; + m_policy = Policy(p.domain()); + } + bool operator==(uniform_point_distribution const& rhs) const + { + return m_policy.equals(m_param.domain(), + rhs.domain(), + rhs.m_policy); + } + domain_type const& domain() const { return m_param.domain(); } + template< typename Generator > + result_type operator()(Generator& g) + { + return m_policy.apply(g, m_param.domain()); + } + template< typename Generator > + result_type operator()(Generator& g, param_type const& p) + { + Policy pol(p.domain()); + return pol.apply(g, p.domain()); + } +private: + Policy m_policy; + param_type m_param; +}; + +template +< + typename DomainGeometry, + typename Point = typename geometry::point_type::type +> +inline uniform_point_distribution + return_uniform_point_distribution(DomainGeometry const& domain) +{ + return uniform_point_distribution(domain); +} + +}}} // namespace boost::geometry::random + +template +< + typename Char, + typename Traits, + typename Point, + typename DomainGeometry, + typename Policy +> +inline std::basic_ostream& operator<< + ( + std::basic_ostream &os, + boost::geometry::random::uniform_point_distribution + < + DomainGeometry, Point, Policy + > const& dist + ) +{ + os << boost::geometry::wkt(dist.domain()); + return os; +} + +template +< + typename Char, + typename Traits, + typename Point, + typename DomainGeometry, + typename Policy +> +inline std::basic_istream& operator>> + ( + std::basic_istream &is, + boost::geometry::random::uniform_point_distribution + < + DomainGeometry, Point, Policy + > & dist + ) +{ + std::basic_string line; + std::getline(is, line); + DomainGeometry g; + namespace bg = boost::geometry; + typedef typename bg::random::uniform_point_distribution + < + DomainGeometry, Point, Policy + >::param_type param_type; + bg::read_wkt(line, g); + dist.param( param_type(g) ); + return is; +} + +#endif // BOOST_GEOMETRY_EXTENSIONS_RANDOM_UNIFORM_POINT_DISTRIBUTION_HPP