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 1392 -
(hide annotations)
(download)
(as text)
Mon Jun 10 18:42:55 2013 UTC (11 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 25437 byte(s)
Mon Jun 10 18:42:55 2013 UTC (11 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 25437 byte(s)
Fix typo in program logging.
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 | amb | 1370 | int count; |
617 | amb | 1342 | off_t offset=relationsx->rrodata[index]; |
618 | amb | 1370 | node_t node=NO_NODE_ID,tempnode; |
619 | amb | 1341 | way_t way=NO_WAY_ID,tempway; |
620 | relation_t relation=NO_RELATION_ID,temprelation; | ||
621 | |||
622 | amb | 1342 | SeekFile(relationsx->rrfd,offset); |
623 | amb | 1341 | |
624 | amb | 1370 | /* Choose a random node */ |
625 | |||
626 | count=0; | ||
627 | |||
628 | while(!ReadFile(relationsx->rrfd,&tempnode,sizeof(node_t)) && tempnode!=NO_NODE_ID) | ||
629 | { | ||
630 | count++; | ||
631 | |||
632 | if((error%count)==0) /* A 1/count chance */ | ||
633 | node=tempnode; | ||
634 | } | ||
635 | |||
636 | if(lookup_lat_long_node(nodesx,node,latitude,longitude)) | ||
637 | return 1; | ||
638 | |||
639 | amb | 1341 | /* Choose a random way */ |
640 | |||
641 | amb | 1370 | count=0; |
642 | |||
643 | amb | 1342 | while(!ReadFile(relationsx->rrfd,&tempway,sizeof(way_t)) && tempway!=NO_WAY_ID) |
644 | amb | 1341 | { |
645 | count++; | ||
646 | |||
647 | if((error%count)==0) /* A 1/count chance */ | ||
648 | way=tempway; | ||
649 | } | ||
650 | |||
651 | if(lookup_lat_long_way(waysx,nodesx,way,latitude,longitude,error)) | ||
652 | return 1; | ||
653 | |||
654 | /* Choose a random relation */ | ||
655 | |||
656 | amb | 1370 | count=0; |
657 | |||
658 | amb | 1342 | while(!ReadFile(relationsx->rrfd,&temprelation,sizeof(relation_t)) && temprelation!=NO_RELATION_ID) |
659 | amb | 1341 | { |
660 | count++; | ||
661 | |||
662 | if((error%count)==0) /* A 1/count chance */ | ||
663 | relation=temprelation; | ||
664 | } | ||
665 | |||
666 | return lookup_lat_long_relation(relationsx,waysx,nodesx,relation,latitude,longitude,error); | ||
667 | } | ||
668 | } | ||
669 | |||
670 | |||
671 | /*++++++++++++++++++++++++++++++++++++++ | ||
672 | amb | 1317 | Sort the error logs geographically. |
673 | amb | 1362 | |
674 | ErrorLogsX *errorlogsx The set of error logs to sort. | ||
675 | amb | 1317 | ++++++++++++++++++++++++++++++++++++++*/ |
676 | |||
677 | amb | 1362 | void SortErrorLogsGeographically(ErrorLogsX *errorlogsx) |
678 | amb | 1317 | { |
679 | int oldfd,newfd; | ||
680 | amb | 1362 | ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin; |
681 | amb | 1317 | |
682 | /* Print the start message */ | ||
683 | |||
684 | printf_first("Sorting Errors Geographically"); | ||
685 | |||
686 | amb | 1362 | /* Work out the range of data */ |
687 | |||
688 | lat_min=radians_to_latlong( 2); | ||
689 | lat_max=radians_to_latlong(-2); | ||
690 | lon_min=radians_to_latlong( 4); | ||
691 | lon_max=radians_to_latlong(-4); | ||
692 | |||
693 | amb | 1317 | /* Re-open the file read-only and a new file writeable */ |
694 | |||
695 | oldfd=ReOpenFile(errorbinfilename); | ||
696 | |||
697 | DeleteFile(errorbinfilename); | ||
698 | |||
699 | newfd=OpenFileNew(errorbinfilename); | ||
700 | |||
701 | /* Sort errors geographically */ | ||
702 | |||
703 | amb | 1362 | filesort_fixed(oldfd,newfd,sizeof(ErrorLogX),NULL, |
704 | (int (*)(const void*,const void*))sort_by_lat_long, | ||
705 | (int (*)(void*,index_t))measure_lat_long); | ||
706 | amb | 1317 | |
707 | /* Close the files */ | ||
708 | |||
709 | CloseFile(oldfd); | ||
710 | CloseFile(newfd); | ||
711 | |||
712 | amb | 1362 | /* Work out the number of bins */ |
713 | |||
714 | lat_min_bin=latlong_to_bin(lat_min); | ||
715 | lon_min_bin=latlong_to_bin(lon_min); | ||
716 | lat_max_bin=latlong_to_bin(lat_max); | ||
717 | lon_max_bin=latlong_to_bin(lon_max); | ||
718 | |||
719 | errorlogsx->latzero=lat_min_bin; | ||
720 | errorlogsx->lonzero=lon_min_bin; | ||
721 | |||
722 | errorlogsx->latbins=(lat_max_bin-lat_min_bin)+1; | ||
723 | errorlogsx->lonbins=(lon_max_bin-lon_min_bin)+1; | ||
724 | |||
725 | amb | 1317 | /* Print the final message */ |
726 | |||
727 | amb | 1392 | printf_last("Sorted Errors Geographically: Errors=%"Pindex_t,errorlogsx->number); |
728 | amb | 1317 | } |
729 | |||
730 | |||
731 | /*++++++++++++++++++++++++++++++++++++++ | ||
732 | Sort the errors into latitude and longitude order (first by longitude bin | ||
733 | number, then by latitude bin number and then by exact longitude and then by | ||
734 | exact latitude). | ||
735 | |||
736 | int sort_by_lat_long Returns the comparison of the latitude and longitude fields. | ||
737 | |||
738 | ErrorLogX *a The first error location. | ||
739 | |||
740 | ErrorLogX *b The second error location. | ||
741 | ++++++++++++++++++++++++++++++++++++++*/ | ||
742 | |||
743 | static int sort_by_lat_long(ErrorLogX *a,ErrorLogX *b) | ||
744 | { | ||
745 | ll_bin_t a_lon=latlong_to_bin(a->longitude); | ||
746 | ll_bin_t b_lon=latlong_to_bin(b->longitude); | ||
747 | |||
748 | if(a_lon<b_lon) | ||
749 | return(-1); | ||
750 | else if(a_lon>b_lon) | ||
751 | return(1); | ||
752 | else | ||
753 | { | ||
754 | ll_bin_t a_lat=latlong_to_bin(a->latitude); | ||
755 | ll_bin_t b_lat=latlong_to_bin(b->latitude); | ||
756 | |||
757 | if(a_lat<b_lat) | ||
758 | return(-1); | ||
759 | else if(a_lat>b_lat) | ||
760 | return(1); | ||
761 | else | ||
762 | { | ||
763 | if(a->longitude<b->longitude) | ||
764 | return(-1); | ||
765 | else if(a->longitude>b->longitude) | ||
766 | return(1); | ||
767 | else | ||
768 | { | ||
769 | if(a->latitude<b->latitude) | ||
770 | return(-1); | ||
771 | else if(a->latitude>b->latitude) | ||
772 | return(1); | ||
773 | } | ||
774 | |||
775 | return(FILESORT_PRESERVE_ORDER(a,b)); | ||
776 | } | ||
777 | } | ||
778 | } | ||
779 | |||
780 | |||
781 | /*++++++++++++++++++++++++++++++++++++++ | ||
782 | amb | 1362 | Measure the extent of the data. |
783 | |||
784 | int measure_lat_long Return 1 if the value is to be kept, otherwise 0. | ||
785 | |||
786 | ErrorLogX *errorlogx The error location. | ||
787 | |||
788 | index_t index The number of sorted error locations that have already been written to the output file. | ||
789 | ++++++++++++++++++++++++++++++++++++++*/ | ||
790 | |||
791 | static int measure_lat_long(ErrorLogX *errorlogx,index_t index) | ||
792 | { | ||
793 | if(errorlogx->latitude!=NO_LATLONG) | ||
794 | { | ||
795 | if(errorlogx->latitude<lat_min) | ||
796 | lat_min=errorlogx->latitude; | ||
797 | if(errorlogx->latitude>lat_max) | ||
798 | lat_max=errorlogx->latitude; | ||
799 | if(errorlogx->longitude<lon_min) | ||
800 | lon_min=errorlogx->longitude; | ||
801 | if(errorlogx->longitude>lon_max) | ||
802 | lon_max=errorlogx->longitude; | ||
803 | } | ||
804 | |||
805 | return(1); | ||
806 | } | ||
807 | |||
808 | |||
809 | /*++++++++++++++++++++++++++++++++++++++ | ||
810 | amb | 1317 | Save the binary error log. |
811 | |||
812 | amb | 1362 | ErrorLogsX *errorlogsx The set of error logs to write. |
813 | amb | 1317 | |
814 | char *filename The name of the final file to write. | ||
815 | ++++++++++++++++++++++++++++++++++++++*/ | ||
816 | |||
817 | amb | 1362 | void SaveErrorLogs(ErrorLogsX *errorlogsx,char *filename) |
818 | amb | 1317 | { |
819 | ErrorLogsFile errorlogsfile; | ||
820 | ErrorLogX errorlogx; | ||
821 | int oldfd,newfd; | ||
822 | ll_bin2_t latlonbin=0,maxlatlonbins; | ||
823 | index_t *offsets; | ||
824 | index_t number=0,number_geo=0,number_nongeo=0; | ||
825 | off_t size; | ||
826 | |||
827 | /* Print the start message */ | ||
828 | |||
829 | printf_first("Writing Errors: Geographical=0 Non-geographical=0"); | ||
830 | |||
831 | /* Allocate the memory for the geographical offsets array */ | ||
832 | |||
833 | amb | 1362 | offsets=(index_t*)malloc((errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t)); |
834 | amb | 1317 | |
835 | logassert(offsets,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ | ||
836 | |||
837 | latlonbin=0; | ||
838 | |||
839 | /* Re-open the file */ | ||
840 | |||
841 | oldfd=ReOpenFile(errorbinfilename); | ||
842 | |||
843 | newfd=OpenFileNew(filename); | ||
844 | |||
845 | /* Write out the geographical errors */ | ||
846 | |||
847 | amb | 1362 | SeekFile(newfd,sizeof(ErrorLogsFile)+(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t)); |
848 | amb | 1317 | |
849 | while(!ReadFile(oldfd,&errorlogx,sizeof(ErrorLogX))) | ||
850 | { | ||
851 | ErrorLog errorlog={0}; | ||
852 | ll_bin_t latbin,lonbin; | ||
853 | ll_bin2_t llbin; | ||
854 | |||
855 | if(errorlogx.latitude==NO_LATLONG) | ||
856 | continue; | ||
857 | |||
858 | /* Create the ErrorLog */ | ||
859 | |||
860 | errorlog.latoffset=latlong_to_off(errorlogx.latitude); | ||
861 | errorlog.lonoffset=latlong_to_off(errorlogx.longitude); | ||
862 | |||
863 | errorlog.offset=errorlogx.offset; | ||
864 | errorlog.length=errorlogx.length; | ||
865 | |||
866 | /* Work out the offsets */ | ||
867 | |||
868 | amb | 1362 | latbin=latlong_to_bin(errorlogx.latitude )-errorlogsx->latzero; |
869 | lonbin=latlong_to_bin(errorlogx.longitude)-errorlogsx->lonzero; | ||
870 | llbin=lonbin*errorlogsx->latbins+latbin; | ||
871 | amb | 1317 | |
872 | for(;latlonbin<=llbin;latlonbin++) | ||
873 | offsets[latlonbin]=number_geo; | ||
874 | |||
875 | /* Write the data */ | ||
876 | |||
877 | WriteFile(newfd,&errorlog,sizeof(ErrorLog)); | ||
878 | |||
879 | number_geo++; | ||
880 | number++; | ||
881 | |||
882 | if(!(number%10000)) | ||
883 | printf_middle("Writing Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo); | ||
884 | } | ||
885 | |||
886 | /* Write out the non-geographical errors */ | ||
887 | |||
888 | SeekFile(oldfd,0); | ||
889 | |||
890 | while(!ReadFile(oldfd,&errorlogx,sizeof(ErrorLogX))) | ||
891 | { | ||
892 | ErrorLog errorlog={0}; | ||
893 | |||
894 | if(errorlogx.latitude!=NO_LATLONG) | ||
895 | continue; | ||
896 | |||
897 | /* Create the ErrorLog */ | ||
898 | |||
899 | errorlog.latoffset=0; | ||
900 | errorlog.lonoffset=0; | ||
901 | |||
902 | errorlog.offset=errorlogx.offset; | ||
903 | errorlog.length=errorlogx.length; | ||
904 | |||
905 | /* Write the data */ | ||
906 | |||
907 | WriteFile(newfd,&errorlog,sizeof(ErrorLog)); | ||
908 | |||
909 | number_nongeo++; | ||
910 | number++; | ||
911 | |||
912 | if(!(number%10000)) | ||
913 | printf_middle("Writing Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo); | ||
914 | } | ||
915 | |||
916 | /* Close the input file */ | ||
917 | |||
918 | CloseFile(oldfd); | ||
919 | |||
920 | DeleteFile(errorbinfilename); | ||
921 | |||
922 | /* Append the text from the log file */ | ||
923 | |||
924 | size=SizeFile(errorlogfilename); | ||
925 | |||
926 | oldfd=ReOpenFile(errorlogfilename); | ||
927 | |||
928 | while(size) | ||
929 | { | ||
930 | amb | 1321 | int i; |
931 | char buffer[4096]; | ||
932 | amb | 1317 | off_t chunksize=(size>sizeof(buffer)?sizeof(buffer):size); |
933 | |||
934 | ReadFile(oldfd,buffer,chunksize); | ||
935 | |||
936 | amb | 1321 | for(i=0;i<chunksize;i++) |
937 | if(buffer[i]=='\n') | ||
938 | buffer[i]=0; | ||
939 | |||
940 | amb | 1317 | WriteFile(newfd,buffer,chunksize); |
941 | |||
942 | size-=chunksize; | ||
943 | } | ||
944 | |||
945 | CloseFile(oldfd); | ||
946 | |||
947 | /* Finish off the offset indexing and write them out */ | ||
948 | |||
949 | amb | 1362 | maxlatlonbins=errorlogsx->latbins*errorlogsx->lonbins; |
950 | amb | 1317 | |
951 | for(;latlonbin<=maxlatlonbins;latlonbin++) | ||
952 | offsets[latlonbin]=number_geo; | ||
953 | |||
954 | SeekFile(newfd,sizeof(ErrorLogsFile)); | ||
955 | amb | 1362 | WriteFile(newfd,offsets,(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t)); |
956 | amb | 1317 | |
957 | free(offsets); | ||
958 | |||
959 | /* Write out the header structure */ | ||
960 | |||
961 | errorlogsfile.number =number; | ||
962 | errorlogsfile.number_geo =number_geo; | ||
963 | errorlogsfile.number_nongeo=number_nongeo; | ||
964 | |||
965 | amb | 1362 | errorlogsfile.latbins=errorlogsx->latbins; |
966 | errorlogsfile.lonbins=errorlogsx->lonbins; | ||
967 | amb | 1317 | |
968 | amb | 1362 | errorlogsfile.latzero=errorlogsx->latzero; |
969 | errorlogsfile.lonzero=errorlogsx->lonzero; | ||
970 | amb | 1317 | |
971 | SeekFile(newfd,0); | ||
972 | WriteFile(newfd,&errorlogsfile,sizeof(ErrorLogsFile)); | ||
973 | |||
974 | CloseFile(newfd); | ||
975 | |||
976 | /* Print the final message */ | ||
977 | |||
978 | printf_last("Wrote Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo); | ||
979 | } |