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

Last change on this file since 30195 was 29238, checked in by pnorman, 7 years ago

Update coast2shp.c to hopefully be 64-bit safe

File size: 21.6 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 long 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 long 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(%ldk) 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 %ld 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  DBFAddField( dbf_point, "way_id", FTInteger, 10, 0 );
386 
387  int shp_poly_count = 0, shp_arc_count = 0;
388 
389  double *v_x = malloc( MAX_VERTICES*sizeof(double) );
390  double *v_y = malloc( MAX_VERTICES*sizeof(double) );
391  double *v_z = malloc( MAX_VERTICES*sizeof(double) );
392  if( !v_x || !v_y || !v_z )
393  {
394    fprintf( stderr, "Out of memory allocating vertex buffers\n" );
395    exit_nicely();
396  }
397  int line = 0;
398  while( !feof(in) )
399  {
400    char type;
401    int length;
402    int i;
403    line++;
404    fscanf( in, "%c", &type );
405    if( type == 'P' )
406    {
407      int t;
408      double x, y;
409      double z = 0;
410      fscanf( in, "%d %lf %lf\n", &t, &y, &x );
411
412      x *= DEG_TO_RAD;
413      y *= DEG_TO_RAD;
414//      printf( "Before transform (%f,%f)\n", x, y );
415      pj_transform(pj_ll, pj_merc, 1, 1, &x, &y, &z);
416//      printf( "After transform (%f,%f)\n", x, y );
417     
418//      if( x > 0.0 && y > 5527259.12027 && x < 78271.516964 && y < 5605266.15512 )
419//      {
420//        fprintf(stderr, "Found at line %d\n", line );
421//      }
422      SHPObject *p;
423      p = SHPCreateSimpleObject( SHPT_POINT, 1, &x, &y, NULL );
424      int idx = SHPWriteObject( shp_point, -1, p );
425      if( idx < 0 ) { fprintf(stderr, "Write failure: %m\n"); exit(1); }
426      DBFWriteIntegerAttribute( dbf_point, idx, 0, t );
427      DBFWriteIntegerAttribute( dbf_point, idx, 1, 0 );
428      SHPDestroyObject(p);
429     
430      continue;
431    }
432    if( type != 'C' && type != 'I' )
433    {
434      fprintf( stderr, "Got bad type at offset %ld\n", ftell(in) );
435      exit_nicely();
436    }
437    fscanf( in, "%d ", &length );
438    printf("Generating type=%c, length=%d, poly_count=%d, arc_count=%d\n", type, length, shp_poly_count, shp_arc_count );
439    struct osmNode *last_match = NULL;
440    struct osmNode *first_match = NULL;
441    int vertex_count = 0;
442    int way_id = 0;
443    for( i=0; i<length; i++ )
444    {
445      struct osmWay key_way;
446      struct osmNode key_node;
447      int j;
448      if( fscanf( in, "%d ", &key_way.id ) != 1 )
449      {
450        fprintf( stderr, "Failed to read\n");
451        exit_nicely();
452      } 
453      struct osmWay *way_match = rb_find( ways_table, &key_way );
454      if( !way_match )
455      {
456        fprintf( stderr, "Failed to find way %d\n", key_way.id );
457        continue;
458      }
459      if( way_id == 0 )
460        way_id = key_way.id;
461       
462      for( j=0; way_match->nds[j]; j++ )
463      {
464//        printf("Adding way %d, node %d (%d)\n", key_way.id, j, way_match->nds[j] );
465        key_node.id = way_match->nds[j];
466        struct osmNode *node_match = rb_find( nodes_table, &key_node );
467        if( !node_match )
468        {
469          fprintf( stderr, "Failed to find node %d\n", key_node.id );
470          continue;
471        }
472        if( !first_match )
473          first_match = node_match;
474        if( last_match == node_match )
475          continue;
476        if( last_match && fabs( last_match->lat - node_match->lat ) < 1e-7
477                       && fabs( last_match->lon - node_match->lon ) < 1e-7 )
478        {
479//          printf( "{%.6f,%.6f} ", node_match->lat, node_match->lon );
480          continue;
481        }
482        /* Extend array as necessary */
483        if( vertex_count > MAX_VERTICES-10 )
484        {
485          MAX_VERTICES <<= 1;
486          v_x = realloc( v_x, MAX_VERTICES*sizeof(double) );
487          v_y = realloc( v_y, MAX_VERTICES*sizeof(double) );
488          v_z = realloc( v_z, MAX_VERTICES*sizeof(double) );
489          memset( v_z, 0, MAX_VERTICES*sizeof(double) );
490          fprintf( stderr, "Resized vertex arrays to %d\n", MAX_VERTICES );
491        }
492        v_y[vertex_count] = node_match->lat;
493        v_x[vertex_count] = node_match->lon;
494       
495        if( vertex_count > 1 )
496        {
497          if( fabs( v_y[vertex_count] - v_y[vertex_count-1] ) > 1*DEG_TO_RAD ||
498              fabs( v_x[vertex_count] - v_x[vertex_count-1] ) > 1*DEG_TO_RAD )
499          {
500            fprintf( stderr, "Problem found at way %d, node %d (%d) (%.3f,%.3f %.3f,%.3f)\n", 
501                      way_id, j, way_match->nds[j],
502                     v_x[vertex_count-1]/DEG_TO_RAD, v_y[vertex_count-1]/DEG_TO_RAD, 
503                     v_x[vertex_count]  /DEG_TO_RAD, v_y[vertex_count]  /DEG_TO_RAD );
504          }
505        }
506        printf( "(%.6f,%.6f) ", node_match->lat, node_match->lon );
507        vertex_count++;
508        last_match = node_match;
509      }
510      printf("|");
511    }
512    printf("\n");
513    if( type == 'C' && vertex_count < MAX_VERTICES-1 ) // Make sure polygon is closed
514    {
515      if( last_match != first_match )
516      {
517        if( fabs( last_match->lat - first_match->lat ) < 1e-7 &&
518            fabs( last_match->lon - first_match->lon ) < 1e-7 )
519        {
520          // If it's close, make sure it's equal
521          v_y[vertex_count-1] = first_match->lat;
522          v_x[vertex_count-1] = first_match->lon;
523        }
524        else
525        {
526          if( fabs( last_match->lat - first_match->lat ) > 0.5 ||
527              fabs( last_match->lon - first_match->lon ) > 0.5 )
528          {
529            fprintf( stderr, "Warning: Overly long last leg: %d\n", way_id );
530          }
531          // Otherwise, link to the first node
532          v_y[vertex_count] = first_match->lat;
533          v_x[vertex_count] = first_match->lon;
534          vertex_count++;
535        }
536      }
537    }
538    if( vertex_count > max_vertex_count )
539      max_vertex_count = vertex_count;
540
541#if 0
542    if( way_id == 20806670 )
543    {
544      fprintf( stderr, "Before:\n");
545      for(int y=0; y<vertex_count; y++)
546        fprintf( stderr, "(%f,%f) ", v_x[y]/DEG_TO_RAD,v_y[y]/DEG_TO_RAD);
547      fprintf(stderr, "\n");
548    }
549#endif
550    memset( v_z, 0, sizeof(double) * ((vertex_count < MAX_VERTICES) ? vertex_count : MAX_VERTICES) );
551    pj_transform(pj_ll, pj_merc, (vertex_count < MAX_VERTICES) ? vertex_count : MAX_VERTICES, 1, v_x, v_y, v_z);
552     
553    SHPObject *tmp = SHPCreateSimpleObject( (type == 'C') ? SHPT_POLYGON : SHPT_ARC, 
554                                            (vertex_count < MAX_VERTICES) ? vertex_count : MAX_VERTICES, 
555                                            v_x, v_y, NULL );
556    if( (tmp->dfXMax - tmp->dfXMin) > 30000000 )
557    {
558      fprintf( stderr, "Oversize: way_id=%d\n", way_id );
559      int scoreleft = 0, scoreright = 0;
560      for(int y=0; y<vertex_count; y++)
561      {
562        if( v_x[y] < -20000000 ) scoreleft++;
563        if( v_x[y] > +20000000 ) scoreright++;
564      }
565      for(int y=0; y<vertex_count; y++)
566      {
567        if( scoreleft < scoreright && v_x[y] < -20000000 ) v_x[y] += 2*20037508.34f;
568        if( scoreleft > scoreright && v_x[y] > +20000000 ) v_x[y] -= 2*20037508.34f;
569      }
570      // Recreate object
571      SHPDestroyObject(tmp);
572      tmp = SHPCreateSimpleObject( (type == 'C') ? SHPT_POLYGON : SHPT_ARC, 
573                                   (vertex_count < MAX_VERTICES) ? vertex_count : MAX_VERTICES, 
574                                   v_x, v_y, NULL );
575      if( (tmp->dfXMax - tmp->dfXMin) > 30000000 )
576      {
577        fprintf( stderr, "Still Oversize: way_id=%d\n", way_id );
578//        for( int y=0; y<vertex_count; y++)
579//          fprintf( stderr, "(%f,%f), ", v_x[y], v_y[y] );
580//        fprintf(stderr, "\n");
581      }
582    }
583#if 0
584    if( way_id == 20806670 )
585    {
586      fprintf( stderr, "After:\n");
587      for(int y=0; y<vertex_count; y++)
588        fprintf( stderr, "(%f,%f) ", v_x[y],v_y[y]);
589      fprintf(stderr, "\n");
590    }
591#endif
592    if( vertex_count < 2 )
593    {
594      fprintf(stderr, "Way %d only has %d node(s)\n", way_id, vertex_count);
595    }
596    if( type == 'C' && vertex_count >= 4 )
597    {
598      int idx = SHPWriteObject( shp_poly, -1, tmp );
599      if( idx < 0 ) { fprintf(stderr, "Write failure: %m\n"); exit(1); }
600      shp_poly_count++;
601      DBFWriteIntegerAttribute( dbf_poly, idx, 0, 0 );
602      DBFWriteIntegerAttribute( dbf_poly, idx, 1, vertex_count );
603      DBFWriteIntegerAttribute( dbf_poly, idx, 2, way_id );
604    }
605    else if( vertex_count > 0 )
606    {
607      tmp->nSHPType = SHPT_ARC;
608      int idx = SHPWriteObject( shp_arc, -1, tmp );
609      if( idx < 0 ) { fprintf(stderr, "Write failure: %m\n"); exit(1); }
610      shp_arc_count++;
611      DBFWriteIntegerAttribute( dbf_arc, idx, 0, 1 );
612      DBFWriteIntegerAttribute( dbf_arc, idx, 1, vertex_count );
613      DBFWriteIntegerAttribute( dbf_arc, idx, 2, way_id );
614     
615      SHPObject *p;
616      p = SHPCreateSimpleObject( SHPT_POINT, 1, &v_x[0], &v_y[0], NULL );
617      idx = SHPWriteObject( shp_point, -1, p );
618      if( idx < 0 ) { fprintf(stderr, "Write failure: %m\n"); exit(1); }
619      DBFWriteIntegerAttribute( dbf_point, idx, 0, 2 );
620      DBFWriteIntegerAttribute( dbf_point, idx, 1, way_id );
621      SHPDestroyObject(p);
622     
623      if( type != 'C' )
624      {
625        p = SHPCreateSimpleObject( SHPT_POINT, 1, &v_x[vertex_count-1], &v_y[vertex_count-1], NULL );
626        idx = SHPWriteObject( shp_point, -1, p );
627        if( idx < 0 ) { fprintf(stderr, "Write failure: %m\n"); exit(1); }
628        DBFWriteIntegerAttribute( dbf_point, idx, 0, 2 );
629        DBFWriteIntegerAttribute( dbf_point, idx, 1, -way_id );
630        SHPDestroyObject(p);
631      }
632    }
633     
634    SHPDestroyObject(tmp);
635  }
636  fprintf( stderr, "Max vertex count: %d\n", max_vertex_count );
637  fprintf( stderr, "Polygons: %d, Arcs: %d\n", shp_poly_count, shp_arc_count );
638  if( max_vertex_count >= MAX_VERTICES )
639    fprintf( stderr, "objects cropped to %d vertices\n", MAX_VERTICES );
640  SHPClose( shp_poly );
641  SHPClose( shp_arc );
642  SHPClose( shp_point );
643  DBFClose( dbf_poly );
644  DBFClose( dbf_arc );
645  DBFClose( dbf_point );
646  return 0;
647}
648
649int main(int argc, char *argv[])
650{
651    fprintf(stderr, "coast2shp SVN version %s $Rev: 4895 $ \n", VERSION);
652
653    if (argc != 4) {
654        usage(argv[0]);
655        exit(EXIT_FAILURE);
656    }
657
658    initList(&nds);
659    nodes_table = rb_create (osm_compare, NULL, NULL);
660    ways_table = rb_create (osm_compare, NULL, NULL);
661
662    count_node = max_node = 0;
663    count_way = max_way = 0;
664    count_rel = max_rel = 0;
665
666    project_init();
667    LIBXML_TEST_VERSION
668
669    fprintf(stderr, "\nReading in file: %s\n", argv[2]);
670    if (streamFile(argv[2]) != 0)
671        exit_nicely();
672
673    xmlCleanupParser();
674    xmlMemoryDump();
675
676    fprintf(stderr, "\nReading in file: %s\n", argv[1]);
677    processList(argv[1], argv[3]);
678   
679    if (count_node || count_way || count_rel) {
680        fprintf(stderr, "\n");
681        fprintf(stderr, "Node stats: total(%ld), max(%ld)\n", count_node, max_node);
682        fprintf(stderr, "Way stats: total(%d), max(%d)\n", count_way, max_way);
683        fprintf(stderr, "Relation stats: total(%d), max(%d)\n", count_rel, max_rel);
684    }
685
686    project_exit();
687
688    return 0;
689}
690
Note: See TracBrowser for help on using the repository browser.