Imported Upstream version 1.5.1
[routino] / src / fakes.c
1 /***************************************
2  $Header: /home/amb/routino/src/RCS/fakes.c,v 1.2 2010/08/04 16:44:51 amb Exp $
3
4  Fake node and segment generation.
5
6  Part of the Routino routing software.
7  ******************/ /******************
8  This file Copyright 2008-2010 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 "types.h"
26 #include "nodes.h"
27 #include "segments.h"
28
29 #include "functions.h"
30
31
32 /*+ The minimum distance along a segment from a node to insert a fake node. (in km). +*/
33 #define MINSEGMENT 0.005
34
35
36 /*+ A set of fake segments to allow start/finish in the middle of a segment. +*/
37 static Segment fake_segments[2*NWAYPOINTS];
38
39 /*+ A set of fake node latitudes and longitudes. +*/
40 static double fake_lon[NWAYPOINTS+1],fake_lat[NWAYPOINTS+1];
41
42
43 /*++++++++++++++++++++++++++++++++++++++
44   Create a pair of fake segments corresponding to the given segment split in two.
45
46   index_t CreateFakes Returns the fake node index (or a real one in special cases).
47
48   Nodes *nodes The set of nodes to use.
49
50   int point Which of the waypoints is this.
51
52   Segment *segment The segment to split.
53
54   index_t node1 The first node at the end of this segment.
55
56   index_t node2 The second node at the end of this segment.
57
58   distance_t dist1 The distance to the first node.
59
60   distance_t dist2 The distance to the second node.
61   ++++++++++++++++++++++++++++++++++++++*/
62
63 index_t CreateFakes(Nodes *nodes,int point,Segment *segment,index_t node1,index_t node2,distance_t dist1,distance_t dist2)
64 {
65  index_t fakenode;
66  double lat1,lon1,lat2,lon2;
67
68  /* Check if we are actually close enough to an existing node */
69
70  if(dist1<km_to_distance(MINSEGMENT) && dist2>km_to_distance(MINSEGMENT))
71     return(node1);
72
73  if(dist2<km_to_distance(MINSEGMENT) && dist1>km_to_distance(MINSEGMENT))
74     return(node2);
75
76  if(dist1<km_to_distance(MINSEGMENT) && dist2<km_to_distance(MINSEGMENT))
77    {
78     if(dist1<dist2)
79        return(node1);
80     else
81        return(node2);
82    }
83
84  /* Create the fake node */
85
86  fakenode=NODE_FAKE+point;
87
88  GetLatLong(nodes,node1,&lat1,&lon1);
89  GetLatLong(nodes,node2,&lat2,&lon2);
90
91  if(lat1>3 && lat2<-3)
92     lat2+=2*M_PI;
93  else if(lat1<-3 && lat2>3)
94     lat1+=2*M_PI;
95
96  fake_lat[point]=lat1+(lat2-lat1)*(double)dist1/(double)(dist1+dist2);
97  fake_lon[point]=lon1+(lon2-lon1)*(double)dist1/(double)(dist1+dist2);
98
99  if(fake_lat[point]>M_PI) fake_lat[point]-=2*M_PI;
100
101  /* Create the first fake segment */
102
103  fake_segments[2*point-2]=*segment;
104
105  if(segment->node1==node1)
106     fake_segments[2*point-2].node1=fakenode;
107  else
108     fake_segments[2*point-2].node2=fakenode;
109
110  fake_segments[2*point-2].distance=DISTANCE(dist1)|DISTFLAG(segment->distance);
111
112  /* Create the second fake segment */
113
114  fake_segments[2*point-1]=*segment;
115
116  if(segment->node1==node2)
117     fake_segments[2*point-1].node1=fakenode;
118  else
119     fake_segments[2*point-1].node2=fakenode;
120
121  fake_segments[2*point-1].distance=DISTANCE(dist2)|DISTFLAG(segment->distance);
122
123  return(fakenode);
124 }
125
126
127 /*++++++++++++++++++++++++++++++++++++++
128   Lookup the latitude and longitude of a fake node.
129
130   index_t fakenode The node to lookup.
131
132   double *latitude Returns the latitude
133
134   double *longitude Returns the longitude.
135   ++++++++++++++++++++++++++++++++++++++*/
136
137 void GetFakeLatLong(index_t fakenode, double *latitude,double *longitude)
138 {
139  index_t realnode=fakenode-NODE_FAKE;
140
141  *latitude =fake_lat[realnode];
142  *longitude=fake_lon[realnode];
143 }
144
145
146 /*++++++++++++++++++++++++++++++++++++++
147   Finds the first fake segment associated to a fake node.
148
149   Segment *FirstFakeSegment Returns the first fake segment.
150
151   index_t fakenode The node to lookup.
152   ++++++++++++++++++++++++++++++++++++++*/
153
154 Segment *FirstFakeSegment(index_t fakenode)
155 {
156  index_t realnode=fakenode-NODE_FAKE;
157
158  return(&fake_segments[2*realnode-2]);
159 }
160
161
162 /*++++++++++++++++++++++++++++++++++++++
163   Finds the next (there can only be two) fake segment associated to a fake node.
164
165   Segment *NextFakeSegment Returns the second fake segment.
166
167   Segment *segment The first fake segment.
168
169   index_t fakenode The node to lookup.
170   ++++++++++++++++++++++++++++++++++++++*/
171
172 Segment *NextFakeSegment(Segment *segment,index_t fakenode)
173 {
174  index_t realnode=fakenode-NODE_FAKE;
175
176  if(segment==&fake_segments[2*realnode-2])
177     return(&fake_segments[2*realnode-1]);
178  else
179     return(NULL);
180 }
181
182
183 /*++++++++++++++++++++++++++++++++++++++
184   Finds the fake segment between a node and a fake node.
185
186   Segment *ExtraFakeSegment Returns a segment between the two specified nodes if it exists.
187
188   index_t node The real node.
189
190   index_t fakenode The fake node to lookup.
191   ++++++++++++++++++++++++++++++++++++++*/
192
193 Segment *ExtraFakeSegment(index_t node,index_t fakenode)
194 {
195  index_t realnode=fakenode-NODE_FAKE;
196
197  if(fake_segments[2*realnode-2].node1==node || fake_segments[2*realnode-2].node2==node)
198     return(&fake_segments[2*realnode-2]);
199
200  if(fake_segments[2*realnode-1].node1==node || fake_segments[2*realnode-1].node2==node)
201     return(&fake_segments[2*realnode-1]);
202
203  return(NULL);
204 }
205
206
207 /*++++++++++++++++++++++++++++++++++++++
208   Lookup a fake segment given its index.
209
210   Segment *LookupFakeSegment Returns a pointer to the segment.
211
212   index_t fakesegment The index of the fake segment.
213   ++++++++++++++++++++++++++++++++++++++*/
214
215 Segment *LookupFakeSegment(index_t fakesegment)
216 {
217  index_t realsegment=fakesegment-SEGMENT_FAKE;
218
219  return(&fake_segments[realsegment]);
220 }
221
222
223 /*++++++++++++++++++++++++++++++++++++++
224   Find the fake index of a fake segment.
225
226   index_t IndexFakeSegment Returns the fake segment.
227
228   Segment *segment The segment to look for.
229   ++++++++++++++++++++++++++++++++++++++*/
230
231 index_t IndexFakeSegment(Segment *segment)
232 {
233  index_t realsegment=segment-&fake_segments[0];
234
235  return(realsegment+SEGMENT_FAKE);
236 }