Merge branch 'develop' of https://github.com/boostorg/geometry into develop

This commit is contained in:
Barend Gehrels
2015-07-15 11:59:16 +02:00
35 changed files with 2331 additions and 1003 deletions

View File

@@ -979,8 +979,7 @@ struct buffered_piece_collection
return;
}
geometry::detail::envelope::envelope_range<>::apply(pc.robust_ring,
pc.robust_envelope);
geometry::envelope(pc.robust_ring, pc.robust_envelope);
geometry::assign_inverse(pc.robust_offsetted_envelope);
for (signed_size_type i = 0; i < pc.offsetted_count; i++)

View File

@@ -9,25 +9,25 @@
// 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
// 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_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
#include <cstddef>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/transform.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
@@ -40,37 +40,97 @@ namespace detail { namespace envelope
{
struct envelope_box_on_spheroid
template
<
std::size_t Index,
std::size_t Dimension,
std::size_t DimensionCount
>
struct envelope_indexed_box
{
template<typename BoxIn, typename BoxOut>
template <typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
BoxIn box_in_normalized = detail::return_normalized<BoxIn>(box_in);
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
geometry::transform(box_in_normalized, mbr);
detail::conversion::point_to_point
<
detail::indexed_point_view<BoxIn const, Index>,
detail::indexed_point_view<BoxOut, Index>,
Dimension,
DimensionCount
>::apply(box_in_corner, mbr_corner);
}
};
template
<
std::size_t Index,
std::size_t DimensionCount
>
struct envelope_indexed_box_on_spheroid
{
template <typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
// transform() does not work with boxes of dimension higher
// than 2; to account for such boxes we transform the min/max
// points of the boxes using the indexed_point_view
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
// first transform the units
transform_units(box_in_corner, mbr_corner);
// now transform the remaining coordinates
detail::conversion::point_to_point
<
detail::indexed_point_view<BoxIn const, Index>,
detail::indexed_point_view<BoxOut, Index>,
2,
DimensionCount
>::apply(box_in_corner, mbr_corner);
}
};
template <typename CSTag>
struct envelope_box
{
template<typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
geometry::convert(box_in, mbr);
envelope_indexed_box
<
min_corner, 0, dimension<BoxIn>::value
>::apply(box_in, mbr);
envelope_indexed_box
<
max_corner, 0, dimension<BoxIn>::value
>::apply(box_in, mbr);
}
};
template <>
struct envelope_box<spherical_equatorial_tag>
: envelope_box_on_spheroid
{};
template <>
struct envelope_box<geographic_tag>
: envelope_box_on_spheroid
{};
struct envelope_box_on_spheroid
{
template <typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
BoxIn box_in_normalized = detail::return_normalized<BoxIn>(box_in);
envelope_indexed_box_on_spheroid
<
min_corner, dimension<BoxIn>::value
>::apply(box_in_normalized, mbr);
envelope_indexed_box_on_spheroid
<
max_corner, dimension<BoxIn>::value
>::apply(box_in_normalized, mbr);
}
};
}} // namespace detail::envelope
@@ -81,14 +141,26 @@ namespace dispatch
{
template <typename Box, typename CS_Tag>
struct envelope<Box, box_tag, CS_Tag>
: detail::envelope::envelope_box
{};
template <typename Box>
struct envelope<Box, box_tag>
: detail::envelope::envelope_box<typename cs_tag<Box>::type>
struct envelope<Box, box_tag, spherical_equatorial_tag>
: detail::envelope::envelope_box_on_spheroid
{};
template <typename Box>
struct envelope<Box, box_tag, geographic_tag>
: detail::envelope::envelope_box_on_spheroid
{};
} // namespace dispatch
#endif
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry

View File

@@ -12,21 +12,21 @@
// 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
// 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_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/linestring.hpp>
#include <boost/geometry/algorithms/detail/envelope/multilinestring.hpp>
#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp>
#include <boost/geometry/algorithms/detail/envelope/point.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
@@ -43,27 +43,28 @@ namespace detail { namespace envelope
{
struct exterior_ring_expand_policy
{
template <typename Box, typename Geometry>
static inline void apply(Box& mbr, Geometry const& geometry)
{
Box ring_mbr;
envelope_range<>::apply(exterior_ring(geometry), ring_mbr);
geometry::expand(mbr, ring_mbr);
}
};
struct envelope_polygon
{
template <typename Polygon, typename Box>
static inline void apply(Polygon const& poly, Box& mbr)
static inline void apply(Polygon const& polygon, Box& mbr)
{
// For polygon, inspecting outer ring is sufficient
envelope_range<>::apply(exterior_ring(poly), mbr);
}
typename ring_return_type<Polygon const>::type ext_ring
= exterior_ring(polygon);
if (geometry::is_empty(ext_ring))
{
// if the exterior ring is empty, consider the interior rings
envelope_multi_range
<
envelope_range
>::apply(interior_rings(polygon), mbr);
}
else
{
// otherwise, consider only the exterior ring
envelope_range::apply(ext_ring, mbr);
}
}
};
@@ -77,7 +78,7 @@ namespace dispatch
template <typename Ring>
struct envelope<Ring, ring_tag>
: detail::envelope::envelope_range<>
: detail::envelope::envelope_range
{};
@@ -89,15 +90,16 @@ struct envelope<Polygon, polygon_tag>
template <typename MultiPolygon>
struct envelope<MultiPolygon, multi_polygon_tag>
: detail::envelope::envelope_range
: detail::envelope::envelope_multi_range
<
detail::envelope::exterior_ring_expand_policy
detail::envelope::envelope_polygon
>
{};
} // namespace dispatch
#endif
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry

View File

@@ -0,0 +1,86 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, 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_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP
#include <cstddef>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct initialize_loop
{
template <typename Box, typename CoordinateType>
static inline void apply(Box& box,
CoordinateType min_value,
CoordinateType max_value)
{
geometry::set<min_corner, Dimension>(box, min_value);
geometry::set<max_corner, Dimension>(box, max_value);
initialize_loop
<
Dimension + 1, DimensionCount
>::apply(box, min_value, max_value);
}
};
template <std::size_t DimensionCount>
struct initialize_loop<DimensionCount, DimensionCount>
{
template <typename Box, typename CoordinateType>
static inline void apply(Box&, CoordinateType, CoordinateType)
{
}
};
template
<
typename Box,
std::size_t Dimension = 0,
std::size_t DimensionCount = dimension<Box>::value
>
struct initialize
{
typedef typename coordinate_type<Box>::type coordinate_type;
static inline void apply(Box& box,
coordinate_type min_value
= boost::numeric::bounds<coordinate_type>::highest(),
coordinate_type max_value
= boost::numeric::bounds<coordinate_type>::lowest())
{
initialize_loop
<
Dimension, DimensionCount
>::apply(box, min_value, max_value);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP

View File

@@ -12,8 +12,8 @@
// 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
// 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_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP

View File

@@ -4,8 +4,9 @@
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
// 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_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP

View File

@@ -0,0 +1,96 @@
// 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
// 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_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
struct envelope_linestring_on_spheroid
{
template <typename Linestring, typename Box>
static inline void apply(Linestring const& linestring, Box& mbr)
{
envelope_range::apply(geometry::segments_begin(linestring),
geometry::segments_end(linestring),
mbr);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linestring, typename CS_Tag>
struct envelope<Linestring, linestring_tag, CS_Tag>
: detail::envelope::envelope_range
{};
template <typename Linestring>
struct envelope<Linestring, linestring_tag, spherical_equatorial_tag>
: detail::envelope::envelope_linestring_on_spheroid
{};
template <typename MultiLinestring, typename CS_Tag>
struct envelope
<
MultiLinestring, multi_linestring_tag, CS_Tag
> : detail::envelope::envelope_multi_range
<
detail::envelope::envelope_range
>
{};
template <typename MultiLinestring>
struct envelope
<
MultiLinestring, multi_linestring_tag, spherical_equatorial_tag
> : detail::envelope::envelope_multi_range_on_spheroid
<
detail::envelope::envelope_linestring_on_spheroid
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP

View File

@@ -1,182 +0,0 @@
// 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 <iterator>
#include <vector>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
struct envelope_linear_on_spheroid
{
template <typename Units, typename Longitude, typename OutputIterator>
static inline OutputIterator push_interval(Longitude const& lon1,
Longitude const& lon2,
OutputIterator oit)
{
typedef longitude_interval<Longitude> interval_type;
typedef math::detail::constants_on_spheroid
<
Longitude, Units
> constants;
BOOST_GEOMETRY_ASSERT(! math::larger(lon1, lon2));
BOOST_GEOMETRY_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 <typename Linear, typename Box>
static inline void apply(Linear const& linear, Box& mbr)
{
typedef typename coordinate_type<Box>::type box_coordinate_type;
typedef longitude_interval<box_coordinate_type> interval_type;
typedef typename geometry::segment_iterator
<
Linear const
> iterator_type;
BOOST_GEOMETRY_ASSERT(! geometry::is_empty(linear));
std::vector<interval_type> longitude_intervals;
std::back_insert_iterator
<
std::vector<interval_type>
> oit(longitude_intervals);
box_coordinate_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)
{
Box segment_mbr;
dispatch::envelope
<
typename std::iterator_traits<iterator_type>::value_type
>::apply(*seg_it, segment_mbr);
oit = push_interval
<
typename coordinate_system<Box>::type::units
>(geometry::get<min_corner, 0>(segment_mbr),
geometry::get<max_corner, 0>(segment_mbr),
oit);
if (first)
{
lat_min = geometry::get<min_corner, 1>(segment_mbr);
lat_max = geometry::get<max_corner, 1>(segment_mbr);
}
// update min and max latitude, if needed
if (math::smaller(geometry::get<min_corner, 1>(segment_mbr),
lat_min))
{
lat_min = geometry::get<min_corner, 1>(segment_mbr);
}
if (math::larger(geometry::get<max_corner, 1>(segment_mbr),
lat_max))
{
lat_max = geometry::get<max_corner, 1>(segment_mbr);
}
}
box_coordinate_type lon_min = 0, lon_max = 0;
envelope_range_of_longitudes
<
typename coordinate_system<Box>::type::units
>::apply(longitude_intervals, lon_min, lon_max);
assign_values(mbr, lon_min, lat_min, lon_max, lat_max);
}
};
template <typename CSTag>
struct envelope_linestring
: envelope_range<>
{};
template <>
struct envelope_linestring<spherical_equatorial_tag>
: envelope_linear_on_spheroid
{};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linestring>
struct envelope<Linestring, linestring_tag>
: detail::envelope::envelope_linestring<typename cs_tag<Linestring>::type>
{};
} // namespace dispatch
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINESTRING_HPP

View File

@@ -1,86 +0,0 @@
// 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_MULTILINESTRING_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTILINESTRING_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/detail/envelope/linestring.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
struct envelope_range_expand_policy
{
template <typename Box, typename Geometry>
static inline void apply(Box& mbr, Geometry const& geometry)
{
Box mbr2;
envelope_range<>::apply(geometry, mbr2);
geometry::expand(mbr, mbr2);
}
};
template <typename CSTag>
struct envelope_multilinestring
: envelope_range<envelope_range_expand_policy>
{};
template <>
struct envelope_multilinestring<spherical_equatorial_tag>
: envelope_linear_on_spheroid
{};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename MultiLinestring>
struct envelope<MultiLinestring, multi_linestring_tag>
: detail::envelope::envelope_multilinestring
<
typename cs_tag<MultiLinestring>::type
>
{};
} // namespace dispatch
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTILINESTRING_HPP

View File

@@ -4,12 +4,14 @@
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
// 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_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
#include <cstddef>
#include <algorithm>
#include <utility>
#include <vector>
@@ -28,14 +30,13 @@
#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/transform.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
#include <boost/geometry/algorithms/detail/expand/point.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
@@ -50,14 +51,14 @@ namespace detail { namespace envelope
class envelope_multipoint_on_spheroid
{
private:
template <std::size_t Dimension>
template <std::size_t Dim>
struct coordinate_less
{
template <typename Point>
inline bool operator()(Point const& point1, Point const& point2) const
{
return math::smaller(geometry::get<Dimension>(point1),
geometry::get<Dimension>(point2));
return math::smaller(geometry::get<Dim>(point1),
geometry::get<Dim>(point2));
}
};
@@ -230,6 +231,10 @@ public:
{
typedef typename point_type<MultiPoint>::type point_type;
typedef typename coordinate_type<MultiPoint>::type coordinate_type;
typedef typename boost::range_iterator
<
MultiPoint const
>::type iterator_type;
typedef math::detail::constants_on_spheroid
<
@@ -237,12 +242,14 @@ public:
typename coordinate_system<MultiPoint>::type::units
> constants;
if (boost::empty(multipoint))
{
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
return;
}
initialize<Box, 0, 2>::apply(mbr);
if (boost::size(multipoint) == 1)
{
return dispatch::envelope
@@ -302,16 +309,37 @@ public:
lat_max);
}
typename helper_geometry
typedef typename helper_geometry
<
Box,
coordinate_type,
typename coordinate_system<MultiPoint>::type::units
>::type helper_mbr;
>::type helper_box_type;
assign_values(helper_mbr, lon_min, lat_min, lon_max, lat_max);
helper_box_type helper_mbr;
geometry::transform(helper_mbr, mbr);
geometry::set<min_corner, 0>(helper_mbr, lon_min);
geometry::set<min_corner, 1>(helper_mbr, lat_min);
geometry::set<max_corner, 0>(helper_mbr, lon_max);
geometry::set<max_corner, 1>(helper_mbr, lat_max);
// now transform to output MBR (per index)
envelope_indexed_box_on_spheroid<min_corner, 2>::apply(helper_mbr, mbr);
envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr);
// compute envelope for higher coordinates
iterator_type it = boost::begin(multipoint);
envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr);
for (++it; it != boost::end(multipoint); ++it)
{
detail::expand::point_loop
<
strategy::compare::default_strategy,
strategy::compare::default_strategy,
2, dimension<Box>::value
>::apply(mbr, *it);
}
}
};
@@ -319,6 +347,8 @@ public:
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
@@ -326,7 +356,7 @@ namespace dispatch
template <typename MultiPoint, typename CSTag>
struct envelope<MultiPoint, multi_point_tag, CSTag>
: detail::envelope::envelope_range<>
: detail::envelope::envelope_range
{};
template <typename MultiPoint>
@@ -341,7 +371,7 @@ struct envelope<MultiPoint, multi_point_tag, geographic_tag>
} // namespace dispatch
#endif
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry

