1 // main.cxx -- process shapefiles and extract polygon outlines,
2 // clipping against and sorting them into the revelant
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.
26 // Include Geographic Foundation Classes library
28 // libgfc.a includes need this bit o' strangeness
32 #include <gfc/gadt_polygon.h>
34 #include <gfc/gshapefile.h>
39 // include Generic Polygon Clipping Library
44 #include <Include/compiler.h>
48 #include <Debug/logstream.hxx>
50 #include <Polygon/index.hxx>
51 #include <Polygon/names.hxx>
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
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;
68 // this is the whole name record
69 dbf_rec = dbf->getRecord( rec );
71 // parse it into individual fields
73 fields = dbf->recordDeform( dbf_rec );
78 string area = fields[4].str_v;
79 // strip leading spaces
80 while ( area[0] == ' ' ) {
81 area = area.substr(1, area.length() - 1);
83 // strip trailing spaces
84 while ( area[area.length() - 1] == ' ' ) {
85 area = area.substr(0, area.length() - 1);
87 // strip other junk encountered
88 while ( (int)area[area.length() - 1] == 9 ) {
89 area = area.substr(0, area.length() - 1);
92 return get_area_type( area );
96 int main( int argc, char **argv ) {
97 gpc_polygon gpc_shape;
100 fglog().setLogLevels( FG_ALL, FG_DEBUG );
103 FG_LOG( FG_GENERAL, FG_ALERT, "Usage: " << argv[0]
104 << " <shape_file> <work_dir> [ area_string ]" );
108 FG_LOG( FG_GENERAL, FG_DEBUG, "Opening " << argv[1] << " for reading." );
110 // make work directory
111 string work_dir = argv[2];
112 string command = "mkdir -p " + work_dir;
113 system( command.c_str() );
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
118 string force_area_type = "";
120 force_area_type = argv[3];
123 // initialize persistant polygon counter
124 string counter_file = work_dir + "/../work.counter";
125 poly_index_init( counter_file );
127 // initialize structure for building gpc polygons
130 GShapeFile * sf = new GShapeFile( argv[1] );
131 GDBFile *dbf = new GDBFile( argv[1] );
132 string path = argv[2];
135 double *coords; // in decimal degrees
138 FG_LOG( FG_GENERAL, FG_INFO, "shape file records = " << sf->numRecords() );
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" );
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() );
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 << ")" );
159 FG_LOG( FG_GENERAL, FG_INFO, " record = " << i
160 << " ring = " << 0 );
162 if ( force_area_type.length() > 0 ) {
163 // interior of polygon is assigned to force_area_type,
164 // holes are maintained
166 area = get_area_type( force_area_type );
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);
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
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);
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);
195 } else if ( area == OceanArea ) {
196 // interior of polygon is ocean, holes are islands
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);
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
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);
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
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);
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
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);
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
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);
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
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);
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
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);
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
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);
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
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);
283 process_shape(path, area, &gpc_shape);
284 free_shape(&gpc_shape);
285 } else if ( area == VoidArea ) {
289 FG_LOG( FG_GENERAL, FG_ALERT, "Void area ... SKIPPING!" );
291 if ( shape.numRings() > 1 ) {
292 FG_LOG( FG_GENERAL, FG_ALERT, " Void area with holes!" );
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);
301 // process_shape(path, area, &gpc_shape);
302 free_shape(&gpc_shape);
303 } else if ( area == NullArea ) {
307 FG_LOG( FG_GENERAL, FG_ALERT, "Null area ... SKIPPING!" );
309 if ( shape.numRings() > 1 ) {
310 FG_LOG( FG_GENERAL, FG_ALERT, " Null area with holes!" );
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);
319 // process_shape(path, area, &gpc_shape);
320 free_shape(&gpc_shape);
322 FG_LOG( FG_GENERAL, FG_ALERT, "Uknown area!" );