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

Last change on this file since 21288 was 21288, checked in by jonb, 9 years ago

coastcheck: Decrease threshold for discarding duplicate points. Previously points within about 10m would be ignored, this causes many small islands to be dropped. It also interferes with the detail of harbours etc. The threshold is now around 1m which should be small enough for z18 tiles.

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 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  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(%d), max(%d)\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.