Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/prunex.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 963 - (show annotations) (download) (as text)
Thu Feb 9 18:36:46 2012 UTC (13 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 13127 byte(s)
Prune isolated segments if they cannot be routed to anywhere else, not just if
they are not connected.

1 /***************************************
2 Data pruning functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2011-2012 Andrew M. Bishop
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ***************************************/
21
22
23 #include <stdlib.h>
24 #include <assert.h>
25
26 #include "typesx.h"
27 #include "nodesx.h"
28 #include "segmentsx.h"
29 #include "waysx.h"
30
31 #include "prunex.h"
32
33 #include "files.h"
34 #include "logging.h"
35
36
37 /* Local functions */
38
39 static void prune_segment(SegmentsX *segmentsx,SegmentX *segmentx);
40 static void modify_segment(SegmentsX *segmentsx,SegmentX *segmentx,index_t newnode1,index_t newnode2);
41
42 static void unlink_segment_node_refs(SegmentsX *segmentsx,SegmentX *segmentx,index_t node);
43
44
45 /*++++++++++++++++++++++++++++++++++++++
46 Initialise the data structures needed for pruning.
47
48 NodesX *nodesx The set of nodes to use.
49
50 SegmentsX *segmentsx The set of segments to use.
51
52 WaysX *waysx The set of ways to use.
53 ++++++++++++++++++++++++++++++++++++++*/
54
55 void StartPruning(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
56 {
57 SegmentX segmentx;
58 index_t index=0,lastnode1=NO_NODE;
59
60 /* Print the start message */
61
62 printf_first("Adding Extra Segment Indexes: Segments=0");
63
64 /* Allocate the array of next segment */
65
66 segmentsx->next1=(index_t*)calloc(segmentsx->number,sizeof(index_t));
67
68 assert(segmentsx->next1); /* Check malloc() worked */
69
70 /* Open the file read-only */
71
72 segmentsx->fd=ReOpenFile(segmentsx->filename);
73
74 /* Read the on-disk image */
75
76 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
77 {
78 index_t node1=segmentx.node1;
79
80 if(index==0)
81 ;
82 else if(lastnode1==node1)
83 segmentsx->next1[index-1]=index;
84 else
85 segmentsx->next1[index-1]=NO_SEGMENT;
86
87 lastnode1=node1;
88 index++;
89
90 if(!(index%10000))
91 printf_middle("Added Extra Segment Indexes: Segments=%"Pindex_t,index);
92 }
93
94 segmentsx->next1[index-1]=NO_SEGMENT;
95
96 /* Close the file */
97
98 segmentsx->fd=CloseFile(segmentsx->fd);
99
100 /* Print the final message */
101
102 printf_last("Added Extra Segment Indexes: Segments=%"Pindex_t,segmentsx->number);
103 }
104
105
106 /*++++++++++++++++++++++++++++++++++++++
107 Delete the data structures needed for pruning.
108
109 NodesX *nodesx The set of nodes to use.
110
111 SegmentsX *segmentsx The set of segments to use.
112
113 WaysX *waysx The set of ways to use.
114 ++++++++++++++++++++++++++++++++++++++*/
115
116 void FinishPruning(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
117 {
118 index_t i,pruned=0;
119 int fd;
120
121
122 /* Delete the pruned segments */
123
124 free(segmentsx->next1);
125 segmentsx->next1=NULL;
126
127 SortSegmentList(segmentsx,1);
128
129 IndexSegments(segmentsx,nodesx);
130
131
132 /* Delete the pruned nodes */
133
134 printf_first("Marking Pruned Nodes: Nodes=0 Pruned=0");
135
136 /* Re-open the file read-only and a new file writeable */
137
138 nodesx->fd=ReOpenFile(nodesx->filename);
139
140 DeleteFile(nodesx->filename);
141
142 fd=OpenFileNew(nodesx->filename);
143
144 /* Modify the on-disk image */
145
146 for(i=0;i<nodesx->number;i++)
147 {
148 NodeX nodex;
149
150 ReadFile(nodesx->fd,&nodex,sizeof(NodeX));
151
152 if(segmentsx->firstnode[i]==NO_SEGMENT)
153 {
154 pruned++;
155 nodex.latitude=NO_LATLONG;
156 nodex.longitude=NO_LATLONG;
157 }
158
159 WriteFile(fd,&nodex,sizeof(NodeX));
160
161 if(!((i+1)%10000))
162 printf_middle("Marking Pruned Nodes: Nodes=%"Pindex_t" Pruned=%"Pindex_t,i+1,pruned);
163 }
164
165 /* Close the files */
166
167 nodesx->fd=CloseFile(nodesx->fd);
168 CloseFile(fd);
169
170 /* Print the final message */
171
172 printf_last("Marked Pruned Nodes: Nodes=%"Pindex_t" Pruned=%"Pindex_t,nodesx->number,pruned);
173 }
174
175
176 /*++++++++++++++++++++++++++++++++++++++
177 Prune out any groups of nodes and segments whose total length is less than a
178 specified minimum.
179
180 NodesX *nodesx The set of nodes to use.
181
182 SegmentsX *segmentsx The set of segments to use.
183
184 WaysX *waysx The set of ways to use.
185
186 distance_t minimum The minimum distance to keep.
187 ++++++++++++++++++++++++++++++++++++++*/
188
189 void PruneIsolatedRegions(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,distance_t minimum)
190 {
191 index_t i,j;
192 index_t nregions=0,npruned=0;
193 BitMask *connected,*region;
194 index_t *regionsegments,*othersegments;
195 int nallocregionsegments,nallocothersegments;
196
197 if(nodesx->number==0 || segmentsx->number==0)
198 return;
199
200 /* Print the start message */
201
202 printf_first("Pruning Isolated Regions: Segments=0 Pruned=0");
203
204 /* Map into memory / open the files */
205
206 #if !SLIM
207 nodesx->data=MapFileWriteable(nodesx->filename);
208 segmentsx->data=MapFileWriteable(segmentsx->filename);
209 waysx->data=MapFile(waysx->filename);
210 #else
211 nodesx->fd=ReOpenFileWriteable(nodesx->filename);
212 segmentsx->fd=ReOpenFileWriteable(segmentsx->filename);
213 waysx->fd=ReOpenFile(waysx->filename);
214 #endif
215
216 connected=AllocBitMask(segmentsx->number);
217 region =AllocBitMask(segmentsx->number);
218
219 assert(connected); /* Check AllocBitMask() worked */
220 assert(region); /* Check AllocBitMask() worked */
221
222 regionsegments=(index_t*)malloc((nallocregionsegments=1024)*sizeof(index_t));
223 othersegments =(index_t*)malloc((nallocothersegments =1024)*sizeof(index_t));
224
225 assert(regionsegments); /* Check malloc() worked */
226 assert(othersegments); /* Check malloc() worked */
227
228 /* Loop through the segments and find the disconnected ones */
229
230 for(i=0;i<segmentsx->number;i++)
231 {
232 if(!IsBitSet(connected,i))
233 {
234 int nregionsegments=0,nothersegments=0;
235 distance_t total=0;
236
237 othersegments[nothersegments++]=i;
238 SetBit(region,i);
239
240 do
241 {
242 SegmentX *segmentx;
243 index_t thissegment,nodes[2];
244 WayX *wayx;
245
246 thissegment=othersegments[--nothersegments];
247
248 if(nregionsegments==nallocregionsegments)
249 regionsegments=(index_t*)realloc(regionsegments,(nallocregionsegments+=1024)*sizeof(index_t));
250
251 regionsegments[nregionsegments++]=thissegment;
252
253 segmentx=LookupSegmentX(segmentsx,thissegment,1);
254
255 nodes[0]=segmentx->node1;
256 nodes[1]=segmentx->node2;
257 total+=DISTANCE(segmentx->distance);
258
259 wayx=LookupWayX(waysx,segmentx->way,1);
260
261 for(j=0;j<2;j++)
262 {
263 NodeX *nodex=LookupNodeX(nodesx,nodes[j],1);
264
265 if(!(nodex->allow&wayx->way.allow)) /* some type of traffic must be allowed */
266 continue;
267
268 segmentx=FirstSegmentX(segmentsx,nodes[j],1);
269
270 while(segmentx)
271 {
272 index_t segment=IndexSegmentX(segmentsx,segmentx);
273
274 if(segment!=thissegment)
275 {
276 WayX *way2x=LookupWayX(waysx,segmentx->way,2);
277
278 if(wayx->way.allow&way2x->way.allow) /* some type of traffic must be allowed */
279 {
280 /* Already connected - finish */
281
282 if(IsBitSet(connected,segment))
283 {
284 total=minimum;
285 goto foundconnection;
286 }
287
288 /* Not in region - add to list */
289
290 if(!IsBitSet(region,segment))
291 {
292 if(nothersegments==nallocothersegments)
293 othersegments=(index_t*)realloc(othersegments,(nallocothersegments+=1024)*sizeof(index_t));
294
295 othersegments[nothersegments++]=segment;
296 SetBit(region,segment);
297 }
298 }
299 }
300
301 segmentx=NextSegmentX(segmentsx,segmentx,nodes[j]);
302 }
303 }
304 }
305 while(nothersegments>0 && total<minimum);
306
307 foundconnection:
308
309 /* Prune the segments or mark them as connected */
310
311 if(total<minimum)
312 {
313 nregions++;
314
315 for(j=0;j<nregionsegments;j++)
316 {
317 SegmentX *segmentx=LookupSegmentX(segmentsx,regionsegments[j],1);
318
319 SetBit(connected,regionsegments[j]);
320
321 prune_segment(segmentsx,segmentx);
322
323 npruned++;
324 }
325 }
326 else
327 {
328 for(j=0;j<nregionsegments;j++)
329 {
330 SetBit(connected,regionsegments[j]);
331 ClearBit(region,regionsegments[j]);
332 }
333
334 for(j=0;j<nothersegments;j++)
335 {
336 SetBit(connected,othersegments[j]);
337 ClearBit(region,othersegments[j]);
338 }
339 }
340 }
341
342 if(!((i+1)%10000))
343 printf_middle("Pruning Isolated Regions: Segments=%"Pindex_t" Pruned=%"Pindex_t" (%"Pindex_t" Regions)",i+1,npruned,nregions);
344 }
345
346 /* Unmap from memory / close the files */
347
348 free(region);
349 free(connected);
350
351 free(regionsegments);
352 free(othersegments);
353
354 #if !SLIM
355 nodesx->data=UnmapFile(nodesx->filename);
356 segmentsx->data=UnmapFile(segmentsx->filename);
357 waysx->data=UnmapFile(waysx->filename);
358 #else
359 nodesx->fd=CloseFile(nodesx->fd);
360 segmentsx->fd=CloseFile(segmentsx->fd);
361 waysx->fd=CloseFile(waysx->fd);
362 #endif
363
364 /* Print the final message */
365
366 printf_last("Pruned Isolated Regions: Segments=%"Pindex_t" Pruned=%"Pindex_t" (%"Pindex_t" Regions)",segmentsx->number,npruned,nregions);
367 }
368
369
370 /*++++++++++++++++++++++++++++++++++++++
371 Prune a segment; unused nodes and ways will get marked for pruning later.
372
373 SegmentsX *segmentsx The set of segments to use.
374
375 SegmentX *segmentx The segment to be pruned.
376 ++++++++++++++++++++++++++++++++++++++*/
377
378 static void prune_segment(SegmentsX *segmentsx,SegmentX *segmentx)
379 {
380 unlink_segment_node_refs(segmentsx,segmentx,segmentx->node1);
381 unlink_segment_node_refs(segmentsx,segmentx,segmentx->node2);
382
383 segmentx->node1=NO_NODE;
384 segmentx->node2=NO_NODE;
385 segmentx->next2=NO_SEGMENT;
386
387 PutBackSegmentX(segmentsx,segmentx);
388 }
389
390
391 /*++++++++++++++++++++++++++++++++++++++
392 Modify a segment's nodes; unused nodes will get marked for pruning later.
393
394 SegmentsX *segmentsx The set of segments to use.
395
396 SegmentX *segmentx The segment to be modified.
397
398 index_t newnode1 The new value of node1.
399
400 index_t newnode2 The new value of node2.
401 ++++++++++++++++++++++++++++++++++++++*/
402
403 static void modify_segment(SegmentsX *segmentsx,SegmentX *segmentx,index_t newnode1,index_t newnode2)
404 {
405 index_t thissegment=IndexSegmentX(segmentsx,segmentx);
406
407 if(newnode1!=segmentx->node1)
408 {
409 unlink_segment_node_refs(segmentsx,segmentx,segmentx->node1);
410
411 segmentx->node1=newnode1;
412
413 segmentsx->next1[thissegment]=segmentsx->firstnode[newnode1];
414 segmentsx->firstnode[newnode1]=thissegment;
415 }
416
417 if(newnode1!=segmentx->node1)
418 {
419 unlink_segment_node_refs(segmentsx,segmentx,segmentx->node2);
420
421 segmentx->node2=newnode2;
422
423 segmentx->next2=segmentsx->firstnode[newnode2];
424 segmentsx->firstnode[newnode2]=thissegment;
425 }
426
427 PutBackSegmentX(segmentsx,segmentx);
428 }
429
430
431 /*++++++++++++++++++++++++++++++++++++++
432 Unlink one node from a segment by modifying the linked list type arrangement of node references.
433
434 SegmentsX *segmentsx The set of segments to use.
435
436 SegmentX *segmentx The segment to be pruned.
437
438 index_t node The node index of the end of the segment being modified here.
439 ++++++++++++++++++++++++++++++++++++++*/
440
441 static void unlink_segment_node_refs(SegmentsX *segmentsx,SegmentX *segmentx,index_t node)
442 {
443 index_t thissegment=IndexSegmentX(segmentsx,segmentx);
444 index_t segment=segmentsx->firstnode[node];
445
446 if(segment==NO_SEGMENT)
447 return;
448
449 if(segment==thissegment)
450 {
451 if(segmentx->node1==node)
452 segmentsx->firstnode[node]=segmentsx->next1[thissegment];
453 else
454 segmentsx->firstnode[node]=segmentx->next2;
455 }
456 else
457 {
458 index_t nextsegment;
459
460 do
461 {
462 SegmentX *segx=LookupSegmentX(segmentsx,segment,2);
463
464 if(segx->node1==node)
465 {
466 nextsegment=segmentsx->next1[segment];
467
468 if(thissegment==nextsegment)
469 {
470 if(segmentx->node1==node)
471 segmentsx->next1[segment]=segmentsx->next1[thissegment];
472 else
473 segmentsx->next1[segment]=segmentx->next2;
474 }
475 }
476 else
477 {
478 nextsegment=segx->next2;
479
480 if(thissegment==nextsegment)
481 {
482 if(segmentx->node1==node)
483 segx->next2=segmentsx->next1[thissegment];
484 else
485 segx->next2=segmentx->next2;
486
487 PutBackSegmentX(segmentsx,segx);
488 }
489 }
490
491 segment=nextsegment;
492 }
493 while(segment!=thissegment && segment!=NO_SEGMENT);
494 }
495 }