]> git.mxchange.org Git - flightgear.git/blob - Clipper/clipper.cxx
3ea78c200fd2f5888116632d97f73209873c0e12
[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_AREAS ) {
126                 polys_in.polys[area].push_back(poly);
127             } else {
128                 FG_LOG( FG_CLIPPER, FG_ALERT, "Polygon type out of range = " 
129                         << 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_diff, result_union, tmp;
147     polylist_iterator current, last;
148
149     FG_LOG( FG_CLIPPER, FG_INFO, "Running master clipper" );
150
151     accum.num_contours = 0;
152
153     cout << "  (" << min.x << "," << min.y << ") (" 
154          << max.x << "," << max.y << ")" << endl;
155
156     // set up clipping tile
157     v_list.vertex[0].x = min.x;
158     v_list.vertex[0].y = min.y;
159
160     v_list.vertex[1].x = max.x;
161     v_list.vertex[1].y = min.y;
162
163     v_list.vertex[2].x = max.x;
164     v_list.vertex[2].y = max.y;
165
166     v_list.vertex[3].x = min.x;
167     v_list.vertex[3].y = max.y;
168
169     v_list.num_vertices = 4;
170
171     polys_in.safety_base.num_contours = 0;
172     polys_in.safety_base.contour = NULL;
173     gpc_add_contour( &polys_in.safety_base, &v_list );
174
175     // process polygons in priority order
176     for ( int i = 0; i < FG_MAX_AREAS; ++i ) {
177
178         current = polys_in.polys[i].begin();
179         last = polys_in.polys[i].end();
180         for ( ; current != last; ++current ) {
181             FG_LOG( FG_CLIPPER, FG_DEBUG, get_area_name( (AreaType)i ) 
182                     << " = " << (*current)->contour->num_vertices );
183
184 #ifdef EXTRA_SAFETY_CLIP
185             // clip to base tile
186             gpc_polygon_clip(GPC_INT, &polys_in.safety_base, *current, &tmp);
187 #else
188             &tmp = *current;
189 #endif
190
191             // clip current polygon against previous higher priority
192             // stuff
193             if ( accum.num_contours == 0 ) {
194                 result_diff = tmp;
195                 result_union = tmp;
196             } else {
197                 gpc_polygon_clip(GPC_DIFF, &accum, &tmp, &result_diff);
198                 gpc_polygon_clip(GPC_UNION, &accum, &tmp, &result_union);
199             }
200             
201             polys_out.polys[i].push_back(&result_diff);
202             accum = result_union;
203         }
204     }
205
206     // finally, what ever is left over goes to base terrain
207
208     // clip to accum against original base tile
209     gpc_polygon_clip(GPC_DIFF, &polys_in.safety_base, &accum, 
210                      &polys_out.safety_base);
211
212     // tmp output accum
213     FILE *ofp= fopen("accum", "w");
214     gpc_write_polygon(ofp, &accum);
215
216     // tmp output safety_base
217     ofp= fopen("safety_base", "w");
218     gpc_write_polygon(ofp, &polys_out.safety_base);
219
220     return true;
221 }
222
223
224 // $Log$
225 // Revision 1.2  1999/03/13 23:51:33  curt
226 // Renamed main.cxx to testclipper.cxx
227 // Converted clipper routines to a class FGClipper.
228 //
229 // Revision 1.1  1999/03/01 15:39:39  curt
230 // Initial revision.
231 //