void PruneShortSegments(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,distance_t minimum)
{
 index_t i;
 index_t nshort=0,npruned=0;

 if(nodesx->number==0 || segmentsx->number==0 || waysx->number==0)
    return;

 /* Print the start message */

 printf_first("Pruning Short Segments: Segments=0 Short=0 Pruned=0");

 /* Map into memory / open the files */

#if !SLIM
 nodesx->data=MapFileWriteable(nodesx->filename_tmp);
 segmentsx->data=MapFileWriteable(segmentsx->filename_tmp);
 waysx->data=MapFile(waysx->filename_tmp);
#else
 nodesx->fd=SlimMapFileWriteable(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

 /* Loop through the segments and find the short ones for possible modification */

 for(i=0;i<segmentsx->number;i++)
   {
    SegmentX *segmentx2=LookupSegmentX(segmentsx,i,2);

    if(IsPrunedSegmentX(segmentx2))
       goto endloop;

    /*
                       :
      Initial state: ..N3 -------- N2
                       :     S2

                       :
      Final state:   ..N3
                       :

      = OR =

                       :                               :
      Initial state: ..N1 -------- N2 ---- N3 -------- N4..
                       :     S1        S2        S3    :

                       :                               :
      Final state:   ..N1 ------------ N3 ------------ N4..
                       :       S1               S3     :

      Not if N1 is the same as N4.
      Must not delete N2 (or N3) if S2 (or S3) has different one-way properties from S1.
      Must not delete N2 (or N3) if S2 (or S3) has different highway properties from S1.
      Must combine N2, S2 and N3 disallowed transports into new N3.
      Must not delete N2 (or N3) if it is a mini-roundabout.
      Must not delete N2 (or N3) if it is involved in a turn restriction.

      = OR =

                       :                   :
      Initial state: ..N1 -------- N2 ---- N3..
                       :     S1        S2  :

                       :               :
      Final state:   ..N1 ------------ N3..
                       :       S1      :

      Not if N1 is the same as N3.
      Not if S1 has different one-way properties from S2.
      Not if S1 has different highway properties from S2.
      Not if N2 disallows transports allowed on S1 and S2.
      Not if N2 is a mini-roundabout.
      Not if N2 is involved in a turn restriction.
     */

    if(DISTANCE(segmentx2->distance)<=minimum)
      {
       index_t node1=NO_NODE,node2,node3,node4=NO_NODE;
       index_t segment1=NO_SEGMENT,segment2=i,segment3=NO_SEGMENT;
       SegmentX *segmentx;
       int segcount2=0,segcount3=0;

       nshort++;

       node2=segmentx2->node1;
       node3=segmentx2->node2;

       /* Count the segments connected to N2 */

       segmentx=FirstSegmentX(segmentsx,node2,4);

       while(segmentx)
         {
          segcount2++;

          if(segment1==NO_SEGMENT)
            {
             index_t segment=IndexSegmentX(segmentsx,segmentx);

             if(segment!=segment2)
               {
                segment1=segment;
                node1=OtherNode(segmentx,node2);
               }
            }
          else if(segcount2>2)
             break;

          segmentx=NextSegmentX(segmentsx,segmentx,node2);
         }

       /* Count the segments connected to N3 */

       segmentx=FirstSegmentX(segmentsx,node3,4);

       while(segmentx)
         {
          segcount3++;

          if(segment3==NO_SEGMENT)
            {
             index_t segment=IndexSegmentX(segmentsx,segmentx);

             if(segment!=segment2)
               {
                segment3=segment;
                node4=OtherNode(segmentx,node3);
               }
            }
          else if(segcount3>2)
             break;

          segmentx=NextSegmentX(segmentsx,segmentx,node3);
         }

       /* Check which case we are handling (and canonicalise) */

       if(segcount2>2 && segcount3>2) /* none of the cases in diagram - too complicated */
         {
          goto endloop;
         }
       else if(segcount2==1 || segcount3==1) /* first case in diagram - prune segment */
         {
          prune_segment(segmentsx,segmentx2);
         }
       else if(segcount2==2 && segcount3==2) /* second case in diagram - modify one segment and prune segment */
         {
          SegmentX *segmentx1,*segmentx3;
          WayX *wayx1,*wayx2,*wayx3;
          NodeX *nodex2,*nodex3,*newnodex;
          index_t newnode;
          int join12=1,join23=1;

          /* Check if pruning would collapse a loop */

          if(node1==node4)
             goto endloop;

          /* Check if allowed due to one-way properties */

          segmentx1=LookupSegmentX(segmentsx,segment1,1);
          segmentx3=LookupSegmentX(segmentsx,segment3,3);

          if(!IsOneway(segmentx1) && !IsOneway(segmentx2))
             ;
          else if(IsOneway(segmentx1) && IsOneway(segmentx2))
            {
             if(IsOnewayTo(segmentx1,node2) && !IsOnewayFrom(segmentx2,node2)) /* S1 is one-way but S2 doesn't continue */
                join12=0;

             if(IsOnewayFrom(segmentx1,node2) && !IsOnewayTo(segmentx2,node2)) /* S1 is one-way but S2 doesn't continue */
                join12=0;
            }
          else
             join12=0;

          if(!IsOneway(segmentx3) && !IsOneway(segmentx2))
             ;
          else if(IsOneway(segmentx3) && IsOneway(segmentx2))
            {
             if(IsOnewayTo(segmentx3,node3) && !IsOnewayFrom(segmentx2,node3)) /* S3 is one-way but S2 doesn't continue */
                join23=0;

             if(IsOnewayFrom(segmentx3,node3) && !IsOnewayTo(segmentx2,node3)) /* S3 is one-way but S2 doesn't continue */
                join23=0;
            }
          else
             join23=0;

          if(!join12 && !join23)
             goto endloop;

          /* Check if allowed due to highway properties */

          wayx1=LookupWayX(waysx,segmentx1->way,1);
          wayx2=LookupWayX(waysx,segmentx2->way,2);
          wayx3=LookupWayX(waysx,segmentx3->way,3);

          if(WaysCompare(&wayx1->way,&wayx2->way))
             join12=0;

          if(WaysCompare(&wayx3->way,&wayx2->way))
             join23=0;

          if(!join12 && !join23)
             goto endloop;

          /* Check if allowed due to mini-roundabout and turn restriction */

          nodex2=LookupNodeX(nodesx,node2,2);
          nodex3=LookupNodeX(nodesx,node3,3);

          if(nodex2->flags&NODE_MINIRNDBT)
             join12=0;

          if(nodex3->flags&NODE_MINIRNDBT)
             join23=0;

          if(!join12 && !join23)
             goto endloop;

          if(nodex2->flags&NODE_TURNRSTRCT2 || nodex2->flags&NODE_TURNRSTRCT)
             join12=0;

          if(nodex3->flags&NODE_TURNRSTRCT2 || nodex3->flags&NODE_TURNRSTRCT)
             join23=0;

          if(!join12 && !join23)
             goto endloop;

          /* New node properties */

          if(join12)
            {
             newnode=node3;
             newnodex=nodex3;
            }
          else /* if(join23) */
            {
             newnode=node2;
             newnodex=nodex2;
            }

          newnodex->allow=nodex2->allow&nodex3->allow; /* combine the restrictions of the two nodes */
          newnodex->allow&=~((~wayx2->way.allow)&wayx3->way.allow); /* disallow anything blocked by segment2 */
          newnodex->allow&=~((~wayx2->way.allow)&wayx1->way.allow); /* disallow anything blocked by segment2 */

          newnodex->latitude =(nodex2->latitude +nodex3->latitude )/2;
          newnodex->longitude=(nodex2->longitude+nodex3->longitude)/2;

          PutBackNodeX(nodesx,newnodex);

          /* Modify segments */

          segmentx1->distance+=DISTANCE(segmentx2->distance)/2;
          segmentx3->distance+=DISTANCE(segmentx2->distance)-DISTANCE(segmentx2->distance)/2;

          if(segmentx1->node1==node1)
            {
             if(segmentx1->node2!=newnode)
                modify_segment(segmentsx,segmentx1,node1,newnode);
             else
                PutBackSegmentX(segmentsx,segmentx1);
            }
          else /* if(segmentx1->node2==node1) */
            {
             if(segmentx1->node1!=newnode)
                modify_segment(segmentsx,segmentx1,newnode,node1);
             else
                PutBackSegmentX(segmentsx,segmentx1);
            }

          if(segmentx3->node1==node4)
            {
             if(segmentx3->node2!=newnode)
                modify_segment(segmentsx,segmentx3,node4,newnode);
             else
                PutBackSegmentX(segmentsx,segmentx3);
            }
          else /* if(segmentx3->node2==node4) */
            {
             if(segmentx3->node1!=newnode)
                modify_segment(segmentsx,segmentx3,newnode,node4);
             else
                PutBackSegmentX(segmentsx,segmentx3);
            }

          ReLookupSegmentX(segmentsx,segmentx2);

          prune_segment(segmentsx,segmentx2);
         }
       else                     /* third case in diagram - prune one segment */
         {
          SegmentX *segmentx1;
          WayX *wayx1,*wayx2;
          NodeX *nodex2;

          if(segcount3==2) /* not as in diagram, shuffle things round */
            {
             index_t temp;

             temp=segment1; segment1=segment3; segment3=temp;
             temp=node1; node1=node4; node4=temp;
             temp=node2; node2=node3; node3=temp;
            }

          /* Check if pruning would collapse a loop */

          if(node1==node3)
             goto endloop;

          /* Check if allowed due to one-way properties */

          segmentx1=LookupSegmentX(segmentsx,segment1,1);

          if(!IsOneway(segmentx1) && !IsOneway(segmentx2))
             ;
          else if(IsOneway(segmentx1) && IsOneway(segmentx2))
            {
             if(IsOnewayTo(segmentx1,node2) && !IsOnewayFrom(segmentx2,node2)) /* S1 is one-way but S2 doesn't continue */
                goto endloop;

             if(IsOnewayFrom(segmentx1,node2) && !IsOnewayTo(segmentx2,node2)) /* S1 is one-way but S2 doesn't continue */
                goto endloop;
            }
          else
             goto endloop;

          /* Check if allowed due to highway properties */

          wayx1=LookupWayX(waysx,segmentx1->way,1);
          wayx2=LookupWayX(waysx,segmentx2->way,2);

          if(WaysCompare(&wayx1->way,&wayx2->way))
             goto endloop;

          /* Check if allowed due to mini-roundabout and turn restriction */

          nodex2=LookupNodeX(nodesx,node2,2);

          if(nodex2->flags&NODE_MINIRNDBT)
             goto endloop;

          if(nodex2->flags&NODE_TURNRSTRCT2 || nodex2->flags&NODE_TURNRSTRCT)
             goto endloop;

          /* Check if allowed due to node restrictions */

          if((nodex2->allow&wayx1->way.allow)!=wayx1->way.allow)
             goto endloop;

          if((nodex2->allow&wayx2->way.allow)!=wayx2->way.allow)
             goto endloop;

          /* Modify segments */

          segmentx1->distance+=DISTANCE(segmentx2->distance);

          if(segmentx1->node1==node1)
             modify_segment(segmentsx,segmentx1,node1,node3);
          else /* if(segmentx1->node2==node1) */
             modify_segment(segmentsx,segmentx1,node3,node1);

          ReLookupSegmentX(segmentsx,segmentx2);

          prune_segment(segmentsx,segmentx2);
         }

       npruned++;
      }

   endloop:

    if(!((i+1)%10000))
       printf_middle("Pruning Short Segments: Segments=%"Pindex_t" Short=%"Pindex_t" Pruned=%"Pindex_t,i+1,nshort,npruned);
   }

 /* Unmap from memory / close the files */

#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 Short Segments: Segments=%"Pindex_t" Short=%"Pindex_t" Pruned=%"Pindex_t,segmentsx->number,nshort,npruned);
}
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);
}
Ejemplo n.º 3
0
Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t start,index_t finish,Profile *profile)
{
 Results *results;
 Queue *queue;
 index_t node1,node2;
 score_t finish_score;
 double  finish_lat,finish_lon;
 Result *result1,*result2;
 Segment *segment;
 Way *way;

 /* Set up the finish conditions */

 finish_score=INF_SCORE;

 if(IsFakeNode(finish))
    GetFakeLatLong(finish,&finish_lat,&finish_lon);
 else
    GetLatLong(nodes,finish,&finish_lat,&finish_lon);

 /* Create the list of results and insert the first node into the queue */

 results=NewResultsList(8);

 results->start=start;
 results->finish=finish;

 result1=InsertResult(results,start);

 ZeroResult(result1);

 queue=NewQueueList();

 InsertInQueue(queue,result1);

 /* Loop across all nodes in the queue */

 while((result1=PopFromQueue(queue)))
   {
    if(result1->score>finish_score)
       continue;

    node1=result1->node;

    if(IsFakeNode(node1))
       segment=FirstFakeSegment(node1);
    else
       segment=FirstSegment(segments,nodes,node1);

    while(segment)
      {
       score_t segment_pref,segment_score,cumulative_score;
       int i;

       node2=OtherNode(segment,node1);  /* need this here because we use node2 later */

       if(!IsNormalSegment(segment))
          goto endloop;

       if(profile->oneway && IsOnewayTo(segment,node1))
          goto endloop;

       if(result1->prev==node2)
          goto endloop;

       if(node2!=finish && !IsFakeNode(node2) && IsSuperNode(nodes,node2))
          goto endloop;

       way=LookupWay(ways,segment->way);

       if(!(way->allow&profile->allow))
          goto endloop;

       if(!profile->highway[HIGHWAY(way->type)])
          goto endloop;

       if(way->weight && way->weight<profile->weight)
          goto endloop;

       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->props & PROPERTIES(i))
            {
             if(way->props & PROPERTIES(i))
                segment_pref*=profile->props_yes[i];
             else
                segment_pref*=profile->props_no[i];
            }

       if(segment_pref==0)
          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;

       if(cumulative_score>finish_score)
          goto endloop;

       result2=FindResult(results,node2);

       if(!result2)                         /* New end node */
         {
          result2=InsertResult(results,node2);
          result2->prev=node1;
          result2->next=NO_NODE;
          result2->score=cumulative_score;
          result2->segment=segment;

          if(node2==finish)
            {
             finish_score=cumulative_score;
            }
          else
            {
             result2->sortby=result2->score;

             InsertInQueue(queue,result2);
            }
         }
       else if(cumulative_score<result2->score) /* New end node is better */
         {
          result2->prev=node1;
          result2->score=cumulative_score;
          result2->segment=segment;

          if(node2==finish)
            {
             finish_score=cumulative_score;
            }
          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))
             segment=ExtraFakeSegment(node1,finish);
         }
      }
   }

 FreeQueueList(queue);

 /* Check it worked */

 if(!FindResult(results,finish))
   {
    FreeResultsList(results);
    return(NULL);
   }

 FixForwardRoute(results,finish);

 return(results);
}
Ejemplo n.º 4
0
static Results *FindRoutesWay(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,node_t start,Way *match)
{
 Results *results;
 Queue *queue;
 Result *result1,*result2;
 WayX *wayx;

 /* Insert the first node into the queue */

 results=NewResultsList(4);

 queue=NewQueueList();

 result1=InsertResult(results,start,NO_SEGMENT);

 InsertInQueue(queue,result1);

 /* Loop across all nodes in the queue */

 while((result1=PopFromQueue(queue)))
   {
    index_t node1;
    SegmentX *segmentx;

    node1=result1->node;

    segmentx=FirstSegmentX(segmentsx,node1,2); /* position 1 is already used */

    while(segmentx)
      {
       index_t node2,seg2;
       distance_t cumulative_distance;

       /* must not be one-way against the direction of travel */
       if(IsOnewayTo(segmentx,node1))
          goto endloop;

       node2=OtherNode(segmentx,node1);

       seg2=IndexSegmentX(segmentsx,segmentx);

       /* must not be a u-turn */
       if(result1->segment==seg2)
          goto endloop;

       wayx=LookupWayX(waysx,segmentx->way,2); /* position 1 is already used */

       /* must be the right type of way */
       if(WaysCompare(&wayx->way,match))
          goto endloop;

       cumulative_distance=(distance_t)result1->score+DISTANCE(segmentx->distance);

       result2=FindResult(results,node2,seg2);

       if(!result2)                         /* New end node */
         {
          result2=InsertResult(results,node2,seg2);
          result2->prev=result1;
          result2->score=cumulative_distance;
          result2->sortby=cumulative_distance;

          /* don't route beyond a super-node. */
          if(!IsBitSet(nodesx->super,node2))
             InsertInQueue(queue,result2);
         }
       else if(cumulative_distance<result2->score)
         {
          result2->prev=result1;
          result2->score=cumulative_distance;
          result2->sortby=cumulative_distance;

          /* don't route beyond a super-node. */
          if(!IsBitSet(nodesx->super,node2))
             InsertInQueue(queue,result2);
         }

      endloop:

       segmentx=NextSegmentX(segmentsx,segmentx,node1);
      }
   }

 FreeQueueList(queue);

 return(results);
}
Ejemplo n.º 5
0
Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t start,Profile *profile)
{
 Results *results;
 Queue *queue;
 index_t node1,node2;
 Result *result1,*result2;
 Segment *segment;
 Way *way;

 /* Insert the first node into the queue */

 results=NewResultsList(8);

 results->start=start;

 result1=InsertResult(results,start);

 ZeroResult(result1);

 queue=NewQueueList();

 InsertInQueue(queue,result1);

 /* Loop across all nodes in the queue */

 while((result1=PopFromQueue(queue)))
   {
    node1=result1->node;

    if(IsFakeNode(node1))
       segment=FirstFakeSegment(node1);
    else
       segment=FirstSegment(segments,nodes,node1);

    while(segment)
      {
       score_t segment_pref,segment_score,cumulative_score;
       int i;

       if(!IsNormalSegment(segment))
          goto endloop;

       if(profile->oneway && IsOnewayTo(segment,node1))
          goto endloop;

       node2=OtherNode(segment,node1);

       if(result1->prev==node2)
          goto endloop;

       way=LookupWay(ways,segment->way);

       if(!(way->allow&profile->allow))
          goto endloop;

       if(!profile->highway[HIGHWAY(way->type)])
          goto endloop;

       if(way->weight && way->weight<profile->weight)
          goto endloop;

       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->props & PROPERTIES(i))
            {
             if(way->props & PROPERTIES(i))
                segment_pref*=profile->props_yes[i];
             else
                segment_pref*=profile->props_no[i];
            }

       if(segment_pref==0)
          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);

       if(!result2)                         /* New end node */
         {
          result2=InsertResult(results,node2);
          result2->prev=node1;
          result2->next=NO_NODE;
          result2->score=cumulative_score;
          result2->segment=segment;

          if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2))
            {
             result2->sortby=result2->score;
             InsertInQueue(queue,result2);
            }
         }
       else if(cumulative_score<result2->score) /* New end node is better */
         {
          result2->prev=node1;
          result2->score=cumulative_score;
          result2->segment=segment;

          if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2))
            {
             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);
   }

 return(results);
}
Ejemplo n.º 6
0
Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *begin,Results *end,Profile *profile)
{
 Results *results;
 Queue *queue;
 index_t node1,node2;
 index_t end_prev;
 score_t finish_score;
 double  finish_lat,finish_lon;
 Result *result1,*result2,*result3;
 Segment *segment;
 Way *way;

 if(!option_quiet)
   {
    printf("Routing: Super-Nodes checked = 0");
    fflush(stdout);
   }

 /* Set up the finish conditions */

 finish_score=INF_DISTANCE;
 end_prev=NO_NODE;

 if(IsFakeNode(end->finish))
    GetFakeLatLong(end->finish,&finish_lat,&finish_lon);
 else
    GetLatLong(nodes,end->finish,&finish_lat,&finish_lon);

 /* Create the list of results and insert the first node into the queue */

 results=NewResultsList(2048);

 results->start=begin->start;
 results->finish=end->finish;

 result1=InsertResult(results,begin->start);
 result3=FindResult(begin,begin->start);

 *result1=*result3;

 queue=NewQueueList();

 /* Insert the finish points of the beginning part of the path into the queue */

 result3=FirstResult(begin);

 while(result3)
   {
    if(result3->node!=begin->start && !IsFakeNode(result3->node) && IsSuperNode(nodes,result3->node))
      {
       result2=InsertResult(results,result3->node);

       *result2=*result3;

       result2->prev=begin->start;

       result2->sortby=result2->score;

       InsertInQueue(queue,result2);
      }

    result3=NextResult(begin,result3);
   }

 if(begin->number==1)
    InsertInQueue(queue,result1);

 /* Loop across all nodes in the queue */

 while((result1=PopFromQueue(queue)))
   {
    if(result1->score>finish_score)
       continue;

    node1=result1->node;

    segment=FirstSegment(segments,nodes,node1);

    while(segment)
      {
       score_t segment_pref,segment_score,cumulative_score;
       int i;

       if(!IsSuperSegment(segment))
          goto endloop;

       if(profile->oneway && IsOnewayTo(segment,node1))
          goto endloop;

       node2=OtherNode(segment,node1);

       if(result1->prev==node2)
          goto endloop;

       way=LookupWay(ways,segment->way);

       if(!(way->allow&profile->allow))
          goto endloop;

       if(!profile->highway[HIGHWAY(way->type)])
          goto endloop;

       if(way->weight && way->weight<profile->weight)
          goto endloop;

       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->props & PROPERTIES(i))
            {
             if(way->props & PROPERTIES(i))
                segment_pref*=profile->props_yes[i];
             else
                segment_pref*=profile->props_no[i];
            }

       if(segment_pref==0)
          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;

       if(cumulative_score>finish_score)
          goto endloop;

       result2=FindResult(results,node2);

       if(!result2)                         /* New end node */
         {
          result2=InsertResult(results,node2);
          result2->prev=node1;
          result2->next=NO_NODE;
          result2->score=cumulative_score;
          result2->segment=segment;

          if((result3=FindResult(end,node2)))
            {
             if((result2->score+result3->score)<finish_score)
               {
                finish_score=result2->score+result3->score;
                end_prev=node2;
               }
            }
          else
            {
             double lat,lon;
             distance_t direct;

             GetLatLong(nodes,node2,&lat,&lon);
             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 is better */
         {
          result2->prev=node1;
          result2->score=cumulative_score;
          result2->segment=segment;

          if((result3=FindResult(end,node2)))
            {
             if((result2->score+result3->score)<finish_score)
               {
                finish_score=result2->score+result3->score;
                end_prev=node2;
               }
            }
          else if(result2->score<finish_score)
            {
             double lat,lon;
             distance_t direct;

             GetLatLong(nodes,node2,&lat,&lon);
             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);
            }
         }

      endloop:

       if(!option_quiet && !(results->number%10000))
         {
          printf("\rRouting: Super-Nodes checked = %d",results->number);
          fflush(stdout);
         }

       segment=NextSegment(segments,segment,node1);
      }
   }

 if(!option_quiet)
   {
    printf("\rRouting: Super-Nodes checked = %d\n",results->number);
    fflush(stdout);
   }

 /* Finish off the end part of the route. */

 if(!FindResult(results,end->finish) && end_prev!=NO_NODE)
   {
    result2=InsertResult(results,end->finish);
    result3=FindResult(end,end->finish);

    *result2=*result3;

    result2->prev=end_prev;
    result2->score=finish_score;
   }

 FreeQueueList(queue);

 /* Check it worked */

 if(end_prev==NO_NODE)
   {
    FreeResultsList(results);
    return(NULL);
   }

 FixForwardRoute(results,end->finish);

 return(results);
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
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);
}