diff --git a/test/algorithms/Jamfile.v2 b/test/algorithms/Jamfile.v2 index 2806c1a10..1e1f77918 100644 --- a/test/algorithms/Jamfile.v2 +++ b/test/algorithms/Jamfile.v2 @@ -22,6 +22,7 @@ test-suite boost-geometry-algorithms [ run centroid.cpp : : : : algorithms_centroid ] [ run centroid_multi.cpp : : : : algorithms_centroid_multi ] [ run comparable_distance.cpp : : : : algorithms_comparable_distance ] + [ run complexify.cpp : : : : algorithms_complexify ] [ run convert.cpp : : : : algorithms_convert ] [ run convert_multi.cpp : : : : algorithms_convert_multi ] [ run convex_hull.cpp : : : : algorithms_convex_hull ] diff --git a/test/algorithms/complexify.cpp b/test/algorithms/complexify.cpp new file mode 100644 index 000000000..6f3e1f805 --- /dev/null +++ b/test/algorithms/complexify.cpp @@ -0,0 +1,198 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2017, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include + + +struct check_lengths +{ + template + void operator()(G const& g, G const& o, S const& s) const + { + double d1 = bg::length(g, s); + double d2 = bg::length(o, s); + + BOOST_CHECK_CLOSE(d1, d2, 0.0001); + } +}; + +struct check_perimeters +{ + template + void operator()(G const& g, G const& o, S const& s) const + { + double d1 = bg::perimeter(g, s); + double d2 = bg::perimeter(o, s); + + BOOST_CHECK_CLOSE(d1, d2, 0.0001); + } +}; + +template +double inline shortest_length(G const& g, DistS const& dist_s) +{ + double min_len = (std::numeric_limits::max)(); + for (bg::segment_iterator it = bg::segments_begin(g); + it != bg::segments_end(g); ++it) + { + double len = bg::length(*it, dist_s); + min_len = (std::min)(min_len, len); + } + return min_len; +} + +template +double inline greatest_length(G const& o, DistS const& dist_s) +{ + double max_len = 0.0; + for (bg::segment_iterator it = bg::segments_begin(o); + it != bg::segments_end(o); ++it) + { + double len = bg::length(*it, dist_s); + max_len = (std::max)(max_len, len); + } + return max_len; +} + +template ::type> +struct cs_data +{}; + +template +struct cs_data +{ + bg::strategy::complexify::cartesian<> compl_s; + bg::strategy::distance::pythagoras<> dist_s; +}; + +template +struct cs_data +{ + cs_data() + : model(6378137.0) + , compl_s(model) + , dist_s(6378137.0) + {} + + bg::srs::sphere model; + bg::strategy::complexify::spherical<> compl_s; + bg::strategy::distance::haversine dist_s; +}; + +template +struct cs_data +{ + cs_data() + : model(6378137.0, 6356752.3142451793) + , compl_s(model) + , dist_s(model) + {} + + bg::srs::spheroid model; + bg::strategy::complexify::geographic<> compl_s; + bg::strategy::distance::geographic<> dist_s; +}; + +template +inline void test_geometry(std::string const& wkt, Check const& check) +{ + cs_data d; + + G g; + bg::read_wkt(wkt, g); + + double max_distance = shortest_length(g, d.dist_s) / 3.0; + + G o; + bg::complexify(g, o, max_distance, d.compl_s); + + // geometry was indeed complexified + std::size_t g_count = bg::num_points(g); + std::size_t o_count = bg::num_points(o); + BOOST_CHECK(g_count < o_count); + + // all segments have lengths smaller or equal to max_distance + double gr_len = greatest_length(o, d.dist_s); + // NOTE: Currently geographic strategies can generate segments that have + // lengths slightly greater than max_distance. In order to change + // this the generation of new points should e.g. be recursive with + // stop condition comparing the current distance calculated by + // inverse strategy. + // NOTE: Closeness value tweaked for Andoyer + bool is_close = (gr_len - max_distance) / (std::max)(gr_len, max_distance) < 0.0001; + BOOST_CHECK(gr_len <= max_distance || is_close); + + // the overall length or perimeter didn't change + check(g, o, d.dist_s); +} + +template +inline void test_linear(std::string const& wkt) +{ + test_geometry(wkt, check_lengths()); +} + +template +inline void test_areal(std::string const& wkt) +{ + test_geometry(wkt, check_perimeters()); +} + +template +void test_all() +{ + typedef bg::model::linestring

ls_t; + typedef bg::model::multi_linestring mls_t; + + typedef bg::model::ring

ring_t; + typedef bg::model::polygon

poly_t; + typedef bg::model::multi_polygon mpoly_t; + + test_linear("LINESTRING(4 -4, 4 -1)"); + test_linear("LINESTRING(4 4, 4 1)"); + test_linear("LINESTRING(0 0, 180 0)"); + test_linear("LINESTRING(1 1, -179 -1)"); + + test_linear("LINESTRING(1 1, 2 2, 4 2)"); + test_linear("MULTILINESTRING((1 1, 2 2),(2 2, 4 2))"); + + test_linear("POLYGON((1 1, 1 2, 2 2, 1 1))"); + test_linear("POLYGON((1 1, 1 4, 4 4, 4 1, 1 1),(1 1, 2 2, 2 3, 1 1))"); + test_linear("MULTIPOLYGON(((1 1, 1 4, 4 4, 4 1, 1 1),(1 1, 2 2, 2 3, 1 1)),((4 4, 5 5, 5 4, 4 4)))"); +} + +int test_main(int, char* []) +{ + test_all< bg::model::point >(); + test_all< bg::model::point > >(); + test_all< bg::model::point > >(); + + return 0; +}