/usr/include/boost/geometry/strategies/spherical
Edit: /usr/include/boost/geometry/strategies/spherical/envelope_multipoint.hpp (13234B)
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Distributed under 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_STRATEGIES_SPHERICAL_ENVELOPE_MULTIPOINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_MULTIPOINT_HPP
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
class spherical_multipoint
{
private:
template
struct coordinate_less
{
template
inline bool operator()(Point const& point1, Point const& point2) const
{
return math::smaller(geometry::get(point1),
geometry::get(point2));
}
};
template
static inline void analyze_point_coordinates(MultiPoint const& multipoint,
bool& has_south_pole,
bool& has_north_pole,
OutputIterator oit)
{
typedef typename boost::range_value::type point_type;
typedef typename boost::range_iterator
<
MultiPoint const
>::type iterator_type;
// analyze point coordinates:
// (1) normalize point coordinates
// (2) check if any point is the north or the south pole
// (3) put all non-pole points in a container
//
// notice that at this point in the algorithm, we have at
// least two points on the spheroid
has_south_pole = false;
has_north_pole = false;
for (iterator_type it = boost::begin(multipoint);
it != boost::end(multipoint);
++it)
{
point_type point;
normalize::spherical_point::apply(*it, point);
if (math::equals(geometry::get<1>(point),
Constants::min_latitude()))
{
has_south_pole = true;
}
else if (math::equals(geometry::get<1>(point),
Constants::max_latitude()))
{
has_north_pole = true;
}
else
{
*oit++ = point;
}
}
}
template
static inline Value maximum_gap(SortedRange const& sorted_range,
Value& max_gap_left,
Value& max_gap_right)
{
typedef typename boost::range_iterator
<
SortedRange const
>::type iterator_type;
iterator_type it1 = boost::begin(sorted_range), it2 = it1;
++it2;
max_gap_left = geometry::get<0>(*it1);
max_gap_right = geometry::get<0>(*it2);
Value max_gap = max_gap_right - max_gap_left;
for (++it1, ++it2; it2 != boost::end(sorted_range); ++it1, ++it2)
{
Value gap = geometry::get<0>(*it2) - geometry::get<0>(*it1);
if (math::larger(gap, max_gap))
{
max_gap_left = geometry::get<0>(*it1);
max_gap_right = geometry::get<0>(*it2);
max_gap = gap;
}
}
return max_gap;
}
template
<
typename Constants,
typename PointRange,
typename LongitudeLess,
typename CoordinateType
>
static inline void get_min_max_longitudes(PointRange& range,
LongitudeLess const& lon_less,
CoordinateType& lon_min,
CoordinateType& lon_max)
{
typedef typename boost::range_iterator
<
PointRange const
>::type iterator_type;
// compute min and max longitude values
std::pair min_max_longitudes
= boost::minmax_element(boost::begin(range),
boost::end(range),
lon_less);
lon_min = geometry::get<0>(*min_max_longitudes.first);
lon_max = geometry::get<0>(*min_max_longitudes.second);
// if the longitude span is "large" compute the true maximum gap
if (math::larger(lon_max - lon_min, Constants::half_period()))
{
std::sort(boost::begin(range), boost::end(range), lon_less);
CoordinateType max_gap_left = 0, max_gap_right = 0;
CoordinateType max_gap
= maximum_gap(range, max_gap_left, max_gap_right);
CoordinateType complement_gap
= Constants::period() + lon_min - lon_max;
if (math::larger(max_gap, complement_gap))
{
lon_min = max_gap_right;
lon_max = max_gap_left + Constants::period();
}
}
}
template
<
typename Constants,
typename Iterator,
typename LatitudeLess,
typename CoordinateType
>
static inline void get_min_max_latitudes(Iterator const first,
Iterator const last,
LatitudeLess const& lat_less,
bool has_south_pole,
bool has_north_pole,
CoordinateType& lat_min,
CoordinateType& lat_max)
{
if (has_south_pole && has_north_pole)
{
lat_min = Constants::min_latitude();
lat_max = Constants::max_latitude();
}
else if (has_south_pole)
{
lat_min = Constants::min_latitude();
lat_max
= geometry::get<1>(*std::max_element(first, last, lat_less));
}
else if (has_north_pole)
{
lat_min
= geometry::get<1>(*std::min_element(first, last, lat_less));
lat_max = Constants::max_latitude();
}
else
{
std::pair min_max_latitudes
= boost::minmax_element(first, last, lat_less);
lat_min = geometry::get<1>(*min_max_latitudes.first);
lat_max = geometry::get<1>(*min_max_latitudes.second);
}
}
public:
template
static inline void apply(MultiPoint const& multipoint, Box& mbr)
{
typedef typename point_type::type point_type;
typedef typename coordinate_type::type coordinate_type;
typedef typename boost::range_iterator
<
MultiPoint const
>::type iterator_type;
typedef math::detail::constants_on_spheroid
<
coordinate_type,
typename geometry::detail::cs_angular_units::type
> constants;
if (boost::empty(multipoint))
{
geometry::detail::envelope::initialize::value>::apply(mbr);
return;
}
geometry::detail::envelope::initialize::apply(mbr);
if (boost::size(multipoint) == 1)
{
return dispatch::envelope
<
typename boost::range_value::type
>::apply(range::front(multipoint), mbr, strategy::envelope::spherical_point());
}
// analyze the points and put the non-pole ones in the
// points vector
std::vector points;
bool has_north_pole = false, has_south_pole = false;
analyze_point_coordinates(multipoint,
has_south_pole, has_north_pole,
std::back_inserter(points));
coordinate_type lon_min, lat_min, lon_max, lat_max;
if (points.size() == 1)
{
// we have one non-pole point and at least one pole point
lon_min = geometry::get<0>(range::front(points));
lon_max = geometry::get<0>(range::front(points));
lat_min = has_south_pole
? constants::min_latitude()
: constants::max_latitude();
lat_max = has_north_pole
? constants::max_latitude()
: constants::min_latitude();
}
else if (points.empty())
{
// all points are pole points
BOOST_GEOMETRY_ASSERT(has_south_pole || has_north_pole);
lon_min = coordinate_type(0);
lon_max = coordinate_type(0);
lat_min = has_south_pole
? constants::min_latitude()
: constants::max_latitude();
lat_max = (has_north_pole)
? constants::max_latitude()
: constants::min_latitude();
}
else
{
get_min_max_longitudes(points,
coordinate_less<0>(),
lon_min,
lon_max);
get_min_max_latitudes(points.begin(),
points.end(),
coordinate_less<1>(),
has_south_pole,
has_north_pole,
lat_min,
lat_max);
}
typedef typename helper_geometry
<
Box,
coordinate_type,
typename geometry::detail::cs_angular_units::type
>::type helper_box_type;
helper_box_type helper_mbr;
geometry::set(helper_mbr, lon_min);
geometry::set(helper_mbr, lat_min);
geometry::set(helper_mbr, lon_max);
geometry::set(helper_mbr, lat_max);
// now transform to output MBR (per index)
geometry::detail::envelope::envelope_indexed_box_on_spheroid::apply(helper_mbr, mbr);
geometry::detail::envelope::envelope_indexed_box_on_spheroid::apply(helper_mbr, mbr);
// compute envelope for higher coordinates
iterator_type it = boost::begin(multipoint);
geometry::detail::envelope::envelope_one_point<2, dimension::value>::apply(*it, mbr);
for (++it; it != boost::end(multipoint); ++it)
{
strategy::expand::detail::point_loop
<
2, dimension::value
>::apply(mbr, *it);
}
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template
struct default_strategy
{
typedef strategy::envelope::spherical_multipoint type;
};
template
struct default_strategy
{
typedef strategy::envelope::spherical_multipoint type;
};
template
struct default_strategy
{
typedef strategy::envelope::spherical_multipoint type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_MULTIPOINT_HPP