source: subversion/applications/utils/import/and2osm/mknodedb.c @ 4349

Last change on this file since 4349 was 4347, checked in by martinvoosterhout, 13 years ago

Output something for ambiguous cases also, by just guessing the first node
is the correct one. We need this so that 2AND knows all the nodes
that are actually needed.

File size: 11.6 KB
Line 
1/********************************************************************************
2 * some code copied from 2AND.c
3 *
4 * Project: AND2osm
5 * Purpose: Scan known roads and try to determine the IDs of their endpoints
6 *          by finding the common nodeID where two roads meet.
7 *
8 * Author: Martijn van Oosterhout <kleptog@svana.org>
9 */
10 
11#include <stdlib.h>
12#include <stdio.h>
13#include <string.h>
14#include <unistd.h>
15#include <errno.h>
16#include "rb.h"
17#include "shapefil.h"
18
19#define DISPLAY_FREQUENCY 1000
20#define FILENAME "020"
21
22struct nodeid
23{
24      long ID;
25      int count;
26      int pref;
27      struct nodeid *next;
28};
29
30struct node
31{
32      double lat, lon;
33      struct nodeid *nodeids;
34};
35 
36struct rb_table * nodes_table;
37
38int compare_nodes (const void *pa, const void *pb, void *param){
39        const struct node * na=pa;
40        const struct node * nb=pb;
41        if (na->lat < nb->lat) return -1;
42        if (na->lat > nb->lat) return 1;
43        if (na->lon < nb->lon) return -1;
44        if (na->lon > nb->lon) return 1;
45        return 0;
46}
47
48struct node * addNode(double lat, double lon){
49        struct node  * storenode;
50        struct node ** p;
51        storenode = (struct node *) calloc(1,sizeof(struct node));
52        if (storenode==NULL)
53        {
54                fprintf(stderr,"out of memory\n");
55                exit(1);
56        }
57
58        storenode->lat=lat;
59        storenode->lon=lon;
60        p=(struct node  **) rb_probe (nodes_table, storenode);
61        if (*p!=storenode)
62        {
63                //item was already in list
64                free(storenode);
65        }
66        return *p;
67}
68
69void init_nodes(){
70        if (nodes_table==NULL)
71        {
72                nodes_table=rb_create (compare_nodes, NULL,NULL);
73        }
74        else
75        {
76                printf("error: nodes_table is inited twice\n");
77                exit(1);
78        }
79        return;
80}
81
82void addCandidateID( struct node *n, int ID, int pref )
83{
84      struct nodeid *p = n->nodeids;
85     
86      while( p != NULL )
87      {
88          if( p->ID == ID )
89          {
90              p->count++;
91              break;
92          }
93          p = p->next;
94      }
95      if( !p )
96      {
97          p = (struct nodeid*)calloc(1,sizeof(struct nodeid));
98          p->ID = ID;
99          p->next = n->nodeids;
100          p->count = 1;
101          p->pref = pref;
102          n->nodeids = p;
103      }
104}
105
106/* First argument is marked as "preferred". So we have a way of breaking ties */
107static void addCandidateIDs(struct node *n, int ID1, int ID2 )
108{
109    addCandidateID( n, ID1, 1 );
110    addCandidateID( n, ID2, 0 );
111}
112
113int ERR_ambiguous;
114int ERR_nontrivial;
115int NodeCount;
116void dumpOutput( SHPHandle shp, DBFHandle dbf)
117{
118        struct rb_traverser tr;
119        struct node * p;
120        rb_t_init (&tr, nodes_table);
121        NodeCount = -1;
122        while ((p=(struct node *) rb_t_next(&tr))!=NULL)
123        {
124                struct nodeid *id;
125                struct nodeid *top = NULL;
126               
127                if( !p->nodeids )  // Dummy node
128                    continue;
129                   
130                int max = 0, non_trivial = 0;
131                for( id = p->nodeids; id; id = id->next )
132                {
133                    if( id->count == 1 )
134                        continue;
135                    if( max == 0 )
136                    {
137                        max = id->count;
138                        top = id;
139                        continue;
140                    }
141                    non_trivial = 1;
142                }
143                if( non_trivial )
144                {
145                    ERR_nontrivial++;
146
147                }
148                else if( top == NULL )
149                {
150                    ERR_ambiguous++;
151                    char buffer[1000];
152                    buffer[0]=0;
153                   
154                    if( (ERR_ambiguous % 100000) == 0 )
155                    {
156                        printf( "Ambiguous: " );
157                        for( id=p->nodeids; id; id=id->next )
158                        {
159                            printf( "%ldx%d, ", id->ID, id->count );
160                        }
161                        printf("\n");
162                    }
163                    double x=0.0;
164                    SHPObject *shape = SHPCreateSimpleObject( SHPT_POINT, 1, &p->lon, &p->lat, &x );
165                    int shapeid = SHPWriteObject( shp, -1, shape );
166                    SHPDestroyObject(shape);
167                    for( id = p->nodeids; id; id = id->next )
168                    {
169                        if( id->pref )
170                            DBFWriteIntegerAttribute( dbf, shapeid, 3, id->ID );
171                        sprintf( buffer+strlen(buffer), "%ldx%d,", id->ID, id->count );
172                    }
173                    DBFWriteStringAttribute( dbf, shapeid, 31, buffer);
174                    NodeCount++;
175                }
176                else
177                {
178                        double x=0.0;
179                        SHPObject *shape = SHPCreateSimpleObject( SHPT_POINT, 1, &p->lon, &p->lat, &x );
180                        int shapeid = SHPWriteObject( shp, -1, shape );
181                        SHPDestroyObject(shape);
182                        DBFWriteIntegerAttribute( dbf, shapeid, 3, top->ID );
183                        NodeCount++;
184                }
185        }
186}
187   
188
189void createOutput(const char *filename)
190{
191        SHPHandle shp = SHPCreate( filename, SHPT_POINT );
192        if( !shp )
193        {
194                printf("Couldn't create shapefile '%s': %s\n", filename, strerror(errno) );
195                return;
196        }
197        DBFHandle dbf = DBFCreate( filename );
198        if( !dbf )
199        {
200                printf("Couldn't create dbffile '%s': %s\n", filename, strerror(errno) );
201                return;
202        }
203        DBFAddField( dbf, "AREA", FTDouble, 20, 5 );
204        DBFAddField( dbf, "PERIMETER", FTDouble, 20, 5 );
205        DBFAddField( dbf, "NLD6_", FTInteger, 11, 0 );
206        DBFAddField( dbf, "ND_1", FTInteger, 11, 0 );
207        DBFAddField( dbf, "ND_2", FTInteger,  2, 0 );
208        DBFAddField( dbf, "ND_3", FTInteger,  2, 0 );
209        DBFAddField( dbf, "ND_4", FTInteger,  3, 0 );
210        DBFAddField( dbf, "ND_5", FTInteger,  3, 0 );
211        DBFAddField( dbf, "ND_6", FTInteger,  2, 0 );
212        DBFAddField( dbf, "ND_7", FTInteger,  2, 0 );
213       
214        DBFAddField( dbf, "ND_8", FTString, 30, 0 );
215        DBFAddField( dbf, "ND_9", FTString, 2, 0 ); //200
216        DBFAddField( dbf, "ND_10", FTString, 10, 0 );
217        DBFAddField( dbf, "ND_11", FTString, 20, 0 );
218        DBFAddField( dbf, "ND_12", FTString, 2, 0 );
219        DBFAddField( dbf, "ND_13", FTString, 10, 0 );
220       
221        DBFAddField( dbf, "ND_14", FTInteger,  3, 0 );
222        DBFAddField( dbf, "ND_15", FTInteger,  2, 0 );
223        DBFAddField( dbf, "ND_16", FTString, 2, 0 ); //200
224        DBFAddField( dbf, "ND_17", FTString, 10, 0 );
225        DBFAddField( dbf, "ND_18", FTString, 20, 0 );
226
227        DBFAddField( dbf, "ND_19", FTInteger,  3, 0 );
228        DBFAddField( dbf, "ND_20", FTString, 2, 0 );
229        DBFAddField( dbf, "ND_21", FTString, 6, 0 ); //6
230        DBFAddField( dbf, "ND_22", FTString, 10, 0 );
231        DBFAddField( dbf, "ND_23", FTString, 20, 0 );
232
233        DBFAddField( dbf, "ND_24", FTInteger,  3, 0 );
234        DBFAddField( dbf, "ND_25", FTInteger, 10, 0 );
235        DBFAddField( dbf, "ND_26", FTString, 6, 0 ); //60
236        DBFAddField( dbf, "ND_27", FTString, 3, 0 ); //30
237        DBFAddField( dbf, "ND_28", FTString, 6, 0 ); //60
238        DBFAddField( dbf, "ND_29", FTString, 60, 0 ); //60
239       
240        dumpOutput(shp,dbf);
241       
242        SHPClose(shp);
243        DBFClose(dbf);
244}
245int readfile(char * inputfile)
246{
247    SHPHandle   hSHP;
248    DBFHandle   hDBF;
249    int         nShapeType, nEntities;
250    long        i;
251    char        szTitle[12];
252    double      adfMinBound[4], adfMaxBound[4];
253
254
255/* -------------------------------------------------------------------- */
256/*      Open the passed shapefile.                                      */
257/* -------------------------------------------------------------------- */
258    hSHP = SHPOpen( inputfile, "rb" );
259        printf("%s\n",inputfile);
260    if( hSHP == NULL )
261    {
262        printf( "Unable to open: %s\n", inputfile );
263        return(1);
264    }
265
266
267    hDBF = DBFOpen( inputfile, "rb" );
268    if( hDBF == NULL )
269    {
270        printf( "DBFOpen(%s,\"r\") failed.\n", inputfile );
271        return(2);
272    }
273   
274    /* -------------------------------------------------------------------- */
275    /*      Print out the file bounds.                                      */
276    /* -------------------------------------------------------------------- */
277    SHPGetInfo( hSHP, &nEntities, &nShapeType, adfMinBound, adfMaxBound );
278
279    printf( "Shapefile Type: %s   # of Shapes: %d\n",
280            SHPTypeName( nShapeType ), nEntities );
281   
282    /*printf( "File Bounds: (%12.8f,%12.8f,%g,%g)\n"
283                    "         to  (%12.8f,%12.8f,%g,%g)\n",
284    adfMinBound[0],
285    adfMinBound[1],
286    adfMinBound[2],
287    adfMinBound[3],
288    adfMaxBound[0],
289    adfMaxBound[1],
290    adfMaxBound[2],
291    adfMaxBound[3] );*/
292
293
294/* -------------------------------------------------------------------- */
295/*        get file type                                                 */
296/* -------------------------------------------------------------------- */
297    DBFGetFieldInfo( hDBF, 0, szTitle, NULL, NULL );
298
299    if(strcmp(szTitle,"FNODE_")==0 )
300    {
301/* -------------------------------------------------------------------- */
302/*      Skim over the list of shapes, printing all the vertices.        */
303/* -------------------------------------------------------------------- */
304           
305            for( i = 0; i <nEntities; i++ )
306            {
307                long            j;
308                SHPObject       *psShape;
309                struct node *prevNode,*lastNode,*firstNode;
310
311                psShape = SHPReadObject( hSHP, i );
312                if ((i%DISPLAY_FREQUENCY)==0)
313                {
314                    printf("\r%7li/%7i   %7i/%7i                       ",i,nEntities,0,psShape->nVertices);
315                    fflush(stdout);
316                }
317                if( psShape->nParts != 1 )
318                {
319                    printf("Not prepared to deal with multiple parts, skipping %li\n", i );
320                    continue;
321                }
322                if( psShape->nVertices <= 1 )
323                {
324                    printf("Not prepared to deal with %d vertices, skipping %li\n", psShape->nVertices, i );
325                    continue;
326                }
327
328                prevNode=lastNode=firstNode=NULL;
329                for( j = 0; j < psShape->nVertices; j++ )
330                {
331                        //printf("%i/%i\n",j,psShape->nVertices);
332                        prevNode=lastNode;
333                        lastNode=addNode(psShape->padfY[j],psShape->padfX[j]);
334                        //printf("%p\n",lastNode);
335                        if (j==0)
336                                firstNode=lastNode;
337                }
338                int ID1 = DBFReadIntegerAttribute( hDBF, i, 0 );
339                int ID2 = DBFReadIntegerAttribute( hDBF, i, 1 );
340
341                addCandidateIDs( firstNode, ID1, ID2 );
342                addCandidateIDs( lastNode, ID2, ID1 );
343                SHPDestroyObject( psShape );
344            }
345    }
346    else
347    {
348            fprintf(stderr,"filetype unkown! %s\n",inputfile);
349            return -1;
350    }
351    printf("\r%7i/%7i                                     \n",nEntities,nEntities);
352    fflush(stdout);
353
354    SHPClose( hSHP );
355    DBFClose( hDBF );
356
357    return(0);
358
359}
360
361int main(int argc, char**argv)
362{
363    int c;
364    init_nodes();
365   
366    while ((c = getopt (argc, argv, "?C:")) != -1)
367            switch (c)
368            {
369            case 'C':
370                    if( chdir( optarg ) < 0 )
371                    {
372                            fprintf(stderr, "Failed to change to directory '%s': %s\n", optarg, strerror(errno) );
373                            exit(1);
374                    }
375                    break;
376            case '?':
377            default:
378                    /* Getopt will print an error message for us. */
379                    fprintf( stderr, "Usage: mknodedb [-C dir]\n"
380                                     "   -C dir                           - Change to given directory before starting\n"
381                                     );
382                    exit(1);
383            }
384           
385    readfile( FILENAME "_r_r");
386    readfile( FILENAME "_nosr_r");
387    createOutput("and_nodes");
388    printf( "total: %d  ambiguous: %d  nontrivial: %d\n", NodeCount, ERR_ambiguous, ERR_nontrivial );
389    return 0;
390}
Note: See TracBrowser for help on using the repository browser.