]> git.mxchange.org Git - flightgear.git/blob - Tools/Prep/ShapeFile/main.cxx
Fixed a small bug which cropped up with the new gpc hole interface.
[flightgear.git] / Tools / Prep / ShapeFile / main.cxx
1 // main.cxx -- process shapefiles and extract polygon outlines,
2 //             clipping against and sorting them into the revelant
3 //             tiles.
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  
25
26 // Include Geographic Foundation Classes library
27
28 // libgfc.a includes need this bit o' strangeness
29 #if defined ( linux )
30 #  define _LINUX_
31 #endif
32 #include <gfc/gadt_polygon.h>
33 #include <gfc/gdbf.h>
34 #include <gfc/gshapefile.h>
35 #undef E
36 #undef DEG_TO_RAD
37 #undef RAD_TO_DEG
38
39 // include Generic Polygon Clipping Library
40 extern "C" {
41 #include <gpc.h>
42 }
43
44 #include <Include/compiler.h>
45
46 #include STL_STRING
47
48 #include <Debug/logstream.hxx>
49
50 #include <Polygon/index.hxx>
51 #include <Polygon/names.hxx>
52 #include "shape.hxx"
53
54
55 // return the type of the shapefile record
56 AreaType get_shapefile_type(GDBFile *dbf, int rec) {
57     // GDBFieldDesc *fdesc[128];        // 128 is an arbitrary number here
58     GDBFValue *fields;          //an array of field values
59     char* dbf_rec;              //a record containing all the fields
60
61     // grab the meta-information for all the fields
62     // this applies to all the records in the DBF file.
63     // for ( int i = 0; i < dbf->numFields(); i++ ) {
64     //   fdesc[i] = dbf->getFieldDesc(i);
65     //   cout << i << ") " << fdesc[i]->name << endl;
66     // }
67
68     // this is the whole name record
69     dbf_rec = dbf->getRecord( rec );
70
71     // parse it into individual fields
72     if ( dbf_rec ) {
73         fields = dbf->recordDeform( dbf_rec );
74     } else {
75         return UnknownArea;
76     }
77
78     string area = fields[4].str_v;
79     // strip leading spaces
80     while ( area[0] == ' ' ) {
81         area = area.substr(1, area.length() - 1);
82     }
83     // strip trailing spaces
84     while ( area[area.length() - 1] == ' ' ) {
85         area = area.substr(0, area.length() - 1);
86     }
87     // strip other junk encountered
88     while ( (int)area[area.length() - 1] == 9 ) {
89         area = area.substr(0, area.length() - 1);
90     }
91
92     return get_area_type( area );
93 }
94
95
96 int main( int argc, char **argv ) {
97     gpc_polygon gpc_shape;
98     int i, j;
99
100     fglog().setLogLevels( FG_ALL, FG_DEBUG );
101
102     if ( argc < 3 ) {
103         FG_LOG( FG_GENERAL, FG_ALERT, "Usage: " << argv[0] 
104                 << " <shape_file> <work_dir> [ area_string ]" );
105         exit(-1);
106     }
107
108     FG_LOG( FG_GENERAL, FG_DEBUG, "Opening " << argv[1] << " for reading." );
109
110     // make work directory
111     string work_dir = argv[2];
112     string command = "mkdir -p " + work_dir;
113     system( command.c_str() );
114
115     // allow us to override the area type from the command line.  All
116     // polygons in the processed shape file will be assigned this area
117     // type
118     string force_area_type = "";
119     if ( argc == 4 ) {
120         force_area_type = argv[3];
121     }
122         
123     // initialize persistant polygon counter
124     string counter_file = work_dir + "/../work.counter";
125     poly_index_init( counter_file );
126
127     // initialize structure for building gpc polygons
128     shape_utils_init();
129
130     GShapeFile * sf = new GShapeFile( argv[1] );
131     GDBFile *dbf = new GDBFile( argv[1] );
132     string path = argv[2];
133
134     GPolygon shape;
135     double  *coords; // in decimal degrees
136     int n_vertices;
137
138     FG_LOG( FG_GENERAL, FG_INFO, "shape file records = " << sf->numRecords() );
139
140     GShapeFile::ShapeType t = sf->shapeType();
141     if ( t != GShapeFile::av_Polygon ) {
142         FG_LOG( FG_GENERAL, FG_ALERT, "Can't handle non-polygon shape files" );
143         exit(-1);
144     }
145
146     for ( i = 0; i < sf->numRecords(); i++ ) {
147         //fetch i-th record (shape)
148         sf->getShapeRec(i, &shape); 
149         FG_LOG( FG_GENERAL, FG_DEBUG, "Record = " << i << "  rings = " 
150                 << shape.numRings() );
151
152         AreaType area;
153         if ( force_area_type.length() == 0 ) {
154             area = get_shapefile_type(dbf, i);
155             FG_LOG( FG_GENERAL, FG_DEBUG, "area type = " << get_area_name(area) 
156                     << " (" << (int)area << ")" );
157         }
158
159         FG_LOG( FG_GENERAL, FG_INFO, "  record = " << i 
160                 << " ring = " << 0 );
161
162         if ( force_area_type.length() > 0 ) {
163             // interior of polygon is assigned to force_area_type,
164             // holes are maintained
165
166             area = get_area_type( force_area_type );
167
168             init_shape(&gpc_shape);
169             for (  j = 0; j < shape.numRings(); j++ ) {
170                 n_vertices = shape.getRing(j, coords);
171                 add_to_shape(n_vertices, coords, &gpc_shape);
172             }
173             process_shape(path, area, &gpc_shape);
174             free_shape(&gpc_shape);
175         } else if ( area == MarshArea ) {
176             // interior of polygon is marsh, holes are water
177
178             // do main outline first
179             init_shape(&gpc_shape);
180             n_vertices = shape.getRing(0, coords);
181             add_to_shape(n_vertices, coords, &gpc_shape);
182             process_shape(path, area, &gpc_shape);
183             free_shape(&gpc_shape);
184
185             // do lakes (individually) next
186             for (  j = 1; j < shape.numRings(); j++ ) {
187                 FG_LOG( FG_GENERAL, FG_INFO, "  record = " << i 
188                         << " ring = " << j );
189                 init_shape(&gpc_shape);
190                 n_vertices = shape.getRing(j, coords);
191                 add_to_shape(n_vertices, coords, &gpc_shape);
192                 process_shape(path, LakeArea, &gpc_shape);
193                 free_shape(&gpc_shape);
194             }
195         } else if ( area == OceanArea ) {
196             // interior of polygon is ocean, holes are islands
197
198             init_shape(&gpc_shape);
199             for (  j = 0; j < shape.numRings(); j++ ) {
200                 n_vertices = shape.getRing(j, coords);
201                 add_to_shape(n_vertices, coords, &gpc_shape);
202             }
203             process_shape(path, area, &gpc_shape);
204             free_shape(&gpc_shape);
205         } else if ( area == LakeArea ) {
206             // interior of polygon is lake, holes are islands
207
208             init_shape(&gpc_shape);
209             for (  j = 0; j < shape.numRings(); j++ ) {
210                 n_vertices = shape.getRing(j, coords);
211                 add_to_shape(n_vertices, coords, &gpc_shape);
212             }
213             process_shape(path, area, &gpc_shape);
214             free_shape(&gpc_shape);
215         } else if ( area == DryLakeArea ) {
216             // interior of polygon is dry lake, holes are islands
217
218             init_shape(&gpc_shape);
219             for (  j = 0; j < shape.numRings(); j++ ) {
220                 n_vertices = shape.getRing(j, coords);
221                 add_to_shape(n_vertices, coords, &gpc_shape);
222             }
223             process_shape(path, area, &gpc_shape);
224             free_shape(&gpc_shape);
225         } else if ( area == IntLakeArea ) {
226             // interior of polygon is intermittent lake, holes are islands
227
228             init_shape(&gpc_shape);
229             for (  j = 0; j < shape.numRings(); j++ ) {
230                 n_vertices = shape.getRing(j, coords);
231                 add_to_shape(n_vertices, coords, &gpc_shape);
232             }
233             process_shape(path, area, &gpc_shape);
234             free_shape(&gpc_shape);
235         } else if ( area == ReservoirArea ) {
236             // interior of polygon is reservoir, holes are islands
237
238             init_shape(&gpc_shape);
239             for (  j = 0; j < shape.numRings(); j++ ) {
240                 n_vertices = shape.getRing(j, coords);
241                 add_to_shape(n_vertices, coords, &gpc_shape);
242             }
243             process_shape(path, area, &gpc_shape);
244             free_shape(&gpc_shape);
245         } else if ( area == IntReservoirArea ) {
246             // interior of polygon is intermittent reservoir, holes are islands
247
248             init_shape(&gpc_shape);
249             for (  j = 0; j < shape.numRings(); j++ ) {
250                 n_vertices = shape.getRing(j, coords);
251                 add_to_shape(n_vertices, coords, &gpc_shape);
252             }
253             process_shape(path, area, &gpc_shape);
254             free_shape(&gpc_shape);
255         } else if ( area == StreamArea ) {
256             // interior of polygon is stream, holes are islands
257
258             init_shape(&gpc_shape);
259             for (  j = 0; j < shape.numRings(); j++ ) {
260                 n_vertices = shape.getRing(j, coords);
261                 add_to_shape(n_vertices, coords, &gpc_shape);
262             }
263             process_shape(path, area, &gpc_shape);
264             free_shape(&gpc_shape);
265         } else if ( area == CanalArea ) {
266             // interior of polygon is canal, holes are islands
267
268             init_shape(&gpc_shape);
269             for (  j = 0; j < shape.numRings(); j++ ) {
270                 n_vertices = shape.getRing(j, coords);
271                 add_to_shape(n_vertices, coords, &gpc_shape);
272             }
273             process_shape(path, area, &gpc_shape);
274             free_shape(&gpc_shape);
275         } else if ( area == GlacierArea ) {
276             // interior of polygon is glacier, holes are dry land
277
278             init_shape(&gpc_shape);
279             for (  j = 0; j < shape.numRings(); j++ ) {
280                 n_vertices = shape.getRing(j, coords);
281                 add_to_shape(n_vertices, coords, &gpc_shape);
282             }
283             process_shape(path, area, &gpc_shape);
284             free_shape(&gpc_shape);
285         } else if ( area == VoidArea ) {
286             // interior is ????
287
288             // skip for now
289             FG_LOG(  FG_GENERAL, FG_ALERT, "Void area ... SKIPPING!" );
290
291             if ( shape.numRings() > 1 ) {
292                 FG_LOG(  FG_GENERAL, FG_ALERT, "  Void area with holes!" );
293                 // exit(-1);
294             }
295
296             init_shape(&gpc_shape);
297             for (  j = 0; j < shape.numRings(); j++ ) {
298                 n_vertices = shape.getRing(j, coords);
299                 add_to_shape(n_vertices, coords, &gpc_shape);
300             }
301             // process_shape(path, area, &gpc_shape);
302             free_shape(&gpc_shape);
303         } else if ( area == NullArea ) {
304             // interior is ????
305
306             // skip for now
307             FG_LOG(  FG_GENERAL, FG_ALERT, "Null area ... SKIPPING!" );
308
309             if ( shape.numRings() > 1 ) {
310                 FG_LOG(  FG_GENERAL, FG_ALERT, "  Null area with holes!" );
311                 // exit(-1);
312             }
313
314             init_shape(&gpc_shape);
315             for (  j = 0; j < shape.numRings(); j++ ) {
316                 n_vertices = shape.getRing(j, coords);
317                 add_to_shape(n_vertices, coords, &gpc_shape);
318             }
319             // process_shape(path, area, &gpc_shape);
320             free_shape(&gpc_shape);
321         } else {
322             FG_LOG(  FG_GENERAL, FG_ALERT, "Uknown area!" );
323             exit(-1);
324         }
325     }
326
327     return 0;
328 }
329
330