Skip to content

Commit cc381b3

Browse files
committedApr 11, 2018
[algorithms] [tests] Fix envelope algorithm for spherical and geographic polygons and rings
1 parent 49b9e7b commit cc381b3

File tree

4 files changed

+195
-81
lines changed

4 files changed

+195
-81
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Boost.Geometry
2+
3+
// Copyright (c) 2018 Oracle and/or its affiliates.
4+
5+
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
6+
7+
// Use, modification and distribution is subject to the Boost Software License,
8+
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9+
// http://www.boost.org/LICENSE_1_0.txt)
10+
11+
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_AREAL_HPP
12+
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_AREAL_HPP
13+
14+
#include <boost/geometry/core/cs.hpp>
15+
#include <boost/geometry/core/tags.hpp>
16+
17+
#include <boost/geometry/iterators/segment_iterator.hpp>
18+
19+
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
20+
#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
21+
22+
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
23+
24+
namespace boost { namespace geometry
25+
{
26+
27+
#ifndef DOXYGEN_NO_DETAIL
28+
namespace detail { namespace envelope
29+
{
30+
31+
template <typename EnvelopePolicy>
32+
struct envelope_polygon
33+
{
34+
template <typename Polygon, typename Box, typename Strategy>
35+
static inline void apply(Polygon const& polygon, Box& mbr, Strategy const& strategy)
36+
{
37+
typename ring_return_type<Polygon const>::type ext_ring
38+
= exterior_ring(polygon);
39+
40+
if (geometry::is_empty(ext_ring))
41+
{
42+
// if the exterior ring is empty, consider the interior rings
43+
envelope_multi_range
44+
<
45+
EnvelopePolicy
46+
>::apply(interior_rings(polygon), mbr, strategy);
47+
}
48+
else
49+
{
50+
// otherwise, consider only the exterior ring
51+
EnvelopePolicy::apply(ext_ring, mbr, strategy);
52+
}
53+
}
54+
};
55+
56+
57+
}} // namespace detail::envelope
58+
#endif // DOXYGEN_NO_DETAIL
59+
60+
#ifndef DOXYGEN_NO_DISPATCH
61+
namespace dispatch
62+
{
63+
64+
65+
template <typename Ring, typename CS_Tag>
66+
struct envelope<Ring, ring_tag, CS_Tag>
67+
: detail::envelope::envelope_range
68+
{};
69+
70+
template <typename Ring>
71+
struct envelope<Ring, ring_tag, spherical_equatorial_tag>
72+
: detail::envelope::envelope_linestring_or_ring_on_spheroid
73+
{};
74+
75+
template <typename Ring>
76+
struct envelope<Ring, ring_tag, geographic_tag>
77+
: detail::envelope::envelope_linestring_or_ring_on_spheroid
78+
{};
79+
80+
81+
template <typename Polygon, typename CS_Tag>
82+
struct envelope<Polygon, polygon_tag, CS_Tag>
83+
: detail::envelope::envelope_polygon
84+
<
85+
detail::envelope::envelope_range
86+
>
87+
{};
88+
89+
template <typename Polygon>
90+
struct envelope<Polygon, polygon_tag, spherical_equatorial_tag>
91+
: detail::envelope::envelope_polygon
92+
<
93+
detail::envelope::envelope_linestring_or_ring_on_spheroid
94+
>
95+
{};
96+
97+
template <typename Polygon>
98+
struct envelope<Polygon, polygon_tag, geographic_tag>
99+
: detail::envelope::envelope_polygon
100+
<
101+
detail::envelope::envelope_linestring_or_ring_on_spheroid
102+
>
103+
{};
104+
105+
106+
template <typename MultiPolygon, typename CS_Tag>
107+
struct envelope<MultiPolygon, multi_polygon_tag, CS_Tag>
108+
: detail::envelope::envelope_multi_range
109+
<
110+
detail::envelope::envelope_polygon
111+
<
112+
detail::envelope::envelope_range
113+
>
114+
>
115+
{};
116+
117+
template <typename MultiPolygon>
118+
struct envelope<MultiPolygon, multi_polygon_tag, spherical_equatorial_tag>
119+
: detail::envelope::envelope_multi_range
120+
<
121+
detail::envelope::envelope_polygon
122+
<
123+
detail::envelope::envelope_linestring_or_ring_on_spheroid
124+
>
125+
>
126+
{};
127+
128+
template <typename MultiPolygon>
129+
struct envelope<MultiPolygon, multi_polygon_tag, geographic_tag>
130+
: detail::envelope::envelope_multi_range
131+
<
132+
detail::envelope::envelope_polygon
133+
<
134+
detail::envelope::envelope_linestring_or_ring_on_spheroid
135+
>
136+
>
137+
{};
138+
139+
140+
} // namespace dispatch
141+
#endif // DOXYGEN_NO_DISPATCH
142+
143+
144+
}} // namespace boost::geometry
145+
146+
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_AREAL_HPP

