Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/nodesx.c
Parent Directory
|
Revision Log
Revision 275 -
(hide annotations)
(download)
(as text)
Wed Oct 7 18:03:48 2009 UTC (15 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 19675 byte(s)
Wed Oct 7 18:03:48 2009 UTC (15 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 19675 byte(s)
Go back to the version 1.1 method of having each segment listed twice. This simplifies the lookup of first/next segments at no in-RAM index cost and now that slim mode has sorting of file contents the balance has tipped back.
1 | amb | 110 | /*************************************** |
2 | amb | 275 | $Header: /home/amb/CVS/routino/src/nodesx.c,v 1.44 2009-10-07 18:03:48 amb Exp $ |
3 | amb | 110 | |
4 | Extented Node data type functions. | ||
5 | amb | 151 | |
6 | Part of the Routino routing software. | ||
7 | amb | 110 | ******************/ /****************** |
8 | amb | 151 | This file Copyright 2008,2009 Andrew M. Bishop |
9 | amb | 110 | |
10 | amb | 151 | 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 | amb | 110 | ***************************************/ |
23 | |||
24 | |||
25 | #include <assert.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <stdio.h> | ||
28 | amb | 249 | #include <string.h> |
29 | amb | 110 | |
30 | #include "types.h" | ||
31 | #include "functions.h" | ||
32 | #include "nodesx.h" | ||
33 | #include "segmentsx.h" | ||
34 | amb | 204 | #include "waysx.h" |
35 | amb | 228 | #include "segments.h" |
36 | #include "nodes.h" | ||
37 | amb | 110 | |
38 | |||
39 | amb | 271 | /* Constants */ |
40 | |||
41 | #define SORT_RAMSIZE (64*1024*1024) | ||
42 | |||
43 | amb | 252 | /* Variables */ |
44 | amb | 110 | |
45 | amb | 252 | extern int option_slim; |
46 | amb | 256 | extern char *tmpdirname; |
47 | amb | 110 | |
48 | /* Functions */ | ||
49 | |||
50 | amb | 271 | static int sort_by_id(NodeX *a,NodeX *b); |
51 | amb | 273 | static int index_by_id(NodeX *nodex,index_t index); |
52 | amb | 271 | |
53 | amb | 252 | static int sort_by_lat_long(node_t *a,node_t *b); |
54 | amb | 110 | |
55 | |||
56 | /*++++++++++++++++++++++++++++++++++++++ | ||
57 | Allocate a new node list. | ||
58 | |||
59 | NodesX *NewNodeList Returns the node list. | ||
60 | ++++++++++++++++++++++++++++++++++++++*/ | ||
61 | |||
62 | amb | 256 | NodesX *NewNodeList(void) |
63 | amb | 110 | { |
64 | NodesX *nodesx; | ||
65 | |||
66 | amb | 213 | nodesx=(NodesX*)calloc(1,sizeof(NodesX)); |
67 | amb | 110 | |
68 | amb | 243 | assert(nodesx); /* Check calloc() worked */ |
69 | |||
70 | amb | 256 | nodesx->filename=(char*)malloc(strlen(tmpdirname)+24); |
71 | sprintf(nodesx->filename,"%s/nodes.%p.tmp",tmpdirname,nodesx); | ||
72 | amb | 216 | |
73 | amb | 252 | nodesx->fd=OpenFile(nodesx->filename); |
74 | amb | 249 | |
75 | amb | 110 | return(nodesx); |
76 | } | ||
77 | |||
78 | |||
79 | /*++++++++++++++++++++++++++++++++++++++ | ||
80 | amb | 226 | Free a node list. |
81 | |||
82 | NodesX *nodesx The list to be freed. | ||
83 | ++++++++++++++++++++++++++++++++++++++*/ | ||
84 | |||
85 | void FreeNodeList(NodesX *nodesx) | ||
86 | { | ||
87 | amb | 252 | DeleteFile(nodesx->filename); |
88 | amb | 226 | |
89 | amb | 252 | if(nodesx->xdata) |
90 | amb | 257 | UnmapFile(nodesx->filename); |
91 | amb | 252 | |
92 | amb | 226 | if(nodesx->gdata) |
93 | free(nodesx->gdata); | ||
94 | if(nodesx->idata) | ||
95 | free(nodesx->idata); | ||
96 | |||
97 | if(nodesx->ndata) | ||
98 | free(nodesx->ndata); | ||
99 | |||
100 | amb | 257 | if(nodesx->offsets) |
101 | free(nodesx->offsets); | ||
102 | |||
103 | amb | 226 | free(nodesx); |
104 | } | ||
105 | |||
106 | |||
107 | /*++++++++++++++++++++++++++++++++++++++ | ||
108 | amb | 110 | Save the node list to a file. |
109 | |||
110 | NodesX* nodesx The set of nodes to save. | ||
111 | |||
112 | const char *filename The name of the file to save. | ||
113 | ++++++++++++++++++++++++++++++++++++++*/ | ||
114 | |||
115 | void SaveNodeList(NodesX* nodesx,const char *filename) | ||
116 | { | ||
117 | amb | 214 | index_t i; |
118 | amb | 110 | int fd; |
119 | amb | 243 | Nodes *nodes; |
120 | amb | 232 | int super_number=0; |
121 | amb | 110 | |
122 | amb | 243 | assert(nodesx->gdata); /* Must have gdata filled in => sorted geographically */ |
123 | assert(nodesx->ndata); /* Must have ndata filled in => real nodes exist */ | ||
124 | amb | 110 | |
125 | amb | 227 | printf("Writing Nodes: Nodes=0"); |
126 | fflush(stdout); | ||
127 | |||
128 | amb | 219 | for(i=0;i<nodesx->number;i++) |
129 | amb | 232 | if(nodesx->ndata[i].firstseg&NODE_SUPER) |
130 | super_number++; | ||
131 | amb | 219 | |
132 | amb | 110 | /* Fill in a Nodes structure with the offset of the real data in the file after |
133 | the Node structure itself. */ | ||
134 | |||
135 | amb | 243 | nodes=calloc(1,sizeof(Nodes)); |
136 | |||
137 | assert(nodes); /* Check calloc() worked */ | ||
138 | |||
139 | amb | 110 | nodes->number=nodesx->number; |
140 | amb | 232 | nodes->snumber=super_number; |
141 | amb | 110 | |
142 | amb | 257 | nodes->latbins=nodesx->latbins; |
143 | nodes->lonbins=nodesx->lonbins; | ||
144 | amb | 110 | |
145 | amb | 257 | nodes->latzero=nodesx->latzero; |
146 | nodes->lonzero=nodesx->lonzero; | ||
147 | amb | 110 | |
148 | nodes->data=NULL; | ||
149 | amb | 232 | |
150 | amb | 110 | nodes->offsets=(void*)sizeof(Nodes); |
151 | amb | 257 | nodes->nodes=(void*)(sizeof(Nodes)+(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t)); |
152 | amb | 110 | |
153 | /* Write out the Nodes structure and then the real data. */ | ||
154 | |||
155 | fd=OpenFile(filename); | ||
156 | |||
157 | WriteFile(fd,nodes,sizeof(Nodes)); | ||
158 | |||
159 | amb | 257 | WriteFile(fd,nodesx->offsets,(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t)); |
160 | amb | 110 | |
161 | amb | 203 | for(i=0;i<nodes->number;i++) |
162 | amb | 132 | { |
163 | amb | 257 | Node *node=&nodesx->ndata[nodesx->gdata[i]]; |
164 | amb | 110 | |
165 | amb | 212 | WriteFile(fd,node,sizeof(Node)); |
166 | |||
167 | amb | 132 | if(!((i+1)%10000)) |
168 | { | ||
169 | printf("\rWriting Nodes: Nodes=%d",i+1); | ||
170 | fflush(stdout); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | amb | 203 | printf("\rWrote Nodes: Nodes=%d \n",nodes->number); |
175 | amb | 132 | fflush(stdout); |
176 | |||
177 | amb | 110 | CloseFile(fd); |
178 | |||
179 | /* Free the fake Nodes */ | ||
180 | |||
181 | free(nodes); | ||
182 | } | ||
183 | |||
184 | |||
185 | /*++++++++++++++++++++++++++++++++++++++ | ||
186 | amb | 252 | Find a particular node index. |
187 | amb | 110 | |
188 | amb | 249 | index_t IndexNodeX Returns the index of the extended node with the specified id. |
189 | amb | 110 | |
190 | NodesX* nodesx The set of nodes to process. | ||
191 | |||
192 | node_t id The node id to look for. | ||
193 | ++++++++++++++++++++++++++++++++++++++*/ | ||
194 | |||
195 | amb | 249 | index_t IndexNodeX(NodesX* nodesx,node_t id) |
196 | amb | 110 | { |
197 | int start=0; | ||
198 | int end=nodesx->number-1; | ||
199 | int mid; | ||
200 | |||
201 | amb | 243 | assert(nodesx->idata); /* Must have idata filled in => sorted by id */ |
202 | amb | 110 | |
203 | /* Binary search - search key exact match only is required. | ||
204 | * | ||
205 | * # <- start | Check mid and move start or end if it doesn't match | ||
206 | * # | | ||
207 | * # | Since an exact match is wanted we can set end=mid-1 | ||
208 | * # <- mid | or start=mid+1 because we know that mid doesn't match. | ||
209 | * # | | ||
210 | * # | Eventually either end=start or end=start+1 and one of | ||
211 | * # <- end | start or end is the wanted one. | ||
212 | */ | ||
213 | |||
214 | amb | 252 | if(end<start) /* There are no nodes */ |
215 | amb | 249 | return(NO_NODE); |
216 | amb | 252 | else if(id<nodesx->idata[start]) /* Check key is not before start */ |
217 | amb | 249 | return(NO_NODE); |
218 | amb | 252 | else if(id>nodesx->idata[end]) /* Check key is not after end */ |
219 | amb | 249 | return(NO_NODE); |
220 | amb | 110 | else |
221 | { | ||
222 | do | ||
223 | { | ||
224 | amb | 252 | mid=(start+end)/2; /* Choose mid point */ |
225 | amb | 110 | |
226 | amb | 252 | if(nodesx->idata[mid]<id) /* Mid point is too low */ |
227 | amb | 110 | start=mid+1; |
228 | amb | 252 | else if(nodesx->idata[mid]>id) /* Mid point is too high */ |
229 | amb | 110 | end=mid-1; |
230 | amb | 252 | else /* Mid point is correct */ |
231 | amb | 249 | return(mid); |
232 | amb | 110 | } |
233 | while((end-start)>1); | ||
234 | |||
235 | amb | 252 | if(nodesx->idata[start]==id) /* Start is correct */ |
236 | amb | 249 | return(start); |
237 | amb | 110 | |
238 | amb | 252 | if(nodesx->idata[end]==id) /* End is correct */ |
239 | amb | 249 | return(end); |
240 | amb | 110 | } |
241 | |||
242 | amb | 249 | return(NO_NODE); |
243 | amb | 110 | } |
244 | |||
245 | |||
246 | /*++++++++++++++++++++++++++++++++++++++ | ||
247 | amb | 275 | Lookup a particular node. |
248 | |||
249 | NodeX *LookupNodeX Returns a pointer to the extended node with the specified id. | ||
250 | |||
251 | NodesX* nodesx The set of nodes to process. | ||
252 | |||
253 | index_t index The node index to look for. | ||
254 | |||
255 | int position The position in the cache to use. | ||
256 | ++++++++++++++++++++++++++++++++++++++*/ | ||
257 | |||
258 | NodeX *LookupNodeX(NodesX* nodesx,index_t index,int position) | ||
259 | { | ||
260 | assert(index!=NO_NODE); /* Must be a valid node */ | ||
261 | |||
262 | if(option_slim) | ||
263 | { | ||
264 | SeekFile(nodesx->fd,index*sizeof(NodeX)); | ||
265 | |||
266 | ReadFile(nodesx->fd,&nodesx->cached[position-1],sizeof(NodeX)); | ||
267 | |||
268 | return(&nodesx->cached[position-1]); | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | return(&nodesx->xdata[index]); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | |||
277 | /*++++++++++++++++++++++++++++++++++++++ | ||
278 | amb | 252 | Append a node to a newly created node list (unsorted). |
279 | amb | 243 | |
280 | amb | 252 | NodesX* nodesx The set of nodes to process. |
281 | amb | 243 | |
282 | amb | 252 | node_t id The node identification. |
283 | amb | 110 | |
284 | amb | 252 | double latitude The latitude of the node. |
285 | amb | 110 | |
286 | amb | 252 | double longitude The longitude of the node. |
287 | ++++++++++++++++++++++++++++++++++++++*/ | ||
288 | amb | 110 | |
289 | amb | 252 | void AppendNode(NodesX* nodesx,node_t id,double latitude,double longitude) |
290 | { | ||
291 | NodeX nodex; | ||
292 | amb | 249 | |
293 | amb | 252 | assert(!nodesx->idata); /* Must not have idata filled in => unsorted */ |
294 | |||
295 | nodex.id=id; | ||
296 | nodex.latitude =radians_to_latlong(latitude); | ||
297 | nodex.longitude=radians_to_latlong(longitude); | ||
298 | |||
299 | WriteFile(nodesx->fd,&nodex,sizeof(NodeX)); | ||
300 | |||
301 | nodesx->xnumber++; | ||
302 | amb | 110 | } |
303 | |||
304 | |||
305 | amb | 271 | /*+ A temporary file-local variable for use by the sort functions. +*/ |
306 | static NodesX *sortnodesx; | ||
307 | |||
308 | |||
309 | amb | 110 | /*++++++++++++++++++++++++++++++++++++++ |
310 | amb | 263 | Sort the node list (i.e. create the sortable indexes). |
311 | amb | 110 | |
312 | NodesX* nodesx The set of nodes to process. | ||
313 | ++++++++++++++++++++++++++++++++++++++*/ | ||
314 | |||
315 | amb | 263 | void SortNodeList(NodesX* nodesx) |
316 | amb | 110 | { |
317 | amb | 263 | int fd; |
318 | amb | 110 | |
319 | amb | 263 | /* Check the start conditions */ |
320 | |||
321 | amb | 252 | assert(!nodesx->idata); /* Must not have idata filled in => unsorted */ |
322 | |||
323 | amb | 263 | /* Print the start message */ |
324 | |||
325 | printf("Sorting Nodes"); | ||
326 | amb | 227 | fflush(stdout); |
327 | amb | 132 | |
328 | amb | 263 | /* Close the files and re-open them (finished appending) */ |
329 | amb | 260 | |
330 | CloseFile(nodesx->fd); | ||
331 | nodesx->fd=ReOpenFile(nodesx->filename); | ||
332 | |||
333 | amb | 271 | DeleteFile(nodesx->filename); |
334 | |||
335 | fd=OpenFile(nodesx->filename); | ||
336 | |||
337 | amb | 252 | /* Allocate the array of indexes */ |
338 | amb | 249 | |
339 | amb | 252 | nodesx->idata=(node_t*)malloc(nodesx->xnumber*sizeof(node_t)); |
340 | amb | 249 | |
341 | amb | 252 | assert(nodesx->idata); /* Check malloc() worked */ |
342 | amb | 249 | |
343 | amb | 271 | /* Sort by node indexes */ |
344 | amb | 249 | |
345 | amb | 271 | sortnodesx=nodesx; |
346 | amb | 110 | |
347 | amb | 273 | filesort(nodesx->fd,fd,sizeof(NodeX),SORT_RAMSIZE,(int (*)(const void*,const void*))sort_by_id,(int (*)(void*,index_t))index_by_id); |
348 | amb | 252 | |
349 | amb | 260 | /* Close the files and re-open them */ |
350 | |||
351 | amb | 257 | CloseFile(nodesx->fd); |
352 | CloseFile(fd); | ||
353 | amb | 252 | |
354 | amb | 257 | nodesx->fd=ReOpenFile(nodesx->filename); |
355 | amb | 252 | |
356 | amb | 263 | /* Print the final message */ |
357 | |||
358 | amb | 273 | printf("\rSorted Nodes: Nodes=%d Duplicates=%d\n",nodesx->xnumber,nodesx->xnumber-nodesx->number); |
359 | amb | 263 | fflush(stdout); |
360 | amb | 110 | } |
361 | |||
362 | |||
363 | /*++++++++++++++++++++++++++++++++++++++ | ||
364 | Sort the nodes into id order. | ||
365 | |||
366 | int sort_by_id Returns the comparison of the id fields. | ||
367 | |||
368 | amb | 271 | NodeX *a The first extended node. |
369 | amb | 110 | |
370 | amb | 271 | NodeX *b The second extended node. |
371 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
372 | |||
373 | amb | 271 | static int sort_by_id(NodeX *a,NodeX *b) |
374 | amb | 110 | { |
375 | amb | 271 | node_t a_id=a->id; |
376 | node_t b_id=b->id; | ||
377 | amb | 252 | |
378 | if(a_id<b_id) | ||
379 | return(-1); | ||
380 | else if(a_id>b_id) | ||
381 | amb | 249 | return(1); |
382 | amb | 110 | else |
383 | amb | 252 | return(0); |
384 | amb | 110 | } |
385 | |||
386 | |||
387 | amb | 271 | /*++++++++++++++++++++++++++++++++++++++ |
388 | Index the nodes after sorting. | ||
389 | amb | 252 | |
390 | amb | 273 | index_by_id Return 1 if the value is to be kept, otherwise zero. |
391 | |||
392 | amb | 271 | NodeX *nodex The extended node. |
393 | amb | 252 | |
394 | amb | 271 | index_t index The index of this node in the total. |
395 | ++++++++++++++++++++++++++++++++++++++*/ | ||
396 | |||
397 | amb | 273 | static int index_by_id(NodeX *nodex,index_t index) |
398 | amb | 271 | { |
399 | amb | 273 | if(index==0 || sortnodesx->idata[index-1]!=nodex->id) |
400 | { | ||
401 | sortnodesx->idata[index]=nodex->id; | ||
402 | amb | 271 | |
403 | amb | 273 | sortnodesx->number++; |
404 | |||
405 | return(1); | ||
406 | } | ||
407 | |||
408 | return(0); | ||
409 | amb | 271 | } |
410 | |||
411 | |||
412 | amb | 110 | /*++++++++++++++++++++++++++++++++++++++ |
413 | amb | 212 | Sort the node list geographically. |
414 | |||
415 | NodesX* nodesx The set of nodes to process. | ||
416 | ++++++++++++++++++++++++++++++++++++++*/ | ||
417 | |||
418 | void SortNodeListGeographically(NodesX* nodesx) | ||
419 | { | ||
420 | amb | 214 | index_t i; |
421 | amb | 257 | ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin; |
422 | latlong_t lat_min,lat_max,lon_min,lon_max; | ||
423 | uint32_t latlonbin; | ||
424 | amb | 212 | |
425 | amb | 263 | /* Check the start conditions */ |
426 | |||
427 | amb | 243 | assert(nodesx->idata); /* Must have idata filled in => sorted by id */ |
428 | assert(!nodesx->gdata); /* Must not have gdata filled in => unsorted geographically */ | ||
429 | amb | 212 | |
430 | amb | 263 | /* Print the start message */ |
431 | |||
432 | amb | 227 | printf("Sorting Nodes Geographically"); |
433 | fflush(stdout); | ||
434 | amb | 212 | |
435 | amb | 275 | /* Map into memory */ |
436 | |||
437 | // FIXME | ||
438 | nodesx->xdata=MapFile(nodesx->filename); | ||
439 | |||
440 | amb | 213 | /* Allocate the array of pointers and sort them */ |
441 | amb | 212 | |
442 | amb | 257 | nodesx->gdata=(index_t*)malloc(nodesx->number*sizeof(index_t)); |
443 | amb | 212 | |
444 | amb | 243 | assert(nodesx->gdata); /* Check malloc() worked */ |
445 | |||
446 | amb | 212 | for(i=0;i<nodesx->number;i++) |
447 | amb | 257 | nodesx->gdata[i]=i; |
448 | amb | 212 | |
449 | amb | 252 | sortnodesx=nodesx; |
450 | amb | 212 | |
451 | amb | 257 | qsort(nodesx->gdata,nodesx->number,sizeof(index_t),(int (*)(const void*,const void*))sort_by_lat_long); |
452 | amb | 252 | |
453 | amb | 257 | /* Work out the range of data */ |
454 | |||
455 | lat_min=radians_to_latlong( 2); | ||
456 | lat_max=radians_to_latlong(-2); | ||
457 | lon_min=radians_to_latlong( 4); | ||
458 | lon_max=radians_to_latlong(-4); | ||
459 | |||
460 | for(i=0;i<nodesx->number;i++) | ||
461 | { | ||
462 | NodeX *nodex=&nodesx->xdata[i]; | ||
463 | |||
464 | if(nodex->latitude<lat_min) | ||
465 | lat_min=nodex->latitude; | ||
466 | if(nodex->latitude>lat_max) | ||
467 | lat_max=nodex->latitude; | ||
468 | if(nodex->longitude<lon_min) | ||
469 | lon_min=nodex->longitude; | ||
470 | if(nodex->longitude>lon_max) | ||
471 | lon_max=nodex->longitude; | ||
472 | } | ||
473 | |||
474 | amb | 263 | /* Work out the number of bins */ |
475 | amb | 257 | |
476 | lat_min_bin=latlong_to_bin(lat_min); | ||
477 | lon_min_bin=latlong_to_bin(lon_min); | ||
478 | lat_max_bin=latlong_to_bin(lat_max); | ||
479 | lon_max_bin=latlong_to_bin(lon_max); | ||
480 | |||
481 | nodesx->latbins=(lat_max_bin-lat_min_bin)+1; | ||
482 | nodesx->lonbins=(lon_max_bin-lon_min_bin)+1; | ||
483 | |||
484 | amb | 263 | /* Work out the offsets */ |
485 | |||
486 | amb | 257 | nodesx->offsets=(index_t*)malloc((nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t)); |
487 | |||
488 | latlonbin=0; | ||
489 | |||
490 | for(i=0;i<nodesx->number;i++) | ||
491 | { | ||
492 | NodeX *nodex=&nodesx->xdata[nodesx->gdata[i]]; | ||
493 | |||
494 | ll_bin_t latbin=latlong_to_bin(nodex->latitude )-lat_min_bin; | ||
495 | ll_bin_t lonbin=latlong_to_bin(nodex->longitude)-lon_min_bin; | ||
496 | int llbin=lonbin*nodesx->latbins+latbin; | ||
497 | |||
498 | for(;latlonbin<=llbin;latlonbin++) | ||
499 | nodesx->offsets[latlonbin]=i; | ||
500 | } | ||
501 | |||
502 | for(;latlonbin<=(nodesx->latbins*nodesx->lonbins);latlonbin++) | ||
503 | nodesx->offsets[latlonbin]=nodesx->number; | ||
504 | |||
505 | nodesx->latzero=lat_min_bin; | ||
506 | nodesx->lonzero=lon_min_bin; | ||
507 | |||
508 | amb | 275 | // FIXME |
509 | nodesx->xdata=UnmapFile(nodesx->filename); | ||
510 | |||
511 | amb | 263 | /* Print the final message */ |
512 | amb | 257 | |
513 | amb | 227 | printf("\rSorted Nodes Geographically \n"); |
514 | fflush(stdout); | ||
515 | amb | 212 | } |
516 | |||
517 | |||
518 | /*++++++++++++++++++++++++++++++++++++++ | ||
519 | amb | 110 | Sort the nodes into latitude and longitude order. |
520 | |||
521 | int sort_by_lat_long Returns the comparison of the latitude and longitude fields. | ||
522 | |||
523 | amb | 257 | index_t *a The first node id. |
524 | amb | 110 | |
525 | amb | 257 | index_t *b The second node id. |
526 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
527 | |||
528 | amb | 257 | static int sort_by_lat_long(index_t *a,index_t *b) |
529 | amb | 110 | { |
530 | amb | 257 | NodeX *nodex_a=&sortnodesx->xdata[*a]; |
531 | NodeX *nodex_b=&sortnodesx->xdata[*b]; | ||
532 | amb | 110 | |
533 | amb | 252 | ll_bin_t a_lon=latlong_to_bin(nodex_a->longitude); |
534 | ll_bin_t b_lon=latlong_to_bin(nodex_b->longitude); | ||
535 | |||
536 | amb | 110 | if(a_lon<b_lon) |
537 | return(-1); | ||
538 | else if(a_lon>b_lon) | ||
539 | return(1); | ||
540 | else | ||
541 | { | ||
542 | amb | 252 | ll_bin_t a_lat=latlong_to_bin(nodex_a->latitude); |
543 | ll_bin_t b_lat=latlong_to_bin(nodex_b->latitude); | ||
544 | amb | 110 | |
545 | if(a_lat<b_lat) | ||
546 | return(-1); | ||
547 | else if(a_lat>b_lat) | ||
548 | return(1); | ||
549 | else | ||
550 | return(0); | ||
551 | } | ||
552 | } | ||
553 | |||
554 | |||
555 | /*++++++++++++++++++++++++++++++++++++++ | ||
556 | Remove any nodes that are not part of a highway. | ||
557 | |||
558 | NodesX *nodesx The complete node list. | ||
559 | |||
560 | SegmentsX *segmentsx The list of segments. | ||
561 | ++++++++++++++++++++++++++++++++++++++*/ | ||
562 | |||
563 | void RemoveNonHighwayNodes(NodesX *nodesx,SegmentsX *segmentsx) | ||
564 | { | ||
565 | amb | 263 | NodeX nodex; |
566 | amb | 273 | int total=0,highway=0,nothighway=0; |
567 | amb | 263 | int fd; |
568 | amb | 275 | node_t *idata; |
569 | amb | 110 | |
570 | amb | 263 | /* Check the start conditions */ |
571 | |||
572 | amb | 249 | assert(nodesx->idata); /* Must have idata filled in => data sorted */ |
573 | amb | 213 | |
574 | amb | 263 | /* Print the start message */ |
575 | |||
576 | amb | 227 | printf("Checking: Nodes=0"); |
577 | fflush(stdout); | ||
578 | |||
579 | amb | 263 | /* Modify the on-disk image */ |
580 | |||
581 | DeleteFile(nodesx->filename); | ||
582 | |||
583 | fd=OpenFile(nodesx->filename); | ||
584 | SeekFile(nodesx->fd,0); | ||
585 | |||
586 | while(!ReadFile(nodesx->fd,&nodex,sizeof(NodeX))) | ||
587 | amb | 110 | { |
588 | amb | 275 | if(IndexFirstSegmentX(segmentsx,nodex.id)==NO_SEGMENT) |
589 | amb | 271 | nothighway++; |
590 | else | ||
591 | amb | 263 | { |
592 | WriteFile(fd,&nodex,sizeof(NodeX)); | ||
593 | |||
594 | nodesx->idata[highway]=nodesx->idata[total]; | ||
595 | amb | 110 | highway++; |
596 | amb | 263 | } |
597 | amb | 110 | |
598 | amb | 263 | total++; |
599 | |||
600 | if(!(total%10000)) | ||
601 | amb | 110 | { |
602 | amb | 273 | printf("\rChecking: Nodes=%d Highway=%d not-Highway=%d",total,highway,nothighway); |
603 | amb | 110 | fflush(stdout); |
604 | } | ||
605 | } | ||
606 | |||
607 | amb | 263 | /* Close the files and re-open them */ |
608 | |||
609 | CloseFile(nodesx->fd); | ||
610 | CloseFile(fd); | ||
611 | |||
612 | nodesx->fd=ReOpenFile(nodesx->filename); | ||
613 | |||
614 | /* Allocate a smaller array for the node index (don't trust realloc to make it smaller) */ | ||
615 | |||
616 | idata=(node_t*)malloc(highway*sizeof(node_t)); | ||
617 | |||
618 | assert(idata); /* Check malloc() worked */ | ||
619 | |||
620 | memcpy(idata,nodesx->idata,highway*sizeof(node_t)); | ||
621 | |||
622 | free(nodesx->idata); | ||
623 | |||
624 | nodesx->idata=idata; | ||
625 | nodesx->number=highway; | ||
626 | |||
627 | /* Allocate and clear the super-node markers */ | ||
628 | |||
629 | nodesx->super=(uint8_t*)calloc(nodesx->number,sizeof(uint8_t)); | ||
630 | |||
631 | assert(nodesx->super); /* Check calloc() worked */ | ||
632 | |||
633 | /* Print the final message */ | ||
634 | |||
635 | amb | 273 | printf("\rChecked: Nodes=%d Highway=%d not-Highway=%d \n",total,highway,nothighway); |
636 | amb | 110 | fflush(stdout); |
637 | } | ||
638 | |||
639 | |||
640 | /*++++++++++++++++++++++++++++++++++++++ | ||
641 | amb | 212 | Create the real node data. |
642 | amb | 110 | |
643 | amb | 212 | NodesX *nodesx The set of nodes to use. |
644 | amb | 110 | |
645 | amb | 212 | int iteration The final super-node iteration. |
646 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
647 | |||
648 | amb | 212 | void CreateRealNodes(NodesX *nodesx,int iteration) |
649 | amb | 110 | { |
650 | amb | 214 | index_t i; |
651 | amb | 110 | |
652 | amb | 275 | /* Check the start conditions */ |
653 | |||
654 | amb | 243 | assert(nodesx->idata); /* Must have idata filled in => sorted by id */ |
655 | assert(!nodesx->ndata); /* Must not have ndata filled in => no real nodes */ | ||
656 | amb | 110 | |
657 | amb | 275 | /* Print the start message */ |
658 | |||
659 | amb | 227 | printf("Creating Real Nodes: Nodes=0"); |
660 | fflush(stdout); | ||
661 | |||
662 | amb | 275 | /* Map into memory */ |
663 | |||
664 | if(!option_slim) | ||
665 | nodesx->xdata=MapFile(nodesx->filename); | ||
666 | |||
667 | amb | 212 | /* Allocate the memory */ |
668 | |||
669 | nodesx->ndata=(Node*)malloc(nodesx->number*sizeof(Node)); | ||
670 | |||
671 | amb | 243 | assert(nodesx->ndata); /* Check malloc() worked */ |
672 | |||
673 | amb | 212 | /* Loop through and allocate. */ |
674 | |||
675 | amb | 110 | for(i=0;i<nodesx->number;i++) |
676 | { | ||
677 | amb | 275 | NodeX *nodex=LookupNodeX(nodesx,i,1); |
678 | amb | 208 | |
679 | amb | 275 | nodesx->ndata[i].latoffset=latlong_to_off(nodex->latitude); |
680 | nodesx->ndata[i].lonoffset=latlong_to_off(nodex->longitude); | ||
681 | amb | 212 | nodesx->ndata[i].firstseg=SEGMENT(NO_SEGMENT); |
682 | |||
683 | amb | 249 | if(nodesx->super[i]==iteration) |
684 | amb | 212 | nodesx->ndata[i].firstseg|=NODE_SUPER; |
685 | |||
686 | amb | 110 | if(!((i+1)%10000)) |
687 | { | ||
688 | amb | 212 | printf("\rCreating Real Nodes: Nodes=%d",i+1); |
689 | amb | 110 | fflush(stdout); |
690 | } | ||
691 | } | ||
692 | |||
693 | amb | 275 | /* Unmap from memory */ |
694 | |||
695 | if(!option_slim) | ||
696 | nodesx->xdata=UnmapFile(nodesx->filename); | ||
697 | |||
698 | /* Print the final message */ | ||
699 | |||
700 | amb | 212 | printf("\rCreating Real Nodes: Nodes=%d \n",nodesx->number); |
701 | amb | 110 | fflush(stdout); |
702 | } | ||
703 | |||
704 | |||
705 | /*++++++++++++++++++++++++++++++++++++++ | ||
706 | Assign the segment indexes to the nodes. | ||
707 | |||
708 | NodesX *nodesx The list of nodes to process. | ||
709 | |||
710 | SegmentsX* segmentsx The set of segments to use. | ||
711 | ++++++++++++++++++++++++++++++++++++++*/ | ||
712 | |||
713 | amb | 209 | void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx) |
714 | amb | 110 | { |
715 | amb | 214 | index_t i; |
716 | amb | 110 | |
717 | amb | 275 | /* Check the start conditions */ |
718 | |||
719 | amb | 243 | assert(nodesx->idata); /* Must have idata filled in => sorted */ |
720 | assert(nodesx->ndata); /* Must have ndata filled in => real nodes exist */ | ||
721 | assert(segmentsx->sdata); /* Must have sdata filled in => real segments exist */ | ||
722 | amb | 110 | |
723 | amb | 275 | /* Print the start message */ |
724 | |||
725 | amb | 227 | printf("Indexing Segments: Segments=0"); |
726 | fflush(stdout); | ||
727 | |||
728 | amb | 275 | /* Map into memory */ |
729 | |||
730 | if(!option_slim) | ||
731 | segmentsx->xdata=MapFile(segmentsx->filename); | ||
732 | |||
733 | amb | 110 | /* Index the nodes */ |
734 | |||
735 | for(i=0;i<segmentsx->number;i++) | ||
736 | { | ||
737 | amb | 275 | SegmentX *segmentx=LookupSegmentX(segmentsx,i,1); |
738 | amb | 257 | node_t id1=segmentx->node1; |
739 | node_t id2=segmentx->node2; | ||
740 | Node *node1=&nodesx->ndata[IndexNodeX(nodesx,id1)]; | ||
741 | Node *node2=&nodesx->ndata[IndexNodeX(nodesx,id2)]; | ||
742 | amb | 110 | |
743 | /* Check node1 */ | ||
744 | |||
745 | amb | 212 | if(SEGMENT(node1->firstseg)==SEGMENT(NO_SEGMENT)) |
746 | amb | 110 | { |
747 | amb | 212 | node1->firstseg^=SEGMENT(NO_SEGMENT); |
748 | node1->firstseg|=i; | ||
749 | amb | 110 | } |
750 | else | ||
751 | { | ||
752 | amb | 212 | index_t index=SEGMENT(node1->firstseg); |
753 | amb | 110 | |
754 | do | ||
755 | { | ||
756 | amb | 275 | segmentx=LookupSegmentX(segmentsx,index,1); |
757 | amb | 256 | |
758 | amb | 257 | if(segmentx->node1==id1) |
759 | amb | 110 | { |
760 | amb | 209 | index++; |
761 | amb | 128 | |
762 | amb | 256 | if(index>=segmentsx->number) |
763 | amb | 209 | break; |
764 | amb | 256 | |
765 | amb | 275 | segmentx=LookupSegmentX(segmentsx,index,1); |
766 | amb | 256 | |
767 | amb | 257 | if(segmentx->node1!=id1) |
768 | amb | 256 | break; |
769 | amb | 110 | } |
770 | else | ||
771 | { | ||
772 | amb | 209 | if(segmentsx->sdata[index].next2==NO_NODE) |
773 | amb | 110 | { |
774 | amb | 209 | segmentsx->sdata[index].next2=i; |
775 | break; | ||
776 | amb | 110 | } |
777 | else | ||
778 | amb | 209 | index=segmentsx->sdata[index].next2; |
779 | amb | 110 | } |
780 | } | ||
781 | amb | 209 | while(1); |
782 | amb | 110 | } |
783 | |||
784 | /* Check node2 */ | ||
785 | |||
786 | amb | 212 | if(SEGMENT(node2->firstseg)==SEGMENT(NO_SEGMENT)) |
787 | amb | 110 | { |
788 | amb | 212 | node2->firstseg^=SEGMENT(NO_SEGMENT); |
789 | node2->firstseg|=i; | ||
790 | amb | 110 | } |
791 | else | ||
792 | { | ||
793 | amb | 212 | index_t index=SEGMENT(node2->firstseg); |
794 | amb | 110 | |
795 | do | ||
796 | { | ||
797 | amb | 275 | segmentx=LookupSegmentX(segmentsx,index,1); |
798 | amb | 256 | |
799 | amb | 257 | if(segmentx->node1==id2) |
800 | amb | 110 | { |
801 | amb | 209 | index++; |
802 | amb | 128 | |
803 | amb | 256 | if(index>=segmentsx->number) |
804 | amb | 209 | break; |
805 | amb | 256 | |
806 | amb | 275 | segmentx=LookupSegmentX(segmentsx,index,1); |
807 | amb | 256 | |
808 | amb | 257 | if(segmentx->node1!=id2) |
809 | amb | 256 | break; |
810 | amb | 110 | } |
811 | else | ||
812 | { | ||
813 | amb | 209 | if(segmentsx->sdata[index].next2==NO_NODE) |
814 | amb | 110 | { |
815 | amb | 209 | segmentsx->sdata[index].next2=i; |
816 | break; | ||
817 | amb | 110 | } |
818 | else | ||
819 | amb | 209 | index=segmentsx->sdata[index].next2; |
820 | amb | 110 | } |
821 | } | ||
822 | amb | 209 | while(1); |
823 | amb | 110 | } |
824 | |||
825 | if(!((i+1)%10000)) | ||
826 | { | ||
827 | printf("\rIndexing Segments: Segments=%d",i+1); | ||
828 | fflush(stdout); | ||
829 | } | ||
830 | } | ||
831 | |||
832 | amb | 275 | /* Unmap from memory */ |
833 | |||
834 | if(!option_slim) | ||
835 | segmentsx->xdata=UnmapFile(segmentsx->filename); | ||
836 | |||
837 | /* Print the final message */ | ||
838 | |||
839 | amb | 110 | printf("\rIndexed Segments: Segments=%d \n",segmentsx->number); |
840 | fflush(stdout); | ||
841 | } |
Properties
Name | Value |
---|---|
cvs:description | Extended nodes functions. |