1 /***************************************
2 $Header: /home/amb/routino/src/RCS/relationsx.c,v 1.8 2010/10/09 18:20:18 amb Exp $
4 Extended Relation data type functions.
6 Part of the Routino routing software.
7 ******************/ /******************
8 This file Copyright 2010 Andrew M. Bishop
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.
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.
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 ***************************************/
32 #include "relationsx.h"
35 #include "functions.h"
40 /*+ The command line '--tmpdir' option or its default value. +*/
41 extern char *option_tmpdirname;
44 /*++++++++++++++++++++++++++++++++++++++
45 Allocate a new relation list (create a new file or open an existing one).
47 RelationsX *NewRelationList Returns the relation list.
49 int append Set to 1 if the file is to be opened for appending (now or later).
50 ++++++++++++++++++++++++++++++++++++++*/
52 RelationsX *NewRelationList(int append)
54 RelationsX *relationsx;
56 relationsx=(RelationsX*)calloc(1,sizeof(RelationsX));
58 assert(relationsx); /* Check calloc() worked */
60 relationsx->rfilename=(char*)malloc(strlen(option_tmpdirname)+32);
63 sprintf(relationsx->rfilename,"%s/relationsx.route.input.tmp",option_tmpdirname);
65 sprintf(relationsx->rfilename,"%s/relationsx.route.%p.tmp",option_tmpdirname,relationsx);
69 off_t size,position=0;
71 relationsx->rfd=OpenFileAppend(relationsx->rfilename);
73 size=SizeFile(relationsx->rfilename);
77 FILESORT_VARINT relationsize;
79 SeekFile(relationsx->rfd,position);
80 ReadFile(relationsx->rfd,&relationsize,FILESORT_VARSIZE);
82 relationsx->rxnumber++;
83 position+=relationsize+FILESORT_VARSIZE;
86 SeekFile(relationsx->rfd,size);
89 relationsx->rfd=OpenFileNew(relationsx->rfilename);
95 /*++++++++++++++++++++++++++++++++++++++
98 RelationsX *relationsx The list to be freed.
100 int keep Set to 1 if the file is to be kept.
101 ++++++++++++++++++++++++++++++++++++++*/
103 void FreeRelationList(RelationsX *relationsx,int keep)
106 DeleteFile(relationsx->rfilename);
108 free(relationsx->rfilename);
114 /*++++++++++++++++++++++++++++++++++++++
115 Append a single relation to an unsorted route relation list.
117 RelationsX* relationsx The set of relations to process.
119 relation_t id The ID of the relation.
121 allow_t routes The types of routes that this relation is for.
123 way_t *ways The array of ways that are members of the relation.
125 int nways The number of ways that are members of the relation.
127 relation_t *relations The array of relations that are members of the relation.
129 int nrelations The number of relations that are members of the relation.
130 ++++++++++++++++++++++++++++++++++++++*/
132 void AppendRouteRelation(RelationsX* relationsx,relation_t id,allow_t routes,
133 way_t *ways,int nways,
134 relation_t *relations,int nrelations)
137 FILESORT_VARINT size;
139 relation_t zerorelation=0;
142 relationx.routes=routes;
144 size=sizeof(RouteRelX)+(nways+1)*sizeof(way_t)+(nrelations+1)*sizeof(relation_t);
146 WriteFile(relationsx->rfd,&size,FILESORT_VARSIZE);
147 WriteFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
149 WriteFile(relationsx->rfd,ways ,nways*sizeof(way_t));
150 WriteFile(relationsx->rfd,&zeroway, sizeof(way_t));
152 WriteFile(relationsx->rfd,relations ,nrelations*sizeof(relation_t));
153 WriteFile(relationsx->rfd,&zerorelation, sizeof(relation_t));
155 relationsx->rxnumber++;
157 assert(!(relationsx->rxnumber==0)); /* Zero marks the high-water mark for relations. */
161 /*++++++++++++++++++++++++++++++++++++++
162 Sort the list of relations.
164 RelationsX* relationsx The set of relations to process.
165 ++++++++++++++++++++++++++++++++++++++*/
167 void SortRelationList(RelationsX* relationsx)
169 /* Don't need to sort route relations */
173 /*++++++++++++++++++++++++++++++++++++++
174 Process the route relations and apply the information to the ways.
176 RelationsX *relationsx The set of relations to process.
178 WaysX *waysx The set of ways to update.
179 ++++++++++++++++++++++++++++++++++++++*/
181 void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx)
183 RouteRelX *unmatched=NULL,*lastunmatched=NULL;
184 int nunmatched=0,lastnunmatched=0,iteration=0;
190 /* Map into memory */
193 waysx->xdata=MapFileWriteable(waysx->filename);
196 /* Re-open the ways file read/write */
199 CloseFile(waysx->fd);
200 waysx->fd=ReOpenFileWriteable(waysx->filename);
203 /* Open the file and read through it */
205 relationsx->rfd=ReOpenFile(relationsx->rfilename);
209 SeekFile(relationsx->rfd,0);
211 /* Print the start message */
213 printf("Processing Route Relations: Iteration=%d Relations=0",iteration);
216 for(i=0;i<relationsx->rxnumber;i++)
218 FILESORT_VARINT size;
221 relation_t relationid;
222 allow_t routes=Allow_None;
224 /* Read each route relation */
226 ReadFile(relationsx->rfd,&size,FILESORT_VARSIZE);
227 ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
229 /* Decide what type of route it is */
232 routes=relationx.routes;
235 if((lastunmatched[j].routes|relationx.routes)==relationx.routes)
236 routes=0; /* Nothing new to add */
238 for(j=0;j<lastnunmatched;j++)
239 if(lastunmatched[j].id==relationx.id)
241 routes=lastunmatched[j].routes;
246 /* Loop through the ways */
250 ReadFile(relationsx->rfd,&wayid,sizeof(way_t));
252 /* Update the ways that are listed for the relation */
256 index_t way=IndexWayX(waysx,wayid);
260 WayX *wayx=LookupWayX(waysx,way,1);
262 if(routes&Allow_Foot)
263 wayx->way.props|=Properties_FootRoute;
265 if(routes&Allow_Bicycle)
266 wayx->way.props|=Properties_BicycleRoute;
269 PutBackWayX(waysx,way,1);
276 /* Loop through the relations */
280 ReadFile(relationsx->rfd,&relationid,sizeof(relation_t));
282 /* Add the relations that are listed for this relation to the list for next time */
284 if(relationid && routes && relationid!=relationx.id)
286 if(nunmatched%256==0)
287 unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX));
289 unmatched[nunmatched].id=relationid;
290 unmatched[nunmatched].routes=routes;
299 printf("\rProcessing Route Relations: Iteration=%d Relations=%d",iteration,i+1);
307 lastunmatched=unmatched;
308 lastnunmatched=nunmatched;
313 /* Print the final message */
315 printf("\rProcessed Route Relations: Iteration=%d Relations=%d \n",iteration,relationsx->rxnumber);
318 while(lastnunmatched && ++iteration<5);
323 CloseFile(relationsx->rfd);
325 /* Unmap from memory */
328 waysx->xdata=UnmapFile(waysx->filename);
331 /* Re-open the ways file read only */
334 CloseFile(waysx->fd);
335 waysx->fd=ReOpenFile(waysx->filename);