‎include/boost/geometry/algorithms/detail/envelope/implementation.hpp

+1-69
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <boost/geometry/algorithms/is_empty.hpp>
2828

29+
#include <boost/geometry/algorithms/detail/envelope/areal.hpp>
2930
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
3031
#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
3132
#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp>
@@ -35,73 +36,4 @@
3536

3637
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
3738

38-
39-
namespace boost { namespace geometry
40-
{
41-
42-
#ifndef DOXYGEN_NO_DETAIL
43-
namespace detail { namespace envelope
44-
{
45-
46-
47-
struct envelope_polygon
48-
{
49-
template <typename Polygon, typename Box, typename Strategy>
50-
static inline void apply(Polygon const& polygon, Box& mbr, Strategy const& strategy)
51-
{
52-
typename ring_return_type<Polygon const>::type ext_ring
53-
= exterior_ring(polygon);
54-
55-
if (geometry::is_empty(ext_ring))
56-
{
57-
// if the exterior ring is empty, consider the interior rings
58-
envelope_multi_range
59-
<
60-
envelope_range
61-
>::apply(interior_rings(polygon), mbr, strategy);
62-
}
63-
else
64-
{
65-
// otherwise, consider only the exterior ring
66-
envelope_range::apply(ext_ring, mbr, strategy);
67-
}
68-
}
69-
};
70-
71-
72-
}} // namespace detail::envelope
73-
#endif // DOXYGEN_NO_DETAIL
74-
75-
#ifndef DOXYGEN_NO_DISPATCH
76-
namespace dispatch
77-
{
78-
79-
80-
template <typename Ring>
81-
struct envelope<Ring, ring_tag>
82-
: detail::envelope::envelope_range
83-
{};
84-
85-
86-
template <typename Polygon>
87-
struct envelope<Polygon, polygon_tag>
88-
: detail::envelope::envelope_polygon
89-
{};
90-
91-
92-
template <typename MultiPolygon>
93-
struct envelope<MultiPolygon, multi_polygon_tag>
94-
: detail::envelope::envelope_multi_range
95-
<
96-
detail::envelope::envelope_polygon
97-
>
98-
{};
99-
100-
101-
} // namespace dispatch
102-
#endif // DOXYGEN_NO_DISPATCH
103-
104-
105-
}} // namespace boost::geometry
106-
10739
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP

‎include/boost/geometry/algorithms/detail/envelope/linear.hpp

