]> git.mxchange.org Git - flightgear.git/blob - Tools/Prep/ShapeFile/main.cxx
Updated to create polygons with properly marked holes.
[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>" );
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     // initialize persistant polygon counter
116     string counter_file = work_dir + "/../work.counter";
117     poly_index_init( counter_file );
118
119     // initialize structure for building gpc polygons
120     shape_utils_init();
121
122     GShapeFile * sf = new GShapeFile( argv[1] );
123     GDBFile *dbf = new GDBFile( argv[1] );
124     string path = argv[2];
125
126     GPolygon shape;
127     double  *coords; // in decimal degrees
128     int n_vertices;
129
130     FG_LOG( FG_GENERAL, FG_INFO, "shape file records = " << sf->numRecords() );
131
132     GShapeFile::ShapeType t = sf->shapeType();
133     if ( t != GShapeFile::av_Polygon ) {
134         FG_LOG( FG_GENERAL, FG_ALERT, "Can't handle non-polygon shape files" );
135         exit(-1);
136     }
137
138     for ( i = 0; i < sf->numRecords(); i++ ) {
139         //fetch i-th record (shape)
140         sf->getShapeRec(i, &shape); 
141         FG_LOG( FG_GENERAL, FG_DEBUG, "Record = " << i << "  rings = " 
142                 << shape.numRings() );
143
144         AreaType area = get_shapefile_type(dbf, i);
145         FG_LOG( FG_GENERAL, FG_DEBUG, "area type = " << get_area_name(area) 
146                 << " (" << (int)area << ")" );
147
148         FG_LOG( FG_GENERAL, FG_INFO, "  record = " << i 
149                 << " ring = " << 0 );
150
151         if ( area == MarshArea ) {
152             // interior of polygon is marsh, holes are water
153
154             // do main outline first
155             init_shape(&gpc_shape);
156             n_vertices = shape.getRing(0, coords);
157             add_to_shape(n_vertices, coords, &gpc_shape);
158             process_shape(path, area, &gpc_shape);
159             free_shape(&gpc_shape);
160
161             // do lakes (individually) next
162             for (  j = 1; j < shape.numRings(); j++ ) {
163                 FG_LOG( FG_GENERAL, FG_INFO, "  record = " << i 
164                         << " ring = " << j );
165                 init_shape(&gpc_shape);
166                 n_vertices = shape.getRing(j, coords);
167                 add_to_shape(n_vertices, coords, &gpc_shape);
168                 process_shape(path, LakeArea, &gpc_shape);
169                 free_shape(&gpc_shape);
170             }
171         } else if ( area == OceanArea ) {
172             // interior of polygon is ocean, holes are islands
173
174             init_shape(&gpc_shape);
175             for (  j = 0; j < shape.numRings(); j++ ) {
176                 n_vertices = shape.getRing(j, coords);
177                 add_to_shape(n_vertices, coords, &gpc_shape);
178             }
179             process_shape(path, area, &gpc_shape);
180             free_shape(&gpc_shape);
181         } else if ( area == LakeArea ) {
182             // interior of polygon is lake, holes are islands
183
184             init_shape(&gpc_shape);
185             for (  j = 0; j < shape.numRings(); j++ ) {
186                 n_vertices = shape.getRing(j, coords);
187                 add_to_shape(n_vertices, coords, &gpc_shape);
188             }
189             process_shape(path, area, &gpc_shape);
190             free_shape(&gpc_shape);
191         } else if ( area == DryLakeArea ) {
192             // interior of polygon is dry lake, holes are islands
193
194             init_shape(&gpc_shape);
195             for (  j = 0; j < shape.numRings(); j++ ) {
196                 n_vertices = shape.getRing(j, coords);
197                 add_to_shape(n_vertices, coords, &gpc_shape);
198             }
199             process_shape(path, area, &gpc_shape);
200             free_shape(&gpc_shape);
201         } else if ( area == IntLakeArea ) {
202             // interior of polygon is intermittent lake, holes are islands
203
204             init_shape(&gpc_shape);
205             for (  j = 0; j < shape.numRings(); j++ ) {
206                 n_vertices = shape.getRing(j, coords);
207                 add_to_shape(n_vertices, coords, &gpc_shape);
208             }
209             process_shape(path, area, &gpc_shape);
210             free_shape(&gpc_shape);
211         } else if ( area == ReservoirArea ) {
212             // interior of polygon is reservoir, holes are islands
213
214             init_shape(&gpc_shape);
215             for (  j = 0; j < shape.numRings(); j++ ) {
216                 n_vertices = shape.getRing(j, coords);
217                 add_to_shape(n_vertices, coords, &gpc_shape);
218             }
219             process_shape(path, area, &gpc_shape);
220             free_shape(&gpc_shape);
221         } else if ( area == IntReservoirArea ) {
222             // interior of polygon is intermittent reservoir, holes are islands
223
224             init_shape(&gpc_shape);
225             for (  j = 0; j < shape.numRings(); j++ ) {
226                 n_vertices = shape.getRing(j, coords);
227                 add_to_shape(n_vertices, coords, &gpc_shape);
228             }
229             process_shape(path, area, &gpc_shape);
230             free_shape(&gpc_shape);
231         } else if ( area == StreamArea ) {
232             // interior of polygon is stream, holes are islands
233
234             init_shape(&gpc_shape);
235             for (  j = 0; j < shape.numRings(); j++ ) {
236                 n_vertices = shape.getRing(j, coords);
237                 add_to_shape(n_vertices, coords, &gpc_shape);
238             }
239             process_shape(path, area, &gpc_shape);
240             free_shape(&gpc_shape);
241         } else if ( area == CanalArea ) {
242             // interior of polygon is canal, holes are islands
243
244             init_shape(&gpc_shape);
245             for (  j = 0; j < shape.numRings(); j++ ) {
246                 n_vertices = shape.getRing(j, coords);
247                 add_to_shape(n_vertices, coords, &gpc_shape);
248             }
249             process_shape(path, area, &gpc_shape);
250             free_shape(&gpc_shape);
251         } else if ( area == GlacierArea ) {
252             // interior of polygon is glacier, holes are dry land
253
254             init_shape(&gpc_shape);
255             for (  j = 0; j < shape.numRings(); j++ ) {
256                 n_vertices = shape.getRing(j, coords);
257                 add_to_shape(n_vertices, coords, &gpc_shape);
258             }
259             process_shape(path, area, &gpc_shape);
260             free_shape(&gpc_shape);
261         } else if ( area == VoidArea ) {
262             // interior is ????
263
264             // skip for now
265             FG_LOG(  FG_GENERAL, FG_ALERT, "Void area ... SKIPPING!" );
266
267             if ( shape.numRings() > 1 ) {
268                 FG_LOG(  FG_GENERAL, FG_ALERT, "  Void area with holes!" );
269                 // exit(-1);
270             }
271
272             init_shape(&gpc_shape);
273             for (  j = 0; j < shape.numRings(); j++ ) {
274                 n_vertices = shape.getRing(j, coords);
275                 add_to_shape(n_vertices, coords, &gpc_shape);
276             }
277             // process_shape(path, area, &gpc_shape);
278             free_shape(&gpc_shape);
279         } else if ( area == NullArea ) {
280             // interior is ????
281
282             // skip for now
283             FG_LOG(  FG_GENERAL, FG_ALERT, "Null area ... SKIPPING!" );
284
285             if ( shape.numRings() > 1 ) {
286                 FG_LOG(  FG_GENERAL, FG_ALERT, "  Null area with holes!" );
287                 // exit(-1);
288             }
289
290             init_shape(&gpc_shape);
291             for (  j = 0; j < shape.numRings(); j++ ) {
292                 n_vertices = shape.getRing(j, coords);
293                 add_to_shape(n_vertices, coords, &gpc_shape);
294             }
295             // process_shape(path, area, &gpc_shape);
296             free_shape(&gpc_shape);
297         } else {
298             FG_LOG(  FG_GENERAL, FG_ALERT, "Uknown area!" );
299             exit(-1);
300         }
301     }
302
303     return 0;
304 }
305
306