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
5 // Written by Curtis Olson, started February 1999.
7 // Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
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.
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.
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.
24 // (Log is kept at end of this file)
28 #include <Debug/logstream.hxx>
29 #include <Include/fg_constants.h>
30 #include <Misc/fgstream.hxx>
31 #include <Polygon/names.hxx>
33 #include "clipper.hxx"
37 FGClipper::FGClipper( void ) {
42 FGClipper::~FGClipper( void ) {
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];;
55 // Load a polygon definition file
56 bool FGClipper::load_polys(const string& path) {
59 int contours, count, i, j;
60 double startx, starty, x, y, lastx, lasty;
62 FG_LOG( FG_CLIPPER, FG_INFO, "Loading " << path << " ..." );
64 fg_gzifstream in( path );
67 FG_LOG( FG_CLIPPER, FG_ALERT, "Cannot open file: " << path );
74 cout << "poly name = " << poly_name << endl;
75 poly_type = get_area_type( poly_name );
76 cout << "poly type (int) = " << (int)poly_type << endl;
78 cout << "num contours = " << contours << endl;
80 for ( i = 0; i < contours; ++i ) {
84 FG_LOG( FG_CLIPPER, FG_ALERT,
85 "Polygon with less than 3 data points." );
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 );
96 for ( j = 1; j < count - 1; ++j ) {
99 v_list.vertex[j].x = x;
100 v_list.vertex[j].y = y;
101 FG_LOG( FG_CLIPPER, FG_BULK, j << " = " << x << ", " << y );
103 v_list.num_vertices = count - 1;
108 if ( (fabs(startx - lastx) < FG_EPSILON)
109 && (fabs(starty - lasty) < FG_EPSILON) ) {
110 // last point same as first, discard
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 );
119 gpc_polygon *poly = new gpc_polygon;
120 poly->num_contours = 0;
121 poly->contour = NULL;
122 gpc_add_contour( poly, &v_list );
124 int area = (int)poly_type;
125 if ( area < FG_MAX_AREA_TYPES ) {
126 polys_in.polys[area].push_back(poly);
128 FG_LOG( FG_CLIPPER, FG_ALERT, "Polygon type out of range = "
137 // FILE *ofp= fopen("outfile", "w");
138 // gpc_write_polygon(ofp, &polys.landuse);
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;
150 FG_LOG( FG_CLIPPER, FG_INFO, "Running master clipper" );
152 accum.num_contours = 0;
154 cout << " (" << min.x << "," << min.y << ") ("
155 << max.x << "," << max.y << ")" << endl;
157 // set up clipping tile
158 v_list.vertex[0].x = min.x;
159 v_list.vertex[0].y = min.y;
161 v_list.vertex[1].x = max.x;
162 v_list.vertex[1].y = min.y;
164 v_list.vertex[2].x = max.x;
165 v_list.vertex[2].y = max.y;
167 v_list.vertex[3].x = min.x;
168 v_list.vertex[3].y = max.y;
170 v_list.num_vertices = 4;
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 );
176 // process polygons in priority order
177 for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
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 );
185 #ifdef EXTRA_SAFETY_CLIP
187 gpc_polygon_clip(GPC_INT, *current, &polys_in.safety_base, &tmp);
192 // clip current polygon against previous higher priority
194 result_diff = new gpc_polygon;
195 result_diff->num_contours = 0;
196 result_diff->contour = NULL;
198 if ( accum.num_contours == 0 ) {
202 gpc_polygon_clip(GPC_DIFF, &tmp, &accum, result_diff);
203 gpc_polygon_clip(GPC_UNION, &tmp, &accum, &result_union);
207 cout << "original contours = " << tmp.num_contours << endl;
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;
216 cout << "clipped contours = " << result_diff->num_contours << endl;
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;
226 // only add to output list if the clip left us with a polygon
227 if ( result_diff->num_contours > 0 ) {
228 polys_clipped.polys[i].push_back(result_diff);
230 accum = result_union;
234 // finally, what ever is left over goes to base terrain
236 // clip to accum against original base tile
237 gpc_polygon_clip(GPC_DIFF, &polys_in.safety_base, &accum,
238 &polys_clipped.safety_base);
241 FILE *ofp= fopen("accum", "w");
242 gpc_write_polygon(ofp, &accum);
244 // tmp output safety_base
245 ofp= fopen("safety_base", "w");
246 gpc_write_polygon(ofp, &polys_clipped.safety_base);
253 // Revision 1.5 1999/03/19 22:28:46 curt
254 // Only add non-null polygons to output list.
256 // Revision 1.4 1999/03/19 00:26:18 curt
257 // Fixed a clipping bug (polygons specified in wrong order).
258 // Touched up a few compiler warnings.
260 // Revision 1.3 1999/03/17 23:48:58 curt
261 // minor renaming and a bit of rearranging.
263 // Revision 1.2 1999/03/13 23:51:33 curt
264 // Renamed main.cxx to testclipper.cxx
265 // Converted clipper routines to a class FGClipper.
267 // Revision 1.1 1999/03/01 15:39:39 curt