]> git.mxchange.org Git - flightgear.git/blob - Clipper/clipper.cxx
e4aaa76f0b424404fe0fd7f2385bf434bc559124
[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 "clipper.hxx"
29
30 #include <Debug/logstream.hxx>
31 #include <Include/fg_constants.h>
32 #include <Misc/fgstream.hxx>
33 #include <Polygon/names.hxx>
34
35
36 #define EXTRA_SAFETY_CLIP
37
38 #define FG_MAX_VERTICES 100000
39
40 static gpc_vertex_list v_list;
41 // static gpc_polygon poly;
42 static FGPolyList polys_in, polys_out;
43
44
45 // Initialize Clipper (allocate and/or connect structures)
46 bool fgClipperInit() {
47     v_list.num_vertices = 0;
48     v_list.vertex = new gpc_vertex[FG_MAX_VERTICES];;
49
50     return true;
51 }
52
53
54 // Load a polygon definition file
55 bool fgClipperLoadPolygons(const string& path) {
56     string poly_name;
57     AreaType poly_type;
58     int contours, count, i, j;
59     double startx, starty, x, y, lastx, lasty;
60
61     FG_LOG( FG_CLIPPER, FG_INFO, "Loading " << path << " ..." );
62
63     fg_gzifstream in( path );
64
65     if ( !in ) {
66         FG_LOG( FG_CLIPPER, FG_ALERT, "Cannot open file: " << path );
67         exit(-1);
68     }
69
70     in >> skipcomment;
71     while ( !in.eof() ) {
72         in >> poly_name;
73         cout << "poly name = " << poly_name << endl;
74         poly_type = get_area_type( poly_name );
75         cout << "poly type (int) = " << (int)poly_type << endl;
76         in >> contours;
77         cout << "num contours = " << contours << endl;
78
79         for ( i = 0; i < contours; ++i ) {
80             in >> count;
81
82             if ( count < 3 ) {
83                 FG_LOG( FG_CLIPPER, FG_ALERT, 
84                         "Polygon with less than 3 data points." );
85                 exit(-1);
86             }
87
88             in >> startx;
89             in >> starty;
90             v_list.vertex[0].x = startx;
91             v_list.vertex[0].y = starty;
92             FG_LOG( FG_CLIPPER, FG_BULK, "0 = " 
93                     << startx << ", " << starty );
94
95             for ( j = 1; j < count - 1; ++j ) {
96                 in >> x;
97                 in >> y;
98                 v_list.vertex[j].x = x;
99                 v_list.vertex[j].y = y;
100                 FG_LOG( FG_CLIPPER, FG_BULK, j << " = " << x << ", " << y );
101             }
102             v_list.num_vertices = count - 1;
103
104             in >> lastx;
105             in >> lasty;
106
107             if ( (fabs(startx - lastx) < FG_EPSILON) 
108                  && (fabs(starty - lasty) < FG_EPSILON) ) {
109                 // last point same as first, discard
110             } else {
111                 v_list.vertex[count - 1].x = lastx;
112                 v_list.vertex[count - 1].y = lasty;
113                 ++v_list.num_vertices;
114                 FG_LOG( FG_CLIPPER, FG_BULK, count - 1 << " = " 
115                         << lastx << ", " << lasty );
116             }
117
118             gpc_polygon *poly = new gpc_polygon;
119             poly->num_contours = 0;
120             poly->contour = NULL;
121             gpc_add_contour( poly, &v_list );
122
123             int area = (int)poly_type;
124             if ( area < FG_MAX_AREAS ) {
125                 polys_in.polys[area].push_back(poly);
126             } else {
127                 FG_LOG( FG_CLIPPER, FG_ALERT, "Polygon type out of range = " 
128                         << poly_type);
129                 exit(-1);
130             }
131         }
132
133         in >> skipcomment;
134     }
135
136     // FILE *ofp= fopen("outfile", "w");
137     // gpc_write_polygon(ofp, &polys.landuse);
138
139     return true;
140 }
141
142
143 // Do actually clipping work
144 bool fgClipperMaster(const point2d& min, const point2d& max) {
145     gpc_polygon accum, result_diff, result_union, tmp;
146     polylist_iterator current, last;
147
148     FG_LOG( FG_CLIPPER, FG_INFO, "Running master clipper" );
149
150     accum.num_contours = 0;
151
152     cout << "  (" << min.x << "," << min.y << ") (" 
153          << max.x << "," << max.y << ")" << endl;
154
155     // set up clipping tile
156     v_list.vertex[0].x = min.x;
157     v_list.vertex[0].y = min.y;
158
159     v_list.vertex[1].x = max.x;
160     v_list.vertex[1].y = min.y;
161
162     v_list.vertex[2].x = max.x;
163     v_list.vertex[2].y = max.y;
164
165     v_list.vertex[3].x = min.x;
166     v_list.vertex[3].y = max.y;
167
168     v_list.num_vertices = 4;
169
170     polys_in.safety_base.num_contours = 0;
171     polys_in.safety_base.contour = NULL;
172     gpc_add_contour( &polys_in.safety_base, &v_list );
173
174     // process polygons in priority order
175     for ( int i = 0; i < FG_MAX_AREAS; ++i ) {
176
177         current = polys_in.polys[i].begin();
178         last = polys_in.polys[i].end();
179         for ( ; current != last; ++current ) {
180             FG_LOG( FG_CLIPPER, FG_DEBUG, get_area_name( (AreaType)i ) 
181                     << " = " << (*current)->contour->num_vertices );
182
183 #ifdef EXTRA_SAFETY_CLIP
184             // clip to base tile
185             gpc_polygon_clip(GPC_INT, &polys_in.safety_base, *current, &tmp);
186 #else
187             &tmp = *current;
188 #endif
189
190             // clip current polygon against previous higher priority
191             // stuff
192             if ( accum.num_contours == 0 ) {
193                 result_diff = tmp;
194                 result_union = tmp;
195             } else {
196                 gpc_polygon_clip(GPC_DIFF, &accum, &tmp, &result_diff);
197                 gpc_polygon_clip(GPC_UNION, &accum, &tmp, &result_union);
198             }
199             
200             polys_out.polys[i].push_back(&result_diff);
201             accum = result_union;
202         }
203     }
204
205     // finally, what ever is left over goes to base terrain
206
207     // clip to accum against original base tile
208     gpc_polygon_clip(GPC_DIFF, &polys_in.safety_base, &accum, 
209                      &polys_out.safety_base);
210
211     // tmp output accum
212     FILE *ofp= fopen("accum", "w");
213     gpc_write_polygon(ofp, &accum);
214
215     // tmp output safety_base
216     ofp= fopen("safety_base", "w");
217     gpc_write_polygon(ofp, &polys_out.safety_base);
218
219     return true;
220 }
221
222
223 // $Log$
224 // Revision 1.1  1999/03/01 15:39:39  curt
225 // Initial revision.
226 //