View File

@@ -9,27 +9,28 @@
// 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
// 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_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/transform.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
@@ -40,6 +41,32 @@ namespace boost { namespace geometry
namespace detail { namespace envelope
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_one_point
{
template <std::size_t Index, typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
detail::indexed_point_view<Box, Index> box_corner(mbr);
detail::conversion::point_to_point
<
Point,
detail::indexed_point_view<Box, Index>,
Dimension,
DimensionCount
>::apply(point, box_corner);
}
template <typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
apply<min_corner>(point, mbr);
apply<max_corner>(point, mbr);
}
};
struct envelope_point_on_spheroid
{
template<typename Point, typename Box>
@@ -49,34 +76,23 @@ struct envelope_point_on_spheroid
typename point_type<Box>::type box_point;
// transform input point to a point of the same type as box's point
geometry::transform(normalized_point, box_point);
// transform units of input point to units of a box point
transform_units(normalized_point, box_point);
geometry::convert(box_point, mbr);
geometry::set<min_corner, 0>(mbr, geometry::get<0>(box_point));
geometry::set<min_corner, 1>(mbr, geometry::get<1>(box_point));
geometry::set<max_corner, 0>(mbr, geometry::get<0>(box_point));
geometry::set<max_corner, 1>(mbr, geometry::get<1>(box_point));
envelope_one_point
<
2, dimension<Point>::value
>::apply(normalized_point, mbr);
}
};
template <typename CSTag>
struct envelope_one_point
{
template<typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
geometry::convert(point, mbr);
}
};
template <>
struct envelope_one_point<spherical_equatorial_tag>
: envelope_point_on_spheroid
{};
template <>
struct envelope_one_point<geographic_tag>
: envelope_point_on_spheroid
{};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
@@ -85,14 +101,26 @@ namespace dispatch
{
template <typename Point, typename CS_Tag>
struct envelope<Point, point_tag, CS_Tag>
: detail::envelope::envelope_one_point<0, dimension<Point>::value>
{};
template <typename Point>
struct envelope<Point, point_tag>
: detail::envelope::envelope_one_point<typename cs_tag<Point>::type>
struct envelope<Point, point_tag, spherical_equatorial_tag>
: detail::envelope::envelope_point_on_spheroid
{};
template <typename Point>
struct envelope<Point, point_tag, geographic_tag>
: detail::envelope::envelope_point_on_spheroid
{};
} // namespace dispatch
#endif
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry

View File

@@ -12,17 +12,30 @@
// 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
// 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_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
#include <iterator>
#include <vector>
#include <boost/range.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/detail/expand/box.hpp>
#include <boost/geometry/algorithms/detail/expand/point.hpp>
#include <boost/geometry/algorithms/detail/expand/segment.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
@@ -35,51 +48,124 @@ namespace detail { namespace envelope
{
struct default_expand_policy
// implementation for simple ranges
struct envelope_range
{
template <typename Box, typename Geometry>
static inline void apply(Box& mbr, Geometry const& geometry)
template <typename Iterator, typename Box>
static inline void apply(Iterator first, Iterator last, Box& mbr)
{
geometry::expand(mbr, geometry);
typedef typename std::iterator_traits<Iterator>::value_type value_type;
// initialize MBR
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
Iterator it = first;
if (it != last)
{
// initialize box with first element in range
dispatch::envelope<value_type>::apply(*it, mbr);
// consider now the remaining elements in the range (if any)
for (++it; it != last; ++it)
{
dispatch::expand<Box, value_type>::apply(mbr, *it);
}
}
}
template <typename Range, typename Box>
static inline void apply(Range const& range, Box& mbr)
{
return apply(boost::begin(range), boost::end(range), mbr);
}
};
template <typename ExpandPolicy, typename Iterator, typename Box>
inline void envelope_iterators(Iterator first, Iterator last, Box& mbr)
// implementation for multi-ranges
template <typename EnvelopePolicy>
struct envelope_multi_range
{
for (Iterator it = first; it != last; ++it)
template <typename MultiRange, typename Box>
static inline void apply(MultiRange const& multirange, Box& mbr)
{
ExpandPolicy::apply(mbr, *it);
}
}
typedef typename boost::range_iterator
<
MultiRange const
>::type iterator_type;
template <typename ExpandPolicy = default_expand_policy>
struct envelope_range
{
/// Calculate envelope of range using a strategy
template <typename Range, typename Box>
static inline void apply(Range const& range, Box& mbr)
{
typename boost::range_iterator<Range const>::type it
= boost::begin(range);
if (it != boost::end(range))
bool initialized = false;
for (iterator_type it = boost::begin(multirange);
it != boost::end(multirange);
++it)
{
// initialize box with first element in range
dispatch::envelope
<
typename boost::range_value<Range>::type
>::apply(*it, mbr);
if (! geometry::is_empty(*it))
{
if (initialized)
{
Box helper_mbr;
EnvelopePolicy::apply(*it, helper_mbr);
// consider now the remaining elements in the range (if any)
++it;
envelope_iterators
<
ExpandPolicy
>(it, boost::end(range), mbr);
dispatch::expand<Box, Box>::apply(mbr, helper_mbr);
}
else
{
// compute the initial envelope
EnvelopePolicy::apply(*it, mbr);
initialized = true;
}
}
}
if (! initialized)
{
// if not already initialized, initialize MBR
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
}
}
};
// implementation for multi-range on a spheroid (longitude is periodic)
template <typename EnvelopePolicy>
struct envelope_multi_range_on_spheroid
{
template <typename MultiRange, typename Box>
static inline void apply(MultiRange const& multirange, Box& mbr)
{
typedef typename boost::range_iterator
<
MultiRange const
>::type iterator_type;
// due to the periodicity of longitudes we need to compute the boxes
// of all the single geometries and keep them in a container
std::vector<Box> boxes;
for (iterator_type it = boost::begin(multirange);
it != boost::end(multirange);
++it)
{
if (! geometry::is_empty(*it))
{
Box helper_box;
EnvelopePolicy::apply(*it, helper_box);
boxes.push_back(helper_box);
}
}
// now we need to compute the envelope of the range of boxes
// (cannot be done in an incremental fashion as in the
// Cartesian coordinate system)
// if all single geometries are empty no boxes have been found
// and the MBR is simply initialized
if (! boxes.empty())
{
envelope_range_of_boxes::apply(boxes, mbr);
}
else
{
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
}
}
};

View File

@@ -4,8 +4,9 @@
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
// 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_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP
@@ -23,9 +24,11 @@
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/max_interval_gap.hpp>
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
namespace boost { namespace geometry
@@ -92,8 +95,6 @@ struct envelope_range_of_longitudes
Longitude const zero = 0;
Longitude const period = constants::period();
Longitude const min_longitude = constants::min_longitude();
Longitude const max_longitude = constants::max_longitude();
lon_min = lon_max = zero;
@@ -118,12 +119,17 @@ struct envelope_range_of_longitudes
max_gap_right);
BOOST_GEOMETRY_ASSERT(! math::larger(lon_min, lon_max));
BOOST_GEOMETRY_ASSERT(! math::larger(lon_max, max_longitude));
BOOST_GEOMETRY_ASSERT(! math::smaller(lon_min, min_longitude));
BOOST_GEOMETRY_ASSERT
(! math::larger(lon_max, constants::max_longitude()));
BOOST_GEOMETRY_ASSERT
(! math::smaller(lon_min, constants::min_longitude()));
BOOST_GEOMETRY_ASSERT(! math::larger(max_gap_left, max_gap_right));
BOOST_GEOMETRY_ASSERT(! math::larger(max_gap_right, max_longitude));
BOOST_GEOMETRY_ASSERT(! math::smaller(max_gap_left, min_longitude));
BOOST_GEOMETRY_ASSERT
(! math::larger(max_gap_left, max_gap_right));
BOOST_GEOMETRY_ASSERT
(! math::larger(max_gap_right, constants::max_longitude()));
BOOST_GEOMETRY_ASSERT
(! math::smaller(max_gap_left, constants::min_longitude()));
if (math::larger(max_gap, zero))
{
@@ -140,6 +146,72 @@ struct envelope_range_of_longitudes
};
template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_range_of_boxes_by_expansion
{
template <typename RangeOfBoxes, typename Box>
static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)
{
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
typedef typename boost::range_iterator
<
RangeOfBoxes const
>::type iterator_type;
// first initialize MBR
detail::indexed_point_view<Box, min_corner> mbr_min(mbr);
detail::indexed_point_view<Box, max_corner> mbr_max(mbr);
detail::indexed_point_view<box_type const, min_corner>
first_box_min(range::front(range_of_boxes));
detail::indexed_point_view<box_type const, max_corner>
first_box_max(range::front(range_of_boxes));
detail::conversion::point_to_point
<
detail::indexed_point_view<box_type const, min_corner>,
detail::indexed_point_view<Box, min_corner>,
Dimension,
DimensionCount
>::apply(first_box_min, mbr_min);
detail::conversion::point_to_point
<
detail::indexed_point_view<box_type const, max_corner>,
detail::indexed_point_view<Box, max_corner>,
Dimension,
DimensionCount
>::apply(first_box_max, mbr_max);
// now expand using the remaining boxes
iterator_type it = boost::begin(range_of_boxes);
for (++it; it != boost::end(range_of_boxes); ++it)
{
detail::expand::indexed_loop
<
strategy::compare::default_strategy,
strategy::compare::default_strategy,
min_corner,
Dimension,
DimensionCount
>::apply(mbr, *it);
detail::expand::indexed_loop
<
strategy::compare::default_strategy,
strategy::compare::default_strategy,
max_corner,
Dimension,
DimensionCount
>::apply(mbr, *it);
}
}
};
struct envelope_range_of_boxes
{
template <std::size_t Index>
@@ -217,7 +289,8 @@ struct envelope_range_of_boxes
}
}
coordinate_type lon_min(0), lon_max(0);
coordinate_type lon_min = 0;
coordinate_type lon_max = 0;
envelope_range_of_longitudes
<
units_type
@@ -225,11 +298,22 @@ struct envelope_range_of_boxes
// do not convert units; conversion will be performed at a
// higher level
assign_values(mbr,
lon_min,
geometry::get<min_corner, 1>(*it_min),
lon_max,
geometry::get<max_corner, 1>(*it_max));
// assign now the min/max longitude/latitude values
detail::indexed_point_view<Box, min_corner> mbr_min(mbr);
detail::indexed_point_view<Box, max_corner> mbr_max(mbr);
geometry::set<0>(mbr_min, lon_min);
geometry::set<1>(mbr_min, geometry::get<min_corner, 1>(*it_min));
geometry::set<0>(mbr_max, lon_max);
geometry::set<1>(mbr_max, geometry::get<max_corner, 1>(*it_max));
// what remains to be done is to compute the envelope range
// for the remaining dimensions (if any)
envelope_range_of_boxes_by_expansion
<
2, dimension<Box>::value
>::apply(range_of_boxes, mbr);
}
};

View File

