• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3 
4 // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 
6 // This file was modified by Oracle on 2019.
7 // Modifications copyright (c) 2019, Oracle and/or its affiliates.
8 
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10 
11 // Use, modification and distribution is subject to the Boost Software License,
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13 // http://www.boost.org/LICENSE_1_0.txt)
14 
15 #include <iostream>
16 #include <iomanip>
17 #include <string>
18 
19 
20 #include <geometry_test_common.hpp>
21 
22 #include <boost/foreach.hpp>
23 
24 #include <boost/geometry/algorithms/correct.hpp>
25 #include <boost/geometry/algorithms/intersection.hpp>
26 #include <boost/geometry/algorithms/union.hpp>
27 #include <boost/geometry/algorithms/difference.hpp>
28 #include <boost/geometry/algorithms/intersects.hpp>
29 #include <boost/geometry/algorithms/within.hpp>
30 #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
31 
32 #include <boost/geometry/geometries/geometries.hpp>
33 #include <boost/geometry/geometries/point_xy.hpp>
34 
35 #include <boost/geometry/strategies/strategies.hpp>
36 
37 #include <boost/geometry/io/wkt/read.hpp>
38 #include <boost/geometry/io/wkt/write.hpp>
39 
40 
41 
42 #if defined(TEST_WITH_SVG)
43 #  include <boost/geometry/io/svg/svg_mapper.hpp>
44 #endif
45 
46 template <typename Geometry>
test_assemble(std::string const & id,Geometry const & p,Geometry const & q,char operation='i')47 inline void test_assemble(std::string const& id, Geometry const& p, Geometry const& q, char operation = 'i')
48 {
49     std::vector<Geometry> u, i, d1, d2;
50     bg::detail::union_::union_insert<Geometry>(p, q, std::back_inserter(u));
51     bg::detail::intersection::intersection_insert<Geometry>(p, q, std::back_inserter(i));
52     bg::detail::difference::difference_insert<Geometry>(p, q, std::back_inserter(d1));
53     bg::detail::difference::difference_insert<Geometry>(q, p, std::back_inserter(d2));
54 
55     if (operation == 'i')
56     {
57         typedef typename bg::default_area_result<Geometry>::type type;
58         type area_p = bg::area(p);
59         type area_q = bg::area(q);
60 
61         type area_i = 0, area_u = 0, area_d1 = 0, area_d2 = 0;
62 
63         BOOST_FOREACH(Geometry const& g, u)
64         {
65             area_u += bg::area(g);
66         }
67         BOOST_FOREACH(Geometry const& g, i)
68         {
69             area_i += bg::area(g);
70         }
71         BOOST_FOREACH(Geometry const& g, d1)
72         {
73             area_d1 += bg::area(g);
74         }
75         BOOST_FOREACH(Geometry const& g, d2)
76         {
77             area_d2 += bg::area(g);
78         }
79 
80         type diff = (area_p + area_q) - area_u - area_i;
81         type diff_d1 = (area_u - area_q) - area_d1;
82         type diff_d2 = (area_u - area_p) - area_d2;
83 
84         bool ok = bg::math::abs(diff) < 0.001
85             && bg::math::abs(diff_d1) < 0.001
86             && bg::math::abs(diff_d2) < 0.001;
87 
88         BOOST_CHECK_MESSAGE(ok,
89             id << " diff:  "
90                 << diff << " d1: "
91                 << diff_d1 << " d2: "
92                 << diff_d2);
93     }
94 
95 #if defined(TEST_WITH_SVG)
96     {
97         std::ostringstream filename;
98         filename << "assemble_" << id << "_" << operation << ".svg";
99         std::ofstream svg(filename.str().c_str());
100 
101         bg::svg_mapper<typename bg::point_type<Geometry>::type> mapper(svg, 500, 500);
102         mapper.add(p);
103         mapper.add(q);
104         mapper.map(p, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:3");
105         mapper.map(q, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:3");
106         std::string linestyle = "opacity:0.7;fill:none;stroke-opacity:1;stroke-miterlimit:4;";
107 
108         std::vector<Geometry> const& v = operation == 'i' ? i
109             : operation == 'u' ? u
110             : operation == 'd' ? d1
111             : d2
112             ;
113 
114         BOOST_FOREACH(Geometry const& geometry, v)
115         {
116             mapper.map(geometry,
117                 linestyle + "stroke-width:3;stroke-linejoin:round;stroke-linecap:square;stroke-dasharray:12,12;stroke:rgb(255,0,0);");
118         }
119     }
120 #endif
121 }
122 
123 template <typename Polygon>
int_ok(Polygon const & poly)124 inline bool int_ok(Polygon const& poly)
125 {
126 
127     typename bg::point_type<Polygon>::type const& pi =
128         bg::interior_rings(poly)[0].front();
129 
130     return bg::within(pi, bg::exterior_ring(poly));
131 }
132 
133 
134 template <typename T>
generate()135 void generate()
136 {
137 
138     static std::string exteriors[4] = {
139             "(0 0,0 10,10 10,10 0,0 0)",
140             "(1 1,1 9,8 9,8 1,1 1)",
141             "(2 0.5, 0.5 2,0.5 8,2 9.5,6 9.5,8.5 8,8.5 2,7 0.5,2 0.5)",
142             "(3 3,3 7,6 7,6 3,3 3)"
143     };
144     static std::string interiors[4] = {
145             "(2 2,2 8,7 8,7 2,2 2)",
146             "(8.5 1,8.5 2,9.5 2,9.5 1,8.5 1)",
147             "(4 4,4 5,5 5,5 4,4 4)",
148             "(6 4,6 5,9 5,9 4,6 4)"
149     };
150     for (int pe = 0; pe < 4; pe++)
151     {
152         for (int qe = 0; qe < 4; qe++)
153         {
154             for (int pi = 0; pi < 4; pi++)
155             {
156                 for (int qi = 0; qi < 4; qi++)
157                 {
158                     std::string ps = "POLYGON(" + exteriors[pe] + "," + interiors[pi] + ")";
159                     std::string qs = "POLYGON(" + exteriors[qe] + "," + interiors[qi] + ")";
160 
161                     typedef bg::model::d2::point_xy<T> point_type;
162                     bg::model::polygon<point_type> p, q;
163                     bg::read_wkt(ps, p);
164                     bg::read_wkt(qs, q);
165                     bg::correct(p);
166                     bg::correct(q);
167                     if (! bg::intersects(p)
168                         && ! bg::intersects(q)
169                         && int_ok(p)
170                         && int_ok(q)
171                         )
172                     {
173                         std::ostringstream out;
174                         out << pe << qe << pi << qi;
175                         test_assemble(out.str(), p, q);
176 
177 #if defined(TEST_WITH_SVG)
178                         test_assemble(out.str(), p, q, 'u');
179                         test_assemble(out.str(), p, q, 'd');
180                         test_assemble(out.str(), p, q, 'r');
181 #endif
182                     }
183                 }
184             }
185         }
186     }
187 }
188 
189 
190 #if ! defined(GEOMETRY_TEST_MULTI)
test_main(int,char * [])191 int test_main(int, char* [])
192 {
193     generate<double>();
194     return 0;
195 }
196 #endif
197