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 273 -
(hide annotations)
(download)
(as text)
Sun Oct 4 15:52:47 2009 UTC (15 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 19133 byte(s)
Sun Oct 4 15:52:47 2009 UTC (15 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 19133 byte(s)
Remove the duplicates when sorting.
1 | amb | 110 | /*************************************** |
2 | amb | 273 | $Header: /home/amb/CVS/routino/src/nodesx.c,v 1.43 2009-10-04 15:52:47 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 | 252 | Append a node to a newly created node list (unsorted). |
248 | amb | 243 | |
249 | amb | 252 | NodesX* nodesx The set of nodes to process. |
250 | amb | 243 | |
251 | amb | 252 | node_t id The node identification. |
252 | amb | 110 | |
253 | amb | 252 | double latitude The latitude of the node. |
254 | amb | 110 | |
255 | amb | 252 | double longitude The longitude of the node. |
256 | ++++++++++++++++++++++++++++++++++++++*/ | ||
257 | amb | 110 | |
258 | amb | 252 | void AppendNode(NodesX* nodesx,node_t id,double latitude,double longitude) |
259 | { | ||
260 | NodeX nodex; | ||
261 | amb | 249 | |
262 | amb | 252 | assert(!nodesx->idata); /* Must not have idata filled in => unsorted */ |
263 | |||
264 | nodex.id=id; | ||
265 | nodex.latitude =radians_to_latlong(latitude); | ||
266 | nodex.longitude=radians_to_latlong(longitude); | ||
267 | |||
268 | WriteFile(nodesx->fd,&nodex,sizeof(NodeX)); | ||
269 | |||
270 | nodesx->xnumber++; | ||
271 | amb | 110 | } |
272 | |||
273 | |||
274 | amb | 271 | /*+ A temporary file-local variable for use by the sort functions. +*/ |
275 | static NodesX *sortnodesx; | ||
276 | |||
277 | |||
278 | amb | 110 | /*++++++++++++++++++++++++++++++++++++++ |
279 | amb | 263 | Sort the node list (i.e. create the sortable indexes). |
280 | amb | 110 | |
281 | NodesX* nodesx The set of nodes to process. | ||
282 | ++++++++++++++++++++++++++++++++++++++*/ | ||
283 | |||
284 | amb | 263 | void SortNodeList(NodesX* nodesx) |
285 | amb | 110 | { |
286 | amb | 263 | int fd; |
287 | amb | 110 | |
288 | amb | 263 | /* Check the start conditions */ |
289 | |||
290 | amb | 252 | assert(!nodesx->idata); /* Must not have idata filled in => unsorted */ |
291 | |||
292 | amb | 263 | /* Print the start message */ |
293 | |||
294 | printf("Sorting Nodes"); | ||
295 | amb | 227 | fflush(stdout); |
296 | amb | 132 | |
297 | amb | 263 | /* Close the files and re-open them (finished appending) */ |
298 | amb | 260 | |
299 | CloseFile(nodesx->fd); | ||
300 | nodesx->fd=ReOpenFile(nodesx->filename); | ||
301 | |||
302 | amb | 271 | DeleteFile(nodesx->filename); |
303 | |||
304 | fd=OpenFile(nodesx->filename); | ||
305 | |||
306 | amb | 252 | /* Allocate the array of indexes */ |
307 | amb | 249 | |
308 | amb | 252 | nodesx->idata=(node_t*)malloc(nodesx->xnumber*sizeof(node_t)); |
309 | amb | 249 | |
310 | amb | 252 | assert(nodesx->idata); /* Check malloc() worked */ |
311 | amb | 249 | |
312 | amb | 271 | /* Sort by node indexes */ |
313 | amb | 249 | |
314 | amb | 271 | sortnodesx=nodesx; |
315 | amb | 110 | |
316 | 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); |
317 | amb | 252 | |
318 | amb | 260 | /* Close the files and re-open them */ |
319 | |||
320 | amb | 257 | CloseFile(nodesx->fd); |
321 | CloseFile(fd); | ||
322 | amb | 252 | |
323 | amb | 257 | nodesx->fd=ReOpenFile(nodesx->filename); |
324 | amb | 252 | |
325 | amb | 266 | if(!option_slim) |
326 | nodesx->xdata=MapFile(nodesx->filename); | ||
327 | |||
328 | amb | 263 | /* Print the final message */ |
329 | |||
330 | amb | 273 | printf("\rSorted Nodes: Nodes=%d Duplicates=%d\n",nodesx->xnumber,nodesx->xnumber-nodesx->number); |
331 | amb | 263 | fflush(stdout); |
332 | amb | 110 | } |
333 | |||
334 | |||
335 | /*++++++++++++++++++++++++++++++++++++++ | ||
336 | Sort the nodes into id order. | ||
337 | |||
338 | int sort_by_id Returns the comparison of the id fields. | ||
339 | |||
340 | amb | 271 | NodeX *a The first extended node. |
341 | amb | 110 | |
342 | amb | 271 | NodeX *b The second extended node. |
343 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
344 | |||
345 | amb | 271 | static int sort_by_id(NodeX *a,NodeX *b) |
346 | amb | 110 | { |
347 | amb | 271 | node_t a_id=a->id; |
348 | node_t b_id=b->id; | ||
349 | amb | 252 | |
350 | if(a_id<b_id) | ||
351 | return(-1); | ||
352 | else if(a_id>b_id) | ||
353 | amb | 249 | return(1); |
354 | amb | 110 | else |
355 | amb | 252 | return(0); |
356 | amb | 110 | } |
357 | |||
358 | |||
359 | amb | 271 | /*++++++++++++++++++++++++++++++++++++++ |
360 | Index the nodes after sorting. | ||
361 | amb | 252 | |
362 | amb | 273 | index_by_id Return 1 if the value is to be kept, otherwise zero. |
363 | |||
364 | amb | 271 | NodeX *nodex The extended node. |
365 | amb | 252 | |
366 | amb | 271 | index_t index The index of this node in the total. |
367 | ++++++++++++++++++++++++++++++++++++++*/ | ||
368 | |||
369 | amb | 273 | static int index_by_id(NodeX *nodex,index_t index) |
370 | amb | 271 | { |
371 | amb | 273 | if(index==0 || sortnodesx->idata[index-1]!=nodex->id) |
372 | { | ||
373 | sortnodesx->idata[index]=nodex->id; | ||
374 | amb | 271 | |
375 | amb | 273 | sortnodesx->number++; |
376 | |||
377 | return(1); | ||
378 | } | ||
379 | |||
380 | return(0); | ||
381 | amb | 271 | } |
382 | |||
383 | |||
384 | amb | 110 | /*++++++++++++++++++++++++++++++++++++++ |
385 | amb | 212 | Sort the node list geographically. |
386 | |||
387 | NodesX* nodesx The set of nodes to process. | ||
388 | ++++++++++++++++++++++++++++++++++++++*/ | ||
389 | |||
390 | void SortNodeListGeographically(NodesX* nodesx) | ||
391 | { | ||
392 | amb | 214 | index_t i; |
393 | amb | 257 | ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin; |
394 | latlong_t lat_min,lat_max,lon_min,lon_max; | ||
395 | uint32_t latlonbin; | ||
396 | amb | 212 | |
397 | amb | 263 | /* Check the start conditions */ |
398 | |||
399 | amb | 243 | assert(nodesx->idata); /* Must have idata filled in => sorted by id */ |
400 | assert(!nodesx->gdata); /* Must not have gdata filled in => unsorted geographically */ | ||
401 | amb | 212 | |
402 | amb | 263 | if(option_slim) |
403 | nodesx->xdata=MapFile(nodesx->filename); | ||
404 | |||
405 | /* Print the start message */ | ||
406 | |||
407 | amb | 227 | printf("Sorting Nodes Geographically"); |
408 | fflush(stdout); | ||
409 | amb | 212 | |
410 | amb | 213 | /* Allocate the array of pointers and sort them */ |
411 | amb | 212 | |
412 | amb | 257 | nodesx->gdata=(index_t*)malloc(nodesx->number*sizeof(index_t)); |
413 | amb | 212 | |
414 | amb | 243 | assert(nodesx->gdata); /* Check malloc() worked */ |
415 | |||
416 | amb | 212 | for(i=0;i<nodesx->number;i++) |
417 | amb | 257 | nodesx->gdata[i]=i; |
418 | amb | 212 | |
419 | amb | 252 | sortnodesx=nodesx; |
420 | amb | 212 | |
421 | amb | 257 | qsort(nodesx->gdata,nodesx->number,sizeof(index_t),(int (*)(const void*,const void*))sort_by_lat_long); |
422 | amb | 252 | |
423 | amb | 257 | /* Work out the range of data */ |
424 | |||
425 | lat_min=radians_to_latlong( 2); | ||
426 | lat_max=radians_to_latlong(-2); | ||
427 | lon_min=radians_to_latlong( 4); | ||
428 | lon_max=radians_to_latlong(-4); | ||
429 | |||
430 | for(i=0;i<nodesx->number;i++) | ||
431 | { | ||
432 | NodeX *nodex=&nodesx->xdata[i]; | ||
433 | |||
434 | if(nodex->latitude<lat_min) | ||
435 | lat_min=nodex->latitude; | ||
436 | if(nodex->latitude>lat_max) | ||
437 | lat_max=nodex->latitude; | ||
438 | if(nodex->longitude<lon_min) | ||
439 | lon_min=nodex->longitude; | ||
440 | if(nodex->longitude>lon_max) | ||
441 | lon_max=nodex->longitude; | ||
442 | } | ||
443 | |||
444 | amb | 263 | /* Work out the number of bins */ |
445 | amb | 257 | |
446 | lat_min_bin=latlong_to_bin(lat_min); | ||
447 | lon_min_bin=latlong_to_bin(lon_min); | ||
448 | lat_max_bin=latlong_to_bin(lat_max); | ||
449 | lon_max_bin=latlong_to_bin(lon_max); | ||
450 | |||
451 | nodesx->latbins=(lat_max_bin-lat_min_bin)+1; | ||
452 | nodesx->lonbins=(lon_max_bin-lon_min_bin)+1; | ||
453 | |||
454 | amb | 263 | /* Work out the offsets */ |
455 | |||
456 | amb | 257 | nodesx->offsets=(index_t*)malloc((nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t)); |
457 | |||
458 | latlonbin=0; | ||
459 | |||
460 | for(i=0;i<nodesx->number;i++) | ||
461 | { | ||
462 | NodeX *nodex=&nodesx->xdata[nodesx->gdata[i]]; | ||
463 | |||
464 | ll_bin_t latbin=latlong_to_bin(nodex->latitude )-lat_min_bin; | ||
465 | ll_bin_t lonbin=latlong_to_bin(nodex->longitude)-lon_min_bin; | ||
466 | int llbin=lonbin*nodesx->latbins+latbin; | ||
467 | |||
468 | for(;latlonbin<=llbin;latlonbin++) | ||
469 | nodesx->offsets[latlonbin]=i; | ||
470 | } | ||
471 | |||
472 | for(;latlonbin<=(nodesx->latbins*nodesx->lonbins);latlonbin++) | ||
473 | nodesx->offsets[latlonbin]=nodesx->number; | ||
474 | |||
475 | nodesx->latzero=lat_min_bin; | ||
476 | nodesx->lonzero=lon_min_bin; | ||
477 | |||
478 | amb | 263 | /* Print the final message */ |
479 | amb | 257 | |
480 | amb | 227 | printf("\rSorted Nodes Geographically \n"); |
481 | fflush(stdout); | ||
482 | amb | 212 | } |
483 | |||
484 | |||
485 | /*++++++++++++++++++++++++++++++++++++++ | ||
486 | amb | 110 | Sort the nodes into latitude and longitude order. |
487 | |||
488 | int sort_by_lat_long Returns the comparison of the latitude and longitude fields. | ||
489 | |||
490 | amb | 257 | index_t *a The first node id. |
491 | amb | 110 | |
492 | amb | 257 | index_t *b The second node id. |
493 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
494 | |||
495 | amb | 257 | static int sort_by_lat_long(index_t *a,index_t *b) |
496 | amb | 110 | { |
497 | amb | 257 | NodeX *nodex_a=&sortnodesx->xdata[*a]; |
498 | NodeX *nodex_b=&sortnodesx->xdata[*b]; | ||
499 | amb | 110 | |
500 | amb | 252 | ll_bin_t a_lon=latlong_to_bin(nodex_a->longitude); |
501 | ll_bin_t b_lon=latlong_to_bin(nodex_b->longitude); | ||
502 | |||
503 | amb | 110 | if(a_lon<b_lon) |
504 | return(-1); | ||
505 | else if(a_lon>b_lon) | ||
506 | return(1); | ||
507 | else | ||
508 | { | ||
509 | amb | 252 | ll_bin_t a_lat=latlong_to_bin(nodex_a->latitude); |
510 | ll_bin_t b_lat=latlong_to_bin(nodex_b->latitude); | ||
511 | amb | 110 | |
512 | if(a_lat<b_lat) | ||
513 | return(-1); | ||
514 | else if(a_lat>b_lat) | ||
515 | return(1); | ||
516 | else | ||
517 | return(0); | ||
518 | } | ||
519 | } | ||
520 | |||
521 | |||
522 | /*++++++++++++++++++++++++++++++++++++++ | ||
523 | Remove any nodes that are not part of a highway. | ||
524 | |||
525 | NodesX *nodesx The complete node list. | ||
526 | |||
527 | SegmentsX *segmentsx The list of segments. | ||
528 | ++++++++++++++++++++++++++++++++++++++*/ | ||
529 | |||
530 | void RemoveNonHighwayNodes(NodesX *nodesx,SegmentsX *segmentsx) | ||
531 | { | ||
532 | amb | 263 | NodeX nodex; |
533 | amb | 273 | int total=0,highway=0,nothighway=0; |
534 | amb | 263 | int fd; |
535 | amb | 271 | node_t previd=NO_NODE,*idata; |
536 | amb | 110 | |
537 | amb | 263 | /* Check the start conditions */ |
538 | |||
539 | amb | 249 | assert(nodesx->idata); /* Must have idata filled in => data sorted */ |
540 | amb | 213 | |
541 | amb | 263 | /* Print the start message */ |
542 | |||
543 | amb | 227 | printf("Checking: Nodes=0"); |
544 | fflush(stdout); | ||
545 | |||
546 | amb | 263 | /* Modify the on-disk image */ |
547 | |||
548 | amb | 266 | if(!option_slim) |
549 | nodesx->xdata=UnmapFile(nodesx->filename); | ||
550 | |||
551 | if(option_slim) | ||
552 | segmentsx->xdata=MapFile(segmentsx->filename); | ||
553 | |||
554 | amb | 263 | DeleteFile(nodesx->filename); |
555 | |||
556 | fd=OpenFile(nodesx->filename); | ||
557 | SeekFile(nodesx->fd,0); | ||
558 | |||
559 | while(!ReadFile(nodesx->fd,&nodex,sizeof(NodeX))) | ||
560 | amb | 110 | { |
561 | amb | 273 | if(!IndexFirstSegmentX(segmentsx,nodex.id)) |
562 | amb | 271 | nothighway++; |
563 | else | ||
564 | amb | 263 | { |
565 | WriteFile(fd,&nodex,sizeof(NodeX)); | ||
566 | |||
567 | nodesx->idata[highway]=nodesx->idata[total]; | ||
568 | amb | 110 | highway++; |
569 | amb | 263 | } |
570 | amb | 110 | |
571 | amb | 271 | previd=nodex.id; |
572 | |||
573 | amb | 263 | total++; |
574 | |||
575 | if(!(total%10000)) | ||
576 | amb | 110 | { |
577 | amb | 273 | printf("\rChecking: Nodes=%d Highway=%d not-Highway=%d",total,highway,nothighway); |
578 | amb | 110 | fflush(stdout); |
579 | } | ||
580 | } | ||
581 | |||
582 | amb | 263 | /* Close the files and re-open them */ |
583 | |||
584 | CloseFile(nodesx->fd); | ||
585 | CloseFile(fd); | ||
586 | |||
587 | nodesx->fd=ReOpenFile(nodesx->filename); | ||
588 | |||
589 | amb | 266 | if(!option_slim) |
590 | nodesx->xdata=MapFile(nodesx->filename); | ||
591 | |||
592 | if(option_slim) | ||
593 | segmentsx->xdata=UnmapFile(segmentsx->filename); | ||
594 | |||
595 | amb | 263 | /* Allocate a smaller array for the node index (don't trust realloc to make it smaller) */ |
596 | |||
597 | idata=(node_t*)malloc(highway*sizeof(node_t)); | ||
598 | |||
599 | assert(idata); /* Check malloc() worked */ | ||
600 | |||
601 | memcpy(idata,nodesx->idata,highway*sizeof(node_t)); | ||
602 | |||
603 | free(nodesx->idata); | ||
604 | |||
605 | nodesx->idata=idata; | ||
606 | nodesx->number=highway; | ||
607 | |||
608 | /* Allocate and clear the super-node markers */ | ||
609 | |||
610 | nodesx->super=(uint8_t*)calloc(nodesx->number,sizeof(uint8_t)); | ||
611 | |||
612 | assert(nodesx->super); /* Check calloc() worked */ | ||
613 | |||
614 | /* Print the final message */ | ||
615 | |||
616 | amb | 273 | printf("\rChecked: Nodes=%d Highway=%d not-Highway=%d \n",total,highway,nothighway); |
617 | amb | 110 | fflush(stdout); |
618 | } | ||
619 | |||
620 | |||
621 | /*++++++++++++++++++++++++++++++++++++++ | ||
622 | amb | 212 | Create the real node data. |
623 | amb | 110 | |
624 | amb | 212 | NodesX *nodesx The set of nodes to use. |
625 | amb | 110 | |
626 | amb | 212 | int iteration The final super-node iteration. |
627 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
628 | |||
629 | amb | 212 | void CreateRealNodes(NodesX *nodesx,int iteration) |
630 | amb | 110 | { |
631 | amb | 214 | index_t i; |
632 | amb | 110 | |
633 | amb | 243 | assert(nodesx->idata); /* Must have idata filled in => sorted by id */ |
634 | assert(!nodesx->ndata); /* Must not have ndata filled in => no real nodes */ | ||
635 | amb | 110 | |
636 | amb | 227 | printf("Creating Real Nodes: Nodes=0"); |
637 | fflush(stdout); | ||
638 | |||
639 | amb | 212 | /* Allocate the memory */ |
640 | |||
641 | nodesx->ndata=(Node*)malloc(nodesx->number*sizeof(Node)); | ||
642 | |||
643 | amb | 243 | assert(nodesx->ndata); /* Check malloc() worked */ |
644 | |||
645 | amb | 257 | SeekFile(nodesx->fd,0); |
646 | |||
647 | amb | 212 | /* Loop through and allocate. */ |
648 | |||
649 | amb | 110 | for(i=0;i<nodesx->number;i++) |
650 | { | ||
651 | amb | 257 | if(option_slim) |
652 | { | ||
653 | NodeX nodex; | ||
654 | amb | 208 | |
655 | amb | 257 | ReadFile(nodesx->fd,&nodex,sizeof(NodeX)); |
656 | amb | 252 | |
657 | amb | 257 | nodesx->ndata[i].latoffset=latlong_to_off(nodex.latitude); |
658 | nodesx->ndata[i].lonoffset=latlong_to_off(nodex.longitude); | ||
659 | } | ||
660 | else | ||
661 | { | ||
662 | nodesx->ndata[i].latoffset=latlong_to_off(nodesx->xdata[i].latitude); | ||
663 | nodesx->ndata[i].lonoffset=latlong_to_off(nodesx->xdata[i].longitude); | ||
664 | } | ||
665 | |||
666 | amb | 212 | nodesx->ndata[i].firstseg=SEGMENT(NO_SEGMENT); |
667 | |||
668 | amb | 249 | if(nodesx->super[i]==iteration) |
669 | amb | 212 | nodesx->ndata[i].firstseg|=NODE_SUPER; |
670 | |||
671 | amb | 110 | if(!((i+1)%10000)) |
672 | { | ||
673 | amb | 212 | printf("\rCreating Real Nodes: Nodes=%d",i+1); |
674 | amb | 110 | fflush(stdout); |
675 | } | ||
676 | } | ||
677 | |||
678 | amb | 212 | printf("\rCreating Real Nodes: Nodes=%d \n",nodesx->number); |
679 | amb | 110 | fflush(stdout); |
680 | } | ||
681 | |||
682 | |||
683 | /*++++++++++++++++++++++++++++++++++++++ | ||
684 | Assign the segment indexes to the nodes. | ||
685 | |||
686 | NodesX *nodesx The list of nodes to process. | ||
687 | |||
688 | SegmentsX* segmentsx The set of segments to use. | ||
689 | ++++++++++++++++++++++++++++++++++++++*/ | ||
690 | |||
691 | amb | 209 | void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx) |
692 | amb | 110 | { |
693 | amb | 214 | index_t i; |
694 | amb | 110 | |
695 | amb | 243 | assert(nodesx->idata); /* Must have idata filled in => sorted */ |
696 | assert(nodesx->ndata); /* Must have ndata filled in => real nodes exist */ | ||
697 | assert(segmentsx->n1data); /* Must have n1data filled in => sorted */ | ||
698 | assert(segmentsx->sdata); /* Must have sdata filled in => real segments exist */ | ||
699 | amb | 110 | |
700 | amb | 227 | printf("Indexing Segments: Segments=0"); |
701 | fflush(stdout); | ||
702 | |||
703 | amb | 110 | /* Index the nodes */ |
704 | |||
705 | for(i=0;i<segmentsx->number;i++) | ||
706 | { | ||
707 | amb | 257 | SegmentX *segmentx=LookupSegmentX(segmentsx,segmentsx->n1data[i]); |
708 | node_t id1=segmentx->node1; | ||
709 | node_t id2=segmentx->node2; | ||
710 | Node *node1=&nodesx->ndata[IndexNodeX(nodesx,id1)]; | ||
711 | Node *node2=&nodesx->ndata[IndexNodeX(nodesx,id2)]; | ||
712 | amb | 110 | |
713 | /* Check node1 */ | ||
714 | |||
715 | amb | 212 | if(SEGMENT(node1->firstseg)==SEGMENT(NO_SEGMENT)) |
716 | amb | 110 | { |
717 | amb | 212 | node1->firstseg^=SEGMENT(NO_SEGMENT); |
718 | node1->firstseg|=i; | ||
719 | amb | 110 | } |
720 | else | ||
721 | { | ||
722 | amb | 212 | index_t index=SEGMENT(node1->firstseg); |
723 | amb | 110 | |
724 | do | ||
725 | { | ||
726 | amb | 257 | segmentx=LookupSegmentX(segmentsx,segmentsx->n1data[index]); |
727 | amb | 256 | |
728 | amb | 257 | if(segmentx->node1==id1) |
729 | amb | 110 | { |
730 | amb | 209 | index++; |
731 | amb | 128 | |
732 | amb | 256 | if(index>=segmentsx->number) |
733 | amb | 209 | break; |
734 | amb | 256 | |
735 | amb | 257 | segmentx=LookupSegmentX(segmentsx,segmentsx->n1data[index]); |
736 | amb | 256 | |
737 | amb | 257 | if(segmentx->node1!=id1) |
738 | amb | 256 | break; |
739 | amb | 110 | } |
740 | else | ||
741 | { | ||
742 | amb | 209 | if(segmentsx->sdata[index].next2==NO_NODE) |
743 | amb | 110 | { |
744 | amb | 209 | segmentsx->sdata[index].next2=i; |
745 | break; | ||
746 | amb | 110 | } |
747 | else | ||
748 | amb | 209 | index=segmentsx->sdata[index].next2; |
749 | amb | 110 | } |
750 | } | ||
751 | amb | 209 | while(1); |
752 | amb | 110 | } |
753 | |||
754 | /* Check node2 */ | ||
755 | |||
756 | amb | 212 | if(SEGMENT(node2->firstseg)==SEGMENT(NO_SEGMENT)) |
757 | amb | 110 | { |
758 | amb | 212 | node2->firstseg^=SEGMENT(NO_SEGMENT); |
759 | node2->firstseg|=i; | ||
760 | amb | 110 | } |
761 | else | ||
762 | { | ||
763 | amb | 212 | index_t index=SEGMENT(node2->firstseg); |
764 | amb | 110 | |
765 | do | ||
766 | { | ||
767 | amb | 257 | segmentx=LookupSegmentX(segmentsx,segmentsx->n1data[index]); |
768 | amb | 256 | |
769 | amb | 257 | if(segmentx->node1==id2) |
770 | amb | 110 | { |
771 | amb | 209 | index++; |
772 | amb | 128 | |
773 | amb | 256 | if(index>=segmentsx->number) |
774 | amb | 209 | break; |
775 | amb | 256 | |
776 | amb | 257 | segmentx=LookupSegmentX(segmentsx,segmentsx->n1data[index]); |
777 | amb | 256 | |
778 | amb | 257 | if(segmentx->node1!=id2) |
779 | amb | 256 | break; |
780 | amb | 110 | } |
781 | else | ||
782 | { | ||
783 | amb | 209 | if(segmentsx->sdata[index].next2==NO_NODE) |
784 | amb | 110 | { |
785 | amb | 209 | segmentsx->sdata[index].next2=i; |
786 | break; | ||
787 | amb | 110 | } |
788 | else | ||
789 | amb | 209 | index=segmentsx->sdata[index].next2; |
790 | amb | 110 | } |
791 | } | ||
792 | amb | 209 | while(1); |
793 | amb | 110 | } |
794 | |||
795 | if(!((i+1)%10000)) | ||
796 | { | ||
797 | printf("\rIndexing Segments: Segments=%d",i+1); | ||
798 | fflush(stdout); | ||
799 | } | ||
800 | } | ||
801 | |||
802 | printf("\rIndexed Segments: Segments=%d \n",segmentsx->number); | ||
803 | fflush(stdout); | ||
804 | } |
Properties
Name | Value |
---|---|
cvs:description | Extended nodes functions. |