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