source: subversion/applications/utils/coastcheck/coast2shp.c @ 9799

Last change on this file since 9799 was 9799, checked in by martinvoosterhout, 11 years ago
  • Make output nicer
  • Remove debug stuff
  • Don't bother indexing the tree just before exit
File size: 21.3 KB
Line 
1/*
2#-----------------------------------------------------------------------------
3# coast2shp - converts list of polygons into shapefilesfile into PostgreSQL
4# compatible output suitable to be rendered by mapnik
5# Use: coast2shp polygonlist coastline.osm.gz
6#-----------------------------------------------------------------------------
7# Based upon osm2pgsql:
8#   Original Python implementation by Artem Pavlenko
9#   Re-implementation by Jon Burgess, Copyright 2006
10# Reused for coast2shp by Martijn van Oosterhout 2007-2008
11#
12# This program is free software; you can redistribute it and/or
13# modify it under the terms of the GNU General Public License
14# as published by the Free Software Foundation; either version 2
15# of the License, or (at your option) any later version.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License
23# along with this program; if not, write to the Free Software
24# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
25#-----------------------------------------------------------------------------
26*/
27
28#define _GNU_SOURCE
29#include <stdio.h>
30#include <unistd.h>
31#include <stdlib.h>
32#include <string.h>
33#include <assert.h>
34#include <getopt.h>
35#include <errno.h>
36#include <math.h>
37
38#include <libxml/xmlstring.h>
39#include <libxml/xmlreader.h>
40
41#include <shapefil.h>
42#include <proj_api.h>
43
44#include "osmtypes.h"
45#include "keyvals.h"
46#include "input.h"
47#include "rb.h"
48
49/* Mercator projection limits for a square map.
50 * Points at 90 degrees are off at infinity
51 */
52const double merc_lat_min = -85.0511;
53const double merc_lat_max = +85.0511;
54
55int MAX_VERTICES = 1024*1024;
56
57static int count_node,    max_node;
58static int count_way,     max_way;
59static int count_rel,     max_rel;
60
61/* Since {node,way} elements are not nested we can guarantee the
62   values in an end tag must match those of the corresponding
63   start tag and can therefore be cached.
64*/
65static double node_lon, node_lat;
66static struct keyval nds;
67static int osm_id;
68struct rb_table *nodes_table;
69struct rb_table *ways_table;
70
71int verbose;
72int latlong;
73
74static projPJ pj_ll, pj_merc;
75
76static void project_init(void)
77{
78        pj_ll   = pj_init_plus("+proj=latlong +ellps=GRS80 +no_defs +over");
79        pj_merc = pj_init_plus("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over");
80
81        if (!pj_ll || !pj_merc) {
82                fprintf(stderr, "Projection code failed to initialise\n");
83                exit(1);
84        }
85}
86
87static void project_exit(void)
88{
89        pj_free(pj_ll);
90        pj_ll = NULL;
91        pj_free(pj_merc);
92        pj_merc = NULL;
93}
94
95static void printStatus(void)
96{
97    if( isatty(STDERR_FILENO) )
98      fprintf(stderr, "\rProcessing: Node(%dk) Way(%dk) Relation(%dk)    ",
99              count_node/1000, count_way/1000, count_rel/1000);
100}
101
102
103void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
104{
105    xmlChar *xid, *xlat, *xlon /**xk, *xv, *xrole, *xtype*/;
106//    char *k;
107
108    if (xmlStrEqual(name, BAD_CAST "node")) {
109        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
110        xlon = xmlTextReaderGetAttribute(reader, BAD_CAST "lon");
111        xlat = xmlTextReaderGetAttribute(reader, BAD_CAST "lat");
112        assert(xid); assert(xlon); assert(xlat);
113
114        osm_id  = strtol((char *)xid, NULL, 10);
115        node_lon = strtod((char *)xlon, NULL);
116        node_lat = strtod((char *)xlat, NULL);
117
118        if (osm_id > max_node)
119            max_node = osm_id;
120
121        count_node++;
122        if (count_node%10000 == 0)
123            printStatus();
124
125        xmlFree(xid);
126        xmlFree(xlon);
127        xmlFree(xlat);
128    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
129#if 0
130        xk = xmlTextReaderGetAttribute(reader, BAD_CAST "k");
131        assert(xk);
132
133        /* 'created_by' and 'source' are common and not interesting to mapnik renderer */
134        if (strcmp((char *)xk, "created_by") && strcmp((char *)xk, "source")) {
135            char *p;
136            xv = xmlTextReaderGetAttribute(reader, BAD_CAST "v");
137            assert(xv);
138            k  = (char *)xmlStrdup(xk);
139            while ((p = strchr(k, ' ')))
140                *p = '_';
141
142            addItem(&tags, k, (char *)xv, 0);
143            xmlFree(k);
144            xmlFree(xv);
145        }
146        xmlFree(xk);
147#endif
148    } else if (xmlStrEqual(name, BAD_CAST "way")) {
149        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
150        assert(xid);
151        osm_id   = strtol((char *)xid, NULL, 10);
152
153        if (osm_id > max_way)
154            max_way = osm_id;
155
156        count_way++;
157        if (count_way%1000 == 0)
158            printStatus();
159
160        xmlFree(xid);
161    } else if (xmlStrEqual(name, BAD_CAST "nd")) {
162        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "ref");
163        assert(xid);
164
165        addItem(&nds, "id", (char *)xid, 0);
166
167        xmlFree(xid);
168    } else if (xmlStrEqual(name, BAD_CAST "relation")) {
169#if 0
170        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
171        assert(xid);
172        osm_id   = strtol((char *)xid, NULL, 10);
173
174        if (osm_id > max_rel)
175            max_rel = osm_id;
176
177        xmlFree(xid);
178#endif
179        count_rel++;
180        if (count_rel%1000 == 0)
181            printStatus();
182
183    } else if (xmlStrEqual(name, BAD_CAST "member")) {
184#if 0
185        xrole = xmlTextReaderGetAttribute(reader, BAD_CAST "role");
186        assert(xrole);
187
188        xtype = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
189        assert(xtype);
190
191        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "ref");
192        assert(xid);
193
194        /* Currently we are only interested in 'way' members since these form polygons with holes */
195        if (xmlStrEqual(xtype, BAD_CAST "way"))
196            addItem(&members, (char *)xrole, (char *)xid, 0);
197
198        xmlFree(xid);
199        xmlFree(xrole);
200        xmlFree(xtype);
201#endif
202    } else if (xmlStrEqual(name, BAD_CAST "osm")) {
203        /* ignore */
204    } else if (xmlStrEqual(name, BAD_CAST "bound")) {
205        /* ignore */
206    } else {
207        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
208    }
209}
210
211void EndElement(const xmlChar *name)
212{
213    if (xmlStrEqual(name, BAD_CAST "node")) {
214        struct osmNode  * storenode;
215        storenode = (struct osmNode *) calloc(1,sizeof(struct osmNode));
216        if (storenode==NULL)
217        {
218                fprintf(stderr,"out of memory\n");
219                exit(1);
220        }
221
222      if (node_lat < merc_lat_min)
223            node_lat = merc_lat_min;
224      else if (node_lat > merc_lat_max)
225            node_lat = merc_lat_max;
226
227        storenode->id = osm_id;
228        storenode->lat = node_lat * DEG_TO_RAD;
229        storenode->lon = node_lon * DEG_TO_RAD;
230
231        rb_insert(nodes_table, storenode);
232    } else if (xmlStrEqual(name, BAD_CAST "way")) {
233        struct osmWay  * storeway;
234        struct keyval *p;
235        int i;
236        storeway = (struct osmWay *) calloc(1,sizeof(struct osmWay)+sizeof(int)*countList(&nds));
237        if (storeway==NULL)
238        {
239                fprintf(stderr,"out of memory\n");
240                exit(1);
241        }
242        storeway->id = osm_id;
243        for( i=0, p = popItem(&nds); p; i++, p = popItem(&nds) )
244        {
245                storeway->nds[i] = strtol(p->value, NULL, 10);
246                freeItem(p);
247        }
248        storeway->nds[i] = 0;
249        if( i == 1 )
250          fprintf(stderr, "Wierd: way %d only has %d nodes\n", osm_id, i);
251        if( i >= 2 )
252                rb_insert( ways_table, storeway );
253        resetList(&nds);
254    } else if (xmlStrEqual(name, BAD_CAST "relation")) {
255        /* ignore */
256    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
257        /* ignore */
258    } else if (xmlStrEqual(name, BAD_CAST "nd")) {
259        /* ignore */
260    } else if (xmlStrEqual(name, BAD_CAST "member")) {
261        /* ignore */
262    } else if (xmlStrEqual(name, BAD_CAST "osm")) {
263        printStatus();
264    } else if (xmlStrEqual(name, BAD_CAST "bound")) {
265        /* ignore */
266    } else {
267        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
268    }
269}
270
271static void processNode(xmlTextReaderPtr reader) {
272    xmlChar *name;
273    name = xmlTextReaderName(reader);
274    if (name == NULL)
275        name = xmlStrdup(BAD_CAST "--");
276       
277    switch(xmlTextReaderNodeType(reader)) {
278        case XML_READER_TYPE_ELEMENT:
279            StartElement(reader, name);
280            if (xmlTextReaderIsEmptyElement(reader))
281                EndElement(name); /* No end_element for self closing tags! */
282            break;
283        case XML_READER_TYPE_END_ELEMENT:
284            EndElement(name);
285            break;
286        case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
287            /* Ignore */
288            break;
289        default:
290            fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
291            break;
292    }
293
294    xmlFree(name);
295}
296
297static int streamFile(char *filename) {
298    xmlTextReaderPtr reader;
299    int ret = 0;
300
301    reader = inputUTF8(filename);
302
303    if (reader != NULL) {
304        ret = xmlTextReaderRead(reader);
305        while (ret == 1) {
306            processNode(reader);
307            ret = xmlTextReaderRead(reader);
308        }
309
310        if (ret != 0) {
311            fprintf(stderr, "%s : failed to parse\n", filename);
312            return ret;
313        }
314
315        xmlFreeTextReader(reader);
316    } else {
317        fprintf(stderr, "Unable to open %s\n", filename);
318        return 1;
319    }
320    return 0;
321}
322
323void exit_nicely(void)
324{
325    fprintf(stderr, "Error occurred, cleaning up\n");
326    exit(1);
327}
328 
329static void usage(const char *arg0)
330{
331    const char *name = basename(arg0);
332
333    fprintf(stderr, "Usage:\n");
334    fprintf(stderr, "\t%s coastline.txt coastline.osm.gz outputprefix\n", name);
335    fprintf(stderr, "\n");
336}
337
338/* Can be used to compare any osm object, cause it only uses the first two fields */
339static int osm_compare (const void *pa, const void *pb, void *param){
340        const struct osmNode * na=pa;
341        const struct osmNode * nb=pb;
342        if (na->id < nb->id) return -1;
343        if (na->id > nb->id) return 1;
344        return 0;
345        param=param;
346}
347
348static int processList(char *filename, char *output_prefix)
349{
350  char out_c[64], out_p[64], out_i[64];
351  FILE *in;
352  SHPHandle shp_poly, shp_arc, shp_point;
353  DBFHandle dbf_poly, dbf_arc, dbf_point;
354 
355  in = fopen( filename, "rt" );
356  if( !in )
357  {
358      fprintf(stderr, "Error opening file %s: %s\n", filename, strerror(errno) );
359      exit_nicely();
360  }
361  if( strlen( output_prefix ) > sizeof(out_c)-10 )
362  {
363      fprintf( stderr, "Output prefix too long\n" );
364      exit_nicely();
365  }
366  sprintf( out_c, "%s_c", output_prefix );
367  sprintf( out_p, "%s_p", output_prefix );
368  sprintf( out_i, "%s_i", output_prefix );
369 
370  int max_vertex_count = 0;
371 
372  shp_poly = SHPCreate( out_c,  SHPT_POLYGON );
373  shp_arc = SHPCreate( out_i, SHPT_ARC );
374  shp_point = SHPCreate( out_p, SHPT_POINT );
375  dbf_poly = DBFCreate( out_c );
376  dbf_arc = DBFCreate( out_i );
377  dbf_point = DBFCreate( out_p );
378  DBFAddField( dbf_poly, "type", FTInteger, 5, 0 );
379  DBFAddField( dbf_poly, "length", FTInteger, 10, 0 );
380  DBFAddField( dbf_poly, "way_id", FTInteger, 10, 0 );
381  DBFAddField( dbf_arc, "type", FTInteger, 5, 0 );
382  DBFAddField( dbf_arc, "length", FTInteger, 10, 0 );
383  DBFAddField( dbf_arc, "way_id", FTInteger, 10, 0 );
384  DBFAddField( dbf_point, "type", FTInteger, 5, 0 );
385 
386  int shp_poly_count = 0, shp_arc_count = 0;
387 
388  double *v_x = malloc( MAX_VERTICES*sizeof(double) );
389  double *v_y = malloc( MAX_VERTICES*sizeof(double) );
390  double *v_z = malloc( MAX_VERTICES*sizeof(double) );
391  if( !v_x || !v_y || !v_z )
392  {
393    fprintf( stderr, "Out of memory allocating vertex buffers\n" );
394    exit_nicely();
395  }
396  int line = 0;
397  while( !feof(in) )
398  {
399    char type;
400    int length;
401    int i;
402    line++;
403    fscanf( in, "%c", &type );
404    if( type == 'P' )
405    {
406      int t;
407      double x, y;
408      double z = 0;
409      fscanf( in, "%d %lf %lf\n", &t, &y, &x );
410
411      x *= DEG_TO_RAD;
412      y *= DEG_TO_RAD;
413//      printf( "Before transform (%f,%f)\n", x, y );
414      pj_transform(pj_ll, pj_merc, 1, 1, &x, &y, &z);
415//      printf( "After transform (%f,%f)\n", x, y );
416     
417//      if( x > 0.0 && y > 5527259.12027 && x < 78271.516964 && y < 5605266.15512 )
418//      {
419//        fprintf(stderr, "Found at line %d\n", line );
420//      }
421      SHPObject *p;
422      p = SHPCreateSimpleObject( SHPT_POINT, 1, &x, &y, NULL );
423      int idx = SHPWriteObject( shp_point, -1, p );
424      if( idx < 0 ) { fprintf(stderr, "Write failure: %m\n"); exit(1); }
425      DBFWriteIntegerAttribute( dbf_point, idx, 0, t );
426      SHPDestroyObject(p);
427     
428      continue;
429    }
430    if( type != 'C' && type != 'I' )
431    {
432      fprintf( stderr, "Got bad type at offset %ld\n", ftell(in) );
433      exit_nicely();
434    }
435    fscanf( in, "%d ", &length );
436    printf("Generating type=%c, length=%d, poly_count=%d, arc_count=%d\n", type, length, shp_poly_count, shp_arc_count );
437    struct osmNode *last_match = NULL;
438    struct osmNode *first_match = NULL;
439    int vertex_count = 0;
440    int way_id = 0;
441    for( i=0; i<length; i++ )
442    {
443      struct osmWay key_way;
444      struct osmNode key_node;
445      int j;
446      if( fscanf( in, "%d ", &key_way.id ) != 1 )
447      {
448        fprintf( stderr, "Failed to read\n");
449        exit_nicely();
450      } 
451      struct osmWay *way_match = rb_find( ways_table, &key_way );
452      if( !way_match )
453      {
454        fprintf( stderr, "Failed to find way %d\n", key_way.id );
455        continue;
456      }
457      if( way_id == 0 )
458        way_id = key_way.id;
459       
460      for( j=0; way_match->nds[j]; j++ )
461      {
462//        printf("Adding way %d, node %d (%d)\n", key_way.id, j, way_match->nds[j] );
463        key_node.id = way_match->nds[j];
464        struct osmNode *node_match = rb_find( nodes_table, &key_node );
465        if( !node_match )
466        {
467          fprintf( stderr, "Failed to find node %d\n", key_node.id );
468          continue;
469        }
470        if( !first_match )
471          first_match = node_match;
472        if( last_match == node_match )
473          continue;
474        if( last_match && fabs( last_match->lat - node_match->lat ) < 1e-6
475                       && fabs( last_match->lon - node_match->lon ) < 1e-6 )
476        {
477//          printf( "{%.6f,%.6f} ", node_match->lat, node_match->lon );
478          continue;
479        }
480        /* Extend array as necessary */
481        if( vertex_count > MAX_VERTICES-10 )
482        {
483          MAX_VERTICES <<= 1;
484          v_x = realloc( v_x, MAX_VERTICES*sizeof(double) );
485          v_y = realloc( v_y, MAX_VERTICES*sizeof(double) );
486          v_z = realloc( v_z, MAX_VERTICES*sizeof(double) );
487          memset( v_z, 0, MAX_VERTICES*sizeof(double) );
488          fprintf( stderr, "Resized vertex arrays to %d\n", MAX_VERTICES );
489        }
490        v_y[vertex_count] = node_match->lat;
491        v_x[vertex_count] = node_match->lon;
492       
493        if( vertex_count > 1 )
494        {
495          if( fabs( v_y[vertex_count] - v_y[vertex_count-1] ) > 1*DEG_TO_RAD ||
496              fabs( v_x[vertex_count] - v_x[vertex_count-1] ) > 1*DEG_TO_RAD )
497          {
498            fprintf( stderr, "Problem found at way %d, node %d (%d) (%.3f,%.3f %.3f,%.3f)\n", 
499                      way_id, j, way_match->nds[j],
500                     v_x[vertex_count-1]/DEG_TO_RAD, v_y[vertex_count-1]/DEG_TO_RAD, 
501                     v_x[vertex_count]  /DEG_TO_RAD, v_y[vertex_count]  /DEG_TO_RAD );
502          }
503        }
504        printf( "(%.6f,%.6f) ", node_match->lat, node_match->lon );
505        vertex_count++;
506        last_match = node_match;
507      }
508      printf("|");
509    }
510    printf("\n");
511    if( type == 'C' && vertex_count < MAX_VERTICES-1 ) // Make sure polygon is closed
512    {
513      if( last_match != first_match )
514      {
515        if( fabs( last_match->lat - first_match->lat ) < 1e-6 &&
516            fabs( last_match->lon - first_match->lon ) < 1e-6 )
517        {
518          // If it's close, make sure it's equal
519          v_y[vertex_count-1] = first_match->lat;
520          v_x[vertex_count-1] = first_match->lon;
521        }
522        else
523        {
524          if( fabs( last_match->lat - first_match->lat ) > 0.5 ||
525              fabs( last_match->lon - first_match->lon ) > 0.5 )
526          {
527            fprintf( stderr, "Warning: Overly long last leg: %d\n", way_id );
528          }
529          // Otherwise, link to the first node
530          v_y[vertex_count] = first_match->lat;
531          v_x[vertex_count] = first_match->lon;
532          vertex_count++;
533        }
534      }
535    }
536    if( vertex_count > max_vertex_count )
537      max_vertex_count = vertex_count;
538
539#if 0
540    if( way_id == 20806670 )
541    {
542      fprintf( stderr, "Before:\n");
543      for(int y=0; y<vertex_count; y++)
544        fprintf( stderr, "(%f,%f) ", v_x[y]/DEG_TO_RAD,v_y[y]/DEG_TO_RAD);
545      fprintf(stderr, "\n");
546    }
547#endif
548    memset( v_z, 0, sizeof(double) * ((vertex_count < MAX_VERTICES) ? vertex_count : MAX_VERTICES) );
549    pj_transform(pj_ll, pj_merc, (vertex_count < MAX_VERTICES) ? vertex_count : MAX_VERTICES, 1, v_x, v_y, v_z);
550     
551    SHPObject *tmp = SHPCreateSimpleObject( (type == 'C') ? SHPT_POLYGON : SHPT_ARC, 
552                                            (vertex_count < MAX_VERTICES) ? vertex_count : MAX_VERTICES, 
553                                            v_x, v_y, NULL );
554    if( (tmp->dfXMax - tmp->dfXMin) > 30000000 )
555    {
556      fprintf( stderr, "Oversize: way_id=%d\n", way_id );
557      int scoreleft = 0, scoreright = 0;
558      for(int y=0; y<vertex_count; y++)
559      {
560        if( v_x[y] < -20000000 ) scoreleft++;
561        if( v_x[y] > +20000000 ) scoreright++;
562      }
563      for(int y=0; y<vertex_count; y++)
564      {
565        if( scoreleft < scoreright && v_x[y] < -20000000 ) v_x[y] += 2*20037508.34f;
566        if( scoreleft > scoreright && v_x[y] > +20000000 ) v_x[y] -= 2*20037508.34f;
567      }
568      // Recreate object
569      SHPDestroyObject(tmp);
570      tmp = SHPCreateSimpleObject( (type == 'C') ? SHPT_POLYGON : SHPT_ARC, 
571                                   (vertex_count < MAX_VERTICES) ? vertex_count : MAX_VERTICES, 
572                                   v_x, v_y, NULL );
573      if( (tmp->dfXMax - tmp->dfXMin) > 30000000 )
574      {
575        fprintf( stderr, "Still Oversize: way_id=%d\n", way_id );
576//        for( int y=0; y<vertex_count; y++)
577//          fprintf( stderr, "(%f,%f), ", v_x[y], v_y[y] );
578//        fprintf(stderr, "\n");
579      }
580    }
581#if 0
582    if( way_id == 20806670 )
583    {
584      fprintf( stderr, "After:\n");
585      for(int y=0; y<vertex_count; y++)
586        fprintf( stderr, "(%f,%f) ", v_x[y],v_y[y]);
587      fprintf(stderr, "\n");
588    }
589#endif
590    if( vertex_count < 2 )
591    {
592      fprintf(stderr, "Way %d only has %d node(s)\n", way_id, vertex_count);
593    }
594    if( type == 'C' && vertex_count >= 4 )
595    {
596      int idx = SHPWriteObject( shp_poly, -1, tmp );
597      if( idx < 0 ) { fprintf(stderr, "Write failure: %m\n"); exit(1); }
598      shp_poly_count++;
599      DBFWriteIntegerAttribute( dbf_poly, idx, 0, 0 );
600      DBFWriteIntegerAttribute( dbf_poly, idx, 1, vertex_count );
601      DBFWriteIntegerAttribute( dbf_poly, idx, 2, way_id );
602    }
603    else if( vertex_count > 0 )
604    {
605      tmp->nSHPType = SHPT_ARC;
606      int idx = SHPWriteObject( shp_arc, -1, tmp );
607      if( idx < 0 ) { fprintf(stderr, "Write failure: %m\n"); exit(1); }
608      shp_arc_count++;
609      DBFWriteIntegerAttribute( dbf_arc, idx, 0, 1 );
610      DBFWriteIntegerAttribute( dbf_arc, idx, 1, vertex_count );
611      DBFWriteIntegerAttribute( dbf_arc, idx, 2, way_id );
612     
613      SHPObject *p;
614      p = SHPCreateSimpleObject( SHPT_POINT, 1, &v_x[0], &v_y[0], NULL );
615      idx = SHPWriteObject( shp_point, -1, p );
616      if( idx < 0 ) { fprintf(stderr, "Write failure: %m\n"); exit(1); }
617      DBFWriteIntegerAttribute( dbf_point, idx, 0, 2 );
618      SHPDestroyObject(p);
619     
620      if( type != 'C' )
621      {
622        p = SHPCreateSimpleObject( SHPT_POINT, 1, &v_x[vertex_count-1], &v_y[vertex_count-1], NULL );
623        idx = SHPWriteObject( shp_point, -1, p );
624        if( idx < 0 ) { fprintf(stderr, "Write failure: %m\n"); exit(1); }
625        DBFWriteIntegerAttribute( dbf_point, idx, 0, 2 );
626        SHPDestroyObject(p);
627      }
628    }
629     
630    SHPDestroyObject(tmp);
631  }
632  fprintf( stderr, "Max vertex count: %d\n", max_vertex_count );
633  fprintf( stderr, "Polygons: %d, Arcs: %d\n", shp_poly_count, shp_arc_count );
634  if( max_vertex_count >= MAX_VERTICES )
635    fprintf( stderr, "objects cropped to %d vertices\n", MAX_VERTICES );
636  SHPClose( shp_poly );
637  SHPClose( shp_arc );
638  SHPClose( shp_point );
639  DBFClose( dbf_poly );
640  DBFClose( dbf_arc );
641  DBFClose( dbf_point );
642  return 0;
643}
644
645int main(int argc, char *argv[])
646{
647    fprintf(stderr, "coast2shp SVN version %s $Rev: 4895 $ \n", VERSION);
648
649    if (argc != 4) {
650        usage(argv[0]);
651        exit(EXIT_FAILURE);
652    }
653
654    initList(&nds);
655    nodes_table = rb_create (osm_compare, NULL, NULL);
656    ways_table = rb_create (osm_compare, NULL, NULL);
657
658    count_node = max_node = 0;
659    count_way = max_way = 0;
660    count_rel = max_rel = 0;
661
662    project_init();
663    LIBXML_TEST_VERSION
664
665    fprintf(stderr, "\nReading in file: %s\n", argv[2]);
666    if (streamFile(argv[2]) != 0)
667        exit_nicely();
668
669    xmlCleanupParser();
670    xmlMemoryDump();
671
672    fprintf(stderr, "\nReading in file: %s\n", argv[1]);
673    processList(argv[1], argv[3]);
674   
675    if (count_node || count_way || count_rel) {
676        fprintf(stderr, "\n");
677        fprintf(stderr, "Node stats: total(%d), max(%d)\n", count_node, max_node);
678        fprintf(stderr, "Way stats: total(%d), max(%d)\n", count_way, max_way);
679        fprintf(stderr, "Relation stats: total(%d), max(%d)\n", count_rel, max_rel);
680    }
681
682    project_exit();
683
684    return 0;
685}
686
Note: See TracBrowser for help on using the repository browser.