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 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); }
void ChooseSuperNodes(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx) { index_t i; index_t nnodes=0; if(nodesx->number==0 || segmentsx->number==0 || waysx->number==0) return; /* Print the start message */ printf_first("Finding Super-Nodes: Nodes=0 Super-Nodes=0"); /* Allocate and set the super-node markers */ if(!nodesx->super) { nodesx->super=AllocBitMask(nodesx->number); assert(nodesx->super); /* Check AllocBitMask() worked */ SetAllBits1(nodesx->super,nodesx->number); } /* Map into memory / open the files */ #if !SLIM nodesx->data=MapFile(nodesx->filename); segmentsx->data=MapFile(segmentsx->filename); waysx->data=MapFile(waysx->filename); #else nodesx->fd=ReOpenFile(nodesx->filename); segmentsx->fd=ReOpenFile(segmentsx->filename); waysx->fd=ReOpenFile(waysx->filename); #endif /* Find super-nodes */ for(i=0;i<nodesx->number;i++) { if(IsBitSet(nodesx->super,i)) { int issuper=0; NodeX *nodex=LookupNodeX(nodesx,i,1); if(IsPrunedNodeX(nodex)) issuper=0; else if(nodex->flags&(NODE_TURNRSTRCT|NODE_TURNRSTRCT2)) issuper=1; else { int count=0,j; Way segmentway[MAX_SEG_PER_NODE]; int segmentweight[MAX_SEG_PER_NODE]; SegmentX *segmentx=FirstSegmentX(segmentsx,i,1); while(segmentx) { WayX *wayx=LookupWayX(waysx,segmentx->way,1); int nsegments; /* Segments that are loops count twice */ assert(count<MAX_SEG_PER_NODE); /* Only a limited amount of information stored. */ if(segmentx->node1==segmentx->node2) segmentweight[count]=2; else segmentweight[count]=1; segmentway[count]=wayx->way; /* If the node allows less traffic types than any connecting way then it is super */ if((wayx->way.allow&nodex->allow)!=wayx->way.allow) { issuper=1; break; } nsegments=segmentweight[count]; for(j=0;j<count;j++) if(wayx->way.allow & segmentway[j].allow) { /* If two ways are different in any attribute and there is a type of traffic that can use both then it is super */ if(WaysCompare(&segmentway[j],&wayx->way)) { issuper=1; break; } /* If there are two other segments that can be used by the same types of traffic as this one then it is super */ nsegments+=segmentweight[j]; if(nsegments>2) { issuper=1; break; } } if(issuper) break; segmentx=NextSegmentX(segmentsx,segmentx,i); count++; } } /* Mark the node as super if it is. */ if(issuper) nnodes++; else ClearBit(nodesx->super,i); } if(!((i+1)%10000)) printf_middle("Finding Super-Nodes: Nodes=%"Pindex_t" Super-Nodes=%"Pindex_t,i+1,nnodes); } /* Unmap from memory / close the files */ #if !SLIM nodesx->data=UnmapFile(nodesx->filename); segmentsx->data=UnmapFile(segmentsx->filename); waysx->data=UnmapFile(waysx->filename); #else nodesx->fd=CloseFile(nodesx->fd); segmentsx->fd=CloseFile(segmentsx->fd); waysx->fd=CloseFile(waysx->fd); #endif /* Print the final message */ printf_last("Found Super-Nodes: Nodes=%"Pindex_t" Super-Nodes=%"Pindex_t,nodesx->number,nnodes); }