int WriteFileBuffered(int fd,const void *address,size_t length) { logassert(fd!=-1,"File descriptor is in error - report a bug"); logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); logassert(!filebuffers[fd]->reading,"File descriptor was not opened for writing - report a bug"); /* Write the data */ if((filebuffers[fd]->pointer+length)>BUFFLEN) { if(write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer)!=(ssize_t)filebuffers[fd]->pointer) return(-1); filebuffers[fd]->pointer=0; } if(length>=BUFFLEN) { if(write(fd,address,length)!=(ssize_t)length) return(-1); return(0); } memcpy(filebuffers[fd]->buffer+filebuffers[fd]->pointer,address,length); filebuffers[fd]->pointer+=length; return(0); }
int SkipFileBuffered(int fd,off_t skip) { logassert(fd!=-1,"File descriptor is in error - report a bug"); logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); logassert(filebuffers[fd]->reading,"File descriptor was not opened for reading - report a bug"); /* Skip the data - needs to be optimised */ if((filebuffers[fd]->pointer+skip)>filebuffers[fd]->length) { skip-=filebuffers[fd]->length-filebuffers[fd]->pointer; filebuffers[fd]->pointer=0; filebuffers[fd]->length=0; if(lseek(fd,skip,SEEK_CUR)==-1) return(-1); } else filebuffers[fd]->pointer+=skip; return(0); }
void AddRelationRefs(int64_t node_id, int64_t way_id, int64_t relation_id, const char* role) { if (node_id == 0 && way_id == 0 && relation_id == 0) { relation_nnodes = 0; relation_nways = 0; relation_nrelations = 0; relation_from = NO_WAY_ID; relation_via = NO_NODE_ID; relation_to = NO_WAY_ID; } else if (node_id != 0) { node_t id; id = (node_t)node_id; logassert((int64_t)id == node_id, "Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */ if (relation_nnodes && (relation_nnodes % 256) == 0) relation_nodes = (node_t*)realloc((void*)relation_nodes, (relation_nnodes + 256) * sizeof(node_t)); relation_nodes[relation_nnodes++] = id; if (role) { if (!strcmp(role, "via")) relation_via = id; } } else if (way_id != 0) { way_t id; id = (way_t)way_id; logassert((int64_t)id == way_id, "Way ID too large (change way_t to 64-bits?)"); /* check way id can be stored in way_t data type. */ if (relation_nways && (relation_nways % 256) == 0) relation_ways = (way_t*)realloc((void*)relation_ways, (relation_nways + 256) * sizeof(way_t)); relation_ways[relation_nways++] = id; if (role) { if (!strcmp(role, "from")) relation_from = id; else if (!strcmp(role, "to")) relation_to = id; } } else /* if(relation_id!=0) */ { relation_t id; id = (relation_t)relation_id; logassert((int64_t)id == relation_id, "Relation ID too large (change relation_t to 64-bits?)"); /* check relation id can be stored in relation_t data type. */ if (relation_nrelations && (relation_nrelations % 256) == 0) relation_relations = (relation_t*)realloc((void*)relation_relations, (relation_nrelations + 256) * sizeof(relation_t)); relation_relations[relation_nrelations++] = relation_id; } }
int ReadFileBuffered(int fd,void *address,size_t length) { logassert(fd!=-1,"File descriptor is in error - report a bug"); logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); logassert(filebuffers[fd]->reading,"File descriptor was not opened for reading - report a bug"); /* Read the data */ if((filebuffers[fd]->pointer+length)>filebuffers[fd]->length) if(filebuffers[fd]->pointer<filebuffers[fd]->length) { memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,filebuffers[fd]->length-filebuffers[fd]->pointer); address+=filebuffers[fd]->length-filebuffers[fd]->pointer; length-=filebuffers[fd]->length-filebuffers[fd]->pointer; filebuffers[fd]->pointer=0; filebuffers[fd]->length=0; } if(length>=BUFFLEN) { if(read(fd,address,length)!=(ssize_t)length) return(-1); return(0); } if(filebuffers[fd]->pointer==filebuffers[fd]->length) { ssize_t len=read(fd,filebuffers[fd]->buffer,BUFFLEN); if(len<=0) return(-1); filebuffers[fd]->length=len; filebuffers[fd]->pointer=0; } if(filebuffers[fd]->length==0) return(-1); memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,length); filebuffers[fd]->pointer+=length; return(0); }
int SeekFileBuffered(int fd,off_t position) { logassert(fd!=-1,"File descriptor is in error - report a bug"); logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); /* Seek the data - doesn't need to be highly optimised */ if(!filebuffers[fd]->reading) if(write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer)!=(ssize_t)filebuffers[fd]->pointer) return(-1); filebuffers[fd]->pointer=0; filebuffers[fd]->length=0; if(lseek(fd,position,SEEK_SET)!=position) return(-1); return(0); }
void StartPruning(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx) { SegmentX segmentx; index_t index=0,lastnode1=NO_NODE; if(segmentsx->number==0) return; /* Print the start message */ printf_first("Adding Extra Segment Indexes: Segments=0"); /* Allocate the array of next segment */ segmentsx->next1=(index_t*)calloc(segmentsx->number,sizeof(index_t)); logassert(segmentsx->next1,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ /* Open the file read-only */ segmentsx->fd=ReOpenFileBuffered(segmentsx->filename_tmp); /* Read the on-disk image */ while(!ReadFileBuffered(segmentsx->fd,&segmentx,sizeof(SegmentX))) { index_t node1=segmentx.node1; if(index==0) ; else if(lastnode1==node1) segmentsx->next1[index-1]=index; else segmentsx->next1[index-1]=NO_SEGMENT; lastnode1=node1; index++; if(!(index%10000)) printf_middle("Added Extra Segment Indexes: Segments=%"Pindex_t,index); } segmentsx->next1[index-1]=NO_SEGMENT; /* Close the file */ segmentsx->fd=CloseFileBuffered(segmentsx->fd); /* Print the final message */ printf_last("Added Extra Segment Indexes: Segments=%"Pindex_t,segmentsx->number); }
WaysX *NewWayList(int append,int readonly) { WaysX *waysx; waysx=(WaysX*)calloc(1,sizeof(WaysX)); logassert(waysx,"Failed to allocate memory (try using slim mode?)"); /* Check calloc() worked */ waysx->filename =(char*)malloc(strlen(option_tmpdirname)+32); waysx->filename_tmp=(char*)malloc(strlen(option_tmpdirname)+32); sprintf(waysx->filename ,"%s/waysx.parsed.mem",option_tmpdirname); sprintf(waysx->filename_tmp,"%s/waysx.%p.tmp" ,option_tmpdirname,(void*)waysx); if(append || readonly) if(ExistsFile(waysx->filename)) { FILESORT_VARINT waysize; int fd; fd=ReOpenFileBuffered(waysx->filename); while(!ReadFileBuffered(fd,&waysize,FILESORT_VARSIZE)) { SkipFileBuffered(fd,waysize); waysx->number++; } CloseFileBuffered(fd); RenameFile(waysx->filename,waysx->filename_tmp); } if(append) waysx->fd=OpenFileBufferedAppend(waysx->filename_tmp); else if(!readonly) waysx->fd=OpenFileBufferedNew(waysx->filename_tmp); else waysx->fd=-1; #if SLIM waysx->cache=NewWayXCache(); #endif waysx->nfilename_tmp=(char*)malloc(strlen(option_tmpdirname)+32); sprintf(waysx->nfilename_tmp,"%s/waynames.%p.tmp",option_tmpdirname,(void*)waysx); return(waysx); }
void CompactWayList(WaysX *waysx,SegmentsX *segmentsx) { int fd; index_t cnumber; if(waysx->number==0) return; /* Print the start message */ printf_first("Sorting Ways and Compacting"); /* Allocate the array of indexes */ waysx->cdata=(index_t*)malloc(waysx->number*sizeof(index_t)); logassert(waysx->cdata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ /* Re-open the file read-only and a new file writeable */ waysx->fd=ReOpenFileBuffered(waysx->filename_tmp); DeleteFile(waysx->filename_tmp); fd=OpenFileBufferedNew(waysx->filename_tmp); /* Sort the ways to allow compacting according to the properties */ sortwaysx=waysx; sortsegmentsx=segmentsx; cnumber=filesort_fixed(waysx->fd,fd,sizeof(WayX),(int (*)(void*,index_t))delete_unused, (int (*)(const void*,const void*))sort_by_name_and_prop_and_id, (int (*)(void*,index_t))deduplicate_and_index_by_compact_id); /* Close the files */ waysx->fd=CloseFileBuffered(waysx->fd); CloseFileBuffered(fd); /* Free the data */ free(segmentsx->usedway); segmentsx->usedway=NULL; /* Print the final message */ printf_last("Sorted and Compacted Ways: Ways=%"Pindex_t" Unique=%"Pindex_t,waysx->number,cnumber); waysx->number=cnumber; }
int CloseFileBuffered(int fd) { logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); if(!filebuffers[fd]->reading) write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer); close(fd); free(filebuffers[fd]); filebuffers[fd]=NULL; return(-1); }
void AddWayRefs(int64_t node_id) { if (node_id == 0) way_nnodes = 0; else { node_t id; if (way_nnodes && (way_nnodes % 256) == 0) way_nodes = (node_t*)realloc((void*)way_nodes, (way_nnodes + 256) * sizeof(node_t)); id = (node_t)node_id; logassert((int64_t)id == node_id, "Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */ way_nodes[way_nnodes++] = id; } }
void SortWayList(WaysX *waysx) { index_t xnumber; int fd; /* Print the start message */ printf_first("Sorting Ways"); /* Re-open the file read-only and a new file writeable */ waysx->fd=ReOpenFileBuffered(waysx->filename_tmp); DeleteFile(waysx->filename_tmp); fd=OpenFileBufferedNew(waysx->filename_tmp); /* Allocate the array of indexes */ waysx->idata=(way_t*)malloc(waysx->number*sizeof(way_t)); logassert(waysx->idata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ /* Sort the ways by ID and index them */ sortwaysx=waysx; xnumber=waysx->number; waysx->number=filesort_vary(waysx->fd,fd,NULL, (int (*)(const void*,const void*))sort_by_id, (int (*)(void*,index_t))deduplicate_and_index_by_id); waysx->knumber=waysx->number; /* Close the files */ waysx->fd=CloseFileBuffered(waysx->fd); CloseFileBuffered(fd); /* Print the final message */ printf_last("Sorted Ways: Ways=%"Pindex_t" Duplicates=%"Pindex_t,xnumber,xnumber-waysx->number); }
void AppendWayList(WaysX *waysx,way_t id,Way *way,node_t *nodes,int nnodes,const char *name) { WayX wayx; FILESORT_VARINT size; node_t nonode=NO_NODE_ID; wayx.id=id; wayx.way=*way; size=sizeof(WayX)+(nnodes+1)*sizeof(node_t)+strlen(name)+1; WriteFileBuffered(waysx->fd,&size,FILESORT_VARSIZE); WriteFileBuffered(waysx->fd,&wayx,sizeof(WayX)); WriteFileBuffered(waysx->fd,nodes ,nnodes*sizeof(node_t)); WriteFileBuffered(waysx->fd,&nonode, sizeof(node_t)); WriteFileBuffered(waysx->fd,name,strlen(name)+1); waysx->number++; logassert(waysx->number!=0,"Too many ways (change index_t to 64-bits?)"); /* Zero marks the high-water mark for ways. */ }
void PruneStraightHighwayNodes(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,distance_t maximum) { index_t i; index_t npruned=0; index_t nalloc; BitMask *checked; index_t *nodes,*segments; double *lats,*lons; double maximumf; if(nodesx->number==0 || segmentsx->number==0 || waysx->number==0) return; /* Print the start message */ printf_first("Pruning Straight Highway Nodes: Nodes=0 Pruned=0"); /* Map into memory / open the files */ #if !SLIM nodesx->data=MapFile(nodesx->filename_tmp); segmentsx->data=MapFileWriteable(segmentsx->filename_tmp); waysx->data=MapFile(waysx->filename_tmp); #else nodesx->fd=SlimMapFile(nodesx->filename_tmp); segmentsx->fd=SlimMapFileWriteable(segmentsx->filename_tmp); waysx->fd=SlimMapFile(waysx->filename_tmp); InvalidateNodeXCache(nodesx->cache); InvalidateSegmentXCache(segmentsx->cache); InvalidateWayXCache(waysx->cache); #endif checked=AllocBitMask(nodesx->number); logassert(checked,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */ nodes =(index_t*)malloc((nalloc=1024)*sizeof(index_t)); segments=(index_t*)malloc( nalloc *sizeof(index_t)); logassert(nodes,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ logassert(segments,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ lats=(double*)malloc(nalloc*sizeof(double)); lons=(double*)malloc(nalloc*sizeof(double)); logassert(lats,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ logassert(lons,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ /* Loop through the nodes and find stretches of simple highway for possible modification */ maximumf=distance_to_km(maximum); for(i=0;i<nodesx->number;i++) { int lowerbounded=0,upperbounded=0; index_t lower=nalloc/2,current=nalloc/2,upper=nalloc/2; if(IsBitSet(checked,i)) goto endloop; if(segmentsx->firstnode[i]==NO_SEGMENT) goto endloop; /* Find all connected nodes */ nodes[current]=i; do { index_t node1=NO_NODE,node2=NO_NODE; index_t segment1=NO_SEGMENT,segment2=NO_SEGMENT; index_t way1=NO_WAY,way2=NO_WAY; int segcount=0; NodeX *nodex; /* Get the node data */ nodex=LookupNodeX(nodesx,nodes[current],1); lats[current]=latlong_to_radians(nodex->latitude); lons[current]=latlong_to_radians(nodex->longitude); /* Count the segments at the node if not forced to be an end node */ if(IsBitSet(checked,nodes[current])) ; else if(nodex->flags&NODE_MINIRNDBT) ; else if(nodex->flags&NODE_TURNRSTRCT2 || nodex->flags&NODE_TURNRSTRCT) ; else { SegmentX *segmentx; /* Count the segments connected to the node */ segmentx=FirstSegmentX(segmentsx,nodes[current],3); while(segmentx) { segcount++; if(node1==NO_NODE) { segment1=IndexSegmentX(segmentsx,segmentx); node1=OtherNode(segmentx,nodes[current]); way1=segmentx->way; } else if(node2==NO_NODE) { segment2=IndexSegmentX(segmentsx,segmentx); node2=OtherNode(segmentx,nodes[current]); way2=segmentx->way; } else break; segmentx=NextSegmentX(segmentsx,segmentx,nodes[current]); } } /* Check if allowed due to one-way properties */ if(segcount==2) { SegmentX *segmentx1,*segmentx2; segmentx1=LookupSegmentX(segmentsx,segment1,1); segmentx2=LookupSegmentX(segmentsx,segment2,2); if(!IsOneway(segmentx1) && !IsOneway(segmentx2)) ; else if(IsOneway(segmentx1) && IsOneway(segmentx2)) { if(IsOnewayTo(segmentx1,nodes[current]) && !IsOnewayFrom(segmentx2,nodes[current])) /* S1 is one-way but S2 doesn't continue */ segcount=0; if(IsOnewayFrom(segmentx1,nodes[current]) && !IsOnewayTo(segmentx2,nodes[current])) /* S1 is one-way but S2 doesn't continue */ segcount=0; } else segcount=0; } /* Check if allowed due to highway properties and node restrictions */ if(segcount==2) { WayX *wayx1,*wayx2; wayx1=LookupWayX(waysx,way1,1); wayx2=LookupWayX(waysx,way2,2); if(WaysCompare(&wayx1->way,&wayx2->way)) segcount=0; if(wayx1->way.name!=wayx2->way.name) segcount=0; if((nodex->allow&wayx1->way.allow)!=wayx1->way.allow) segcount=0; if((nodex->allow&wayx2->way.allow)!=wayx2->way.allow) segcount=0; } /* Update the lists */ if(segcount==2) { /* Make space in the lists */ if(upper==(nalloc-1)) { nodes =(index_t*)realloc(nodes ,(nalloc+=1024)*sizeof(index_t)); segments=(index_t*)realloc(segments, nalloc *sizeof(index_t)); lats=(double*)realloc(lats,nalloc*sizeof(double)); lons=(double*)realloc(lons,nalloc*sizeof(double)); } if(lower==0) /* move everything up by one */ { memmove(nodes+1 ,nodes ,(1+upper-lower)*sizeof(index_t)); memmove(segments+1,segments,(1+upper-lower)*sizeof(index_t)); memmove(lats+1,lats,(1+upper-lower)*sizeof(double)); memmove(lons+1,lons,(1+upper-lower)*sizeof(double)); current++; lower++; upper++; } if(lower==upper) /* first */ { lower--; nodes[lower]=node1; segments[lower]=segment1; upper++; nodes[upper]=node2; segments[upper-1]=segment2; segments[upper]=NO_SEGMENT; current--; } else if(current==lower) { lower--; if(nodes[current+1]==node2) { nodes[lower]=node1; segments[lower]=segment1; } else /* if(nodes[current+1]==node1) */ { nodes[lower]=node2; segments[lower]=segment2; } current--; } else /* if(current==upper) */ { upper++; if(nodes[current-1]==node2) { nodes[upper]=node1; segments[upper-1]=segment1; } else /* if(nodes[current-1]==node1) */ { nodes[upper]=node2; segments[upper-1]=segment2; } segments[upper]=NO_SEGMENT; current++; } if(nodes[upper]==nodes[lower]) { if(!lowerbounded && !upperbounded) { nodex=LookupNodeX(nodesx,nodes[lower],1); lats[lower]=latlong_to_radians(nodex->latitude); lons[lower]=latlong_to_radians(nodex->longitude); } lats[upper]=lats[lower]; lons[upper]=lons[lower]; lowerbounded=1; upperbounded=1; } } else /* if(segment!=2) */ { if(current==upper) upperbounded=1; if(current==lower) { lowerbounded=1; current=upper; } } } while(!(lowerbounded && upperbounded)); /* Mark the nodes */ for(current=lower;current<=upper;current++) SetBit(checked,nodes[current]); /* Check for straight highway */ for(;lower<(upper-1);lower++) { for(current=upper;current>(lower+1);current--) { SegmentX *segmentx; distance_t dist=0; double dist1,dist2,dist3,distp; index_t c; dist3=distance(lats[lower],lons[lower],lats[current],lons[current]); for(c=lower+1;c<current;c++) { dist1=distance(lats[lower] ,lons[lower] ,lats[c],lons[c]); dist2=distance(lats[current],lons[current],lats[c],lons[c]); /* Use law of cosines (assume flat Earth) */ if(dist3==0) distp=dist1; /* == dist2 */ else if((dist1+dist2)<dist3) distp=0; else { double dist3a=(dist1*dist1-dist2*dist2+dist3*dist3)/(2.0*dist3); double dist3b=dist3-dist3a; if(dist3a>=0 && dist3b>=0) distp=sqrt(dist1*dist1-dist3a*dist3a); else if(dist3a>0) distp=dist2; else /* if(dist3b>0) */ distp=dist1; } if(distp>maximumf) /* gone too far */ break; } if(c<current) /* not finished */ continue; /* Delete some segments and shift along */ for(c=lower+1;c<current;c++) { segmentx=LookupSegmentX(segmentsx,segments[c],1); dist+=DISTANCE(segmentx->distance); prune_segment(segmentsx,segmentx); npruned++; } segmentx=LookupSegmentX(segmentsx,segments[lower],1); if(nodes[lower]==nodes[current]) /* loop; all within maximum distance */ { prune_segment(segmentsx,segmentx); npruned++; } else { segmentx->distance+=dist; if(segmentx->node1==nodes[lower]) modify_segment(segmentsx,segmentx,nodes[lower],nodes[current]); else /* if(segmentx->node2==nodes[lower]) */ modify_segment(segmentsx,segmentx,nodes[current],nodes[lower]); } lower=current-1; break; } } endloop: if(!((i+1)%10000)) printf_middle("Pruning Straight Highway Nodes: Nodes=%"Pindex_t" Pruned=%"Pindex_t,i+1,npruned); } /* Unmap from memory / close the files */ free(checked); free(nodes); free(segments); free(lats); free(lons); #if !SLIM nodesx->data=UnmapFile(nodesx->data); segmentsx->data=UnmapFile(segmentsx->data); waysx->data=UnmapFile(waysx->data); #else nodesx->fd=SlimUnmapFile(nodesx->fd); segmentsx->fd=SlimUnmapFile(segmentsx->fd); waysx->fd=SlimUnmapFile(waysx->fd); #endif /* Print the final message */ printf_last("Pruned Straight Highway Nodes: Nodes=%"Pindex_t" Pruned=%"Pindex_t,nodesx->number,npruned); }
index_t filesort_vary(int fd_in,int fd_out,int (*pre_sort_function)(void*,index_t), int (*compare_function)(const void*,const void*), int (*post_sort_function)(void*,index_t)) { int *fds=NULL,*heap=NULL; int nfiles=0,ndata=0; index_t count_out=0,count_in=0,total=0; size_t datasize=option_filesort_ramsize/option_filesort_threads; FILESORT_VARINT nextitemsize,largestitemsize=0; void *data,**datap; thread_data *threads; size_t item; int i,more=1; #if defined(USE_PTHREADS) && USE_PTHREADS int nthreads=0; #endif /* Allocate the RAM buffer and other bits */ threads=(thread_data*)malloc(option_filesort_threads*sizeof(thread_data)); for(i=0;i<option_filesort_threads;i++) { threads[i].running=0; threads[i].data=malloc(datasize); threads[i].datap=NULL; threads[i].filename=(char*)malloc(strlen(option_tmpdirname)+24); threads[i].compare=compare_function; } /* Loop around, fill the buffer, sort the data and write a temporary file */ if(ReadFileBuffered(fd_in,&nextitemsize,FILESORT_VARSIZE)) /* Always have the next item size known in advance */ goto tidy_and_exit; do { size_t ramused=FILESORT_VARALIGN-FILESORT_VARSIZE; int thread=0; #if defined(USE_PTHREADS) && USE_PTHREADS if(option_filesort_threads>1) { /* Find a spare slot (one *must* be unused at all times) */ pthread_mutex_lock(&running_mutex); for(thread=0;thread<option_filesort_threads;thread++) if(!threads[thread].running) break; pthread_mutex_unlock(&running_mutex); } #endif threads[thread].datap=threads[thread].data+datasize; threads[thread].n=0; /* Read in the data and create pointers */ while((ramused+FILESORT_VARSIZE+nextitemsize)<=(unsigned)((void*)threads[thread].datap-sizeof(void*)-threads[thread].data)) { FILESORT_VARINT itemsize=nextitemsize; *(FILESORT_VARINT*)(threads[thread].data+ramused)=itemsize; ramused+=FILESORT_VARSIZE; ReadFileBuffered(fd_in,threads[thread].data+ramused,itemsize); if(!pre_sort_function || pre_sort_function(threads[thread].data+ramused,count_in)) { *--threads[thread].datap=threads[thread].data+ramused; /* points to real data */ if(itemsize>largestitemsize) largestitemsize=itemsize; ramused+=itemsize; ramused =FILESORT_VARALIGN*((ramused+FILESORT_VARSIZE-1)/FILESORT_VARALIGN); ramused+=FILESORT_VARALIGN-FILESORT_VARSIZE; total++; threads[thread].n++; } else ramused-=FILESORT_VARSIZE; count_in++; if(ReadFileBuffered(fd_in,&nextitemsize,FILESORT_VARSIZE)) { more=0; break; } } /* No new data read in this time round */ if(threads[thread].n==0) break; /* Sort the data pointers using a heap sort (potentially in a thread) */ if(more==0 && nfiles==0) threads[thread].filename[0]=0; else sprintf(threads[thread].filename,"%s/filesort.%d.tmp",option_tmpdirname,nfiles); #if defined(USE_PTHREADS) && USE_PTHREADS /* Shortcut if only one file, don't write to disk */ if(more==0 && nfiles==0) filesort_heapsort(threads[thread].datap,threads[thread].n,threads[thread].compare); else if(option_filesort_threads>1) { pthread_mutex_lock(&running_mutex); while(nthreads==(option_filesort_threads-1)) { for(i=0;i<option_filesort_threads;i++) if(threads[i].running==2) { pthread_join(threads[i].thread,NULL); threads[i].running=0; nthreads--; } if(nthreads==(option_filesort_threads-1)) pthread_cond_wait(&running_cond,&running_mutex); } threads[thread].running=1; pthread_mutex_unlock(&running_mutex); pthread_create(&threads[thread].thread,NULL,(void* (*)(void*))filesort_vary_heapsort_thread,&threads[thread]); nthreads++; } else filesort_vary_heapsort_thread(&threads[thread]); #else /* Shortcut if only one file, don't write to disk */ if(more==0 && nfiles==0) filesort_heapsort(threads[thread].datap,threads[thread].n,threads[thread].compare); else filesort_vary_heapsort_thread(&threads[thread]); #endif nfiles++; } while(more); /* Wait for all of the threads to finish */ #if defined(USE_PTHREADS) && USE_PTHREADS while(option_filesort_threads>1 && nthreads) { pthread_mutex_lock(&running_mutex); pthread_cond_wait(&running_cond,&running_mutex); for(i=0;i<option_filesort_threads;i++) if(threads[i].running==2) { pthread_join(threads[i].thread,NULL); threads[i].running=0; nthreads--; } pthread_mutex_unlock(&running_mutex); } #endif /* Shortcut if only one file, lucky for us we still have the data in RAM) */ if(nfiles==1) { for(item=0;item<threads[0].n;item++) { if(!post_sort_function || post_sort_function(threads[0].datap[item],count_out)) { FILESORT_VARINT itemsize=*(FILESORT_VARINT*)(threads[0].datap[item]-FILESORT_VARSIZE); WriteFileBuffered(fd_out,threads[0].datap[item]-FILESORT_VARSIZE,itemsize+FILESORT_VARSIZE); count_out++; } } DeleteFile(threads[0].filename); goto tidy_and_exit; } /* Check that number of files is less than file size */ largestitemsize=FILESORT_VARALIGN*(1+(largestitemsize+FILESORT_VARALIGN-FILESORT_VARSIZE)/FILESORT_VARALIGN); logassert((unsigned)nfiles<((datasize-nfiles*sizeof(void*))/largestitemsize),"Too many temporary files (use more sorting memory?)"); /* Open all of the temporary files */ fds=(int*)malloc(nfiles*sizeof(int)); for(i=0;i<nfiles;i++) { char *filename=threads[0].filename; sprintf(filename,"%s/filesort.%d.tmp",option_tmpdirname,i); fds[i]=ReOpenFileBuffered(filename); DeleteFile(filename); } /* Perform an n-way merge using a binary heap */ heap=(int*)malloc((1+nfiles)*sizeof(int)); data=threads[0].data; datap=data+datasize-nfiles*sizeof(void*); /* Fill the heap to start with */ for(i=0;i<nfiles;i++) { int index; FILESORT_VARINT itemsize; datap[i]=data+FILESORT_VARALIGN-FILESORT_VARSIZE+i*largestitemsize; ReadFileBuffered(fds[i],&itemsize,FILESORT_VARSIZE); *(FILESORT_VARINT*)(datap[i]-FILESORT_VARSIZE)=itemsize; ReadFileBuffered(fds[i],datap[i],itemsize); index=i+1; heap[index]=i; /* Bubble up the new value */ while(index>1) { int newindex; int temp; newindex=index/2; if(compare_function(datap[heap[index]],datap[heap[newindex]])>=0) break; temp=heap[index]; heap[index]=heap[newindex]; heap[newindex]=temp; index=newindex; } } /* Repeatedly pull out the root of the heap and refill from the same file */ ndata=nfiles; do { int index=1; FILESORT_VARINT itemsize; if(!post_sort_function || post_sort_function(datap[heap[index]],count_out)) { itemsize=*(FILESORT_VARINT*)(datap[heap[index]]-FILESORT_VARSIZE); WriteFileBuffered(fd_out,datap[heap[index]]-FILESORT_VARSIZE,itemsize+FILESORT_VARSIZE); count_out++; } if(ReadFileBuffered(fds[heap[index]],&itemsize,FILESORT_VARSIZE)) { heap[index]=heap[ndata]; ndata--; } else { *(FILESORT_VARINT*)(datap[heap[index]]-FILESORT_VARSIZE)=itemsize; ReadFileBuffered(fds[heap[index]],datap[heap[index]],itemsize); } /* Bubble down the new value */ while((2*index)<ndata) { int newindex; int temp; newindex=2*index; if(compare_function(datap[heap[newindex]],datap[heap[newindex+1]])>=0) newindex=newindex+1; if(compare_function(datap[heap[index]],datap[heap[newindex]])<=0) break; temp=heap[newindex]; heap[newindex]=heap[index]; heap[index]=temp; index=newindex; } if((2*index)==ndata) { int newindex; int temp; newindex=2*index; if(compare_function(datap[heap[index]],datap[heap[newindex]])<=0) ; /* break */ else { temp=heap[newindex]; heap[newindex]=heap[index]; heap[index]=temp; } } } while(ndata>0); /* Tidy up */ tidy_and_exit: if(fds) { for(i=0;i<nfiles;i++) CloseFileBuffered(fds[i]); free(fds); } if(heap) free(heap); for(i=0;i<option_filesort_threads;i++) { free(threads[i].data); free(threads[i].filename); } free(threads); return(count_out); }
void PruneIsolatedRegions(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,distance_t minimum) { WaysX *newwaysx; WayX tmpwayx; transport_t transport; BitMask *connected,*region; index_t *regionsegments,*othersegments; index_t nallocregionsegments,nallocothersegments; if(nodesx->number==0 || segmentsx->number==0) return; /* Map into memory / open the files */ #if !SLIM nodesx->data=MapFile(nodesx->filename_tmp); segmentsx->data=MapFileWriteable(segmentsx->filename_tmp); waysx->data=MapFile(waysx->filename_tmp); #else nodesx->fd=SlimMapFile(nodesx->filename_tmp); segmentsx->fd=SlimMapFileWriteable(segmentsx->filename_tmp); waysx->fd=SlimMapFile(waysx->filename_tmp); InvalidateNodeXCache(nodesx->cache); InvalidateSegmentXCache(segmentsx->cache); InvalidateWayXCache(waysx->cache); #endif newwaysx=NewWayList(0,0); CloseFileBuffered(newwaysx->fd); newwaysx->fd=SlimMapFileWriteable(newwaysx->filename_tmp); connected=AllocBitMask(segmentsx->number); region =AllocBitMask(segmentsx->number); logassert(connected,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */ logassert(region,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */ regionsegments=(index_t*)malloc((nallocregionsegments=1024)*sizeof(index_t)); othersegments =(index_t*)malloc((nallocothersegments =1024)*sizeof(index_t)); logassert(regionsegments,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ logassert(othersegments,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ /* Loop through the transport types */ for(transport=Transport_None+1;transport<Transport_Count;transport++) { index_t i,j; index_t nregions=0,npruned=0,nadjusted=0; const char *transport_str=TransportName(transport); transports_t transports=TRANSPORTS(transport); if(!(waysx->allow&transports)) continue; /* Print the start message */ printf_first("Pruning Isolated Regions (%s): Segments=0 Adjusted=0 Pruned=0",transport_str); /* Loop through the segments and find the disconnected ones */ ClearAllBits(connected,segmentsx->number); ClearAllBits(region ,segmentsx->number); for(i=0;i<segmentsx->number;i++) { index_t nregionsegments=0,nothersegments=0; distance_t total=0; SegmentX *segmentx; WayX *wayx; if(IsBitSet(connected,i)) goto endloop; segmentx=LookupSegmentX(segmentsx,i,1); if(IsPrunedSegmentX(segmentx)) goto endloop; if(segmentx->way<waysx->number) wayx=LookupWayX(waysx,segmentx->way,1); else SlimFetch(newwaysx->fd,(wayx=&tmpwayx),sizeof(WayX),(segmentx->way-waysx->number)*sizeof(WayX)); if(!(wayx->way.allow&transports)) goto endloop; othersegments[nothersegments++]=i; SetBit(region,i); do { index_t thissegment,nodes[2]; thissegment=othersegments[--nothersegments]; if(nregionsegments==nallocregionsegments) regionsegments=(index_t*)realloc(regionsegments,(nallocregionsegments+=1024)*sizeof(index_t)); regionsegments[nregionsegments++]=thissegment; segmentx=LookupSegmentX(segmentsx,thissegment,1); nodes[0]=segmentx->node1; nodes[1]=segmentx->node2; total+=DISTANCE(segmentx->distance); for(j=0;j<2;j++) { NodeX *nodex=LookupNodeX(nodesx,nodes[j],1); if(!(nodex->allow&transports)) continue; segmentx=FirstSegmentX(segmentsx,nodes[j],1); while(segmentx) { index_t segment=IndexSegmentX(segmentsx,segmentx); if(segment!=thissegment) { if(segmentx->way<waysx->number) wayx=LookupWayX(waysx,segmentx->way,1); else SlimFetch(newwaysx->fd,(wayx=&tmpwayx),sizeof(WayX),(segmentx->way-waysx->number)*sizeof(WayX)); if(wayx->way.allow&transports) { /* Already connected - finish */ if(IsBitSet(connected,segment)) { total=minimum; goto foundconnection; } /* Not in region - add to list */ if(!IsBitSet(region,segment)) { if(nothersegments==nallocothersegments) othersegments=(index_t*)realloc(othersegments,(nallocothersegments+=1024)*sizeof(index_t)); othersegments[nothersegments++]=segment; SetBit(region,segment); } } } segmentx=NextSegmentX(segmentsx,segmentx,nodes[j]); } } } while(nothersegments>0 && total<minimum); foundconnection: /* Prune the segments or mark them as connected */ if(total<minimum) /* not connected - delete them */ { nregions++; for(j=0;j<nregionsegments;j++) { SegmentX *segmentx; WayX *wayx,tmpwayx; SetBit(connected,regionsegments[j]); /* not really connected, but don't need to check again */ ClearBit(region,regionsegments[j]); segmentx=LookupSegmentX(segmentsx,regionsegments[j],1); if(segmentx->way<waysx->number) wayx=LookupWayX(waysx,segmentx->way,1); else SlimFetch(newwaysx->fd,(wayx=&tmpwayx),sizeof(WayX),(segmentx->way-waysx->number)*sizeof(WayX)); if(wayx->way.allow==transports) { prune_segment(segmentsx,segmentx); npruned++; } else { if(segmentx->way<waysx->number) /* create a new way */ { tmpwayx=*wayx; tmpwayx.way.allow&=~transports; segmentx->way=waysx->number+newwaysx->number; SlimReplace(newwaysx->fd,&tmpwayx,sizeof(WayX),(segmentx->way-waysx->number)*sizeof(WayX)); newwaysx->number++; PutBackSegmentX(segmentsx,segmentx); } else /* modify the existing one */ { tmpwayx.way.allow&=~transports; SlimReplace(newwaysx->fd,&tmpwayx,sizeof(WayX),(segmentx->way-waysx->number)*sizeof(WayX)); } nadjusted++; } } } else /* connected - mark as part of the main region */ { for(j=0;j<nregionsegments;j++) { SetBit(connected,regionsegments[j]); ClearBit(region,regionsegments[j]); } for(j=0;j<nothersegments;j++) { SetBit(connected,othersegments[j]); ClearBit(region,othersegments[j]); } } endloop: if(!((i+1)%10000)) printf_middle("Pruning Isolated Regions (%s): Segments=%"Pindex_t" Adjusted=%"Pindex_t" Pruned=%"Pindex_t" (%"Pindex_t" Regions)",transport_str,i+1,nadjusted,npruned,nregions); } /* Print the final message */ printf_last("Pruned Isolated Regions (%s): Segments=%"Pindex_t" Adjusted=%"Pindex_t" Pruned=%"Pindex_t" (%"Pindex_t" Regions)",transport_str,segmentsx->number,nadjusted,npruned,nregions); } /* Unmap from memory / close the files */ free(region); free(connected); free(regionsegments); free(othersegments); #if !SLIM nodesx->data=UnmapFile(nodesx->data); segmentsx->data=UnmapFile(segmentsx->data); waysx->data=UnmapFile(waysx->data); #else nodesx->fd=SlimUnmapFile(nodesx->fd); segmentsx->fd=SlimUnmapFile(segmentsx->fd); waysx->fd=SlimUnmapFile(waysx->fd); #endif SlimUnmapFile(newwaysx->fd); waysx->number+=newwaysx->number; waysx->fd=OpenFileBufferedAppend(waysx->filename_tmp); newwaysx->fd=ReOpenFileBuffered(newwaysx->filename_tmp); while(!ReadFileBuffered(newwaysx->fd,&tmpwayx,sizeof(WayX))) WriteFileBuffered(waysx->fd,&tmpwayx,sizeof(WayX)); CloseFileBuffered(waysx->fd); CloseFileBuffered(newwaysx->fd); FreeWayList(newwaysx,0); }
void ProcessRelationTags(TagList *tags,int64_t relation_id,int mode) { transports_t routes=Transports_None; transports_t except=Transports_None; int relation_turn_restriction=0; TurnRestriction restriction=TurnRestrict_None; relation_t id; int i; /* Convert id */ id=(relation_t)relation_id; logassert((int64_t)id==relation_id,"Relation ID too large (change relation_t to 64-bits?)"); /* check relation id can be stored in relation_t data type. */ /* Delete */ if(mode==MODE_DELETE || mode==MODE_MODIFY) { AppendRouteRelationList(relations,id,RELATION_DELETED, relation_nodes,relation_nnodes, relation_ways,relation_nways, relation_relations,relation_nrelations); AppendTurnRelationList(relations,id, relation_from,relation_to,relation_via, restriction,RELATION_DELETED); } if(mode==MODE_DELETE) return; /* Sanity check */ if(relation_nnodes==0 && relation_nways==0 && relation_nrelations==0) { logerror("Relation %"Prelation_t" has no nodes, ways or relations.\n",logerror_relation(id)); return; } /* Parse the tags */ for(i=0;i<tags->ntags;i++) { int recognised=0; char *k=tags->k[i]; char *v=tags->v[i]; switch(*k) { case 'b': if(!strcmp(k,"bicycleroute")) { if(ISTRUE(v)) routes|=Transports_Bicycle; else if(!ISFALSE(v)) logerror("Relation %"Prelation_t" has an unrecognised tag 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",logerror_relation(id),v); recognised=1; break; } break; case 'e': if(!strcmp(k,"except")) { for(i=1;i<Transport_Count;i++) if(strstr(v,TransportName(i))) except|=TRANSPORTS(i); if(except==Transports_None) logerror("Relation %"Prelation_t" has an unrecognised tag 'except' = '%s' (after tagging rules); ignoring it.\n",logerror_relation(id),v); recognised=1; break; } break; case 'f': if(!strcmp(k,"footroute")) { if(ISTRUE(v)) routes|=Transports_Foot; else if(!ISFALSE(v)) logerror("Relation %"Prelation_t" has an unrecognised tag 'footroute' = '%s' (after tagging rules); using 'no'.\n",logerror_relation(id),v); recognised=1; break; } break; case 'r': if(!strcmp(k,"restriction")) { if(!strcmp(v,"no_right_turn" )) restriction=TurnRestrict_no_right_turn; if(!strcmp(v,"no_left_turn" )) restriction=TurnRestrict_no_left_turn; if(!strcmp(v,"no_u_turn" )) restriction=TurnRestrict_no_u_turn; if(!strcmp(v,"no_straight_on" )) restriction=TurnRestrict_no_straight_on; if(!strcmp(v,"only_right_turn" )) restriction=TurnRestrict_only_right_turn; if(!strcmp(v,"only_left_turn" )) restriction=TurnRestrict_only_left_turn; if(!strcmp(v,"only_straight_on")) restriction=TurnRestrict_only_straight_on; if(restriction==TurnRestrict_None) logerror("Relation %"Prelation_t" has an unrecognised tag 'restriction' = '%s' (after tagging rules); ignoring it.\n",logerror_relation(id),v); recognised=1; break; } break; case 't': if(!strcmp(k,"type")) { if(!strcmp(v,"restriction")) relation_turn_restriction=1; /* Don't log an error for relations of types that we don't handle - there are so many */ recognised=1; break; } break; default: break; } if(!recognised) logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_relation(id),k,v); } /* Create the route relation (must store all relations that have ways or relations even if they are not routes because they might be referenced by other relations that are routes) */ if((relation_nways || relation_nrelations) && !relation_turn_restriction) AppendRouteRelationList(relations,id,routes, relation_nodes,relation_nnodes, relation_ways,relation_nways, relation_relations,relation_nrelations); /* Create the turn restriction relation. */ if(relation_turn_restriction && restriction!=TurnRestrict_None) { if(relation_from==NO_WAY_ID) { /* Extra logerror information since relation isn't stored */ if(relation_to!=NO_WAY_ID) logerror_way(relation_to); if(relation_via!=NO_NODE_ID) logerror_node(relation_via); logerror("Relation %"Prelation_t" is a turn restriction but has no 'from' way.\n",logerror_relation(id)); } if(relation_to==NO_WAY_ID) { /* Extra logerror information since relation isn't stored */ if(relation_via!=NO_NODE_ID) logerror_node(relation_via); if(relation_from!=NO_WAY_ID) logerror_way(relation_from); logerror("Relation %"Prelation_t" is a turn restriction but has no 'to' way.\n",logerror_relation(id)); } if(relation_via==NO_NODE_ID) { /* Extra logerror information since relation isn't stored */ if(relation_to!=NO_WAY_ID) logerror_way(relation_to); if(relation_from!=NO_WAY_ID) logerror_way(relation_from); logerror("Relation %"Prelation_t" is a turn restriction but has no 'via' node.\n",logerror_relation(id)); } if(relation_from!=NO_WAY_ID && relation_to!=NO_WAY_ID && relation_via!=NO_NODE_ID) AppendTurnRelationList(relations,id, relation_from,relation_to,relation_via, restriction,except); } }
void ProcessWayTags(TagList *tags,int64_t way_id,int mode) { Way way={0}; int oneway=0,area=0; int roundabout=0,lanes=0; char *name=NULL,*ref=NULL,*refname=NULL; way_t id; int i; /* Convert id */ id=(way_t)way_id; logassert((int64_t)id==way_id,"Way ID too large (change way_t to 64-bits?)"); /* check way id can be stored in way_t data type. */ /* Delete */ if(mode==MODE_DELETE || mode==MODE_MODIFY) { way.type=WAY_DELETED; AppendWayList(ways,id,&way,way_nodes,way_nnodes,""); } if(mode==MODE_DELETE) return; /* Sanity check */ if(way_nnodes==0) { logerror("Way %"Pway_t" has no nodes.\n",logerror_way(id)); return; } if(way_nnodes==1) { logerror_node(way_nodes[0]); /* Extra logerror information since way isn't stored */ logerror("Way %"Pway_t" has only one node.\n",logerror_way(id)); return; } /* Parse the tags - just look for highway */ for(i=0;i<tags->ntags;i++) { char *k=tags->k[i]; char *v=tags->v[i]; if(!strcmp(k,"highway")) { way.type=HighwayType(v); if(way.type==Highway_None) logerror("Way %"Pway_t" has an unrecognised highway type '%s' (after tagging rules); ignoring it.\n",logerror_way(id),v); break; } } /* Don't continue if this is not a highway (bypass error logging) */ if(way.type==Highway_None) return; /* Parse the tags - look for the others */ for(i=0;i<tags->ntags;i++) { int recognised=0; char *k=tags->k[i]; char *v=tags->v[i]; switch(*k) { case 'a': if(!strcmp(k,"area")) { if(ISTRUE(v)) area=1; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'area' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } break; case 'b': if(!strcmp(k,"bicycle")) { if(ISTRUE(v)) way.allow|=Transports_Bicycle; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'bicycle' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } if(!strcmp(k,"bicycleroute")) { if(ISTRUE(v)) way.props|=Properties_BicycleRoute; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } if(!strcmp(k,"bridge")) { if(ISTRUE(v)) way.props|=Properties_Bridge; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'bridge' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } break; case 'c': if(!strcmp(k,"cycleway")) { if(!strcmp(v,"opposite_lane")) way.props|=Properties_DoubleSens; recognised=1; break; } break; case 'f': if(!strcmp(k,"foot")) { if(ISTRUE(v)) way.allow|=Transports_Foot; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'foot' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } if(!strcmp(k,"footroute")) { if(ISTRUE(v)) way.props|=Properties_FootRoute; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'footroute' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } break; case 'g': if(!strcmp(k,"goods")) { if(ISTRUE(v)) way.allow|=Transports_Goods; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'goods' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } break; case 'h': if(!strcmp(k,"highway")) {recognised=1; break;} if(!strcmp(k,"horse")) { if(ISTRUE(v)) way.allow|=Transports_Horse; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'horse' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } if(!strcmp(k,"hgv")) { if(ISTRUE(v)) way.allow|=Transports_HGV; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'hgv' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } break; case 'i': if(!strcmp(k,"incline")) { /* logerror("Way %"Pway_t" has an 'incline' = '%s' \n",logerror_way(id),v); */ way.incline=pourcent_to_incline(parse_incline(id,k,v)); recognised=1; break; } break; case 'l': if(!strcmp(k,"lanes")) { int en=0; float lanesf; if(sscanf(v,"%f%n",&lanesf,&en)==1 && en && !v[en]) lanes=(int)lanesf; else logerror("Way %"Pway_t" has an unrecognised tag 'lanes' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),v); recognised=1; break; } break; case 'm': if(!strncmp(k,"max",3)) { if(!strcmp(k+3,"speed")) { way.speed=kph_to_speed(parse_speed(id,k,v)); recognised=1; break; } if(!strcmp(k+3,"weight")) { way.weight=tonnes_to_weight(parse_weight(id,k,v)); recognised=1; break; } if(!strcmp(k+3,"height")) { way.height=metres_to_height(parse_length(id,k,v)); recognised=1; break; } if(!strcmp(k+3,"width")) { way.width=metres_to_height(parse_length(id,k,v)); recognised=1; break; } if(!strcmp(k+3,"length")) { way.length=metres_to_height(parse_length(id,k,v)); recognised=1; break; } } if(!strcmp(k,"moped")) { if(ISTRUE(v)) way.allow|=Transports_Moped; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'moped' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } if(!strcmp(k,"motorcycle")) { if(ISTRUE(v)) way.allow|=Transports_Motorcycle; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'motorcycle' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } if(!strcmp(k,"motorcar")) { if(ISTRUE(v)) way.allow|=Transports_Motorcar; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'motorcar' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } if(!strcmp(k,"multilane")) { if(ISTRUE(v)) way.props|=Properties_Multilane; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'multilane' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } break; case 'n': if(!strcmp(k,"name")) { name=v; recognised=1; break; } break; case 'o': if(!strcmp(k,"oneway")) { if(ISTRUE(v)) oneway=1; else if(!strcmp(v,"-1")) oneway=-1; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'oneway' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } break; case 'p': if(!strcmp(k,"paved")) { if(ISTRUE(v)) way.props|=Properties_Paved; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'paved' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } if(!strcmp(k,"psv")) { if(ISTRUE(v)) way.allow|=Transports_PSV; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'psv' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } break; case 'r': if(!strcmp(k,"ref")) { ref=v; recognised=1; break; } if(!strcmp(k,"roundabout")) { if(ISTRUE(v)) roundabout=1; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'roundabout' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } break; case 't': if(!strcmp(k,"tunnel")) { if(ISTRUE(v)) way.props|=Properties_Tunnel; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'tunnel' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } break; case 'w': if(!strcmp(k,"wheelchair")) { if(ISTRUE(v)) way.allow|=Transports_Wheelchair; else if(!ISFALSE(v)) logerror("Way %"Pway_t" has an unrecognised tag 'wheelchair' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); recognised=1; break; } break; default: break; } if(!recognised) logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); } /* Create the way */ if(area && oneway) { logerror("Way %"Pway_t" is an area and oneway; ignoring area tagging.\n",logerror_way(id)); area=0; } if(!way.allow) return; if(oneway) { way.type|=Highway_OneWay; if(oneway==-1) for(i=0;i<way_nnodes/2;i++) { node_t temp; temp=way_nodes[i]; way_nodes[i]=way_nodes[way_nnodes-i-1]; way_nodes[way_nnodes-i-1]=temp; } } if(roundabout) way.type|=Highway_Roundabout; if(area) { way.type|=Highway_Area; if(way_nodes[0]!=way_nodes[way_nnodes-1]) logerror("Way %"Pway_t" is an area but not closed.\n",logerror_way(id)); } if(lanes) { if(oneway || (lanes/2)>1) way.props|=Properties_Multilane; if(oneway && lanes==1) way.props&=~Properties_Multilane; } if(ref && name) { refname=(char*)malloc(strlen(ref)+strlen(name)+4); sprintf(refname,"%s (%s)",name,ref); } else if(ref && !name) refname=ref; else if(!ref && name) refname=name; else /* if(!ref && !name) */ refname=""; AppendWayList(ways,id,&way,way_nodes,way_nnodes,refname); if(ref && name) free(refname); }
void ProcessNodeTags(TagList *tags,int64_t node_id,double latitude,double longitude,int mode) { transports_t allow=Transports_ALL; nodeflags_t flags=0; node_t id; int i; /* Convert id */ id=(node_t)node_id; logassert((int64_t)id==node_id,"Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */ /* Delete */ if(mode==MODE_DELETE) { AppendNodeList(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,NODE_DELETED); return; } /* Parse the tags */ for(i=0;i<tags->ntags;i++) { int recognised=0; char *k=tags->k[i]; char *v=tags->v[i]; switch(*k) { case 'b': if(!strcmp(k,"bicycle")) { if(ISFALSE(v)) allow&=~Transports_Bicycle; else if(!ISTRUE(v)) logerror("Node %"Pnode_t" has an unrecognised tag 'bicycle' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); recognised=1; break; } break; case 'f': if(!strcmp(k,"foot")) { if(ISFALSE(v)) allow&=~Transports_Foot; else if(!ISTRUE(v)) logerror("Node %"Pnode_t" has an unrecognised tag 'foot' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); recognised=1; break; } break; case 'g': if(!strcmp(k,"goods")) { if(ISFALSE(v)) allow&=~Transports_Goods; else if(!ISTRUE(v)) logerror("Node %"Pnode_t" has an unrecognised tag 'goods' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); recognised=1; break; } break; case 'h': if(!strcmp(k,"horse")) { if(ISFALSE(v)) allow&=~Transports_Horse; else if(!ISTRUE(v)) logerror("Node %"Pnode_t" has an unrecognised tag 'horse' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); recognised=1; break; } if(!strcmp(k,"hgv")) { if(ISFALSE(v)) allow&=~Transports_HGV; else if(!ISTRUE(v)) logerror("Node %"Pnode_t" has an unrecognised tag 'hgv' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); recognised=1; break; } break; case 'm': if(!strcmp(k,"moped")) { if(ISFALSE(v)) allow&=~Transports_Moped; else if(!ISTRUE(v)) logerror("Node %"Pnode_t" has an unrecognised tag 'moped' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); recognised=1; break; } if(!strcmp(k,"motorcycle")) { if(ISFALSE(v)) allow&=~Transports_Motorcycle; else if(!ISTRUE(v)) logerror("Node %"Pnode_t" has an unrecognised tag 'motorcycle' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); recognised=1; break; } if(!strcmp(k,"motorcar")) { if(ISFALSE(v)) allow&=~Transports_Motorcar; else if(!ISTRUE(v)) logerror("Node %"Pnode_t" has an unrecognised tag 'motorcar' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); recognised=1; break; } break; case 'p': if(!strcmp(k,"psv")) { if(ISFALSE(v)) allow&=~Transports_PSV; else if(!ISTRUE(v)) logerror("Node %"Pnode_t" has an unrecognised tag 'psv' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); recognised=1; break; } break; case 'r': if(!strcmp(k,"roundabout")) { if(ISTRUE(v)) flags|=NODE_MINIRNDBT; else logerror("Node %"Pnode_t" has an unrecognised tag 'roundabout' = '%s' (after tagging rules); using 'no'.\n",id,v); recognised=1; break; } break; case 'w': if(!strcmp(k,"wheelchair")) { if(ISFALSE(v)) allow&=~Transports_Wheelchair; else if(!ISTRUE(v)) logerror("Node %"Pnode_t" has an unrecognised tag 'wheelchair' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); recognised=1; break; } break; default: break; } if(!recognised) logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_node(id),k,v); } /* Create the node */ AppendNodeList(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,flags); }