Routino SVN Repository Browser

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

ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 955 - (show annotations) (download) (as text)
Sat Jan 28 14:40:54 2012 UTC (13 years, 1 month ago) by amb
Original Path: trunk/src/relations.c
File MIME type: text/x-csrc
File size: 9804 byte(s)
Simplify and standardise the included headers.

1 /***************************************
2 Relation data type functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2012 Andrew M. Bishop
7
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 <stdlib.h>
24
25 #include "types.h"
26 #include "relations.h"
27 #include "fakes.h"
28
29 #include "files.h"
30
31
32 /*++++++++++++++++++++++++++++++++++++++
33 Load in a relation list from a file.
34
35 Relations *LoadRelationList Returns the relation list.
36
37 const char *filename The name of the file to load.
38 ++++++++++++++++++++++++++++++++++++++*/
39
40 Relations *LoadRelationList(const char *filename)
41 {
42 Relations *relations;
43 #if SLIM
44 int i;
45 #endif
46
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 for(i=0;i<sizeof(relations->cached)/sizeof(relations->cached[0]);i++)
72 relations->incache[i]=NO_RELATION;
73
74 #endif
75
76 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 return(relations);
90 }
91
92
93 /*++++++++++++++++++++++++++++++++++++++
94 Find the first turn relation in the file whose 'via' matches a specific node.
95
96 index_t FindFirstTurnRelation1 Returns the index of the first turn relation matching.
97
98 Relations *relations The set of relations to use.
99
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 index_t start=0;
107 index_t end=relations->file.trnumber-1;
108 index_t mid;
109 index_t match=-1;
110
111 /* Binary search - search key any exact match is required.
112 *
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 * # <- end | start or end matches (but may not be the first).
120 */
121
122 do
123 {
124 mid=(start+end)/2; /* Choose mid point */
125
126 relation=LookupTurnRelation(relations,mid,1);
127
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 end=mid?(mid-1):mid;
132 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 relation=LookupTurnRelation(relations,start,1);
143
144 if(relation->via==via)
145 match=start;
146 }
147
148 if(match==-1) /* Check if end matches */
149 {
150 relation=LookupTurnRelation(relations,end,1);
151
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 relation=LookupTurnRelation(relations,match-1,1);
162
163 if(relation->via==via)
164 match--;
165 else
166 break;
167 }
168
169 return(match);
170 }
171
172
173 /*++++++++++++++++++++++++++++++++++++++
174 Find the next turn relation in the file whose 'via' matches a specific node.
175
176 index_t FindNextTurnRelation1 Returns the index of the next turn relation matching.
177
178 Relations *relations The set of relations to use.
179
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 relation=LookupTurnRelation(relations,current,1);
189
190 via=relation->via;
191
192 current++;
193
194 if(current==relations->file.trnumber)
195 return(NO_RELATION);
196
197 relation=LookupTurnRelation(relations,current,1);
198
199 if(relation->via==via)
200 return(current);
201 else
202 return(NO_RELATION);
203 }
204
205
206 /*++++++++++++++++++++++++++++++++++++++
207 Find the first turn relation in the file whose 'via' and 'from' match a specific node and segment.
208
209 index_t FindFirstTurnRelation2 Returns the index of the first turn relation matching.
210
211 Relations *relations The set of relations to use.
212
213 index_t via The node that the route is going via.
214
215 index_t from The segment that the route is coming from.
216 ++++++++++++++++++++++++++++++++++++++*/
217
218 index_t FindFirstTurnRelation2(Relations *relations,index_t via,index_t from)
219 {
220 TurnRelation *relation;
221 index_t start=0;
222 index_t end=relations->file.trnumber-1;
223 index_t mid;
224 index_t match=-1;
225
226 if(IsFakeSegment(from))
227 from=IndexRealSegment(from);
228
229 /* 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 * # <- end | start or end matches (but may not be the first).
238 */
239
240 do
241 {
242 mid=(start+end)/2; /* Choose mid point */
243
244 relation=LookupTurnRelation(relations,mid,1);
245
246 if(relation->via<via) /* Mid point is too low for 'via' */
247 start=mid+1;
248 else if(relation->via>via) /* Mid point is too high for 'via' */
249 end=mid?(mid-1):mid;
250 else /* Mid point is correct for 'via' */
251 {
252 if(relation->from<from) /* Mid point is too low for 'from' */
253 start=mid+1;
254 else if(relation->from>from) /* Mid point is too high for 'from' */
255 end=mid?(mid-1):mid;
256 else /* Mid point is correct for 'from' */
257 {
258 match=mid;
259 break;
260 }
261 }
262 }
263 while((end-start)>1);
264
265 if(match==-1) /* Check if start matches */
266 {
267 relation=LookupTurnRelation(relations,start,1);
268
269 if(relation->via==via && relation->from==from)
270 match=start;
271 }
272
273 if(match==-1) /* Check if end matches */
274 {
275 relation=LookupTurnRelation(relations,end,1);
276
277 if(relation->via==via && relation->from==from)
278 match=end;
279 }
280
281 if(match==-1)
282 return(NO_RELATION);
283
284 while(match>0) /* Search backwards for the first match */
285 {
286 relation=LookupTurnRelation(relations,match-1,1);
287
288 if(relation->via==via && relation->from==from)
289 match--;
290 else
291 break;
292 }
293
294 return(match);
295 }
296
297
298 /*++++++++++++++++++++++++++++++++++++++
299 Find the next turn relation in the file whose 'via' and 'from' match a specific node and segment.
300
301 index_t FindNextTurnRelation2 Returns the index of the next turn relation matching.
302
303 Relations *relations The set of relations to use.
304
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 relation=LookupTurnRelation(relations,current,1);
314
315 via=relation->via;
316 from=relation->from;
317
318 current++;
319
320 if(current==relations->file.trnumber)
321 return(NO_RELATION);
322
323 relation=LookupTurnRelation(relations,current,1);
324
325 if(relation->via==via && relation->from==from)
326 return(current);
327 else
328 return(NO_RELATION);
329 }
330
331
332 /*++++++++++++++++++++++++++++++++++++++
333 Determine if a turn is allowed between the nodes 'from', 'via' and 'to' for a particular transport type.
334
335 int IsTurnAllowed Return 1 if the turn is allowed or 0 if not.
336
337 Relations *relations The set of relations to use.
338
339 index_t index The index of the first turn relation containing 'via' and 'from'.
340
341 index_t via The via node.
342
343 index_t from The from segment.
344
345 index_t to The to segment.
346
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 if(IsFakeSegment(from))
353 from=IndexRealSegment(from);
354
355 if(IsFakeSegment(to))
356 to=IndexRealSegment(to);
357
358 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 }