// Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test // 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. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // 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 #include #include #include #include #include #include //#include template void add_to_ring(PRJ const& prj, LL const& ll, bg::model::ring& ring_ll, bg::model::ring& ring_xy) { ring_ll.push_back(ll); XY xy; prj.forward(ll, xy); ring_xy.push_back(xy); } template void test_area_polygon_ll(bool concave, bool hole, double perc) { BOOST_ASSERT(! (concave && hole) ); typedef typename bg::coordinate_type::type T; // Amsterdam, Rotterdam, The Hague, Utrecht, // these cities together are the city group "Randstad" LL a, r, h, u; // Amsterdam 52 22'23"N 4 53'32"E a.lat(bg::dms(52, 22, 23)); a.lon(bg::dms(4, 53, 32)); // Rotterdam 51 55'51"N 4 28'45"E r.lat(bg::dms(51, 55, 51)); r.lon(bg::dms(4, 28, 45)); // The hague: 52 4' 48" N, 4 18' 0" E h.lat(bg::dms(52, 4, 48)); h.lon(bg::dms(4, 18, 0)); // Utrecht u.lat(bg::dms(52, 5, 36)); u.lon(bg::dms(5, 7, 10)); // For checking calculated area, use the Dutch projection (RD), this is EPSG code 28992 bg::projections::sterea_ellipsoid dutch_prj(bg::projections::init(28992)); // Add them in clockwise direction bg::model::polygon randstad; bg::model::polygon randstad_xy; add_to_ring(dutch_prj, a, randstad.outer(), randstad_xy.outer()); add_to_ring(dutch_prj, u, randstad.outer(), randstad_xy.outer()); // Concave case if (concave) { // Add the city "Alphen" to create a concave case // Alphen 52 7' 48" N, 4 39' 0" E LL alphen( bg::latitude(bg::dms(52, 7, 48)), bg::longitude(bg::dms(4, 39))); add_to_ring(dutch_prj, alphen, randstad.outer(), randstad_xy.outer()); } add_to_ring(dutch_prj, r, randstad.outer(), randstad_xy.outer()); add_to_ring(dutch_prj, h, randstad.outer(), randstad_xy.outer()); add_to_ring(dutch_prj, a, randstad.outer(), randstad_xy.outer()); // Hole case if (hole) { // Gouda 52 1' 12" N, 4 42' 0" E LL gouda( bg::latitude(bg::dms(52, 1, 12)), bg::longitude(bg::dms(4, 42))); // Woerden 52 5' 9" N, 4 53' 0" E LL woerden( bg::latitude(bg::dms(52, 5, 9)), bg::longitude(bg::dms(4, 53, 0))); // Uithoorn 52 13' 48" N, 4 49' 48" E LL uithoorn(bg::latitude (bg::dms(52, 13, 48)), bg::longitude(bg::dms(4, 49, 48))); // Alphen 52 7' 48" N, 4 39' 0" E LL alphen(bg::latitude( bg::dms(52, 7, 48)), bg::longitude(bg::dms(4, 39))); randstad.inners().resize(1); randstad_xy.inners().resize(1); typename bg::model::polygon::ring_type& ring = randstad.inners()[0]; typename bg::model::polygon::ring_type& ring_xy = randstad_xy.inners()[0]; // Add them in counter-clockwise direction (see map of the Netherlands) add_to_ring(dutch_prj, gouda, ring, ring_xy); add_to_ring(dutch_prj, woerden, ring, ring_xy); add_to_ring(dutch_prj, uithoorn, ring, ring_xy); add_to_ring(dutch_prj, alphen, ring, ring_xy); add_to_ring(dutch_prj, gouda, ring, ring_xy); } // Check the area in square KM static const double KM2 = 1.0e6; double d_ll = bg::area(randstad) / KM2; double d_xy = bg::area(randstad_xy) / KM2; BOOST_CHECK_CLOSE(d_ll, d_xy, 1.0); if (hole) { BOOST_CHECK_CLOSE(d_ll, 1148.210, perc); BOOST_CHECK_CLOSE(d_xy, 1151.573, perc); } else { BOOST_CHECK_CLOSE(d_ll, concave ? 977.786 : 1356.168, perc); BOOST_CHECK_CLOSE(d_xy, concave ? 980.658 : 1360.140, perc); // No hole: area of outer should be equal to area of ring double r_ll = bg::area(randstad.outer()) / KM2; double r_xy = bg::area(randstad_xy.outer()) / KM2; BOOST_CHECK_CLOSE(d_ll, r_ll, perc); BOOST_CHECK_CLOSE(d_xy, r_xy, perc); } // Calculate are using specified strategy, here with radius in KM // We then don't have to divide by KM*KM to get the same result bg::strategy::area::huiller strategy(6372.8); d_ll = bg::area(randstad, strategy); BOOST_CHECK_CLOSE(d_ll, d_xy, 1.0); } template void test_latlong(double perc) { test_area_polygon_ll, bg::model::ll::point >(false, false, perc); // with concavities test_area_polygon_ll, bg::model::ll::point >(true, false, perc); // with holes test_area_polygon_ll, bg::model::ll::point >(false, true, perc); } int test_main(int, char* []) { test_latlong(0.01); //test_latlong(0.3); // LL area calculations using projections differ return 0; }