1 /*! \file bezier_traits_adapter.cpp
2 * Using the traits adaptor to generate a traits class for Bezier polygons.
3 */
4
5 #include <CGAL/config.h>
6
7 #ifndef CGAL_USE_CORE
8 #include <iostream>
main()9 int main()
10 {
11 std::cout << "Sorry, this example needs CORE ..." << std::endl;
12 return (0);
13 }
14 #else
15
16 #include <CGAL/Cartesian.h>
17 #include <CGAL/CORE_algebraic_number_traits.h>
18 #include <CGAL/Arr_Bezier_curve_traits_2.h>
19 #include <CGAL/Gps_traits_2.h>
20 #include <CGAL/Boolean_set_operations_2.h>
21 #include <CGAL/General_polygon_set_2.h>
22 #include <CGAL/Timer.h>
23
24 #include <fstream>
25
26 typedef CGAL::CORE_algebraic_number_traits Nt_traits;
27 typedef Nt_traits::Rational Rational;
28 typedef Nt_traits::Algebraic Algebraic;
29
30 typedef CGAL::Cartesian<Rational> Rat_kernel;
31 typedef CGAL::Cartesian<Algebraic> Alg_kernel;
32 typedef CGAL::Arr_Bezier_curve_traits_2<Rat_kernel, Alg_kernel, Nt_traits>
33 Traits_2;
34
35 typedef Rat_kernel::Point_2 Bezier_rat_point;
36 typedef Traits_2::Curve_2 Bezier_curve;
37 typedef Traits_2::X_monotone_curve_2 Bezier_X_monotone_curve;
38 typedef CGAL::Gps_traits_2<Traits_2> Bezier_traits;
39 typedef Bezier_traits::General_polygon_2 Bezier_polygon;
40 typedef Bezier_traits::General_polygon_with_holes_2 Bezier_polygon_with_holes;
41 typedef CGAL::General_polygon_set_2<Bezier_traits> Bezier_polygon_set;
42 typedef std::vector<Bezier_polygon> Bezier_polygon_vector;
43
read_bezier_curve(std::istream & is,bool aDoubleFormat)44 Bezier_curve read_bezier_curve(std::istream& is, bool aDoubleFormat)
45 {
46 // Read the number of control points.
47 unsigned int n;
48
49 is >> n;
50
51 // Read the control points.
52 std::vector<Bezier_rat_point> ctrl_pts;
53 for (unsigned int k = 0; k < n; ++k) {
54 Bezier_rat_point p;
55 if (aDoubleFormat) {
56 double x, y;
57 is >> x >> y;
58 p = Bezier_rat_point(x,y);
59 }
60 else
61 is >> p;
62
63 if ((k == 0) || (ctrl_pts[k-1] != p))
64 ctrl_pts.push_back(p);
65 }
66
67 return Bezier_curve(ctrl_pts.begin(), ctrl_pts.end());
68 }
69
read_bezier(char const * aFileName,Bezier_polygon_set & rSet)70 bool read_bezier(char const* aFileName, Bezier_polygon_set& rSet)
71 {
72
73 bool rOK = false;
74
75 std::ifstream in_file(aFileName);
76
77 if (in_file) {
78 try {
79 std::cout << "Reading " << aFileName << std::endl;
80
81 std::string format;
82 std::getline(in_file, format);
83
84 bool lDoubleFormat =
85 ((format.length() >= 6) && (format.substr(0,6) == "DOUBLE"));
86
87 // Red the number of bezier polygon with holes
88 unsigned int n_regions;
89 in_file >> n_regions;
90
91 for (unsigned int r = 0; r < n_regions; ++r) {
92 Bezier_polygon_vector polygons;
93
94 // Read the number of bezier curves.
95 unsigned int n_boundaries;
96 in_file >> n_boundaries;
97
98 for (unsigned int b = 0; b < n_boundaries; ++b) {
99 // Read the number of bezier curves.
100 unsigned int n_curves;
101 in_file >> n_curves;
102
103 // Read the curves one by one, and construct the general polygon these
104 // curve form (the outer boundary and the holes inside it).
105
106 std::list<Bezier_X_monotone_curve> xcvs;
107
108 for (unsigned int k = 0; k < n_curves; ++k) {
109 // Read the current curve and subdivide it into x-monotone subcurves.
110
111 std::list<CGAL::Object> x_objs;
112 std::list<CGAL::Object>::const_iterator xoit;
113 Bezier_X_monotone_curve xcv;
114 Bezier_traits traits;
115 Bezier_traits::Make_x_monotone_2 make_x_monotone =
116 traits.make_x_monotone_2_object();
117
118 Bezier_curve B = read_bezier_curve(in_file, lDoubleFormat);
119 if (B.number_of_control_points() >= 2) {
120
121 make_x_monotone(B, std::back_inserter(x_objs));
122
123 for (xoit = x_objs.begin(); xoit != x_objs.end(); ++xoit) {
124 if (CGAL::assign(xcv, *xoit))
125 xcvs.push_back(xcv);
126 }
127 }
128 }
129
130 Bezier_polygon pgn(xcvs.begin(), xcvs.end());
131
132 CGAL::Orientation orient = pgn.orientation();
133 std::cout << " Orientation: " << orient << std::endl;
134
135 if (((b == 0) && (orient == CGAL::CLOCKWISE)) ||
136 ((b > 0) && (orient == CGAL::COUNTERCLOCKWISE)))
137 {
138 std::cout << " Reversing orientation: " << std::endl;
139 pgn.reverse_orientation();
140 }
141
142 polygons.push_back(pgn);
143 }
144
145 if (polygons.size() > 0) {
146 Bezier_polygon_with_holes pwh(polygons.front());
147
148 if (polygons.size() > 1) {
149 Bezier_polygon_vector::const_iterator it;
150 for (it = std::next(polygons.begin());
151 it != polygons.end(); ++it)
152 pwh.add_hole(*it);
153 }
154
155 if (is_valid_polygon_with_holes(pwh, rSet.traits())) {
156 std::cout << " Inserting Bezier polygon with holes comprising "
157 << polygons.size() << " boundaries in total into set."
158 << std::endl;
159 rSet.join(pwh);
160 std::cout << " Done." << std::endl;
161 }
162 else
163 std::cout << " **** Bezier polygon with holes is NOT VALID ****"
164 << std::endl;
165 }
166
167 rOK = true;
168 }
169 }
170 catch(std::exception const& x) {
171 std::cout << "An exception ocurred during reading of Bezier polygon set:"
172 << x.what() << std::endl;
173 }
174 catch(...) {
175 std::cout << "An exception ocurred during reading of Bezier polygon set."
176 << std::endl;
177 }
178 }
179
180 return rOK;
181 }
182
183 // The main program.
main(int argc,char * argv[])184 int main(int argc, char* argv[])
185 {
186 const char* filename1 = (argc > 1) ? argv[1] : "char_g.bps";
187 const char* filename2 = (argc > 2) ? argv[2] : "char_m.bps";
188 const char* bop = (argc > 3) ? argv[3] : "i";
189
190 // Read the general polygons from the input files.
191 CGAL::Timer timer;
192 Bezier_polygon_set S1, S2;
193
194 timer.start();
195
196
197 if (! read_bezier(filename1, S1)) {
198 std::cerr << "Failed to read " << filename1 << " ..." << std::endl;
199 return 1;
200 }
201
202 if (! read_bezier(filename2, S2)) {
203 std::cerr << "Failed to read " << filename2 << " ..." << std::endl;
204 return 1;
205 }
206
207 timer.stop();
208 std::cout << "Constructed the input polygons in " << timer.time()
209 << " seconds." << std::endl << std::endl;
210
211 std::cout << "Starting boolean operation..." << std::endl;
212 timer.reset();
213 timer.start();
214 try {
215 switch (bop[0]) {
216 case 'i': S1.intersection(S2); break;
217 case 'u': S1.join(S2); break;
218 }
219 }
220 catch(std::exception const& x) {
221 std::cout << "An exception occurred during the Boolean operation:"
222 << x.what() << std::endl;
223 }
224 catch(...) {
225 std::cout << "An exception occurred during the Boolean operation."
226 << std::endl;
227 }
228 timer.stop();
229
230 std::cout << "The " << ( bop[0] == 'i' ? "intersection" : "union" )
231 << " computation took "
232 << timer.time() << " seconds." << std::endl;
233
234 return 0;
235 }
236
237 #endif
238