@@ -9,16 +9,14 @@
// 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
// 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_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP
#include <cstddef>
#include <utility>
#include <boost/numeric/conversion/cast.hpp>
@@ -35,15 +33,15 @@
#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/transform.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/point.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/detail/expand/point.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
@@ -55,6 +53,25 @@ namespace boost { namespace geometry
namespace detail { namespace envelope
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_one_segment
{
template<typename Point, typename Box>
static inline void apply(Point const& p1, Point const& p2, Box& mbr)
{
envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr);
detail::expand::point_loop
<
strategy::compare::default_strategy,
strategy::compare::default_strategy,
Dimension,
DimensionCount
>::apply(mbr, p2);
}
};
// Computes the MBR of a segment given by (lon1, lat1) and (lon2,
// lat2), and with azimuths a1 and a2 at the two endpoints of the
// segment.
@@ -255,29 +272,47 @@ public:
{
typedef typename coordinate_type<Box>::type box_coordinate_type;
typename helper_geometry
typedef typename helper_geometry
<
Box, box_coordinate_type, radian
>::type radian_mbr;
>::type helper_box_type;
helper_box_type radian_mbr;
apply(lon1, lat1, lon2, lat2);
assign_values(radian_mbr,
boost::numeric_cast<box_coordinate_type>(lon1),
boost::numeric_cast<box_coordinate_type>(lat1),
boost::numeric_cast<box_coordinate_type>(lon2),
boost::numeric_cast<box_coordinate_type>(lat2));
geometry::set
<
min_corner, 0
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon1));
geometry::transform(radian_mbr, mbr);
geometry::set
<
min_corner, 1
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat1));
geometry::set
<
max_corner, 0
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon2));
geometry::set
<
max_corner, 1
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat2));
transform_units(radian_mbr, mbr);
}
};
struct envelope_segment_on_spheroid
template <std::size_t DimensionCount>
struct envelope_segment_on_sphere
{
template <typename Point, typename Box>
static inline void apply(Point const& p1, Point const& p2, Box& mbr)
{
// first compute the envelope range for the first two coordinates
Point p1_normalized = detail::return_normalized<Point>(p1);
Point p2_normalized = detail::return_normalized<Point>(p2);
@@ -286,25 +321,37 @@ struct envelope_segment_on_spheroid
geometry::get_as_radian<0>(p2_normalized),
geometry::get_as_radian<1>(p2_normalized),
mbr);
}
};
template <typename CSTag>
struct envelope_one_segment
{
template<typename Point, typename Box>
static inline void apply(Point const& p1, Point const& p2, Box& mbr)
// now compute the envelope range for coordinates of
// dimension 2 and higher
envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr);
}
template <typename Segment, typename Box>
static inline void apply(Segment const& segment, Box& mbr)
{
envelope_one_point<CSTag>::apply(p1, mbr);
geometry::expand(mbr, p2);
typename point_type<Segment>::type p[2];
detail::assign_point_from_index<0>(segment, p[0]);
detail::assign_point_from_index<1>(segment, p[1]);
apply(p[0], p[1], mbr);
}
};
template <>
struct envelope_one_segment<spherical_equatorial_tag>
: envelope_segment_on_spheroid
template <std::size_t DimensionCount, typename CS_Tag>
struct envelope_segment
: envelope_one_segment<0, DimensionCount>
{};
template <std::size_t DimensionCount>
struct envelope_segment<DimensionCount, spherical_equatorial_tag>
: envelope_segment_on_sphere<DimensionCount>
{};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
@@ -314,8 +361,8 @@ namespace dispatch
{
template <typename Segment>
struct envelope<Segment, segment_tag>
template <typename Segment, typename CS_Tag>
struct envelope<Segment, segment_tag, CS_Tag>
{
template <typename Box>
static inline void apply(Segment const& segment, Box& mbr)
@@ -323,16 +370,16 @@ struct envelope<Segment, segment_tag>
typename point_type<Segment>::type p[2];
detail::assign_point_from_index<0>(segment, p[0]);
detail::assign_point_from_index<1>(segment, p[1]);
detail::envelope::envelope_one_segment
detail::envelope::envelope_segment
<
typename cs_tag<Segment>::type
dimension<Segment>::value, CS_Tag
>::apply(p[0], p[1], mbr);
}
};
} // namespace dispatch
#endif
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry

View File

@@ -0,0 +1,103 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, 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_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP
#include <cstddef>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/views/detail/two_dimensional_view.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/transform.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template
<
typename GeometryIn,
typename GeometryOut,
typename TagIn = typename tag<GeometryIn>::type,
typename TagOut = typename tag<GeometryOut>::type
>
struct transform_units_impl
: not_implemented<TagIn, TagOut>
{};
template <typename PointIn, typename PointOut>
struct transform_units_impl<PointIn, PointOut, point_tag, point_tag>
{
static inline void apply(PointIn const& point_in, PointOut& point_out)
{
detail::two_dimensional_view<PointIn const> view_in(point_in);
detail::two_dimensional_view<PointOut> view_out(point_out);
geometry::transform(view_in, view_out);
}
};
template <typename BoxIn, typename BoxOut>
struct transform_units_impl<BoxIn, BoxOut, box_tag, box_tag>
{
template <std::size_t Index>
static inline void apply(BoxIn const& box_in, BoxOut& box_out)
{
typedef detail::indexed_point_view<BoxIn const, Index> view_in_type;
typedef detail::indexed_point_view<BoxOut, Index> view_out_type;
view_in_type view_in(box_in);
view_out_type view_out(box_out);
transform_units_impl
<
view_in_type, view_out_type
>::apply(view_in, view_out);
}
static inline void apply(BoxIn const& box_in, BoxOut& box_out)
{
apply<min_corner>(box_in, box_out);
apply<max_corner>(box_in, box_out);
}
};
// Short utility to transform the units of the first two coordinates of
// geometry_in to the units of geometry_out
template <typename GeometryIn, typename GeometryOut>
inline void transform_units(GeometryIn const& geometry_in,
GeometryOut& geometry_out)
{
transform_units_impl
<
GeometryIn, GeometryOut
>::apply(geometry_in, geometry_out);
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost:geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP

View File

@@ -10,24 +10,27 @@
// 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
// 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_ALGORITHMS_DETAIL_EXPAND_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP
#include <cstddef>
#include <algorithm>
#include <boost/geometry/core/access.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
@@ -72,10 +75,19 @@ template
>
struct expand
<
BoxOut, BoxIn, StrategyLess, StrategyGreater,
box_tag, box_tag, CSTagOut, CSTag
> : detail::expand::expand_indexed<StrategyLess, StrategyGreater>
{};
BoxOut, BoxIn,
StrategyLess, StrategyGreater,
box_tag, box_tag,
CSTagOut, CSTag
> : detail::expand::expand_indexed
<
0, dimension<BoxIn>::value, StrategyLess, StrategyGreater
>
{
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
(types<CSTagOut, CSTag>()));
};
template
<
@@ -84,8 +96,10 @@ template
>
struct expand
<
BoxOut, BoxIn, StrategyLess, StrategyGreater,
box_tag, box_tag, spherical_equatorial_tag, spherical_equatorial_tag
BoxOut, BoxIn,
StrategyLess, StrategyGreater,
box_tag, box_tag,
spherical_equatorial_tag, spherical_equatorial_tag
> : detail::expand::box_on_spheroid
{};
@@ -96,8 +110,10 @@ template
>
struct expand
<
BoxOut, BoxIn, StrategyLess, StrategyGreater,
box_tag, box_tag, geographic_tag, geographic_tag
BoxOut, BoxIn,
StrategyLess, StrategyGreater,
box_tag, box_tag,
geographic_tag, geographic_tag
> : detail::expand::box_on_spheroid
{};

View File

@@ -13,8 +13,8 @@
// 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
// 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_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP

View File

@@ -13,8 +13,8 @@
// 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
// 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_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
@@ -23,7 +23,6 @@
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
@@ -113,6 +112,7 @@ struct indexed_loop
// Changes a box such that the other box is also contained by the box
template
<
std::size_t Dimension, std::size_t DimensionCount,
typename StrategyLess, typename StrategyGreater
>
struct expand_indexed
@@ -123,13 +123,13 @@ struct expand_indexed
indexed_loop
<
StrategyLess, StrategyGreater,
0, 0, dimension<Geometry>::type::value
0, Dimension, DimensionCount
>::apply(box, geometry);
indexed_loop
<
StrategyLess, StrategyGreater,
1, 0, dimension<Geometry>::type::value
1, Dimension, DimensionCount
>::apply(box, geometry);
}
};

View File

@@ -13,8 +13,8 @@
// 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
// 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_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP

View File

@@ -13,8 +13,8 @@
// 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
// 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_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
@@ -23,6 +23,9 @@
#include <cstddef>
#include <algorithm>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
@@ -33,14 +36,10 @@
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/transform.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
@@ -53,11 +52,81 @@ namespace detail { namespace expand
{
struct point_on_spheroid
template
<
typename StrategyLess, typename StrategyGreater,
std::size_t Dimension, std::size_t DimensionCount
>
struct point_loop
{
template <typename Box, typename Point>
static inline void apply(Box& box, Point const& source)
{
typedef typename strategy::compare::detail::select_strategy
<
StrategyLess, 1, Point, Dimension
>::type less_type;
typedef typename strategy::compare::detail::select_strategy
<
StrategyGreater, -1, Point, Dimension
>::type greater_type;
typedef typename select_coordinate_type
<
Point, Box
>::type coordinate_type;
less_type less;
greater_type greater;
coordinate_type const coord = get<Dimension>(source);
if (less(coord, get<min_corner, Dimension>(box)))
{
set<min_corner, Dimension>(box, coord);
}
if (greater(coord, get<max_corner, Dimension>(box)))
{
set<max_corner, Dimension>(box, coord);
}
point_loop
<
StrategyLess, StrategyGreater, Dimension + 1, DimensionCount
>::apply(box, source);
}
};
template
<
typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount
>
struct point_loop
<
StrategyLess, StrategyGreater, DimensionCount, DimensionCount
>
{
template <typename Box, typename Point>
static inline void apply(Box&, Point const&) {}
};
// implementation for the spherical equatorial and geographic coordinate systems
template
<
typename StrategyLess,
typename StrategyGreater,
std::size_t DimensionCount
>
struct point_loop_on_spheroid
{
template <typename Box, typename Point>
static inline void apply(Box& box, Point const& point)
{
typedef typename point_type<Box>::type box_point_type;
typedef typename coordinate_type<Box>::type box_coordinate_type;
typedef math::detail::constants_on_spheroid
@@ -70,9 +139,9 @@ struct point_on_spheroid
Point p_normalized = detail::return_normalized<Point>(point);
detail::normalize(box, box);
// transform input point to be the same type as the box point
typename point_type<Box>::type box_point;
geometry::transform(p_normalized, box_point);
// transform input point to be of the same type as the box point
box_point_type box_point;
detail::envelope::transform_units(p_normalized, box_point);
box_coordinate_type p_lon = geometry::get<0>(box_point);
box_coordinate_type p_lat = geometry::get<1>(box_point);
@@ -89,11 +158,8 @@ struct point_on_spheroid
// south pole; the only important coordinate here is the
// pole's latitude, as the longitude can be anything;
// we, thus, take into account the point's latitude only and return
assign_values(box,
b_lon_min,
(std::min)(p_lat, b_lat_min),
b_lon_max,
(std::max)(p_lat, b_lat_max));
geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
return;
}
@@ -104,11 +170,10 @@ struct point_on_spheroid
// the only important coordinate here is the pole's latitude,
// as the longitude can be anything;
// we thus take into account the box's latitude only and return
assign_values(box,
p_lon,
(std::min)(p_lat, b_lat_min),
p_lon,
(std::max)(p_lat, b_lat_max));
geometry::set<min_corner, 0>(box, p_lon);
geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
geometry::set<max_corner, 0>(box, p_lon);
geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
return;
}
@@ -151,71 +216,19 @@ struct point_on_spheroid
}
}
assign_values(box, b_lon_min, b_lat_min, b_lon_max, b_lat_max);
}
};
template
<
typename StrategyLess, typename StrategyGreater,
std::size_t Dimension, std::size_t DimensionCount
>
struct point_loop
{
template <typename Box, typename Point>
static inline void apply(Box& box, Point const& source)
{
typedef typename strategy::compare::detail::select_strategy
<
StrategyLess, 1, Point, Dimension
>::type less_type;
typedef typename strategy::compare::detail::select_strategy
<
StrategyGreater, -1, Point, Dimension
>::type greater_type;
typedef typename select_coordinate_type<Point, Box>::type coordinate_type;
less_type less;
greater_type greater;
coordinate_type const coord = get<Dimension>(source);
if (less(coord, get<min_corner, Dimension>(box)))
{
set<min_corner, Dimension>(box, coord);
}
if (greater(coord, get<max_corner, Dimension>(box)))
{
set<max_corner, Dimension>(box, coord);
}
geometry::set<min_corner, 0>(box, b_lon_min);
geometry::set<min_corner, 1>(box, b_lat_min);
geometry::set<max_corner, 0>(box, b_lon_max);
geometry::set<max_corner, 1>(box, b_lat_max);
point_loop
<
StrategyLess, StrategyGreater,
Dimension + 1, DimensionCount
>::apply(box, source);
StrategyLess, StrategyGreater, 2, DimensionCount
>::apply(box, point);
}
};
template
<
typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount
>
struct point_loop
<
StrategyLess, StrategyGreater, DimensionCount, DimensionCount
>
{
template <typename Box, typename Point>
static inline void apply(Box&, Point const&) {}
};
}} // namespace detail::expand
#endif // DOXYGEN_NO_DETAIL
@@ -223,6 +236,7 @@ struct point_loop
namespace dispatch
{
// Box + point -> new box containing also point
template
<
@@ -232,12 +246,34 @@ template
>
struct expand
<
BoxOut, Point, StrategyLess, StrategyGreater,
box_tag, point_tag, CSTagOut, CSTag
BoxOut, Point,
StrategyLess, StrategyGreater,
box_tag, point_tag,
CSTagOut, CSTag
> : detail::expand::point_loop
<
StrategyLess, StrategyGreater,
0, dimension<Point>::type::value
StrategyLess, StrategyGreater, 0, dimension<Point>::value
>
{
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
(types<CSTagOut, CSTag>()));
};
template
<
typename BoxOut, typename Point,
typename StrategyLess, typename StrategyGreater
>
struct expand
<
BoxOut, Point,
StrategyLess, StrategyGreater,
box_tag, point_tag,
spherical_equatorial_tag, spherical_equatorial_tag
> : detail::expand::point_loop_on_spheroid
<
StrategyLess, StrategyGreater, dimension<Point>::value
>
{};
@@ -248,22 +284,16 @@ template
>
struct expand
<
BoxOut, Point, StrategyLess, StrategyGreater,
box_tag, point_tag, spherical_equatorial_tag, spherical_equatorial_tag
> : detail::expand::point_on_spheroid
BoxOut, Point,
StrategyLess, StrategyGreater,
box_tag, point_tag,
geographic_tag, geographic_tag
> : detail::expand::point_loop_on_spheroid
<
StrategyLess, StrategyGreater, dimension<Point>::value
>
{};
template
<
typename BoxOut, typename Point,
typename StrategyLess, typename StrategyGreater
>
struct expand
<
BoxOut, Point, StrategyLess, StrategyGreater,
box_tag, point_tag, geographic_tag, geographic_tag
> : detail::expand::point_on_spheroid
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

