int main(int argc,char** argv) { NodesX *Nodes; SegmentsX *Segments,*SuperSegments=NULL,*MergedSegments=NULL; WaysX *Ways; int iteration=0,quit=0; int max_iterations=10; char *dirname=NULL,*prefix=NULL,*tagging=NULL; int option_parse_only=0,option_process_only=0; int option_filenames=0; int arg; /* Parse the command line arguments */ for(arg=1;arg<argc;arg++) { if(!strcmp(argv[arg],"--help")) print_usage(1); else if(!strcmp(argv[arg],"--slim")) option_slim=1; else if(!strncmp(argv[arg],"--sort-ram-size=",16)) option_filesort_ramsize=atoi(&argv[arg][16]); else if(!strncmp(argv[arg],"--dir=",6)) dirname=&argv[arg][6]; else if(!strncmp(argv[arg],"--tmpdir=",9)) option_tmpdirname=&argv[arg][9]; else if(!strncmp(argv[arg],"--prefix=",9)) prefix=&argv[arg][9]; else if(!strcmp(argv[arg],"--parse-only")) option_parse_only=1; else if(!strcmp(argv[arg],"--process-only")) option_process_only=1; else if(!strncmp(argv[arg],"--max-iterations=",17)) max_iterations=atoi(&argv[arg][17]); else if(!strncmp(argv[arg],"--tagging=",10)) tagging=&argv[arg][10]; else if(argv[arg][0]=='-' && argv[arg][1]=='-') print_usage(0); else option_filenames++; } /* Check the specified command line options */ if(option_parse_only && option_process_only) print_usage(0); if(option_filenames && option_process_only) print_usage(0); if(!option_filesort_ramsize) { if(option_slim) option_filesort_ramsize=64*1024*1024; else option_filesort_ramsize=256*1024*1024; } else option_filesort_ramsize*=1024*1024; if(!option_tmpdirname) { if(!dirname) option_tmpdirname="."; else option_tmpdirname=dirname; } if(tagging && ExistsFile(tagging)) ; else if(!tagging && ExistsFile(FileName(dirname,prefix,"tagging.xml"))) tagging=FileName(dirname,prefix,"tagging.xml"); if(tagging && ParseXMLTaggingRules(tagging)) { fprintf(stderr,"Error: Cannot read the tagging rules in the file '%s'.\n",tagging); return(1); } if(!tagging) { fprintf(stderr,"Error: Cannot run without reading some tagging rules.\n"); return(1); } /* Create new node, segment and way variables */ Nodes=NewNodeList(option_parse_only||option_process_only); Segments=NewSegmentList(option_parse_only||option_process_only); Ways=NewWayList(option_parse_only||option_process_only); /* Parse the file */ if(option_filenames) { for(arg=1;arg<argc;arg++) { FILE *file; if(argv[arg][0]=='-' && argv[arg][1]=='-') continue; file=fopen(argv[arg],"rb"); if(!file) { fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",argv[arg],strerror(errno)); exit(EXIT_FAILURE); } printf("\nParse OSM Data [%s]\n==============\n\n",argv[arg]); fflush(stdout); if(ParseOSM(file,Nodes,Segments,Ways)) exit(EXIT_FAILURE); fclose(file); } } else if(!option_process_only) { printf("\nParse OSM Data\n==============\n\n"); fflush(stdout); if(ParseOSM(stdin,Nodes,Segments,Ways)) exit(EXIT_FAILURE); } if(option_parse_only) { FreeNodeList(Nodes,1); FreeSegmentList(Segments,1); FreeWayList(Ways,1); return(0); } /* Process the data */ printf("\nProcess OSM Data\n================\n\n"); fflush(stdout); /* Sort the nodes, segments and ways */ SortNodeList(Nodes); SortSegmentList(Segments); SortWayList(Ways); /* Remove bad segments (must be after sorting the nodes and segments) */ RemoveBadSegments(Nodes,Segments); /* Remove non-highway nodes (must be after removing the bad segments) */ RemoveNonHighwayNodes(Nodes,Segments); /* Measure the segments and replace node/way id with index (must be after removing non-highway nodes) */ UpdateSegments(Segments,Nodes,Ways); /* Repeated iteration on Super-Nodes and Super-Segments */ do { printf("\nProcess Super-Data (iteration %d)\n================================%s\n\n",iteration,iteration>9?"=":""); fflush(stdout); if(iteration==0) { /* Select the super-nodes */ ChooseSuperNodes(Nodes,Segments,Ways); /* Select the super-segments */ SuperSegments=CreateSuperSegments(Nodes,Segments,Ways,iteration); } else { SegmentsX *SuperSegments2; /* Select the super-nodes */ ChooseSuperNodes(Nodes,SuperSegments,Ways); /* Select the super-segments */ SuperSegments2=CreateSuperSegments(Nodes,SuperSegments,Ways,iteration); if(SuperSegments->xnumber==SuperSegments2->xnumber) quit=1; FreeSegmentList(SuperSegments,0); SuperSegments=SuperSegments2; } /* Sort the super-segments */ SortSegmentList(SuperSegments); /* Remove duplicated super-segments */ DeduplicateSegments(SuperSegments,Nodes,Ways); iteration++; if(iteration>max_iterations) quit=1; } while(!quit); /* Combine the super-segments */ printf("\nCombine Segments and Super-Segments\n===================================\n\n"); fflush(stdout); /* Merge the super-segments */ MergedSegments=MergeSuperSegments(Segments,SuperSegments); FreeSegmentList(Segments,0); FreeSegmentList(SuperSegments,0); Segments=MergedSegments; /* Rotate segments so that node1<node2 */ RotateSegments(Segments); /* Sort the segments */ SortSegmentList(Segments); /* Remove duplicated segments */ DeduplicateSegments(Segments,Nodes,Ways); /* Cross reference the nodes and segments */ printf("\nCross-Reference Nodes and Segments\n==================================\n\n"); fflush(stdout); /* Sort the node list geographically */ SortNodeListGeographically(Nodes); /* Create the real segments and nodes */ CreateRealNodes(Nodes,iteration); CreateRealSegments(Segments,Ways); /* Fix the segment and node indexes */ IndexNodes(Nodes,Segments); IndexSegments(Segments,Nodes); /* Output the results */ printf("\nWrite Out Database Files\n========================\n\n"); fflush(stdout); /* Write out the nodes */ SaveNodeList(Nodes,FileName(dirname,prefix,"nodes.mem")); FreeNodeList(Nodes,0); /* Write out the segments */ SaveSegmentList(Segments,FileName(dirname,prefix,"segments.mem")); FreeSegmentList(Segments,0); /* Write out the ways */ SaveWayList(Ways,FileName(dirname,prefix,"ways.mem")); FreeWayList(Ways,0); return(0); }
SegmentsX *CreateSuperSegments(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx) { index_t i; SegmentsX *supersegmentsx; index_t sn=0,ss=0; supersegmentsx=NewSegmentList(0); if(segmentsx->number==0 || waysx->number==0) return(supersegmentsx); /* Print the start message */ printf_first("Creating Super-Segments: Super-Nodes=0 Super-Segments=0"); /* Map into memory / open the files */ #if !SLIM segmentsx->data=MapFile(segmentsx->filename); waysx->data=MapFile(waysx->filename); #else segmentsx->fd=ReOpenFile(segmentsx->filename); waysx->fd=ReOpenFile(waysx->filename); #endif /* Create super-segments for each super-node. */ for(i=0;i<nodesx->number;i++) { if(IsBitSet(nodesx->super,i)) { SegmentX *segmentx; int count=0,match; Way prevway[MAX_SEG_PER_NODE]; segmentx=FirstSegmentX(segmentsx,i,1); while(segmentx) { WayX *wayx=LookupWayX(waysx,segmentx->way,1); /* Check that this type of way hasn't already been routed */ match=0; if(count>0) { int j; for(j=0;j<count;j++) if(!WaysCompare(&prevway[j],&wayx->way)) { match=1; break; } } assert(count<MAX_SEG_PER_NODE); /* Only a limited amount of history stored. */ prevway[count++]=wayx->way; /* Route the way and store the super-segments. */ if(!match) { Results *results=FindRoutesWay(nodesx,segmentsx,waysx,i,&wayx->way); Result *result=FirstResult(results); while(result) { if(IsBitSet(nodesx->super,result->node) && result->segment!=NO_SEGMENT) { if(wayx->way.type&Way_OneWay && result->node!=i) AppendSegment(supersegmentsx,segmentx->way,i,result->node,DISTANCE((distance_t)result->score)|ONEWAY_1TO2); else AppendSegment(supersegmentsx,segmentx->way,i,result->node,DISTANCE((distance_t)result->score)); ss++; } result=NextResult(results,result); } FreeResultsList(results); } segmentx=NextSegmentX(segmentsx,segmentx,i); } sn++; if(!(sn%10000)) printf_middle("Creating Super-Segments: Super-Nodes=%"Pindex_t" Super-Segments=%"Pindex_t,sn,ss); } } /* Unmap from memory / close the files */ #if !SLIM segmentsx->data=UnmapFile(segmentsx->filename); waysx->data=UnmapFile(waysx->filename); #else segmentsx->fd=CloseFile(segmentsx->fd); waysx->fd=CloseFile(waysx->fd); #endif /* Print the final message */ printf_last("Created Super-Segments: Super-Nodes=%"Pindex_t" Super-Segments=%"Pindex_t,sn,ss); return(supersegmentsx); }
SegmentsX *MergeSuperSegments(SegmentsX *segmentsx,SegmentsX *supersegmentsx) { index_t i,j; index_t merged=0,added=0; SegmentsX *mergedsegmentsx; mergedsegmentsx=NewSegmentList(0); if(segmentsx->number==0) return(mergedsegmentsx); /* Print the start message */ printf_first("Merging Segments: Segments=0 Super=0 Merged=0 Added=0"); /* Map into memory / open the files */ #if !SLIM segmentsx->data=MapFile(segmentsx->filename); if(supersegmentsx->number>0) supersegmentsx->data=MapFile(supersegmentsx->filename); #else segmentsx->fd=ReOpenFile(segmentsx->filename); if(supersegmentsx->number>0) supersegmentsx->fd=ReOpenFile(supersegmentsx->filename); #endif /* Loop through and create a new list of combined segments */ for(i=0,j=0;i<segmentsx->number;i++) { int super=0; SegmentX *segmentx=LookupSegmentX(segmentsx,i,1); while(j<supersegmentsx->number) { SegmentX *supersegmentx=LookupSegmentX(supersegmentsx,j,1); if(segmentx->node1 ==supersegmentx->node1 && segmentx->node2 ==supersegmentx->node2 && segmentx->distance==supersegmentx->distance) { merged++; j++; /* mark as super-segment and normal segment */ super=1; break; } else if((segmentx->node1==supersegmentx->node1 && segmentx->node2==supersegmentx->node2) || (segmentx->node1==supersegmentx->node1 && segmentx->node2>supersegmentx->node2) || (segmentx->node1>supersegmentx->node1)) { /* mark as super-segment */ AppendSegment(mergedsegmentsx,supersegmentx->way,supersegmentx->node1,supersegmentx->node2,supersegmentx->distance|SEGMENT_SUPER); added++; j++; } else { /* mark as normal segment */ break; } } if(super) AppendSegment(mergedsegmentsx,segmentx->way,segmentx->node1,segmentx->node2,segmentx->distance|SEGMENT_SUPER|SEGMENT_NORMAL); else AppendSegment(mergedsegmentsx,segmentx->way,segmentx->node1,segmentx->node2,segmentx->distance|SEGMENT_NORMAL); if(!((i+1)%10000)) printf_middle("Merging Segments: Segments=%"Pindex_t" Super=%"Pindex_t" Merged=%"Pindex_t" Added=%"Pindex_t,i+1,j,merged,added); } /* Unmap from memory / close the files */ #if !SLIM segmentsx->data=UnmapFile(segmentsx->filename); if(supersegmentsx->number>0) supersegmentsx->data=UnmapFile(supersegmentsx->filename); #else segmentsx->fd=CloseFile(segmentsx->fd); if(supersegmentsx->number>0) supersegmentsx->fd=CloseFile(supersegmentsx->fd); #endif /* Print the final message */ printf_last("Merged Segments: Segments=%"Pindex_t" Super=%"Pindex_t" Merged=%"Pindex_t" Added=%"Pindex_t,segmentsx->number,supersegmentsx->number,merged,added); return(mergedsegmentsx); }
SegmentsX *SplitWays(WaysX *waysx,NodesX *nodesx,int keep) { SegmentsX *segmentsx; index_t i; int fd,nfd; char *name=NULL; int namelen=0; /* Print the start message */ printf_first("Splitting Ways: Ways=0 Segments=0"); segmentsx=NewSegmentList(); /* Re-open the file read-only and a new file writeable */ waysx->fd=ReOpenFileBuffered(waysx->filename_tmp); if(keep) RenameFile(waysx->filename_tmp,waysx->filename); else DeleteFile(waysx->filename_tmp); fd=OpenFileBufferedNew(waysx->filename_tmp); nfd=OpenFileBufferedNew(waysx->nfilename_tmp); /* Loop through the ways and create the segments and way names */ for(i=0;i<waysx->number;i++) { WayX wayx; FILESORT_VARINT size; node_t node,prevnode=NO_NODE_ID; index_t index,previndex=NO_NODE; ReadFileBuffered(waysx->fd,&size,FILESORT_VARSIZE); ReadFileBuffered(waysx->fd,&wayx,sizeof(WayX)); waysx->allow|=wayx.way.allow; while(!ReadFileBuffered(waysx->fd,&node,sizeof(node_t)) && node!=NO_NODE_ID) { index=IndexNodeX(nodesx,node); if(prevnode==node) { logerror("Way %"Pway_t" contains node %"Pnode_t" that is connected to itself.\n",logerror_way(wayx.id),logerror_node(node)); } else if(index==NO_NODE) { logerror("Way %"Pway_t" contains node %"Pnode_t" that does not exist in the Routino database.\n",logerror_way(wayx.id),logerror_node(node)); } else if(previndex==NO_NODE) ; else { distance_t segment_flags=0; if(wayx.way.type&Highway_OneWay) segment_flags|=ONEWAY_1TO2; if(wayx.way.type&Highway_Area) segment_flags|=SEGMENT_AREA; AppendSegmentList(segmentsx,i,previndex,index,segment_flags); } prevnode=node; previndex=index; size-=sizeof(node_t); } size-=sizeof(node_t)+sizeof(WayX); if(namelen<size) name=(char*)realloc((void*)name,namelen=size); ReadFileBuffered(waysx->fd,name,size); WriteFileBuffered(fd,&wayx,sizeof(WayX)); size+=sizeof(index_t); WriteFileBuffered(nfd,&size,FILESORT_VARSIZE); WriteFileBuffered(nfd,&i,sizeof(index_t)); WriteFileBuffered(nfd,name,size-sizeof(index_t)); if(!((i+1)%1000)) printf_middle("Splitting Ways: Ways=%"Pindex_t" Segments=%"Pindex_t,i+1,segmentsx->number); } FinishSegmentList(segmentsx); if(name) free(name); /* Close the files */ waysx->fd=CloseFileBuffered(waysx->fd); CloseFileBuffered(fd); CloseFileBuffered(nfd); /* Print the final message */ printf_last("Split Ways: Ways=%"Pindex_t" Segments=%"Pindex_t,waysx->number,segmentsx->number); return(segmentsx); }