1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3 
4 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
6 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
7 // Copyright (c) 2014 Samuel Debionne, Grenoble, France.
8 
9 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
10 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
11 
12 // Use, modification and distribution is subject to the Boost Software License,
13 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
14 // http://www.boost.org/LICENSE_1_0.txt)
15 
16 #include <geometry_test_common.hpp>
17 
18 #include <boost/geometry/arithmetic/arithmetic.hpp>
19 #include <boost/geometry/algorithms/assign.hpp>
20 #include <boost/geometry/algorithms/num_points.hpp>
21 
22 #include <boost/geometry/geometries/geometries.hpp>
23 #include <boost/geometry/geometries/adapted/c_array.hpp>
24 #include <boost/geometry/geometries/adapted/boost_tuple.hpp>
25 #include <boost/geometry/io/wkt/wkt.hpp>
26 #include <boost/variant/variant.hpp>
27 #include <test_common/test_point.hpp>
28 
29 BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian)
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)30 BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
31 
32 
33 template <typename Geometry>
34 void check_geometry(Geometry const& geometry, std::string const& expected)
35 {
36     std::ostringstream out;
37     out << bg::wkt(geometry);
38     BOOST_CHECK_EQUAL(out.str(), expected);
39 }
40 
41 template <typename Geometry, typename Points>
check_assign_points(Points const & points,std::string const &)42 void check_assign_points(Points const& points, std::string const& /*expected*/)
43 {
44     Geometry geometry;
45     bg::assign_points(geometry, points);
46     check_geometry(geometry, "LINESTRING(1 2,3 4,5 6)");
47 
48     boost::variant<Geometry> v;
49     bg::assign_points(v, points);
50 }
51 
52 template <typename Point>
test_assign_linestring_2d()53 void test_assign_linestring_2d()
54 {
55     bg::model::linestring<Point> line;
56 
57     // Test assignment of plain array (note that this is only possible if adapted c-array is included!)
58     const double coors[3][2] = { {1, 2}, {3, 4}, {5, 6} };
59     check_assign_points<bg::model::linestring<Point> >(coors, "LINESTRING(1 2,3 4,5 6)");
60 
61     // Test assignment of point array
62     Point points[3];
63     bg::assign_values(points[0], 1, 2);
64     bg::assign_values(points[1], 3, 4);
65     bg::assign_values(points[2], 5, 6);
66     check_assign_points<bg::model::linestring<Point> >(points, "LINESTRING(1 2,3 4,5 6)");
67 
68     // Test assignment of array with different point-type (tuple adaption should be included)
69     boost::tuple<float, float> tuples[3];
70     tuples[0] = boost::make_tuple(1, 2);
71     tuples[1] = boost::make_tuple(3, 4);
72     tuples[2] = boost::make_tuple(5, 6);
73     check_assign_points<bg::model::linestring<Point> >(tuples, "LINESTRING(1 2,3 4,5 6)");
74 }
75 
76 namespace detail
77 {
78     template <typename BoxOrSegment>
test_assign_box_or_segment_2d()79     void test_assign_box_or_segment_2d()
80     {
81         BoxOrSegment geometry;
82         bg::assign_values(geometry, 1, 2, 3, 4);
83         BOOST_CHECK((bg::get<bg::min_corner, 0>(geometry) == 1));
84         BOOST_CHECK((bg::get<bg::min_corner, 1>(geometry) == 2));
85         BOOST_CHECK((bg::get<bg::max_corner, 0>(geometry) == 3));
86         BOOST_CHECK((bg::get<bg::max_corner, 1>(geometry) == 4));
87 
88         bg::assign_zero(geometry);
89         BOOST_CHECK((bg::get<bg::min_corner, 0>(geometry) == 0));
90         BOOST_CHECK((bg::get<bg::min_corner, 1>(geometry) == 0));
91         BOOST_CHECK((bg::get<bg::max_corner, 0>(geometry) == 0));
92         BOOST_CHECK((bg::get<bg::max_corner, 1>(geometry) == 0));
93 
94         bg::assign_inverse(geometry);
95         BOOST_CHECK((bg::get<bg::min_corner, 0>(geometry) > 9999));
96         BOOST_CHECK((bg::get<bg::min_corner, 1>(geometry) > 9999));
97         BOOST_CHECK((bg::get<bg::max_corner, 0>(geometry) < 9999));
98         BOOST_CHECK((bg::get<bg::max_corner, 1>(geometry) < 9999));
99     }
100 }
101 
102 template <typename Point>
test_assign_box_or_segment_2d()103 void test_assign_box_or_segment_2d()
104 {
105     detail::test_assign_box_or_segment_2d<bg::model::box<Point> >();
106     detail::test_assign_box_or_segment_2d<bg::model::segment<Point> >();
107 }
108 
109 template <typename Point>
test_assign_box_2d()110 void test_assign_box_2d()
111 {
112     detail::test_assign_box_or_segment_2d<bg::model::box<Point> >();
113 }
114 
115 template <typename Point>
test_assign_point_3d()116 void test_assign_point_3d()
117 {
118     Point p;
119     bg::assign_values(p, 1, 2, 3);
120     check_geometry(p, "POINT(1 2 3)");
121 
122     bg::assign_value(p, 123);
123     check_geometry(p, "POINT(123 123 123)");
124 
125     bg::assign_zero(p);
126     check_geometry(p, "POINT(0 0 0)");
127 }
128 
129 template <typename P>
test_assign_conversion()130 void test_assign_conversion()
131 {
132     typedef bg::model::box<P> box_type;
133     typedef bg::model::ring<P> ring_type;
134     typedef bg::model::polygon<P> polygon_type;
135 
136     P p;
137     bg::assign_values(p, 1, 2);
138 
139     box_type b;
140     bg::assign(b, p);
141 
142     BOOST_CHECK_CLOSE((bg::get<0, 0>(b)), 1.0, 0.001);
143     BOOST_CHECK_CLOSE((bg::get<0, 1>(b)), 2.0, 0.001);
144     BOOST_CHECK_CLOSE((bg::get<1, 0>(b)), 1.0, 0.001);
145     BOOST_CHECK_CLOSE((bg::get<1, 1>(b)), 2.0, 0.001);
146 
147 
148     bg::set<bg::min_corner, 0>(b, 1);
149     bg::set<bg::min_corner, 1>(b, 2);
150     bg::set<bg::max_corner, 0>(b, 3);
151     bg::set<bg::max_corner, 1>(b, 4);
152 
153     ring_type ring;
154     bg::assign(ring, b);
155 
156     {
157         typedef bg::model::ring<P, false, false> ring_type_ccw;
158         ring_type_ccw ring_ccw;
159         // Should NOT compile (currently): bg::assign(ring_ccw, ring);
160 
161     }
162 
163     typename boost::range_const_iterator<ring_type>::type it = ring.begin();
164     BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001);
165     BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001);
166     it++;
167     BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001);
168     BOOST_CHECK_CLOSE(bg::get<1>(*it), 4.0, 0.001);
169     it++;
170     BOOST_CHECK_CLOSE(bg::get<0>(*it), 3.0, 0.001);
171     BOOST_CHECK_CLOSE(bg::get<1>(*it), 4.0, 0.001);
172     it++;
173     BOOST_CHECK_CLOSE(bg::get<0>(*it), 3.0, 0.001);
174     BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001);
175     it++;
176     BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001);
177     BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001);
178 
179     BOOST_CHECK_EQUAL(ring.size(), 5u);
180 
181 
182     polygon_type polygon;
183 
184     bg::assign(polygon, ring);
185     BOOST_CHECK_EQUAL(bg::num_points(polygon), 5u);
186 
187     ring_type ring2;
188     bg::assign(ring2, polygon);
189     BOOST_CHECK_EQUAL(bg::num_points(ring2), 5u);
190 }
191 
192 
193 template <typename P>
test_assign_conversion_variant()194 void test_assign_conversion_variant()
195 {
196     typedef bg::model::box<P> box_type;
197     typedef bg::model::ring<P> ring_type;
198     typedef bg::model::polygon<P> polygon_type;
199 
200     P p;
201     bg::assign_values(p, 1, 2);
202 
203     box_type b;
204     boost::variant<box_type&> variant_b(b);
205     bg::assign(variant_b, p);
206 
207     BOOST_CHECK_CLOSE((bg::get<0, 0>(b)), 1.0, 0.001);
208     BOOST_CHECK_CLOSE((bg::get<0, 1>(b)), 2.0, 0.001);
209     BOOST_CHECK_CLOSE((bg::get<1, 0>(b)), 1.0, 0.001);
210     BOOST_CHECK_CLOSE((bg::get<1, 1>(b)), 2.0, 0.001);
211 
212 
213     bg::set<bg::min_corner, 0>(b, 1);
214     bg::set<bg::min_corner, 1>(b, 2);
215     bg::set<bg::max_corner, 0>(b, 3);
216     bg::set<bg::max_corner, 1>(b, 4);
217 
218     ring_type ring;
219     boost::variant<ring_type&> variant_ring(ring);
220     bg::assign(variant_ring, boost::variant<box_type>(b));
221 
222     {
223         typedef bg::model::ring<P, false, false> ring_type_ccw;
224         ring_type_ccw ring_ccw;
225         // Should NOT compile (currently): bg::assign(ring_ccw, ring);
226 
227     }
228 
229     typename boost::range_const_iterator<ring_type>::type it = ring.begin();
230     BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001);
231     BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001);
232     it++;
233     BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001);
234     BOOST_CHECK_CLOSE(bg::get<1>(*it), 4.0, 0.001);
235     it++;
236     BOOST_CHECK_CLOSE(bg::get<0>(*it), 3.0, 0.001);
237     BOOST_CHECK_CLOSE(bg::get<1>(*it), 4.0, 0.001);
238     it++;
239     BOOST_CHECK_CLOSE(bg::get<0>(*it), 3.0, 0.001);
240     BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001);
241     it++;
242     BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001);
243     BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001);
244 
245     BOOST_CHECK_EQUAL(ring.size(), 5u);
246 
247 
248     polygon_type polygon;
249     boost::variant<polygon_type&> variant_polygon(polygon);
250 
251     bg::assign(variant_polygon, boost::variant<ring_type>(ring));
252     BOOST_CHECK_EQUAL(bg::num_points(polygon), 5u);
253 
254     ring_type ring2;
255     boost::variant<ring_type&> variant_ring2(ring2);
256     bg::assign(variant_ring2, boost::variant<polygon_type>(polygon));
257     BOOST_CHECK_EQUAL(bg::num_points(ring2), 5u);
258 }
259 
260 
261 template <typename Point>
test_assign_point_2d()262 void test_assign_point_2d()
263 {
264     Point p;
265     bg::assign_values(p, 1, 2);
266     check_geometry(p, "POINT(1 2)");
267 
268     bg::assign_value(p, 123);
269     check_geometry(p, "POINT(123 123)");
270 
271     bg::assign_zero(p);
272     check_geometry(p, "POINT(0 0)");
273 }
274 
275 
276 
277 
278 
test_main(int,char * [])279 int test_main(int, char* [])
280 {
281     test_assign_point_3d<int[3]>();
282     test_assign_point_3d<float[3]>();
283     test_assign_point_3d<double[3]>();
284     test_assign_point_3d<test::test_point>();
285     test_assign_point_3d<bg::model::point<int, 3, bg::cs::cartesian> >();
286     test_assign_point_3d<bg::model::point<float, 3, bg::cs::cartesian> >();
287     test_assign_point_3d<bg::model::point<double, 3, bg::cs::cartesian> >();
288 
289     test_assign_point_2d<int[2]>();
290     test_assign_point_2d<float[2]>();
291     test_assign_point_2d<double[2]>();
292     test_assign_point_2d<bg::model::point<int, 2, bg::cs::cartesian> >();
293     test_assign_point_2d<bg::model::point<float, 2, bg::cs::cartesian> >();
294     test_assign_point_2d<bg::model::point<double, 2, bg::cs::cartesian> >();
295 
296     test_assign_conversion<bg::model::point<double, 2, bg::cs::cartesian> >();
297     test_assign_conversion_variant<bg::model::point<double, 2, bg::cs::cartesian> >();
298 
299 
300     // Segment (currently) cannot handle array's because derived from std::pair
301     test_assign_box_2d<int[2]>();
302     test_assign_box_2d<float[2]>();
303     test_assign_box_2d<double[2]>();
304 
305     test_assign_box_or_segment_2d<bg::model::point<int, 2, bg::cs::cartesian> >();
306     test_assign_box_or_segment_2d<bg::model::point<float, 2, bg::cs::cartesian> >();
307     test_assign_box_or_segment_2d<bg::model::point<double, 2, bg::cs::cartesian> >();
308 
309     test_assign_linestring_2d<bg::model::point<int, 2, bg::cs::cartesian> >();
310     test_assign_linestring_2d<bg::model::point<float, 2, bg::cs::cartesian> >();
311     test_assign_linestring_2d<bg::model::point<double, 2, bg::cs::cartesian> >();
312 
313     return 0;
314 }
315