View File

@@ -10,21 +10,25 @@
// 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
// 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_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/algorithms/detail/expand/box.hpp>
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
@@ -36,14 +40,24 @@ namespace detail { namespace expand
{
struct segment_on_spheroid
struct segment_on_sphere
{
template <typename Box, typename Segment>
static inline void apply(Box& box, Segment const& segment)
{
Box segment_envelope;
dispatch::envelope<Segment>::apply(segment, segment_envelope);
box_on_spheroid::apply(box, segment_envelope);
Box mbrs[2];
// compute the envelope of the segment
detail::envelope::envelope_segment_on_sphere
<
dimension<Segment>::value
>::apply(segment, mbrs[0]);
// normalize the box
detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1]);
// compute the envelope of the two boxes
detail::envelope::envelope_range_of_boxes::apply(mbrs, box);
}
};
@@ -64,10 +78,19 @@ template
>
struct expand
<
Box, Segment, StrategyLess, StrategyGreater,
box_tag, segment_tag, CSTagOut, CSTag
> : detail::expand::expand_indexed<StrategyLess, StrategyGreater>
{};
Box, Segment,
StrategyLess, StrategyGreater,
box_tag, segment_tag,
CSTagOut, CSTag
> : detail::expand::expand_indexed
<
0, dimension<Segment>::value, StrategyLess, StrategyGreater
>
{
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
(types<CSTagOut, CSTag>()));
};
template
<
@@ -76,10 +99,11 @@ template
>
struct expand
<
Box, Segment, StrategyLess, StrategyGreater,
Box, Segment,
StrategyLess, StrategyGreater,
box_tag, segment_tag,
spherical_equatorial_tag, spherical_equatorial_tag
> : detail::expand::segment_on_spheroid
> : detail::expand::segment_on_sphere
{};

View File

