From 7b807c7b4c101af89e8a12eea6ca307a475fd98f Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 29 Apr 2015 17:06:42 +0300 Subject: [PATCH] [algorithms][envelope][spherical] move existing implementation for envelope(linestring, mbr) to separate file and add implementation for envelope(linestring, mbr) for the spherical equatorial coordinate system --- .../algorithms/detail/envelope/linestring.hpp | 221 ++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 include/boost/geometry/algorithms/detail/envelope/linestring.hpp diff --git a/include/boost/geometry/algorithms/detail/envelope/linestring.hpp b/include/boost/geometry/algorithms/detail/envelope/linestring.hpp new file mode 100644 index 000000000..49e2351d4 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/envelope/linestring.hpp @@ -0,0 +1,221 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// 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) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINESTRING_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINESTRING_HPP + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +struct envelope_linear_on_spheroid +{ + template + static inline OutputIterator push_interval(Longitude const& lon1, + Longitude const& lon2, + OutputIterator oit) + { + typedef longitude_interval interval_type; + + typedef math::detail::constants_on_spheroid + < + Longitude, radian + > constants; + + BOOST_ASSERT(! math::larger(lon1, lon2)); + BOOST_ASSERT(! math::larger(lon1, constants::max_longitude())); + + if (math::larger(lon2, constants::max_longitude())) + { + *oit++ = interval_type(lon1, constants::max_longitude()); + *oit++ = interval_type(constants::min_longitude(), + lon2 - constants::period()); + } + else + { + *oit++ = interval_type(lon1, lon2); + } + return oit; + } + + template + static inline void apply(Linear const& linear, Box& mbr) + { + typedef typename coordinate_type::type box_coordinate_type; + typedef typename fp_coordinate_type::type calculation_type; + + typedef typename geometry::segment_iterator + < + Linear const + > iterator_type; + + typedef typename coordinate_system + < + Linear + >::type::units linear_units_type; + + BOOST_ASSERT(geometry::num_points(linear) != 0); + + typedef longitude_interval interval_type; + + calculation_type const pi = math::pi(); + + std::vector longitude_intervals; + std::back_insert_iterator + < + std::vector + > oit(longitude_intervals); + + calculation_type lat_min = 0, lat_max = 0; + bool first = true; + for (iterator_type seg_it = geometry::segments_begin(linear); + seg_it != geometry::segments_end(linear); + ++seg_it, first = false) + { + typename point_type::type p[2]; + detail::assign_point_from_index<0>(*seg_it, p[0]); + detail::assign_point_from_index<1>(*seg_it, p[1]); + + calculation_type lon1 = geometry::get<0>(p[0]); + calculation_type lat1 = geometry::get<1>(p[0]); + calculation_type lon2 = geometry::get<0>(p[1]); + calculation_type lat2 = geometry::get<1>(p[1]); + + math::normalize_spheroidal_coordinates + < + linear_units_type + >(lon1, lat1); + + math::normalize_spheroidal_coordinates + < + linear_units_type + >(lon2, lat2); + + math::convert_coordinates(lon1, lat1); + math::convert_coordinates(lon2, lat2); + + compute_mbr_of_segment::apply(lon1, lat1, lon2, lat2); + oit = push_interval(lon1, lon2, oit); + + if (first) + { + lat_min = lat1; + lat_max = lat2; + } + + // update min and max latitude, if needed + if (math::smaller(lat1, lat_min)) + { + lat_min = lat1; + } + + if (math::larger(lat2, lat_max)) + { + lat_max = lat2; + } + } + + calculation_type lon_min = 0, lon_max = 0; + envelope_range_of_longitudes + < + radian + >::apply(longitude_intervals, lon_min, lon_max); + + math::convert_coordinates + < + radian, typename coordinate_system::type::units + >(lon_min, lat_min); + + math::convert_coordinates + < + radian, typename coordinate_system::type::units + >(lon_max, lat_max); + + assign_values(mbr, + boost::numeric_cast(lon_min), + boost::numeric_cast(lat_min), + boost::numeric_cast(lon_max), + boost::numeric_cast(lat_max)); + } +}; + + +template +struct envelope_linestring + : envelope_range<> +{}; + +template <> +struct envelope_linestring + : envelope_linear_on_spheroid +{}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct envelope + : detail::envelope::envelope_linestring::type> +{}; + +} // namespace dispatch +#endif + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINESTRING_HPP