int InsertNodeInTree(TreeNode *node) { if (root == NULL) { TreeNode *node = calloc(sizeof(TreeNode), 1); VerifyPointerOrTerminate(node, "root TreeNode during insert"); node->name[0] = '.'; root = node; } // Make sure node doesn't exist if (LookupNode(node->name) != NULL) { printf("ERROR: node already exists\n"); return -1; } // Make sure name isn't blank if (node->name[0] == '\0') { printf("ERROR: Name cannot be blank\n"); return -1; } // Lookup parent node char local_name[64]; memcpy(local_name, node->name, sizeof(local_name)); char *last_part = strrchr(local_name, '.'); TreeNode *insert_location = root; // If no subparts in name, insert as child to root if (last_part == NULL) { if (insert_location->child == NULL) { insert_location->child = node; } else { insert_location = insert_location->child; while (insert_location->peer != NULL) { insert_location = insert_location->peer; } insert_location->peer = node; } return 0; } // Strip leading portion of name strncpy(node->name, last_part + 1, sizeof(node->name)); last_part[0] = '\0'; insert_location = LookupNode(local_name); if (insert_location == NULL) { printf("ERROR: Parent node doesn't exist: @s\n", local_name); return -1; } if (insert_location->child == NULL) { insert_location->child = node; return 0; } else { insert_location = insert_location->child; while (insert_location->peer != NULL) { insert_location = insert_location->peer; } insert_location->peer = node; return 0; } }
static void find_all_nodes(Nodes *nodes,callback_t callback) { ll_bin_t latminbin=latlong_to_bin(radians_to_latlong(LatMin))-nodes->file.latzero; ll_bin_t latmaxbin=latlong_to_bin(radians_to_latlong(LatMax))-nodes->file.latzero; ll_bin_t lonminbin=latlong_to_bin(radians_to_latlong(LonMin))-nodes->file.lonzero; ll_bin_t lonmaxbin=latlong_to_bin(radians_to_latlong(LonMax))-nodes->file.lonzero; ll_bin_t latb,lonb; index_t i,index1,index2; /* Loop through all of the nodes. */ for(latb=latminbin;latb<=latmaxbin;latb++) for(lonb=lonminbin;lonb<=lonmaxbin;lonb++) { ll_bin2_t llbin=lonb*nodes->file.latbins+latb; if(llbin<0 || llbin>(nodes->file.latbins*nodes->file.lonbins)) continue; index1=LookupNodeOffset(nodes,llbin); index2=LookupNodeOffset(nodes,llbin+1); for(i=index1;i<index2;i++) { Node *node=LookupNode(nodes,i,1); double lat=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb)+off_to_latlong(node->latoffset)); double lon=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb)+off_to_latlong(node->lonoffset)); if(lat>LatMin && lat<LatMax && lon>LonMin && lon<LonMax) (*callback)(i,lat,lon); } } }
static void output_oneway(index_t node,double latitude,double longitude) { Node *nodep=LookupNode(OSMNodes,node,1); Segment *segment; segment=FirstSegment(OSMSegments,nodep,1); do { if(IsNormalSegment(segment)) { index_t othernode=OtherNode(segment,node); if(node>othernode) { double lat,lon; GetLatLong(OSMNodes,othernode,&lat,&lon); if(IsOnewayFrom(segment,node)) printf("%.6f %.6f %.6f %.6f\n",radians_to_degrees(latitude),radians_to_degrees(longitude),radians_to_degrees(lat),radians_to_degrees(lon)); else if(IsOnewayFrom(segment,othernode)) printf("%.6f %.6f %.6f %.6f\n",radians_to_degrees(lat),radians_to_degrees(lon),radians_to_degrees(latitude),radians_to_degrees(longitude)); } } segment=NextSegment(OSMSegments,segment,node); } while(segment); }
static void output_super(index_t node,double latitude,double longitude) { Node *nodep=LookupNode(OSMNodes,node,1); Segment *segment; if(!IsSuperNode(nodep)) return; printf("%.6f %.6f n\n",radians_to_degrees(latitude),radians_to_degrees(longitude)); segment=FirstSegment(OSMSegments,nodep,1); do { if(IsSuperSegment(segment)) { index_t othernode=OtherNode(segment,node); double lat,lon; GetLatLong(OSMNodes,othernode,&lat,&lon); if(node>othernode || (lat<LatMin || lat>LatMax || lon<LonMin || lon>LonMax)) printf("%.6f %.6f s\n",radians_to_degrees(lat),radians_to_degrees(lon)); } segment=NextSegment(OSMSegments,segment,node); } while(segment); }
static void output_junctions(index_t node,double latitude,double longitude) { Node *nodep=LookupNode(OSMNodes,node,1); Segment *segment; Way *firstway; int count=0,difference=0; segment=FirstSegment(OSMSegments,nodep,1); firstway=LookupWay(OSMWays,segment->way,1); do { Way *way=LookupWay(OSMWays,segment->way,2); if(IsNormalSegment(segment)) count++; if(WaysCompare(firstway,way)) difference=1; segment=NextSegment(OSMSegments,segment,node); } while(segment); if(count!=2 || difference) printf("%.6f %.6f %d\n",radians_to_degrees(latitude),radians_to_degrees(longitude),count); }
int DeleteNode(char *name) { TreeNode *node, *parent; // Lookup node node = LookupNode(name); if (node == NULL) { printf("ERROR: Could not locate node for deletion\n"); return -1; } // Lookup parent node char local_name[64]; memcpy(local_name, name, sizeof(local_name)); char *last_part = strrchr(local_name, '.'); if (last_part == NULL) { parent = root; } else { last_part[0] = '\0'; parent = LookupNode(local_name); } if (node == NULL || parent == NULL) { return -1; } // Take node out of tree if (parent->child == NULL) { return -1; } else if (parent->child == node) { parent->child = node->peer; node->peer = NULL; } else { TreeNode *prev = parent->child; while (prev->peer != node && prev != NULL) { prev = prev->peer; } if (prev == NULL) { printf("ERROR: Could not locate node for deletion\n"); return -1; } prev->peer = node->peer; node->peer = NULL; } FreeTree(node); return 0; }
int PrintTree(char *name) { TreeNode *start; if (name == NULL || name[0]=='\0') { start = root; } else { start = LookupNode(name); } if (start == NULL) { printf("ERROR: Tree not found: @s\n", name); return -1; } WalkTree(start); return 0; }
static void output_turnrestriction(index_t node,double latitude,double longitude) { Node *nodep=LookupNode(OSMNodes,node,1); index_t turnrelation=NO_RELATION; if(!IsTurnRestrictedNode(nodep)) return; turnrelation=FindFirstTurnRelation1(OSMRelations,node); do { TurnRelation *relation; Segment *from_segment,*to_segment; index_t from_node,to_node; double from_lat,from_lon,to_lat,to_lon; relation=LookupTurnRelation(OSMRelations,turnrelation,1); from_segment=LookupSegment(OSMSegments,relation->from,1); to_segment =LookupSegment(OSMSegments,relation->to ,2); from_node=OtherNode(from_segment,node); to_node=OtherNode(to_segment,node); GetLatLong(OSMNodes,from_node,&from_lat,&from_lon); GetLatLong(OSMNodes,to_node,&to_lat,&to_lon); printf("%.6f %.6f %.6f %.6f %.6f %.6f\n",radians_to_degrees(from_lat),radians_to_degrees(from_lon), radians_to_degrees(latitude),radians_to_degrees(longitude), radians_to_degrees(to_lat),radians_to_degrees(to_lon)); turnrelation=FindNextTurnRelation1(OSMRelations,turnrelation); } while(turnrelation!=NO_RELATION); }
int CGnuInfoDoc::scanfile(CGnuInfoFile *file, const char *name, const char *parent) { if (!file->file.Open(name, CFile::modeRead| CFile::typeBinary)) { /* Cant find this file, try again with the parents root */ CString trypath ; trypath = parent; int l = trypath.ReverseFind('\\'); l ++; trypath = trypath.Left(l); trypath += name; if (!file->file.Open(trypath, CFile::modeRead| CFile::typeBinary)) return FALSE; } int c = file->gc(); while (c > 0) { if (c != 037) c = file->gc(); else { long off = file->where(); int len = 0; char buf1[200]; c = file->gc(); c = file->gc(); while (c != '\n' && len < sizeof(buf1)-1) { buf1[len++] = c; c = file->gc(); } buf1[len]=0; /* Scan out the node if there is one */ if (buf1[0] == 'I') { c = file->gc(); /* This is the start of an indirect file list, process each sub file too until another esc is reached */ while (c != 037) { int i = 0; while (c != ':') { buf1[i++] = c; c = file->gc(); } buf1[i++] = 0; while (c != '\n') c = file->gc(); c = file->gc(); CGnuInfoFile *n = new CGnuInfoFile(); if (! scanfile (n,buf1, parent)) { char buf[20]; sprintf(buf,"not found %s", buf1); CGnuInfoNode *node = new CGnuInfoNode(buf); node->init (0,0,0, file, off, npages); vector.SetAtGrow(npages, node); npages++; } else { n->next = head; head = n; } } } else if (buf1[0] == 'F') { char *f; char *next; char *prev; char *nodename; char *up; int i =0; i = get(buf1, i, "File:", &f); i = get(buf1, i, "Node:", &nodename); i = get(buf1, i, "Next:", &next); i = get(buf1, i, "Prev:", &prev); i = get(buf1, i, "Up:", &up); CGnuInfoNode *node = LookupNode(nodename); node->init (LookupNode(up), LookupNode(prev), LookupNode(next), file, file->where(), npages); if (!nodes) nodes = node; vector.SetAtGrow(npages, node); npages++; } } } open = 1; return TRUE; }
static void output_limits(index_t node,double latitude,double longitude) { Node *nodep=LookupNode(OSMNodes,node,1); Segment *segment,segments[MAX_SEG_PER_NODE]; int limits[MAX_SEG_PER_NODE]; int count=0; int i,j,same=0; segment=FirstSegment(OSMSegments,nodep,1); do { if(IsNormalSegment(segment) && count<MAX_SEG_PER_NODE) { Way *way=LookupWay(OSMWays,segment->way,1); segments[count]=*segment; switch(limit_type) { case SPEED_LIMIT: limits[count]=way->speed; break; case WEIGHT_LIMIT: limits[count]=way->weight; break; case HEIGHT_LIMIT: limits[count]=way->height; break; case WIDTH_LIMIT: limits[count]=way->width; break; case LENGTH_LIMIT: limits[count]=way->length; break; } if(limits[count] || HIGHWAY(way->type)<Way_Track) count++; } segment=NextSegment(OSMSegments,segment,node); } while(segment); /* Nodes with only one limit are not interesting */ if(count==1) return; /* Nodes with all segments the same limit are not interesting */ same=0; for(j=0;j<count;j++) if(limits[0]==limits[j]) same++; if(same==count) return; /* Display the interesting limits */ printf("%.6f %.6f\n",radians_to_degrees(latitude),radians_to_degrees(longitude)); for(i=0;i<count;i++) { same=0; for(j=0;j<count;j++) if(limits[i]==limits[j]) same++; if(count==2 || same!=(count-1)) { double lat,lon; GetLatLong(OSMNodes,OtherNode(&segments[i],node),&lat,&lon); switch(limit_type) { case SPEED_LIMIT: printf("%.6f %.6f %d\n",radians_to_degrees(lat),radians_to_degrees(lon),speed_to_kph(limits[i])); break; case WEIGHT_LIMIT: printf("%.6f %.6f %.1f\n",radians_to_degrees(lat),radians_to_degrees(lon),weight_to_tonnes(limits[i])); break; case HEIGHT_LIMIT: printf("%.6f %.6f %.1f\n",radians_to_degrees(lat),radians_to_degrees(lon),height_to_metres(limits[i])); break; case WIDTH_LIMIT: printf("%.6f %.6f %.1f\n",radians_to_degrees(lat),radians_to_degrees(lon),width_to_metres(limits[i])); break; case LENGTH_LIMIT: printf("%.6f %.6f %.1f\n",radians_to_degrees(lat),radians_to_degrees(lon),length_to_metres(limits[i])); break; } } } }
index_t FindClosestSegmentHeading(Nodes *nodes,Segments *segments,Ways *ways,index_t node1,double heading,Profile *profile) { Segment *segmentp; index_t best_seg=NO_SEGMENT; double best_difference=360; if(IsFakeNode(node1)) segmentp=FirstFakeSegment(node1); else { Node *nodep=LookupNode(nodes,node1,3); segmentp=FirstSegment(segments,nodep,1); } while(segmentp) { Way *wayp; index_t node2,seg2; double bearing,difference; node2=OtherNode(segmentp,node1); /* need this here because we use node2 at the end of the loop */ if(!IsNormalSegment(segmentp)) goto endloop; if(IsFakeNode(node1) || IsFakeNode(node2)) seg2=IndexFakeSegment(segmentp); else seg2=IndexSegment(segments,segmentp); wayp=LookupWay(ways,segmentp->way,1); if(!(wayp->allow&profile->allow)) goto endloop; if(profile->oneway && IsOnewayFrom(segmentp,node1)) { if(profile->allow!=Transports_Bicycle) goto endloop; if(!(wayp->type&Highway_CycleBothWays)) goto endloop; } bearing=BearingAngle(nodes,segmentp,node1); difference=(heading-bearing); if(difference<-180) difference+=360; if(difference> 180) difference-=360; if(difference<0) difference=-difference; if(difference<best_difference) { best_difference=difference; best_seg=seg2; } endloop: if(IsFakeNode(node1)) segmentp=NextFakeSegment(segmentp,node1); else if(IsFakeNode(node2)) segmentp=NULL; /* cannot call NextSegment() with a fake segment */ else segmentp=NextSegment(segments,segmentp,node1); } return(best_seg); }
void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,Ways *ways,Profile *profile) { FILE *htmlfile=NULL,*gpxtrackfile=NULL,*gpxroutefile=NULL,*textfile=NULL,*textallfile=NULL; char *prev_bearing=NULL,*prev_wayname=NULL; distance_t cum_distance=0; duration_t cum_duration=0; int point=1; int segment_count=0,route_count=0; int point_count=0; int roundabout=0; /* Open the files */ if(option_quickest==0) { /* Print the result for the shortest route */ if(option_html) htmlfile =fopen("shortest.html","w"); if(option_gpx_track) gpxtrackfile=fopen("shortest-track.gpx","w"); if(option_gpx_route) gpxroutefile=fopen("shortest-route.gpx","w"); if(option_text) textfile =fopen("shortest.txt","w"); if(option_text_all) textallfile =fopen("shortest-all.txt","w"); if(option_html && !htmlfile) fprintf(stderr,"Warning: Cannot open file 'shortest.html' for writing [%s].\n",strerror(errno)); if(option_gpx_track && !gpxtrackfile) fprintf(stderr,"Warning: Cannot open file 'shortest-track.gpx' for writing [%s].\n",strerror(errno)); if(option_gpx_route && !gpxroutefile) fprintf(stderr,"Warning: Cannot open file 'shortest-route.gpx' for writing [%s].\n",strerror(errno)); if(option_text && !textfile) fprintf(stderr,"Warning: Cannot open file 'shortest.txt' for writing [%s].\n",strerror(errno)); if(option_text_all && !textallfile) fprintf(stderr,"Warning: Cannot open file 'shortest-all.txt' for writing [%s].\n",strerror(errno)); } else { /* Print the result for the quickest route */ if(option_html) htmlfile =fopen("quickest.html","w"); if(option_gpx_track) gpxtrackfile=fopen("quickest-track.gpx","w"); if(option_gpx_route) gpxroutefile=fopen("quickest-route.gpx","w"); if(option_text) textfile =fopen("quickest.txt","w"); if(option_text_all) textallfile =fopen("quickest-all.txt","w"); if(option_html && !htmlfile) fprintf(stderr,"Warning: Cannot open file 'quickest.html' for writing [%s].\n",strerror(errno)); if(option_gpx_track && !gpxtrackfile) fprintf(stderr,"Warning: Cannot open file 'quickest-track.gpx' for writing [%s].\n",strerror(errno)); if(option_gpx_route && !gpxroutefile) fprintf(stderr,"Warning: Cannot open file 'quickest-route.gpx' for writing [%s].\n",strerror(errno)); if(option_text && !textfile) fprintf(stderr,"Warning: Cannot open file 'quickest.txt' for writing [%s].\n",strerror(errno)); if(option_text_all && !textallfile) fprintf(stderr,"Warning: Cannot open file 'quickest-all.txt' for writing [%s].\n",strerror(errno)); } /* Print the head of the files */ if(htmlfile) { fprintf(htmlfile,"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n"); fprintf(htmlfile,"<HTML>\n"); if(translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1]) fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); if(translate_xml_copyright_source[0] && translate_xml_copyright_source[1]) fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_source[0],translate_xml_copyright_source[1]); if(translate_xml_copyright_license[0] && translate_xml_copyright_license[1]) fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_license[0],translate_xml_copyright_license[1]); fprintf(htmlfile,"<HEAD>\n"); fprintf(htmlfile,"<TITLE>"); fprintf(htmlfile,translate_html_title,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); fprintf(htmlfile,"</TITLE>\n"); fprintf(htmlfile,"<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"); fprintf(htmlfile,"<STYLE type=\"text/css\">\n"); fprintf(htmlfile,"<!--\n"); fprintf(htmlfile," table {table-layout: fixed; border: none; border-collapse: collapse;}\n"); fprintf(htmlfile," table.c {color: grey; font-size: x-small;} /* copyright */\n"); fprintf(htmlfile," tr {border: 0px;}\n"); fprintf(htmlfile," tr.c {display: none;} /* coords */\n"); fprintf(htmlfile," tr.n {} /* node */\n"); fprintf(htmlfile," tr.s {} /* segment */\n"); fprintf(htmlfile," tr.t {font-weight: bold;} /* total */\n"); fprintf(htmlfile," td.l {font-weight: bold;}\n"); fprintf(htmlfile," td.r {}\n"); fprintf(htmlfile," span.w {font-weight: bold;} /* waypoint */\n"); fprintf(htmlfile," span.h {text-decoration: underline;} /* highway */\n"); fprintf(htmlfile," span.d {} /* segment distance */\n"); fprintf(htmlfile," span.j {font-style: italic;} /* total journey distance */\n"); fprintf(htmlfile," span.t {font-variant: small-caps;} /* turn */\n"); fprintf(htmlfile," span.b {font-variant: small-caps;} /* bearing */\n"); fprintf(htmlfile,"-->\n"); fprintf(htmlfile,"</STYLE>\n"); fprintf(htmlfile,"</HEAD>\n"); fprintf(htmlfile,"<BODY>\n"); fprintf(htmlfile,"<H1>"); fprintf(htmlfile,translate_html_title,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); fprintf(htmlfile,"</H1>\n"); fprintf(htmlfile,"<table>\n"); } if(gpxtrackfile) { fprintf(gpxtrackfile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); fprintf(gpxtrackfile,"<gpx version=\"1.1\" creator=\"Routino\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/1\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n"); fprintf(gpxtrackfile,"<metadata>\n"); fprintf(gpxtrackfile,"<desc>%s : %s</desc>\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); if(translate_xml_copyright_source[1]) { fprintf(gpxtrackfile,"<copyright author=\"%s\">\n",translate_xml_copyright_source[1]); if(translate_xml_copyright_license[1]) fprintf(gpxtrackfile,"<license>%s</license>\n",translate_xml_copyright_license[1]); fprintf(gpxtrackfile,"</copyright>\n"); } fprintf(gpxtrackfile,"</metadata>\n"); fprintf(gpxtrackfile,"<trk>\n"); fprintf(gpxtrackfile,"<name>"); fprintf(gpxtrackfile,translate_gpx_name,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); fprintf(gpxtrackfile,"</name>\n"); fprintf(gpxtrackfile,"<desc>"); fprintf(gpxtrackfile,translate_gpx_desc,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); fprintf(gpxtrackfile,"</desc>\n"); } if(gpxroutefile) { fprintf(gpxroutefile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); fprintf(gpxroutefile,"<gpx version=\"1.1\" creator=\"Routino\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/1\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n"); fprintf(gpxroutefile,"<metadata>\n"); fprintf(gpxroutefile,"<desc>%s : %s</desc>\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); if(translate_xml_copyright_source[1]) { fprintf(gpxroutefile,"<copyright author=\"%s\">\n",translate_xml_copyright_source[1]); if(translate_xml_copyright_license[1]) fprintf(gpxroutefile,"<license>%s</license>\n",translate_xml_copyright_license[1]); fprintf(gpxroutefile,"</copyright>\n"); } fprintf(gpxroutefile,"</metadata>\n"); fprintf(gpxroutefile,"<rte>\n"); fprintf(gpxroutefile,"<name>"); fprintf(gpxroutefile,translate_gpx_name,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); fprintf(gpxroutefile,"</name>\n"); fprintf(gpxroutefile,"<desc>"); fprintf(gpxroutefile,translate_gpx_desc,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); fprintf(gpxroutefile,"</desc>\n"); } if(textfile) { if(translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) fprintf(textfile,"# %s : %s\n",translate_raw_copyright_creator[0],translate_raw_copyright_creator[1]); if(translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) fprintf(textfile,"# %s : %s\n",translate_raw_copyright_source[0],translate_raw_copyright_source[1]); if(translate_raw_copyright_license[0] && translate_raw_copyright_license[1]) fprintf(textfile,"# %s : %s\n",translate_raw_copyright_license[0],translate_raw_copyright_license[1]); if((translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) || (translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) || (translate_raw_copyright_license[0] && translate_raw_copyright_license[1])) fprintf(textfile,"#\n"); fprintf(textfile,"#Latitude\tLongitude\tSection \tSection \tTotal \tTotal \tPoint\tTurn\tBearing\tHighway\n"); fprintf(textfile,"# \t \tDistance\tDuration\tDistance\tDuration\tType \t \t \t \n"); /* "%10.6f\t%11.6f\t%6.3f km\t%4.1f min\t%5.1f km\t%4.0f min\t%s\t %+d\t %+d\t%s\n" */ } if(textallfile) { if(translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_creator[0],translate_raw_copyright_creator[1]); if(translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_source[0],translate_raw_copyright_source[1]); if(translate_raw_copyright_license[0] && translate_raw_copyright_license[1]) fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_license[0],translate_raw_copyright_license[1]); if((translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) || (translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) || (translate_raw_copyright_license[0] && translate_raw_copyright_license[1])) fprintf(textallfile,"#\n"); fprintf(textallfile,"#Latitude\tLongitude\t Node\tType\tSegment\tSegment\tTotal\tTotal \tSpeed\tBearing\tHighway\n"); fprintf(textallfile,"# \t \t \t \tDist \tDurat'n\tDist \tDurat'n\t \t \t \n"); /* "%10.6f\t%11.6f\t%8d%c\t%s\t%5.3f\t%5.2f\t%5.2f\t%5.1f\t%3d\t%4d\t%s\n" */ } /* Loop through all the sections of the route and print them */ while(!results[point]) point++; while(point<=nresults) { int next_point=point; distance_t junc_distance=0; duration_t junc_duration=0; Result *result; result=FindResult(results[point],results[point]->start_node,results[point]->prev_segment); /* Print the start of the segment */ if(gpxtrackfile) fprintf(gpxtrackfile,"<trkseg>\n"); /* Loop through all the points within a section of the route and print them */ do { double latitude,longitude; Node *resultnode=NULL; index_t realsegment=NO_SEGMENT,next_realsegment=NO_SEGMENT; Segment *resultsegment=NULL,*next_resultsegment=NULL; Way *resultway=NULL,*next_resultway=NULL; Result *next_result; int important=IMP_UNIMPORTANT; distance_t seg_distance=0; duration_t seg_duration=0; speed_t seg_speed=0; char *waynameraw=NULL,*wayname=NULL,*next_waynameraw=NULL,*next_wayname=NULL; int bearing_int=0,turn_int=0,next_bearing_int=0; char *turn=NULL,*next_bearing=NULL; /* Calculate the information about this point */ if(IsFakeNode(result->node)) GetFakeLatLong(result->node,&latitude,&longitude); else GetLatLong(nodes,result->node,&latitude,&longitude); if(!IsFakeNode(result->node)) resultnode=LookupNode(nodes,result->node,6); /* Calculate the next result */ next_result=result->next; if(!next_result) for(next_point=point+1; next_point<=nresults; next_point++) if(results[next_point]) { next_result=FindResult(results[next_point],results[next_point]->start_node,results[next_point]->prev_segment); next_result=next_result->next; break; } /* Calculate the information about this segment */ if(result->node!=results[point]->start_node) /* not first point of a section of the route */ { if(IsFakeSegment(result->segment)) { resultsegment=LookupFakeSegment(result->segment); realsegment=IndexRealSegment(result->segment); } else { resultsegment=LookupSegment(segments,result->segment,2); realsegment=result->segment; } resultway=LookupWay(ways,resultsegment->way,1); seg_distance+=DISTANCE(resultsegment->distance); seg_duration+=Duration(resultsegment,resultway,profile); /* Calculate the cumulative distance/duration */ junc_distance+=seg_distance; junc_duration+=seg_duration; cum_distance+=seg_distance; cum_duration+=seg_duration; } /* Calculate the information about the next segment */ if(next_result) { if(IsFakeSegment(next_result->segment)) { next_resultsegment=LookupFakeSegment(next_result->segment); next_realsegment=IndexRealSegment(next_result->segment); } else { next_resultsegment=LookupSegment(segments,next_result->segment,1); next_realsegment=next_result->segment; } } /* Decide if this is a roundabout */ if(next_result) { next_resultway=LookupWay(ways,next_resultsegment->way,2); if(next_resultway->type&Way_Roundabout) { if(roundabout==0) { roundabout++; important=IMP_RB_ENTRY; } else { Segment *segment=FirstSegment(segments,resultnode,3); do { index_t othernode=OtherNode(segment,result->node); if(othernode!=result->prev->node && IndexSegment(segments,segment)!=realsegment) if(IsNormalSegment(segment) && (!profile->oneway || !IsOnewayTo(segment,result->node))) { Way *way=LookupWay(ways,segment->way,3); if(!(way->type&Way_Roundabout)) if(othernode!=next_result->node) { roundabout++; important=IMP_RB_NOT_EXIT; } } segment=NextSegment(segments,segment,result->node); } while(segment); } } else if(roundabout) { roundabout++; important=IMP_RB_EXIT; } } /* Decide if this is an important junction */ if(roundabout) /* roundabout */ ; else if(point_count==0) /* first point overall = Waypoint */ important=IMP_WAYPOINT; else if(result->node==results[point]->finish_node) /* Waypoint */ important=IMP_WAYPOINT; else if(result->node==results[point]->start_node) /* first point of a section of the route */ important=IMP_IGNORE; else if(realsegment==next_realsegment) /* U-turn */ important=IMP_UTURN; else if(resultnode && (resultnode->flags&NODE_MINIRNDBT)) important=IMP_MINI_RB; /* mini-roundabout */ else { Segment *segment=FirstSegment(segments,resultnode,3); do { index_t othernode=OtherNode(segment,result->node); if(othernode!=result->prev->node && IndexSegment(segments,segment)!=realsegment) if(IsNormalSegment(segment) && (!profile->oneway || !IsOnewayTo(segment,result->node))) { Way *way=LookupWay(ways,segment->way,3); if(othernode==next_result->node) /* the next segment that we follow */ { if(HIGHWAY(way->type)!=HIGHWAY(resultway->type)) if(important<IMP_CHANGE) important=IMP_CHANGE; } else if(IsFakeNode(next_result->node)) ; else /* a segment that we don't follow */ { if(junction_other_way[HIGHWAY(resultway->type)-1][HIGHWAY(way->type)-1]) if(important<IMP_JUNCT_IMPORT) important=IMP_JUNCT_IMPORT; if(important<IMP_JUNCT_CONT) important=IMP_JUNCT_CONT; } } segment=NextSegment(segments,segment,result->node); } while(segment); } /* Calculate the strings to be used */ if(resultway && textallfile) { waynameraw=WayName(ways,resultway); if(!*waynameraw) waynameraw=translate_raw_highway[HIGHWAY(resultway->type)]; bearing_int=(int)BearingAngle(nodes,resultsegment,result->node); seg_speed=profile->speed[HIGHWAY(resultway->type)]; } if(next_result && important>IMP_JUNCT_CONT) { if(resultsegment && (htmlfile || textfile)) { turn_int=(int)TurnAngle(nodes,resultsegment,next_resultsegment,result->node); turn=translate_xml_turn[((202+turn_int)/45)%8]; } if(gpxroutefile || htmlfile) { next_waynameraw=WayName(ways,next_resultway); if(!*next_waynameraw) next_waynameraw=translate_raw_highway[HIGHWAY(next_resultway->type)]; next_wayname=ParseXML_Encode_Safe_XML(next_waynameraw); } if(htmlfile || gpxroutefile || textfile) { next_bearing_int=(int)BearingAngle(nodes,next_resultsegment,next_result->node); next_bearing=translate_xml_heading[(4+(22+next_bearing_int)/45)%8]; } } /* Print out the important points (junctions / waypoints) */ if(important>IMP_JUNCT_CONT) { if(htmlfile) { char *type; if(important==IMP_WAYPOINT) type=translate_html_waypoint; else if(important==IMP_MINI_RB) type=translate_html_roundabout; else type=translate_html_junction; if(point_count>0) /* not the first point */ { /* <tr class='s'><td class='l'>Follow:<td class='r'><span class='h'>*highway name*</span> for <span class='d'>*distance* km, *time* min</span> [<span class='j'>*distance* km, *time* minutes</span>] */ fprintf(htmlfile,"<tr class='s'><td class='l'>%s:<td class='r'>",translate_html_segment[0]); fprintf(htmlfile,translate_html_segment[1], (roundabout>1?translate_html_roundabout:prev_wayname), distance_to_km(junc_distance),duration_to_minutes(junc_duration)); fprintf(htmlfile," [<span class='j'>"); fprintf(htmlfile,translate_html_total[1], distance_to_km(cum_distance),duration_to_minutes(cum_duration)); fprintf(htmlfile,"</span>]\n"); } /* <tr class='c'><td class='l'>*N*:<td class='r'>*latitude* *longitude* */ fprintf(htmlfile,"<tr class='c'><td class='l'>%d:<td class='r'>%.6f %.6f\n", point_count+1, radians_to_degrees(latitude),radians_to_degrees(longitude)); if(point_count==0) /* first point */ { /* <tr class='n'><td class='l'>Start:<td class='r'>At <span class='w'>Waypoint</span>, head <span class='b'>*heading*</span> */ fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_start[0]); fprintf(htmlfile,translate_html_start[1], translate_html_waypoint, next_bearing); fprintf(htmlfile,"\n"); } else if(next_result) /* middle point */ { if(roundabout>1) { /* <tr class='n'><td class='l'>At:<td class='r'>Roundabout, take <span class='t'>the *Nth* exit</span> heading <span class='b'>*heading*</span> */ fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_rbnode[0]); fprintf(htmlfile,translate_html_rbnode[1], translate_html_roundabout, translate_xml_ordinal[roundabout-2], next_bearing); fprintf(htmlfile,"\n"); } else { /* <tr class='n'><td class='l'>At:<td class='r'>Junction, go <span class='t'>*direction*</span> heading <span class='b'>*heading*</span> */ fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_node[0]); fprintf(htmlfile,translate_html_node[1], type, turn, next_bearing); fprintf(htmlfile,"\n"); } } else /* end point */ { /* <tr class='n'><td class='l'>Stop:<td class='r'>At <span class='w'>Waypoint</span> */ fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_stop[0]); fprintf(htmlfile,translate_html_stop[1], translate_html_waypoint); fprintf(htmlfile,"\n"); /* <tr class='t'><td class='l'>Total:<td class='r'><span class='j'>*distance* km, *time* minutes</span> */ fprintf(htmlfile,"<tr class='t'><td class='l'>%s:<td class='r'><span class='j'>",translate_html_total[0]); fprintf(htmlfile,translate_html_total[1], distance_to_km(cum_distance),duration_to_minutes(cum_duration)); fprintf(htmlfile,"</span>\n"); } } if(gpxroutefile) { if(point_count>0) /* not first point */ { fprintf(gpxroutefile,"<desc>"); fprintf(gpxroutefile,translate_gpx_step, prev_bearing, prev_wayname, distance_to_km(junc_distance),duration_to_minutes(junc_duration)); fprintf(gpxroutefile,"</desc></rtept>\n"); } if(point_count==0) /* first point */ { fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n", radians_to_degrees(latitude),radians_to_degrees(longitude), translate_gpx_start); } else if(!next_result) /* end point */ { fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n", radians_to_degrees(latitude),radians_to_degrees(longitude), translate_gpx_finish); fprintf(gpxroutefile,"<desc>"); fprintf(gpxroutefile,translate_gpx_final, distance_to_km(cum_distance),duration_to_minutes(cum_duration)); fprintf(gpxroutefile,"</desc></rtept>\n"); } else /* middle point */ { if(important==IMP_WAYPOINT) fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%d</name>\n", radians_to_degrees(latitude),radians_to_degrees(longitude), translate_gpx_inter,++segment_count); else fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%03d</name>\n", radians_to_degrees(latitude),radians_to_degrees(longitude), translate_gpx_trip,++route_count); } } if(textfile) { char *type; if(important==IMP_WAYPOINT) type="Waypt"; else type="Junct"; if(point_count==0) /* first point */ { fprintf(textfile,"%10.6f\t%11.6f\t%6.3f km\t%4.1f min\t%5.1f km\t%4.0f min\t%s\t\t %+d\t%s\n", radians_to_degrees(latitude),radians_to_degrees(longitude), 0.0,0.0,0.0,0.0, type, ((22+next_bearing_int)/45+4)%8-4, next_waynameraw); } else if(!next_result) /* end point */ { fprintf(textfile,"%10.6f\t%11.6f\t%6.3f km\t%4.1f min\t%5.1f km\t%4.0f min\t%s\t\t\t\n", radians_to_degrees(latitude),radians_to_degrees(longitude), distance_to_km(junc_distance),duration_to_minutes(junc_duration), distance_to_km(cum_distance),duration_to_minutes(cum_duration), type); } else /* middle point */ { fprintf(textfile,"%10.6f\t%11.6f\t%6.3f km\t%4.1f min\t%5.1f km\t%4.0f min\t%s\t %+d\t %+d\t%s\n", radians_to_degrees(latitude),radians_to_degrees(longitude), distance_to_km(junc_distance),duration_to_minutes(junc_duration), distance_to_km(cum_distance),duration_to_minutes(cum_duration), type, (22+turn_int)/45, ((22+next_bearing_int)/45+4)%8-4, next_waynameraw); } } junc_distance=0; junc_duration=0; if(htmlfile || gpxroutefile) { if(prev_wayname) free(prev_wayname); if(next_wayname) prev_wayname=strcpy((char*)malloc(strlen(next_wayname)+1),next_wayname); else prev_wayname=NULL; if(next_wayname && next_wayname!=next_waynameraw) free(next_wayname); } if(gpxroutefile) prev_bearing=next_bearing; if(roundabout>1) roundabout=0; } /* Print out all of the results */ if(gpxtrackfile) fprintf(gpxtrackfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"/>\n", radians_to_degrees(latitude),radians_to_degrees(longitude)); if(important>IMP_IGNORE) { if(textallfile) { char *type; if(important==IMP_WAYPOINT) type="Waypt"; else if(important==IMP_UTURN) type="U-turn"; else if(important==IMP_MINI_RB) type="Mini-RB"; else if(important==IMP_CHANGE) type="Change"; else if(important==IMP_UNIMPORTANT) type="Inter"; else type="Junct"; if(point_count==0) /* first point */ { fprintf(textallfile,"%10.6f\t%11.6f\t%8d%c\t%s\t%5.3f\t%5.2f\t%5.2f\t%5.1f\t\t\t\n", radians_to_degrees(latitude),radians_to_degrees(longitude), IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node, (resultnode && IsSuperNode(resultnode))?'*':' ',type, 0.0,0.0,0.0,0.0); } else /* not the first point */ { fprintf(textallfile,"%10.6f\t%11.6f\t%8d%c\t%s\t%5.3f\t%5.2f\t%5.2f\t%5.1f\t%3d\t%4d\t%s\n", radians_to_degrees(latitude),radians_to_degrees(longitude), IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node, (resultnode && IsSuperNode(resultnode))?'*':' ',type, distance_to_km(seg_distance),duration_to_minutes(seg_duration), distance_to_km(cum_distance),duration_to_minutes(cum_duration), speed_to_kph(seg_speed), bearing_int, waynameraw); } } } if(wayname && wayname!=waynameraw) free(wayname); result=next_result; if(important>IMP_JUNCT_CONT) point_count++; } while(point==next_point); /* Print the end of the segment */ if(gpxtrackfile) fprintf(gpxtrackfile,"</trkseg>\n"); point=next_point; } /* Print the tail of the files */ if(htmlfile) { fprintf(htmlfile,"</table>\n"); if((translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1]) || (translate_xml_copyright_source[0] && translate_xml_copyright_source[1]) || (translate_xml_copyright_license[0] && translate_xml_copyright_license[1])) { fprintf(htmlfile,"<p>\n"); fprintf(htmlfile,"<table class='c'>\n"); if(translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1]) fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); if(translate_xml_copyright_source[0] && translate_xml_copyright_source[1]) fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_source[0],translate_xml_copyright_source[1]); if(translate_xml_copyright_license[0] && translate_xml_copyright_license[1]) fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_license[0],translate_xml_copyright_license[1]); fprintf(htmlfile,"</table>\n"); } fprintf(htmlfile,"</BODY>\n"); fprintf(htmlfile,"</HTML>\n"); } if(gpxtrackfile) { fprintf(gpxtrackfile,"</trk>\n"); fprintf(gpxtrackfile,"</gpx>\n"); } if(gpxroutefile) { fprintf(gpxroutefile,"</rte>\n"); fprintf(gpxroutefile,"</gpx>\n"); } /* Close the files */ if(htmlfile) fclose(htmlfile); if(gpxtrackfile) fclose(gpxtrackfile); if(gpxroutefile) fclose(gpxroutefile); if(textfile) fclose(textfile); if(textallfile) fclose(textallfile); }
Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,index_t finish_node) { Results *results,*results2; Queue *queue; Result *result1,*result2,*result3; /* Create the results and insert the finish node */ results=NewResultsList(64); results->finish_node=finish_node; result1=InsertResult(results,finish_node,NO_SEGMENT); /* Insert the first node into the queue */ queue=NewQueueList(); InsertInQueue(queue,result1); /* Loop across all nodes in the queue */ while((result1=PopFromQueue(queue))) { index_t node1,seg1,seg1r; Segment *segment; index_t turnrelation=NO_RELATION; node1=result1->node; seg1=result1->segment; if(IsFakeSegment(seg1)) seg1r=IndexRealSegment(seg1); else seg1r=seg1; /* lookup if a turn restriction applies */ if(profile->turns && !IsFakeNode(node1) && IsTurnRestrictedNode(LookupNode(nodes,node1,1))) turnrelation=FindFirstTurnRelation1(relations,node1); /* working backwards => turn relation sort order doesn't help */ /* Loop across all segments */ if(IsFakeNode(node1)) segment=FirstFakeSegment(node1); else segment=FirstSegment(segments,nodes,node1,1); while(segment) { Way *way; index_t node2,seg2,seg2r; score_t segment_pref,segment_score,cumulative_score; int i; /* must be a normal segment */ if((IsFakeNode(node1) || !IsSuperNode(LookupNode(nodes,node1,1))) && !IsNormalSegment(segment)) goto endloop; /* must obey one-way restrictions (unless profile allows) */ if(profile->oneway && IsOnewayFrom(segment,node1)) /* Disallow oneway from node2 *to* node1 */ goto endloop; node2=OtherNode(segment,node1); if(IsFakeNode(node1) || IsFakeNode(node2)) { seg2 =IndexFakeSegment(segment); seg2r=IndexRealSegment(seg2); } else { seg2 =IndexSegment(segments,segment); seg2r=seg2; } /* must not perform U-turn (unless profile allows) */ if(profile->turns && (seg1==seg2 || seg1==seg2r || seg1r==seg2 || (seg1r==seg2r && IsFakeUTurn(seg1,seg2)))) goto endloop; /* must obey turn relations */ if(turnrelation!=NO_RELATION) { index_t turnrelation2=FindFirstTurnRelation2(relations,node1,seg2r); /* node2 -> node1 -> result1->next->node */ if(turnrelation2!=NO_RELATION && !IsTurnAllowed(relations,turnrelation2,node1,seg2r,seg1r,profile->allow)) goto endloop; } way=LookupWay(ways,segment->way,1); /* mode of transport must be allowed on the highway */ if(!(way->allow&profile->allow)) goto endloop; /* must obey weight restriction (if exists) */ if(way->weight && way->weight<profile->weight) goto endloop; /* must obey height/width/length restriction (if exists) */ if((way->height && way->height<profile->height) || (way->width && way->width <profile->width ) || (way->length && way->length<profile->length)) goto endloop; segment_pref=profile->highway[HIGHWAY(way->type)]; for(i=1;i<Property_Count;i++) if(ways->file.props & PROPERTIES(i)) { if(way->props & PROPERTIES(i)) segment_pref*=profile->props_yes[i]; else segment_pref*=profile->props_no[i]; } /* profile preferences must allow this highway */ if(segment_pref==0) goto endloop; /* mode of transport must be allowed through node2 */ if(!IsFakeNode(node2)) { Node *node=LookupNode(nodes,node2,2); if(!(node->allow&profile->allow)) goto endloop; } if(option_quickest==0) segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; else segment_score=(score_t)Duration(segment,way,profile)/segment_pref; cumulative_score=result1->score+segment_score; result2=FindResult(results,node2,seg2); if(!result2) /* New end node */ { result2=InsertResult(results,node2,seg2); result2->next=result1; /* working backwards */ result2->score=cumulative_score; if(IsFakeNode(node1) || (!IsFakeNode(node1) && !IsSuperNode(LookupNode(nodes,node1,1)))) /* Overshoot by one segment */ { result2->sortby=result2->score; InsertInQueue(queue,result2); } } else if(cumulative_score<result2->score) /* New end node is better */ { result2->next=result1; /* working backwards */ result2->score=cumulative_score; if(IsFakeNode(node1) || (!IsFakeNode(node1) && !IsSuperNode(LookupNode(nodes,node1,1)))) /* Overshoot by one segment */ { result2->sortby=result2->score; InsertInQueue(queue,result2); } } endloop: if(IsFakeNode(node1)) segment=NextFakeSegment(segment,node1); else segment=NextSegment(segments,segment,node1); } } FreeQueueList(queue); /* Check it worked */ if(results->number==1) { FreeResultsList(results); return(NULL); } /* Create a results structure with the node at the end of the segment opposite the start */ results2=NewResultsList(64); results2->finish_node=results->finish_node; result3=FirstResult(results); while(result3) { if(result3->next) { result2=InsertResult(results2,result3->next->node,result3->segment); result2->score=result3->next->score; } result3=NextResult(results,result3); } /* Fix up the result->next pointers */ result3=FirstResult(results); while(result3) { if(result3->next && result3->next->next) { result1=FindResult(results2,result3->next->node,result3->segment); result2=FindResult(results2,result3->next->next->node,result3->next->segment); result1->next=result2; } result3=NextResult(results,result3); } FreeResultsList(results); return(results2); }
Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,index_t start_node,index_t prev_segment,index_t finish_node) { Results *results; Queue *queue; score_t finish_score; double finish_lat,finish_lon; Result *finish_result; Result *result1,*result2; /* Set up the finish conditions */ finish_score=INF_SCORE; finish_result=NULL; if(IsFakeNode(finish_node)) GetFakeLatLong(finish_node,&finish_lat,&finish_lon); else GetLatLong(nodes,finish_node,&finish_lat,&finish_lon); /* Create the list of results and insert the first node into the queue */ results=NewResultsList(64); results->start_node=start_node; results->prev_segment=prev_segment; result1=InsertResult(results,results->start_node,results->prev_segment); queue=NewQueueList(); InsertInQueue(queue,result1); /* Loop across all nodes in the queue */ while((result1=PopFromQueue(queue))) { Segment *segment; index_t node1,seg1,seg1r; index_t turnrelation=NO_RELATION; /* score must be better than current best score */ if(result1->score>finish_score) continue; node1=result1->node; seg1=result1->segment; if(IsFakeSegment(seg1)) seg1r=IndexRealSegment(seg1); else seg1r=seg1; /* lookup if a turn restriction applies */ if(profile->turns && !IsFakeNode(node1) && IsTurnRestrictedNode(LookupNode(nodes,node1,1))) turnrelation=FindFirstTurnRelation2(relations,node1,seg1r); /* Loop across all segments */ if(IsFakeNode(node1)) segment=FirstFakeSegment(node1); else segment=FirstSegment(segments,nodes,node1,1); while(segment) { Way *way; index_t node2,seg2,seg2r; score_t segment_pref,segment_score,cumulative_score; int i; node2=OtherNode(segment,node1); /* need this here because we use node2 at the end of the loop */ /* must be a normal segment */ if(!IsNormalSegment(segment)) goto endloop; /* must obey one-way restrictions (unless profile allows) */ if(profile->oneway && IsOnewayTo(segment,node1)) goto endloop; if(IsFakeNode(node1) || IsFakeNode(node2)) { seg2 =IndexFakeSegment(segment); seg2r=IndexRealSegment(seg2); } else { seg2 =IndexSegment(segments,segment); seg2r=seg2; } /* must not perform U-turn (unless profile allows) */ if(profile->turns && (seg1==seg2 || seg1==seg2r || seg1r==seg2 || (seg1r==seg2r && IsFakeUTurn(seg1,seg2)))) goto endloop; /* must obey turn relations */ if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,node1,seg1r,seg2r,profile->allow)) goto endloop; /* must not pass over super-node */ if(node2!=finish_node && !IsFakeNode(node2) && IsSuperNode(LookupNode(nodes,node2,2))) goto endloop; way=LookupWay(ways,segment->way,1); /* mode of transport must be allowed on the highway */ if(!(way->allow&profile->allow)) goto endloop; /* must obey weight restriction (if exists) */ if(way->weight && way->weight<profile->weight) goto endloop; /* must obey height/width/length restriction (if exists) */ if((way->height && way->height<profile->height) || (way->width && way->width <profile->width ) || (way->length && way->length<profile->length)) goto endloop; segment_pref=profile->highway[HIGHWAY(way->type)]; for(i=1;i<Property_Count;i++) if(ways->file.props & PROPERTIES(i)) { if(way->props & PROPERTIES(i)) segment_pref*=profile->props_yes[i]; else segment_pref*=profile->props_no[i]; } /* profile preferences must allow this highway */ if(segment_pref==0) goto endloop; /* mode of transport must be allowed through node2 */ if(!IsFakeNode(node2)) { Node *node=LookupNode(nodes,node2,2); if(!(node->allow&profile->allow)) goto endloop; } if(option_quickest==0) segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; else segment_score=(score_t)Duration(segment,way,profile)/segment_pref; cumulative_score=result1->score+segment_score; /* score must be better than current best score */ if(cumulative_score>finish_score) goto endloop; result2=FindResult(results,node2,seg2); if(!result2) /* New end node/segment combination */ { result2=InsertResult(results,node2,seg2); result2->prev=result1; result2->score=cumulative_score; if(node2==finish_node) { if(cumulative_score<finish_score) { finish_score=cumulative_score; finish_result=result2; } } else { result2->sortby=result2->score; InsertInQueue(queue,result2); } } else if(cumulative_score<result2->score) /* New score for end node/segment combination is better */ { result2->prev=result1; result2->score=cumulative_score; result2->segment=seg2; if(node2==finish_node) { if(cumulative_score<finish_score) { finish_score=cumulative_score; finish_result=result2; } } else { result2->sortby=result2->score; if(result2->score<finish_score) InsertInQueue(queue,result2); } } endloop: if(IsFakeNode(node1)) segment=NextFakeSegment(segment,node1); else if(IsFakeNode(node2)) segment=NULL; /* cannot call NextSegment() with a fake segment */ else { segment=NextSegment(segments,segment,node1); if(!segment && IsFakeNode(finish_node)) segment=ExtraFakeSegment(node1,finish_node); } } } FreeQueueList(queue); /* Check it worked */ if(!finish_result) { FreeResultsList(results); return(NULL); } FixForwardRoute(results,finish_result); return(results); }
Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,Results *begin,Results *end) { Results *results; Queue *queue; Result *finish_result; score_t finish_score; double finish_lat,finish_lon; Result *result1,*result2,*result3,*result4; if(!option_quiet) printf_first("Routing: Super-Nodes checked = 0"); /* Set up the finish conditions */ finish_score=INF_DISTANCE; finish_result=NULL; if(IsFakeNode(end->finish_node)) GetFakeLatLong(end->finish_node,&finish_lat,&finish_lon); else GetLatLong(nodes,end->finish_node,&finish_lat,&finish_lon); /* Create the list of results and insert the first node into the queue */ results=NewResultsList(65536); results->start_node=begin->start_node; results->prev_segment=begin->prev_segment; if(begin->number==1) { if(begin->prev_segment==NO_SEGMENT) results->prev_segment=NO_SEGMENT; else { index_t superseg=FindSuperSegment(nodes,segments,ways,relations,profile,begin->start_node,begin->prev_segment); results->prev_segment=superseg; } } result1=InsertResult(results,results->start_node,results->prev_segment); queue=NewQueueList(); /* Insert the finish points of the beginning part of the path into the queue, translating the segments into super-segments. */ result3=FirstResult(begin); while(result3) { if((results->start_node!=result3->node || results->prev_segment!=result3->segment) && !IsFakeNode(result3->node) && IsSuperNode(LookupNode(nodes,result3->node,1))) { Result *result5=result1; index_t superseg=FindSuperSegment(nodes,segments,ways,relations,profile,result3->node,result3->segment); if(superseg!=result3->segment) { result5=InsertResult(results,result3->node,result3->segment); result5->prev=result1; } if(!FindResult(results,result3->node,superseg)) { result2=InsertResult(results,result3->node,superseg); result2->prev=result5; result2->score=result3->score; result2->sortby=result3->score; InsertInQueue(queue,result2); if((result4=FindResult(end,result2->node,result2->segment))) { if((result2->score+result4->score)<finish_score) { finish_score=result2->score+result4->score; finish_result=result2; } } } } result3=NextResult(begin,result3); } if(begin->number==1) InsertInQueue(queue,result1); /* Loop across all nodes in the queue */ while((result1=PopFromQueue(queue))) { index_t node1,seg1; Segment *segment; index_t turnrelation=NO_RELATION; /* score must be better than current best score */ if(result1->score>finish_score) continue; node1=result1->node; seg1=result1->segment; /* lookup if a turn restriction applies */ if(profile->turns && IsTurnRestrictedNode(LookupNode(nodes,node1,1))) /* node1 cannot be a fake node (must be a super-node) */ turnrelation=FindFirstTurnRelation2(relations,node1,seg1); /* Loop across all segments */ segment=FirstSegment(segments,nodes,node1,1); /* node1 cannot be a fake node (must be a super-node) */ while(segment) { Way *way; Node *node; index_t node2,seg2; score_t segment_pref,segment_score,cumulative_score; int i; /* must be a super segment */ if(!IsSuperSegment(segment)) goto endloop; /* must obey one-way restrictions (unless profile allows) */ if(profile->oneway && IsOnewayTo(segment,node1)) goto endloop; node2=OtherNode(segment,node1); seg2=IndexSegment(segments,segment); /* node2 cannot be a fake node (must be a super-node) */ /* must not perform U-turn */ if(seg1==seg2) /* No fake segments, applies to all profiles */ goto endloop; /* must obey turn relations */ if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,node1,seg1,seg2,profile->allow)) goto endloop; way=LookupWay(ways,segment->way,1); /* transport must be allowed on the highway */ if(!(way->allow&profile->allow)) goto endloop; /* must obey weight restriction (if exists) */ if(way->weight && way->weight<profile->weight) goto endloop; /* must obey height/width/length restriction (if exists) */ if((way->height && way->height<profile->height) || (way->width && way->width <profile->width ) || (way->length && way->length<profile->length)) goto endloop; segment_pref=profile->highway[HIGHWAY(way->type)]; for(i=1;i<Property_Count;i++) if(ways->file.props & PROPERTIES(i)) { if(way->props & PROPERTIES(i)) segment_pref*=profile->props_yes[i]; else segment_pref*=profile->props_no[i]; } /* profile preferences must allow this highway */ if(segment_pref==0) goto endloop; node=LookupNode(nodes,node2,2); /* node2 cannot be a fake node (must be a super-node) */ /* mode of transport must be allowed through node2 */ if(!(node->allow&profile->allow)) goto endloop; if(option_quickest==0) segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; else segment_score=(score_t)Duration(segment,way,profile)/segment_pref; cumulative_score=result1->score+segment_score; /* score must be better than current best score */ if(cumulative_score>finish_score) goto endloop; result2=FindResult(results,node2,seg2); if(!result2) /* New end node/segment pair */ { result2=InsertResult(results,node2,seg2); result2->prev=result1; result2->score=cumulative_score; if((result3=FindResult(end,node2,seg2))) { if((result2->score+result3->score)<finish_score) { finish_score=result2->score+result3->score; finish_result=result2; } } else { double lat,lon; distance_t direct; GetLatLong(nodes,node2,&lat,&lon); /* node2 cannot be a fake node (must be a super-node) */ direct=Distance(lat,lon,finish_lat,finish_lon); if(option_quickest==0) result2->sortby=result2->score+(score_t)direct/profile->max_pref; else result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref; InsertInQueue(queue,result2); } } else if(cumulative_score<result2->score) /* New end node/segment pair is better */ { result2->prev=result1; result2->score=cumulative_score; if((result3=FindResult(end,node2,seg2))) { if((result2->score+result3->score)<finish_score) { finish_score=result2->score+result3->score; finish_result=result2; } } else if(result2->score<finish_score) { double lat,lon; distance_t direct; GetLatLong(nodes,node2,&lat,&lon); /* node2 cannot be a fake node (must be a super-node) */ direct=Distance(lat,lon,finish_lat,finish_lon); if(option_quickest==0) result2->sortby=result2->score+(score_t)direct/profile->max_pref; else result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref; InsertInQueue(queue,result2); } } if(!option_quiet && !(results->number%1000)) printf_middle("Routing: Super-Nodes checked = %d",results->number); endloop: segment=NextSegment(segments,segment,node1); /* node1 cannot be a fake node (must be a super-node) */ } } if(!option_quiet) printf_last("Routing: Super-Nodes checked = %d",results->number); FreeQueueList(queue); /* Check it worked */ if(!finish_result) { FreeResultsList(results); return(NULL); } /* Finish off the end part of the route */ if(finish_result->node!=end->finish_node) { result3=InsertResult(results,end->finish_node,NO_SEGMENT); result3->prev=finish_result; result3->score=finish_score; finish_result=result3; } FixForwardRoute(results,finish_result); return(results); }