Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/errorlogx.c
Parent Directory
|
Revision Log
Revision 1362 -
(hide annotations)
(download)
(as text)
Sat Jun 1 11:10:24 2013 UTC (11 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 25046 byte(s)
Sat Jun 1 11:10:24 2013 UTC (11 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 25046 byte(s)
Make the functions for processing error logs more like the ones for nodes, ways and relations.
1 | amb | 1317 | /*************************************** |
2 | amb | 1319 | Error log processing functions. |
3 | amb | 1317 | |
4 | Part of the Routino routing software. | ||
5 | ******************/ /****************** | ||
6 | This file Copyright 2013 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 "typesx.h" | ||
24 | #include "nodesx.h" | ||
25 | #include "waysx.h" | ||
26 | #include "relationsx.h" | ||
27 | |||
28 | amb | 1320 | #include "errorlogx.h" |
29 | #include "errorlog.h" | ||
30 | |||
31 | amb | 1317 | #include "files.h" |
32 | #include "sorting.h" | ||
33 | |||
34 | |||
35 | amb | 1362 | /* Global variables */ |
36 | amb | 1317 | |
37 | /*+ The name of the error log file. +*/ | ||
38 | extern char *errorlogfilename; | ||
39 | |||
40 | /*+ The name of the binary error log file. +*/ | ||
41 | extern char *errorbinfilename; | ||
42 | |||
43 | amb | 1362 | /* Local variables */ |
44 | amb | 1317 | |
45 | amb | 1362 | /*+ Temporary file-local variables for use by the sort functions. +*/ |
46 | static latlong_t lat_min,lat_max,lon_min,lon_max; | ||
47 | |||
48 | amb | 1317 | /* Local functions */ |
49 | |||
50 | static void reindex_nodes(NodesX *nodesx); | ||
51 | static void reindex_ways(WaysX *waysx); | ||
52 | static void reindex_relations(RelationsX *relationsx); | ||
53 | amb | 1341 | |
54 | static int lookup_lat_long_node(NodesX *nodesx,node_t node,latlong_t *latitude,latlong_t *longitude); | ||
55 | static int lookup_lat_long_way(WaysX *waysx,NodesX *nodesx,way_t way,latlong_t *latitude,latlong_t *longitude,index_t error); | ||
56 | static int lookup_lat_long_relation(RelationsX *relationsx,WaysX *waysx,NodesX *nodesx,relation_t relation,latlong_t *latitude,latlong_t *longitude,index_t error); | ||
57 | |||
58 | amb | 1317 | static int sort_by_lat_long(ErrorLogX *a,ErrorLogX *b); |
59 | amb | 1362 | static int measure_lat_long(ErrorLogX *errorlogx,index_t index); |
60 | amb | 1317 | |
61 | |||
62 | /*++++++++++++++++++++++++++++++++++++++ | ||
63 | amb | 1362 | Allocate a new error log list (create a new file). |
64 | |||
65 | ErrorLogsX *NewErrorLogList Returns a pointer to the error log list. | ||
66 | ++++++++++++++++++++++++++++++++++++++*/ | ||
67 | |||
68 | ErrorLogsX *NewErrorLogList(void) | ||
69 | { | ||
70 | ErrorLogsX *errorlogsx; | ||
71 | |||
72 | errorlogsx=(ErrorLogsX*)calloc(1,sizeof(ErrorLogsX)); | ||
73 | |||
74 | logassert(errorlogsx,"Failed to allocate memory (try using slim mode?)"); /* Check calloc() worked */ | ||
75 | |||
76 | return(errorlogsx); | ||
77 | } | ||
78 | |||
79 | |||
80 | /*++++++++++++++++++++++++++++++++++++++ | ||
81 | Free an error log list. | ||
82 | |||
83 | ErrorLogsX *errorlogsx The set of error logs to be freed. | ||
84 | ++++++++++++++++++++++++++++++++++++++*/ | ||
85 | |||
86 | void FreeErrorLogList(ErrorLogsX *errorlogsx) | ||
87 | { | ||
88 | free(errorlogsx); | ||
89 | } | ||
90 | |||
91 | |||
92 | /*++++++++++++++++++++++++++++++++++++++ | ||
93 | amb | 1317 | Process the binary error log. |
94 | |||
95 | amb | 1362 | ErrorLogsX *errorlogsx The set of error logs to update. |
96 | |||
97 | amb | 1317 | NodesX *nodesx The set of nodes. |
98 | |||
99 | WaysX *waysx The set of ways. | ||
100 | |||
101 | RelationsX *relationsx The set of relations. | ||
102 | ++++++++++++++++++++++++++++++++++++++*/ | ||
103 | |||
104 | amb | 1362 | void ProcessErrorLogs(ErrorLogsX *errorlogsx,NodesX *nodesx,WaysX *waysx,RelationsX *relationsx) |
105 | amb | 1317 | { |
106 | int oldfd,newfd; | ||
107 | uint32_t offset=0; | ||
108 | int nerrorlogobjects=0; | ||
109 | int finished; | ||
110 | ErrorLogObject errorlogobjects[8]; | ||
111 | |||
112 | /* Re-index the nodes, ways and relations */ | ||
113 | |||
114 | amb | 1341 | printf_first("Re-indexing the Data: Nodes=0 Ways=0 Route-Relations=0 Turn-Relations=0"); |
115 | amb | 1317 | |
116 | reindex_nodes(nodesx); | ||
117 | |||
118 | amb | 1341 | printf_middle("Re-indexing the Data: Nodes=%"Pindex_t" Ways=0 Route-Relations=0 Turn-Relations=0",nodesx->number); |
119 | amb | 1317 | |
120 | reindex_ways(waysx); | ||
121 | |||
122 | amb | 1341 | printf_middle("Re-indexing the Data: Nodes=%"Pindex_t" Ways=%"Pindex_t" Route-Relations=0 Turn-Relations=0",nodesx->number,waysx->number); |
123 | amb | 1317 | |
124 | reindex_relations(relationsx); | ||
125 | |||
126 | amb | 1342 | printf_last("Re-indexed the Data: Nodes=%"Pindex_t" Ways=%"Pindex_t" Route-Relations=%"Pindex_t" Turn-Relations=%"Pindex_t,nodesx->number,waysx->number,relationsx->rrnumber,relationsx->trnumber); |
127 | amb | 1317 | |
128 | |||
129 | /* Print the start message */ | ||
130 | |||
131 | printf_first("Calculating Coordinates: Errors=0"); | ||
132 | |||
133 | /* Map into memory / open the files */ | ||
134 | |||
135 | #if !SLIM | ||
136 | nodesx->data=MapFile(nodesx->filename); | ||
137 | #else | ||
138 | nodesx->fd=ReOpenFile(nodesx->filename); | ||
139 | |||
140 | InvalidateNodeXCache(nodesx->cache); | ||
141 | #endif | ||
142 | |||
143 | amb | 1338 | waysx->fd=ReOpenFile(waysx->filename); |
144 | amb | 1342 | relationsx->rrfd=ReOpenFile(relationsx->rrfilename); |
145 | amb | 1341 | relationsx->trfd=ReOpenFile(relationsx->trfilename); |
146 | amb | 1338 | |
147 | amb | 1317 | /* Open the binary log file read-only and a new file writeable */ |
148 | |||
149 | oldfd=ReOpenFile(errorbinfilename); | ||
150 | |||
151 | DeleteFile(errorbinfilename); | ||
152 | |||
153 | newfd=OpenFileNew(errorbinfilename); | ||
154 | |||
155 | /* Loop through the file and merge the raw data into coordinates */ | ||
156 | |||
157 | amb | 1362 | errorlogsx->number=0; |
158 | amb | 1317 | |
159 | do | ||
160 | { | ||
161 | ErrorLogObject errorlogobject; | ||
162 | |||
163 | finished=ReadFile(oldfd,&errorlogobject,sizeof(ErrorLogObject)); | ||
164 | |||
165 | if(finished) | ||
166 | errorlogobject.offset=SizeFile(errorlogfilename); | ||
167 | |||
168 | if(offset!=errorlogobject.offset) | ||
169 | { | ||
170 | ErrorLogX errorlogx; | ||
171 | amb | 1341 | latlong_t errorlat=NO_LATLONG,errorlon=NO_LATLONG; |
172 | amb | 1317 | |
173 | /* Calculate suitable coordinates */ | ||
174 | |||
175 | amb | 1341 | if(nerrorlogobjects==1) |
176 | amb | 1317 | { |
177 | amb | 1341 | if(((errorlogobjects[0].type_id>>56)&0xff)=='N') |
178 | { | ||
179 | node_t node=(node_t)(errorlogobjects[0].type_id&(uint64_t)0x00ffffffffffffff); | ||
180 | amb | 1338 | |
181 | amb | 1341 | lookup_lat_long_node(nodesx,node,&errorlat,&errorlon); |
182 | } | ||
183 | else if(((errorlogobjects[0].type_id>>56)&0xff)=='W') | ||
184 | amb | 1317 | { |
185 | amb | 1341 | way_t way=(way_t)(errorlogobjects[0].type_id&(uint64_t)0x00ffffffffffffff); |
186 | amb | 1317 | |
187 | amb | 1362 | lookup_lat_long_way(waysx,nodesx,way,&errorlat,&errorlon,errorlogsx->number); |
188 | amb | 1341 | } |
189 | else if(((errorlogobjects[0].type_id>>56)&0xff)=='R') | ||
190 | { | ||
191 | relation_t relation=(relation_t)(errorlogobjects[0].type_id&(uint64_t)0x00ffffffffffffff); | ||
192 | |||
193 | amb | 1362 | lookup_lat_long_relation(relationsx,waysx,nodesx,relation,&errorlat,&errorlon,errorlogsx->number); |
194 | amb | 1341 | } |
195 | } | ||
196 | else | ||
197 | { | ||
198 | latlong_t latitude[8],longitude[8]; | ||
199 | int i; | ||
200 | int ncoords=0,nnodes=0,nways=0,nrelations=0; | ||
201 | |||
202 | for(i=0;i<nerrorlogobjects;i++) | ||
203 | { | ||
204 | if(((errorlogobjects[i].type_id>>56)&0xff)=='N') | ||
205 | amb | 1317 | { |
206 | amb | 1341 | node_t node=(node_t)(errorlogobjects[i].type_id&(uint64_t)0x00ffffffffffffff); |
207 | amb | 1317 | |
208 | amb | 1341 | if(lookup_lat_long_node(nodesx,node,&latitude[ncoords],&longitude[ncoords])) |
209 | ncoords++; | ||
210 | amb | 1338 | |
211 | nnodes++; | ||
212 | amb | 1317 | } |
213 | amb | 1341 | else if(((errorlogobjects[i].type_id>>56)&0xff)=='W') nways++; |
214 | else if(((errorlogobjects[i].type_id>>56)&0xff)=='R') nrelations++; | ||
215 | amb | 1317 | } |
216 | amb | 1341 | |
217 | if(nways==0 && nrelations==0) /* only nodes */ | ||
218 | ; | ||
219 | else if(ncoords) /* some good nodes, possibly ways and/or relations */ | ||
220 | ; | ||
221 | else if(nways) /* no good nodes, possibly some good ways */ | ||
222 | amb | 1338 | { |
223 | amb | 1341 | for(i=0;i<nerrorlogobjects;i++) |
224 | if(((errorlogobjects[i].type_id>>56)&0xff)=='W') | ||
225 | { | ||
226 | way_t way=(way_t)(errorlogobjects[i].type_id&(uint64_t)0x00ffffffffffffff); | ||
227 | amb | 1338 | |
228 | amb | 1362 | if(lookup_lat_long_way(waysx,nodesx,way,&latitude[ncoords],&longitude[ncoords],errorlogsx->number)) |
229 | amb | 1341 | ncoords++; |
230 | } | ||
231 | } | ||
232 | amb | 1338 | |
233 | amb | 1341 | if(nrelations==0) /* only nodes and/or ways */ |
234 | ; | ||
235 | else if(ncoords) /* some good nodes and/or ways, possibly relations */ | ||
236 | ; | ||
237 | else /* if(nrelations) */ | ||
238 | { | ||
239 | for(i=0;i<nerrorlogobjects;i++) | ||
240 | if(((errorlogobjects[i].type_id>>56)&0xff)=='R') | ||
241 | { | ||
242 | relation_t relation=(relation_t)(errorlogobjects[i].type_id&(uint64_t)0x00ffffffffffffff); | ||
243 | amb | 1338 | |
244 | amb | 1362 | if(lookup_lat_long_relation(relationsx,waysx,nodesx,relation,&latitude[ncoords],&longitude[ncoords],errorlogsx->number)) |
245 | amb | 1341 | ncoords++; |
246 | } | ||
247 | } | ||
248 | amb | 1338 | |
249 | amb | 1341 | if(ncoords) |
250 | { | ||
251 | errorlat=0; | ||
252 | errorlon=0; | ||
253 | amb | 1338 | |
254 | amb | 1341 | for(i=0;i<ncoords;i++) |
255 | { | ||
256 | errorlat+=latitude[i]; | ||
257 | errorlon+=longitude[i]; | ||
258 | } | ||
259 | amb | 1338 | |
260 | amb | 1341 | errorlat/=ncoords; |
261 | errorlon/=ncoords; | ||
262 | amb | 1338 | } |
263 | amb | 1341 | else |
264 | amb | 1338 | { |
265 | amb | 1341 | errorlat=NO_LATLONG; |
266 | errorlon=NO_LATLONG; | ||
267 | amb | 1338 | } |
268 | amb | 1317 | } |
269 | |||
270 | /* Write to file */ | ||
271 | |||
272 | errorlogx.offset=offset; | ||
273 | errorlogx.length=errorlogobject.offset-offset; | ||
274 | |||
275 | amb | 1338 | errorlogx.latitude =errorlat; |
276 | errorlogx.longitude=errorlon; | ||
277 | amb | 1317 | |
278 | WriteFile(newfd,&errorlogx,sizeof(ErrorLogX)); | ||
279 | |||
280 | amb | 1362 | errorlogsx->number++; |
281 | amb | 1317 | |
282 | offset=errorlogobject.offset; | ||
283 | nerrorlogobjects=0; | ||
284 | |||
285 | amb | 1362 | if(!(errorlogsx->number%10000)) |
286 | printf_middle("Calculating Coordinates: Errors=%"Pindex_t,errorlogsx->number); | ||
287 | amb | 1317 | } |
288 | |||
289 | /* Store for later */ | ||
290 | |||
291 | logassert(nerrorlogobjects<8,"Too many error log objects for one error message."); /* Only a limited amount of information stored. */ | ||
292 | |||
293 | errorlogobjects[nerrorlogobjects]=errorlogobject; | ||
294 | |||
295 | nerrorlogobjects++; | ||
296 | } | ||
297 | while(!finished); | ||
298 | |||
299 | /* Unmap from memory / close the files */ | ||
300 | |||
301 | #if !SLIM | ||
302 | nodesx->data=UnmapFile(nodesx->data); | ||
303 | #else | ||
304 | nodesx->fd=CloseFile(nodesx->fd); | ||
305 | #endif | ||
306 | |||
307 | amb | 1338 | waysx->fd=CloseFile(waysx->fd); |
308 | amb | 1342 | relationsx->rrfd=CloseFile(relationsx->rrfd); |
309 | amb | 1341 | relationsx->trfd=CloseFile(relationsx->trfd); |
310 | amb | 1338 | |
311 | amb | 1317 | CloseFile(oldfd); |
312 | CloseFile(newfd); | ||
313 | |||
314 | /* Print the final message */ | ||
315 | |||
316 | amb | 1362 | printf_last("Calculated Coordinates: Errors=%"Pindex_t,errorlogsx->number); |
317 | amb | 1317 | } |
318 | |||
319 | |||
320 | /*++++++++++++++++++++++++++++++++++++++ | ||
321 | Re-index the nodes that were kept. | ||
322 | |||
323 | NodesX *nodesx The set of nodes to process (contains the filename and number of nodes). | ||
324 | ++++++++++++++++++++++++++++++++++++++*/ | ||
325 | |||
326 | static void reindex_nodes(NodesX *nodesx) | ||
327 | { | ||
328 | int fd; | ||
329 | index_t index=0; | ||
330 | NodeX nodex; | ||
331 | |||
332 | nodesx->number=nodesx->knumber; | ||
333 | |||
334 | nodesx->idata=(node_t*)malloc(nodesx->number*sizeof(node_t)); | ||
335 | |||
336 | /* Get the node id for each node in the file. */ | ||
337 | |||
338 | fd=ReOpenFile(nodesx->filename); | ||
339 | |||
340 | while(!ReadFile(fd,&nodex,sizeof(NodeX))) | ||
341 | { | ||
342 | nodesx->idata[index]=nodex.id; | ||
343 | |||
344 | index++; | ||
345 | } | ||
346 | |||
347 | CloseFile(fd); | ||
348 | } | ||
349 | |||
350 | |||
351 | /*++++++++++++++++++++++++++++++++++++++ | ||
352 | Re-index the ways that were kept. | ||
353 | |||
354 | WaysX *waysx The set of ways to process (contains the filename and number of ways). | ||
355 | ++++++++++++++++++++++++++++++++++++++*/ | ||
356 | |||
357 | static void reindex_ways(WaysX *waysx) | ||
358 | { | ||
359 | int fd; | ||
360 | off_t size,position=0; | ||
361 | index_t index=0; | ||
362 | |||
363 | waysx->number=waysx->knumber; | ||
364 | |||
365 | waysx->idata=(way_t*)malloc(waysx->number*sizeof(way_t)); | ||
366 | waysx->odata=(off_t*)malloc(waysx->number*sizeof(off_t)); | ||
367 | |||
368 | /* Get the way id and the offset for each way in the file */ | ||
369 | |||
370 | size=SizeFile(waysx->filename); | ||
371 | |||
372 | fd=ReOpenFile(waysx->filename); | ||
373 | |||
374 | while(position<size) | ||
375 | { | ||
376 | amb | 1338 | WayX wayx; |
377 | amb | 1317 | FILESORT_VARINT waysize; |
378 | |||
379 | SeekReadFile(fd,&waysize,FILESORT_VARSIZE,position); | ||
380 | amb | 1338 | SeekReadFile(fd,&wayx,sizeof(WayX),position+FILESORT_VARSIZE); |
381 | amb | 1317 | |
382 | waysx->idata[index]=wayx.id; | ||
383 | amb | 1338 | waysx->odata[index]=position+FILESORT_VARSIZE+sizeof(WayX); |
384 | amb | 1317 | |
385 | index++; | ||
386 | |||
387 | position+=waysize+FILESORT_VARSIZE; | ||
388 | } | ||
389 | |||
390 | CloseFile(fd); | ||
391 | } | ||
392 | |||
393 | |||
394 | /*++++++++++++++++++++++++++++++++++++++ | ||
395 | Re-index the relations that were kept. | ||
396 | |||
397 | amb | 1341 | RelationsX *relationsx The set of relations to process (contains the filenames and numbers of relations). |
398 | amb | 1317 | ++++++++++++++++++++++++++++++++++++++*/ |
399 | |||
400 | static void reindex_relations(RelationsX *relationsx) | ||
401 | { | ||
402 | amb | 1341 | int fd; |
403 | off_t size,position=0; | ||
404 | index_t index; | ||
405 | TurnRelX turnrelx; | ||
406 | |||
407 | /* Route relations */ | ||
408 | |||
409 | amb | 1342 | relationsx->rrnumber=relationsx->rrknumber; |
410 | amb | 1341 | |
411 | amb | 1342 | relationsx->rridata=(relation_t*)malloc(relationsx->rrnumber*sizeof(relation_t)); |
412 | relationsx->rrodata=(off_t*)malloc(relationsx->rrnumber*sizeof(off_t)); | ||
413 | amb | 1341 | |
414 | /* Get the relation id and the offset for each relation in the file */ | ||
415 | |||
416 | amb | 1342 | size=SizeFile(relationsx->rrfilename); |
417 | amb | 1341 | |
418 | amb | 1342 | fd=ReOpenFile(relationsx->rrfilename); |
419 | amb | 1341 | |
420 | index=0; | ||
421 | |||
422 | while(position<size) | ||
423 | { | ||
424 | FILESORT_VARINT relationsize; | ||
425 | RouteRelX routerelx; | ||
426 | |||
427 | SeekReadFile(fd,&relationsize,FILESORT_VARSIZE,position); | ||
428 | SeekReadFile(fd,&routerelx,sizeof(RouteRelX),position+FILESORT_VARSIZE); | ||
429 | |||
430 | amb | 1342 | relationsx->rridata[index]=routerelx.id; |
431 | relationsx->rrodata[index]=position+FILESORT_VARSIZE+sizeof(RouteRelX); | ||
432 | amb | 1341 | |
433 | index++; | ||
434 | |||
435 | position+=relationsize+FILESORT_VARSIZE; | ||
436 | } | ||
437 | |||
438 | CloseFile(fd); | ||
439 | |||
440 | |||
441 | /* Turn relations */ | ||
442 | |||
443 | relationsx->trnumber=relationsx->trknumber; | ||
444 | |||
445 | relationsx->tridata=(relation_t*)malloc(relationsx->trnumber*sizeof(relation_t)); | ||
446 | |||
447 | /* Get the relation id and the offset for each relation in the file */ | ||
448 | |||
449 | fd=ReOpenFile(relationsx->trfilename); | ||
450 | |||
451 | index=0; | ||
452 | |||
453 | while(!ReadFile(fd,&turnrelx,sizeof(TurnRelX))) | ||
454 | { | ||
455 | relationsx->tridata[index]=turnrelx.id; | ||
456 | |||
457 | index++; | ||
458 | } | ||
459 | |||
460 | CloseFile(fd); | ||
461 | amb | 1317 | } |
462 | |||
463 | |||
464 | /*++++++++++++++++++++++++++++++++++++++ | ||
465 | amb | 1341 | Lookup a node's latitude and longitude. |
466 | |||
467 | int lookup_lat_long_node Returns 1 if a node was found. | ||
468 | |||
469 | NodesX *nodesx The set of nodes to use. | ||
470 | |||
471 | node_t node The node number. | ||
472 | |||
473 | latlong_t *latitude Returns the latitude. | ||
474 | |||
475 | latlong_t *longitude Returns the longitude. | ||
476 | ++++++++++++++++++++++++++++++++++++++*/ | ||
477 | |||
478 | static int lookup_lat_long_node(NodesX *nodesx,node_t node,latlong_t *latitude,latlong_t *longitude) | ||
479 | { | ||
480 | index_t index=IndexNodeX(nodesx,node); | ||
481 | |||
482 | if(index==NO_NODE) | ||
483 | return 0; | ||
484 | else | ||
485 | { | ||
486 | NodeX *nodex=LookupNodeX(nodesx,index,1); | ||
487 | |||
488 | *latitude =nodex->latitude; | ||
489 | *longitude=nodex->longitude; | ||
490 | |||
491 | return 1; | ||
492 | } | ||
493 | } | ||
494 | |||
495 | |||
496 | /*++++++++++++++++++++++++++++++++++++++ | ||
497 | Lookup a way's latitude and longitude. | ||
498 | |||
499 | int lookup_lat_long_way Returns 1 if a way was found. | ||
500 | |||
501 | WaysX *waysx The set of ways to use. | ||
502 | |||
503 | NodesX *nodesx The set of nodes to use. | ||
504 | |||
505 | way_t way The way number. | ||
506 | |||
507 | latlong_t *latitude Returns the latitude. | ||
508 | |||
509 | latlong_t *longitude Returns the longitude. | ||
510 | |||
511 | index_t error The index of the error in the complete set of errors. | ||
512 | ++++++++++++++++++++++++++++++++++++++*/ | ||
513 | |||
514 | static int lookup_lat_long_way(WaysX *waysx,NodesX *nodesx,way_t way,latlong_t *latitude,latlong_t *longitude,index_t error) | ||
515 | { | ||
516 | index_t index=IndexWayX(waysx,way); | ||
517 | |||
518 | if(index==NO_WAY) | ||
519 | return 0; | ||
520 | else | ||
521 | { | ||
522 | int count=1; | ||
523 | off_t offset=waysx->odata[index]; | ||
524 | node_t node1,node2,prevnode,node; | ||
525 | latlong_t latitude1,longitude1,latitude2,longitude2; | ||
526 | |||
527 | SeekFile(waysx->fd,offset); | ||
528 | |||
529 | /* Choose a random pair of adjacent nodes */ | ||
530 | |||
531 | if(ReadFile(waysx->fd,&node1,sizeof(node_t)) || node1==NO_NODE_ID) | ||
532 | return 0; | ||
533 | |||
534 | if(ReadFile(waysx->fd,&node2,sizeof(node_t)) || node2==NO_NODE_ID) | ||
535 | return lookup_lat_long_node(nodesx,node1,latitude,longitude); | ||
536 | |||
537 | prevnode=node2; | ||
538 | |||
539 | while(!ReadFile(waysx->fd,&node,sizeof(node_t)) && node!=NO_NODE_ID) | ||
540 | { | ||
541 | count++; | ||
542 | |||
543 | if((error%count)==0) /* A 1/count chance */ | ||
544 | { | ||
545 | node1=prevnode; | ||
546 | node2=node; | ||
547 | } | ||
548 | |||
549 | prevnode=node; | ||
550 | } | ||
551 | |||
552 | if(!lookup_lat_long_node(nodesx,node1,&latitude1,&longitude1)) | ||
553 | return lookup_lat_long_node(nodesx,node2,latitude,longitude); | ||
554 | |||
555 | if(!lookup_lat_long_node(nodesx,node2,&latitude2,&longitude2)) | ||
556 | return lookup_lat_long_node(nodesx,node1,latitude,longitude); | ||
557 | |||
558 | *latitude =(latitude1 +latitude2 )/2; | ||
559 | *longitude=(longitude1+longitude2)/2; | ||
560 | |||
561 | return 1; | ||
562 | } | ||
563 | } | ||
564 | |||
565 | |||
566 | /*++++++++++++++++++++++++++++++++++++++ | ||
567 | Lookup a relation's latitude and longitude. | ||
568 | |||
569 | int lookup_lat_long_relation Returns 1 if a relation was found. | ||
570 | |||
571 | RelationsX *relationsx The set of relations to use. | ||
572 | |||
573 | WaysX *waysx The set of ways to use. | ||
574 | |||
575 | NodesX *nodesx The set of nodes to use. | ||
576 | |||
577 | relation_t relation The relation number. | ||
578 | |||
579 | latlong_t *latitude Returns the latitude. | ||
580 | |||
581 | latlong_t *longitude Returns the longitude. | ||
582 | |||
583 | index_t error The index of the error in the complete set of errors. | ||
584 | ++++++++++++++++++++++++++++++++++++++*/ | ||
585 | |||
586 | static int lookup_lat_long_relation(RelationsX *relationsx,WaysX *waysx,NodesX *nodesx,relation_t relation,latlong_t *latitude,latlong_t *longitude,index_t error) | ||
587 | { | ||
588 | index_t index=IndexRouteRelX(relationsx,relation); | ||
589 | |||
590 | if(index==NO_RELATION) | ||
591 | { | ||
592 | index=IndexTurnRelX(relationsx,relation); | ||
593 | |||
594 | if(index==NO_RELATION) | ||
595 | return 0; | ||
596 | else | ||
597 | { | ||
598 | TurnRelX turnrelx; | ||
599 | |||
600 | SeekReadFile(relationsx->trfd,&turnrelx,sizeof(TurnRelX),index*sizeof(TurnRelX)); | ||
601 | |||
602 | if(lookup_lat_long_node(nodesx,turnrelx.via,latitude,longitude)) | ||
603 | return 1; | ||
604 | |||
605 | if(lookup_lat_long_way(waysx,nodesx,turnrelx.from,latitude,longitude,error)) | ||
606 | return 1; | ||
607 | |||
608 | if(lookup_lat_long_way(waysx,nodesx,turnrelx.to,latitude,longitude,error)) | ||
609 | return 1; | ||
610 | |||
611 | return 0; | ||
612 | } | ||
613 | } | ||
614 | else | ||
615 | { | ||
616 | int count=0; | ||
617 | amb | 1342 | off_t offset=relationsx->rrodata[index]; |
618 | amb | 1341 | way_t way=NO_WAY_ID,tempway; |
619 | relation_t relation=NO_RELATION_ID,temprelation; | ||
620 | |||
621 | amb | 1342 | SeekFile(relationsx->rrfd,offset); |
622 | amb | 1341 | |
623 | /* Choose a random way */ | ||
624 | |||
625 | amb | 1342 | while(!ReadFile(relationsx->rrfd,&tempway,sizeof(way_t)) && tempway!=NO_WAY_ID) |
626 | amb | 1341 | { |
627 | count++; | ||
628 | |||
629 | if((error%count)==0) /* A 1/count chance */ | ||
630 | way=tempway; | ||
631 | } | ||
632 | |||
633 | if(lookup_lat_long_way(waysx,nodesx,way,latitude,longitude,error)) | ||
634 | return 1; | ||
635 | |||
636 | /* Choose a random relation */ | ||
637 | |||
638 | amb | 1342 | while(!ReadFile(relationsx->rrfd,&temprelation,sizeof(relation_t)) && temprelation!=NO_RELATION_ID) |
639 | amb | 1341 | { |
640 | count++; | ||
641 | |||
642 | if((error%count)==0) /* A 1/count chance */ | ||
643 | relation=temprelation; | ||
644 | } | ||
645 | |||
646 | return lookup_lat_long_relation(relationsx,waysx,nodesx,relation,latitude,longitude,error); | ||
647 | } | ||
648 | } | ||
649 | |||
650 | |||
651 | /*++++++++++++++++++++++++++++++++++++++ | ||
652 | amb | 1317 | Sort the error logs geographically. |
653 | amb | 1362 | |
654 | ErrorLogsX *errorlogsx The set of error logs to sort. | ||
655 | amb | 1317 | ++++++++++++++++++++++++++++++++++++++*/ |
656 | |||
657 | amb | 1362 | void SortErrorLogsGeographically(ErrorLogsX *errorlogsx) |
658 | amb | 1317 | { |
659 | int oldfd,newfd; | ||
660 | amb | 1362 | ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin; |
661 | amb | 1317 | |
662 | /* Print the start message */ | ||
663 | |||
664 | printf_first("Sorting Errors Geographically"); | ||
665 | |||
666 | amb | 1362 | /* Work out the range of data */ |
667 | |||
668 | lat_min=radians_to_latlong( 2); | ||
669 | lat_max=radians_to_latlong(-2); | ||
670 | lon_min=radians_to_latlong( 4); | ||
671 | lon_max=radians_to_latlong(-4); | ||
672 | |||
673 | amb | 1317 | /* Re-open the file read-only and a new file writeable */ |
674 | |||
675 | oldfd=ReOpenFile(errorbinfilename); | ||
676 | |||
677 | DeleteFile(errorbinfilename); | ||
678 | |||
679 | newfd=OpenFileNew(errorbinfilename); | ||
680 | |||
681 | /* Sort errors geographically */ | ||
682 | |||
683 | amb | 1362 | filesort_fixed(oldfd,newfd,sizeof(ErrorLogX),NULL, |
684 | (int (*)(const void*,const void*))sort_by_lat_long, | ||
685 | (int (*)(void*,index_t))measure_lat_long); | ||
686 | amb | 1317 | |
687 | /* Close the files */ | ||
688 | |||
689 | CloseFile(oldfd); | ||
690 | CloseFile(newfd); | ||
691 | |||
692 | amb | 1362 | /* Work out the number of bins */ |
693 | |||
694 | lat_min_bin=latlong_to_bin(lat_min); | ||
695 | lon_min_bin=latlong_to_bin(lon_min); | ||
696 | lat_max_bin=latlong_to_bin(lat_max); | ||
697 | lon_max_bin=latlong_to_bin(lon_max); | ||
698 | |||
699 | errorlogsx->latzero=lat_min_bin; | ||
700 | errorlogsx->lonzero=lon_min_bin; | ||
701 | |||
702 | errorlogsx->latbins=(lat_max_bin-lat_min_bin)+1; | ||
703 | errorlogsx->lonbins=(lon_max_bin-lon_min_bin)+1; | ||
704 | |||
705 | amb | 1317 | /* Print the final message */ |
706 | |||
707 | amb | 1362 | printf_last("Sorted Errors Geographically: Error=%"Pindex_t,errorlogsx->number); |
708 | amb | 1317 | } |
709 | |||
710 | |||
711 | /*++++++++++++++++++++++++++++++++++++++ | ||
712 | Sort the errors into latitude and longitude order (first by longitude bin | ||
713 | number, then by latitude bin number and then by exact longitude and then by | ||
714 | exact latitude). | ||
715 | |||
716 | int sort_by_lat_long Returns the comparison of the latitude and longitude fields. | ||
717 | |||
718 | ErrorLogX *a The first error location. | ||
719 | |||
720 | ErrorLogX *b The second error location. | ||
721 | ++++++++++++++++++++++++++++++++++++++*/ | ||
722 | |||
723 | static int sort_by_lat_long(ErrorLogX *a,ErrorLogX *b) | ||
724 | { | ||
725 | ll_bin_t a_lon=latlong_to_bin(a->longitude); | ||
726 | ll_bin_t b_lon=latlong_to_bin(b->longitude); | ||
727 | |||
728 | if(a_lon<b_lon) | ||
729 | return(-1); | ||
730 | else if(a_lon>b_lon) | ||
731 | return(1); | ||
732 | else | ||
733 | { | ||
734 | ll_bin_t a_lat=latlong_to_bin(a->latitude); | ||
735 | ll_bin_t b_lat=latlong_to_bin(b->latitude); | ||
736 | |||
737 | if(a_lat<b_lat) | ||
738 | return(-1); | ||
739 | else if(a_lat>b_lat) | ||
740 | return(1); | ||
741 | else | ||
742 | { | ||
743 | if(a->longitude<b->longitude) | ||
744 | return(-1); | ||
745 | else if(a->longitude>b->longitude) | ||
746 | return(1); | ||
747 | else | ||
748 | { | ||
749 | if(a->latitude<b->latitude) | ||
750 | return(-1); | ||
751 | else if(a->latitude>b->latitude) | ||
752 | return(1); | ||
753 | } | ||
754 | |||
755 | return(FILESORT_PRESERVE_ORDER(a,b)); | ||
756 | } | ||
757 | } | ||
758 | } | ||
759 | |||
760 | |||
761 | /*++++++++++++++++++++++++++++++++++++++ | ||
762 | amb | 1362 | Measure the extent of the data. |
763 | |||
764 | int measure_lat_long Return 1 if the value is to be kept, otherwise 0. | ||
765 | |||
766 | ErrorLogX *errorlogx The error location. | ||
767 | |||
768 | index_t index The number of sorted error locations that have already been written to the output file. | ||
769 | ++++++++++++++++++++++++++++++++++++++*/ | ||
770 | |||
771 | static int measure_lat_long(ErrorLogX *errorlogx,index_t index) | ||
772 | { | ||
773 | if(errorlogx->latitude!=NO_LATLONG) | ||
774 | { | ||
775 | if(errorlogx->latitude<lat_min) | ||
776 | lat_min=errorlogx->latitude; | ||
777 | if(errorlogx->latitude>lat_max) | ||
778 | lat_max=errorlogx->latitude; | ||
779 | if(errorlogx->longitude<lon_min) | ||
780 | lon_min=errorlogx->longitude; | ||
781 | if(errorlogx->longitude>lon_max) | ||
782 | lon_max=errorlogx->longitude; | ||
783 | } | ||
784 | |||
785 | return(1); | ||
786 | } | ||
787 | |||
788 | |||
789 | /*++++++++++++++++++++++++++++++++++++++ | ||
790 | amb | 1317 | Save the binary error log. |
791 | |||
792 | amb | 1362 | ErrorLogsX *errorlogsx The set of error logs to write. |
793 | amb | 1317 | |
794 | char *filename The name of the final file to write. | ||
795 | ++++++++++++++++++++++++++++++++++++++*/ | ||
796 | |||
797 | amb | 1362 | void SaveErrorLogs(ErrorLogsX *errorlogsx,char *filename) |
798 | amb | 1317 | { |
799 | ErrorLogsFile errorlogsfile; | ||
800 | ErrorLogX errorlogx; | ||
801 | int oldfd,newfd; | ||
802 | ll_bin2_t latlonbin=0,maxlatlonbins; | ||
803 | index_t *offsets; | ||
804 | index_t number=0,number_geo=0,number_nongeo=0; | ||
805 | off_t size; | ||
806 | |||
807 | /* Print the start message */ | ||
808 | |||
809 | printf_first("Writing Errors: Geographical=0 Non-geographical=0"); | ||
810 | |||
811 | /* Allocate the memory for the geographical offsets array */ | ||
812 | |||
813 | amb | 1362 | offsets=(index_t*)malloc((errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t)); |
814 | amb | 1317 | |
815 | logassert(offsets,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ | ||
816 | |||
817 | latlonbin=0; | ||
818 | |||
819 | /* Re-open the file */ | ||
820 | |||
821 | oldfd=ReOpenFile(errorbinfilename); | ||
822 | |||
823 | newfd=OpenFileNew(filename); | ||
824 | |||
825 | /* Write out the geographical errors */ | ||
826 | |||
827 | amb | 1362 | SeekFile(newfd,sizeof(ErrorLogsFile)+(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t)); |
828 | amb | 1317 | |
829 | while(!ReadFile(oldfd,&errorlogx,sizeof(ErrorLogX))) | ||
830 | { | ||
831 | ErrorLog errorlog={0}; | ||
832 | ll_bin_t latbin,lonbin; | ||
833 | ll_bin2_t llbin; | ||
834 | |||
835 | if(errorlogx.latitude==NO_LATLONG) | ||
836 | continue; | ||
837 | |||
838 | /* Create the ErrorLog */ | ||
839 | |||
840 | errorlog.latoffset=latlong_to_off(errorlogx.latitude); | ||
841 | errorlog.lonoffset=latlong_to_off(errorlogx.longitude); | ||
842 | |||
843 | errorlog.offset=errorlogx.offset; | ||
844 | errorlog.length=errorlogx.length; | ||
845 | |||
846 | /* Work out the offsets */ | ||
847 | |||
848 | amb | 1362 | latbin=latlong_to_bin(errorlogx.latitude )-errorlogsx->latzero; |
849 | lonbin=latlong_to_bin(errorlogx.longitude)-errorlogsx->lonzero; | ||
850 | llbin=lonbin*errorlogsx->latbins+latbin; | ||
851 | amb | 1317 | |
852 | for(;latlonbin<=llbin;latlonbin++) | ||
853 | offsets[latlonbin]=number_geo; | ||
854 | |||
855 | /* Write the data */ | ||
856 | |||
857 | WriteFile(newfd,&errorlog,sizeof(ErrorLog)); | ||
858 | |||
859 | number_geo++; | ||
860 | number++; | ||
861 | |||
862 | if(!(number%10000)) | ||
863 | printf_middle("Writing Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo); | ||
864 | } | ||
865 | |||
866 | /* Write out the non-geographical errors */ | ||
867 | |||
868 | SeekFile(oldfd,0); | ||
869 | |||
870 | while(!ReadFile(oldfd,&errorlogx,sizeof(ErrorLogX))) | ||
871 | { | ||
872 | ErrorLog errorlog={0}; | ||
873 | |||
874 | if(errorlogx.latitude!=NO_LATLONG) | ||
875 | continue; | ||
876 | |||
877 | /* Create the ErrorLog */ | ||
878 | |||
879 | errorlog.latoffset=0; | ||
880 | errorlog.lonoffset=0; | ||
881 | |||
882 | errorlog.offset=errorlogx.offset; | ||
883 | errorlog.length=errorlogx.length; | ||
884 | |||
885 | /* Write the data */ | ||
886 | |||
887 | WriteFile(newfd,&errorlog,sizeof(ErrorLog)); | ||
888 | |||
889 | number_nongeo++; | ||
890 | number++; | ||
891 | |||
892 | if(!(number%10000)) | ||
893 | printf_middle("Writing Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo); | ||
894 | } | ||
895 | |||
896 | /* Close the input file */ | ||
897 | |||
898 | CloseFile(oldfd); | ||
899 | |||
900 | DeleteFile(errorbinfilename); | ||
901 | |||
902 | /* Append the text from the log file */ | ||
903 | |||
904 | size=SizeFile(errorlogfilename); | ||
905 | |||
906 | oldfd=ReOpenFile(errorlogfilename); | ||
907 | |||
908 | while(size) | ||
909 | { | ||
910 | amb | 1321 | int i; |
911 | char buffer[4096]; | ||
912 | amb | 1317 | off_t chunksize=(size>sizeof(buffer)?sizeof(buffer):size); |
913 | |||
914 | ReadFile(oldfd,buffer,chunksize); | ||
915 | |||
916 | amb | 1321 | for(i=0;i<chunksize;i++) |
917 | if(buffer[i]=='\n') | ||
918 | buffer[i]=0; | ||
919 | |||
920 | amb | 1317 | WriteFile(newfd,buffer,chunksize); |
921 | |||
922 | size-=chunksize; | ||
923 | } | ||
924 | |||
925 | CloseFile(oldfd); | ||
926 | |||
927 | /* Finish off the offset indexing and write them out */ | ||
928 | |||
929 | amb | 1362 | maxlatlonbins=errorlogsx->latbins*errorlogsx->lonbins; |
930 | amb | 1317 | |
931 | for(;latlonbin<=maxlatlonbins;latlonbin++) | ||
932 | offsets[latlonbin]=number_geo; | ||
933 | |||
934 | SeekFile(newfd,sizeof(ErrorLogsFile)); | ||
935 | amb | 1362 | WriteFile(newfd,offsets,(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t)); |
936 | amb | 1317 | |
937 | free(offsets); | ||
938 | |||
939 | /* Write out the header structure */ | ||
940 | |||
941 | errorlogsfile.number =number; | ||
942 | errorlogsfile.number_geo =number_geo; | ||
943 | errorlogsfile.number_nongeo=number_nongeo; | ||
944 | |||
945 | amb | 1362 | errorlogsfile.latbins=errorlogsx->latbins; |
946 | errorlogsfile.lonbins=errorlogsx->lonbins; | ||
947 | amb | 1317 | |
948 | amb | 1362 | errorlogsfile.latzero=errorlogsx->latzero; |
949 | errorlogsfile.lonzero=errorlogsx->lonzero; | ||
950 | amb | 1317 | |
951 | SeekFile(newfd,0); | ||
952 | WriteFile(newfd,&errorlogsfile,sizeof(ErrorLogsFile)); | ||
953 | |||
954 | CloseFile(newfd); | ||
955 | |||
956 | /* Print the final message */ | ||
957 | |||
958 | printf_last("Wrote Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo); | ||
959 | } |