Imported Upstream version 1.49.0
[platform/upstream/boost.git] / libs / geometry / test / algorithms / overlay / robustness / test_overlay_p_q.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3 //
4 // Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // Use, modification and distribution is subject to the Boost Software License,
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8
9 #ifndef BOOST_GEOMETRY_TEST_OVERLAY_P_Q_HPP
10 #define BOOST_GEOMETRY_TEST_OVERLAY_P_Q_HPP
11
12 #include <fstream>
13 #include <iomanip>
14
15 //#define BOOST_GEOMETRY_ROBUSTNESS_USE_DIFFERENCE
16
17
18 #include <geometry_test_common.hpp>
19
20 // For mixing int/float
21 #if defined(_MSC_VER)
22 #pragma warning( disable : 4244 )
23 #pragma warning( disable : 4267 )
24 #endif
25
26
27 #include <boost/geometry.hpp>
28 #include <boost/geometry/geometries/geometries.hpp>
29 #include <boost/geometry/geometries/point_xy.hpp>
30 #include <boost/geometry/multi/geometries/multi_polygon.hpp>
31 #include <boost/geometry/extensions/io/svg/svg_mapper.hpp>
32
33 #include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
34
35 struct p_q_settings
36 {
37     bool svg;
38     bool also_difference;
39     bool wkt;
40     double tolerance;
41
42     p_q_settings()
43         : svg(false)
44         , also_difference(false)
45         , wkt(false)
46         , tolerance(1.0e-6)
47     {}
48 };
49
50 template <typename Geometry>
51 inline typename bg::default_area_result<Geometry>::type p_q_area(Geometry const& g)
52 {
53     try
54     {
55         return bg::area(g);
56     }
57     catch(bg::empty_input_exception const&)
58     {
59         return 0;
60     }
61 }
62
63 template <typename OutputType, typename CalculationType, typename G1, typename G2>
64 static bool test_overlay_p_q(std::string const& caseid,
65             G1 const& p, G2 const& q,
66             p_q_settings const& settings)
67 {
68     bool result = true;
69
70     typedef typename bg::coordinate_type<G1>::type coordinate_type;
71     typedef typename bg::point_type<G1>::type point_type;
72
73     bg::model::multi_polygon<OutputType> out_i, out_u, out_d, out_d2;
74
75     CalculationType area_p = p_q_area(p);
76     CalculationType area_q = p_q_area(q);
77     CalculationType area_d1 = 0, area_d2 = 0;
78
79     bg::intersection(p, q, out_i);
80     CalculationType area_i = p_q_area(out_i);
81
82     bg::union_(p, q, out_u);
83     CalculationType area_u = p_q_area(out_u);
84
85     double sum = (area_p + area_q) - area_u - area_i;
86
87     bool wrong = std::abs(sum) > settings.tolerance;
88
89     if (settings.also_difference)
90     {
91         bg::difference(p, q, out_d);
92         bg::difference(q, p, out_d2);
93         area_d1 = p_q_area(out_d);
94         area_d2 = p_q_area(out_d2);
95         double sum_d1 = (area_u - area_q) - area_d1;
96         double sum_d2 = (area_u - area_p) - area_d2;
97         bool wrong_d1 = std::abs(sum_d1) > settings.tolerance;
98         bool wrong_d2 = std::abs(sum_d2) > settings.tolerance;
99
100         if (wrong_d1 || wrong_d2)
101         {
102             wrong = true;
103         }
104     }
105
106     bool svg = settings.svg;
107
108     if (wrong || settings.wkt)
109     {
110         if (wrong)
111         {
112             result = false;
113             svg = true;
114         }
115         bg::unique(out_i);
116         bg::unique(out_u);
117
118         std::cout
119             << "type: " << string_from_type<CalculationType>::name()
120             << " id: " << caseid
121             << " area i: " << area_i
122             << " area u: " << area_u
123             << " area p: " << area_p
124             << " area q: " << area_q
125             << " sum: " << sum;
126
127         if (settings.also_difference)
128         {
129             std::cout
130                 << " area d1: " << area_d1
131                 << " area d2: " << area_d2;
132         }
133         std::cout
134             << std::endl
135             << std::setprecision(9)
136             << " p: " << bg::wkt(p) << std::endl
137             << " q: " << bg::wkt(q) << std::endl
138             << " i: " << bg::wkt(out_i) << std::endl
139             << " u: " << bg::wkt(out_u) << std::endl
140             ;
141
142     }
143
144     if(svg)
145     {
146         std::ostringstream filename;
147         filename << "overlay_" << caseid << "_"
148             << string_from_type<coordinate_type>::name()
149             << string_from_type<CalculationType>::name()
150             << ".svg";
151
152         std::ofstream svg(filename.str().c_str());
153
154         bg::svg_mapper<point_type> mapper(svg, 500, 500);
155
156         mapper.add(p);
157         mapper.add(q);
158
159         // Input shapes in green/blue
160         mapper.map(p, "fill-opacity:0.5;fill:rgb(153,204,0);"
161                 "stroke:rgb(153,204,0);stroke-width:3");
162         mapper.map(q, "fill-opacity:0.3;fill:rgb(51,51,153);"
163                 "stroke:rgb(51,51,153);stroke-width:3");
164
165         if (settings.also_difference)
166         {
167             for (BOOST_AUTO(it, out_d.begin()); it != out_d.end(); ++it)
168             {
169                 mapper.map(*it,
170                     "opacity:0.8;fill:none;stroke:rgb(255,128,0);stroke-width:4;stroke-dasharray:1,7;stroke-linecap:round");
171             }
172             for (BOOST_AUTO(it, out_d2.begin()); it != out_d2.end(); ++it)
173             {
174                 mapper.map(*it,
175                     "opacity:0.8;fill:none;stroke:rgb(255,0,255);stroke-width:4;stroke-dasharray:1,7;stroke-linecap:round");
176             }
177         }
178         else
179         {
180             for (BOOST_AUTO(it, out_i.begin()); it != out_i.end(); ++it)
181             {
182                 mapper.map(*it, "fill-opacity:0.1;stroke-opacity:0.4;fill:rgb(255,0,0);"
183                         "stroke:rgb(255,0,0);stroke-width:4");
184             }
185             for (BOOST_AUTO(it, out_u.begin()); it != out_u.end(); ++it)
186             {
187                 mapper.map(*it, "fill-opacity:0.1;stroke-opacity:0.4;fill:rgb(255,0,0);"
188                         "stroke:rgb(255,0,255);stroke-width:4");
189             }
190         }
191     }
192     return result;
193 }
194
195 #endif // BOOST_GEOMETRY_TEST_OVERLAY_P_Q_HPP