]> git.mxchange.org Git - flightgear.git/blob - Clipper/clipper.cxx
0a10f32768f7ad3ea5f0e9053e62151a9e5e92a3
[flightgear.git] / Clipper / clipper.cxx
1 // clipper.cxx -- top level routines to take a series of arbitrary areas and
2 //                produce a tight fitting puzzle pieces that combine to make a
3 //                tile
4 //
5 // Written by Curtis Olson, started February 1999.
6 //
7 // Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
8 //
9 // This program is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 //
23 // $Id$
24 // (Log is kept at end of this file)
25  
26
27
28 #include <Debug/logstream.hxx>
29 #include <Include/fg_constants.h>
30 #include <Misc/fgstream.hxx>
31 #include <Polygon/names.hxx>
32
33 #include "clipper.hxx"
34
35
36 // Constructor
37 FGClipper::FGClipper( void ) {
38 }
39
40
41 // Destructor
42 FGClipper::~FGClipper( void ) {
43 }
44
45
46 // Initialize Clipper (allocate and/or connect structures)
47 bool FGClipper::init() {
48     v_list.num_vertices = 0;
49     v_list.vertex = new gpc_vertex[FG_MAX_VERTICES];;
50
51     return true;
52 }
53
54
55 // Load a polygon definition file
56 bool FGClipper::load_polys(const string& path) {
57     string poly_name;
58     AreaType poly_type;
59     int contours, count, i, j;
60     double startx, starty, x, y, lastx, lasty;
61
62     FG_LOG( FG_CLIPPER, FG_INFO, "Loading " << path << " ..." );
63
64     fg_gzifstream in( path );
65
66     if ( !in ) {
67         FG_LOG( FG_CLIPPER, FG_ALERT, "Cannot open file: " << path );
68         exit(-1);
69     }
70
71     in >> skipcomment;
72     while ( !in.eof() ) {
73         in >> poly_name;
74         cout << "poly name = " << poly_name << endl;
75         poly_type = get_area_type( poly_name );
76         cout << "poly type (int) = " << (int)poly_type << endl;
77         in >> contours;
78         cout << "num contours = " << contours << endl;
79
80         for ( i = 0; i < contours; ++i ) {
81             in >> count;
82
83             if ( count < 3 ) {
84                 FG_LOG( FG_CLIPPER, FG_ALERT, 
85                         "Polygon with less than 3 data points." );
86                 exit(-1);
87             }
88
89             in >> startx;
90             in >> starty;
91             v_list.vertex[0].x = startx;
92             v_list.vertex[0].y = starty;
93             FG_LOG( FG_CLIPPER, FG_BULK, "0 = " 
94                     << startx << ", " << starty );
95
96             for ( j = 1; j < count - 1; ++j ) {
97                 in >> x;
98                 in >> y;
99                 v_list.vertex[j].x = x;
100                 v_list.vertex[j].y = y;
101                 FG_LOG( FG_CLIPPER, FG_BULK, j << " = " << x << ", " << y );
102             }
103             v_list.num_vertices = count - 1;
104
105             in >> lastx;
106             in >> lasty;
107
108             if ( (fabs(startx - lastx) < FG_EPSILON) 
109                  && (fabs(starty - lasty) < FG_EPSILON) ) {
110                 // last point same as first, discard
111             } else {
112                 v_list.vertex[count - 1].x = lastx;
113                 v_list.vertex[count - 1].y = lasty;
114                 ++v_list.num_vertices;
115                 FG_LOG( FG_CLIPPER, FG_BULK, count - 1 << " = " 
116                         << lastx << ", " << lasty );
117             }
118
119             gpc_polygon *poly = new gpc_polygon;
120             poly->num_contours = 0;
121             poly->contour = NULL;
122             gpc_add_contour( poly, &v_list );
123
124             int area = (int)poly_type;
125             if ( area < FG_MAX_AREA_TYPES ) {
126                 polys_in.polys[area].push_back(poly);
127             } else {
128                 FG_LOG( FG_CLIPPER, FG_ALERT, "Polygon type out of range = " 
129                         << (int)poly_type);
130                 exit(-1);
131             }
132         }
133
134         in >> skipcomment;
135     }
136
137     // FILE *ofp= fopen("outfile", "w");
138     // gpc_write_polygon(ofp, &polys.landuse);
139
140     return true;
141 }
142
143
144 // Do actually clipping work
145 bool FGClipper::clip_all(const point2d& min, const point2d& max) {
146     gpc_polygon accum, result_union, tmp;
147     gpc_polygon *result_diff;
148     gpcpoly_iterator current, last;
149
150     FG_LOG( FG_CLIPPER, FG_INFO, "Running master clipper" );
151
152     accum.num_contours = 0;
153
154     cout << "  (" << min.x << "," << min.y << ") (" 
155          << max.x << "," << max.y << ")" << endl;
156
157     // set up clipping tile
158     v_list.vertex[0].x = min.x;
159     v_list.vertex[0].y = min.y;
160
161     v_list.vertex[1].x = max.x;
162     v_list.vertex[1].y = min.y;
163
164     v_list.vertex[2].x = max.x;
165     v_list.vertex[2].y = max.y;
166
167     v_list.vertex[3].x = min.x;
168     v_list.vertex[3].y = max.y;
169
170     v_list.num_vertices = 4;
171
172     polys_in.safety_base.num_contours = 0;
173     polys_in.safety_base.contour = NULL;
174     gpc_add_contour( &polys_in.safety_base, &v_list );
175
176     // process polygons in priority order
177     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
178
179         current = polys_in.polys[i].begin();
180         last = polys_in.polys[i].end();
181         for ( ; current != last; ++current ) {
182             FG_LOG( FG_CLIPPER, FG_DEBUG, get_area_name( (AreaType)i ) 
183                     << " = " << (*current)->contour->num_vertices );
184
185 #ifdef EXTRA_SAFETY_CLIP
186             // clip to base tile
187             gpc_polygon_clip(GPC_INT, *current, &polys_in.safety_base, &tmp);
188 #else
189             tmp = *current;
190 #endif
191
192             // clip current polygon against previous higher priority
193             // stuff
194             result_diff = new gpc_polygon;
195             result_diff->num_contours = 0;
196             result_diff->contour = NULL;
197
198             if ( accum.num_contours == 0 ) {
199                 *result_diff = tmp;
200                 result_union = tmp;
201             } else {
202                 gpc_polygon_clip(GPC_DIFF, &tmp, &accum, result_diff);
203                 gpc_polygon_clip(GPC_UNION, &tmp, &accum, &result_union);
204             }
205
206             /*
207             cout << "original contours = " << tmp.num_contours << endl;
208
209             for ( int j = 0; j < tmp.num_contours; j++ ) {
210                 for (int k = 0;k < tmp.contour[j].num_vertices;k++ ) {
211                     cout << tmp.contour[j].vertex[k].x << ","
212                          << tmp.contour[j].vertex[k].y << endl;
213                 }
214             }
215
216             cout << "clipped contours = " << result_diff->num_contours << endl;
217
218             for ( int j = 0; j < result_diff->num_contours; j++ ) {
219                 for (int k = 0;k < result_diff->contour[j].num_vertices;k++ ) {
220                     cout << result_diff->contour[j].vertex[k].x << ","
221                          << result_diff->contour[j].vertex[k].y << endl;
222                 }
223             }
224             */
225
226             polys_clipped.polys[i].push_back(result_diff);
227             accum = result_union;
228         }
229     }
230
231     // finally, what ever is left over goes to base terrain
232
233     // clip to accum against original base tile
234     gpc_polygon_clip(GPC_DIFF, &polys_in.safety_base, &accum, 
235                      &polys_clipped.safety_base);
236
237     // tmp output accum
238     FILE *ofp= fopen("accum", "w");
239     gpc_write_polygon(ofp, &accum);
240
241     // tmp output safety_base
242     ofp= fopen("safety_base", "w");
243     gpc_write_polygon(ofp, &polys_clipped.safety_base);
244
245     return true;
246 }
247
248
249 // $Log$
250 // Revision 1.4  1999/03/19 00:26:18  curt
251 // Fixed a clipping bug (polygons specified in wrong order).
252 // Touched up a few compiler warnings.
253 //
254 // Revision 1.3  1999/03/17 23:48:58  curt
255 // minor renaming and a bit of rearranging.
256 //
257 // Revision 1.2  1999/03/13 23:51:33  curt
258 // Renamed main.cxx to testclipper.cxx
259 // Converted clipper routines to a class FGClipper.
260 //
261 // Revision 1.1  1999/03/01 15:39:39  curt
262 // Initial revision.
263 //