PageRenderTime 59ms CodeModel.GetById 12ms app.highlight 43ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/geometry/test/robustness/convex_hull/random_multi_points.cpp

https://github.com/delalond/boost_1_54_0-bgq
C++ | 225 lines | 179 code | 39 blank | 7 comment | 18 complexity | d27dab88a0c2a8e2d7fd45f848acb5c4 MD5 | raw file
  1// Boost.Geometry (aka GGL, Generic Geometry Library)
  2// Robustness Test - convex_hull
  3
  4// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
  5
  6// Use, modification and distribution is subject to the Boost Software License,
  7// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  8// http://www.boost.org/LICENSE_1_0.txt)
  9
 10#define BOOST_GEOMETRY_REPORT_OVERLAY_ERROR
 11#define BOOST_GEOMETRY_NO_BOOST_TEST
 12
 13#include <sstream>
 14#include <fstream>
 15
 16#include <boost/program_options.hpp>
 17#include <boost/random/linear_congruential.hpp>
 18#include <boost/random/uniform_int.hpp>
 19#include <boost/random/uniform_real.hpp>
 20#include <boost/random/variate_generator.hpp>
 21#include <boost/timer.hpp>
 22
 23#include <boost/geometry.hpp>
 24#include <boost/geometry/geometries/geometries.hpp>
 25#include <boost/geometry/geometries/point_xy.hpp>
 26#include <boost/geometry/multi/geometries/multi_geometries.hpp>
 27#include <boost/geometry/io/svg/svg_mapper.hpp>
 28
 29struct settings_type
 30{
 31    bool svg;
 32    bool wkt;
 33
 34    settings_type()
 35        : svg(false)
 36        , wkt(false)
 37    {}
 38};
 39
 40namespace bg = boost::geometry;
 41
 42template <typename Geometry1, typename Geometry2>
 43void create_svg(std::string const& filename, Geometry1 const& points, Geometry2 const& hull)
 44{
 45    typedef typename boost::geometry::point_type<Geometry1>::type point_type;
 46
 47    boost::geometry::model::box<point_type> box;
 48    bg::envelope(hull, box);
 49    bg::buffer(box, box, 1.0);
 50
 51    std::ofstream svg(filename.c_str());
 52    boost::geometry::svg_mapper<point_type> mapper(svg, 800, 800);
 53    mapper.add(box);
 54
 55    mapper.map(hull, "opacity:0.8;fill:none;stroke:rgb(255,0,255);stroke-width:4;stroke-dasharray:1,7;stroke-linecap:round");
 56    mapper.map(points, "fill-opacity:0.5;fill:rgb(0,0,255);", 5);
 57}
 58
 59
 60template <typename MultiPoint, typename Generator>
 61inline void make_multi_point(MultiPoint& mp, Generator& generator, int pcount)
 62{
 63    typedef typename bg::point_type<MultiPoint>::type point_type;
 64    typedef typename bg::coordinate_type<MultiPoint>::type coordinate_type;
 65
 66    for(int i = 0; i < pcount; i++)
 67    {
 68        coordinate_type x, y;
 69        x = generator();
 70        y = generator();
 71
 72        point_type p;
 73        bg::set<0>(p, x);
 74        bg::set<1>(p, y);
 75
 76        mp.push_back(p);
 77    }
 78}
 79
 80template <typename MultiPoint, typename Polygon>
 81bool check_hull(MultiPoint const& mp, Polygon const& poly)
 82{
 83    for(typename boost::range_iterator<MultiPoint const>::type it = boost::begin(mp);
 84        it != boost::end(mp);
 85        ++it)
 86    {
 87        if (! bg::covered_by(*it, poly))
 88        {
 89            return false;
 90        }
 91    }
 92    return true;
 93}
 94
 95
 96template <typename MultiPoint, typename Generator>
 97void test_random_multi_points(MultiPoint& result, int& index,
 98            Generator& generator,
 99            int pcount, settings_type const& settings)
100{
101    typedef typename bg::point_type<MultiPoint>::type point_type;
102
103    MultiPoint mp;
104    bg::model::polygon<point_type> hull;
105
106    make_multi_point(mp, generator, pcount);
107    bg::convex_hull(mp, hull);
108    // Check if each point lies in the hull
109    bool correct = check_hull(mp, hull);
110    if (! correct)
111    {
112        std::cout << "ERROR! " << std::endl
113            << bg::wkt(mp) << std::endl
114            << bg::wkt(hull) << std::endl
115            << std::endl;
116            ;
117    }
118
119    if (settings.svg || ! correct)
120    {
121        std::ostringstream out;
122        out << "random_mp_" << index++ << "_" << pcount << ".svg";
123        create_svg(out.str(), mp, hull);
124    }
125    if (settings.wkt)
126    {
127        std::cout 
128            << "input: " << bg::wkt(mp) << std::endl
129            << "output: " << bg::wkt(hull) << std::endl
130            << std::endl;
131            ;
132    }
133}
134
135
136template <typename T>
137void test_all(int seed, int count, int field_size, int pcount, settings_type const& settings)
138{
139    boost::timer t;
140
141    typedef boost::minstd_rand base_generator_type;
142
143    base_generator_type generator(seed);
144
145    boost::uniform_int<> random_coordinate(0, field_size - 1);
146    boost::variate_generator<base_generator_type&, boost::uniform_int<> >
147        coordinate_generator(generator, random_coordinate);
148
149    typedef bg::model::multi_point
150        <
151            bg::model::d2::point_xy<T>
152        > mp;
153
154    int index = 0;
155    for(int i = 0; i < count; i++)
156    {
157        mp p;
158        test_random_multi_points<mp>(p, index, coordinate_generator, pcount, settings);
159    }
160    std::cout
161        << "points: " << index
162        << " type: " << typeid(T).name()
163        << " time: " << t.elapsed()  << std::endl;
164}
165
166int main(int argc, char** argv)
167{
168    try
169    {
170        namespace po = boost::program_options;
171        po::options_description description("=== random_multi_points ===\nAllowed options");
172
173        std::string type = "double";
174        int count = 1;
175        int seed = static_cast<unsigned int>(std::time(0));
176        int pcount = 3;
177        int field_size = 10;
178        settings_type settings;
179
180        description.add_options()
181            ("help", "Help message")
182            ("seed", po::value<int>(&seed), "Initialization seed for random generator")
183            ("count", po::value<int>(&count)->default_value(1), "Number of tests")
184            ("number", po::value<int>(&pcount)->default_value(30), "Number of points")
185            ("size", po::value<int>(&field_size)->default_value(10), "Size of the field")
186            ("type", po::value<std::string>(&type)->default_value("double"), "Type (int,float,double)")
187            ("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests")
188            ("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests")
189        ;
190
191        po::variables_map varmap;
192        po::store(po::parse_command_line(argc, argv, description), varmap);
193        po::notify(varmap);
194
195        if (varmap.count("help"))
196        {
197            std::cout << description << std::endl;
198            return 1;
199        }
200
201        if (type == "float")
202        {
203            test_all<float>(seed, count, field_size, pcount, settings);
204        }
205        else if (type == "double")
206        {
207            test_all<double>(seed, count, field_size, pcount, settings);
208        }
209        else if (type == "int")
210        {
211            test_all<int>(seed, count, field_size, pcount, settings);
212        }
213
214    }
215    catch(std::exception const& e)
216    {
217        std::cout << "Exception " << e.what() << std::endl;
218    }
219    catch(...)
220    {
221        std::cout << "Other exception" << std::endl;
222    }
223
224    return 0;
225}