Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /branches/destination-access/src/relations.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 843 - (hide annotations) (download) (as text)
Wed Sep 7 12:18:35 2011 UTC (13 years, 6 months ago) by amb
Original Path: trunk/src/relations.c
File MIME type: text/x-csrc
File size: 9808 byte(s)
Check binary search functions and improve comments, fix pathological case with
end point and/or improve start point.

1 amb 561 /***************************************
2     Relation data type functions.
3    
4     Part of the Routino routing software.
5     ******************/ /******************
6 amb 596 This file Copyright 2008-2011 Andrew M. Bishop
7 amb 561
8     This program is free software: you can redistribute it and/or modify
9     it under the terms of the GNU Affero General Public License as published by
10     the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12    
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     GNU Affero General Public License for more details.
17    
18     You should have received a copy of the GNU Affero General Public License
19     along with this program. If not, see <http://www.gnu.org/licenses/>.
20     ***************************************/
21    
22    
23     #include <sys/types.h>
24     #include <stdlib.h>
25    
26     #include "relations.h"
27 amb 608 #include "fakes.h"
28 amb 561
29     #include "files.h"
30    
31    
32     /*++++++++++++++++++++++++++++++++++++++
33     Load in a relation list from a file.
34    
35 amb 681 Relations *LoadRelationList Returns the relation list.
36 amb 561
37     const char *filename The name of the file to load.
38     ++++++++++++++++++++++++++++++++++++++*/
39    
40     Relations *LoadRelationList(const char *filename)
41     {
42     Relations *relations;
43 amb 706 #if SLIM
44     int i;
45     #endif
46 amb 561
47     relations=(Relations*)malloc(sizeof(Relations));
48    
49     #if !SLIM
50    
51     relations->data=MapFile(filename);
52    
53     /* Copy the RelationsFile header structure from the loaded data */
54    
55     relations->file=*((RelationsFile*)relations->data);
56    
57     /* Set the pointers in the Relations structure. */
58    
59     relations->turnrelations=(TurnRelation*)(relations->data+sizeof(RelationsFile));
60    
61     #else
62    
63     relations->fd=ReOpenFile(filename);
64    
65     /* Copy the RelationsFile header structure from the loaded data */
66    
67     ReadFile(relations->fd,&relations->file,sizeof(RelationsFile));
68    
69     relations->troffset=sizeof(RelationsFile);
70    
71 amb 706 for(i=0;i<sizeof(relations->cached)/sizeof(relations->cached[0]);i++)
72     relations->incache[i]=NO_RELATION;
73 amb 562
74 amb 561 #endif
75    
76 amb 563 if(relations->file.trnumber>0)
77     {
78     TurnRelation *relation;
79    
80     relation=LookupTurnRelation(relations,0,1);
81    
82     relations->via_start =relation->via;
83    
84     relation=LookupTurnRelation(relations,relations->file.trnumber-1,1);
85    
86     relations->via_end =relation->via;
87     }
88    
89 amb 561 return(relations);
90     }
91 amb 562
92    
93     /*++++++++++++++++++++++++++++++++++++++
94 amb 680 Find the first turn relation in the file whose 'via' matches a specific node.
95 amb 562
96 amb 680 index_t FindFirstTurnRelation1 Returns the index of the first turn relation matching.
97 amb 562
98 amb 681 Relations *relations The set of relations to use.
99 amb 562
100     index_t via The node that the route is going via.
101     ++++++++++++++++++++++++++++++++++++++*/
102    
103     index_t FindFirstTurnRelation1(Relations *relations,index_t via)
104     {
105     TurnRelation *relation;
106 amb 780 index_t start=0;
107     index_t end=relations->file.trnumber-1;
108     index_t mid;
109     index_t match=-1;
110 amb 562
111 amb 843 /* Binary search - search key any exact match is required.
112 amb 562 *
113     * # <- start | Check mid and move start or end if it doesn't match
114     * # |
115     * # | Since an exact match is wanted we can set end=mid-1
116     * # <- mid | or start=mid+1 because we know that mid doesn't match.
117     * # |
118     * # | Eventually either end=start or end=start+1 and one of
119 amb 680 * # <- end | start or end matches (but may not be the first).
120 amb 562 */
121    
122     do
123     {
124     mid=(start+end)/2; /* Choose mid point */
125    
126 amb 563 relation=LookupTurnRelation(relations,mid,1);
127 amb 562
128     if(relation->via<via) /* Mid point is too low for 'via' */
129     start=mid+1;
130     else if(relation->via>via) /* Mid point is too high for 'via' */
131 amb 843 end=mid?(mid-1):mid;
132 amb 562 else /* Mid point is correct for 'from' */
133     {
134     match=mid;
135     break;
136     }
137     }
138     while((end-start)>1);
139    
140     if(match==-1) /* Check if start matches */
141     {
142 amb 563 relation=LookupTurnRelation(relations,start,1);
143 amb 562
144     if(relation->via==via)
145     match=start;
146     }
147    
148     if(match==-1) /* Check if end matches */
149     {
150 amb 563 relation=LookupTurnRelation(relations,end,1);
151 amb 562
152     if(relation->via==via)
153     match=end;
154     }
155    
156     if(match==-1)
157     return(NO_RELATION);
158    
159     while(match>0) /* Search backwards for the first match */
160     {
161 amb 563 relation=LookupTurnRelation(relations,match-1,1);
162 amb 562
163     if(relation->via==via)
164     match--;
165     else
166     break;
167     }
168    
169     return(match);
170     }
171    
172    
173     /*++++++++++++++++++++++++++++++++++++++
174 amb 680 Find the next turn relation in the file whose 'via' matches a specific node.
175 amb 562
176 amb 680 index_t FindNextTurnRelation1 Returns the index of the next turn relation matching.
177 amb 562
178 amb 681 Relations *relations The set of relations to use.
179 amb 562
180     index_t current The current index of a relation that matches.
181     ++++++++++++++++++++++++++++++++++++++*/
182    
183     index_t FindNextTurnRelation1(Relations *relations,index_t current)
184     {
185     TurnRelation *relation;
186     index_t via;
187    
188 amb 563 relation=LookupTurnRelation(relations,current,1);
189 amb 562
190     via=relation->via;
191    
192     current++;
193    
194 amb 596 if(current==relations->file.trnumber)
195     return(NO_RELATION);
196    
197 amb 563 relation=LookupTurnRelation(relations,current,1);
198 amb 562
199     if(relation->via==via)
200     return(current);
201     else
202     return(NO_RELATION);
203     }
204    
205    
206     /*++++++++++++++++++++++++++++++++++++++
207 amb 680 Find the first turn relation in the file whose 'via' and 'from' match a specific node and segment.
208 amb 562
209 amb 680 index_t FindFirstTurnRelation2 Returns the index of the first turn relation matching.
210 amb 562
211 amb 681 Relations *relations The set of relations to use.
212 amb 562
213     index_t via The node that the route is going via.
214    
215 amb 599 index_t from The segment that the route is coming from.
216 amb 562 ++++++++++++++++++++++++++++++++++++++*/
217    
218     index_t FindFirstTurnRelation2(Relations *relations,index_t via,index_t from)
219     {
220     TurnRelation *relation;
221 amb 780 index_t start=0;
222     index_t end=relations->file.trnumber-1;
223     index_t mid;
224     index_t match=-1;
225 amb 562
226 amb 608 if(IsFakeSegment(from))
227     from=IndexRealSegment(from);
228    
229 amb 562 /* Binary search - search key first match is required.
230     *
231     * # <- start | Check mid and move start or end if it doesn't match
232     * # |
233     * # | Since an exact match is wanted we can set end=mid-1
234     * # <- mid | or start=mid+1 because we know that mid doesn't match.
235     * # |
236     * # | Eventually either end=start or end=start+1 and one of
237 amb 680 * # <- end | start or end matches (but may not be the first).
238 amb 562 */
239    
240     do
241     {
242 amb 563 mid=(start+end)/2; /* Choose mid point */
243 amb 562
244 amb 563 relation=LookupTurnRelation(relations,mid,1);
245 amb 562
246 amb 563 if(relation->via<via) /* Mid point is too low for 'via' */
247 amb 562 start=mid+1;
248 amb 563 else if(relation->via>via) /* Mid point is too high for 'via' */
249 amb 843 end=mid?(mid-1):mid;
250 amb 563 else /* Mid point is correct for 'via' */
251 amb 562 {
252 amb 563 if(relation->from<from) /* Mid point is too low for 'from' */
253 amb 562 start=mid+1;
254 amb 563 else if(relation->from>from) /* Mid point is too high for 'from' */
255 amb 843 end=mid?(mid-1):mid;
256 amb 563 else /* Mid point is correct for 'from' */
257 amb 562 {
258     match=mid;
259     break;
260     }
261     }
262     }
263     while((end-start)>1);
264    
265 amb 563 if(match==-1) /* Check if start matches */
266 amb 562 {
267 amb 563 relation=LookupTurnRelation(relations,start,1);
268 amb 562
269     if(relation->via==via && relation->from==from)
270     match=start;
271     }
272    
273 amb 563 if(match==-1) /* Check if end matches */
274 amb 562 {
275 amb 563 relation=LookupTurnRelation(relations,end,1);
276 amb 562
277     if(relation->via==via && relation->from==from)
278     match=end;
279     }
280    
281     if(match==-1)
282     return(NO_RELATION);
283    
284 amb 563 while(match>0) /* Search backwards for the first match */
285 amb 562 {
286 amb 563 relation=LookupTurnRelation(relations,match-1,1);
287 amb 562
288     if(relation->via==via && relation->from==from)
289     match--;
290     else
291     break;
292     }
293    
294     return(match);
295     }
296    
297    
298     /*++++++++++++++++++++++++++++++++++++++
299 amb 680 Find the next turn relation in the file whose 'via' and 'from' match a specific node and segment.
300 amb 562
301 amb 680 index_t FindNextTurnRelation2 Returns the index of the next turn relation matching.
302 amb 562
303 amb 681 Relations *relations The set of relations to use.
304 amb 562
305     index_t current The current index of a relation that matches.
306     ++++++++++++++++++++++++++++++++++++++*/
307    
308     index_t FindNextTurnRelation2(Relations *relations,index_t current)
309     {
310     TurnRelation *relation;
311     index_t via,from;
312    
313 amb 563 relation=LookupTurnRelation(relations,current,1);
314 amb 562
315     via=relation->via;
316     from=relation->from;
317    
318     current++;
319    
320 amb 596 if(current==relations->file.trnumber)
321     return(NO_RELATION);
322    
323 amb 563 relation=LookupTurnRelation(relations,current,1);
324 amb 562
325     if(relation->via==via && relation->from==from)
326     return(current);
327     else
328     return(NO_RELATION);
329     }
330 amb 596
331    
332     /*++++++++++++++++++++++++++++++++++++++
333 amb 680 Determine if a turn is allowed between the nodes 'from', 'via' and 'to' for a particular transport type.
334 amb 596
335 amb 680 int IsTurnAllowed Return 1 if the turn is allowed or 0 if not.
336 amb 596
337 amb 681 Relations *relations The set of relations to use.
338 amb 596
339 amb 680 index_t index The index of the first turn relation containing 'via' and 'from'.
340 amb 596
341     index_t via The via node.
342    
343 amb 599 index_t from The from segment.
344 amb 596
345 amb 599 index_t to The to segment.
346 amb 596
347     transports_t transport The type of transport that is being routed.
348     ++++++++++++++++++++++++++++++++++++++*/
349    
350     int IsTurnAllowed(Relations *relations,index_t index,index_t via,index_t from,index_t to,transports_t transport)
351     {
352 amb 608 if(IsFakeSegment(from))
353     from=IndexRealSegment(from);
354    
355     if(IsFakeSegment(to))
356     to=IndexRealSegment(to);
357    
358 amb 596 while(index<relations->file.trnumber)
359     {
360     TurnRelation *relation=LookupTurnRelation(relations,index,1);
361    
362     if(relation->via!=via)
363     return(1);
364    
365     if(relation->from!=from)
366     return(1);
367    
368     if(relation->to>to)
369     return(1);
370    
371     if(relation->to==to)
372     if(!(relation->except & transport))
373     return(0);
374    
375     index++;
376     }
377    
378     return(1);
379     }