+9-10
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,15 @@ namespace boost { namespace geometry
3434
namespace detail { namespace envelope
3535
{
3636

37-
38-
struct envelope_linestring_on_spheroid
37+
struct envelope_linestring_or_ring_on_spheroid
3938
{
40-
template <typename Linestring, typename Box, typename Strategy>
41-
static inline void apply(Linestring const& linestring,
39+
template <typename LinestringRing, typename Box, typename Strategy>
40+
static inline void apply(LinestringRing const& linestring_or_ring,
4241
Box& mbr,
4342
Strategy const& strategy)
4443
{
45-
envelope_range::apply(geometry::segments_begin(linestring),
46-
geometry::segments_end(linestring),
44+
envelope_range::apply(geometry::segments_begin(linestring_or_ring),
45+
geometry::segments_end(linestring_or_ring),
4746
mbr,
4847
strategy);
4948
}
@@ -66,12 +65,12 @@ struct envelope<Linestring, linestring_tag, CS_Tag>
6665

6766
template <typename Linestring>
6867
struct envelope<Linestring, linestring_tag, spherical_equatorial_tag>
69-
: detail::envelope::envelope_linestring_on_spheroid
68+
: detail::envelope::envelope_linestring_or_ring_on_spheroid
7069
{};
7170

7271
template <typename Linestring>
7372
struct envelope<Linestring, linestring_tag, geographic_tag>
74-
: detail::envelope::envelope_linestring_on_spheroid
73+
: detail::envelope::envelope_linestring_or_ring_on_spheroid
7574
{};
7675

7776

@@ -91,7 +90,7 @@ struct envelope
9190
MultiLinestring, multi_linestring_tag, spherical_equatorial_tag
9291
> : detail::envelope::envelope_multi_range_on_spheroid
9392
<
94-
detail::envelope::envelope_linestring_on_spheroid
93+
detail::envelope::envelope_linestring_or_ring_on_spheroid
9594
>
9695
{};
9796

@@ -101,7 +100,7 @@ struct envelope
101100
MultiLinestring, multi_linestring_tag, geographic_tag
102101
> : detail::envelope::envelope_multi_range_on_spheroid
103102
<
104-
detail::envelope::envelope_linestring_on_spheroid
103+
detail::envelope::envelope_linestring_or_ring_on_spheroid
105104
>
106105
{};
107106

‎test/algorithms/envelope_expand/envelope_on_spheroid.cpp

+39-2
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,8 @@ struct test_envelope_on_sphere_or_spheroid<Geometry, MBR, bg::ring_tag, TestReve
442442
<
443443
MBR
444444
>::apply(case_id, geometry,
445-
lon_min1, lat_min1, lon_max1, lat_max1,
445+
lon_min1, lat_min1, 0,
446+
lon_max1, lat_max1, 0,
446447
tolerance);
447448

448449
std::string ccw_case_id = case_id + "-2ccw";
@@ -457,7 +458,8 @@ struct test_envelope_on_sphere_or_spheroid<Geometry, MBR, bg::ring_tag, TestReve
457458
<
458459
MBR
459460
>::apply(ccw_case_id, ccw_ring,
460-
lon_min2, lat_min2, lon_max2, lat_max2,
461+
lon_min2, lat_min2, 0,
462+
lon_max2, lat_max2, 0,
461463
tolerance);
462464

463465
#ifdef BOOST_GEOMETRY_TEST_DEBUG
@@ -2433,6 +2435,41 @@ BOOST_AUTO_TEST_CASE( envelope_multilinestring_spheroid_with_height )
24332435
-10, 25, 300, 260, 80, 700);
24342436
}
24352437

2438+
//Test spherical polygons and rings (geographic should be similar)
2439+
BOOST_AUTO_TEST_CASE( envelope_polygon )
2440+
{
2441+
typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
2442+
typedef bg::model::point<double, 2, coordinate_system_type> point_type;
2443+
typedef bg::model::polygon<point_type> G;
2444+
typedef bg::model::box<point_type> B;
2445+
typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
2446+
2447+
typedef bg::model::ring<point_type> R;
2448+
typedef test_envelope_on_sphere_or_spheroid<R, B> testerR;
2449+
R ring1;
2450+
bg::append(ring1, point_type(0.0, 0.0));
2451+
bg::append(ring1, point_type(0.0, 5.0));
2452+
bg::append(ring1, point_type(5.0, 5.0));
2453+
bg::append(ring1, point_type(5.0, 0.0));
2454+
bg::append(ring1, point_type(0.0, 0.0));
2455+
2456+
testerR::apply("r01",
2457+
ring1,
2458+
0, 0, 5, 5.0047392446083938);
2459+
tester::apply("p01",
2460+
from_wkt<G>("POLYGON((0 0,1 0,1 1,0 1,0 0))"),
2461+
0, 0, 1, 1.0000380706527705);
2462+
tester::apply("p02",
2463+
from_wkt<G>("POLYGON((0 0,1 0,1 1,0 1,0 0),(0.5 0.5,0.7 0.5,0.7 0.7,0.5 0.5))"),
2464+
0, 0, 1, 1.0000380706527705);
2465+
tester::apply("p03",
2466+
from_wkt<G>("POLYGON((),(0.5 0.5,0.5 0.7,0.7 0.7,0.5 0.5))"),
2467+
0.5, 0.5, 0.7, 0.70000106605644807);
2468+
tester::apply("p04",
2469+
from_wkt<G>("POLYGON((),(0.5 0.5,0.5 0.7,0.7 0.7,0.5 0.5),\
2470+
(0.7 0.5,0.9 0.5,0.9 0.7,0.7 0.5))"),
2471+
0.5, 0.5, 0.9, 0.70000106605644807);
2472+
}
24362473

24372474
// unit test for rings de-activated for now (current implementation
24382475
// for area on the spherical equatorial coordinate system is not complete)

0 commit comments

Comments
 (0)
Please sign in to comment.