@@ -16,6 +16,7 @@
#include <boost/range.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -77,13 +78,24 @@ struct not_equal_to
template <typename Range, closure_selector Closure>
struct has_spikes
{
template <typename Iterator>
static inline Iterator find_different_from_first(Iterator first,
Iterator last)
{
typedef not_equal_to<typename point_type<Range>::type> not_equal;
BOOST_GEOMETRY_ASSERT(first != last);
Iterator second = first;
++second;
return std::find_if(second, last, not_equal(*first));
}
template <typename VisitPolicy>
static inline bool apply(Range const& range, VisitPolicy& visitor)
{
boost::ignore_unused(visitor);
typedef not_equal_to<typename point_type<Range>::type> not_equal;
typedef typename closeable_view<Range const, Closure>::type view_type;
typedef typename boost::range_iterator<view_type const>::type iterator;
@@ -94,23 +106,23 @@ struct has_spikes
iterator prev = boost::begin(view);
iterator cur = std::find_if(prev, boost::end(view), not_equal(*prev));
if ( cur == boost::end(view) )
iterator cur = find_different_from_first(prev, boost::end(view));
if (cur == boost::end(view))
{
// the range has only one distinct point, so it
// cannot have a spike
return ! visitor.template apply<no_failure>();
}
iterator next = std::find_if(cur, boost::end(view), not_equal(*cur));
if ( next == boost::end(view) )
iterator next = find_different_from_first(cur, boost::end(view));
if (next == boost::end(view))
{
// the range has only two distinct points, so it
// cannot have a spike
return ! visitor.template apply<no_failure>();
}
while ( next != boost::end(view) )
while (next != boost::end(view))
{
if ( geometry::detail::point_is_spike_or_equal(*prev,
*next,
@@ -121,20 +133,19 @@ struct has_spikes
}
prev = cur;
cur = next;
next = std::find_if(cur, boost::end(view), not_equal(*cur));
next = find_different_from_first(cur, boost::end(view));
}
if ( geometry::equals(range::front(view), range::back(view)) )
if (geometry::equals(range::front(view), range::back(view)))
{
iterator cur = boost::begin(view);
typename boost::range_reverse_iterator
<
view_type const
>::type prev = std::find_if(boost::rbegin(view),
boost::rend(view),
not_equal(range::back(view)));
iterator next =
std::find_if(cur, boost::end(view), not_equal(*cur));
>::type prev = find_different_from_first(boost::rbegin(view),
boost::rend(view));
iterator next = find_different_from_first(cur, boost::end(view));
if (detail::point_is_spike_or_equal(*prev, *next, *cur))
{
return

View File

@@ -217,7 +217,9 @@ public:
: base_t(pi, pj, pk, qi, qj, qk, robust_policy)
, m_result(strategy::apply(segment_type1(pi, pj),
segment_type2(qi, qj),
robust_policy))
robust_policy,
base_t::rpi(), base_t::rpj(),
base_t::rqi(), base_t::rqj()))
, m_robust_policy(robust_policy)
{}

View File

@@ -12,8 +12,8 @@
// 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
// 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_ALGORITHMS_DISPATCH_ENVELOPE_HPP
@@ -36,7 +36,7 @@ template
<
typename Geometry,
typename Tag = typename tag<Geometry>::type,
typename CSTag = typename cs_tag<Geometry>::type
typename CS_Tag = typename cs_tag<Geometry>::type
>
struct envelope : not_implemented<Tag>
{};

View File

@@ -13,8 +13,8 @@
// 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
// 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_ALGORITHMS_DISPATCH_EXPAND_HPP

View File

@@ -12,8 +12,8 @@
// 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
// 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_ALGORITHMS_ENVELOPE_HPP

View File

@@ -13,8 +13,8 @@
// 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
// 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_ALGORITHMS_EXPAND_HPP

View File

@@ -119,15 +119,10 @@ struct relate_cartesian_segments
boost::ignore_unused_variable_warning(robust_policy);
typedef typename select_calculation_type
<Segment1, Segment2, CalculationType>::type coordinate_type;
using geometry::detail::equals::equals_point_point;
bool const a_is_point = equals_point_point(robust_a1, robust_a2);
bool const b_is_point = equals_point_point(robust_b1, robust_b2);
typedef side::side_by_triangle<coordinate_type> side;
if(a_is_point && b_is_point)
{
return equals_point_point(robust_a1, robust_b2)
@@ -136,20 +131,32 @@ struct relate_cartesian_segments
;
}
typedef typename select_calculation_type
<Segment1, Segment2, CalculationType>::type coordinate_type;
typedef side::side_by_triangle<coordinate_type> side;
side_info sides;
sides.set<0>(side::apply(robust_b1, robust_b2, robust_a1),
side::apply(robust_b1, robust_b2, robust_a2));
sides.set<1>(side::apply(robust_a1, robust_a2, robust_b1),
side::apply(robust_a1, robust_a2, robust_b2));
bool collinear = sides.collinear();
if (sides.same<0>() || sides.same<1>())
if (sides.same<0>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
sides.set<1>(side::apply(robust_a1, robust_a2, robust_b1),
side::apply(robust_a1, robust_a2, robust_b2));
if (sides.same<1>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
bool collinear = sides.collinear();
typedef typename select_most_precise
<
coordinate_type, double

View File

@@ -0,0 +1,194 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP
#define BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP
#include <cstddef>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/int.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template
<
typename Geometry,
std::size_t Dimension1 = 0,
std::size_t Dimension2 = 1,
typename Tag = typename tag<Geometry>::type
>
struct two_dimensional_view
: not_implemented<Tag>
{};
// View that enables to choose two dimensions of a point and see it as
// a two-dimensional point
template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
struct two_dimensional_view<Point, Dimension1, Dimension2, point_tag>
{
BOOST_MPL_ASSERT_MSG((Dimension1 < dimension<Point>::value),
COORDINATE_DIMENSION1_IS_LARGER_THAN_POINT_DIMENSION,
(boost::mpl::int_<Dimension1>));
BOOST_MPL_ASSERT_MSG((Dimension2 < dimension<Point>::value),
COORDINATE_DIMENSION2_IS_LARGER_THAN_POINT_DIMENSION,
(boost::mpl::int_<Dimension2>));
two_dimensional_view(Point& point)
: m_point(point)
{}
Point& m_point;
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
namespace traits
{
template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
struct tag
<
geometry::detail::two_dimensional_view
<
Point, Dimension1, Dimension2, point_tag
>
>
{
typedef point_tag type;
};
template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
struct coordinate_system
<
geometry::detail::two_dimensional_view
<
Point, Dimension1, Dimension2, point_tag
>
> : coordinate_system<typename geometry::point_type<Point>::type>
{};
template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
struct coordinate_type
<
geometry::detail::two_dimensional_view
<
Point, Dimension1, Dimension2, point_tag
>
> : coordinate_type<typename geometry::point_type<Point>::type>
{};
template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
struct dimension
<
geometry::detail::two_dimensional_view
<
Point, Dimension1, Dimension2, point_tag
>
> : boost::mpl::int_<2>
{};
template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
struct point_type
<
geometry::detail::two_dimensional_view
<
Point, Dimension1, Dimension2, point_tag
>
>
{
typedef typename geometry::point_type<Point>::type type;
};
template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
struct access
<
geometry::detail::two_dimensional_view
<
Point, Dimension1, Dimension2, point_tag
>,
0
>
{
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
typedef geometry::detail::two_dimensional_view
<
Point, Dimension1, Dimension2, point_tag
> view_type;
static inline coordinate_type get(view_type const& view)
{
return geometry::get<Dimension1>(view.m_point);
}
static inline void set(view_type& view, coordinate_type const& value)
{
geometry::set<Dimension1>(view.m_point, value);
}
};
template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
struct access
<
geometry::detail::two_dimensional_view
<
Point, Dimension1, Dimension2, point_tag
>,
1
>
{
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
typedef geometry::detail::two_dimensional_view
<
Point, Dimension1, Dimension2, point_tag
> view_type;
static inline coordinate_type get(view_type const& view)
{
return geometry::get<Dimension2>(view.m_point);
}
static inline void set(view_type& view, coordinate_type const& value)
{
geometry::set<Dimension2>(view.m_point, value);
}
};
} // namespace traits
#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP

View File

@@ -1,9 +1,14 @@
// 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.
// 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.
@@ -12,6 +17,7 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/numeric/conversion/bounds.hpp>
#include <algorithms/test_envelope.hpp>
@@ -57,6 +63,144 @@ void test_3d()
test_envelope<bg::model::box<P> >("BOX(1 1 1,3 3 3)", 1, 3, 1, 3, 1, 3);
}
template <typename Geometry>
void test_empty_geometry(std::string const& wkt)
{
typedef typename bg::coordinate_type<Geometry>::type ct;
ct high_val = boost::numeric::bounds<ct>::highest();
ct low_val = boost::numeric::bounds<ct>::lowest();
test_envelope<Geometry>(wkt, high_val, low_val, high_val, low_val);
}
template <typename P>
void test_empty()
{
test_empty_geometry<bg::model::linestring<P> >("LINESTRING()");
test_empty_geometry<bg::model::ring<P> >("POLYGON(())");
test_empty_geometry<bg::model::polygon<P> >("POLYGON(())");
test_empty_geometry<bg::model::multi_point<P> >("MULTIPOINT()");
test_empty_geometry
<
bg::model::multi_linestring<bg::model::linestring<P> >
>("MULTILINESTRING()");
test_empty_geometry
<
bg::model::multi_polygon<bg::model::polygon<P> >
>("MULTIPOLYGON()");
}
template <typename P>
void test_invalid()
{
// polygon with empty exterior and interior rings
test_empty_geometry<bg::model::polygon<P> >("POLYGON((),(),())");
// polygon with empty interior rings
test_envelope
<
bg::model::polygon<P>
>("POLYGON((1 2,1 20,22 20,22 2,1 2),(),())",
1, 22, 2, 20);
// another polygon with empty interior rings
test_envelope
<
bg::model::polygon<P>
>("POLYGON((1 2,1 20,22 20,22 2,1 2),(),(3 4,19 4,19 18,3 18,3 4),())",
1, 22, 2, 20);
// polygon with empty exterior ring
test_envelope
<
bg::model::polygon<P>
>("POLYGON((),(),(3 4,19 4,19 18,3 18,3 4),())",
3, 19, 4, 18);
// another polygon with empty exterior ring
test_envelope
<
bg::model::polygon<P>
>("POLYGON((),(),(3 4,19 4,19 18,3 18,3 4),(4 5,18 5,18 17,4 17,4 5))",
3, 19, 4, 18);
// yet one more polygon with empty exterior ring
test_envelope
<
bg::model::polygon<P>
>("POLYGON((),(),(4 5,18 5,18 17,4 17,4 5),(3 4,19 4,19 18,3 18,3 4))",
3, 19, 4, 18);
// multilinestring with empty linestrings
test_empty_geometry
<
bg::model::multi_linestring<bg::model::linestring<P> >
>("MULTILINESTRING((),(),())");
// multilinestring with empty and non-empty linestrings
test_envelope
<
bg::model::multi_linestring<bg::model::linestring<P> >
>("MULTILINESTRING((),(10 20),())", 10, 10, 20, 20);
// multipolygon with empty polygon
test_empty_geometry
<
bg::model::multi_polygon<bg::model::polygon<P> >
>("MULTIPOLYGON((()))");
// multipolygon with many empty polygons
test_empty_geometry
<
bg::model::multi_polygon<bg::model::polygon<P> >
>("MULTIPOLYGON(((),(),()),(()),((),(),(),(),()))");
// multipolygon with empty polygons and non-empty (valid) polygon
test_envelope
<
bg::model::multi_polygon<bg::model::polygon<P> >
>("MULTIPOLYGON(((),(),()),((10 30,10 40,20 30,10 30)),\
((),(),()),(()))", 10, 20, 30, 40);
// multipolygon with empty polygons and non-empty (valid) polygon
// that has an interior ring
test_envelope
<
bg::model::multi_polygon<bg::model::polygon<P> >
>("MULTIPOLYGON(((),(),()),(()),\
((1 2,1 20,22 20,22 2,1 2),(3 4,19 4,19 18,3 18,3 4)),(()))",
1, 22, 2, 20);
// multipolygon with empty polygons and non-empty (invalid) polygon
// that has an interior ring but empty exterior ring
test_envelope
<
bg::model::multi_polygon<bg::model::polygon<P> >
>("MULTIPOLYGON(((),(),()),(()),((),(3 4,19 4,19 18,3 18,3 4)),(()))",
3, 19, 4, 18);
// multipolygon with empty polygons and non-empty (invalid) polygon
// that has an interior ring but empty exterior ring
test_envelope
<
bg::model::multi_polygon<bg::model::polygon<P> >
>("MULTIPOLYGON(((),(),()),((),(),(3 4,19 4,19 18,3 18,3 4),()),(()))",
3, 19, 4, 18);
// multipolygon with empty polygons and non-empty (invalid) polygon
// that has two non-empty interior rings but empty exterior ring
test_envelope
<
bg::model::multi_polygon<bg::model::polygon<P> >
>("MULTIPOLYGON(((),(),()),\
((),(),(3 4,19 4,19 18,3 18,3 4),(4 5,18 5,18 17,4 17,4 5),()),\
(()))",
3, 19, 4, 18);
}
int test_main(int, char* [])
{
@@ -71,6 +215,16 @@ int test_main(int, char* [])
test_3d<test::test_point>();
test_3d<boost::tuple<int, int, int> >();
test_empty<boost::tuple<float, float> >();
test_empty<bg::model::d2::point_xy<int> >();
test_empty<bg::model::d2::point_xy<float> >();
test_empty<bg::model::d2::point_xy<double> >();
test_invalid<boost::tuple<float, float> >();
test_invalid<bg::model::d2::point_xy<int> >();
test_invalid<bg::model::d2::point_xy<float> >();
test_invalid<bg::model::d2::point_xy<double> >();
#ifdef HAVE_TTMATH
test_2d<bg::model::d2::point_xy<ttmath_big> >();
test_3d<boost::tuple<ttmath_big, ttmath_big, ttmath_big> >();

View File

@@ -15,6 +15,7 @@
#include <boost/test/included/unit_test.hpp>
#include <cstddef>
#include <limits>
#include <iostream>
#include <string>
@@ -22,8 +23,10 @@
#include <geometry_test_common.hpp>
#include <from_wkt.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -38,125 +41,53 @@
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/reverse.hpp>
typedef bg::cs::spherical_equatorial<bg::radian> se_rad_type;
typedef bg::cs::spherical_equatorial<bg::degree> se_deg_type;
typedef bg::model::point<double, 2, se_rad_type> rad_point_type;
typedef bg::model::point<double, 2, se_deg_type> deg_point_type;
typedef bg::model::multi_point<rad_point_type> rad_multipoint_type;
typedef bg::model::multi_point<deg_point_type> deg_multipoint_type;
typedef bg::model::segment<rad_point_type> rad_segment_type;
typedef bg::model::segment<deg_point_type> deg_segment_type;
typedef bg::model::box<rad_point_type> rad_box_type;
typedef bg::model::box<deg_point_type> deg_box_type;
typedef bg::model::linestring<rad_point_type> rad_linestring_type;
typedef bg::model::linestring<deg_point_type> deg_linestring_type;
typedef bg::model::multi_linestring
<
rad_linestring_type
> rad_multilinestring_type;
typedef bg::model::multi_linestring
<
deg_linestring_type
> deg_multilinestring_type;
typedef bg::model::ring<rad_point_type> rad_cw_ring_type;
typedef bg::model::ring<deg_point_type> deg_cw_ring_type;
typedef bg::model::ring<rad_point_type, false> rad_ccw_ring_type;
typedef bg::model::ring<deg_point_type, false> deg_ccw_ring_type;
template <typename Units>
char const* units2string()
{
if (BOOST_GEOMETRY_CONDITION((boost::is_same<Units, bg::degree>::value)))
{
return "degrees";
}
return "radians";
}
template <typename Units>
struct other_system_info
{
typedef bg::degree units;
typedef bg::cs::spherical_equatorial<units> type;
template <typename T>
static inline T convert(T const& value)
{
return value * bg::math::r2d<T>();
}
};
template <>
struct other_system_info<bg::degree>
{
typedef bg::radian units;
typedef bg::cs::spherical_equatorial<units> type;
template <typename T>
static inline T convert(T const& value)
{
return value * bg::math::d2r<T>();
}
};
class equals_with_tolerance
{
private:
double m_tolerance;
template <typename T>
static inline T const& get_max(T const& a, T const& b, T const& c)
{
return (std::max)((std::max)(a, b), c);
}
template <typename T>
static inline bool check_close(T const& a, T const& b, double tol)
{
return (a == b)
|| (std::abs(a - b) <= tol * get_max(std::abs(a), std::abs(b), 1.0));
}
public:
equals_with_tolerance(double tolerance) : m_tolerance(tolerance) {}
template <typename T>
inline bool operator()(T const& value1, T const& value2) const
{
return check_close(value1, value2, m_tolerance);
}
};
template <typename Box1, typename Box2>
inline bool box_equals(Box1 const& box1, Box2 const& box2, double tol)
{
equals_with_tolerance equals(tol);
return equals(bg::get<0, 0>(box1), bg::get<0, 0>(box2))
&& equals(bg::get<0, 1>(box1), bg::get<0, 1>(box2))
&& equals(bg::get<1, 0>(box1), bg::get<1, 0>(box2))
&& equals(bg::get<1, 1>(box1), bg::get<1, 1>(box2));
}
#include "test_envelope_expand_on_spheroid.hpp"
template <typename MBR>
class envelope_on_spheroid_basic_tester
{
private:
template
<
typename Geometry,
typename Tag = typename bg::tag<Geometry>::type
>
struct write_geometry
{
template <typename OutputStream>
static inline OutputStream& apply(OutputStream& os,
Geometry const& geometry)
{
os << bg::wkt(geometry);
return os;
}
};
template <typename Segment>
struct write_geometry<Segment, bg::segment_tag>
{
template <typename OutputStream>
static inline OutputStream& apply(OutputStream& os,
Segment const& segment)
{
os << "SEGMENT" << bg::dsv(segment);
return os;
}
};
template <typename Box>
struct write_geometry<Box, bg::box_tag>
{
template <typename OutputStream>
static inline OutputStream& apply(OutputStream& os,
Box const& box)
{
os << "BOX" << bg::dsv(box);
return os;
}
};
template <typename Geometry, typename Box>
static inline void check_message(bool same_boxes,
std::string const& case_id,
@@ -165,33 +96,12 @@ private:
Box const& expected,
Box const& detected)
{
bool const is_box = boost::is_same
<
typename bg::tag<Geometry>::type, bg::box_tag
>::value;
bool const is_segment = boost::is_same
<
typename bg::tag<Geometry>::type, bg::segment_tag
>::value;
std::ostringstream stream;
stream << "case ID: " << case_id << ", "
<< "MBR units: " << units_str << "; "
<< "geometry: ";
if (BOOST_GEOMETRY_CONDITION(is_box))
{
stream << "BOX" << bg::dsv(geometry);
}
else if (BOOST_GEOMETRY_CONDITION(is_segment))
{
stream << "SEGMENT" << bg::dsv(geometry);
}
else
{
stream << bg::wkt(geometry);
}
write_geometry<Geometry>::apply(stream, geometry);
stream << "; " << "expected: " << bg::dsv(expected)
<< ", " << "detected: " << bg::dsv(detected);
@@ -202,8 +112,8 @@ private:
template <typename Box, typename Geometry>
static inline void base_test(std::string const& case_id,
Geometry const& geometry,
double lon_min, double lat_min,
double lon_max, double lat_max,
double lon_min, double lat_min, double height_min,
double lon_max, double lat_max, double height_max,
double tolerance)
{
typedef typename bg::coordinate_system<Box>::type::units box_units_type;
@@ -214,32 +124,13 @@ private:
bg::envelope(geometry, detected);
Box expected;
bg::assign_values(expected, lon_min, lat_min, lon_max, lat_max);
initialize_box<Box>::apply(expected,
lon_min, lat_min, height_min,
lon_max, lat_max, height_max);
#ifdef BOOST_GEOMETRY_TEST_DEBUG
bool const is_box = boost::is_same
<
typename bg::tag<Geometry>::type, bg::box_tag
>::value;
bool const is_segment = boost::is_same
<
typename bg::tag<Geometry>::type, bg::segment_tag
>::value;
std::cout << "geometry: ";
if (BOOST_GEOMETRY_CONDITION(is_box))
{
std::cout << "BOX" << bg::dsv(geometry);
}
else if(BOOST_GEOMETRY_CONDITION(is_segment))
{
std::cout << "SEGMENT" << bg::dsv(geometry);
}
else
{
std::cout << bg::wkt(geometry);
}
write_geometry<Geometry>::apply(std::cout, geometry);
std::cout << std::endl
<< "MBR units: " << units_str
@@ -250,7 +141,7 @@ private:
<< std::endl << std::endl;
#endif
check_message(box_equals(detected, expected, tolerance),
check_message(box_equals<Box>::apply(detected, expected, tolerance),
case_id, units_str,
geometry, expected, detected);
}
@@ -259,13 +150,13 @@ public:
template <typename Geometry>
static inline void apply(std::string const& case_id,
Geometry const& geometry,
double lon_min, double lat_min,
double lon_max, double lat_max,
double lon_min, double lat_min, double height_min,
double lon_max, double lat_max, double height_max,
double tolerance)
{
typedef other_system_info
<
typename bg::coordinate_system<MBR>::type::units
typename bg::coordinate_system<MBR>::type
> other;
typedef bg::model::box
@@ -273,7 +164,7 @@ public:
bg::model::point
<
typename bg::coordinate_type<MBR>::type,
2,
bg::dimension<MBR>::value,
typename other::type
>
> other_mbr_type;
@@ -284,15 +175,30 @@ public:
#endif
base_test<MBR>(case_id, geometry,
lon_min, lat_min, lon_max, lat_max,
lon_min, lat_min, height_min,
lon_max, lat_max, height_max,
tolerance);
base_test<other_mbr_type>(case_id, geometry,
other::convert(lon_min),
other::convert(lat_min),
other::convert(lon_max),
other::convert(lat_max),
tolerance);
if (lon_max < lon_min)
{
// we are in the case were a special MBR is returned;
// makes no sense to change units
base_test<other_mbr_type>(case_id, geometry,
lon_min, lat_min, height_min,
lon_max, lat_max, height_max,
tolerance);
}
else
{
base_test<other_mbr_type>(case_id, geometry,
other::convert(lon_min),
other::convert(lat_min),
height_min,
other::convert(lon_max),
other::convert(lat_max),
height_max,
tolerance);
}
}
};
@@ -331,17 +237,18 @@ struct test_envelope_on_spheroid
{
static inline void apply(std::string const& case_id,
Geometry const& geometry,
double lon_min1, double lat_min1,
double lon_max1, double lat_max1,
double lon_min2, double lat_min2,
double lon_max2, double lat_max2,
double lon_min1, double lat_min1, double height_min1,
double lon_max1, double lat_max1, double height_max1,
double lon_min2, double lat_min2, double height_min2,
double lon_max2, double lat_max2, double height_max2,
double tolerance = std::numeric_limits<double>::epsilon())
{
envelope_on_spheroid_basic_tester
<
MBR
>::apply(case_id, geometry,
lon_min1, lat_min1, lon_max1, lat_max1,
lon_min1, lat_min1, height_min1,
lon_max1, lat_max1, height_max1,
tolerance);
if (BOOST_GEOMETRY_CONDITION(TestReverse))
@@ -354,7 +261,8 @@ struct test_envelope_on_spheroid
<
MBR
>::apply(reversed_case_id, reversed_geometry,
lon_min2, lat_min2, lon_max2, lat_max2,
lon_min2, lat_min2, height_min2,
lon_max2, lat_max2, height_max2,
tolerance);
}
@@ -364,6 +272,34 @@ struct test_envelope_on_spheroid
#endif
}
static inline void apply(std::string const& case_id,
Geometry const& geometry,
double lon_min1, double lat_min1,
double lon_max1, double lat_max1,
double lon_min2, double lat_min2,
double lon_max2, double lat_max2,
double tolerance = std::numeric_limits<double>::epsilon())
{
apply(case_id, geometry,
lon_min1, lat_min1, 0, lon_max1, lat_max1, 0,
lon_min2, lat_min2, 0, lon_max2, lat_max2, 0,
tolerance);
}
static inline void apply(std::string const& case_id,
Geometry const& geometry,
double lon_min, double lat_min, double height_min,
double lon_max, double lat_max, double height_max,
double tolerance = std::numeric_limits<double>::epsilon())
{
apply(case_id, geometry,
lon_min, lat_min, height_min,
lon_max, lat_max, height_max,
lon_min, lat_min, height_min,
lon_max, lat_max, height_max,
tolerance);
}
static inline void apply(std::string const& case_id,
Geometry const& geometry,
double lon_min, double lat_min,
@@ -371,8 +307,7 @@ struct test_envelope_on_spheroid
double tolerance = std::numeric_limits<double>::epsilon())
{
apply(case_id, geometry,
lon_min, lat_min, lon_max, lat_max,
lon_min, lat_min, lon_max, lat_max,
lon_min, lat_min, 0, lon_max, lat_max, 0,
tolerance);
}
};
@@ -399,7 +334,10 @@ struct test_envelope_on_spheroid<Geometry, MBR, bg::ring_tag, TestReverse>
std::string ccw_case_id = case_id + "-2ccw";
deg_ccw_ring_type ccw_ring;
bg::model::ring
<
typename bg::point_type<Geometry>::type, false
> ccw_ring;
bg::convert(geometry, ccw_ring);
envelope_on_spheroid_basic_tester
@@ -429,10 +367,41 @@ struct test_envelope_on_spheroid<Geometry, MBR, bg::ring_tag, TestReverse>
};
BOOST_AUTO_TEST_CASE( envelope_point )
template <typename CoordinateSystem, typename Geometry>
void test_empty_geometry(std::string const& case_id, std::string const& wkt)
{
typedef deg_point_type G;
typedef test_envelope_on_spheroid<G, deg_box_type> tester;
std::size_t const dim = bg::dimension<Geometry>::value;
typedef bg::model::point<double, dim, CoordinateSystem> point_type;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<Geometry, B> tester;
typedef typename bg::coordinate_type<Geometry>::type ct;
ct high_val = boost::numeric::bounds<ct>::highest();
ct low_val = boost::numeric::bounds<ct>::lowest();
if (BOOST_GEOMETRY_CONDITION(dim == 2))
{
tester::apply(case_id,
from_wkt<Geometry>(wkt),
high_val, high_val, low_val, low_val);
}
else
{
tester::apply(case_id,
from_wkt<Geometry>(wkt),
high_val, high_val, high_val, low_val, low_val, low_val);
}
}
template <typename CoordinateSystem>
void test_envelope_point()
{
typedef bg::model::point<double, 2, CoordinateSystem> point_type;
typedef point_type G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
tester::apply("p01",
from_wkt<G>("POINT(10 10)"),
@@ -506,11 +475,43 @@ BOOST_AUTO_TEST_CASE( envelope_point )
0, -90, 0, -90);
}
BOOST_AUTO_TEST_CASE( envelope_point )
{
test_envelope_point<bg::cs::spherical_equatorial<bg::degree> >();
test_envelope_point<bg::cs::geographic<bg::degree> >();
}
template <typename CoordinateSystem>
void test_envelope_point_with_height()
{
typedef bg::model::point<double, 3, CoordinateSystem> point_type;
typedef point_type G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
tester::apply("ph01",
from_wkt<G>("POINT(10 10 1256)"),
10, 10, 1256, 10, 10, 1256);
}
BOOST_AUTO_TEST_CASE( envelope_point_with_height )
{
test_envelope_point_with_height
<
bg::cs::spherical_equatorial<bg::degree>
>();
test_envelope_point_with_height<bg::cs::geographic<bg::degree> >();
}
BOOST_AUTO_TEST_CASE( envelope_segment )
{
typedef deg_segment_type G;
typedef test_envelope_on_spheroid<G, deg_box_type> tester;
typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
typedef bg::model::point<double, 2, coordinate_system_type> point_type;
typedef bg::model::segment<point_type> G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
tester::apply("s01",
from_wkt<G>("SEGMENT(10 10,40 40)"),
@@ -661,10 +662,34 @@ BOOST_AUTO_TEST_CASE( envelope_segment )
}
BOOST_AUTO_TEST_CASE( envelope_multipoint )
BOOST_AUTO_TEST_CASE( envelope_segment_with_height )
{
typedef deg_multipoint_type G;
typedef test_envelope_on_spheroid<G, deg_box_type> tester;
typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
typedef bg::model::point<double, 3, coordinate_system_type> point_type;
typedef bg::model::segment<point_type> G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
tester::apply("sh01",
from_wkt<G>("SEGMENT(10 10 567,40 40 1356)"),
10, 10, 567, 40, 40, 1356);
tester::apply("sh02",
from_wkt<G>("SEGMENT(10 10 1356,40 40 567)"),
10, 10, 567, 40, 40, 1356);
}
template <typename CoordinateSystem>
void test_envelope_multipoint()
{
typedef bg::model::point<double, 2, CoordinateSystem> point_type;
typedef bg::model::multi_point<point_type> G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
// empty multipoint
test_empty_geometry<CoordinateSystem, G>("mp00", "MULTIPOINT()");
tester::apply("mp01",
from_wkt<G>("MULTIPOINT(0 0,10 10)"),
@@ -791,11 +816,51 @@ BOOST_AUTO_TEST_CASE( envelope_multipoint )
#endif
}
BOOST_AUTO_TEST_CASE( envelope_box )
BOOST_AUTO_TEST_CASE( envelope_multipoint )
{
typedef deg_box_type G;
typedef test_envelope_on_spheroid<G, deg_box_type> tester;
test_envelope_multipoint<bg::cs::spherical_equatorial<bg::degree> >();
test_envelope_multipoint<bg::cs::geographic<bg::degree> >();
}
template <typename CoordinateSystem>
void test_envelope_multipoint_with_height()
{
typedef bg::model::point<double, 3, CoordinateSystem> point_type;
typedef bg::model::multi_point<point_type> G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
// empty multipoint
test_empty_geometry<CoordinateSystem, G>("mph00", "MULTIPOINT()");
tester::apply("mph01",
from_wkt<G>("MULTIPOINT(0 0 567,10 10 1456)"),
0, 0, 567, 10, 10, 1456);
tester::apply("mph02",
from_wkt<G>("MULTIPOINT(0 0 567,10 10 1456,20 90 967)"),
0, 0, 567, 10, 90, 1456);
}
BOOST_AUTO_TEST_CASE( envelope_multipoint_with_height )
{
test_envelope_multipoint_with_height
<
bg::cs::spherical_equatorial<bg::degree>
>();
test_envelope_multipoint_with_height<bg::cs::geographic<bg::degree> >();
}
template <typename CoordinateSystem>
void test_envelope_box()
{
typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
typedef bg::model::point<double, 2, coordinate_system_type> point_type;
typedef bg::model::box<point_type> G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
tester::apply("b01",
from_wkt<G>("BOX(10 10,20 20)"),
@@ -976,11 +1041,52 @@ BOOST_AUTO_TEST_CASE( envelope_box )
0, -90, 0, -90);
}
BOOST_AUTO_TEST_CASE( envelope_box )
{
test_envelope_box<bg::cs::spherical_equatorial<bg::degree> >();
test_envelope_box<bg::cs::geographic<bg::degree> >();
}
template <typename CoordinateSystem>
void test_envelope_box_with_height()
{
typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
typedef bg::model::point<double, 3, coordinate_system_type> point_type;
typedef bg::model::box<point_type> G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
tester::apply("bh01",
from_wkt<G>("BOX(10 10 567,20 20 2834)"),
10, 10, 567, 20, 20, 2834);
tester::apply("bh02",
from_wkt<G>("BOX(10 10 567,20 20 567)"),
10, 10, 567, 20, 20, 567);
tester::apply("bh03",
from_wkt<G>("BOX(0 10 567,170 90 1567)"),
0, 10, 567, 170, 90, 1567);
}
BOOST_AUTO_TEST_CASE( envelope_box_with_height )
{
test_envelope_box_with_height<bg::cs::spherical_equatorial<bg::degree> >();
test_envelope_box_with_height<bg::cs::geographic<bg::degree> >();
}
BOOST_AUTO_TEST_CASE( envelope_linestring )
{
typedef deg_linestring_type G;
typedef test_envelope_on_spheroid<G, deg_box_type> tester;
typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
typedef bg::model::point<double, 2, coordinate_system_type> point_type;
typedef bg::model::linestring<point_type> G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
// empty linestring
test_empty_geometry<coordinate_system_type, G>("l00", "LINESTRING()");
tester::apply("l01",
from_wkt<G>("LINESTRING(10 15)"),
@@ -1086,14 +1192,61 @@ BOOST_AUTO_TEST_CASE( envelope_linestring )
}
BOOST_AUTO_TEST_CASE( envelope_linestring_with_height )
{
typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
typedef bg::model::point<double, 3, coordinate_system_type> point_type;
typedef bg::model::linestring<point_type> G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
// empty linestring
test_empty_geometry<coordinate_system_type, G>("lh00", "LINESTRING()");
tester::apply("lh01",
from_wkt<G>("LINESTRING(10 15 30,20 25 434,30 35 186)"),
10, 15, 30, 30, 35, 434);
}
BOOST_AUTO_TEST_CASE( envelope_multilinestring )
{
typedef deg_multilinestring_type G;
typedef test_envelope_on_spheroid<G, deg_box_type> tester;
typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
typedef bg::model::point<double, 2, coordinate_system_type> point_type;
typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
// empty multilinestring
test_empty_geometry<coordinate_system_type, G>("ml00", "MULTILINESTRING()");
// invalid multilinestring
test_empty_geometry<coordinate_system_type, G>("ml00a",
"MULTILINESTRING(())");
// invalid multilinestring
test_empty_geometry<coordinate_system_type, G>("ml00b",
"MULTILINESTRING((),())");
// invalid multilinestring
tester::apply("ml00c",
from_wkt<G>("MULTILINESTRING((10 15),(),())"),
10, 15, 10, 15);
// invalid multilinestring
tester::apply("ml00d",
from_wkt<G>("MULTILINESTRING((),(10 15),())"),
10, 15, 10, 15);
tester::apply("ml01",
from_wkt<G>("MULTILINESTRING((10 15))"),
10, 15, 10, 15);
#ifdef BOOST_GEOMETRY_INCLUDE_FAILING_TESTS
tester::apply("ml01a",
from_wkt<G>("MULTILINESTRING((),(),(10 15),())"),
10, 15, 10, 15);
#endif // BOOST_GEOMETRY_INCLUDE_FAILING_TESTS
tester::apply("ml02",
from_wkt<G>("MULTILINESTRING((-170 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"),
@@ -1121,6 +1274,30 @@ BOOST_AUTO_TEST_CASE( envelope_multilinestring )
}
BOOST_AUTO_TEST_CASE( envelope_multilinestring_with_height )
{
typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
typedef bg::model::point<double, 3, coordinate_system_type> point_type;
typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
typedef bg::model::box<point_type> B;
typedef test_envelope_on_spheroid<G, B> tester;
tester::apply("mlh01",
from_wkt<G>("MULTILINESTRING((10 15 1000))"),
10, 15, 1000, 10, 15, 1000);
#ifdef BOOST_GEOMETRY_INCLUDE_FAILING_TESTS
tester::apply("mlh01a",
from_wkt<G>("MULTILINESTRING((),(),(10 15 1000),())"),
10, 15, 1000, 10, 15, 1000);
#endif // BOOST_GEOMETRY_INCLUDE_FAILING_TESTS
tester::apply("mlh02",
from_wkt<G>("MULTILINESTRING((-170 40 400,-100 80 300),(-10 25 600,10 35 700,120 45 450))"),
-10, 25, 300, 260, 80, 700);
}
#if 0
// unit test for rings de-activated for now (current implementation
// for area on the spherical equatorial coordinate system is not complete)

View File

@@ -8,13 +8,14 @@
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_TEST_MODULE
#define BOOST_TEST_MODULE test_expand_on_spheroid
#endif
#include <boost/test/included/unit_test.hpp>
#include <cstddef>
#include <iostream>
#include <string>
@@ -23,112 +24,70 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/io/dsv/write.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/transform.hpp>
typedef bg::cs::spherical_equatorial<bg::radian> se_rad_type;
typedef bg::cs::spherical_equatorial<bg::degree> se_deg_type;
typedef bg::model::point<double, 2, se_rad_type> rad_point_type;
typedef bg::model::point<double, 2, se_deg_type> deg_point_type;
typedef bg::model::segment<rad_point_type> rad_segment_type;
typedef bg::model::segment<deg_point_type> deg_segment_type;
typedef bg::model::box<rad_point_type> rad_box_type;
typedef bg::model::box<deg_point_type> deg_box_type;
template <typename Units>
char const* units2string()
{
if (BOOST_GEOMETRY_CONDITION((boost::is_same<Units, bg::degree>::value)))
{
return "degrees";
}
return "radians";
}
template <typename Units>
struct other_system_info
{
typedef bg::degree units;
typedef bg::cs::spherical_equatorial<units> type;
template <typename T>
static inline T convert(T const& value)
{
return value * bg::math::r2d<T>();
}
};
template <>
struct other_system_info<bg::degree>
{
typedef bg::radian units;
typedef bg::cs::spherical_equatorial<units> type;
template <typename T>
static inline T convert(T const& value)
{
return value * bg::math::d2r<T>();
}
};
class equals_with_tolerance
{
private:
double m_tolerence;
template <typename T>
static inline T const& get_max(T const& a, T const& b, T const& c)
{
return (std::max)((std::max)(a, b), c);
}
template <typename T>
static inline bool check_close(T const& a, T const& b, double tol)
{
return (a == b)
|| (std::abs(a - b) <= tol * get_max(std::abs(a), std::abs(b), 1.0));
}
public:
equals_with_tolerance(double tolerence) : m_tolerence(tolerence) {}
template <typename T>
inline bool operator()(T const& value1, T const& value2) const
{
return check_close(value1, value2, m_tolerence);
}
};
template <typename Box1, typename Box2>
inline bool box_equals(Box1 const& box1, Box2 const& box2, double tol)
{
equals_with_tolerance equals(tol);
return equals(bg::get<0, 0>(box1), bg::get<0, 0>(box2))
&& equals(bg::get<0, 1>(box1), bg::get<0, 1>(box2))
&& equals(bg::get<1, 0>(box1), bg::get<1, 0>(box2))
&& equals(bg::get<1, 1>(box1), bg::get<1, 1>(box2));
}
#include "test_envelope_expand_on_spheroid.hpp"
class test_expand_on_spheroid
{
private:
template
<
typename Geometry,
typename Tag = typename bg::tag<Geometry>::type
>
struct write_geometry
{
template <typename OutputStream>
static inline OutputStream& apply(OutputStream& os,
Geometry const& geometry)
{
os << bg::wkt(geometry);
return os;
}
};
template <typename Segment>
struct write_geometry<Segment, bg::segment_tag>
{
template <typename OutputStream>
static inline OutputStream& apply(OutputStream& os,
Segment const& segment)
{
os << "SEGMENT" << bg::dsv(segment);
return os;
}
};
template <typename Box>
struct write_geometry<Box, bg::box_tag>
{
template <typename OutputStream>
static inline OutputStream& apply(OutputStream& os,
Box const& box)
{
os << "BOX" << bg::dsv(box);
return os;
}
};
template <typename Box, typename Geometry>
static inline void check_message(bool same_boxes,
std::string const& case_id,
@@ -140,34 +99,13 @@ private:
Box const& expected2,
Box const& detected)
{
bool const is_box = boost::is_same
<
typename bg::tag<Geometry>::type, bg::box_tag
>::value;
bool const is_segment = boost::is_same
<
typename bg::tag<Geometry>::type, bg::segment_tag
>::value;
std::ostringstream stream;
stream << "case ID: " << case_id << ", "
<< "MBR units: " << units_str << "; "
<< "input box: BOX" << bg::dsv(box) << ", "
<< "geometry: ";
if (BOOST_GEOMETRY_CONDITION(is_box))
{
stream << "BOX" << bg::dsv(geometry);
}
else if (BOOST_GEOMETRY_CONDITION(is_segment))
{
stream << "SEGMENT" << bg::dsv(geometry);
}
else
{
stream << bg::wkt(geometry);
}
write_geometry<Geometry>::apply(stream, geometry);
stream << "; " << "expected: " << bg::dsv(expected1);
if (expected_are_different)
@@ -188,9 +126,13 @@ private:
Box const& box,
Geometry const& geometry,
double lon_min1, double lat_min1,
double height_min1,
double lon_max1, double lat_max1,
double height_max1,
double lon_min2, double lat_min2,
double height_min2,
double lon_max2, double lat_max2,
double height_max2,
double tolerance)
{
typedef typename bg::coordinate_system
@@ -209,39 +151,20 @@ private:
|| (lon_max1 != lon_max2) || (lat_max1 != lat_max2);
Box expected1;
bg::assign_values(expected1,
lon_min1, lat_min1, lon_max1, lat_max1);
initialize_box<Box>::apply(expected1,
lon_min1, lat_min1, height_min1,
lon_max1, lat_max1, height_max1);
Box expected2;
bg::assign_values(expected2,
lon_min2, lat_min2, lon_max2, lat_max2);
initialize_box<Box>::apply(expected2,
lon_min2, lat_min2, height_min2,
lon_max2, lat_max2, height_max2);
#ifdef BOOST_GEOMETRY_TEST_DEBUG
bool const is_box = boost::is_same
<
typename bg::tag<Geometry>::type, bg::box_tag
>::value;
bool const is_segment = boost::is_same
<
typename bg::tag<Geometry>::type, bg::segment_tag
>::value;
std::cout << "input box: BOX" << bg::dsv(box) << std::endl;
std::cout << "geometry: ";
if (BOOST_GEOMETRY_CONDITION(is_box))
{
std::cout << "BOX" << bg::dsv(geometry);
}
else if(BOOST_GEOMETRY_CONDITION(is_segment))
{
std::cout << "SEGMENT" << bg::dsv(geometry);
}
else
{
std::cout << bg::wkt(geometry);
}
write_geometry<Geometry>::apply(std::cout, geometry);
std::cout << std::endl
<< "MBR units: " << units_str
@@ -257,11 +180,13 @@ private:
<< "detected: " << bg::dsv(detected)
<< std::endl << std::endl;
#endif
bool same_boxes = box_equals(detected, expected1, tolerance);
bool same_boxes
= box_equals<Box>::apply(detected, expected1, tolerance);
if (expected_are_different)
{
same_boxes = same_boxes
|| box_equals(detected, expected2, tolerance);
|| box_equals<Box>::apply(detected, expected2, tolerance);
}
check_message(same_boxes, case_id, units_str,
@@ -274,14 +199,18 @@ private:
Box const& box,
Geometry const& geometry,
double lon_min1, double lat_min1,
double height_min1,
double lon_max1, double lat_max1,
double height_max1,
double lon_min2, double lat_min2,
double height_min2,
double lon_max2, double lat_max2,
double height_max2,
double tolerance)
{
typedef other_system_info
<
typename bg::coordinate_system<Box>::type::units
typename bg::coordinate_system<Box>::type
> other;
typedef bg::model::box
@@ -289,7 +218,7 @@ private:
bg::model::point
<
typename bg::coordinate_type<Box>::type,
2,
bg::dimension<Box>::value,
typename other::type
>
> other_mbr_type;
@@ -300,26 +229,41 @@ private:
#endif
base_test(case_id, box, geometry,
lon_min1, lat_min1, lon_max1, lat_max1,
lon_min2, lat_min2, lon_max2, lat_max2,
lon_min1, lat_min1, height_min1,
lon_max1, lat_max1, height_max1,
lon_min2, lat_min2, height_min2,
lon_max2, lat_max2, height_max2,
tolerance);
other_mbr_type other_box;
bg::assign_values(other_box,
other::convert(bg::get<0, 0>(box)),
other::convert(bg::get<0, 1>(box)),
other::convert(bg::get<1, 0>(box)),
other::convert(bg::get<1, 1>(box)));
bg::detail::indexed_point_view<Box const, 0> p_min(box);
bg::detail::indexed_point_view<Box const, 1> p_max(box);
bg::detail::indexed_point_view
<
other_mbr_type, 0
> other_min(other_box);
bg::detail::indexed_point_view
<
other_mbr_type, 1
> other_max(other_box);
bg::transform(p_min, other_min);
bg::transform(p_max, other_max);
base_test(case_id, other_box, geometry,
other::convert(lon_min1),
other::convert(lat_min1),
height_min1,
other::convert(lon_max1),
other::convert(lat_max1),
height_max1,
other::convert(lon_min2),
other::convert(lat_min2),
height_min2,
other::convert(lon_max2),
other::convert(lat_max2),
height_max2,
tolerance);
#ifdef BOOST_GEOMETRY_TEST_DEBUG
@@ -337,17 +281,23 @@ private:
Box const& box,
Geometry const& geometry,
double lon_min1, double lat_min1,
double height_min1,
double lon_max1, double lat_max1,
double height_max1,
double lon_min2, double lat_min2,
double height_min2,
double lon_max2, double lat_max2,
double height_max2,
double tolerance)
{
basic_tester
<
false
>::apply(case_id, box, geometry,
lon_min1, lat_min1, lon_max1, lat_max1,
lon_min2, lat_min2, lon_max2, lat_max2,
lon_min1, lat_min1, height_min1,
lon_max1, lat_max1, height_max1,
lon_min2, lat_min2, height_min1,
lon_max2, lat_max2, height_max2,
tolerance);
std::string case_id_r = case_id + "[R]";
@@ -356,8 +306,10 @@ private:
<
false
>::apply(case_id_r, geometry, box,
lon_min1, lat_min1, lon_max1, lat_max1,
lon_min2, lat_min2, lon_max2, lat_max2,
lon_min1, lat_min1, height_min1,
lon_max1, lat_max1, height_max1,
lon_min2, lat_min2, height_min2,
lon_max2, lat_max2, height_max2,
tolerance);
}
};
@@ -368,10 +320,10 @@ public:
static inline void apply(std::string const& case_id,
Box const& box,
Geometry const& geometry,
double lon_min1, double lat_min1,
double lon_max1, double lat_max1,
double lon_min2, double lat_min2,
double lon_max2, double lat_max2,
double lon_min1, double lat_min1, double height_min1,
double lon_max1, double lat_max1, double height_max1,
double lon_min2, double lat_min2, double height_min2,
double lon_max2, double lat_max2, double height_max2,
double tolerance = std::numeric_limits<double>::epsilon())
{
@@ -383,11 +335,29 @@ public:
bg::box_tag
>::value
>::apply(case_id, box, geometry,
lon_min1, lat_min1, lon_max1, lat_max1,
lon_min2, lat_min2, lon_max2, lat_max2,
lon_min1, lat_min1, height_min1,
lon_max1, lat_max1, height_max1,
lon_min2, lat_min2, height_min2,
lon_max2, lat_max2, height_max2,
tolerance);
}
template <typename Box, typename Geometry>
static inline void apply(std::string const& case_id,
Box const& box,
Geometry const& geometry,
double lon_min1, double lat_min1,
double lon_max1, double lat_max1,
double lon_min2, double lat_min2,
double lon_max2, double lat_max2,
double tolerance = std::numeric_limits<double>::epsilon())
{
apply(case_id, box, geometry,
lon_min1, lat_min1, 0, lon_max1, lat_max1, 0,
lon_min2, lat_min2, 0, lon_max2, lat_max2, 0,
tolerance);
}
template <typename Box, typename Geometry>
static inline void apply(std::string const& case_id,
Box const& box,
@@ -397,17 +367,33 @@ public:
double tolerance = std::numeric_limits<double>::epsilon())
{
apply(case_id, box, geometry,
lon_min, lat_min, lon_max, lat_max,
lon_min, lat_min, lon_max, lat_max,
lon_min, lat_min, 0, lon_max, lat_max, 0,
lon_min, lat_min, 0, lon_max, lat_max, 0,
tolerance);
}
template <typename Box, typename Geometry>
static inline void apply(std::string const& case_id,
Box const& box,
Geometry const& geometry,
double lon_min, double lat_min, double height_min,
double lon_max, double lat_max, double height_max,
double tolerance = std::numeric_limits<double>::epsilon())
{
apply(case_id, box, geometry,
lon_min, lat_min, height_min, lon_max, lat_max, height_max,
lon_min, lat_min, height_min, lon_max, lat_max, height_max,
tolerance);
}
};
BOOST_AUTO_TEST_CASE( expand_point )
template <typename CoordinateSystem>
void test_expand_point()
{
typedef deg_box_type B;
typedef deg_point_type G;
typedef bg::model::point<double, 2, CoordinateSystem> point_type;
typedef bg::model::box<point_type> B;
typedef point_type G;
typedef test_expand_on_spheroid tester;
tester::apply("p01",
@@ -596,11 +582,51 @@ BOOST_AUTO_TEST_CASE( expand_point )
10, -90, 100, 90);
}
BOOST_AUTO_TEST_CASE( expand_point )
{
test_expand_point<bg::cs::spherical_equatorial<bg::degree> >();
test_expand_point<bg::cs::geographic<bg::degree> >();
}
template <typename CoordinateSystem>
void test_expand_point_with_height()
{
typedef bg::model::point<double, 3, CoordinateSystem> point_type;
typedef bg::model::box<point_type> B;
typedef point_type G;
typedef test_expand_on_spheroid tester;
// deactivate this for now
tester::apply("ph01",
from_wkt<B>("BOX(0 0 20,5 5 100)"),
from_wkt<G>("POINT(10 10 80)"),
0, 0, 20, 10, 10, 100);
tester::apply("ph02",
from_wkt<B>("BOX(0 0 20,5 5 100)"),
from_wkt<G>("POINT(10 10 120)"),
0, 0, 20, 10, 10, 120);
tester::apply("ph03",
from_wkt<B>("BOX(0 0 20,5 5 100)"),
from_wkt<G>("POINT(10 10 5)"),
0, 0, 5, 10, 10, 100);
}
BOOST_AUTO_TEST_CASE( expand_point_with_height )
{
test_expand_point_with_height<bg::cs::spherical_equatorial<bg::degree> >();
test_expand_point_with_height<bg::cs::geographic<bg::degree> >();
}
BOOST_AUTO_TEST_CASE( expand_segment )
{
typedef deg_box_type B;
typedef deg_segment_type G;
typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
typedef bg::model::point<double, 2, coordinate_system_type> point_type;
typedef bg::model::box<point_type> B;
typedef bg::model::segment<point_type> G;
typedef test_expand_on_spheroid tester;
tester::apply("s01",
@@ -675,10 +701,42 @@ BOOST_AUTO_TEST_CASE( expand_segment )
}
BOOST_AUTO_TEST_CASE( expand_box )
BOOST_AUTO_TEST_CASE( expand_segment_with_height )
{
typedef deg_box_type B;
typedef deg_box_type G;
typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
typedef bg::model::point<double, 3, coordinate_system_type> point_type;
typedef bg::model::box<point_type> B;
typedef bg::model::segment<point_type> G;
typedef test_expand_on_spheroid tester;
tester::apply("sh01",
from_wkt<B>("BOX(20 20 100,50 50 1000)"),
from_wkt<G>("SEGMENT(10 10 150,40 40 500)"),
10, 10, 100, 50, 50, 1000);
tester::apply("sh02",
from_wkt<B>("BOX(20 20 100,50 50 1000)"),
from_wkt<G>("SEGMENT(10 10 60,40 40 1500)"),
10, 10, 60, 50, 50, 1500);
tester::apply("sh03",
from_wkt<B>("BOX(20 20 100,50 50 1000)"),
from_wkt<G>("SEGMENT(10 10 150,40 40 1500)"),
10, 10, 100, 50, 50, 1500);
tester::apply("sh04",
from_wkt<B>("BOX(20 20 100,50 50 1000)"),
from_wkt<G>("SEGMENT(10 10 60,40 40 800)"),
10, 10, 60, 50, 50, 1000);
}
template <typename CoordinateSystem>
void test_expand_box()
{
typedef bg::model::point<double, 2, CoordinateSystem> point_type;
typedef bg::model::box<point_type> B;
typedef bg::model::box<point_type> G;
typedef test_expand_on_spheroid tester;
tester::apply("b01",
@@ -846,3 +904,45 @@ BOOST_AUTO_TEST_CASE( expand_box )
from_wkt<G>("BOX(0 -10,185 50)"),
-180, -40, 180, 50);
}
BOOST_AUTO_TEST_CASE( expand_box )
{
test_expand_box<bg::cs::spherical_equatorial<bg::degree> >();
test_expand_box<bg::cs::geographic<bg::degree> >();
}
template <typename CoordinateSystem>
void test_expand_box_with_height()
{
typedef bg::model::point<double, 3, CoordinateSystem> point_type;
typedef bg::model::box<point_type> B;
typedef bg::model::box<point_type> G;
typedef test_expand_on_spheroid tester;
tester::apply("bh01",
from_wkt<B>("BOX(11 11 100,19 19 1000)"),
from_wkt<G>("BOX(10 10 200,20 20 800)"),
10, 10, 100, 20, 20, 1000);
tester::apply("bh02",
from_wkt<B>("BOX(11 11 200,19 19 1000)"),
from_wkt<G>("BOX(10 10 100,20 20 800)"),
10, 10, 100, 20, 20, 1000);
tester::apply("bh03",
from_wkt<B>("BOX(11 11 100,19 19 800)"),
from_wkt<G>("BOX(10 10 200,20 20 1000)"),
10, 10, 100, 20, 20, 1000);
tester::apply("bh04",
from_wkt<B>("BOX(11 11 200,19 19 1000)"),
from_wkt<G>("BOX(10 10 100,20 20 800)"),
10, 10, 100, 20, 20, 1000);
}
BOOST_AUTO_TEST_CASE( expand_box_with_height )
{
test_expand_box_with_height<bg::cs::spherical_equatorial<bg::degree> >();
test_expand_box_with_height<bg::cs::geographic<bg::degree> >();
}

View File

@@ -33,6 +33,7 @@
#include <boost/geometry/io/wkt/wkt.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/is_valid.hpp>
#include <boost/geometry/algorithms/is_simple.hpp>
@@ -296,6 +297,27 @@ BOOST_AUTO_TEST_CASE( test_is_simple_areal )
false);
}
BOOST_AUTO_TEST_CASE( test_geometry_with_NaN_coordinates )
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl;
std::cout << "************************************" << std::endl;
std::cout << " is_valid: geometry with NaN coordinates" << std::endl;
std::cout << "************************************" << std::endl;
#endif
linestring_type ls1, ls2;
bg::read_wkt("LINESTRING(1 1,1.115235e+308 1.738137e+308)", ls1);
bg::read_wkt("LINESTRING(-1 1,1.115235e+308 1.738137e+308)", ls2);
// the intersection of the two linestrings is a new linestring
// (multilinestring with a single element) that has NaN coordinates
multi_linestring_type mls;
bg::intersection(ls1, ls2, mls);
test_simple(mls, true);
}
BOOST_AUTO_TEST_CASE( test_is_simple_variant )
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG

View File

@@ -20,6 +20,7 @@
#include "test_is_valid.hpp"
#include <boost/geometry/algorithms/correct.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/reverse.hpp>
BOOST_AUTO_TEST_CASE( test_is_valid_point )
@@ -1114,6 +1115,38 @@ BOOST_AUTO_TEST_CASE( test_is_valid_multipolygon )
test_open_multipolygons<point_type, do_not_allow_duplicates>();
}
BOOST_AUTO_TEST_CASE( test_geometry_with_NaN_coordinates )
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl;
std::cout << "************************************" << std::endl;
std::cout << " is_valid: geometry with NaN coordinates" << std::endl;
std::cout << "************************************" << std::endl;
#endif
linestring_type ls1, ls2;
bg::read_wkt("LINESTRING(1 1,1.115235e+308 1.738137e+308)", ls1);
bg::read_wkt("LINESTRING(-1 1,1.115235e+308 1.738137e+308)", ls2);
// the intersection of the two linestrings is a new linestring
// (multilinestring with a single element) that has NaN coordinates
multi_linestring_type mls;
bg::intersection(ls1, ls2, mls);
typedef validity_tester_linear<true> tester_allow_spikes;
typedef validity_tester_linear<false> tester_disallow_spikes;
test_valid
<
tester_allow_spikes, multi_linestring_type
>::apply("mls-NaN", mls, true);
test_valid
<
tester_disallow_spikes, multi_linestring_type
>::apply("mls-NaN", mls, true);
}
BOOST_AUTO_TEST_CASE( test_is_valid_variant )
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG

View File

@@ -0,0 +1,192 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_TEST_ENVELOPE_EXPAND_ON_SPHEROID_HPP
#define BOOST_GEOMETRY_TEST_ENVELOPE_EXPAND_ON_SPHEROID_HPP
#include <cmath>
#include <cstddef>
#include <algorithm>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/assign.hpp>
template <typename Units>
char const* units2string()
{
if (BOOST_GEOMETRY_CONDITION((boost::is_same<Units, bg::degree>::value)))
{
return "degrees";
}
return "radians";
}
template <typename CoordinateSystem>
struct other_system_info
{};
template <>
struct other_system_info<bg::cs::spherical_equatorial<bg::radian> >
{
typedef bg::degree units;
typedef bg::cs::spherical_equatorial<units> type;
template <typename T>
static inline T convert(T const& value)
{
return value * bg::math::r2d<T>();
}
};
template <>
struct other_system_info<bg::cs::spherical_equatorial<bg::degree> >
{
typedef bg::radian units;
typedef bg::cs::spherical_equatorial<units> type;
template <typename T>
static inline T convert(T const& value)
{
return value * bg::math::d2r<T>();
}
};
template <>
struct other_system_info<bg::cs::geographic<bg::radian> >
{
typedef bg::degree units;
typedef bg::cs::geographic<units> type;
template <typename T>
static inline T convert(T const& value)
{
return value * bg::math::r2d<T>();
}
};
template <>
struct other_system_info<bg::cs::geographic<bg::degree> >
{
typedef bg::radian units;
typedef bg::cs::geographic<units> type;
template <typename T>
static inline T convert(T const& value)
{
return value * bg::math::d2r<T>();
}
};
class equals_with_tolerance
{
private:
double m_tolerence;
template <typename T>
static inline T const& get_max(T const& a, T const& b, T const& c)
{
return (std::max)((std::max)(a, b), c);
}
template <typename T>
static inline bool check_close(T const& a, T const& b, double tol)
{
return (a == b)
|| (std::abs(a - b) <= tol * get_max(std::abs(a), std::abs(b), 1.0));
}
public:
equals_with_tolerance(double tolerence) : m_tolerence(tolerence) {}
template <typename T>
inline bool operator()(T const& value1, T const& value2) const
{
return check_close(value1, value2, m_tolerence);
}
};
template
<
typename Box1,
typename Box2 = Box1,
std::size_t DimensionCount = bg::dimension<Box1>::value
>
struct box_equals
{
static inline bool apply(Box1 const& box1, Box2 const& box2, double tol)
{
equals_with_tolerance equals(tol);
return equals(bg::get<0, 0>(box1), bg::get<0, 0>(box2))
&& equals(bg::get<0, 1>(box1), bg::get<0, 1>(box2))
&& equals(bg::get<1, 0>(box1), bg::get<1, 0>(box2))
&& equals(bg::get<1, 1>(box1), bg::get<1, 1>(box2));
}
};
template <typename Box1, typename Box2>
struct box_equals<Box1, Box2, 3>
{
static inline bool apply(Box1 const& box1, Box2 const& box2, double tol)
{
equals_with_tolerance equals(tol);
return box_equals<Box1, Box2, 2>::apply(box1, box2, tol)
&& equals(bg::get<0, 2>(box1), bg::get<0, 2>(box2))
&& equals(bg::get<1, 2>(box1), bg::get<1, 2>(box2));
}
};
template <typename Box, std::size_t Dimension = bg::dimension<Box>::value>
struct initialize_box
{
static inline void apply(Box& box,
double lon_min, double lat_min, double,
double lon_max, double lat_max, double)
{
bg::detail::indexed_point_view<Box, bg::min_corner> p_min(box);
bg::detail::indexed_point_view<Box, bg::max_corner> p_max(box);
bg::assign_values(p_min, lon_min, lat_min);
bg::assign_values(p_max, lon_max, lat_max);
}
};
template <typename Box>
struct initialize_box<Box, 3>
{
static inline void apply(Box& box,
double lon_min, double lat_min, double height_min,
double lon_max, double lat_max, double height_max)
{
bg::detail::indexed_point_view<Box, bg::min_corner> p_min(box);
bg::detail::indexed_point_view<Box, bg::max_corner> p_max(box);
bg::assign_values(p_min, lon_min, lat_min, height_min);
bg::assign_values(p_max, lon_max, lat_max, height_max);
}
};
#endif // BOOST_GEOMETRY_TEST_ENVELOPE_EXPAND_ON_SPHEROID_HPP