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 279 -
(hide annotations)
(download)
(as text)
Thu Oct 8 19:20:29 2009 UTC (15 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 19397 byte(s)
Thu Oct 8 19:20:29 2009 UTC (15 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 19397 byte(s)
Replace node, segment and way indexes with a single index for a set of segments containing the location of the first segment for each node.
1 | amb | 110 | /*************************************** |
2 | amb | 279 | $Header: /home/amb/CVS/routino/src/nodesx.c,v 1.45 2009-10-08 19:20:29 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 | amb | 279 | |
95 | amb | 226 | if(nodesx->idata) |
96 | free(nodesx->idata); | ||
97 | |||
98 | if(nodesx->ndata) | ||
99 | free(nodesx->ndata); | ||
100 | |||
101 | amb | 257 | if(nodesx->offsets) |
102 | free(nodesx->offsets); | ||
103 | |||
104 | amb | 226 | free(nodesx); |
105 | } | ||
106 | |||
107 | |||
108 | /*++++++++++++++++++++++++++++++++++++++ | ||
109 | amb | 110 | Save the node list to a file. |
110 | |||
111 | NodesX* nodesx The set of nodes to save. | ||
112 | |||
113 | const char *filename The name of the file to save. | ||
114 | ++++++++++++++++++++++++++++++++++++++*/ | ||
115 | |||
116 | void SaveNodeList(NodesX* nodesx,const char *filename) | ||
117 | { | ||
118 | amb | 214 | index_t i; |
119 | amb | 110 | int fd; |
120 | amb | 243 | Nodes *nodes; |
121 | amb | 232 | int super_number=0; |
122 | amb | 110 | |
123 | amb | 243 | assert(nodesx->gdata); /* Must have gdata filled in => sorted geographically */ |
124 | assert(nodesx->ndata); /* Must have ndata filled in => real nodes exist */ | ||
125 | amb | 110 | |
126 | amb | 227 | printf("Writing Nodes: Nodes=0"); |
127 | fflush(stdout); | ||
128 | |||
129 | amb | 219 | for(i=0;i<nodesx->number;i++) |
130 | amb | 232 | if(nodesx->ndata[i].firstseg&NODE_SUPER) |
131 | super_number++; | ||
132 | amb | 219 | |
133 | amb | 110 | /* Fill in a Nodes structure with the offset of the real data in the file after |
134 | the Node structure itself. */ | ||
135 | |||
136 | amb | 243 | nodes=calloc(1,sizeof(Nodes)); |
137 | |||
138 | assert(nodes); /* Check calloc() worked */ | ||
139 | |||
140 | amb | 110 | nodes->number=nodesx->number; |
141 | amb | 232 | nodes->snumber=super_number; |
142 | amb | 110 | |
143 | amb | 257 | nodes->latbins=nodesx->latbins; |
144 | nodes->lonbins=nodesx->lonbins; | ||
145 | amb | 110 | |
146 | amb | 257 | nodes->latzero=nodesx->latzero; |
147 | nodes->lonzero=nodesx->lonzero; | ||
148 | amb | 110 | |
149 | nodes->data=NULL; | ||
150 | amb | 232 | |
151 | amb | 110 | nodes->offsets=(void*)sizeof(Nodes); |
152 | amb | 257 | nodes->nodes=(void*)(sizeof(Nodes)+(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t)); |
153 | amb | 110 | |
154 | /* Write out the Nodes structure and then the real data. */ | ||
155 | |||
156 | fd=OpenFile(filename); | ||
157 | |||
158 | WriteFile(fd,nodes,sizeof(Nodes)); | ||
159 | |||
160 | amb | 257 | WriteFile(fd,nodesx->offsets,(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t)); |
161 | amb | 110 | |
162 | amb | 203 | for(i=0;i<nodes->number;i++) |
163 | amb | 132 | { |
164 | amb | 257 | Node *node=&nodesx->ndata[nodesx->gdata[i]]; |
165 | amb | 110 | |
166 | amb | 212 | WriteFile(fd,node,sizeof(Node)); |
167 | |||
168 | amb | 132 | if(!((i+1)%10000)) |
169 | { | ||
170 | printf("\rWriting Nodes: Nodes=%d",i+1); | ||
171 | fflush(stdout); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | amb | 203 | printf("\rWrote Nodes: Nodes=%d \n",nodes->number); |
176 | amb | 132 | fflush(stdout); |
177 | |||
178 | amb | 110 | CloseFile(fd); |
179 | |||
180 | /* Free the fake Nodes */ | ||
181 | |||
182 | free(nodes); | ||
183 | } | ||
184 | |||
185 | |||
186 | /*++++++++++++++++++++++++++++++++++++++ | ||
187 | amb | 252 | Find a particular node index. |
188 | amb | 110 | |
189 | amb | 249 | index_t IndexNodeX Returns the index of the extended node with the specified id. |
190 | amb | 110 | |
191 | NodesX* nodesx The set of nodes to process. | ||
192 | |||
193 | node_t id The node id to look for. | ||
194 | ++++++++++++++++++++++++++++++++++++++*/ | ||
195 | |||
196 | amb | 249 | index_t IndexNodeX(NodesX* nodesx,node_t id) |
197 | amb | 110 | { |
198 | int start=0; | ||
199 | int end=nodesx->number-1; | ||
200 | int mid; | ||
201 | |||
202 | amb | 243 | assert(nodesx->idata); /* Must have idata filled in => sorted by id */ |
203 | amb | 110 | |
204 | /* Binary search - search key exact match only is required. | ||
205 | * | ||
206 | * # <- start | Check mid and move start or end if it doesn't match | ||
207 | * # | | ||
208 | * # | Since an exact match is wanted we can set end=mid-1 | ||
209 | * # <- mid | or start=mid+1 because we know that mid doesn't match. | ||
210 | * # | | ||
211 | * # | Eventually either end=start or end=start+1 and one of | ||
212 | * # <- end | start or end is the wanted one. | ||
213 | */ | ||
214 | |||
215 | amb | 252 | if(end<start) /* There are no nodes */ |
216 | amb | 249 | return(NO_NODE); |
217 | amb | 252 | else if(id<nodesx->idata[start]) /* Check key is not before start */ |
218 | amb | 249 | return(NO_NODE); |
219 | amb | 252 | else if(id>nodesx->idata[end]) /* Check key is not after end */ |
220 | amb | 249 | return(NO_NODE); |
221 | amb | 110 | else |
222 | { | ||
223 | do | ||
224 | { | ||
225 | amb | 252 | mid=(start+end)/2; /* Choose mid point */ |
226 | amb | 110 | |
227 | amb | 252 | if(nodesx->idata[mid]<id) /* Mid point is too low */ |
228 | amb | 110 | start=mid+1; |
229 | amb | 252 | else if(nodesx->idata[mid]>id) /* Mid point is too high */ |
230 | amb | 110 | end=mid-1; |
231 | amb | 252 | else /* Mid point is correct */ |
232 | amb | 249 | return(mid); |
233 | amb | 110 | } |
234 | while((end-start)>1); | ||
235 | |||
236 | amb | 252 | if(nodesx->idata[start]==id) /* Start is correct */ |
237 | amb | 249 | return(start); |
238 | amb | 110 | |
239 | amb | 252 | if(nodesx->idata[end]==id) /* End is correct */ |
240 | amb | 249 | return(end); |
241 | amb | 110 | } |
242 | |||
243 | amb | 249 | return(NO_NODE); |
244 | amb | 110 | } |
245 | |||
246 | |||
247 | /*++++++++++++++++++++++++++++++++++++++ | ||
248 | amb | 275 | Lookup a particular node. |
249 | |||
250 | NodeX *LookupNodeX Returns a pointer to the extended node with the specified id. | ||
251 | |||
252 | NodesX* nodesx The set of nodes to process. | ||
253 | |||
254 | index_t index The node index to look for. | ||
255 | |||
256 | int position The position in the cache to use. | ||
257 | ++++++++++++++++++++++++++++++++++++++*/ | ||
258 | |||
259 | NodeX *LookupNodeX(NodesX* nodesx,index_t index,int position) | ||
260 | { | ||
261 | assert(index!=NO_NODE); /* Must be a valid node */ | ||
262 | |||
263 | if(option_slim) | ||
264 | { | ||
265 | SeekFile(nodesx->fd,index*sizeof(NodeX)); | ||
266 | |||
267 | ReadFile(nodesx->fd,&nodesx->cached[position-1],sizeof(NodeX)); | ||
268 | |||
269 | return(&nodesx->cached[position-1]); | ||
270 | } | ||
271 | else | ||
272 | { | ||
273 | return(&nodesx->xdata[index]); | ||
274 | } | ||
275 | } | ||
276 | |||
277 | |||
278 | /*++++++++++++++++++++++++++++++++++++++ | ||
279 | amb | 252 | Append a node to a newly created node list (unsorted). |
280 | amb | 243 | |
281 | amb | 252 | NodesX* nodesx The set of nodes to process. |
282 | amb | 243 | |
283 | amb | 252 | node_t id The node identification. |
284 | amb | 110 | |
285 | amb | 252 | double latitude The latitude of the node. |
286 | amb | 110 | |
287 | amb | 252 | double longitude The longitude of the node. |
288 | ++++++++++++++++++++++++++++++++++++++*/ | ||
289 | amb | 110 | |
290 | amb | 252 | void AppendNode(NodesX* nodesx,node_t id,double latitude,double longitude) |
291 | { | ||
292 | NodeX nodex; | ||
293 | amb | 249 | |
294 | amb | 252 | assert(!nodesx->idata); /* Must not have idata filled in => unsorted */ |
295 | |||
296 | nodex.id=id; | ||
297 | nodex.latitude =radians_to_latlong(latitude); | ||
298 | nodex.longitude=radians_to_latlong(longitude); | ||
299 | |||
300 | WriteFile(nodesx->fd,&nodex,sizeof(NodeX)); | ||
301 | |||
302 | nodesx->xnumber++; | ||
303 | amb | 110 | } |
304 | |||
305 | |||
306 | amb | 271 | /*+ A temporary file-local variable for use by the sort functions. +*/ |
307 | static NodesX *sortnodesx; | ||
308 | |||
309 | |||
310 | amb | 110 | /*++++++++++++++++++++++++++++++++++++++ |
311 | amb | 263 | Sort the node list (i.e. create the sortable indexes). |
312 | amb | 110 | |
313 | NodesX* nodesx The set of nodes to process. | ||
314 | ++++++++++++++++++++++++++++++++++++++*/ | ||
315 | |||
316 | amb | 263 | void SortNodeList(NodesX* nodesx) |
317 | amb | 110 | { |
318 | amb | 263 | int fd; |
319 | amb | 110 | |
320 | amb | 263 | /* Check the start conditions */ |
321 | |||
322 | amb | 252 | assert(!nodesx->idata); /* Must not have idata filled in => unsorted */ |
323 | |||
324 | amb | 263 | /* Print the start message */ |
325 | |||
326 | printf("Sorting Nodes"); | ||
327 | amb | 227 | fflush(stdout); |
328 | amb | 132 | |
329 | amb | 263 | /* Close the files and re-open them (finished appending) */ |
330 | amb | 260 | |
331 | CloseFile(nodesx->fd); | ||
332 | nodesx->fd=ReOpenFile(nodesx->filename); | ||
333 | |||
334 | amb | 271 | DeleteFile(nodesx->filename); |
335 | |||
336 | fd=OpenFile(nodesx->filename); | ||
337 | |||
338 | amb | 252 | /* Allocate the array of indexes */ |
339 | amb | 249 | |
340 | amb | 252 | nodesx->idata=(node_t*)malloc(nodesx->xnumber*sizeof(node_t)); |
341 | amb | 249 | |
342 | amb | 252 | assert(nodesx->idata); /* Check malloc() worked */ |
343 | amb | 249 | |
344 | amb | 271 | /* Sort by node indexes */ |
345 | amb | 249 | |
346 | amb | 271 | sortnodesx=nodesx; |
347 | amb | 110 | |
348 | 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); |
349 | amb | 252 | |
350 | amb | 260 | /* Close the files and re-open them */ |
351 | |||
352 | amb | 257 | CloseFile(nodesx->fd); |
353 | CloseFile(fd); | ||
354 | amb | 252 | |
355 | amb | 257 | nodesx->fd=ReOpenFile(nodesx->filename); |
356 | amb | 252 | |
357 | amb | 263 | /* Print the final message */ |
358 | |||
359 | amb | 273 | printf("\rSorted Nodes: Nodes=%d Duplicates=%d\n",nodesx->xnumber,nodesx->xnumber-nodesx->number); |
360 | amb | 263 | fflush(stdout); |
361 | amb | 110 | } |
362 | |||
363 | |||
364 | /*++++++++++++++++++++++++++++++++++++++ | ||
365 | Sort the nodes into id order. | ||
366 | |||
367 | int sort_by_id Returns the comparison of the id fields. | ||
368 | |||
369 | amb | 271 | NodeX *a The first extended node. |
370 | amb | 110 | |
371 | amb | 271 | NodeX *b The second extended node. |
372 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
373 | |||
374 | amb | 271 | static int sort_by_id(NodeX *a,NodeX *b) |
375 | amb | 110 | { |
376 | amb | 271 | node_t a_id=a->id; |
377 | node_t b_id=b->id; | ||
378 | amb | 252 | |
379 | if(a_id<b_id) | ||
380 | return(-1); | ||
381 | else if(a_id>b_id) | ||
382 | amb | 249 | return(1); |
383 | amb | 110 | else |
384 | amb | 252 | return(0); |
385 | amb | 110 | } |
386 | |||
387 | |||
388 | amb | 271 | /*++++++++++++++++++++++++++++++++++++++ |
389 | Index the nodes after sorting. | ||
390 | amb | 252 | |
391 | amb | 273 | index_by_id Return 1 if the value is to be kept, otherwise zero. |
392 | |||
393 | amb | 271 | NodeX *nodex The extended node. |
394 | amb | 252 | |
395 | amb | 271 | index_t index The index of this node in the total. |
396 | ++++++++++++++++++++++++++++++++++++++*/ | ||
397 | |||
398 | amb | 273 | static int index_by_id(NodeX *nodex,index_t index) |
399 | amb | 271 | { |
400 | amb | 273 | if(index==0 || sortnodesx->idata[index-1]!=nodex->id) |
401 | { | ||
402 | sortnodesx->idata[index]=nodex->id; | ||
403 | amb | 271 | |
404 | amb | 273 | sortnodesx->number++; |
405 | |||
406 | return(1); | ||
407 | } | ||
408 | |||
409 | return(0); | ||
410 | amb | 271 | } |
411 | |||
412 | |||
413 | amb | 110 | /*++++++++++++++++++++++++++++++++++++++ |
414 | amb | 212 | Sort the node list geographically. |
415 | |||
416 | NodesX* nodesx The set of nodes to process. | ||
417 | ++++++++++++++++++++++++++++++++++++++*/ | ||
418 | |||
419 | void SortNodeListGeographically(NodesX* nodesx) | ||
420 | { | ||
421 | amb | 214 | index_t i; |
422 | amb | 257 | ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin; |
423 | latlong_t lat_min,lat_max,lon_min,lon_max; | ||
424 | uint32_t latlonbin; | ||
425 | amb | 212 | |
426 | amb | 263 | /* Check the start conditions */ |
427 | |||
428 | amb | 279 | 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->ndata); /* Must not have ndata filled in => no real nodes */ |
655 | amb | 110 | |
656 | amb | 275 | /* Print the start message */ |
657 | |||
658 | amb | 227 | printf("Creating Real Nodes: Nodes=0"); |
659 | fflush(stdout); | ||
660 | |||
661 | amb | 275 | /* Map into memory */ |
662 | |||
663 | if(!option_slim) | ||
664 | nodesx->xdata=MapFile(nodesx->filename); | ||
665 | |||
666 | amb | 212 | /* Allocate the memory */ |
667 | |||
668 | nodesx->ndata=(Node*)malloc(nodesx->number*sizeof(Node)); | ||
669 | |||
670 | amb | 243 | assert(nodesx->ndata); /* Check malloc() worked */ |
671 | |||
672 | amb | 212 | /* Loop through and allocate. */ |
673 | |||
674 | amb | 110 | for(i=0;i<nodesx->number;i++) |
675 | { | ||
676 | amb | 275 | NodeX *nodex=LookupNodeX(nodesx,i,1); |
677 | amb | 208 | |
678 | amb | 275 | nodesx->ndata[i].latoffset=latlong_to_off(nodex->latitude); |
679 | nodesx->ndata[i].lonoffset=latlong_to_off(nodex->longitude); | ||
680 | amb | 212 | nodesx->ndata[i].firstseg=SEGMENT(NO_SEGMENT); |
681 | |||
682 | amb | 249 | if(nodesx->super[i]==iteration) |
683 | amb | 212 | nodesx->ndata[i].firstseg|=NODE_SUPER; |
684 | |||
685 | amb | 110 | if(!((i+1)%10000)) |
686 | { | ||
687 | amb | 212 | printf("\rCreating Real Nodes: Nodes=%d",i+1); |
688 | amb | 110 | fflush(stdout); |
689 | } | ||
690 | } | ||
691 | |||
692 | amb | 275 | /* Unmap from memory */ |
693 | |||
694 | if(!option_slim) | ||
695 | nodesx->xdata=UnmapFile(nodesx->filename); | ||
696 | |||
697 | /* Print the final message */ | ||
698 | |||
699 | amb | 212 | printf("\rCreating Real Nodes: Nodes=%d \n",nodesx->number); |
700 | amb | 110 | fflush(stdout); |
701 | } | ||
702 | |||
703 | |||
704 | /*++++++++++++++++++++++++++++++++++++++ | ||
705 | Assign the segment indexes to the nodes. | ||
706 | |||
707 | NodesX *nodesx The list of nodes to process. | ||
708 | |||
709 | SegmentsX* segmentsx The set of segments to use. | ||
710 | ++++++++++++++++++++++++++++++++++++++*/ | ||
711 | |||
712 | amb | 209 | void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx) |
713 | amb | 110 | { |
714 | amb | 214 | index_t i; |
715 | amb | 110 | |
716 | amb | 275 | /* Check the start conditions */ |
717 | |||
718 | amb | 243 | assert(nodesx->ndata); /* Must have ndata filled in => real nodes exist */ |
719 | assert(segmentsx->sdata); /* Must have sdata filled in => real segments exist */ | ||
720 | amb | 110 | |
721 | amb | 275 | /* Print the start message */ |
722 | |||
723 | amb | 227 | printf("Indexing Segments: Segments=0"); |
724 | fflush(stdout); | ||
725 | |||
726 | amb | 275 | /* Map into memory */ |
727 | |||
728 | if(!option_slim) | ||
729 | segmentsx->xdata=MapFile(segmentsx->filename); | ||
730 | |||
731 | amb | 110 | /* Index the nodes */ |
732 | |||
733 | for(i=0;i<segmentsx->number;i++) | ||
734 | { | ||
735 | amb | 275 | SegmentX *segmentx=LookupSegmentX(segmentsx,i,1); |
736 | amb | 257 | node_t id1=segmentx->node1; |
737 | node_t id2=segmentx->node2; | ||
738 | amb | 279 | Node *node1=&nodesx->ndata[id1]; |
739 | Node *node2=&nodesx->ndata[id2]; | ||
740 | amb | 110 | |
741 | /* Check node1 */ | ||
742 | |||
743 | amb | 212 | if(SEGMENT(node1->firstseg)==SEGMENT(NO_SEGMENT)) |
744 | amb | 110 | { |
745 | amb | 212 | node1->firstseg^=SEGMENT(NO_SEGMENT); |
746 | node1->firstseg|=i; | ||
747 | amb | 110 | } |
748 | else | ||
749 | { | ||
750 | amb | 212 | index_t index=SEGMENT(node1->firstseg); |
751 | amb | 110 | |
752 | do | ||
753 | { | ||
754 | amb | 275 | segmentx=LookupSegmentX(segmentsx,index,1); |
755 | amb | 256 | |
756 | amb | 257 | if(segmentx->node1==id1) |
757 | amb | 110 | { |
758 | amb | 209 | index++; |
759 | amb | 128 | |
760 | amb | 256 | if(index>=segmentsx->number) |
761 | amb | 209 | break; |
762 | amb | 256 | |
763 | amb | 275 | segmentx=LookupSegmentX(segmentsx,index,1); |
764 | amb | 256 | |
765 | amb | 257 | if(segmentx->node1!=id1) |
766 | amb | 256 | break; |
767 | amb | 110 | } |
768 | else | ||
769 | { | ||
770 | amb | 209 | if(segmentsx->sdata[index].next2==NO_NODE) |
771 | amb | 110 | { |
772 | amb | 209 | segmentsx->sdata[index].next2=i; |
773 | break; | ||
774 | amb | 110 | } |
775 | else | ||
776 | amb | 209 | index=segmentsx->sdata[index].next2; |
777 | amb | 110 | } |
778 | } | ||
779 | amb | 209 | while(1); |
780 | amb | 110 | } |
781 | |||
782 | /* Check node2 */ | ||
783 | |||
784 | amb | 212 | if(SEGMENT(node2->firstseg)==SEGMENT(NO_SEGMENT)) |
785 | amb | 110 | { |
786 | amb | 212 | node2->firstseg^=SEGMENT(NO_SEGMENT); |
787 | node2->firstseg|=i; | ||
788 | amb | 110 | } |
789 | else | ||
790 | { | ||
791 | amb | 212 | index_t index=SEGMENT(node2->firstseg); |
792 | amb | 110 | |
793 | do | ||
794 | { | ||
795 | amb | 275 | segmentx=LookupSegmentX(segmentsx,index,1); |
796 | amb | 256 | |
797 | amb | 257 | if(segmentx->node1==id2) |
798 | amb | 110 | { |
799 | amb | 209 | index++; |
800 | amb | 128 | |
801 | amb | 256 | if(index>=segmentsx->number) |
802 | amb | 209 | break; |
803 | amb | 256 | |
804 | amb | 275 | segmentx=LookupSegmentX(segmentsx,index,1); |
805 | amb | 256 | |
806 | amb | 257 | if(segmentx->node1!=id2) |
807 | amb | 256 | break; |
808 | amb | 110 | } |
809 | else | ||
810 | { | ||
811 | amb | 209 | if(segmentsx->sdata[index].next2==NO_NODE) |
812 | amb | 110 | { |
813 | amb | 209 | segmentsx->sdata[index].next2=i; |
814 | break; | ||
815 | amb | 110 | } |
816 | else | ||
817 | amb | 209 | index=segmentsx->sdata[index].next2; |
818 | amb | 110 | } |
819 | } | ||
820 | amb | 209 | while(1); |
821 | amb | 110 | } |
822 | |||
823 | if(!((i+1)%10000)) | ||
824 | { | ||
825 | printf("\rIndexing Segments: Segments=%d",i+1); | ||
826 | fflush(stdout); | ||
827 | } | ||
828 | } | ||
829 | |||
830 | amb | 275 | /* Unmap from memory */ |
831 | |||
832 | if(!option_slim) | ||
833 | segmentsx->xdata=UnmapFile(segmentsx->filename); | ||
834 | |||
835 | /* Print the final message */ | ||
836 | |||
837 | amb | 110 | printf("\rIndexed Segments: Segments=%d \n",segmentsx->number); |
838 | fflush(stdout); | ||
839 | } |
Properties
Name | Value |
---|---|
cvs:description | Extended nodes functions. |