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