Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/relationsx.c
Parent Directory
|
Revision Log
Revision 496 -
(hide annotations)
(download)
(as text)
Fri Sep 17 17:42:45 2010 UTC (14 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 8395 byte(s)
Fri Sep 17 17:42:45 2010 UTC (14 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 8395 byte(s)
Initial revision
1 | amb | 496 | /*************************************** |
2 | $Header: /home/amb/CVS/routino/src/relationsx.c,v 1.1 2010-09-17 17:42:45 amb Exp $ | ||
3 | |||
4 | Extended Relation data type functions. | ||
5 | |||
6 | Part of the Routino routing software. | ||
7 | ******************/ /****************** | ||
8 | This file Copyright 2010 Andrew M. Bishop | ||
9 | |||
10 | This program is free software: you can redistribute it and/or modify | ||
11 | it under the terms of the GNU Affero General Public License as published by | ||
12 | the Free Software Foundation, either version 3 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU Affero General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU Affero General Public License | ||
21 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
22 | ***************************************/ | ||
23 | |||
24 | |||
25 | #include <assert.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <stdio.h> | ||
28 | #include <string.h> | ||
29 | #include <sys/stat.h> | ||
30 | |||
31 | #include "waysx.h" | ||
32 | #include "relationsx.h" | ||
33 | |||
34 | #include "files.h" | ||
35 | #include "functions.h" | ||
36 | |||
37 | |||
38 | /* Variables */ | ||
39 | |||
40 | /*+ The command line '--tmpdir' option or its default value. +*/ | ||
41 | extern char *option_tmpdirname; | ||
42 | |||
43 | /*+ A temporary file-local variable for use by the sort functions. +*/ | ||
44 | static RelationsX *sortrelationsx; | ||
45 | |||
46 | /* Functions */ | ||
47 | |||
48 | static int sort_by_id(RouteRelX *a,RouteRelX *b); | ||
49 | static int deduplicate_by_id(RouteRelX *relationx,index_t index); | ||
50 | |||
51 | |||
52 | /*++++++++++++++++++++++++++++++++++++++ | ||
53 | Allocate a new relation list (create a new file or open an existing one). | ||
54 | |||
55 | RelationsX *NewRelationList Returns the relation list. | ||
56 | |||
57 | int append Set to 1 if the file is to be opened for appending (now or later). | ||
58 | ++++++++++++++++++++++++++++++++++++++*/ | ||
59 | |||
60 | RelationsX *NewRelationList(int append) | ||
61 | { | ||
62 | RelationsX *relationsx; | ||
63 | |||
64 | relationsx=(RelationsX*)calloc(1,sizeof(RelationsX)); | ||
65 | |||
66 | assert(relationsx); /* Check calloc() worked */ | ||
67 | |||
68 | relationsx->rfilename=(char*)malloc(strlen(option_tmpdirname)+32); | ||
69 | |||
70 | if(append) | ||
71 | sprintf(relationsx->rfilename,"%s/relationsx.route.input.tmp",option_tmpdirname); | ||
72 | else | ||
73 | sprintf(relationsx->rfilename,"%s/relationsx.route.%p.tmp",option_tmpdirname,relationsx); | ||
74 | |||
75 | if(append) | ||
76 | { | ||
77 | off_t size,position=0; | ||
78 | |||
79 | relationsx->rfd=AppendFile(relationsx->rfilename); | ||
80 | |||
81 | size=SizeFile(relationsx->rfilename); | ||
82 | |||
83 | while(position<size) | ||
84 | { | ||
85 | FILESORT_VARINT relationsize; | ||
86 | |||
87 | SeekFile(relationsx->rfd,position); | ||
88 | ReadFile(relationsx->rfd,&relationsize,FILESORT_VARSIZE); | ||
89 | |||
90 | relationsx->rxnumber++; | ||
91 | position+=relationsize+FILESORT_VARSIZE; | ||
92 | } | ||
93 | |||
94 | SeekFile(relationsx->rfd,size); | ||
95 | } | ||
96 | else | ||
97 | relationsx->rfd=OpenFile(relationsx->rfilename); | ||
98 | |||
99 | return(relationsx); | ||
100 | } | ||
101 | |||
102 | |||
103 | /*++++++++++++++++++++++++++++++++++++++ | ||
104 | Free a relation list. | ||
105 | |||
106 | RelationsX *relationsx The list to be freed. | ||
107 | |||
108 | int keep Set to 1 if the file is to be kept. | ||
109 | ++++++++++++++++++++++++++++++++++++++*/ | ||
110 | |||
111 | void FreeRelationList(RelationsX *relationsx,int keep) | ||
112 | { | ||
113 | if(!keep) | ||
114 | DeleteFile(relationsx->rfilename); | ||
115 | |||
116 | free(relationsx->rfilename); | ||
117 | |||
118 | free(relationsx); | ||
119 | } | ||
120 | |||
121 | |||
122 | /*++++++++++++++++++++++++++++++++++++++ | ||
123 | Append a single relation to an unsorted route relation list. | ||
124 | |||
125 | RelationsX* relationsx The set of relations to process. | ||
126 | |||
127 | relation_t id The ID of the relation. | ||
128 | |||
129 | allow_t routes The types of routes that this relation is for. | ||
130 | |||
131 | way_t *ways The array of ways that are members of the relation. | ||
132 | |||
133 | int nways The number of ways that are members of the relation. | ||
134 | |||
135 | relation_t *relations The array of relations that are members of the relation. | ||
136 | |||
137 | int nrelations The number of relations that are members of the relation. | ||
138 | ++++++++++++++++++++++++++++++++++++++*/ | ||
139 | |||
140 | void AppendRouteRelation(RelationsX* relationsx,relation_t id,allow_t routes, | ||
141 | way_t *ways,int nways, | ||
142 | relation_t *relations,int nrelations) | ||
143 | { | ||
144 | RouteRelX relationx; | ||
145 | FILESORT_VARINT size,padsize; | ||
146 | way_t zeroway=0; | ||
147 | relation_t zerorelation=0; | ||
148 | void *zeropointer=NULL; | ||
149 | |||
150 | relationx.id=id; | ||
151 | relationx.routes=routes; | ||
152 | |||
153 | size=sizeof(RouteRelX)+(nways+1)*sizeof(way_t)+(nrelations+1)*sizeof(relation_t); | ||
154 | padsize=sizeof(RouteRelX*)*((size+sizeof(RouteRelX*)-1)/sizeof(RouteRelX*)); | ||
155 | |||
156 | WriteFile(relationsx->rfd,&padsize,FILESORT_VARSIZE); | ||
157 | WriteFile(relationsx->rfd,&relationx,sizeof(RouteRelX)); | ||
158 | |||
159 | WriteFile(relationsx->rfd,ways ,nways*sizeof(way_t)); | ||
160 | WriteFile(relationsx->rfd,&zeroway, sizeof(way_t)); | ||
161 | |||
162 | WriteFile(relationsx->rfd,relations ,nrelations*sizeof(relation_t)); | ||
163 | WriteFile(relationsx->rfd,&zerorelation, sizeof(relation_t)); | ||
164 | |||
165 | WriteFile(relationsx->rfd,&zeropointer,padsize-size); | ||
166 | |||
167 | relationsx->rxnumber++; | ||
168 | |||
169 | assert(!(relationsx->rxnumber==0)); /* Zero marks the high-water mark for relations. */ | ||
170 | } | ||
171 | |||
172 | |||
173 | /*++++++++++++++++++++++++++++++++++++++ | ||
174 | Sort the list of relations. | ||
175 | |||
176 | RelationsX* relationsx The set of relations to process. | ||
177 | ++++++++++++++++++++++++++++++++++++++*/ | ||
178 | |||
179 | void SortRelationList(RelationsX* relationsx) | ||
180 | { | ||
181 | int rfd; | ||
182 | |||
183 | /* Print the start message */ | ||
184 | |||
185 | printf("Sorting Relations"); | ||
186 | fflush(stdout); | ||
187 | |||
188 | /* Close the file and re-open it (finished appending) */ | ||
189 | |||
190 | CloseFile(relationsx->rfd); | ||
191 | relationsx->rfd=ReOpenFile(relationsx->rfilename); | ||
192 | |||
193 | DeleteFile(relationsx->rfilename); | ||
194 | |||
195 | rfd=OpenFile(relationsx->rfilename); | ||
196 | |||
197 | /* Sort the relations to allow removing duplicates */ | ||
198 | |||
199 | sortrelationsx=relationsx; | ||
200 | |||
201 | filesort_vary(relationsx->rfd,rfd,(int (*)(const void*,const void*))sort_by_id,(int (*)(void*,index_t))deduplicate_by_id); | ||
202 | |||
203 | /* Close the files */ | ||
204 | |||
205 | CloseFile(relationsx->rfd); | ||
206 | CloseFile(rfd); | ||
207 | |||
208 | /* Print the final message */ | ||
209 | |||
210 | printf("\rSorted Relations: Relations=%d Duplicates=%d\n",relationsx->rxnumber,relationsx->rxnumber-relationsx->rnumber); | ||
211 | fflush(stdout); | ||
212 | } | ||
213 | |||
214 | |||
215 | /*++++++++++++++++++++++++++++++++++++++ | ||
216 | Sort the relations into id order. | ||
217 | |||
218 | int sort_by_id Returns the comparison of the id fields. | ||
219 | |||
220 | RouteRelX *a The first extended relation. | ||
221 | |||
222 | RouteRelX *b The second extended relation. | ||
223 | ++++++++++++++++++++++++++++++++++++++*/ | ||
224 | |||
225 | static int sort_by_id(RouteRelX *a,RouteRelX *b) | ||
226 | { | ||
227 | relation_t a_id=a->id; | ||
228 | relation_t b_id=b->id; | ||
229 | |||
230 | if(a_id<b_id) | ||
231 | return(-1); | ||
232 | else if(a_id>b_id) | ||
233 | return(1); | ||
234 | else | ||
235 | return(0); | ||
236 | } | ||
237 | |||
238 | |||
239 | /*++++++++++++++++++++++++++++++++++++++ | ||
240 | Deduplicate the extended relations using the id after sorting. | ||
241 | |||
242 | int deduplicate_by_id Return 1 if the value is to be kept, otherwise zero. | ||
243 | |||
244 | RouteRelX *relationx The extended relation. | ||
245 | |||
246 | index_t index The index of this relation in the total. | ||
247 | ++++++++++++++++++++++++++++++++++++++*/ | ||
248 | |||
249 | static int deduplicate_by_id(RouteRelX *relationx,index_t index) | ||
250 | { | ||
251 | static relation_t previd; | ||
252 | |||
253 | if(index==0 || relationx->id!=previd) | ||
254 | { | ||
255 | previd=relationx->id; | ||
256 | |||
257 | sortrelationsx->rnumber++; | ||
258 | |||
259 | return(1); | ||
260 | } | ||
261 | |||
262 | return(0); | ||
263 | } | ||
264 | |||
265 | |||
266 | /*++++++++++++++++++++++++++++++++++++++ | ||
267 | Process the route relations and apply the information to the ways. | ||
268 | |||
269 | RelationsX *relationsx The set of relations to process. | ||
270 | |||
271 | WaysX *waysx The set of ways to update. | ||
272 | ++++++++++++++++++++++++++++++++++++++*/ | ||
273 | |||
274 | void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx) | ||
275 | { | ||
276 | int i; | ||
277 | |||
278 | /* Print the start message */ | ||
279 | |||
280 | printf("Processing Route Relations: Relations=0"); | ||
281 | fflush(stdout); | ||
282 | |||
283 | /* Open the file and read through it */ | ||
284 | |||
285 | relationsx->rfd=ReOpenFile(relationsx->rfilename); | ||
286 | |||
287 | for(i=0;i<relationsx->rnumber;i++) | ||
288 | { | ||
289 | FILESORT_VARINT padsize,size; | ||
290 | RouteRelX relationx; | ||
291 | way_t way; | ||
292 | relation_t relation; | ||
293 | void *pointer; | ||
294 | |||
295 | ReadFile(relationsx->rfd,&padsize,FILESORT_VARSIZE); | ||
296 | ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX)); | ||
297 | |||
298 | size=FILESORT_VARSIZE+sizeof(RouteRelX); | ||
299 | |||
300 | do | ||
301 | { | ||
302 | ReadFile(relationsx->rfd,&way,sizeof(way_t)); | ||
303 | |||
304 | // if(way) | ||
305 | // printf("Relation %d includes way %d\n",relationx.id,way); | ||
306 | |||
307 | size+=sizeof(way_t); | ||
308 | } | ||
309 | while(way); | ||
310 | |||
311 | do | ||
312 | { | ||
313 | ReadFile(relationsx->rfd,&relation,sizeof(relation_t)); | ||
314 | |||
315 | // if(relation) | ||
316 | // printf("Relation %d includes relation %d\n",relationx.id,relation); | ||
317 | |||
318 | size+=sizeof(relation_t); | ||
319 | } | ||
320 | while(relation); | ||
321 | |||
322 | ReadFile(relationsx->rfd,&pointer,padsize-size); | ||
323 | } | ||
324 | |||
325 | CloseFile(relationsx->rfd); | ||
326 | |||
327 | /* Print the final message */ | ||
328 | |||
329 | printf("\rProcessed Route Relations: Relations=%d \n",relationsx->rnumber); | ||
330 | fflush(stdout); | ||
331 | } |