|
|
1 | /** |
|
|
2 | * ZANavi, Zoff Android Navigation system. |
|
|
3 | * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc> |
|
|
4 | * |
|
|
5 | * This program is free software; you can redistribute it and/or |
|
|
6 | * modify it under the terms of the GNU General Public License |
|
|
7 | * version 2 as published by the Free Software Foundation. |
|
|
8 | * |
|
|
9 | * This program is distributed in the hope that it will be useful, |
|
|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
12 | * GNU General Public License for more details. |
|
|
13 | * |
|
|
14 | * You should have received a copy of the GNU General Public License |
|
|
15 | * along with this program; if not, write to the |
|
|
16 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
|
17 | * Boston, MA 02110-1301, USA. |
|
|
18 | */ |
|
|
19 | |
1 | /** |
20 | /** |
2 | * Navit, a modular navigation system. |
21 | * Navit, a modular navigation system. |
3 | * Copyright (C) 2005-2008 Navit Team |
22 | * Copyright (C) 2005-2008 Navit Team |
4 | * |
23 | * |
5 | * This program is free software; you can redistribute it and/or |
24 | * This program is free software; you can redistribute it and/or |
… | |
… | |
40 | #include "plugin.h" |
59 | #include "plugin.h" |
41 | #include "navit_nls.h" |
60 | #include "navit_nls.h" |
42 | |
61 | |
43 | /* #define DEBUG */ |
62 | /* #define DEBUG */ |
44 | |
63 | |
45 | static int roundabout_extra_length=50; |
64 | static int roundabout_extra_length = 50; |
46 | |
65 | |
47 | |
|
|
48 | struct suffix { |
66 | struct suffix |
|
|
67 | { |
49 | char *fullname; |
68 | char *fullname; |
50 | char *abbrev; |
69 | char *abbrev; |
51 | int sex; |
70 | int sex; |
52 | } suffixes[]= { |
71 | } suffixes[] = |
|
|
72 | { |
53 | {"weg",NULL,1}, |
73 | { "weg", NULL, 1 }, |
54 | {"platz","pl.",1}, |
74 | { "platz", "pl.", 1 }, |
55 | {"ring",NULL,1}, |
75 | { "ring", NULL, 1 }, |
56 | {"allee",NULL,2}, |
76 | { "allee", NULL, 2 }, |
57 | {"gasse",NULL,2}, |
77 | { "gasse", NULL, 2 }, |
58 | {"straße","str.",2}, |
78 | { "straße", "str.", 2 }, |
59 | {"strasse",NULL,2}, |
79 | { "strasse", NULL, 2 }, }; |
60 | }; |
|
|
61 | |
80 | |
62 | struct navigation { |
81 | struct navigation |
|
|
82 | { |
63 | struct route *route; |
83 | struct route *route; |
64 | struct map *map; |
84 | struct map *map; |
65 | struct item_hash *hash; |
85 | struct item_hash *hash; |
66 | struct vehicleprofile *vehicleprofile; |
86 | struct vehicleprofile *vehicleprofile; |
67 | struct navigation_itm *first; |
87 | struct navigation_itm *first; |
… | |
… | |
76 | struct item item_last; |
96 | struct item item_last; |
77 | int turn_around; |
97 | int turn_around; |
78 | int turn_around_limit; |
98 | int turn_around_limit; |
79 | int distance_turn; |
99 | int distance_turn; |
80 | struct callback *route_cb; |
100 | struct callback *route_cb; |
81 | int announce[route_item_last-route_item_first+1][3]; |
101 | int announce[route_item_last - route_item_first + 1][3]; |
82 | int tell_street_name; |
102 | int tell_street_name; |
83 | int delay; |
103 | int delay; |
84 | int curr_delay; |
104 | int curr_delay; |
85 | }; |
105 | }; |
86 | |
106 | |
|
|
107 | int distances[] = |
87 | int distances[]={1,2,3,4,5,10,25,50,75,100,150,200,250,300,400,500,750,-1}; |
108 | { 1, 2, 3, 4, 5, 10, 25, 50, 75, 100, 150, 200, 250, 300, 400, 500, 750, -1 }; |
88 | |
109 | |
89 | |
|
|
90 | struct navigation_command { |
110 | struct navigation_command |
|
|
111 | { |
91 | struct navigation_itm *itm; |
112 | struct navigation_itm *itm; |
92 | struct navigation_command *next; |
113 | struct navigation_command *next; |
93 | struct navigation_command *prev; |
114 | struct navigation_command *prev; |
94 | int delta; |
115 | int delta; |
95 | int roundabout_delta; |
116 | int roundabout_delta; |
… | |
… | |
101 | /** |
122 | /** |
102 | * @brief Calculates the delta between two angles |
123 | * @brief Calculates the delta between two angles |
103 | * @param angle1 The first angle |
124 | * @param angle1 The first angle |
104 | * @param angle2 The second angle |
125 | * @param angle2 The second angle |
105 | * @return The difference between the angles: -179..-1=angle2 is left of angle1,0=same,1..179=angle2 is right of angle1,180=angle1 is opposite of angle2 |
126 | * @return The difference between the angles: -179..-1=angle2 is left of angle1,0=same,1..179=angle2 is right of angle1,180=angle1 is opposite of angle2 |
106 | */ |
127 | */ |
107 | |
128 | |
108 | static int |
|
|
109 | angle_delta(int angle1, int angle2) |
129 | static int angle_delta(int angle1, int angle2) |
110 | { |
130 | { |
111 | int delta=angle2-angle1; |
131 | int delta = angle2 - angle1; |
112 | if (delta <= -180) |
132 | if (delta <= -180) |
113 | delta+=360; |
133 | delta += 360; |
114 | if (delta > 180) |
134 | if (delta > 180) |
115 | delta-=360; |
135 | delta -= 360; |
116 | return delta; |
136 | return delta; |
117 | } |
137 | } |
118 | |
138 | |
119 | static int |
|
|
120 | angle_median(int angle1, int angle2) |
139 | static int angle_median(int angle1, int angle2) |
121 | { |
140 | { |
122 | int delta=angle_delta(angle1, angle2); |
141 | int delta = angle_delta(angle1, angle2); |
123 | int ret=angle1+delta/2; |
142 | int ret = angle1 + delta / 2; |
124 | if (ret < 0) |
143 | if (ret < 0) |
125 | ret+=360; |
144 | ret += 360; |
126 | if (ret > 360) |
145 | if (ret > 360) |
127 | ret-=360; |
146 | ret -= 360; |
128 | return ret; |
147 | return ret; |
129 | } |
148 | } |
130 | |
149 | |
131 | static int |
|
|
132 | angle_opposite(int angle) |
150 | static int angle_opposite(int angle) |
133 | { |
151 | { |
134 | return ((angle+180)%360); |
152 | return ((angle + 180) % 360); |
135 | } |
153 | } |
136 | |
154 | |
137 | int |
155 | int navigation_get_attr(struct navigation *this_, enum attr_type type, |
138 | navigation_get_attr(struct navigation *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter) |
156 | struct attr *attr, struct attr_iter *iter) |
139 | { |
157 | { |
140 | struct map_rect *mr; |
158 | struct map_rect *mr; |
141 | struct item *item; |
159 | struct item *item; |
142 | dbg(1,"enter %s\n", attr_to_name(type)); |
160 | dbg(1, "enter %s\n", attr_to_name(type)); |
143 | switch (type) { |
161 | switch (type) |
|
|
162 | { |
144 | case attr_map: |
163 | case attr_map: |
145 | attr->u.map=this_->map; |
164 | attr->u.map = this_->map; |
146 | break; |
165 | break; |
147 | case attr_item_type: |
166 | case attr_item_type: |
148 | case attr_length: |
167 | case attr_length: |
149 | case attr_navigation_speech: |
168 | case attr_navigation_speech: |
150 | mr=map_rect_new(this_->map, NULL); |
169 | mr = map_rect_new(this_->map, NULL); |
151 | while ((item=map_rect_get_item(mr))) { |
170 | while ((item = map_rect_get_item(mr))) |
|
|
171 | { |
152 | if (item->type != type_nav_none && item->type != type_nav_position) { |
172 | if (item->type != type_nav_none && item->type |
|
|
173 | != type_nav_position) |
|
|
174 | { |
153 | if (type == attr_item_type) |
175 | if (type == attr_item_type) |
154 | attr->u.item_type=item->type; |
176 | attr->u.item_type = item->type; |
155 | else { |
177 | else |
|
|
178 | { |
156 | if (!item_attr_get(item, type, attr)) |
179 | if (!item_attr_get(item, type, attr)) |
157 | item=NULL; |
180 | item = NULL; |
|
|
181 | } |
|
|
182 | break; |
158 | } |
183 | } |
159 | break; |
|
|
160 | } |
|
|
161 | } |
184 | } |
162 | map_rect_destroy(mr); |
185 | map_rect_destroy(mr); |
163 | if (!item) |
186 | if (!item) |
|
|
187 | return 0; |
|
|
188 | break; |
|
|
189 | default: |
164 | return 0; |
190 | return 0; |
165 | break; |
|
|
166 | default: |
|
|
167 | return 0; |
|
|
168 | } |
191 | } |
169 | attr->type=type; |
192 | attr->type = type; |
170 | return 1; |
193 | return 1; |
171 | } |
194 | } |
172 | |
195 | |
173 | int |
|
|
174 | navigation_set_attr(struct navigation *this_, struct attr *attr) |
196 | int navigation_set_attr(struct navigation *this_, struct attr *attr) |
175 | { |
197 | { |
176 | switch (attr->type) { |
198 | switch (attr->type) |
|
|
199 | { |
177 | case attr_speech: |
200 | case attr_speech: |
178 | this_->speech=attr->u.speech; |
201 | this_->speech = attr->u.speech; |
179 | return 1; |
202 | return 1; |
180 | default: |
203 | default: |
181 | return 0; |
204 | return 0; |
182 | } |
205 | } |
183 | } |
206 | } |
184 | |
|
|
185 | |
207 | |
186 | struct navigation * |
208 | struct navigation * |
187 | navigation_new(struct attr *parent, struct attr **attrs) |
209 | navigation_new(struct attr *parent, struct attr **attrs) |
188 | { |
210 | { |
189 | int i,j; |
211 | int i, j; |
190 | struct attr * attr; |
212 | struct attr * attr; |
191 | struct navigation *ret=g_new0(struct navigation, 1); |
213 | struct navigation *ret=g_new0(struct navigation, 1); |
192 | ret->hash=item_hash_new(); |
214 | ret->hash = item_hash_new(); |
193 | ret->callback=callback_list_new(); |
215 | ret->callback = callback_list_new(); |
194 | ret->callback_speech=callback_list_new(); |
216 | ret->callback_speech = callback_list_new(); |
195 | ret->level_last=-2; |
217 | ret->level_last = -2; |
196 | ret->distance_turn=50; |
218 | ret->distance_turn = 50; |
197 | ret->turn_around_limit=3; |
219 | ret->turn_around_limit = 3; |
198 | ret->navit=parent->u.navit; |
220 | ret->navit = parent->u.navit; |
199 | ret->tell_street_name=1; |
221 | ret->tell_street_name = 1; |
200 | |
222 | |
201 | for (j = 0 ; j <= route_item_last-route_item_first ; j++) { |
223 | for (j = 0; j <= route_item_last - route_item_first; j++) |
|
|
224 | { |
202 | for (i = 0 ; i < 3 ; i++) { |
225 | for (i = 0; i < 3; i++) |
|
|
226 | { |
203 | ret->announce[j][i]=-1; |
227 | ret->announce[j][i] = -1; |
204 | } |
|
|
205 | } |
228 | } |
|
|
229 | } |
206 | |
230 | |
207 | if ((attr=attr_search(attrs, NULL, attr_tell_street_name))) { |
231 | if ((attr = attr_search(attrs, NULL, attr_tell_street_name))) |
|
|
232 | { |
208 | ret->tell_street_name = attr->u.num; |
233 | ret->tell_street_name = attr->u.num; |
209 | } |
234 | } |
210 | if ((attr=attr_search(attrs, NULL, attr_delay))) { |
235 | if ((attr = attr_search(attrs, NULL, attr_delay))) |
|
|
236 | { |
211 | ret->delay = attr->u.num; |
237 | ret->delay = attr->u.num; |
212 | } |
238 | } |
213 | |
239 | |
214 | return ret; |
240 | return ret; |
215 | } |
241 | } |
216 | |
242 | |
217 | int |
|
|
218 | navigation_set_announce(struct navigation *this_, enum item_type type, int *level) |
243 | int navigation_set_announce(struct navigation *this_, enum item_type type, |
|
|
244 | int *level) |
219 | { |
245 | { |
220 | int i; |
246 | int i; |
221 | if (type < route_item_first || type > route_item_last) { |
247 | if (type < route_item_first || type > route_item_last) |
|
|
248 | { |
222 | dbg(0,"street type %d out of range [%d,%d]", type, route_item_first, route_item_last); |
249 | dbg(0, "street type %d out of range [%d,%d]", type, route_item_first, |
|
|
250 | route_item_last); |
223 | return 0; |
251 | return 0; |
224 | } |
252 | } |
225 | for (i = 0 ; i < 3 ; i++) |
253 | for (i = 0; i < 3; i++) |
226 | this_->announce[type-route_item_first][i]=level[i]; |
254 | this_->announce[type - route_item_first][i] = level[i]; |
227 | return 1; |
255 | return 1; |
228 | } |
256 | } |
229 | |
257 | |
230 | static int |
258 | static int navigation_get_announce_level(struct navigation *this_, |
231 | navigation_get_announce_level(struct navigation *this_, enum item_type type, int dist) |
259 | enum item_type type, int dist) |
232 | { |
260 | { |
233 | int i; |
261 | int i; |
234 | |
262 | |
235 | if (type < route_item_first || type > route_item_last) |
263 | if (type < route_item_first || type > route_item_last) |
236 | return -1; |
264 | return -1; |
237 | for (i = 0 ; i < 3 ; i++) { |
265 | for (i = 0; i < 3; i++) |
|
|
266 | { |
238 | if (dist <= this_->announce[type-route_item_first][i]) |
267 | if (dist <= this_->announce[type - route_item_first][i]) |
239 | return i; |
268 | return i; |
240 | } |
269 | } |
241 | return i; |
270 | return i; |
242 | } |
271 | } |
243 | |
|
|
244 | |
272 | |
245 | /** |
273 | /** |
246 | * @brief Holds a way that one could possibly drive from a navigation item |
274 | * @brief Holds a way that one could possibly drive from a navigation item |
247 | */ |
275 | */ |
248 | struct navigation_way { |
276 | struct navigation_way |
|
|
277 | { |
249 | struct navigation_way *next; /**< Pointer to a linked-list of all navigation_ways from this navigation item */ |
278 | struct navigation_way *next; /**< Pointer to a linked-list of all navigation_ways from this navigation item */ |
250 | short dir; /**< The direction -1 or 1 of the way */ |
279 | short dir; /**< The direction -1 or 1 of the way */ |
251 | short angle2; /**< The angle one has to steer to drive from the old item to this street */ |
280 | short angle2; /**< The angle one has to steer to drive from the old item to this street */ |
252 | int flags; /**< The flags of the way */ |
281 | int flags; /**< The flags of the way */ |
253 | struct item item; /**< The item of the way */ |
282 | struct item item; /**< The item of the way */ |
254 | char *name1; |
283 | char *name1; |
255 | char *name2; |
284 | char *name2; |
256 | }; |
285 | }; |
257 | |
286 | |
258 | struct navigation_itm { |
287 | struct navigation_itm |
|
|
288 | { |
259 | struct navigation_way way; |
289 | struct navigation_way way; |
260 | int angle_end; |
290 | int angle_end; |
261 | struct coord start,end; |
291 | struct coord start, end; |
262 | int time; |
292 | int time; |
263 | int length; |
293 | int length; |
264 | int speed; |
294 | int speed; |
265 | int dest_time; |
295 | int dest_time; |
266 | int dest_length; |
296 | int dest_length; |
267 | int told; /**< Indicates if this item's announcement has been told earlier and should not be told again*/ |
297 | int told; /**< Indicates if this item's announcement has been told earlier and should not be told again*/ |
268 | int streetname_told; /**< Indicates if this item's streetname has been told in speech navigation*/ |
298 | int streetname_told; /**< Indicates if this item's streetname has been told in speech navigation*/ |
269 | int dest_count; |
299 | int dest_count; |
270 | struct navigation_itm *next; |
300 | struct navigation_itm *next; |
271 | struct navigation_itm *prev; |
301 | struct navigation_itm *prev; |
272 | }; |
302 | }; |
273 | |
303 | |
274 | static int is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode); |
304 | static int is_way_allowed(struct navigation *nav, struct navigation_way *way, |
|
|
305 | int mode); |
275 | |
306 | |
276 | static int |
307 | static int navigation_get_announce_level_cmd(struct navigation *this_, |
277 | navigation_get_announce_level_cmd(struct navigation *this_, struct navigation_itm *itm, struct navigation_command *cmd, int distance) |
308 | struct navigation_itm *itm, struct navigation_command *cmd, |
|
|
309 | int distance) |
278 | { |
310 | { |
279 | int level2,level=navigation_get_announce_level(this_, itm->way.item.type, distance); |
311 | int level2, level = navigation_get_announce_level(this_, |
|
|
312 | itm->way.item.type, distance); |
280 | if (this_->cmd_first->itm->prev) { |
313 | if (this_->cmd_first->itm->prev) |
281 | level2=navigation_get_announce_level(this_, cmd->itm->prev->way.item.type, distance); |
314 | { |
|
|
315 | level2 = navigation_get_announce_level(this_, |
|
|
316 | cmd->itm->prev->way.item.type, distance); |
282 | if (level2 > level) |
317 | if (level2 > level) |
283 | level=level2; |
318 | level = level2; |
284 | } |
319 | } |
285 | return level; |
320 | return level; |
286 | } |
321 | } |
287 | |
322 | |
288 | /* 0=N,90=E */ |
323 | /* 0=N,90=E */ |
289 | static int |
|
|
290 | road_angle(struct coord *c1, struct coord *c2, int dir) |
324 | static int road_angle(struct coord *c1, struct coord *c2, int dir) |
291 | { |
325 | { |
292 | int ret=transform_get_angle_delta(c1, c2, dir); |
326 | int ret = transform_get_angle_delta(c1, c2, dir); |
293 | dbg(1, "road_angle(0x%x,0x%x - 0x%x,0x%x)=%d\n", c1->x, c1->y, c2->x, c2->y, ret); |
327 | // dbg(1, "road_angle(0x%x,0x%x - 0x%x,0x%x)=%d\n", c1->x, c1->y, c2->x, c2->y, ret); |
294 | return ret; |
328 | return ret; |
295 | } |
329 | } |
296 | |
330 | |
297 | static char |
|
|
298 | *get_count_str(int n) |
331 | static char *get_count_str(int n) |
299 | { |
332 | { |
300 | switch (n) { |
333 | switch (n) |
|
|
334 | { |
301 | case 0: |
335 | case 0: |
302 | /* TRANSLATORS: the following counts refer to streets */ |
336 | #ifdef HAVE_API_ANDROID |
|
|
337 | android_send_generic_text(1,"+*#O:zeroth\n"); |
|
|
338 | #endif |
|
|
339 | // TRANSLATORS: the following counts refer to streets (example: turn right after the zeroth street) |
303 | return _("zeroth"); // Not sure if this exists, neither if it will ever be needed |
340 | return _("zeroth"); // Not sure if this exists, neither if it will ever be needed |
304 | case 1: |
341 | case 1: |
|
|
342 | #ifdef HAVE_API_ANDROID |
|
|
343 | android_send_generic_text(1,"+*#O:first\n"); |
|
|
344 | #endif |
|
|
345 | // TRANSLATORS: the following counts refer to streets (example: turn right after the first street) |
305 | return _("first"); |
346 | return _("first"); |
306 | case 2: |
347 | case 2: |
|
|
348 | #ifdef HAVE_API_ANDROID |
|
|
349 | android_send_generic_text(1,"+*#O:second\n"); |
|
|
350 | #endif |
|
|
351 | // TRANSLATORS: the following counts refer to streets (example: turn right after the second street) |
307 | return _("second"); |
352 | return _("second"); |
308 | case 3: |
353 | case 3: |
|
|
354 | #ifdef HAVE_API_ANDROID |
|
|
355 | android_send_generic_text(1,"+*#O:third\n"); |
|
|
356 | #endif |
|
|
357 | // TRANSLATORS: the following counts refer to streets (example: turn right after the third street) |
309 | return _("third"); |
358 | return _("third"); |
310 | case 4: |
359 | case 4: |
|
|
360 | #ifdef HAVE_API_ANDROID |
|
|
361 | android_send_generic_text(1,"+*#O:fourth\n"); |
|
|
362 | #endif |
|
|
363 | // TRANSLATORS: the following counts refer to streets (example: turn right after the fourth street) |
311 | return _("fourth"); |
364 | return _("fourth"); |
312 | case 5: |
365 | case 5: |
|
|
366 | #ifdef HAVE_API_ANDROID |
|
|
367 | android_send_generic_text(1,"+*#O:fifth\n"); |
|
|
368 | #endif |
|
|
369 | // TRANSLATORS: the following counts refer to streets (example: turn right after the fifth street) |
313 | return _("fifth"); |
370 | return _("fifth"); |
314 | case 6: |
371 | case 6: |
|
|
372 | #ifdef HAVE_API_ANDROID |
|
|
373 | android_send_generic_text(1,"+*#O:sixth\n"); |
|
|
374 | #endif |
|
|
375 | // TRANSLATORS: the following counts refer to streets (example: turn right after the sixth street) |
315 | return _("sixth"); |
376 | return _("sixth"); |
|
|
377 | case 7: |
|
|
378 | #ifdef HAVE_API_ANDROID |
|
|
379 | android_send_generic_text(1,"+*#O:seventh\n"); |
|
|
380 | #endif |
|
|
381 | // TRANSLATORS: the following counts refer to streets (example: turn right after the seventh street) |
|
|
382 | return _("seventh"); |
|
|
383 | case 8: |
|
|
384 | #ifdef HAVE_API_ANDROID |
|
|
385 | android_send_generic_text(1,"+*#O:eighth\n"); |
|
|
386 | #endif |
|
|
387 | // TRANSLATORS: the following counts refer to streets (example: turn right after the eighth street) |
|
|
388 | return _("eighth"); |
|
|
389 | case 9: |
|
|
390 | #ifdef HAVE_API_ANDROID |
|
|
391 | android_send_generic_text(1,"+*#O:ninth\n"); |
|
|
392 | #endif |
|
|
393 | // TRANSLATORS: the following counts refer to streets (example: turn right after the ninth street) |
|
|
394 | return _("ninth"); |
316 | default: |
395 | default: |
317 | return NULL; |
396 | return NULL; |
318 | } |
397 | } |
319 | } |
398 | } |
320 | |
399 | |
321 | static char |
|
|
322 | *get_exit_count_str(int n) |
400 | static char *get_exit_count_str(int n) |
323 | { |
401 | { |
324 | switch (n) { |
402 | switch (n) |
|
|
403 | { |
325 | case 0: |
404 | case 0: |
326 | /* TRANSLATORS: the following counts refer to roundabout exits */ |
405 | #ifdef HAVE_API_ANDROID |
|
|
406 | android_send_generic_text(1,"+*#O:zeroth exit\n"); |
|
|
407 | #endif |
|
|
408 | // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the zeroth exit) |
327 | return _("zeroth exit"); // Not sure if this exists, neither if it will ever be needed |
409 | return _("zeroth exit"); // Not sure if this exists, neither if it will ever be needed |
328 | case 1: |
410 | case 1: |
|
|
411 | #ifdef HAVE_API_ANDROID |
|
|
412 | android_send_generic_text(1,"+*#O:first exit\n"); |
|
|
413 | #endif |
|
|
414 | // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the first exit) |
329 | return _("first exit"); |
415 | return _("first exit"); |
330 | case 2: |
416 | case 2: |
|
|
417 | #ifdef HAVE_API_ANDROID |
|
|
418 | android_send_generic_text(1,"+*#O:second exit\n"); |
|
|
419 | #endif |
|
|
420 | // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the second exit) |
331 | return _("second exit"); |
421 | return _("second exit"); |
332 | case 3: |
422 | case 3: |
|
|
423 | #ifdef HAVE_API_ANDROID |
|
|
424 | android_send_generic_text(1,"+*#O:third exit\n"); |
|
|
425 | #endif |
|
|
426 | // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the third exit) |
333 | return _("third exit"); |
427 | return _("third exit"); |
334 | case 4: |
428 | case 4: |
|
|
429 | #ifdef HAVE_API_ANDROID |
|
|
430 | android_send_generic_text(1,"+*#O:fourth exit\n"); |
|
|
431 | #endif |
|
|
432 | // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the fourth exit) |
335 | return _("fourth exit"); |
433 | return _("fourth exit"); |
336 | case 5: |
434 | case 5: |
|
|
435 | #ifdef HAVE_API_ANDROID |
|
|
436 | android_send_generic_text(1,"+*#O:fifth exit\n"); |
|
|
437 | #endif |
|
|
438 | // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the fifth exit) |
337 | return _("fifth exit"); |
439 | return _("fifth exit"); |
338 | case 6: |
440 | case 6: |
|
|
441 | #ifdef HAVE_API_ANDROID |
|
|
442 | android_send_generic_text(1,"+*#O:sixth exit\n"); |
|
|
443 | #endif |
|
|
444 | // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the sixth exit) |
339 | return _("sixth exit"); |
445 | return _("sixth exit"); |
|
|
446 | case 7: |
|
|
447 | #ifdef HAVE_API_ANDROID |
|
|
448 | android_send_generic_text(1,"+*#O:seventh exit\n"); |
|
|
449 | #endif |
|
|
450 | // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the seventh exit) |
|
|
451 | return _("seventh exit"); |
|
|
452 | case 8: |
|
|
453 | #ifdef HAVE_API_ANDROID |
|
|
454 | android_send_generic_text(1,"+*#O:eighth exit\n"); |
|
|
455 | #endif |
|
|
456 | // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the eighth exit) |
|
|
457 | return _("eighth exit"); |
|
|
458 | case 9: |
|
|
459 | #ifdef HAVE_API_ANDROID |
|
|
460 | android_send_generic_text(1,"+*#O:ninth exit\n"); |
|
|
461 | #endif |
|
|
462 | // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the ninth exit) |
|
|
463 | return _("ninth exit"); |
340 | default: |
464 | default: |
341 | return NULL; |
465 | return NULL; |
342 | } |
466 | } |
343 | } |
467 | } |
344 | static int |
|
|
345 | round_distance(int dist) |
468 | static int round_distance(int dist) |
346 | { |
469 | { |
347 | if (dist < 100) { |
470 | if (dist < 100) |
|
|
471 | { |
348 | dist=(dist+5)/10; |
472 | dist = (dist + 5) / 10; |
349 | return dist*10; |
473 | return dist * 10; |
350 | } |
474 | } |
351 | if (dist < 250) { |
475 | if (dist < 250) |
|
|
476 | { |
352 | dist=(dist+13)/25; |
477 | dist = (dist + 13) / 25; |
353 | return dist*25; |
478 | return dist * 25; |
354 | } |
479 | } |
355 | if (dist < 500) { |
480 | if (dist < 500) |
|
|
481 | { |
356 | dist=(dist+25)/50; |
482 | dist = (dist + 25) / 50; |
357 | return dist*50; |
483 | return dist * 50; |
358 | } |
484 | } |
359 | if (dist < 1000) { |
485 | if (dist < 1000) |
|
|
486 | { |
360 | dist=(dist+50)/100; |
487 | dist = (dist + 50) / 100; |
361 | return dist*100; |
488 | return dist * 100; |
362 | } |
489 | } |
363 | if (dist < 5000) { |
490 | if (dist < 5000) |
|
|
491 | { |
364 | dist=(dist+50)/100; |
492 | dist = (dist + 50) / 100; |
365 | return dist*100; |
493 | return dist * 100; |
366 | } |
494 | } |
367 | if (dist < 100000) { |
495 | if (dist < 100000) |
|
|
496 | { |
368 | dist=(dist+500)/1000; |
497 | dist = (dist + 500) / 1000; |
369 | return dist*1000; |
498 | return dist * 1000; |
370 | } |
499 | } |
371 | dist=(dist+5000)/10000; |
500 | dist = (dist + 5000) / 10000; |
372 | return dist*10000; |
501 | return dist * 10000; |
373 | } |
502 | } |
374 | |
503 | |
375 | static int |
|
|
376 | round_for_vocabulary(int vocabulary, int dist, int factor) |
504 | static int round_for_vocabulary(int vocabulary, int dist, int factor) |
377 | { |
505 | { |
378 | if (!(vocabulary & 256)) { |
506 | if (!(vocabulary & 256)) |
|
|
507 | { |
379 | if (factor != 1) |
508 | if (factor != 1) |
380 | dist=(dist+factor/2)/factor; |
509 | dist = (dist + factor / 2) / factor; |
|
|
510 | } |
381 | } else |
511 | else |
382 | factor=1; |
512 | factor = 1; |
383 | if (!(vocabulary & 255)) { |
513 | if (!(vocabulary & 255)) |
|
|
514 | { |
384 | int i=0,d=0,m=0; |
515 | int i = 0, d = 0, m = 0; |
385 | while (distances[i] > 0) { |
516 | while (distances[i] > 0) |
|
|
517 | { |
386 | if (!i || abs(distances[i]-dist) <= d) { |
518 | if (!i || abs(distances[i] - dist) <= d) |
|
|
519 | { |
387 | d=abs(distances[i]-dist); |
520 | d = abs(distances[i] - dist); |
388 | m=i; |
521 | m = i; |
389 | } |
522 | } |
390 | if (distances[i] > dist) |
523 | if (distances[i] > dist) |
391 | break; |
524 | break; |
392 | i++; |
525 | i++; |
393 | } |
526 | } |
394 | dbg(0,"converted %d to %d with factor %d\n",dist,distances[m],factor); |
527 | // dbg(0, "converted %d to %d with factor %d\n", dist, distances[m], factor); |
395 | dist=distances[m]; |
528 | dist = distances[m]; |
396 | } |
529 | } |
397 | return dist*factor; |
530 | return dist * factor; |
398 | } |
531 | } |
399 | |
532 | |
400 | static int |
|
|
401 | vocabulary_last(int vocabulary) |
533 | static int vocabulary_last(int vocabulary) |
402 | { |
534 | { |
403 | int i=0; |
535 | int i = 0; |
404 | if (vocabulary == 65535) |
536 | if (vocabulary == 65535) |
405 | return 1000; |
537 | return 1000; |
406 | while (distances[i] > 0) |
538 | while (distances[i] > 0) |
407 | i++; |
539 | i++; |
408 | return distances[i-1]; |
540 | return distances[i - 1]; |
409 | } |
541 | } |
410 | |
542 | |
411 | static char * |
543 | static char * |
412 | get_distance(struct navigation *nav, int dist, enum attr_type type, int is_length) |
544 | get_distance(struct navigation *nav, int dist, enum attr_type type, |
|
|
545 | int is_length) |
413 | { |
546 | { |
414 | int imperial=0,vocabulary=65535; |
547 | int imperial = 0, vocabulary = 65535; |
415 | struct attr attr; |
548 | struct attr attr; |
416 | |
549 | |
417 | if (type == attr_navigation_long) { |
550 | if (type == attr_navigation_long) |
|
|
551 | { |
418 | if (is_length) |
552 | if (is_length) |
|
|
553 | { |
|
|
554 | #ifdef HAVE_API_ANDROID |
|
|
555 | android_send_generic_text(1,"+*#O:%d m\n"); |
|
|
556 | #endif |
419 | return g_strdup_printf(_("%d m"), dist); |
557 | return g_strdup_printf(_("%d m"), dist); |
|
|
558 | } |
420 | else |
559 | else |
|
|
560 | { |
|
|
561 | #ifdef HAVE_API_ANDROID |
|
|
562 | android_send_generic_text(1,"+*#O:in %d m\n"); |
|
|
563 | #endif |
421 | return g_strdup_printf(_("in %d m"), dist); |
564 | return g_strdup_printf(_("in %d m"), dist); |
|
|
565 | } |
422 | } |
566 | } |
423 | if (navit_get_attr(nav->navit, attr_imperial, &attr, NULL)) |
567 | if (navit_get_attr(nav->navit, attr_imperial, &attr, NULL)) |
424 | imperial=attr.u.num; |
568 | imperial = attr.u.num; |
425 | if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_distances, &attr, NULL)) |
569 | if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_distances, |
|
|
570 | &attr, NULL)) |
426 | vocabulary=attr.u.num; |
571 | vocabulary = attr.u.num; |
427 | if (imperial) { |
572 | if (imperial) |
|
|
573 | { |
428 | if (dist*FEET_PER_METER < vocabulary_last(vocabulary)) { |
574 | if (dist * FEET_PER_METER < vocabulary_last(vocabulary)) |
|
|
575 | { |
429 | dist=round_for_vocabulary(vocabulary, dist*FEET_PER_METER, 1); |
576 | dist = round_for_vocabulary(vocabulary, dist * FEET_PER_METER, 1); |
430 | if (is_length) |
577 | if (is_length) |
|
|
578 | { |
|
|
579 | #ifdef HAVE_API_ANDROID |
|
|
580 | android_send_generic_text(1,"+*#O:%d feet\n"); |
|
|
581 | #endif |
431 | return g_strdup_printf(_("%d feet"), dist); |
582 | return g_strdup_printf(_("%d feet"), dist); |
|
|
583 | } |
432 | else |
584 | else |
|
|
585 | { |
|
|
586 | #ifdef HAVE_API_ANDROID |
|
|
587 | android_send_generic_text(1,"+*#O:in %d feet\n"); |
|
|
588 | #endif |
433 | return g_strdup_printf(_("in %d feet"), dist); |
589 | return g_strdup_printf(_("in %d feet"), dist); |
434 | } |
590 | } |
435 | } else { |
591 | } |
|
|
592 | } |
|
|
593 | else |
|
|
594 | { |
436 | if (dist < vocabulary_last(vocabulary)) { |
595 | if (dist < vocabulary_last(vocabulary)) |
|
|
596 | { |
437 | dist=round_for_vocabulary(vocabulary, dist, 1); |
597 | dist = round_for_vocabulary(vocabulary, dist, 1); |
438 | if (is_length) |
598 | if (is_length) |
|
|
599 | { |
|
|
600 | #ifdef HAVE_API_ANDROID |
|
|
601 | android_send_generic_text(1,"+*#O:%d meters\n"); |
|
|
602 | gchar* xy=g_strdup_printf("+*#1:%d\n", dist); |
|
|
603 | android_send_generic_text(1,xy); |
|
|
604 | g_free(xy); |
|
|
605 | #endif |
439 | return g_strdup_printf(_("%d meters"), dist); |
606 | return g_strdup_printf(_("%d meters"), dist); |
|
|
607 | } |
440 | else |
608 | else |
|
|
609 | { |
|
|
610 | #ifdef HAVE_API_ANDROID |
|
|
611 | android_send_generic_text(1,"+*#O:in %d meters\n"); |
|
|
612 | gchar* xy=g_strdup_printf("+*#1:%d\n", dist); |
|
|
613 | android_send_generic_text(1,xy); |
|
|
614 | g_free(xy); |
|
|
615 | #endif |
441 | return g_strdup_printf(_("in %d meters"), dist); |
616 | return g_strdup_printf(_("in %d meters"), dist); |
|
|
617 | } |
442 | } |
618 | } |
443 | } |
619 | } |
444 | if (imperial) |
620 | if (imperial) |
445 | dist=round_for_vocabulary(vocabulary, dist*FEET_PER_METER*1000/FEET_PER_MILE, 1000); |
621 | { |
|
|
622 | dist = round_for_vocabulary(vocabulary, |
|
|
623 | dist * FEET_PER_METER * 1000 / FEET_PER_MILE, 1000); |
|
|
624 | } |
446 | else |
625 | else |
|
|
626 | { |
447 | dist=round_for_vocabulary(vocabulary, dist, 1000); |
627 | dist = round_for_vocabulary(vocabulary, dist, 1000); |
|
|
628 | } |
|
|
629 | |
448 | if (dist < 5000) { |
630 | if (dist < 5000) |
|
|
631 | { |
449 | int rem=(dist/100)%10; |
632 | int rem = (dist / 100) % 10; |
450 | if (rem) { |
633 | if (rem) |
|
|
634 | { |
451 | if (imperial) { |
635 | if (imperial) |
|
|
636 | { |
452 | if (is_length) |
637 | if (is_length) |
|
|
638 | { |
|
|
639 | #ifdef HAVE_API_ANDROID |
|
|
640 | android_send_generic_text(1,"+*#O:%d.%d miles\n"); |
|
|
641 | #endif |
453 | return g_strdup_printf(_("%d.%d miles"), dist/1000, rem); |
642 | return g_strdup_printf(_("%d.%d miles"), dist / 1000, rem); |
|
|
643 | } |
454 | else |
644 | else |
|
|
645 | { |
|
|
646 | #ifdef HAVE_API_ANDROID |
|
|
647 | android_send_generic_text(1,"+*#O:in %d.%d miles\n"); |
|
|
648 | #endif |
455 | return g_strdup_printf(_("in %d.%d miles"), dist/1000, rem); |
649 | return g_strdup_printf(_("in %d.%d miles"), dist / 1000, |
|
|
650 | rem); |
|
|
651 | } |
|
|
652 | } |
456 | } else { |
653 | else |
|
|
654 | { |
457 | if (is_length) |
655 | if (is_length) |
|
|
656 | { |
|
|
657 | #ifdef HAVE_API_ANDROID |
|
|
658 | android_send_generic_text(1,"+*#O:%d.%d kilometers\n"); |
|
|
659 | #endif |
458 | return g_strdup_printf(_("%d.%d kilometers"), dist/1000, rem); |
660 | return g_strdup_printf(_("%d.%d kilometers"), dist / 1000, |
|
|
661 | rem); |
|
|
662 | } |
459 | else |
663 | else |
|
|
664 | { |
|
|
665 | #ifdef HAVE_API_ANDROID |
|
|
666 | android_send_generic_text(1,"+*#O:in %d.%d kilometers\n"); |
|
|
667 | #endif |
460 | return g_strdup_printf(_("in %d.%d kilometers"), dist/1000, rem); |
668 | return g_strdup_printf(_("in %d.%d kilometers"), |
|
|
669 | dist / 1000, rem); |
461 | } |
670 | } |
462 | } |
671 | } |
463 | } |
672 | } |
|
|
673 | } |
464 | if (imperial) { |
674 | if (imperial) |
|
|
675 | { |
465 | if (is_length) |
676 | if (is_length) |
|
|
677 | return g_strdup_printf( |
466 | return g_strdup_printf(ngettext("one mile","%d miles", dist/1000), dist/1000); |
678 | ngettext("one mile", "%d miles", dist / 1000), dist / 1000); |
467 | else |
679 | else |
468 | return g_strdup_printf(ngettext("in one mile","in %d miles", dist/1000), dist/1000); |
680 | return g_strdup_printf( |
469 | } else { |
681 | ngettext("in one mile", "in %d miles", dist / 1000), |
|
|
682 | dist / 1000); |
|
|
683 | } |
|
|
684 | else |
|
|
685 | { |
470 | if (is_length) |
686 | if (is_length) |
471 | return g_strdup_printf(ngettext("one kilometer","%d kilometers", dist/1000), dist/1000); |
687 | { |
|
|
688 | #ifdef HAVE_API_ANDROID |
|
|
689 | android_send_generic_text(1,"+*#O:one kilometer|%d kilometers\n"); |
|
|
690 | #endif |
|
|
691 | return g_strdup_printf( |
|
|
692 | ngettext("one kilometer", "%d kilometers", dist / 1000), |
|
|
693 | dist / 1000); |
|
|
694 | } |
472 | else |
695 | else |
473 | return g_strdup_printf(ngettext("in one kilometer","in %d kilometers", dist/1000), dist/1000); |
696 | { |
|
|
697 | #ifdef HAVE_API_ANDROID |
|
|
698 | android_send_generic_text(1,"+*#O:in one kilometer|in %d kilometers\n"); |
|
|
699 | #endif |
|
|
700 | return g_strdup_printf( |
|
|
701 | ngettext("in one kilometer", "in %d kilometers", |
|
|
702 | dist / 1000), dist / 1000); |
474 | } |
703 | } |
|
|
704 | } |
475 | } |
705 | } |
476 | |
|
|
477 | |
706 | |
478 | /** |
707 | /** |
479 | * @brief This calculates the angle with which an item starts or ends |
708 | * @brief This calculates the angle with which an item starts or ends |
480 | * |
709 | * |
481 | * This function can be used to get the angle an item (from a route graph map) |
710 | * This function can be used to get the angle an item (from a route graph map) |
… | |
… | |
484 | * |
713 | * |
485 | * This is meant to be used with items from a route graph map |
714 | * This is meant to be used with items from a route graph map |
486 | * With other items this will probably not be optimal... |
715 | * With other items this will probably not be optimal... |
487 | * |
716 | * |
488 | * @param w The way which should be calculated |
717 | * @param w The way which should be calculated |
489 | */ |
718 | */ |
490 | static void |
|
|
491 | calculate_angle(struct navigation_way *w) |
719 | static void calculate_angle(struct navigation_way *w) |
492 | { |
720 | { |
493 | struct coord cbuf[2]; |
721 | struct coord cbuf[2]; |
494 | struct item *ritem; // the "real" item |
722 | struct item *ritem; // the "real" item |
495 | struct coord c; |
723 | struct coord c; |
496 | struct map_rect *mr; |
724 | struct map_rect *mr; |
497 | struct attr attr; |
725 | struct attr attr; |
498 | |
726 | |
499 | w->angle2=361; |
727 | w->angle2 = 361; |
500 | mr = map_rect_new(w->item.map, NULL); |
728 | mr = map_rect_new(w->item.map, NULL); |
501 | if (!mr) |
729 | if (!mr) |
502 | return; |
730 | return; |
503 | |
731 | |
504 | ritem = map_rect_get_item_byid(mr, w->item.id_hi, w->item.id_lo); |
732 | ritem = map_rect_get_item_byid(mr, w->item.id_hi, w->item.id_lo); |
505 | if (!ritem) { |
733 | if (!ritem) |
|
|
734 | { |
506 | dbg(1,"Item from segment not found on map!\n"); |
735 | dbg(1, "Item from segment not found on map!\n"); |
507 | map_rect_destroy(mr); |
736 | map_rect_destroy(mr); |
508 | return; |
737 | return; |
509 | } |
738 | } |
510 | |
739 | |
511 | if (ritem->type < type_line || ritem->type >= type_area) { |
740 | if (ritem->type < type_line || ritem->type >= type_area) |
|
|
741 | { |
512 | map_rect_destroy(mr); |
742 | map_rect_destroy(mr); |
513 | return; |
743 | return; |
514 | } |
744 | } |
515 | if (item_attr_get(ritem, attr_flags, &attr)) |
745 | if (item_attr_get(ritem, attr_flags, &attr)) |
516 | w->flags=attr.u.num; |
746 | w->flags = attr.u.num; |
517 | else |
747 | else |
518 | w->flags=0; |
748 | w->flags = 0; |
519 | if (item_attr_get(ritem, attr_street_name, &attr)) |
749 | if (item_attr_get(ritem, attr_street_name, &attr)) |
520 | w->name1=map_convert_string(ritem->map,attr.u.str); |
750 | w->name1 = map_convert_string(ritem->map, attr.u.str); |
521 | else |
751 | else |
522 | w->name1=NULL; |
752 | w->name1 = NULL; |
523 | if (item_attr_get(ritem, attr_street_name_systematic, &attr)) |
753 | if (item_attr_get(ritem, attr_street_name_systematic, &attr)) |
524 | w->name2=map_convert_string(ritem->map,attr.u.str); |
754 | w->name2 = map_convert_string(ritem->map, attr.u.str); |
525 | else |
755 | else |
526 | w->name2=NULL; |
756 | w->name2 = NULL; |
527 | |
757 | |
528 | if (w->dir < 0) { |
758 | if (w->dir < 0) |
|
|
759 | { |
529 | if (item_coord_get(ritem, cbuf, 2) != 2) { |
760 | if (item_coord_get(ritem, cbuf, 2) != 2) |
|
|
761 | { |
|
|
762 | dbg(1, |
530 | dbg(1,"Using calculate_angle() with a less-than-two-coords-item?\n"); |
763 | "Using calculate_angle() with a less-than-two-coords-item?\n"); |
531 | map_rect_destroy(mr); |
764 | map_rect_destroy(mr); |
532 | return; |
765 | return; |
533 | } |
766 | } |
534 | |
767 | |
535 | while (item_coord_get(ritem, &c, 1)) { |
768 | while (item_coord_get(ritem, &c, 1)) |
|
|
769 | { |
536 | cbuf[0] = cbuf[1]; |
770 | cbuf[0] = cbuf[1]; |
537 | cbuf[1] = c; |
771 | cbuf[1] = c; |
538 | } |
772 | } |
539 | |
773 | |
540 | } else { |
774 | } |
|
|
775 | else |
|
|
776 | { |
541 | if (item_coord_get(ritem, cbuf, 2) != 2) { |
777 | if (item_coord_get(ritem, cbuf, 2) != 2) |
|
|
778 | { |
|
|
779 | dbg(1, |
542 | dbg(1,"Using calculate_angle() with a less-than-two-coords-item?\n"); |
780 | "Using calculate_angle() with a less-than-two-coords-item?\n"); |
543 | map_rect_destroy(mr); |
781 | map_rect_destroy(mr); |
544 | return; |
782 | return; |
545 | } |
783 | } |
546 | c = cbuf[0]; |
784 | c = cbuf[0]; |
547 | cbuf[0] = cbuf[1]; |
785 | cbuf[0] = cbuf[1]; |
548 | cbuf[1] = c; |
786 | cbuf[1] = c; |
549 | } |
787 | } |
550 | |
788 | |
551 | map_rect_destroy(mr); |
789 | map_rect_destroy(mr); |
552 | |
790 | |
553 | w->angle2=road_angle(&cbuf[1],&cbuf[0],0); |
791 | w->angle2 = road_angle(&cbuf[1], &cbuf[0], 0); |
554 | } |
792 | } |
555 | |
793 | |
556 | /** |
794 | /** |
557 | * @brief Returns the time (in seconds) one will drive between two navigation items |
795 | * @brief Returns the time (in seconds) one will drive between two navigation items |
558 | * |
796 | * |
… | |
… | |
561 | * |
799 | * |
562 | * @param from The first item |
800 | * @param from The first item |
563 | * @param to The last item |
801 | * @param to The last item |
564 | * @return The travel time in seconds, or -1 on error |
802 | * @return The travel time in seconds, or -1 on error |
565 | */ |
803 | */ |
566 | static int |
804 | static int navigation_time(struct navigation_itm *from, |
567 | navigation_time(struct navigation_itm *from, struct navigation_itm *to) |
805 | struct navigation_itm *to) |
568 | { |
806 | { |
569 | struct navigation_itm *cur; |
807 | struct navigation_itm *cur; |
570 | int time; |
808 | int time; |
571 | |
809 | |
572 | time = 0; |
810 | time = 0; |
573 | cur = from; |
811 | cur = from; |
574 | while (cur) { |
812 | while (cur) |
|
|
813 | { |
575 | time += cur->time; |
814 | time += cur->time; |
576 | |
815 | |
577 | if (cur == to) { |
816 | if (cur == to) |
|
|
817 | { |
578 | break; |
818 | break; |
579 | } |
819 | } |
580 | cur = cur->next; |
820 | cur = cur->next; |
581 | } |
821 | } |
582 | |
822 | |
583 | if (!cur) { |
823 | if (!cur) |
|
|
824 | { |
584 | return -1; |
825 | return -1; |
585 | } |
826 | } |
586 | |
827 | |
587 | return time; |
828 | return time; |
588 | } |
829 | } |
… | |
… | |
590 | /** |
831 | /** |
591 | * @brief Clears the ways one can drive from itm |
832 | * @brief Clears the ways one can drive from itm |
592 | * |
833 | * |
593 | * @param itm The item that should have its ways cleared |
834 | * @param itm The item that should have its ways cleared |
594 | */ |
835 | */ |
595 | static void |
|
|
596 | navigation_itm_ways_clear(struct navigation_itm *itm) |
836 | static void navigation_itm_ways_clear(struct navigation_itm *itm) |
597 | { |
837 | { |
598 | struct navigation_way *c,*n; |
838 | struct navigation_way *c, *n; |
599 | |
839 | |
600 | c = itm->way.next; |
840 | c = itm->way.next; |
601 | while (c) { |
841 | while (c) |
|
|
842 | { |
602 | n = c->next; |
843 | n = c->next; |
603 | map_convert_free(c->name1); |
844 | map_convert_free(c->name1); |
604 | map_convert_free(c->name2); |
845 | map_convert_free(c->name2); |
605 | g_free(c); |
846 | g_free(c); |
606 | c = n; |
847 | c = n; |
… | |
… | |
616 | * and the next navigation item are excluded. |
857 | * and the next navigation item are excluded. |
617 | * |
858 | * |
618 | * @param itm The item that should be updated |
859 | * @param itm The item that should be updated |
619 | * @param graph_map The route graph's map that these items are on |
860 | * @param graph_map The route graph's map that these items are on |
620 | */ |
861 | */ |
621 | static void |
|
|
622 | navigation_itm_ways_update(struct navigation_itm *itm, struct map *graph_map) |
862 | static void navigation_itm_ways_update(struct navigation_itm *itm, |
|
|
863 | struct map *graph_map) |
623 | { |
864 | { |
624 | struct map_selection coord_sel; |
865 | struct map_selection coord_sel; |
625 | struct map_rect *g_rect; // Contains a map rectangle from the route graph's map |
866 | struct map_rect *g_rect; // Contains a map rectangle from the route graph's map |
626 | struct item *i,*sitem; |
867 | struct item *i, *sitem; |
627 | struct attr sitem_attr,direction_attr; |
868 | struct attr sitem_attr, direction_attr; |
628 | struct navigation_way *w,*l; |
869 | struct navigation_way *w, *l; |
629 | |
870 | |
630 | navigation_itm_ways_clear(itm); |
871 | navigation_itm_ways_clear(itm); |
631 | |
872 | |
632 | // These values cause the code in route.c to get us only the route graph point and connected segments |
873 | // These values cause the code in route.c to get us only the route graph point and connected segments |
633 | coord_sel.next = NULL; |
874 | coord_sel.next = NULL; |
634 | coord_sel.u.c_rect.lu = itm->start; |
875 | coord_sel.u.c_rect.lu = itm->start; |
635 | coord_sel.u.c_rect.rl = itm->start; |
876 | coord_sel.u.c_rect.rl = itm->start; |
636 | // the selection's order is ignored |
877 | // the selection's order is ignored |
637 | |
878 | |
638 | g_rect = map_rect_new(graph_map, &coord_sel); |
879 | g_rect = map_rect_new(graph_map, &coord_sel); |
639 | |
880 | |
640 | i = map_rect_get_item(g_rect); |
881 | i = map_rect_get_item(g_rect); |
641 | if (!i || i->type != type_rg_point) { // probably offroad? |
882 | if (!i || i->type != type_rg_point) |
|
|
883 | { // probably offroad? |
642 | return ; |
884 | return; |
643 | } |
885 | } |
644 | |
886 | |
645 | w = NULL; |
887 | w = NULL; |
646 | |
888 | |
647 | while (1) { |
889 | while (1) |
|
|
890 | { |
648 | i = map_rect_get_item(g_rect); |
891 | i = map_rect_get_item(g_rect); |
649 | |
892 | |
650 | if (!i) { |
893 | if (!i) |
|
|
894 | { |
651 | break; |
895 | break; |
652 | } |
896 | } |
653 | |
897 | |
654 | if (i->type != type_rg_segment) { |
898 | if (i->type != type_rg_segment) |
|
|
899 | { |
655 | continue; |
900 | continue; |
656 | } |
901 | } |
657 | |
902 | |
658 | if (!item_attr_get(i,attr_street_item,&sitem_attr)) { |
903 | if (!item_attr_get(i, attr_street_item, &sitem_attr)) |
|
|
904 | { |
|
|
905 | dbg(1, |
659 | dbg(1, "Got no street item for route graph item in entering_straight()\n"); |
906 | "Got no street item for route graph item in entering_straight()\n"); |
660 | continue; |
907 | continue; |
661 | } |
908 | } |
662 | |
909 | |
663 | if (!item_attr_get(i,attr_direction,&direction_attr)) { |
910 | if (!item_attr_get(i, attr_direction, &direction_attr)) |
|
|
911 | { |
664 | continue; |
912 | continue; |
665 | } |
913 | } |
666 | |
914 | |
667 | sitem = sitem_attr.u.item; |
915 | sitem = sitem_attr.u.item; |
668 | if (sitem->type == type_street_turn_restriction_no || sitem->type == type_street_turn_restriction_only) |
916 | if (sitem->type == type_street_turn_restriction_no || sitem->type |
|
|
917 | == type_street_turn_restriction_only) |
669 | continue; |
918 | continue; |
670 | |
919 | |
671 | if (item_is_equal(itm->way.item,*sitem) || ((itm->prev) && item_is_equal(itm->prev->way.item,*sitem))) { |
920 | if (item_is_equal(itm->way.item, *sitem) || ((itm->prev) |
|
|
921 | && item_is_equal(itm->prev->way.item, *sitem))) |
|
|
922 | { |
672 | continue; |
923 | continue; |
673 | } |
924 | } |
674 | |
925 | |
675 | l = w; |
926 | l = w; |
676 | w = g_new(struct navigation_way, 1); |
927 | w = g_new(struct navigation_way, 1); |
… | |
… | |
679 | w->next = l; |
930 | w->next = l; |
680 | calculate_angle(w); |
931 | calculate_angle(w); |
681 | } |
932 | } |
682 | |
933 | |
683 | map_rect_destroy(g_rect); |
934 | map_rect_destroy(g_rect); |
684 | |
935 | |
685 | itm->way.next = w; |
936 | itm->way.next = w; |
686 | } |
937 | } |
687 | |
938 | |
688 | static void |
939 | static void navigation_destroy_itms_cmds(struct navigation *this_, |
689 | navigation_destroy_itms_cmds(struct navigation *this_, struct navigation_itm *end) |
940 | struct navigation_itm *end) |
690 | { |
941 | { |
691 | struct navigation_itm *itm; |
942 | struct navigation_itm *itm; |
692 | struct navigation_command *cmd; |
943 | struct navigation_command *cmd; |
693 | dbg(2,"enter this_=%p this_->first=%p this_->cmd_first=%p end=%p\n", this_, this_->first, this_->cmd_first, end); |
944 | // dbg(2, "enter this_=%p this_->first=%p this_->cmd_first=%p end=%p\n", this_, this_->first, this_->cmd_first, end); |
694 | if (this_->cmd_first) |
945 | if (this_->cmd_first) |
|
|
946 | { |
695 | dbg(2,"this_->cmd_first->itm=%p\n", this_->cmd_first->itm); |
947 | // dbg(2, "this_->cmd_first->itm=%p\n", this_->cmd_first->itm); |
|
|
948 | } |
696 | while (this_->first && this_->first != end) { |
949 | while (this_->first && this_->first != end) |
|
|
950 | { |
697 | itm=this_->first; |
951 | itm = this_->first; |
698 | dbg(3,"destroying %p\n", itm); |
952 | // dbg(3, "destroying %p\n", itm); |
699 | item_hash_remove(this_->hash, &itm->way.item); |
953 | item_hash_remove(this_->hash, &itm->way.item); |
700 | this_->first=itm->next; |
954 | this_->first = itm->next; |
701 | if (this_->first) |
955 | if (this_->first) |
702 | this_->first->prev=NULL; |
956 | this_->first->prev = NULL; |
703 | if (this_->cmd_first && this_->cmd_first->itm == itm->next) { |
957 | if (this_->cmd_first && this_->cmd_first->itm == itm->next) |
|
|
958 | { |
704 | cmd=this_->cmd_first; |
959 | cmd = this_->cmd_first; |
705 | this_->cmd_first=cmd->next; |
960 | this_->cmd_first = cmd->next; |
706 | if (cmd->next) { |
961 | if (cmd->next) |
|
|
962 | { |
707 | cmd->next->prev = NULL; |
963 | cmd->next->prev = NULL; |
708 | } |
964 | } |
709 | g_free(cmd); |
965 | g_free(cmd); |
710 | } |
966 | } |
711 | map_convert_free(itm->way.name1); |
967 | map_convert_free(itm->way.name1); |
712 | map_convert_free(itm->way.name2); |
968 | map_convert_free(itm->way.name2); |
713 | navigation_itm_ways_clear(itm); |
969 | navigation_itm_ways_clear(itm); |
714 | g_free(itm); |
970 | g_free(itm); |
715 | } |
971 | } |
716 | if (! this_->first) |
972 | if (!this_->first) |
717 | this_->last=NULL; |
973 | this_->last = NULL; |
718 | if (! this_->first && end) |
974 | if (!this_->first && end) |
|
|
975 | { |
719 | dbg(0,"end wrong\n"); |
976 | // dbg(0, "end wrong\n"); |
|
|
977 | } |
720 | dbg(2,"ret this_->first=%p this_->cmd_first=%p\n",this_->first, this_->cmd_first); |
978 | // dbg(2, "ret this_->first=%p this_->cmd_first=%p\n", this_->first, this_->cmd_first); |
721 | } |
979 | } |
722 | |
980 | |
723 | static void |
|
|
724 | navigation_itm_update(struct navigation_itm *itm, struct item *ritem) |
981 | static void navigation_itm_update(struct navigation_itm *itm, |
|
|
982 | struct item *ritem) |
725 | { |
983 | { |
726 | struct attr length, time, speed; |
984 | struct attr length, time, speed; |
727 | |
985 | |
728 | if (! item_attr_get(ritem, attr_length, &length)) { |
986 | if (!item_attr_get(ritem, attr_length, &length)) |
|
|
987 | { |
729 | dbg(0,"no length\n"); |
988 | // dbg(0, "no length\n"); |
730 | return; |
989 | return; |
731 | } |
990 | } |
732 | if (! item_attr_get(ritem, attr_time, &time)) { |
991 | if (!item_attr_get(ritem, attr_time, &time)) |
|
|
992 | { |
733 | dbg(0,"no time\n"); |
993 | // dbg(0, "no time\n"); |
734 | return; |
994 | return; |
735 | } |
995 | } |
736 | if (! item_attr_get(ritem, attr_speed, &speed)) { |
996 | if (!item_attr_get(ritem, attr_speed, &speed)) |
|
|
997 | { |
737 | dbg(0,"no time\n"); |
998 | // dbg(0, "no time\n"); |
738 | return; |
999 | return; |
739 | } |
1000 | } |
740 | |
1001 | |
741 | dbg(1,"length=%d time=%d speed=%d\n", length.u.num, time.u.num, speed.u.num); |
1002 | // dbg(1, "length=%d time=%d speed=%d\n", length.u.num, time.u.num, speed.u.num); |
742 | itm->length=length.u.num; |
1003 | itm->length = length.u.num; |
743 | itm->time=time.u.num; |
1004 | itm->time = time.u.num; |
744 | itm->speed=speed.u.num; |
1005 | itm->speed = speed.u.num; |
745 | } |
1006 | } |
746 | |
1007 | |
747 | /** |
1008 | /** |
748 | * @brief This check if an item is part of a roundabout |
1009 | * @brief This check if an item is part of a roundabout |
749 | * |
1010 | * |
750 | * @param itm The item to be checked |
1011 | * @param itm The item to be checked |
751 | * @return True if the item is part of a roundabout |
1012 | * @return True if the item is part of a roundabout |
752 | */ |
1013 | */ |
753 | static int |
|
|
754 | check_roundabout(struct navigation_itm *itm, struct map *graph_map) |
1014 | static int check_roundabout(struct navigation_itm *itm, struct map *graph_map) |
755 | { |
1015 | { |
756 | struct map_selection coord_sel; |
1016 | struct map_selection coord_sel; |
757 | struct map_rect *g_rect; // Contains a map rectangle from the route graph's map |
1017 | struct map_rect *g_rect; // Contains a map rectangle from the route graph's map |
758 | struct item *i,*sitem; |
1018 | struct item *i, *sitem; |
759 | struct attr sitem_attr,flags_attr; |
1019 | struct attr sitem_attr, flags_attr; |
760 | |
1020 | |
761 | // These values cause the code in route.c to get us only the route graph point and connected segments |
1021 | // These values cause the code in route.c to get us only the route graph point and connected segments |
762 | coord_sel.next = NULL; |
1022 | coord_sel.next = NULL; |
763 | coord_sel.u.c_rect.lu = itm->start; |
1023 | coord_sel.u.c_rect.lu = itm->start; |
764 | coord_sel.u.c_rect.rl = itm->start; |
1024 | coord_sel.u.c_rect.rl = itm->start; |
765 | // the selection's order is ignored |
1025 | // the selection's order is ignored |
766 | |
1026 | |
767 | g_rect = map_rect_new(graph_map, &coord_sel); |
1027 | g_rect = map_rect_new(graph_map, &coord_sel); |
768 | |
1028 | |
769 | i = map_rect_get_item(g_rect); |
1029 | i = map_rect_get_item(g_rect); |
770 | if (!i || i->type != type_rg_point) { // probably offroad? |
1030 | if (!i || i->type != type_rg_point) |
|
|
1031 | { // probably offroad? |
771 | map_rect_destroy(g_rect); |
1032 | map_rect_destroy(g_rect); |
772 | return 0; |
1033 | return 0; |
773 | } |
1034 | } |
774 | |
1035 | |
775 | while (1) { |
1036 | while (1) |
|
|
1037 | { |
776 | i = map_rect_get_item(g_rect); |
1038 | i = map_rect_get_item(g_rect); |
777 | |
1039 | |
778 | if (!i) { |
1040 | if (!i) |
|
|
1041 | { |
779 | break; |
1042 | break; |
780 | } |
1043 | } |
781 | |
1044 | |
782 | if (i->type != type_rg_segment) { |
1045 | if (i->type != type_rg_segment) |
|
|
1046 | { |
783 | continue; |
1047 | continue; |
784 | } |
1048 | } |
785 | |
1049 | |
786 | if (!item_attr_get(i,attr_street_item,&sitem_attr)) { |
1050 | if (!item_attr_get(i, attr_street_item, &sitem_attr)) |
|
|
1051 | { |
787 | continue; |
1052 | continue; |
788 | } |
1053 | } |
789 | |
1054 | |
790 | sitem = sitem_attr.u.item; |
1055 | sitem = sitem_attr.u.item; |
791 | if (item_is_equal(itm->way.item,*sitem)) { |
1056 | if (item_is_equal(itm->way.item, *sitem)) |
|
|
1057 | { |
792 | if (item_attr_get(i,attr_flags,&flags_attr) && (flags_attr.u.num & AF_ROUNDABOUT)) { |
1058 | if (item_attr_get(i, attr_flags, &flags_attr) && (flags_attr.u.num |
|
|
1059 | & AF_ROUNDABOUT)) |
|
|
1060 | { |
793 | map_rect_destroy(g_rect); |
1061 | map_rect_destroy(g_rect); |
794 | return 1; |
1062 | return 1; |
795 | } |
1063 | } |
796 | } |
1064 | } |
797 | } |
1065 | } |
… | |
… | |
802 | |
1070 | |
803 | static struct navigation_itm * |
1071 | static struct navigation_itm * |
804 | navigation_itm_new(struct navigation *this_, struct item *ritem) |
1072 | navigation_itm_new(struct navigation *this_, struct item *ritem) |
805 | { |
1073 | { |
806 | struct navigation_itm *ret=g_new0(struct navigation_itm, 1); |
1074 | struct navigation_itm *ret=g_new0(struct navigation_itm, 1); |
807 | int i=0; |
1075 | int i = 0; |
808 | struct item *sitem; |
1076 | struct item *sitem; |
809 | struct map *graph_map = NULL; |
1077 | struct map *graph_map = NULL; |
810 | struct attr street_item,direction,route_attr; |
1078 | struct attr street_item, direction, route_attr; |
811 | struct map_rect *mr; |
1079 | struct map_rect *mr; |
812 | struct attr attr; |
1080 | struct attr attr; |
813 | struct coord c[5]; |
1081 | struct coord c[5]; |
814 | |
1082 | |
815 | if (ritem) { |
1083 | if (ritem) |
|
|
1084 | { |
816 | ret->streetname_told=0; |
1085 | ret->streetname_told = 0; |
817 | if (! item_attr_get(ritem, attr_street_item, &street_item)) { |
1086 | if (!item_attr_get(ritem, attr_street_item, &street_item)) |
|
|
1087 | { |
818 | dbg(1, "no street item\n"); |
1088 | //dbg(1, "no street item\n"); |
819 | g_free(ret); |
1089 | g_free(ret); |
820 | ret = NULL; |
1090 | ret = NULL; |
821 | return ret; |
1091 | return ret; |
822 | } |
1092 | } |
823 | if (item_attr_get(ritem, attr_direction, &direction)) |
1093 | if (item_attr_get(ritem, attr_direction, &direction)) |
824 | ret->way.dir=direction.u.num; |
1094 | ret->way.dir = direction.u.num; |
825 | else |
1095 | else |
826 | ret->way.dir=0; |
1096 | ret->way.dir = 0; |
827 | |
1097 | |
828 | sitem=street_item.u.item; |
1098 | sitem = street_item.u.item; |
829 | ret->way.item=*sitem; |
1099 | ret->way.item = *sitem; |
830 | item_hash_insert(this_->hash, sitem, ret); |
1100 | item_hash_insert(this_->hash, sitem, ret); |
831 | mr=map_rect_new(sitem->map, NULL); |
1101 | mr = map_rect_new(sitem->map, NULL); |
832 | if (! (sitem=map_rect_get_item_byid(mr, sitem->id_hi, sitem->id_lo))) |
1102 | if (!(sitem = map_rect_get_item_byid(mr, sitem->id_hi, sitem->id_lo))) |
833 | return NULL; |
1103 | return NULL; |
834 | if (item_attr_get(sitem, attr_street_name, &attr)) |
1104 | if (item_attr_get(sitem, attr_street_name, &attr)) |
835 | ret->way.name1=map_convert_string(sitem->map,attr.u.str); |
1105 | ret->way.name1 = map_convert_string(sitem->map, attr.u.str); |
836 | if (item_attr_get(sitem, attr_street_name_systematic, &attr)) |
1106 | if (item_attr_get(sitem, attr_street_name_systematic, &attr)) |
837 | ret->way.name2=map_convert_string(sitem->map,attr.u.str); |
1107 | ret->way.name2 = map_convert_string(sitem->map, attr.u.str); |
838 | navigation_itm_update(ret, ritem); |
1108 | navigation_itm_update(ret, ritem); |
839 | |
1109 | |
840 | while (item_coord_get(ritem, &c[i], 1)) { |
1110 | while (item_coord_get(ritem, &c[i], 1)) |
|
|
1111 | { |
841 | dbg(1, "coord %d 0x%x 0x%x\n", i, c[i].x ,c[i].y); |
1112 | //dbg(1, "coord %d 0x%x 0x%x\n", i, c[i].x, c[i].y); |
842 | |
1113 | |
843 | if (i < 4) |
1114 | if (i < 4) |
844 | i++; |
1115 | i++; |
845 | else { |
1116 | else |
|
|
1117 | { |
846 | c[2]=c[3]; |
1118 | c[2] = c[3]; |
847 | c[3]=c[4]; |
1119 | c[3] = c[4]; |
848 | } |
|
|
849 | } |
1120 | } |
|
|
1121 | } |
850 | dbg(1,"count=%d\n", i); |
1122 | //dbg(1, "count=%d\n", i); |
851 | i--; |
1123 | i--; |
852 | |
1124 | |
853 | ret->way.angle2=road_angle(&c[0], &c[1], 0); |
1125 | ret->way.angle2 = road_angle(&c[0], &c[1], 0); |
854 | ret->angle_end=road_angle(&c[i-1], &c[i], 0); |
1126 | ret->angle_end = road_angle(&c[i - 1], &c[i], 0); |
855 | |
1127 | |
856 | ret->start=c[0]; |
1128 | ret->start = c[0]; |
857 | ret->end=c[i]; |
1129 | ret->end = c[i]; |
858 | |
1130 | |
859 | item_attr_get(ritem, attr_route, &route_attr); |
1131 | item_attr_get(ritem, attr_route, &route_attr); |
860 | graph_map = route_get_graph_map(route_attr.u.route); |
1132 | graph_map = route_get_graph_map(route_attr.u.route); |
861 | if (check_roundabout(ret, graph_map)) { |
1133 | if (check_roundabout(ret, graph_map)) |
|
|
1134 | { |
862 | ret->way.flags |= AF_ROUNDABOUT; |
1135 | ret->way.flags |= AF_ROUNDABOUT; |
863 | } |
1136 | } |
864 | |
1137 | |
865 | dbg(1,"i=%d start %d end %d '%s' '%s'\n", i, ret->way.angle2, ret->angle_end, ret->way.name1, ret->way.name2); |
1138 | // dbg(1, "i=%d start %d end %d '%s' '%s'\n", i, ret->way.angle2, ret->angle_end, ret->way.name1, ret->way.name2); |
866 | map_rect_destroy(mr); |
1139 | map_rect_destroy(mr); |
867 | } else { |
1140 | } |
|
|
1141 | else |
|
|
1142 | { |
868 | if (this_->last) |
1143 | if (this_->last) |
869 | ret->start=ret->end=this_->last->end; |
1144 | ret->start = ret->end = this_->last->end; |
870 | } |
1145 | } |
871 | if (! this_->first) |
1146 | if (!this_->first) |
872 | this_->first=ret; |
1147 | this_->first = ret; |
873 | if (this_->last) { |
1148 | if (this_->last) |
|
|
1149 | { |
874 | this_->last->next=ret; |
1150 | this_->last->next = ret; |
875 | ret->prev=this_->last; |
1151 | ret->prev = this_->last; |
876 | if (graph_map) { |
1152 | if (graph_map) |
|
|
1153 | { |
877 | navigation_itm_ways_update(ret,graph_map); |
1154 | navigation_itm_ways_update(ret, graph_map); |
878 | } |
|
|
879 | } |
1155 | } |
|
|
1156 | } |
880 | dbg(1,"ret=%p\n", ret); |
1157 | //dbg(1, "ret=%p\n", ret); |
881 | this_->last=ret; |
1158 | this_->last = ret; |
882 | return ret; |
1159 | return ret; |
883 | } |
1160 | } |
884 | |
1161 | |
885 | /** |
1162 | /** |
886 | * @brief Counts how many times a driver could turn right/left |
1163 | * @brief Counts how many times a driver could turn right/left |
… | |
… | |
892 | * @param from The navigation item which should form the start |
1169 | * @param from The navigation item which should form the start |
893 | * @param to The navigation item which should form the end |
1170 | * @param to The navigation item which should form the end |
894 | * @param direction Set to < 0 to count turns to the left >= 0 for turns to the right |
1171 | * @param direction Set to < 0 to count turns to the left >= 0 for turns to the right |
895 | * @return The number of possibilities to turn or -1 on error |
1172 | * @return The number of possibilities to turn or -1 on error |
896 | */ |
1173 | */ |
897 | static int |
1174 | static int count_possible_turns(struct navigation *nav, |
898 | count_possible_turns(struct navigation *nav, struct navigation_itm *from, struct navigation_itm *to, int direction) |
1175 | struct navigation_itm *from, struct navigation_itm *to, int direction) |
899 | { |
1176 | { |
900 | int count; |
1177 | int count; |
901 | struct navigation_itm *curr; |
1178 | struct navigation_itm *curr; |
902 | struct navigation_way *w; |
1179 | struct navigation_way *w; |
903 | |
1180 | |
904 | count = 0; |
1181 | count = 0; |
905 | curr = from->next; |
1182 | curr = from->next; |
906 | while (curr && (curr != to)) { |
1183 | while (curr && (curr != to)) |
|
|
1184 | { |
907 | w = curr->way.next; |
1185 | w = curr->way.next; |
908 | |
1186 | |
909 | while (w) { |
1187 | while (w) |
|
|
1188 | { |
910 | if (is_way_allowed(nav, w, 4)) { |
1189 | if (is_way_allowed(nav, w, 4)) |
|
|
1190 | { |
911 | if (direction < 0) { |
1191 | if (direction < 0) |
|
|
1192 | { |
912 | if (angle_delta(curr->prev->angle_end, w->angle2) < 0) { |
1193 | if (angle_delta(curr->prev->angle_end, w->angle2) < 0) |
|
|
1194 | { |
913 | count++; |
1195 | count++; |
914 | break; |
1196 | break; |
915 | } |
1197 | } |
|
|
1198 | } |
916 | } else { |
1199 | else |
|
|
1200 | { |
917 | if (angle_delta(curr->prev->angle_end, w->angle2) > 0) { |
1201 | if (angle_delta(curr->prev->angle_end, w->angle2) > 0) |
|
|
1202 | { |
918 | count++; |
1203 | count++; |
919 | break; |
1204 | break; |
920 | } |
1205 | } |
921 | } |
1206 | } |
922 | } |
1207 | } |
923 | w = w->next; |
1208 | w = w->next; |
924 | } |
1209 | } |
925 | curr = curr->next; |
1210 | curr = curr->next; |
926 | } |
1211 | } |
927 | |
1212 | |
|
|
1213 | if (!curr) |
928 | if (!curr) { // from does not lead to to? |
1214 | { // from does not lead to to? |
929 | return -1; |
1215 | return -1; |
930 | } |
1216 | } |
931 | |
1217 | |
932 | return count; |
1218 | return count; |
933 | } |
1219 | } |
… | |
… | |
941 | * only if the rest of the navigation already has been calculated. |
1227 | * only if the rest of the navigation already has been calculated. |
942 | * |
1228 | * |
943 | * @param this_ The navigation whose destination / time should be calculated |
1229 | * @param this_ The navigation whose destination / time should be calculated |
944 | * @param incr Set this to true to only calculate the first item. See description. |
1230 | * @param incr Set this to true to only calculate the first item. See description. |
945 | */ |
1231 | */ |
946 | static void |
|
|
947 | calculate_dest_distance(struct navigation *this_, int incr) |
1232 | static void calculate_dest_distance(struct navigation *this_, int incr) |
948 | { |
1233 | { |
949 | int len=0, time=0, count=0; |
1234 | int len = 0, time = 0, count = 0; |
950 | struct navigation_itm *next,*itm=this_->last; |
1235 | struct navigation_itm *next, *itm = this_->last; |
951 | dbg(1, "enter this_=%p, incr=%d\n", this_, incr); |
1236 | //dbg(1, "enter this_=%p, incr=%d\n", this_, incr); |
952 | if (incr) { |
1237 | if (incr) |
|
|
1238 | { |
953 | if (itm) { |
1239 | if (itm) |
954 | dbg(2, "old values: (%p) time=%d lenght=%d\n", itm, itm->dest_length, itm->dest_time); |
1240 | { |
|
|
1241 | //dbg(2, "old values: (%p) time=%d lenght=%d\n", itm, |
|
|
1242 | // itm->dest_length, itm->dest_time); |
|
|
1243 | } |
955 | } else { |
1244 | else |
|
|
1245 | { |
956 | dbg(2, "old values: itm is null\n"); |
1246 | //dbg(2, "old values: itm is null\n"); |
957 | } |
1247 | } |
958 | itm=this_->first; |
1248 | itm = this_->first; |
959 | next=itm->next; |
1249 | next = itm->next; |
960 | dbg(2, "itm values: time=%d lenght=%d\n", itm->length, itm->time); |
1250 | //dbg(2, "itm values: time=%d lenght=%d\n", itm->length, itm->time); |
961 | dbg(2, "next values: (%p) time=%d lenght=%d\n", next, next->dest_length, next->dest_time); |
1251 | //dbg(2, "next values: (%p) time=%d lenght=%d\n", next, next->dest_length, next->dest_time); |
962 | itm->dest_length=next->dest_length+itm->length; |
1252 | itm->dest_length = next->dest_length + itm->length; |
963 | itm->dest_count=next->dest_count+1; |
1253 | itm->dest_count = next->dest_count + 1; |
964 | itm->dest_time=next->dest_time+itm->time; |
1254 | itm->dest_time = next->dest_time + itm->time; |
965 | dbg(2, "new values: time=%d lenght=%d\n", itm->dest_length, itm->dest_time); |
1255 | //dbg(2, "new values: time=%d lenght=%d\n", itm->dest_length, itm->dest_time); |
966 | return; |
1256 | return; |
967 | } |
1257 | } |
968 | while (itm) { |
1258 | while (itm) |
|
|
1259 | { |
969 | len+=itm->length; |
1260 | len += itm->length; |
970 | time+=itm->time; |
1261 | time += itm->time; |
971 | itm->dest_length=len; |
1262 | itm->dest_length = len; |
972 | itm->dest_time=time; |
1263 | itm->dest_time = time; |
973 | itm->dest_count=count++; |
1264 | itm->dest_count = count++; |
974 | itm=itm->prev; |
1265 | itm = itm->prev; |
975 | } |
1266 | } |
976 | dbg(1,"len %d time %d\n", len, time); |
1267 | //dbg(1, "len %d time %d\n", len, time); |
977 | } |
1268 | } |
978 | |
1269 | |
979 | /** |
1270 | /** |
980 | * @brief Checks if two navigation items are on the same street |
1271 | * @brief Checks if two navigation items are on the same street |
981 | * |
1272 | * |
… | |
… | |
985 | * |
1276 | * |
986 | * @param old The first item to be checked |
1277 | * @param old The first item to be checked |
987 | * @param new The second item to be checked |
1278 | * @param new The second item to be checked |
988 | * @return True if both old and new are on the same street |
1279 | * @return True if both old and new are on the same street |
989 | */ |
1280 | */ |
990 | static int |
|
|
991 | is_same_street2(char *old_name1, char *old_name2, char *new_name1, char *new_name2) |
1281 | static int is_same_street2(char *old_name1, char *old_name2, char *new_name1, |
|
|
1282 | char *new_name2) |
992 | { |
1283 | { |
993 | if (old_name1 && new_name1 && !strcmp(old_name1, new_name1)) { |
1284 | if (old_name1 && new_name1 && !strcmp(old_name1, new_name1)) |
|
|
1285 | { |
994 | dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' yes (1.)\n", old_name2, new_name2, old_name1, new_name1); |
1286 | // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (1.)\n", old_name2, new_name2, old_name1, new_name1); |
995 | return 1; |
1287 | return 1; |
996 | } |
1288 | } |
997 | if (old_name2 && new_name2 && !strcmp(old_name2, new_name2)) { |
1289 | if (old_name2 && new_name2 && !strcmp(old_name2, new_name2)) |
|
|
1290 | { |
998 | dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' yes (2.)\n", old_name2, new_name2, old_name1, new_name1); |
1291 | // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (2.)\n", old_name2, new_name2, old_name1, new_name1); |
999 | return 1; |
1292 | return 1; |
1000 | } |
1293 | } |
1001 | dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' no\n", old_name2, new_name2, old_name1, new_name1); |
1294 | // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' no\n", old_name2, new_name2, old_name1, new_name1); |
1002 | return 0; |
1295 | return 0; |
1003 | } |
1296 | } |
1004 | |
1297 | |
1005 | #if 0 |
1298 | #if 0 |
1006 | /** |
1299 | /** |
… | |
… | |
1018 | static int |
1311 | static int |
1019 | is_same_street_systematic(struct navigation_itm *old, struct navigation_itm *new) |
1312 | is_same_street_systematic(struct navigation_itm *old, struct navigation_itm *new) |
1020 | { |
1313 | { |
1021 | int slashold,slashnew; |
1314 | int slashold,slashnew; |
1022 | if (!old->name2 || !new->name2) |
1315 | if (!old->name2 || !new->name2) |
1023 | return 1; |
1316 | return 1; |
1024 | slashold=strcspn(old->name2, "/"); |
1317 | slashold=strcspn(old->name2, "/"); |
1025 | slashnew=strcspn(new->name2, "/"); |
1318 | slashnew=strcspn(new->name2, "/"); |
1026 | if (slashold != slashnew || strncmp(old->name2, new->name2, slashold)) |
1319 | if (slashold != slashnew || strncmp(old->name2, new->name2, slashold)) |
1027 | return 0; |
1320 | return 0; |
1028 | return 1; |
1321 | return 1; |
1029 | } |
1322 | } |
1030 | |
|
|
1031 | |
1323 | |
1032 | /** |
1324 | /** |
1033 | * @brief Check if there are multiple possibilities to drive from old |
1325 | * @brief Check if there are multiple possibilities to drive from old |
1034 | * |
1326 | * |
1035 | * This function checks, if there are multiple streets connected to the exit of "old". |
1327 | * This function checks, if there are multiple streets connected to the exit of "old". |
… | |
… | |
1037 | * being connected there, and it is not useful if navit creates a maneuver there. |
1329 | * being connected there, and it is not useful if navit creates a maneuver there. |
1038 | * |
1330 | * |
1039 | * @param new The navigation item we're driving to |
1331 | * @param new The navigation item we're driving to |
1040 | * @return True if there are multiple streets |
1332 | * @return True if there are multiple streets |
1041 | */ |
1333 | */ |
1042 | static int |
1334 | static int |
1043 | maneuver_multiple_streets(struct navigation_itm *new) |
1335 | maneuver_multiple_streets(struct navigation_itm *new) |
1044 | { |
1336 | { |
1045 | if (new->way.next) { |
1337 | if (new->way.next) |
|
|
1338 | { |
1046 | return 1; |
1339 | return 1; |
1047 | } else { |
1340 | } |
|
|
1341 | else |
|
|
1342 | { |
1048 | return 0; |
1343 | return 0; |
1049 | } |
1344 | } |
1050 | } |
1345 | } |
1051 | |
|
|
1052 | |
1346 | |
1053 | /** |
1347 | /** |
1054 | * @brief Check if the new item is entered "straight" |
1348 | * @brief Check if the new item is entered "straight" |
1055 | * |
1349 | * |
1056 | * This function checks if the new item is entered "straight" from the old item, i.e. if there |
1350 | * This function checks if the new item is entered "straight" from the old item, i.e. if there |
… | |
… | |
1058 | * |
1352 | * |
1059 | * @param new The navigation item we're driving to |
1353 | * @param new The navigation item we're driving to |
1060 | * @param diff The absolute angle one needs to steer to drive to this item |
1354 | * @param diff The absolute angle one needs to steer to drive to this item |
1061 | * @return True if the new item is entered "straight" |
1355 | * @return True if the new item is entered "straight" |
1062 | */ |
1356 | */ |
1063 | static int |
1357 | static int |
1064 | maneuver_straight(struct navigation_itm *new, int diff) |
1358 | maneuver_straight(struct navigation_itm *new, int diff) |
1065 | { |
1359 | { |
1066 | int curr_diff; |
1360 | int curr_diff; |
1067 | struct navigation_way *w; |
1361 | struct navigation_way *w; |
1068 | |
1362 | |
1069 | w = new->way.next; |
1363 | w = new->way.next; |
1070 | dbg(1,"diff=%d\n", diff); |
1364 | dbg(1,"diff=%d\n", diff); |
1071 | while (w) { |
1365 | while (w) |
|
|
1366 | { |
1072 | curr_diff=abs(angle_delta(new->prev->angle_end, w->angle2)); |
1367 | curr_diff=abs(angle_delta(new->prev->angle_end, w->angle2)); |
1073 | dbg(1,"curr_diff=%d\n", curr_diff); |
1368 | dbg(1,"curr_diff=%d\n", curr_diff); |
1074 | if (curr_diff < diff) { |
1369 | if (curr_diff < diff) |
|
|
1370 | { |
1075 | return 0; |
1371 | return 0; |
1076 | } |
1372 | } |
1077 | w = w->next; |
1373 | w = w->next; |
1078 | } |
1374 | } |
1079 | return 1; |
1375 | return 1; |
1080 | } |
1376 | } |
1081 | #endif |
1377 | #endif |
1082 | |
1378 | |
1083 | static int maneuver_category(enum item_type type) |
1379 | static int maneuver_category(enum item_type type) |
1084 | { |
1380 | { |
1085 | switch (type) { |
1381 | switch (type) |
|
|
1382 | { |
1086 | case type_street_0: |
1383 | case type_street_0: |
|
|
1384 | return 1; |
|
|
1385 | case type_street_1_city: |
|
|
1386 | return 2; |
|
|
1387 | case type_street_2_city: |
|
|
1388 | return 3; |
|
|
1389 | case type_street_3_city: |
|
|
1390 | return 4; |
|
|
1391 | case type_street_4_city: |
|
|
1392 | return 5; |
|
|
1393 | case type_highway_city: |
|
|
1394 | return 7; |
|
|
1395 | case type_street_1_land: |
|
|
1396 | return 2; |
|
|
1397 | case type_street_2_land: |
|
|
1398 | return 3; |
|
|
1399 | case type_street_3_land: |
|
|
1400 | return 4; |
|
|
1401 | case type_street_4_land: |
|
|
1402 | return 5; |
|
|
1403 | case type_street_n_lanes: |
|
|
1404 | return 6; |
|
|
1405 | case type_highway_land: |
|
|
1406 | return 7; |
|
|
1407 | case type_ramp: |
|
|
1408 | return 0; |
|
|
1409 | case type_roundabout: |
|
|
1410 | return 0; |
|
|
1411 | case type_ferry: |
|
|
1412 | return 0; |
|
|
1413 | default: |
|
|
1414 | return 0; |
|
|
1415 | } |
|
|
1416 | |
|
|
1417 | } |
|
|
1418 | |
|
|
1419 | static int is_way_allowed(struct navigation *nav, struct navigation_way *way, |
|
|
1420 | int mode) |
|
|
1421 | { |
|
|
1422 | if (!nav->vehicleprofile) |
|
|
1423 | { |
1087 | return 1; |
1424 | return 1; |
1088 | case type_street_1_city: |
|
|
1089 | return 2; |
|
|
1090 | case type_street_2_city: |
|
|
1091 | return 3; |
|
|
1092 | case type_street_3_city: |
|
|
1093 | return 4; |
|
|
1094 | case type_street_4_city: |
|
|
1095 | return 5; |
|
|
1096 | case type_highway_city: |
|
|
1097 | return 7; |
|
|
1098 | case type_street_1_land: |
|
|
1099 | return 2; |
|
|
1100 | case type_street_2_land: |
|
|
1101 | return 3; |
|
|
1102 | case type_street_3_land: |
|
|
1103 | return 4; |
|
|
1104 | case type_street_4_land: |
|
|
1105 | return 5; |
|
|
1106 | case type_street_n_lanes: |
|
|
1107 | return 6; |
|
|
1108 | case type_highway_land: |
|
|
1109 | return 7; |
|
|
1110 | case type_ramp: |
|
|
1111 | return 0; |
|
|
1112 | case type_roundabout: |
|
|
1113 | return 0; |
|
|
1114 | case type_ferry: |
|
|
1115 | return 0; |
|
|
1116 | default: |
|
|
1117 | return 0; |
|
|
1118 | } |
1425 | } |
1119 | |
1426 | return !way->flags || ((way->flags |
1120 | |
1427 | & (way->dir >= 0 ? nav->vehicleprofile->flags_forward_mask |
1121 | } |
1428 | : nav->vehicleprofile->flags_reverse_mask)) |
1122 | |
1429 | == nav->vehicleprofile->flags); |
1123 | static int |
|
|
1124 | is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode) |
|
|
1125 | { |
|
|
1126 | if (!nav->vehicleprofile) |
|
|
1127 | return 1; |
|
|
1128 | return !way->flags || ((way->flags & (way->dir >= 0 ? nav->vehicleprofile->flags_forward_mask : nav->vehicleprofile->flags_reverse_mask)) == nav->vehicleprofile->flags); |
|
|
1129 | } |
1430 | } |
1130 | |
1431 | |
1131 | /** |
1432 | /** |
1132 | * @brief Checks if navit has to create a maneuver to drive from old to new |
1433 | * @brief Checks if navit has to create a maneuver to drive from old to new |
1133 | * |
1434 | * |
… | |
… | |
1138 | * @param new The new navigation item, where we're going to |
1439 | * @param new The new navigation item, where we're going to |
1139 | * @param delta The angle the user has to steer to navigate from old to new |
1440 | * @param delta The angle the user has to steer to navigate from old to new |
1140 | * @param reason A text string explaining how the return value resulted |
1441 | * @param reason A text string explaining how the return value resulted |
1141 | * @return True if navit should guide the user, false otherwise |
1442 | * @return True if navit should guide the user, false otherwise |
1142 | */ |
1443 | */ |
1143 | static int |
1444 | static int maneuver_required2(struct navigation *nav, |
1144 | maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct navigation_itm *new, int *delta, char **reason) |
1445 | struct navigation_itm *old, struct navigation_itm *new, int *delta, |
|
|
1446 | char **reason) |
1145 | { |
1447 | { |
1146 | int ret=0,d,dw,dlim; |
1448 | int ret = 0, d, dw, dlim; |
1147 | char *r=NULL; |
1449 | char *r = NULL; |
1148 | struct navigation_way *w; |
1450 | struct navigation_way *w; |
1149 | int cat,ncat,wcat,maxcat,left=-180,right=180,is_unambigous=0,is_same_street; |
1451 | int cat, ncat, wcat, maxcat, left = -180, right = 180, is_unambigous = 0, |
|
|
1452 | is_same_street; |
1150 | |
1453 | |
1151 | dbg(1,"enter %p %p %p\n",old, new, delta); |
1454 | //dbg(1, "enter %p %p %p\n", old, new, delta); |
1152 | d=angle_delta(old->angle_end, new->way.angle2); |
1455 | d = angle_delta(old->angle_end, new->way.angle2); |
1153 | if (!new->way.next) { |
1456 | if (!new->way.next) |
|
|
1457 | { |
1154 | /* No announcement necessary */ |
1458 | /* No announcement necessary */ |
1155 | r="no: Only one possibility"; |
1459 | r = "no: Only one possibility"; |
|
|
1460 | } |
1156 | } else if (!new->way.next->next && new->way.next->item.type == type_ramp && !is_way_allowed(nav,new->way.next,1)) { |
1461 | else if (!new->way.next->next && new->way.next->item.type == type_ramp |
|
|
1462 | && !is_way_allowed(nav, new->way.next, 1)) |
|
|
1463 | { |
1157 | /* If the other way is only a ramp and it is one-way in the wrong direction, no announcement necessary */ |
1464 | /* If the other way is only a ramp and it is one-way in the wrong direction, no announcement necessary */ |
1158 | r="no: Only ramp"; |
1465 | r = "no: Only ramp"; |
1159 | } |
1466 | } |
1160 | if (! r) { |
1467 | if (!r) |
|
|
1468 | { |
1161 | if ((old->way.flags & AF_ROUNDABOUT) && ! (new->way.flags & AF_ROUNDABOUT)) { |
1469 | if ((old->way.flags & AF_ROUNDABOUT) && !(new->way.flags |
|
|
1470 | & AF_ROUNDABOUT)) |
|
|
1471 | { |
1162 | r="yes: leaving roundabout"; |
1472 | r = "yes: leaving roundabout"; |
1163 | ret=1; |
1473 | ret = 1; |
|
|
1474 | } |
1164 | } else if (!(old->way.flags & AF_ROUNDABOUT) && (new->way.flags & AF_ROUNDABOUT)) { |
1475 | else if (!(old->way.flags & AF_ROUNDABOUT) && (new->way.flags |
|
|
1476 | & AF_ROUNDABOUT)) |
|
|
1477 | { |
1165 | r="no: entering roundabout"; |
1478 | r = "no: entering roundabout"; |
|
|
1479 | } |
1166 | } else if ((old->way.flags & AF_ROUNDABOUT) && (new->way.flags & AF_ROUNDABOUT)) |
1480 | else if ((old->way.flags & AF_ROUNDABOUT) && (new->way.flags |
|
|
1481 | & AF_ROUNDABOUT)) |
1167 | r="no: staying in roundabout"; |
1482 | r = "no: staying in roundabout"; |
1168 | } |
1483 | } |
1169 | if (!r && abs(d) > 75) { |
1484 | if (!r && abs(d) > 75) |
|
|
1485 | { |
1170 | /* always make an announcement if you have to make a sharp turn */ |
1486 | /* always make an announcement if you have to make a sharp turn */ |
1171 | r="yes: delta over 75"; |
1487 | r = "yes: delta over 75"; |
1172 | ret=1; |
1488 | ret = 1; |
1173 | } |
1489 | } |
1174 | cat=maneuver_category(old->way.item.type); |
1490 | cat = maneuver_category(old->way.item.type); |
1175 | ncat=maneuver_category(new->way.item.type); |
1491 | ncat = maneuver_category(new->way.item.type); |
1176 | if (!r) { |
1492 | if (!r) |
|
|
1493 | { |
1177 | /* Check whether the street keeps its name */ |
1494 | /* Check whether the street keeps its name */ |
1178 | is_same_street=is_same_street2(old->way.name1, old->way.name2, new->way.name1, new->way.name2); |
1495 | is_same_street = is_same_street2(old->way.name1, old->way.name2, |
|
|
1496 | new->way.name1, new->way.name2); |
1179 | w = new->way.next; |
1497 | w = new->way.next; |
1180 | maxcat=-1; |
1498 | maxcat = -1; |
1181 | while (w) { |
1499 | while (w) |
|
|
1500 | { |
1182 | dw=angle_delta(old->angle_end, w->angle2); |
1501 | dw = angle_delta(old->angle_end, w->angle2); |
1183 | if (dw < 0) { |
1502 | if (dw < 0) |
|
|
1503 | { |
1184 | if (dw > left) |
1504 | if (dw > left) |
1185 | left=dw; |
1505 | left = dw; |
|
|
1506 | } |
1186 | } else { |
1507 | else |
|
|
1508 | { |
1187 | if (dw < right) |
1509 | if (dw < right) |
1188 | right=dw; |
1510 | right = dw; |
1189 | } |
1511 | } |
1190 | wcat=maneuver_category(w->item.type); |
1512 | wcat = maneuver_category(w->item.type); |
1191 | /* If any other street has the same name but isn't a highway (a highway might split up temporarily), then |
1513 | /* If any other street has the same name but isn't a highway (a highway might split up temporarily), then |
1192 | we can't use the same name criterium */ |
1514 | we can't use the same name criterium */ |
1193 | if (is_same_street && is_same_street2(old->way.name1, old->way.name2, w->name1, w->name2) && (cat != 7 || wcat != 7) && is_way_allowed(nav,w,2)) |
1515 | if (is_same_street && is_same_street2(old->way.name1, |
|
|
1516 | old->way.name2, w->name1, w->name2) && (cat != 7 || wcat |
|
|
1517 | != 7) && is_way_allowed(nav, w, 2)) |
1194 | is_same_street=0; |
1518 | is_same_street = 0; |
1195 | /* Even if the ramp has the same name, announce it */ |
1519 | /* Even if the ramp has the same name, announce it */ |
1196 | if (new->way.item.type == type_ramp && old->way.item.type != type_ramp) |
1520 | if (new->way.item.type == type_ramp && old->way.item.type |
|
|
1521 | != type_ramp) |
1197 | is_same_street=0; |
1522 | is_same_street = 0; |
1198 | /* Mark if the street has a higher or the same category */ |
1523 | /* Mark if the street has a higher or the same category */ |
1199 | if (wcat > maxcat) |
1524 | if (wcat > maxcat) |
1200 | maxcat=wcat; |
1525 | maxcat = wcat; |
1201 | w = w->next; |
1526 | w = w->next; |
1202 | } |
1527 | } |
1203 | /* get the delta limit for checking for other streets. It is lower if the street has no other |
1528 | /* get the delta limit for checking for other streets. It is lower if the street has no other |
1204 | streets of the same or higher category */ |
1529 | streets of the same or higher category */ |
1205 | if (ncat < cat) |
1530 | if (ncat < cat) |
1206 | dlim=80; |
1531 | dlim = 80; |
1207 | else |
1532 | else |
1208 | dlim=120; |
1533 | dlim = 120; |
1209 | /* if the street is really straight, the others might be closer to straight */ |
1534 | /* if the street is really straight, the others might be closer to straight */ |
1210 | if (abs(d) < 20) |
1535 | if (abs(d) < 20) |
1211 | dlim/=2; |
1536 | dlim /= 2; |
1212 | if ((maxcat == ncat && maxcat == cat) || (ncat == 0 && cat == 0)) |
1537 | if ((maxcat == ncat && maxcat == cat) || (ncat == 0 && cat == 0)) |
1213 | dlim=abs(d)*620/256; |
1538 | dlim = abs(d) * 620 / 256; |
1214 | else if (maxcat < ncat && maxcat < cat) |
1539 | else if (maxcat < ncat && maxcat < cat) |
1215 | dlim=abs(d)*128/256; |
1540 | dlim = abs(d) * 128 / 256; |
1216 | if (left < -dlim && right > dlim) |
1541 | if (left < -dlim && right > dlim) |
1217 | is_unambigous=1; |
1542 | is_unambigous = 1; |
1218 | if (!is_same_street && is_unambigous < 1) { |
1543 | if (!is_same_street && is_unambigous < 1) |
|
|
1544 | { |
1219 | ret=1; |
1545 | ret = 1; |
1220 | r="yes: not same street or ambigous"; |
1546 | r = "yes: not same street or ambigous"; |
|
|
1547 | } |
1221 | } else |
1548 | else |
1222 | r="no: same street and unambigous"; |
1549 | r = "no: same street and unambigous"; |
1223 | #ifdef DEBUG |
1550 | #ifdef DEBUG |
1224 | r=g_strdup_printf("yes: d %d left %d right %d dlim=%d cat old:%d new:%d max:%d unambigous=%d same_street=%d", d, left, right, dlim, cat, ncat, maxcat, is_unambigous, is_same_street); |
1551 | // r=g_strdup_printf("yes: d %d left %d right %d dlim=%d cat old:%d new:%d max:%d unambigous=%d same_street=%d", d, left, right, dlim, cat, ncat, maxcat, is_unambigous, is_same_street); |
1225 | #endif |
1552 | #endif |
1226 | } |
1553 | } |
1227 | *delta=d; |
1554 | *delta = d; |
1228 | if (reason) |
1555 | if (reason) |
|
|
1556 | { |
1229 | *reason=r; |
1557 | *reason = r; |
|
|
1558 | } |
1230 | return ret; |
1559 | return ret; |
1231 | |
|
|
1232 | |
1560 | |
1233 | #if 0 |
1561 | #if 0 |
1234 | if (new->item.type == old->item.type || (new->item.type != type_ramp && old->item.type != type_ramp)) { |
1562 | if (new->item.type == old->item.type || (new->item.type != type_ramp && old->item.type != type_ramp)) |
|
|
1563 | { |
1235 | if (is_same_street2(old, new)) { |
1564 | if (is_same_street2(old, new)) |
|
|
1565 | { |
1236 | if (! entering_straight(new, abs(*delta))) { |
1566 | if (! entering_straight(new, abs(*delta))) |
|
|
1567 | { |
1237 | dbg(1, "maneuver_required: Not driving straight: yes\n"); |
1568 | dbg(1, "maneuver_required: Not driving straight: yes\n"); |
1238 | if (reason) |
1569 | if (reason) |
1239 | *reason="yes: Not driving straight"; |
1570 | *reason="yes: Not driving straight"; |
1240 | return 1; |
1571 | return 1; |
1241 | } |
1572 | } |
1242 | |
1573 | |
1243 | if (check_multiple_streets(new)) { |
1574 | if (check_multiple_streets(new)) |
|
|
1575 | { |
1244 | if (entering_straight(new,abs(*delta)*2)) { |
1576 | if (entering_straight(new,abs(*delta)*2)) |
|
|
1577 | { |
1245 | if (reason) |
1578 | if (reason) |
1246 | *reason="no: delta < ext_limit for same name"; |
1579 | *reason="no: delta < ext_limit for same name"; |
1247 | return 0; |
1580 | return 0; |
1248 | } |
1581 | } |
1249 | if (reason) |
1582 | if (reason) |
1250 | *reason="yes: delta > ext_limit for same name"; |
1583 | *reason="yes: delta > ext_limit for same name"; |
1251 | return 1; |
1584 | return 1; |
|
|
1585 | } |
1252 | } else { |
1586 | else |
|
|
1587 | { |
1253 | dbg(1, "maneuver_required: Staying on the same street: no\n"); |
1588 | dbg(1, "maneuver_required: Staying on the same street: no\n"); |
1254 | if (reason) |
1589 | if (reason) |
1255 | *reason="no: Staying on same street"; |
1590 | *reason="no: Staying on same street"; |
1256 | return 0; |
1591 | return 0; |
1257 | } |
1592 | } |
1258 | } |
1593 | } |
|
|
1594 | } |
1259 | } else |
1595 | else |
1260 | dbg(1, "maneuver_required: old or new is ramp\n"); |
1596 | dbg(1, "maneuver_required: old or new is ramp\n"); |
1261 | #if 0 |
1597 | #if 0 |
1262 | if (old->item.type == type_ramp && (new->item.type == type_highway_city || new->item.type == type_highway_land)) { |
1598 | if (old->item.type == type_ramp && (new->item.type == type_highway_city || new->item.type == type_highway_land)) |
|
|
1599 | { |
1263 | dbg(1, "no_maneuver_required: old is ramp new is highway\n"); |
1600 | dbg(1, "no_maneuver_required: old is ramp new is highway\n"); |
1264 | if (reason) |
1601 | if (reason) |
1265 | *reason="no: old is ramp new is highway"; |
1602 | *reason="no: old is ramp new is highway"; |
1266 | return 0; |
1603 | return 0; |
1267 | } |
1604 | } |
1268 | #endif |
1605 | #endif |
1269 | #if 0 |
1606 | #if 0 |
1270 | if (old->crossings_end == 2) { |
1607 | if (old->crossings_end == 2) |
|
|
1608 | { |
1271 | dbg(1, "maneuver_required: only 2 connections: no\n"); |
1609 | dbg(1, "maneuver_required: only 2 connections: no\n"); |
1272 | return 0; |
1610 | return 0; |
1273 | } |
1611 | } |
1274 | #endif |
1612 | #endif |
1275 | dbg(1,"delta=%d-%d=%d\n", new->way.angle2, old->angle_end, *delta); |
1613 | dbg(1,"delta=%d-%d=%d\n", new->way.angle2, old->angle_end, *delta); |
1276 | if ((new->item.type == type_highway_land || new->item.type == type_highway_city || old->item.type == type_highway_land || old->item.type == type_highway_city) && (!is_same_street_systematic(old, new) || (old->name2 != NULL && new->name2 == NULL))) { |
1614 | if ((new->item.type == type_highway_land || new->item.type == type_highway_city || old->item.type == type_highway_land || old->item.type == type_highway_city) && (!is_same_street_systematic(old, new) || (old->name2 != NULL && new->name2 == NULL))) |
|
|
1615 | { |
1277 | dbg(1, "maneuver_required: highway changed name\n"); |
1616 | dbg(1, "maneuver_required: highway changed name\n"); |
1278 | if (reason) |
1617 | if (reason) |
1279 | *reason="yes: highway changed name"; |
1618 | *reason="yes: highway changed name"; |
1280 | return 1; |
1619 | return 1; |
1281 | } |
1620 | } |
1282 | if (abs(*delta) < straight_limit) { |
1621 | if (abs(*delta) < straight_limit) |
|
|
1622 | { |
1283 | if (! entering_straight(new,abs(*delta))) { |
1623 | if (! entering_straight(new,abs(*delta))) |
|
|
1624 | { |
1284 | if (reason) |
1625 | if (reason) |
1285 | *reason="yes: not straight"; |
1626 | *reason="yes: not straight"; |
1286 | dbg(1, "maneuver_required: not driving straight: yes\n"); |
1627 | dbg(1, "maneuver_required: not driving straight: yes\n"); |
1287 | return 1; |
1628 | return 1; |
1288 | } |
1629 | } |
1289 | |
1630 | |
1290 | dbg(1, "maneuver_required: delta(%d) < %d: no\n", *delta, straight_limit); |
1631 | dbg(1, "maneuver_required: delta(%d) < %d: no\n", *delta, straight_limit); |
1291 | if (reason) |
1632 | if (reason) |
1292 | *reason="no: delta < limit"; |
1633 | *reason="no: delta < limit"; |
1293 | return 0; |
1634 | return 0; |
1294 | } |
1635 | } |
1295 | if (abs(*delta) < ext_straight_limit) { |
1636 | if (abs(*delta) < ext_straight_limit) |
|
|
1637 | { |
1296 | if (entering_straight(new,abs(*delta)*2)) { |
1638 | if (entering_straight(new,abs(*delta)*2)) |
|
|
1639 | { |
1297 | if (reason) |
1640 | if (reason) |
1298 | *reason="no: delta < ext_limit"; |
1641 | *reason="no: delta < ext_limit"; |
1299 | return 0; |
1642 | return 0; |
1300 | } |
1643 | } |
1301 | } |
1644 | } |
1302 | |
1645 | |
1303 | if (! check_multiple_streets(new)) { |
1646 | if (! check_multiple_streets(new)) |
|
|
1647 | { |
1304 | dbg(1, "maneuver_required: only one possibility: no\n"); |
1648 | dbg(1, "maneuver_required: only one possibility: no\n"); |
1305 | if (reason) |
1649 | if (reason) |
1306 | *reason="no: only one possibility"; |
1650 | *reason="no: only one possibility"; |
1307 | return 0; |
1651 | return 0; |
1308 | } |
1652 | } |
1309 | |
1653 | |
1310 | dbg(1, "maneuver_required: delta=%d: yes\n", *delta); |
1654 | dbg(1, "maneuver_required: delta=%d: yes\n", *delta); |
1311 | if (reason) |
1655 | if (reason) |
1312 | *reason="yes: delta >= limit"; |
1656 | *reason="yes: delta >= limit"; |
1313 | return 1; |
1657 | return 1; |
1314 | #endif |
1658 | #endif |
1315 | } |
1659 | } |
1316 | |
1660 | |
1317 | static struct navigation_command * |
1661 | static struct navigation_command * |
1318 | command_new(struct navigation *this_, struct navigation_itm *itm, int delta) |
1662 | command_new(struct navigation *this_, struct navigation_itm *itm, int delta) |
1319 | { |
1663 | { |
1320 | struct navigation_command *ret=g_new0(struct navigation_command, 1); |
1664 | struct navigation_command *ret=g_new0(struct navigation_command, 1); |
1321 | dbg(1,"enter this_=%p itm=%p delta=%d\n", this_, itm, delta); |
1665 | //dbg(1, "enter this_=%p itm=%p delta=%d\n", this_, itm, delta); |
1322 | ret->delta=delta; |
1666 | ret->delta = delta; |
1323 | ret->itm=itm; |
1667 | ret->itm = itm; |
1324 | if (itm && itm->prev && itm->way.next && itm->prev->way.next && !(itm->way.flags & AF_ROUNDABOUT) && (itm->prev->way.flags & AF_ROUNDABOUT)) { |
1668 | if (itm && itm->prev && itm->way.next && itm->prev->way.next |
|
|
1669 | && !(itm->way.flags & AF_ROUNDABOUT) && (itm->prev->way.flags |
|
|
1670 | & AF_ROUNDABOUT)) |
|
|
1671 | { |
1325 | int len=0; |
1672 | int len = 0; |
1326 | int angle=0; |
1673 | int angle = 0; |
1327 | int entry_angle; |
1674 | int entry_angle; |
1328 | struct navigation_itm *itm2=itm->prev; |
1675 | struct navigation_itm *itm2 = itm->prev; |
1329 | int exit_angle=angle_median(itm->prev->angle_end, itm->way.next->angle2); |
1676 | int exit_angle = angle_median(itm->prev->angle_end, |
|
|
1677 | itm->way.next->angle2); |
1330 | dbg(1,"exit %d median from %d,%d\n", exit_angle,itm->prev->angle_end, itm->way.next->angle2); |
1678 | //dbg(1, "exit %d median from %d,%d\n", exit_angle, itm->prev->angle_end, itm->way.next->angle2); |
1331 | while (itm2 && (itm2->way.flags & AF_ROUNDABOUT)) { |
1679 | while (itm2 && (itm2->way.flags & AF_ROUNDABOUT)) |
|
|
1680 | { |
1332 | len+=itm2->length; |
1681 | len += itm2->length; |
1333 | angle=itm2->angle_end; |
1682 | angle = itm2->angle_end; |
1334 | itm2=itm2->prev; |
1683 | itm2 = itm2->prev; |
1335 | } |
1684 | } |
1336 | if (itm2 && itm2->next && itm2->next->way.next) { |
1685 | if (itm2 && itm2->next && itm2->next->way.next) |
|
|
1686 | { |
1337 | itm2=itm2->next; |
1687 | itm2 = itm2->next; |
1338 | entry_angle=angle_median(angle_opposite(itm2->way.angle2), itm2->way.next->angle2); |
1688 | entry_angle = angle_median(angle_opposite(itm2->way.angle2), |
|
|
1689 | itm2->way.next->angle2); |
1339 | dbg(1,"entry %d median from %d(%d),%d\n", entry_angle,angle_opposite(itm2->way.angle2), itm2->way.angle2, itm2->way.next->angle2); |
1690 | // dbg(1, "entry %d median from %d(%d),%d\n", entry_angle, angle_opposite(itm2->way.angle2), itm2->way.angle2, itm2->way.next->angle2); |
|
|
1691 | } |
1340 | } else { |
1692 | else |
|
|
1693 | { |
1341 | entry_angle=angle_opposite(angle); |
1694 | entry_angle = angle_opposite(angle); |
1342 | } |
1695 | } |
1343 | dbg(0,"entry %d exit %d\n", entry_angle, exit_angle); |
1696 | //dbg(0, "entry %d exit %d\n", entry_angle, exit_angle); |
1344 | ret->roundabout_delta=angle_delta(entry_angle, exit_angle); |
1697 | ret->roundabout_delta = angle_delta(entry_angle, exit_angle); |
1345 | ret->length=len+roundabout_extra_length; |
1698 | ret->length = len + roundabout_extra_length; |
1346 | } |
1699 | } |
1347 | if (this_->cmd_last) { |
1700 | if (this_->cmd_last) |
|
|
1701 | { |
1348 | this_->cmd_last->next=ret; |
1702 | this_->cmd_last->next = ret; |
1349 | ret->prev = this_->cmd_last; |
1703 | ret->prev = this_->cmd_last; |
1350 | } |
1704 | } |
1351 | this_->cmd_last=ret; |
1705 | this_->cmd_last = ret; |
1352 | |
1706 | |
1353 | if (!this_->cmd_first) |
1707 | if (!this_->cmd_first) |
1354 | this_->cmd_first=ret; |
1708 | this_->cmd_first = ret; |
1355 | return ret; |
1709 | return ret; |
1356 | } |
1710 | } |
1357 | |
1711 | |
1358 | static void |
|
|
1359 | make_maneuvers(struct navigation *this_, struct route *route) |
1712 | static void make_maneuvers(struct navigation *this_, struct route *route) |
1360 | { |
1713 | { |
1361 | struct navigation_itm *itm, *last=NULL, *last_itm=NULL; |
1714 | struct navigation_itm *itm, *last = NULL, *last_itm = NULL; |
1362 | int delta; |
1715 | int delta; |
1363 | itm=this_->first; |
1716 | itm = this_->first; |
1364 | this_->cmd_last=NULL; |
1717 | this_->cmd_last = NULL; |
1365 | this_->cmd_first=NULL; |
1718 | this_->cmd_first = NULL; |
1366 | while (itm) { |
1719 | while (itm) |
|
|
1720 | { |
1367 | if (last) { |
1721 | if (last) |
|
|
1722 | { |
1368 | if (maneuver_required2(this_, last_itm, itm,&delta,NULL)) { |
1723 | if (maneuver_required2(this_, last_itm, itm, &delta, NULL)) |
|
|
1724 | { |
1369 | command_new(this_, itm, delta); |
1725 | command_new(this_, itm, delta); |
1370 | } |
1726 | } |
|
|
1727 | } |
1371 | } else |
1728 | else |
1372 | last=itm; |
1729 | last = itm; |
1373 | last_itm=itm; |
1730 | last_itm = itm; |
1374 | itm=itm->next; |
1731 | itm = itm->next; |
1375 | } |
1732 | } |
1376 | command_new(this_, last_itm, 0); |
1733 | command_new(this_, last_itm, 0); |
1377 | } |
1734 | } |
1378 | |
1735 | |
1379 | static int |
|
|
1380 | contains_suffix(char *name, char *suffix) |
1736 | static int contains_suffix(char *name, char *suffix) |
1381 | { |
1737 | { |
1382 | if (!suffix) |
1738 | if (!suffix) |
1383 | return 0; |
1739 | return 0; |
1384 | if (strlen(name) < strlen(suffix)) |
1740 | if (strlen(name) < strlen(suffix)) |
1385 | return 0; |
1741 | return 0; |
1386 | return !g_strcasecmp(name+strlen(name)-strlen(suffix), suffix); |
1742 | return !g_strcasecmp(name + strlen(name) - strlen(suffix), suffix); |
1387 | } |
1743 | } |
1388 | |
1744 | |
1389 | static char * |
1745 | static char * |
1390 | replace_suffix(char *name, char *search, char *replace) |
1746 | replace_suffix(char *name, char *search, char *replace) |
1391 | { |
1747 | { |
1392 | int len=strlen(name)-strlen(search); |
1748 | int len = strlen(name) - strlen(search); |
1393 | char *ret=g_malloc(len+strlen(replace)+1); |
1749 | char *ret = g_malloc(len + strlen(replace) + 1); |
1394 | strncpy(ret, name, len); |
1750 | strncpy(ret, name, len); |
1395 | strcpy(ret+len, replace); |
1751 | strcpy(ret + len, replace); |
1396 | if (isupper(name[len])) { |
1752 | if (isupper(name[len])) |
|
|
1753 | { |
1397 | ret[len]=toupper(ret[len]); |
1754 | ret[len] = toupper(ret[len]); |
1398 | } |
1755 | } |
1399 | |
1756 | |
1400 | return ret; |
1757 | return ret; |
1401 | } |
1758 | } |
1402 | |
1759 | |
1403 | static char * |
1760 | static char * |
1404 | navigation_item_destination(struct navigation *nav, struct navigation_itm *itm, struct navigation_itm *next, char *prefix) |
1761 | navigation_item_destination(struct navigation *nav, struct navigation_itm *itm, |
|
|
1762 | struct navigation_itm *next, char *prefix) |
1405 | { |
1763 | { |
1406 | char *ret=NULL,*name1,*sep,*name2; |
1764 | char *ret = NULL, *name1, *sep, *name2; |
1407 | char *n1,*n2; |
1765 | char *n1, *n2; |
1408 | int i,sex; |
1766 | int i, sex; |
1409 | int vocabulary1=65535; |
1767 | int vocabulary1 = 65535; |
1410 | int vocabulary2=65535; |
1768 | int vocabulary2 = 65535; |
1411 | struct attr attr; |
1769 | struct attr attr; |
1412 | |
1770 | |
1413 | if (! prefix) |
1771 | if (!prefix) |
1414 | prefix=""; |
1772 | prefix = ""; |
1415 | if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name, &attr, NULL)) |
1773 | if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name, |
|
|
1774 | &attr, NULL)) |
1416 | vocabulary1=attr.u.num; |
1775 | vocabulary1 = attr.u.num; |
1417 | if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name_systematic, &attr, NULL)) |
1776 | if (nav->speech && speech_get_attr(nav->speech, |
|
|
1777 | attr_vocabulary_name_systematic, &attr, NULL)) |
1418 | vocabulary2=attr.u.num; |
1778 | vocabulary2 = attr.u.num; |
1419 | n1=itm->way.name1; |
1779 | n1 = itm->way.name1; |
1420 | n2=itm->way.name2; |
1780 | n2 = itm->way.name2; |
1421 | if (!vocabulary1) |
1781 | if (!vocabulary1) |
1422 | n1=NULL; |
1782 | n1 = NULL; |
1423 | if (!vocabulary2) |
1783 | if (!vocabulary2) |
1424 | n2=NULL; |
1784 | n2 = NULL; |
1425 | if(!n1 && !n2 && itm->way.item.type == type_ramp && vocabulary2) { |
1785 | if (!n1 && !n2 && itm->way.item.type == type_ramp && vocabulary2) |
|
|
1786 | { |
1426 | dbg(1,">> Next is ramp %lx current is %lx \n", itm->way.item.type, next->way.item.type); |
1787 | //dbg(1,">> Next is ramp %lx current is %lx \n", itm->way.item.type, next->way.item.type); |
1427 | |
1788 | |
1428 | if(next->way.item.type == type_ramp) |
1789 | if (next->way.item.type == type_ramp) |
1429 | return NULL; |
1790 | return NULL; |
1430 | if(itm->way.item.type == type_highway_city || itm->way.item.type == type_highway_land ) |
1791 | if (itm->way.item.type == type_highway_city || itm->way.item.type |
|
|
1792 | == type_highway_land) |
|
|
1793 | { |
|
|
1794 | #ifdef HAVE_API_ANDROID |
|
|
1795 | android_send_generic_text(1,"+*#O:exit\n"); |
|
|
1796 | gchar* xy=g_strdup_printf("+*#1:%s\n", prefix); |
|
|
1797 | android_send_generic_text(1,xy); |
|
|
1798 | g_free(xy); |
|
|
1799 | #endif |
1431 | return g_strdup_printf("%s%s",prefix,_("exit")); /* %FIXME Can this even be reached? */ |
1800 | return g_strdup_printf("%s%s", prefix, _("exit")); /* %FIXME Can this even be reached? and "exit" is the wrong text anyway ! */ |
|
|
1801 | } |
1432 | else |
1802 | else |
|
|
1803 | { |
|
|
1804 | #ifdef HAVE_API_ANDROID |
|
|
1805 | android_send_generic_text(1,"+*#O:into the ramp\n"); |
|
|
1806 | gchar* xy=g_strdup_printf("+*#1:%s\n", prefix); |
|
|
1807 | android_send_generic_text(1,xy); |
|
|
1808 | g_free(xy); |
|
|
1809 | #endif |
1433 | return g_strdup_printf("%s%s",prefix,_("into the ramp")); |
1810 | return g_strdup_printf("%s%s", prefix, _("into the ramp")); |
1434 | |
1811 | } |
|
|
1812 | |
1435 | } |
1813 | } |
|
|
1814 | |
1436 | if (!n1 && !n2) |
1815 | if (!n1 && !n2) |
|
|
1816 | { |
1437 | return NULL; |
1817 | return NULL; |
|
|
1818 | } |
|
|
1819 | |
1438 | if (n1) { |
1820 | if (n1) |
|
|
1821 | { |
1439 | sex=-1; |
1822 | sex = -1; |
1440 | name1=NULL; |
1823 | name1 = NULL; |
1441 | for (i = 0 ; i < sizeof(suffixes)/sizeof(suffixes[0]) ; i++) { |
1824 | for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++) |
|
|
1825 | { |
1442 | if (contains_suffix(n1,suffixes[i].fullname)) { |
1826 | if (contains_suffix(n1, suffixes[i].fullname)) |
|
|
1827 | { |
1443 | sex=suffixes[i].sex; |
1828 | sex = suffixes[i].sex; |
1444 | name1=g_strdup(n1); |
1829 | name1 = g_strdup(n1); |
1445 | break; |
1830 | break; |
1446 | } |
1831 | } |
1447 | if (contains_suffix(n1,suffixes[i].abbrev)) { |
1832 | if (contains_suffix(n1, suffixes[i].abbrev)) |
|
|
1833 | { |
1448 | sex=suffixes[i].sex; |
1834 | sex = suffixes[i].sex; |
1449 | name1=replace_suffix(n1, suffixes[i].abbrev, suffixes[i].fullname); |
1835 | name1 = replace_suffix(n1, suffixes[i].abbrev, |
|
|
1836 | suffixes[i].fullname); |
1450 | break; |
1837 | break; |
1451 | } |
1838 | } |
1452 | } |
1839 | } |
|
|
1840 | |
1453 | if (n2) { |
1841 | if (n2) |
|
|
1842 | { |
1454 | name2=n2; |
1843 | name2 = n2; |
1455 | sep=" "; |
1844 | sep = " "; |
|
|
1845 | } |
1456 | } else { |
1846 | else |
|
|
1847 | { |
1457 | name2=""; |
1848 | name2 = ""; |
1458 | sep=""; |
1849 | sep = ""; |
1459 | } |
1850 | } |
|
|
1851 | |
|
|
1852 | gchar* xy; |
1460 | switch (sex) { |
1853 | switch (sex) |
|
|
1854 | { |
1461 | case -1: |
1855 | case -1: |
|
|
1856 | #ifdef HAVE_API_ANDROID |
|
|
1857 | android_send_generic_text(1,"+*#O:%sinto the street %s%s%s\n"); |
|
|
1858 | xy=g_strdup_printf("+*#1:%s\n", prefix); |
|
|
1859 | android_send_generic_text(1,xy); |
|
|
1860 | g_free(xy); |
|
|
1861 | xy=g_strdup_printf("+*#1:%s\n", n1); |
|
|
1862 | android_send_generic_text(1,xy); |
|
|
1863 | g_free(xy); |
|
|
1864 | xy=g_strdup_printf("+*#1:%s\n", sep); |
|
|
1865 | android_send_generic_text(1,xy); |
|
|
1866 | g_free(xy); |
|
|
1867 | xy=g_strdup_printf("+*#1:%s\n", name2); |
|
|
1868 | android_send_generic_text(1,xy); |
|
|
1869 | g_free(xy); |
|
|
1870 | #endif |
1462 | /* TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name */ |
1871 | // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name |
1463 | ret=g_strdup_printf(_("%sinto the street %s%s%s"),prefix,n1, sep, name2); |
1872 | ret = g_strdup_printf(_("%sinto the street %s%s%s"), prefix, |
|
|
1873 | n1, sep, name2); |
1464 | break; |
1874 | break; |
1465 | case 1: |
1875 | case 1: |
|
|
1876 | #ifdef HAVE_API_ANDROID |
|
|
1877 | android_send_generic_text(1,"+*#O:%sinto the %s%s%s|male form\n"); |
|
|
1878 | xy=g_strdup_printf("+*#1:%s\n", prefix); |
|
|
1879 | android_send_generic_text(1,xy); |
|
|
1880 | g_free(xy); |
|
|
1881 | xy=g_strdup_printf("+*#1:%s\n", name1); |
|
|
1882 | android_send_generic_text(1,xy); |
|
|
1883 | g_free(xy); |
|
|
1884 | xy=g_strdup_printf("+*#1:%s\n", sep); |
|
|
1885 | android_send_generic_text(1,xy); |
|
|
1886 | g_free(xy); |
|
|
1887 | xy=g_strdup_printf("+*#1:%s\n", name2); |
|
|
1888 | android_send_generic_text(1,xy); |
|
|
1889 | g_free(xy); |
|
|
1890 | #endif |
1466 | /* TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Male form. The stuff after | doesn't have to be included */ |
1891 | // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Male form. The stuff after | doesn't have to be included |
1467 | ret=g_strdup_printf(_("%sinto the %s%s%s|male form"),prefix,name1, sep, name2); |
1892 | ret = g_strdup_printf(_("%sinto the %s%s%s|male form"), prefix, |
|
|
1893 | name1, sep, name2); |
1468 | break; |
1894 | break; |
1469 | case 2: |
1895 | case 2: |
|
|
1896 | #ifdef HAVE_API_ANDROID |
|
|
1897 | android_send_generic_text(1,"+*#O:%sinto the %s%s%s|female form\n"); |
|
|
1898 | xy=g_strdup_printf("+*#1:%s\n", prefix); |
|
|
1899 | android_send_generic_text(1,xy); |
|
|
1900 | g_free(xy); |
|
|
1901 | xy=g_strdup_printf("+*#1:%s\n", name1); |
|
|
1902 | android_send_generic_text(1,xy); |
|
|
1903 | g_free(xy); |
|
|
1904 | xy=g_strdup_printf("+*#1:%s\n", sep); |
|
|
1905 | android_send_generic_text(1,xy); |
|
|
1906 | g_free(xy); |
|
|
1907 | xy=g_strdup_printf("+*#1:%s\n", name2); |
|
|
1908 | android_send_generic_text(1,xy); |
|
|
1909 | g_free(xy); |
|
|
1910 | #endif |
1470 | /* TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Female form. The stuff after | doesn't have to be included */ |
1911 | // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Female form. The stuff after | doesn't have to be included |
1471 | ret=g_strdup_printf(_("%sinto the %s%s%s|female form"),prefix,name1, sep, name2); |
1912 | ret = g_strdup_printf(_("%sinto the %s%s%s|female form"), |
|
|
1913 | prefix, name1, sep, name2); |
1472 | break; |
1914 | break; |
1473 | case 3: |
1915 | case 3: |
|
|
1916 | #ifdef HAVE_API_ANDROID |
|
|
1917 | android_send_generic_text(1,"+*#O:%sinto the %s%s%s|neutral form\n"); |
|
|
1918 | xy=g_strdup_printf("+*#1:%s\n", prefix); |
|
|
1919 | android_send_generic_text(1,xy); |
|
|
1920 | g_free(xy); |
|
|
1921 | xy=g_strdup_printf("+*#1:%s\n", name1); |
|
|
1922 | android_send_generic_text(1,xy); |
|
|
1923 | g_free(xy); |
|
|
1924 | xy=g_strdup_printf("+*#1:%s\n", sep); |
|
|
1925 | android_send_generic_text(1,xy); |
|
|
1926 | g_free(xy); |
|
|
1927 | xy=g_strdup_printf("+*#1:%s\n", name2); |
|
|
1928 | android_send_generic_text(1,xy); |
|
|
1929 | g_free(xy); |
|
|
1930 | #endif |
1474 | /* TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Neutral form. The stuff after | doesn't have to be included */ |
1931 | // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Neutral form. The stuff after | doesn't have to be included |
1475 | ret=g_strdup_printf(_("%sinto the %s%s%s|neutral form"),prefix,name1, sep, name2); |
1932 | ret = g_strdup_printf(_("%sinto the %s%s%s|neutral form"), |
|
|
1933 | prefix, name1, sep, name2); |
1476 | break; |
1934 | break; |
1477 | } |
1935 | } |
1478 | g_free(name1); |
1936 | g_free(name1); |
1479 | |
1937 | |
|
|
1938 | } |
1480 | } else |
1939 | else |
|
|
1940 | { |
|
|
1941 | #ifdef HAVE_API_ANDROID |
|
|
1942 | android_send_generic_text(1,"+*#O:sinto the %s\n"); |
|
|
1943 | gchar* xy=g_strdup_printf("+*#1:%s\n", prefix); |
|
|
1944 | android_send_generic_text(1,xy); |
|
|
1945 | g_free(xy); |
|
|
1946 | xy=g_strdup_printf("+*#1:%s\n", n2); |
|
|
1947 | android_send_generic_text(1,xy); |
|
|
1948 | g_free(xy); |
|
|
1949 | #endif |
1481 | /* TRANSLATORS: gives the name of the next road to turn into (into the E17) */ |
1950 | // TRANSLATORS: gives the name of the next road to turn into (into the E17) |
1482 | ret=g_strdup_printf(_("%sinto the %s"),prefix,n2); |
1951 | ret = g_strdup_printf(_("%sinto the %s"), prefix, n2); |
|
|
1952 | } |
|
|
1953 | |
1483 | name1=ret; |
1954 | name1 = ret; |
|
|
1955 | |
1484 | while (name1 && *name1) { |
1956 | while (name1 && *name1) |
|
|
1957 | { |
1485 | switch (*name1) { |
1958 | switch (*name1) |
|
|
1959 | { |
1486 | case '|': |
1960 | case '|': |
1487 | *name1='\0'; |
1961 | *name1 = '\0'; |
1488 | break; |
1962 | break; |
1489 | case '/': |
1963 | case '/': |
1490 | *name1++=' '; |
1964 | *name1++ = ' '; |
1491 | break; |
1965 | break; |
1492 | default: |
1966 | default: |
1493 | name1++; |
1967 | name1++; |
1494 | } |
|
|
1495 | } |
1968 | } |
|
|
1969 | } |
|
|
1970 | |
1496 | return ret; |
1971 | return ret; |
1497 | } |
1972 | } |
1498 | |
1973 | |
1499 | static char * |
1974 | static char * |
1500 | show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type, int connect) |
1975 | show_maneuver(struct navigation *nav, struct navigation_itm *itm, |
|
|
1976 | struct navigation_command *cmd, enum attr_type type, int connect) |
1501 | { |
1977 | { |
1502 | /* TRANSLATORS: right, as in 'Turn right' */ |
1978 | // TRANSLATORS: right, as in 'Turn right' |
1503 | char *dir=_("right"),*strength=""; |
1979 | char *dir = _("right"); |
|
|
1980 | char *strength = ""; |
1504 | int distance=itm->dest_length-cmd->itm->dest_length; |
1981 | int distance = itm->dest_length - cmd->itm->dest_length; |
1505 | char *d,*ret=NULL; |
1982 | char *d, *ret = NULL; |
1506 | int delta=cmd->delta; |
1983 | int delta = cmd->delta; |
1507 | int level; |
1984 | int level; |
1508 | int strength_needed; |
1985 | int strength_needed; |
1509 | int skip_roads; |
1986 | int skip_roads; |
1510 | int count_roundabout; |
1987 | int count_roundabout; |
1511 | struct navigation_itm *cur; |
1988 | struct navigation_itm *cur; |
1512 | struct navigation_way *w; |
1989 | struct navigation_way *w; |
1513 | |
1990 | |
1514 | if (connect) { |
1991 | if (connect) |
|
|
1992 | { |
1515 | level = -2; // level = -2 means "connect to another maneuver via 'then ...'" |
1993 | level = -2; // level = -2 means "connect to another maneuver via 'then ...'" |
1516 | } else { |
1994 | } |
|
|
1995 | else |
|
|
1996 | { |
1517 | level=1; |
1997 | level = 1; |
1518 | } |
1998 | } |
1519 | |
1999 | |
1520 | w = itm->next->way.next; |
2000 | w = itm->next->way.next; |
1521 | strength_needed = 0; |
2001 | strength_needed = 0; |
|
|
2002 | |
1522 | if (angle_delta(itm->next->way.angle2,itm->angle_end) < 0) { |
2003 | if (angle_delta(itm->next->way.angle2, itm->angle_end) < 0) |
|
|
2004 | { |
1523 | while (w) { |
2005 | while (w) |
|
|
2006 | { |
1524 | if (angle_delta(w->angle2,itm->angle_end) < 0) { |
2007 | if (angle_delta(w->angle2, itm->angle_end) < 0) |
|
|
2008 | { |
1525 | strength_needed = 1; |
2009 | strength_needed = 1; |
1526 | break; |
2010 | break; |
1527 | } |
2011 | } |
1528 | w = w->next; |
2012 | w = w->next; |
1529 | } |
2013 | } |
1530 | } else { |
2014 | } |
|
|
2015 | else |
|
|
2016 | { |
1531 | while (w) { |
2017 | while (w) |
|
|
2018 | { |
1532 | if (angle_delta(w->angle2,itm->angle_end) > 0) { |
2019 | if (angle_delta(w->angle2, itm->angle_end) > 0) |
|
|
2020 | { |
1533 | strength_needed = 1; |
2021 | strength_needed = 1; |
1534 | break; |
2022 | break; |
1535 | } |
2023 | } |
1536 | w = w->next; |
2024 | w = w->next; |
1537 | } |
2025 | } |
1538 | } |
2026 | } |
1539 | |
2027 | |
1540 | if (delta < 0) { |
2028 | if (delta < 0) |
|
|
2029 | { |
|
|
2030 | #ifdef HAVE_API_ANDROID |
|
|
2031 | android_send_generic_text(1,"+*#O:left\n"); |
|
|
2032 | #endif |
1541 | /* TRANSLATORS: left, as in 'Turn left' */ |
2033 | // TRANSLATORS: left, as in 'Turn left' |
1542 | dir=_("left"); |
2034 | dir = _("left"); |
1543 | delta=-delta; |
2035 | delta = -delta; |
1544 | } |
2036 | } |
|
|
2037 | else |
|
|
2038 | { |
|
|
2039 | // dir = right |
|
|
2040 | #ifdef HAVE_API_ANDROID |
|
|
2041 | android_send_generic_text(1,"+*#O:right\n"); |
|
|
2042 | #endif |
|
|
2043 | } |
1545 | |
2044 | |
1546 | if (strength_needed) { |
2045 | if (strength_needed) |
|
|
2046 | { |
1547 | if (delta < 45) { |
2047 | if (delta < 45) |
|
|
2048 | { |
|
|
2049 | #ifdef HAVE_API_ANDROID |
|
|
2050 | android_send_generic_text(1,"+*#O:slight \n"); |
|
|
2051 | #endif |
1548 | /* TRANSLATORS: Don't forget the ending space */ |
2052 | // TRANSLATORS: Don't forget the ending space |
|
|
2053 | // TRANSLATORS: EXAMPLE: turn slight right |
1549 | strength=_("easily "); |
2054 | strength = _("slight "); |
|
|
2055 | } |
1550 | } else if (delta < 105) { |
2056 | else if (delta < 105) |
|
|
2057 | { |
1551 | strength=""; |
2058 | strength = ""; |
|
|
2059 | } |
1552 | } else if (delta < 165) { |
2060 | else if (delta < 165) |
|
|
2061 | { |
|
|
2062 | #ifdef HAVE_API_ANDROID |
|
|
2063 | android_send_generic_text(1,"+*#O:hard \n"); |
|
|
2064 | #endif |
1553 | /* TRANSLATORS: Don't forget the ending space */ |
2065 | // TRANSLATORS: Don't forget the ending space |
|
|
2066 | // TRANSLATORS: EXAMPLE: turn hard right |
1554 | strength=_("strongly "); |
2067 | strength = _("hard "); |
|
|
2068 | } |
1555 | } else if (delta < 180) { |
2069 | else if (delta < 180) |
|
|
2070 | { |
|
|
2071 | #ifdef HAVE_API_ANDROID |
|
|
2072 | android_send_generic_text(1,"+*#O:really hard \n"); |
|
|
2073 | #endif |
1556 | /* TRANSLATORS: Don't forget the ending space */ |
2074 | // TRANSLATORS: Don't forget the ending space |
|
|
2075 | // TRANSLATORS: EXAMPLE: turn really hard right |
1557 | strength=_("really strongly "); |
2076 | strength = _("really hard "); |
|
|
2077 | } |
1558 | } else { |
2078 | else |
|
|
2079 | { |
1559 | dbg(1,"delta=%d\n", delta); |
2080 | // dbg(1,"delta=%d\n", delta); |
1560 | /* TRANSLATORS: Don't forget the ending space */ |
2081 | // TRANSLATORS: Don't forget the ending space |
1561 | strength=_("unknown "); |
2082 | //strength=_("unknown "); |
1562 | } |
2083 | strength = ""; |
1563 | } |
2084 | } |
|
|
2085 | } |
|
|
2086 | |
1564 | if (type != attr_navigation_long_exact) |
2087 | if (type != attr_navigation_long_exact) |
|
|
2088 | { |
1565 | distance=round_distance(distance); |
2089 | distance = round_distance(distance); |
|
|
2090 | } |
|
|
2091 | |
1566 | if (type == attr_navigation_speech) { |
2092 | if (type == attr_navigation_speech) |
|
|
2093 | { |
1567 | if (nav->turn_around && nav->turn_around == nav->turn_around_limit) |
2094 | if (nav->turn_around && nav->turn_around == nav->turn_around_limit) |
|
|
2095 | { |
|
|
2096 | #ifdef HAVE_API_ANDROID |
|
|
2097 | android_send_generic_text(1,"+*#O:When possible, please turn around\n"); |
|
|
2098 | #endif |
1568 | return g_strdup(_("When possible, please turn around")); |
2099 | return g_strdup(_("When possible, please turn around")); |
|
|
2100 | } |
|
|
2101 | |
1569 | if (!connect) { |
2102 | if (!connect) |
|
|
2103 | { |
1570 | level=navigation_get_announce_level_cmd(nav, itm, cmd, distance-cmd->length); |
2104 | level = navigation_get_announce_level_cmd(nav, itm, cmd, |
|
|
2105 | distance - cmd->length); |
1571 | } |
2106 | } |
1572 | dbg(1,"distance=%d level=%d type=0x%x\n", distance, level, itm->way.item.type); |
2107 | // dbg(1,"distance=%d level=%d type=0x%x\n", distance, level, itm->way.item.type); |
1573 | } |
2108 | } |
1574 | |
2109 | |
1575 | if (cmd->itm->prev->way.flags & AF_ROUNDABOUT) { |
2110 | if (cmd->itm->prev->way.flags & AF_ROUNDABOUT) |
|
|
2111 | { |
1576 | cur = cmd->itm->prev; |
2112 | cur = cmd->itm->prev; |
1577 | count_roundabout = 0; |
2113 | count_roundabout = 0; |
1578 | while (cur && (cur->way.flags & AF_ROUNDABOUT)) { |
2114 | while (cur && (cur->way.flags & AF_ROUNDABOUT)) |
1579 | if (cur->next->way.next && is_way_allowed(nav,cur->next->way.next,3)) { // If the next segment has no exit or the exit isn't allowed, don't count it |
2115 | { |
|
|
2116 | // If the next segment has no exit or the exit isn't allowed, don't count it |
|
|
2117 | if (cur->next->way.next && is_way_allowed(nav, cur->next->way.next, |
|
|
2118 | 3)) |
|
|
2119 | { |
1580 | count_roundabout++; |
2120 | count_roundabout++; |
1581 | } |
2121 | } |
1582 | cur = cur->prev; |
2122 | cur = cur->prev; |
1583 | } |
2123 | } |
|
|
2124 | |
|
|
2125 | gchar* xy; |
|
|
2126 | |
1584 | switch (level) { |
2127 | switch (level) |
|
|
2128 | { |
1585 | case 2: |
2129 | case 2: |
|
|
2130 | #ifdef HAVE_API_ANDROID |
|
|
2131 | android_send_generic_text(1,"+*#O:Enter the roundabout soon\n"); |
|
|
2132 | #endif |
1586 | return g_strdup(_("Enter the roundabout soon")); |
2133 | return g_strdup(_("Enter the roundabout soon")); |
1587 | case 1: |
2134 | case 1: |
1588 | d = get_distance(nav, distance, type, 0); |
2135 | d = get_distance(nav, distance, type, 1); |
|
|
2136 | |
|
|
2137 | #ifdef HAVE_API_ANDROID |
|
|
2138 | android_send_generic_text(1,"+*#O:In %s, enter the roundabout\n"); |
|
|
2139 | xy=g_strdup_printf("+*#1:%s\n", d); |
|
|
2140 | android_send_generic_text(1,xy); |
|
|
2141 | g_free(xy); |
|
|
2142 | #endif |
1589 | /* TRANSLATORS: %s is the distance to the roundabout */ |
2143 | // TRANSLATORS: %s is the distance to the roundabout |
|
|
2144 | // TRANSLATORS: EXAMPLE: In 300m, enter the roundabout |
1590 | ret = g_strdup_printf(_("In %s, enter the roundabout"), d); |
2145 | ret = g_strdup_printf(_("In %s, enter the roundabout"), d); |
|
|
2146 | g_free(d); |
|
|
2147 | return ret; |
|
|
2148 | case -2: |
|
|
2149 | #ifdef HAVE_API_ANDROID |
|
|
2150 | android_send_generic_text(1,"+*#O:then leave the roundabout at the %s\n"); |
|
|
2151 | xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout)); |
|
|
2152 | android_send_generic_text(1,xy); |
|
|
2153 | g_free(xy); |
|
|
2154 | #endif |
|
|
2155 | // TRANSLATORS: EXAMPLE: ... then leave the roundabout at the second exit |
|
|
2156 | return g_strdup_printf( |
|
|
2157 | _("then leave the roundabout at the %s"), |
|
|
2158 | get_exit_count_str(count_roundabout)); |
|
|
2159 | case 0: |
|
|
2160 | #ifdef HAVE_API_ANDROID |
|
|
2161 | android_send_generic_text(1,"+*#O:Leave the roundabout at the %s\n"); |
|
|
2162 | xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout)); |
|
|
2163 | android_send_generic_text(1,xy); |
|
|
2164 | g_free(xy); |
|
|
2165 | #endif |
|
|
2166 | // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit |
|
|
2167 | return g_strdup_printf(_("Leave the roundabout at the %s"), |
|
|
2168 | get_exit_count_str(count_roundabout)); |
|
|
2169 | } |
|
|
2170 | } |
|
|
2171 | |
|
|
2172 | switch (level) |
|
|
2173 | { |
|
|
2174 | case 3: |
|
|
2175 | d = get_distance(nav, distance, type, 1); |
|
|
2176 | |
|
|
2177 | #ifdef HAVE_API_ANDROID |
|
|
2178 | android_send_generic_text(1,"+*#O:Follow the road for the next %s\n"); |
|
|
2179 | gchar* xy=g_strdup_printf("+*#1:%s\n", d); |
|
|
2180 | android_send_generic_text(1,xy); |
|
|
2181 | g_free(xy); |
|
|
2182 | #endif |
|
|
2183 | // TRANSLATORS: EXAMPLE: Follow the road for the next 300 meters |
|
|
2184 | ret = g_strdup_printf(_("Follow the road for the next %s"), d); |
1591 | g_free(d); |
2185 | g_free(d); |
1592 | return ret; |
2186 | return ret; |
|
|
2187 | case 2: |
|
|
2188 | #ifdef HAVE_API_ANDROID |
|
|
2189 | android_send_generic_text(1,"+*#O:soon\n"); |
|
|
2190 | #endif |
|
|
2191 | d = g_strdup(_("soon")); |
|
|
2192 | break; |
|
|
2193 | case 1: |
|
|
2194 | d = get_distance(nav, distance, attr_navigation_short, 0); |
|
|
2195 | break; |
|
|
2196 | case 0: |
|
|
2197 | skip_roads = count_possible_turns(nav, |
|
|
2198 | cmd->prev ? cmd->prev->itm : nav->first, cmd->itm, |
|
|
2199 | cmd->delta); |
|
|
2200 | if (skip_roads > 0) |
|
|
2201 | { |
|
|
2202 | if (get_count_str(skip_roads + 1)) |
|
|
2203 | { |
|
|
2204 | #ifdef HAVE_API_ANDROID |
|
|
2205 | android_send_generic_text(1,"+*#O:Take the %1$s road to the %2$s\n"); |
|
|
2206 | gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1)); |
|
|
2207 | android_send_generic_text(1,xy); |
|
|
2208 | g_free(xy); |
|
|
2209 | xy=g_strdup_printf("+*#1:%s\n", dir); |
|
|
2210 | android_send_generic_text(1,xy); |
|
|
2211 | g_free(xy); |
|
|
2212 | #endif |
|
|
2213 | // TRANSLATORS: First argument is the how manieth street to take, second the direction |
|
|
2214 | ret = g_strdup_printf(_("Take the %1$s road to the %2$s"), |
|
|
2215 | get_count_str(skip_roads + 1), dir); |
|
|
2216 | return ret; |
|
|
2217 | } |
|
|
2218 | else |
|
|
2219 | { |
|
|
2220 | #ifdef HAVE_API_ANDROID |
|
|
2221 | android_send_generic_text(1,"+*#O:after %i roads\n"); |
|
|
2222 | gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads); |
|
|
2223 | android_send_generic_text(1,xy); |
|
|
2224 | g_free(xy); |
|
|
2225 | #endif |
|
|
2226 | d = g_strdup_printf(_("after %i roads"), skip_roads); |
|
|
2227 | } |
|
|
2228 | } |
|
|
2229 | else |
|
|
2230 | { |
|
|
2231 | #ifdef HAVE_API_ANDROID |
|
|
2232 | android_send_generic_text(1,"+*#O:now\n"); |
|
|
2233 | #endif |
|
|
2234 | d = g_strdup(_("now")); |
|
|
2235 | } |
|
|
2236 | break; |
1593 | case -2: |
2237 | case -2: |
1594 | return g_strdup_printf(_("then leave the roundabout at the %s"), get_exit_count_str(count_roundabout)); |
|
|
1595 | case 0: |
|
|
1596 | return g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout)); |
|
|
1597 | } |
|
|
1598 | } |
|
|
1599 | |
|
|
1600 | switch(level) { |
|
|
1601 | case 3: |
|
|
1602 | d=get_distance(nav, distance, type, 1); |
|
|
1603 | ret=g_strdup_printf(_("Follow the road for the next %s"), d); |
|
|
1604 | g_free(d); |
|
|
1605 | return ret; |
|
|
1606 | case 2: |
|
|
1607 | d=g_strdup(_("soon")); |
|
|
1608 | break; |
|
|
1609 | case 1: |
|
|
1610 | d=get_distance(nav, distance, attr_navigation_short, 0); |
|
|
1611 | break; |
|
|
1612 | case 0: |
|
|
1613 | skip_roads = count_possible_turns(nav,cmd->prev?cmd->prev->itm:nav->first,cmd->itm,cmd->delta); |
2238 | skip_roads = count_possible_turns(nav, cmd->prev->itm, cmd->itm, |
|
|
2239 | cmd->delta); |
1614 | if (skip_roads > 0) { |
2240 | if (skip_roads > 0) |
1615 | if (get_count_str(skip_roads+1)) { |
2241 | { |
1616 | /* TRANSLATORS: First argument is the how manieth street to take, second the direction */ |
2242 | // TRANSLATORS: First argument is the how manieth street to take, second the direction |
1617 | ret = g_strdup_printf(_("Take the %1$s road to the %2$s"), get_count_str(skip_roads+1), dir); |
2243 | // TRANSLATORS: EXAMPLE: ... then take the second road to the right |
|
|
2244 | if (get_count_str(skip_roads + 1)) |
|
|
2245 | { |
|
|
2246 | #ifdef HAVE_API_ANDROID |
|
|
2247 | android_send_generic_text(1,"+*#O:then take the %1$s road to the %2$s\n"); |
|
|
2248 | gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1)); |
|
|
2249 | android_send_generic_text(1,xy); |
|
|
2250 | g_free(xy); |
|
|
2251 | xy=g_strdup_printf("+*#1:%s\n", dir); |
|
|
2252 | android_send_generic_text(1,xy); |
|
|
2253 | g_free(xy); |
|
|
2254 | #endif |
|
|
2255 | ret = g_strdup_printf( |
|
|
2256 | _("then take the %1$s road to the %2$s"), |
|
|
2257 | get_count_str(skip_roads + 1), dir); |
1618 | return ret; |
2258 | return ret; |
1619 | } else { |
2259 | } |
|
|
2260 | else |
|
|
2261 | { |
|
|
2262 | #ifdef HAVE_API_ANDROID |
|
|
2263 | android_send_generic_text(1,"+*#O:after %i roads\n"); |
|
|
2264 | gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads); |
|
|
2265 | android_send_generic_text(1,xy); |
|
|
2266 | g_free(xy); |
|
|
2267 | #endif |
1620 | d = g_strdup_printf(_("after %i roads"), skip_roads); |
2268 | d = g_strdup_printf(_("after %i roads"), skip_roads); |
1621 | } |
2269 | } |
1622 | } else { |
2270 | |
1623 | d=g_strdup(_("now")); |
|
|
1624 | } |
2271 | } |
1625 | break; |
|
|
1626 | case -2: |
|
|
1627 | skip_roads = count_possible_turns(nav,cmd->prev->itm,cmd->itm,cmd->delta); |
|
|
1628 | if (skip_roads > 0) { |
|
|
1629 | /* TRANSLATORS: First argument is the how manieth street to take, second the direction */ |
|
|
1630 | if (get_count_str(skip_roads+1)) { |
|
|
1631 | ret = g_strdup_printf(_("then take the %1$s road to the %2$s"), get_count_str(skip_roads+1), dir); |
|
|
1632 | return ret; |
|
|
1633 | } else { |
2272 | else |
1634 | d = g_strdup_printf(_("after %i roads"), skip_roads); |
|
|
1635 | } |
2273 | { |
1636 | |
|
|
1637 | } else { |
|
|
1638 | d = g_strdup(""); |
2274 | d = g_strdup(""); |
1639 | } |
2275 | } |
1640 | break; |
2276 | break; |
1641 | default: |
2277 | default: |
|
|
2278 | #ifdef HAVE_API_ANDROID |
|
|
2279 | android_send_generic_text(1,"+*#O:error\n"); |
|
|
2280 | #endif |
1642 | d=g_strdup(_("error")); |
2281 | d = g_strdup(_("error")); |
1643 | } |
2282 | } |
|
|
2283 | |
1644 | if (cmd->itm->next) { |
2284 | if (cmd->itm->next) |
|
|
2285 | { |
1645 | int tellstreetname = 0; |
2286 | int tellstreetname = 0; |
1646 | char *destination = NULL; |
2287 | char *destination = NULL; |
1647 | |
2288 | |
1648 | if(type == attr_navigation_speech) { // In voice mode |
2289 | if (type == attr_navigation_speech) |
|
|
2290 | { // In voice mode |
1649 | // In Voice Mode only tell the street name in level 1 or in level 0 if level 1 |
2291 | // In Voice Mode only tell the street name in level 1 or in level 0 if level 1 |
1650 | // was skipped |
2292 | // was skipped |
1651 | |
2293 | |
|
|
2294 | if (level == 1) |
1652 | if (level == 1) { // we are close to the intersection |
2295 | { // we are close to the intersection |
1653 | cmd->itm->streetname_told = 1; // remeber to be checked when we turn |
2296 | cmd->itm->streetname_told = 1; // remeber to be checked when we turn |
1654 | tellstreetname = 1; // Ok so we tell the name of the street |
2297 | tellstreetname = 1; // Ok so we tell the name of the street |
1655 | } |
2298 | } |
1656 | |
2299 | |
1657 | if (level == 0) { |
2300 | if (level == 0) |
|
|
2301 | { |
1658 | if(cmd->itm->streetname_told == 0) // we are right at the intersection |
2302 | if (cmd->itm->streetname_told == 0) // we are right at the intersection |
|
|
2303 | { |
1659 | tellstreetname = 1; |
2304 | tellstreetname = 1; |
|
|
2305 | } |
1660 | else |
2306 | else |
|
|
2307 | { |
1661 | cmd->itm->streetname_told = 0; // reset just in case we come to the same street again |
2308 | cmd->itm->streetname_told = 0; // reset just in case we come to the same street again |
|
|
2309 | } |
1662 | } |
2310 | } |
1663 | |
2311 | |
1664 | } |
2312 | } |
1665 | else |
2313 | else |
|
|
2314 | { |
1666 | tellstreetname = 1; |
2315 | tellstreetname = 1; |
|
|
2316 | } |
1667 | |
2317 | |
|
|
2318 | if (global_speak_streetnames == 0) |
|
|
2319 | { |
|
|
2320 | // never speak streetnames (user config option) |
|
|
2321 | tellstreetname = 0; |
|
|
2322 | } |
|
|
2323 | |
1668 | if(nav->tell_street_name && tellstreetname) |
2324 | if (nav->tell_street_name && tellstreetname) |
|
|
2325 | { |
1669 | destination=navigation_item_destination(nav, cmd->itm, itm, " "); |
2326 | destination = navigation_item_destination(nav, cmd->itm, itm, " "); |
|
|
2327 | } |
1670 | |
2328 | |
1671 | if (level != -2) { |
2329 | if (level != -2) |
|
|
2330 | { |
|
|
2331 | #ifdef HAVE_API_ANDROID |
|
|
2332 | android_send_generic_text(1,"+*#O:Turn %1$s%2$s %3$s%4$s\n"); |
|
|
2333 | gchar* xy=g_strdup_printf("+*#1:%s\n", strength); |
|
|
2334 | android_send_generic_text(1,xy); |
|
|
2335 | g_free(xy); |
|
|
2336 | xy=g_strdup_printf("+*#1:%s\n", dir); |
|
|
2337 | android_send_generic_text(1,xy); |
|
|
2338 | g_free(xy); |
|
|
2339 | xy=g_strdup_printf("+*#1:%s\n", d); |
|
|
2340 | android_send_generic_text(1,xy); |
|
|
2341 | g_free(xy); |
|
|
2342 | xy=g_strdup_printf("+*#1:%s\n", destination ? destination : ""); |
|
|
2343 | android_send_generic_text(1,xy); |
|
|
2344 | g_free(xy); |
|
|
2345 | #endif |
1672 | /* TRANSLATORS: The first argument is strength, the second direction, the third distance and the fourth destination Example: 'Turn 'slightly' 'left' in '100 m' 'onto baker street' */ |
2346 | // TRANSLATORS: The first argument is strength, the second direction, the third distance and the fourth destination Example: 'Turn 'slightly' 'left' in '100 m' 'onto baker street' |
1673 | ret=g_strdup_printf(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination:""); |
2347 | ret = g_strdup_printf(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, |
|
|
2348 | d, destination ? destination : ""); |
|
|
2349 | } |
1674 | } else { |
2350 | else |
|
|
2351 | { |
|
|
2352 | #ifdef HAVE_API_ANDROID |
|
|
2353 | android_send_generic_text(1,"+*#O:then turn %1$s%2$s %3$s%4$s\n"); |
|
|
2354 | gchar* xy=g_strdup_printf("+*#1:%s\n", strength); |
|
|
2355 | android_send_generic_text(1,xy); |
|
|
2356 | g_free(xy); |
|
|
2357 | xy=g_strdup_printf("+*#1:%s\n", dir); |
|
|
2358 | android_send_generic_text(1,xy); |
|
|
2359 | g_free(xy); |
|
|
2360 | xy=g_strdup_printf("+*#1:%s\n", d); |
|
|
2361 | android_send_generic_text(1,xy); |
|
|
2362 | g_free(xy); |
|
|
2363 | xy=g_strdup_printf("+*#1:%s\n", destination ? destination : ""); |
|
|
2364 | android_send_generic_text(1,xy); |
|
|
2365 | g_free(xy); |
|
|
2366 | #endif |
1675 | /* TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination */ |
2367 | // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination |
1676 | ret=g_strdup_printf(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination:""); |
2368 | ret = g_strdup_printf(_("then turn %1$s%2$s %3$s%4$s"), strength, |
|
|
2369 | dir, d, destination ? destination : ""); |
1677 | } |
2370 | } |
1678 | g_free(destination); |
2371 | g_free(destination); |
1679 | } else { |
2372 | } |
|
|
2373 | else |
|
|
2374 | { |
1680 | if (!connect) { |
2375 | if (!connect) |
|
|
2376 | { |
|
|
2377 | #ifdef HAVE_API_ANDROID |
|
|
2378 | android_send_generic_text(1,"+*#O:You have reached your destination %s\n"); |
|
|
2379 | gchar* xy=g_strdup_printf("+*#1:%s\n", d); |
|
|
2380 | android_send_generic_text(1,xy); |
|
|
2381 | g_free(xy); |
|
|
2382 | #endif |
|
|
2383 | // TRANSLATORS: EXAMPLE: You have reached your destination in 300 meters |
1681 | ret=g_strdup_printf(_("You have reached your destination %s"), d); |
2384 | ret = g_strdup_printf(_("You have reached your destination %s"), d); |
|
|
2385 | } |
1682 | } else { |
2386 | else |
|
|
2387 | { |
|
|
2388 | #ifdef HAVE_API_ANDROID |
|
|
2389 | android_send_generic_text(1,"+*#O:then you have reached your destination.\n"); |
|
|
2390 | #endif |
1683 | ret=g_strdup_printf(_("then you have reached your destination.")); |
2391 | ret = g_strdup_printf(_("then you have reached your destination.")); |
1684 | } |
2392 | } |
1685 | } |
2393 | } |
1686 | g_free(d); |
2394 | g_free(d); |
1687 | return ret; |
2395 | return ret; |
1688 | } |
2396 | } |
… | |
… | |
1694 | * immediately following that maneuver, if these are too close and we're in speech navigation. |
2402 | * immediately following that maneuver, if these are too close and we're in speech navigation. |
1695 | * |
2403 | * |
1696 | * @return An announcement that should be made |
2404 | * @return An announcement that should be made |
1697 | */ |
2405 | */ |
1698 | static char * |
2406 | static char * |
1699 | show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type) |
2407 | show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm, |
|
|
2408 | struct navigation_command *cmd, enum attr_type type) |
1700 | { |
2409 | { |
1701 | struct navigation_command *cur,*prev; |
2410 | struct navigation_command *cur, *prev; |
1702 | int distance=itm->dest_length-cmd->itm->dest_length; |
2411 | int distance = itm->dest_length - cmd->itm->dest_length; |
1703 | int level, dist, i, time; |
2412 | int level, dist, i, time; |
1704 | int speech_time,time2nav; |
2413 | int speech_time, time2nav; |
1705 | char *ret,*old,*buf,*next; |
2414 | char *ret, *old, *buf, *next; |
1706 | |
2415 | |
1707 | if (type != attr_navigation_speech) { |
2416 | if (type != attr_navigation_speech) |
|
|
2417 | { |
1708 | return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only in speech navigation |
2418 | return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only in speech navigation |
1709 | } |
2419 | } |
1710 | |
2420 | |
1711 | level=navigation_get_announce_level(nav, itm->way.item.type, distance-cmd->length); |
2421 | level = navigation_get_announce_level(nav, itm->way.item.type, |
|
|
2422 | distance - cmd->length); |
1712 | |
2423 | |
1713 | if (level > 1) { |
2424 | if (level > 1) |
|
|
2425 | { |
1714 | return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only if they are close |
2426 | return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only if they are close |
1715 | } |
2427 | } |
1716 | |
2428 | |
1717 | if (cmd->itm->told) { |
2429 | if (cmd->itm->told) |
|
|
2430 | { |
|
|
2431 | #ifdef HAVE_API_ANDROID |
|
|
2432 | android_send_generic_text(1,"+*#C1:*CANCEL*\n"); |
|
|
2433 | #endif |
1718 | return g_strdup(""); |
2434 | return g_strdup(""); |
1719 | } |
2435 | } |
1720 | |
2436 | |
1721 | ret = show_maneuver(nav, itm, cmd, type, 0); |
2437 | ret = show_maneuver(nav, itm, cmd, type, 0); |
1722 | time2nav = navigation_time(itm,cmd->itm->prev); |
2438 | time2nav = navigation_time(itm, cmd->itm->prev); |
1723 | old = NULL; |
2439 | old = NULL; |
1724 | |
2440 | |
1725 | cur = cmd->next; |
2441 | cur = cmd->next; |
1726 | prev = cmd; |
2442 | prev = cmd; |
1727 | i = 0; |
2443 | i = 0; |
1728 | while (cur && cur->itm) { |
2444 | while (cur && cur->itm) |
|
|
2445 | { |
1729 | // We don't merge more than 3 announcements... |
2446 | // We don't merge more than 3 announcements... |
|
|
2447 | if (i > 1) |
1730 | if (i > 1) { // if you change this, please also change the value below, that is used to terminate the loop |
2448 | { // if you change this, please also change the value below, that is used to terminate the loop |
1731 | break; |
2449 | break; |
1732 | } |
2450 | } |
1733 | |
2451 | |
1734 | next = show_maneuver(nav,prev->itm, cur, type, 0); |
2452 | next = show_maneuver(nav, prev->itm, cur, type, 0); |
1735 | if (nav->speech) |
2453 | if (nav->speech) |
|
|
2454 | { |
1736 | speech_time = speech_estimate_duration(nav->speech,next); |
2455 | speech_time = speech_estimate_duration(nav->speech, next); |
|
|
2456 | } |
1737 | else |
2457 | else |
|
|
2458 | { |
1738 | speech_time = -1; |
2459 | speech_time = -1; |
|
|
2460 | } |
1739 | g_free(next); |
2461 | g_free(next); |
1740 | |
2462 | |
1741 | if (speech_time == -1) { // user didn't set cps |
2463 | if (speech_time == -1) |
|
|
2464 | { // user didn't set cps |
1742 | speech_time = 30; // assume 3 seconds |
2465 | speech_time = 30; // assume 3 seconds |
1743 | } |
2466 | } |
1744 | |
2467 | |
1745 | dist = prev->itm->dest_length - cur->itm->dest_length; |
2468 | dist = prev->itm->dest_length - cur->itm->dest_length; |
1746 | time = navigation_time(prev->itm,cur->itm->prev); |
2469 | time = navigation_time(prev->itm, cur->itm->prev); |
1747 | |
2470 | |
|
|
2471 | if (time >= (speech_time + 30)) |
1748 | if (time >= (speech_time + 30)) { // 3 seconds for understanding what has been said |
2472 | { // 3 seconds for understanding what has been said |
1749 | break; |
2473 | break; |
1750 | } |
2474 | } |
1751 | |
2475 | |
1752 | old = ret; |
2476 | old = ret; |
1753 | buf = show_maneuver(nav, prev->itm, cur, type, 1); |
2477 | buf = show_maneuver(nav, prev->itm, cur, type, 1); |
1754 | ret = g_strdup_printf("%s, %s", old, buf); |
2478 | ret = g_strdup_printf("%s, %s", old, buf); |
1755 | g_free(buf); |
2479 | g_free(buf); |
|
|
2480 | |
1756 | if (nav->speech && speech_estimate_duration(nav->speech,ret) > time2nav) { |
2481 | if (nav->speech && speech_estimate_duration(nav->speech, ret) |
|
|
2482 | > time2nav) |
|
|
2483 | { |
1757 | g_free(ret); |
2484 | g_free(ret); |
1758 | ret = old; |
2485 | ret = old; |
1759 | i = 2; // This will terminate the loop |
2486 | i = 2; // This will terminate the loop |
|
|
2487 | } |
1760 | } else { |
2488 | else |
|
|
2489 | { |
1761 | g_free(old); |
2490 | g_free(old); |
1762 | } |
2491 | } |
1763 | |
2492 | |
1764 | // If the two maneuvers are *really* close, we shouldn't tell the second one again, because TTS won't be fast enough |
2493 | // If the two maneuvers are *really* close, we shouldn't tell the second one again, because TTS won't be fast enough |
1765 | if (time <= speech_time) { |
2494 | if (time <= speech_time) |
|
|
2495 | { |
|
|
2496 | #ifdef HAVE_API_ANDROID |
|
|
2497 | android_send_generic_text(1,"+*#C2:*CANCEL*\n"); |
|
|
2498 | #endif |
1766 | cur->itm->told = 1; |
2499 | cur->itm->told = 1; |
1767 | } |
2500 | } |
1768 | |
2501 | |
1769 | prev = cur; |
2502 | prev = cur; |
1770 | cur = cur->next; |
2503 | cur = cur->next; |
… | |
… | |
1772 | } |
2505 | } |
1773 | |
2506 | |
1774 | return ret; |
2507 | return ret; |
1775 | } |
2508 | } |
1776 | |
2509 | |
1777 | static void |
|
|
1778 | navigation_call_callbacks(struct navigation *this_, int force_speech) |
2510 | static void navigation_call_callbacks(struct navigation *this_, |
|
|
2511 | int force_speech) |
1779 | { |
2512 | { |
1780 | int distance, level = 0; |
2513 | int distance, level = 0; |
1781 | void *p=this_; |
2514 | void *p = this_; |
1782 | if (!this_->cmd_first) |
2515 | if (!this_->cmd_first) |
1783 | return; |
2516 | return; |
1784 | callback_list_call(this_->callback, 1, &p); |
2517 | callback_list_call(this_->callback, 1, &p); |
1785 | dbg(1,"force_speech=%d turn_around=%d turn_around_limit=%d\n", force_speech, this_->turn_around, this_->turn_around_limit); |
2518 | //dbg(1,"force_speech=%d turn_around=%d turn_around_limit=%d\n", force_speech, this_->turn_around, this_->turn_around_limit); |
|
|
2519 | distance = round_distance( |
1786 | distance=round_distance(this_->first->dest_length-this_->cmd_first->itm->dest_length); |
2520 | this_->first->dest_length - this_->cmd_first->itm->dest_length); |
1787 | if (this_->turn_around_limit && this_->turn_around == this_->turn_around_limit) { |
2521 | if (this_->turn_around_limit && this_->turn_around |
|
|
2522 | == this_->turn_around_limit) |
|
|
2523 | { |
1788 | dbg(1,"distance=%d distance_turn=%d\n", distance, this_->distance_turn); |
2524 | //dbg(1,"distance=%d distance_turn=%d\n", distance, this_->distance_turn); |
1789 | while (distance > this_->distance_turn) { |
2525 | while (distance > this_->distance_turn) |
|
|
2526 | { |
1790 | this_->level_last=4; |
2527 | this_->level_last = 4; |
1791 | level=4; |
2528 | level = 4; |
1792 | force_speech=2; |
2529 | force_speech = 2; |
1793 | if (this_->distance_turn >= 500) |
2530 | if (this_->distance_turn >= 500) |
1794 | this_->distance_turn*=2; |
2531 | this_->distance_turn *= 2; |
1795 | else |
2532 | else |
1796 | this_->distance_turn=500; |
2533 | this_->distance_turn = 500; |
|
|
2534 | } |
1797 | } |
2535 | } |
1798 | } else if (!this_->turn_around_limit || this_->turn_around == -this_->turn_around_limit+1) { |
2536 | else if (!this_->turn_around_limit || this_->turn_around |
|
|
2537 | == -this_->turn_around_limit + 1) |
|
|
2538 | { |
1799 | this_->distance_turn=50; |
2539 | this_->distance_turn = 50; |
1800 | distance-=this_->cmd_first->length; |
2540 | distance -= this_->cmd_first->length; |
1801 | level=navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance); |
2541 | level = navigation_get_announce_level_cmd(this_, this_->first, |
|
|
2542 | this_->cmd_first, distance); |
1802 | if (level < this_->level_last) { |
2543 | if (level < this_->level_last) |
|
|
2544 | { |
1803 | /* only tell if the level is valid for more than 3 seconds */ |
2545 | /* only tell if the level is valid for more than 3 seconds */ |
1804 | int speed_distance=this_->first->speed*30/36; |
2546 | int speed_distance = this_->first->speed * 30 / 36; |
1805 | if (distance < speed_distance || navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance-speed_distance) == level) { |
2547 | if (distance < speed_distance || navigation_get_announce_level_cmd( |
|
|
2548 | this_, this_->first, this_->cmd_first, |
|
|
2549 | distance - speed_distance) == level) |
|
|
2550 | { |
1806 | dbg(1,"distance %d speed_distance %d\n",distance,speed_distance); |
2551 | dbg(1, "distance %d speed_distance %d\n", distance, |
|
|
2552 | speed_distance); |
1807 | dbg(1,"level %d < %d\n", level, this_->level_last); |
2553 | dbg(1, "level %d < %d\n", level, this_->level_last); |
1808 | this_->level_last=level; |
2554 | this_->level_last = level; |
1809 | force_speech=3; |
2555 | force_speech = 3; |
1810 | } |
|
|
1811 | } |
2556 | } |
|
|
2557 | } |
|
|
2558 | |
1812 | if (!item_is_equal(this_->cmd_first->itm->way.item, this_->item_last)) { |
2559 | if (!item_is_equal(this_->cmd_first->itm->way.item, this_->item_last)) |
|
|
2560 | { |
1813 | this_->item_last=this_->cmd_first->itm->way.item; |
2561 | this_->item_last = this_->cmd_first->itm->way.item; |
1814 | if (this_->delay) |
2562 | if (this_->delay) |
1815 | this_->curr_delay=this_->delay; |
2563 | this_->curr_delay = this_->delay; |
1816 | else |
2564 | else |
1817 | force_speech=5; |
2565 | force_speech = 5; |
|
|
2566 | } |
1818 | } else { |
2567 | else |
|
|
2568 | { |
1819 | if (this_->curr_delay) { |
2569 | if (this_->curr_delay) |
|
|
2570 | { |
1820 | this_->curr_delay--; |
2571 | this_->curr_delay--; |
1821 | if (!this_->curr_delay) |
2572 | if (!this_->curr_delay) |
1822 | force_speech=4; |
2573 | force_speech = 4; |
1823 | } |
|
|
1824 | } |
2574 | } |
1825 | } |
2575 | } |
|
|
2576 | } |
|
|
2577 | |
1826 | if (force_speech) { |
2578 | if (force_speech) |
|
|
2579 | { |
1827 | this_->level_last=level; |
2580 | this_->level_last = level; |
1828 | this_->curr_delay=0; |
2581 | this_->curr_delay = 0; |
1829 | dbg(1,"force_speech=%d distance=%d level=%d type=0x%x\n", force_speech, distance, level, this_->first->way.item.type); |
2582 | dbg(1, "force_speech=%d distance=%d level=%d type=0x%x\n", |
|
|
2583 | force_speech, distance, level, this_->first->way.item.type); |
1830 | callback_list_call(this_->callback_speech, 1, &p); |
2584 | callback_list_call(this_->callback_speech, 1, &p); |
1831 | } |
2585 | } |
1832 | } |
2586 | } |
1833 | |
2587 | |
1834 | static void |
|
|
1835 | navigation_update(struct navigation *this_, struct route *route, struct attr *attr) |
2588 | static void navigation_update(struct navigation *this_, struct route *route, |
|
|
2589 | struct attr *attr) |
1836 | { |
2590 | { |
1837 | struct map *map; |
2591 | struct map *map; |
1838 | struct map_rect *mr; |
2592 | struct map_rect *mr; |
1839 | struct item *ritem; /* Holds an item from the route map */ |
2593 | struct item *ritem; /* Holds an item from the route map */ |
1840 | struct item *sitem; /* Holds the corresponding item from the actual map */ |
2594 | struct item *sitem; /* Holds the corresponding item from the actual map */ |
1841 | struct attr street_item,street_direction; |
2595 | struct attr street_item, street_direction; |
1842 | struct navigation_itm *itm; |
2596 | struct navigation_itm *itm; |
1843 | struct attr vehicleprofile; |
2597 | struct attr vehicleprofile; |
1844 | int mode=0, incr=0, first=1; |
2598 | int mode = 0, incr = 0, first = 1; |
1845 | if (attr->type != attr_route_status) |
2599 | if (attr->type != attr_route_status) |
1846 | return; |
2600 | return; |
1847 | |
2601 | |
1848 | dbg(1,"enter %d\n", mode); |
2602 | dbg(1, "enter %d\n", mode); |
1849 | if (attr->u.num == route_status_no_destination || attr->u.num == route_status_not_found || attr->u.num == route_status_path_done_new) |
2603 | if (attr->u.num == route_status_no_destination || attr->u.num |
|
|
2604 | == route_status_not_found || attr->u.num |
|
|
2605 | == route_status_path_done_new) |
1850 | navigation_flush(this_); |
2606 | navigation_flush(this_); |
1851 | if (attr->u.num != route_status_path_done_new && attr->u.num != route_status_path_done_incremental) |
2607 | if (attr->u.num != route_status_path_done_new && attr->u.num |
|
|
2608 | != route_status_path_done_incremental) |
1852 | return; |
2609 | return; |
1853 | |
2610 | |
1854 | if (! this_->route) |
2611 | if (!this_->route) |
1855 | return; |
2612 | return; |
1856 | map=route_get_map(this_->route); |
2613 | map = route_get_map(this_->route); |
1857 | if (! map) |
2614 | if (!map) |
1858 | return; |
2615 | return; |
1859 | mr=map_rect_new(map, NULL); |
2616 | mr = map_rect_new(map, NULL); |
1860 | if (! mr) |
2617 | if (!mr) |
1861 | return; |
2618 | return; |
1862 | if (route_get_attr(route, attr_vehicleprofile, &vehicleprofile, NULL)) |
2619 | if (route_get_attr(route, attr_vehicleprofile, &vehicleprofile, NULL)) |
1863 | this_->vehicleprofile=vehicleprofile.u.vehicleprofile; |
2620 | this_->vehicleprofile = vehicleprofile.u.vehicleprofile; |
1864 | else |
2621 | else |
1865 | this_->vehicleprofile=NULL; |
2622 | this_->vehicleprofile = NULL; |
1866 | dbg(1,"enter\n"); |
2623 | //dbg(1,"enter\n"); |
|
|
2624 | |
1867 | while ((ritem=map_rect_get_item(mr))) { |
2625 | while ((ritem = map_rect_get_item(mr))) |
|
|
2626 | { |
1868 | if (ritem->type == type_route_start && this_->turn_around > -this_->turn_around_limit+1) |
2627 | if (ritem->type == type_route_start && this_->turn_around |
|
|
2628 | > -this_->turn_around_limit + 1) |
1869 | this_->turn_around--; |
2629 | this_->turn_around--; |
1870 | if (ritem->type == type_route_start_reverse && this_->turn_around < this_->turn_around_limit) |
2630 | if (ritem->type == type_route_start_reverse && this_->turn_around |
|
|
2631 | < this_->turn_around_limit) |
1871 | this_->turn_around++; |
2632 | this_->turn_around++; |
1872 | if (ritem->type != type_street_route) |
2633 | if (ritem->type != type_street_route) |
1873 | continue; |
2634 | continue; |
|
|
2635 | |
1874 | if (first && item_attr_get(ritem, attr_street_item, &street_item)) { |
2636 | if (first && item_attr_get(ritem, attr_street_item, &street_item)) |
|
|
2637 | { |
1875 | first=0; |
2638 | first = 0; |
1876 | if (!item_attr_get(ritem, attr_direction, &street_direction)) |
2639 | if (!item_attr_get(ritem, attr_direction, &street_direction)) |
1877 | street_direction.u.num=0; |
2640 | street_direction.u.num = 0; |
1878 | sitem=street_item.u.item; |
2641 | sitem = street_item.u.item; |
1879 | dbg(1,"sitem=%p\n", sitem); |
2642 | //dbg(1,"sitem=%p\n", sitem); |
1880 | itm=item_hash_lookup(this_->hash, sitem); |
2643 | itm = item_hash_lookup(this_->hash, sitem); |
1881 | dbg(2,"itm for item with id (0x%x,0x%x) is %p\n", sitem->id_hi, sitem->id_lo, itm); |
2644 | //dbg(2,"itm for item with id (0x%x,0x%x) is %p\n", sitem->id_hi, sitem->id_lo, itm); |
|
|
2645 | |
1882 | if (itm && itm->way.dir != street_direction.u.num) { |
2646 | if (itm && itm->way.dir != street_direction.u.num) |
|
|
2647 | { |
1883 | dbg(2,"wrong direction\n"); |
2648 | //dbg(2,"wrong direction\n"); |
1884 | itm=NULL; |
2649 | itm = NULL; |
1885 | } |
2650 | } |
1886 | navigation_destroy_itms_cmds(this_, itm); |
2651 | navigation_destroy_itms_cmds(this_, itm); |
1887 | if (itm) { |
2652 | if (itm) |
|
|
2653 | { |
1888 | navigation_itm_update(itm, ritem); |
2654 | navigation_itm_update(itm, ritem); |
1889 | break; |
2655 | break; |
1890 | } |
2656 | } |
1891 | dbg(1,"not on track\n"); |
2657 | //dbg(1,"not on track\n"); |
1892 | } |
2658 | } |
1893 | navigation_itm_new(this_, ritem); |
2659 | navigation_itm_new(this_, ritem); |
1894 | } |
2660 | } |
1895 | dbg(2,"turn_around=%d\n", this_->turn_around); |
2661 | dbg(2, "turn_around=%d\n", this_->turn_around); |
1896 | if (first) |
2662 | if (first) |
1897 | navigation_destroy_itms_cmds(this_, NULL); |
2663 | navigation_destroy_itms_cmds(this_, NULL); |
1898 | else { |
2664 | else |
|
|
2665 | { |
1899 | if (! ritem) { |
2666 | if (!ritem) |
|
|
2667 | { |
1900 | navigation_itm_new(this_, NULL); |
2668 | navigation_itm_new(this_, NULL); |
1901 | make_maneuvers(this_,this_->route); |
2669 | make_maneuvers(this_, this_->route); |
1902 | } |
2670 | } |
1903 | calculate_dest_distance(this_, incr); |
2671 | calculate_dest_distance(this_, incr); |
1904 | profile(0,"end"); |
2672 | //profile(0,"end"); |
1905 | navigation_call_callbacks(this_, FALSE); |
2673 | navigation_call_callbacks(this_, FALSE); |
1906 | } |
2674 | } |
1907 | map_rect_destroy(mr); |
2675 | map_rect_destroy(mr); |
1908 | } |
2676 | } |
1909 | |
2677 | |
1910 | static void |
|
|
1911 | navigation_flush(struct navigation *this_) |
2678 | static void navigation_flush(struct navigation *this_) |
1912 | { |
2679 | { |
1913 | navigation_destroy_itms_cmds(this_, NULL); |
2680 | navigation_destroy_itms_cmds(this_, NULL); |
1914 | } |
2681 | } |
1915 | |
2682 | |
1916 | |
|
|
1917 | void |
|
|
1918 | navigation_destroy(struct navigation *this_) |
2683 | void navigation_destroy(struct navigation *this_) |
1919 | { |
2684 | { |
1920 | navigation_flush(this_); |
2685 | navigation_flush(this_); |
1921 | item_hash_destroy(this_->hash); |
2686 | item_hash_destroy(this_->hash); |
1922 | callback_list_destroy(this_->callback); |
2687 | callback_list_destroy(this_->callback); |
1923 | callback_list_destroy(this_->callback_speech); |
2688 | callback_list_destroy(this_->callback_speech); |
1924 | g_free(this_); |
2689 | g_free(this_); |
1925 | } |
2690 | } |
1926 | |
2691 | |
1927 | int |
|
|
1928 | navigation_register_callback(struct navigation *this_, enum attr_type type, struct callback *cb) |
2692 | int navigation_register_callback(struct navigation *this_, enum attr_type type, |
|
|
2693 | struct callback *cb) |
1929 | { |
2694 | { |
1930 | if (type == attr_navigation_speech) |
2695 | if (type == attr_navigation_speech) |
1931 | callback_list_add(this_->callback_speech, cb); |
2696 | callback_list_add(this_->callback_speech, cb); |
1932 | else |
2697 | else |
1933 | callback_list_add(this_->callback, cb); |
2698 | callback_list_add(this_->callback, cb); |
1934 | return 1; |
2699 | return 1; |
1935 | } |
2700 | } |
1936 | |
2701 | |
1937 | void |
2702 | void navigation_unregister_callback(struct navigation *this_, |
1938 | navigation_unregister_callback(struct navigation *this_, enum attr_type type, struct callback *cb) |
2703 | enum attr_type type, struct callback *cb) |
1939 | { |
2704 | { |
1940 | if (type == attr_navigation_speech) |
2705 | if (type == attr_navigation_speech) |
1941 | callback_list_remove_destroy(this_->callback_speech, cb); |
2706 | callback_list_remove_destroy(this_->callback_speech, cb); |
1942 | else |
2707 | else |
1943 | callback_list_remove_destroy(this_->callback, cb); |
2708 | callback_list_remove_destroy(this_->callback, cb); |
… | |
… | |
1945 | |
2710 | |
1946 | struct map * |
2711 | struct map * |
1947 | navigation_get_map(struct navigation *this_) |
2712 | navigation_get_map(struct navigation *this_) |
1948 | { |
2713 | { |
1949 | struct attr *attrs[5]; |
2714 | struct attr *attrs[5]; |
1950 | struct attr type,navigation,data,description; |
2715 | struct attr type, navigation, data, description; |
1951 | type.type=attr_type; |
2716 | type.type = attr_type; |
1952 | type.u.str="navigation"; |
2717 | type.u.str = "navigation"; |
1953 | navigation.type=attr_navigation; |
2718 | navigation.type = attr_navigation; |
1954 | navigation.u.navigation=this_; |
2719 | navigation.u.navigation = this_; |
1955 | data.type=attr_data; |
2720 | data.type = attr_data; |
1956 | data.u.str=""; |
2721 | data.u.str = ""; |
1957 | description.type=attr_description; |
2722 | description.type = attr_description; |
1958 | description.u.str="Navigation"; |
2723 | description.u.str = "Navigation"; |
1959 | |
2724 | |
1960 | attrs[0]=&type; |
2725 | attrs[0] = &type; |
1961 | attrs[1]=&navigation; |
2726 | attrs[1] = &navigation; |
1962 | attrs[2]=&data; |
2727 | attrs[2] = &data; |
1963 | attrs[3]=&description; |
2728 | attrs[3] = &description; |
1964 | attrs[4]=NULL; |
2729 | attrs[4] = NULL; |
1965 | if (! this_->map) |
2730 | if (!this_->map) |
1966 | this_->map=map_new(NULL, attrs); |
2731 | this_->map = map_new(NULL, attrs); |
1967 | return this_->map; |
2732 | return this_->map; |
1968 | } |
2733 | } |
1969 | |
2734 | |
1970 | struct map_priv { |
2735 | struct map_priv |
|
|
2736 | { |
1971 | struct navigation *navigation; |
2737 | struct navigation *navigation; |
1972 | }; |
2738 | }; |
1973 | |
2739 | |
1974 | struct map_rect_priv { |
2740 | struct map_rect_priv |
|
|
2741 | { |
1975 | struct navigation *nav; |
2742 | struct navigation *nav; |
1976 | struct navigation_command *cmd; |
2743 | struct navigation_command *cmd; |
1977 | struct navigation_command *cmd_next; |
2744 | struct navigation_command *cmd_next; |
1978 | struct navigation_itm *itm; |
2745 | struct navigation_itm *itm; |
1979 | struct navigation_itm *itm_next; |
2746 | struct navigation_itm *itm_next; |
… | |
… | |
1986 | struct navigation_way *ways; |
2753 | struct navigation_way *ways; |
1987 | int show_all; |
2754 | int show_all; |
1988 | char *str; |
2755 | char *str; |
1989 | }; |
2756 | }; |
1990 | |
2757 | |
1991 | static int |
|
|
1992 | navigation_map_item_coord_get(void *priv_data, struct coord *c, int count) |
2758 | static int navigation_map_item_coord_get(void *priv_data, struct coord *c, |
|
|
2759 | int count) |
1993 | { |
2760 | { |
1994 | struct map_rect_priv *this=priv_data; |
2761 | struct map_rect_priv *this = priv_data; |
1995 | if (this->ccount || ! count) |
2762 | if (this->ccount || !count) |
1996 | return 0; |
2763 | return 0; |
1997 | *c=this->itm->start; |
2764 | *c = this->itm->start; |
1998 | this->ccount=1; |
2765 | this->ccount = 1; |
1999 | return 1; |
2766 | return 1; |
2000 | } |
2767 | } |
2001 | |
2768 | |
2002 | static int |
2769 | static int navigation_map_item_attr_get(void *priv_data, |
2003 | navigation_map_item_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) |
2770 | enum attr_type attr_type, struct attr *attr) |
2004 | { |
2771 | { |
2005 | struct map_rect_priv *this_=priv_data; |
2772 | struct map_rect_priv *this_ = priv_data; |
2006 | struct navigation_command *cmd=this_->cmd; |
2773 | struct navigation_command *cmd = this_->cmd; |
2007 | struct navigation_itm *itm=this_->itm; |
2774 | struct navigation_itm *itm = this_->itm; |
2008 | struct navigation_itm *prev=itm->prev; |
2775 | struct navigation_itm *prev = itm->prev; |
2009 | attr->type=attr_type; |
2776 | attr->type = attr_type; |
2010 | |
2777 | |
2011 | if (this_->str) { |
2778 | if (this_->str) |
|
|
2779 | { |
2012 | g_free(this_->str); |
2780 | g_free(this_->str); |
2013 | this_->str=NULL; |
2781 | this_->str = NULL; |
2014 | } |
2782 | } |
2015 | |
2783 | |
2016 | if (cmd) { |
2784 | if (cmd) |
|
|
2785 | { |
2017 | if (cmd->itm != itm) |
2786 | if (cmd->itm != itm) |
2018 | cmd=NULL; |
2787 | cmd = NULL; |
2019 | } |
2788 | } |
2020 | switch(attr_type) { |
2789 | switch (attr_type) |
|
|
2790 | { |
2021 | case attr_navigation_short: |
2791 | case attr_navigation_short: |
2022 | this_->attr_next=attr_navigation_long; |
2792 | this_->attr_next = attr_navigation_long; |
2023 | if (cmd) { |
2793 | if (cmd) |
|
|
2794 | { |
2024 | this_->str=attr->u.str=show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type); |
2795 | this_->str = attr->u.str = show_next_maneuvers(this_->nav, |
|
|
2796 | this_->cmd_itm, cmd, attr_type); |
|
|
2797 | return 1; |
|
|
2798 | } |
|
|
2799 | return 0; |
|
|
2800 | case attr_navigation_long: |
|
|
2801 | this_->attr_next = attr_navigation_long_exact; |
|
|
2802 | if (cmd) |
|
|
2803 | { |
|
|
2804 | this_->str = attr->u.str = show_next_maneuvers(this_->nav, |
|
|
2805 | this_->cmd_itm, cmd, attr_type); |
|
|
2806 | return 1; |
|
|
2807 | } |
|
|
2808 | return 0; |
|
|
2809 | case attr_navigation_long_exact: |
|
|
2810 | this_->attr_next = attr_navigation_speech; |
|
|
2811 | if (cmd) |
|
|
2812 | { |
|
|
2813 | this_->str = attr->u.str = show_next_maneuvers(this_->nav, |
|
|
2814 | this_->cmd_itm, cmd, attr_type); |
|
|
2815 | return 1; |
|
|
2816 | } |
|
|
2817 | return 0; |
|
|
2818 | case attr_navigation_speech: |
|
|
2819 | this_->attr_next = attr_length; |
|
|
2820 | if (cmd) |
|
|
2821 | { |
|
|
2822 | this_->str = attr->u.str = show_next_maneuvers(this_->nav, |
|
|
2823 | this_->cmd_itm, this_->cmd, attr_type); |
|
|
2824 | return 1; |
|
|
2825 | } |
|
|
2826 | return 0; |
|
|
2827 | case attr_length: |
|
|
2828 | this_->attr_next = attr_time; |
|
|
2829 | if (cmd) |
|
|
2830 | { |
|
|
2831 | attr->u.num = this_->cmd_itm->dest_length |
|
|
2832 | - cmd->itm->dest_length; |
|
|
2833 | return 1; |
|
|
2834 | } |
|
|
2835 | return 0; |
|
|
2836 | case attr_time: |
|
|
2837 | this_->attr_next = attr_destination_length; |
|
|
2838 | if (cmd) |
|
|
2839 | { |
|
|
2840 | attr->u.num = this_->cmd_itm->dest_time - cmd->itm->dest_time; |
|
|
2841 | return 1; |
|
|
2842 | } |
|
|
2843 | return 0; |
|
|
2844 | case attr_destination_length: |
|
|
2845 | attr->u.num = itm->dest_length; |
|
|
2846 | this_->attr_next = attr_destination_time; |
2025 | return 1; |
2847 | return 1; |
2026 | } |
2848 | case attr_destination_time: |
2027 | return 0; |
2849 | attr->u.num = itm->dest_time; |
2028 | case attr_navigation_long: |
2850 | this_->attr_next = attr_street_name; |
2029 | this_->attr_next=attr_navigation_long_exact; |
|
|
2030 | if (cmd) { |
|
|
2031 | this_->str=attr->u.str=show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type); |
|
|
2032 | return 1; |
2851 | return 1; |
2033 | } |
|
|
2034 | return 0; |
|
|
2035 | case attr_navigation_long_exact: |
|
|
2036 | this_->attr_next=attr_navigation_speech; |
|
|
2037 | if (cmd) { |
|
|
2038 | this_->str=attr->u.str=show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type); |
|
|
2039 | return 1; |
|
|
2040 | } |
|
|
2041 | return 0; |
|
|
2042 | case attr_navigation_speech: |
|
|
2043 | this_->attr_next=attr_length; |
|
|
2044 | if (cmd) { |
|
|
2045 | this_->str=attr->u.str=show_next_maneuvers(this_->nav, this_->cmd_itm, this_->cmd, attr_type); |
|
|
2046 | return 1; |
|
|
2047 | } |
|
|
2048 | return 0; |
|
|
2049 | case attr_length: |
|
|
2050 | this_->attr_next=attr_time; |
|
|
2051 | if (cmd) { |
|
|
2052 | attr->u.num=this_->cmd_itm->dest_length-cmd->itm->dest_length; |
|
|
2053 | return 1; |
|
|
2054 | } |
|
|
2055 | return 0; |
|
|
2056 | case attr_time: |
|
|
2057 | this_->attr_next=attr_destination_length; |
|
|
2058 | if (cmd) { |
|
|
2059 | attr->u.num=this_->cmd_itm->dest_time-cmd->itm->dest_time; |
|
|
2060 | return 1; |
|
|
2061 | } |
|
|
2062 | return 0; |
|
|
2063 | case attr_destination_length: |
|
|
2064 | attr->u.num=itm->dest_length; |
|
|
2065 | this_->attr_next=attr_destination_time; |
|
|
2066 | return 1; |
|
|
2067 | case attr_destination_time: |
|
|
2068 | attr->u.num=itm->dest_time; |
|
|
2069 | this_->attr_next=attr_street_name; |
|
|
2070 | return 1; |
|
|
2071 | case attr_street_name: |
2852 | case attr_street_name: |
2072 | attr->u.str=itm->way.name1; |
2853 | attr->u.str = itm->way.name1; |
2073 | this_->attr_next=attr_street_name_systematic; |
2854 | this_->attr_next = attr_street_name_systematic; |
2074 | if (attr->u.str) |
2855 | if (attr->u.str) |
2075 | return 1; |
|
|
2076 | return 0; |
|
|
2077 | case attr_street_name_systematic: |
|
|
2078 | attr->u.str=itm->way.name2; |
|
|
2079 | this_->attr_next=attr_debug; |
|
|
2080 | if (attr->u.str) |
|
|
2081 | return 1; |
|
|
2082 | return 0; |
|
|
2083 | case attr_debug: |
|
|
2084 | switch(this_->debug_idx) { |
|
|
2085 | case 0: |
|
|
2086 | this_->debug_idx++; |
|
|
2087 | this_->str=attr->u.str=g_strdup_printf("angle:%d (- %d)", itm->way.angle2, itm->angle_end); |
|
|
2088 | return 1; |
|
|
2089 | case 1: |
|
|
2090 | this_->debug_idx++; |
|
|
2091 | this_->str=attr->u.str=g_strdup_printf("item type:%s", item_to_name(itm->way.item.type)); |
|
|
2092 | return 1; |
|
|
2093 | case 2: |
|
|
2094 | this_->debug_idx++; |
|
|
2095 | if (cmd) { |
|
|
2096 | this_->str=attr->u.str=g_strdup_printf("delta:%d", cmd->delta); |
|
|
2097 | return 1; |
2856 | return 1; |
2098 | } |
2857 | return 0; |
2099 | case 3: |
2858 | case attr_street_name_systematic: |
2100 | this_->debug_idx++; |
2859 | attr->u.str = itm->way.name2; |
2101 | if (prev) { |
2860 | this_->attr_next = attr_debug; |
2102 | this_->str=attr->u.str=g_strdup_printf("prev street_name:%s", prev->way.name1); |
2861 | if (attr->u.str) |
2103 | return 1; |
2862 | return 1; |
|
|
2863 | return 0; |
|
|
2864 | case attr_debug: |
|
|
2865 | switch (this_->debug_idx) |
2104 | } |
2866 | { |
2105 | case 4: |
2867 | case 0: |
2106 | this_->debug_idx++; |
2868 | this_->debug_idx++; |
2107 | if (prev) { |
2869 | this_->str = attr->u.str = g_strdup_printf( |
2108 | this_->str=attr->u.str=g_strdup_printf("prev street_name_systematic:%s", prev->way.name2); |
2870 | "angle:%d (- %d)", itm->way.angle2, itm->angle_end); |
2109 | return 1; |
2871 | return 1; |
2110 | } |
|
|
2111 | case 5: |
2872 | case 1: |
2112 | this_->debug_idx++; |
2873 | this_->debug_idx++; |
2113 | if (prev) { |
2874 | this_->str = attr->u.str = g_strdup_printf("item type:%s", |
2114 | this_->str=attr->u.str=g_strdup_printf("prev angle:(%d -) %d", prev->way.angle2, prev->angle_end); |
2875 | item_to_name(itm->way.item.type)); |
2115 | return 1; |
2876 | return 1; |
2116 | } |
|
|
2117 | case 6: |
2877 | case 2: |
2118 | this_->debug_idx++; |
2878 | this_->debug_idx++; |
|
|
2879 | if (cmd) |
|
|
2880 | { |
|
|
2881 | this_->str = attr->u.str = g_strdup_printf("delta:%d", |
|
|
2882 | cmd->delta); |
|
|
2883 | return 1; |
|
|
2884 | } |
|
|
2885 | case 3: |
|
|
2886 | this_->debug_idx++; |
|
|
2887 | if (prev) |
|
|
2888 | { |
|
|
2889 | this_->str = attr->u.str = g_strdup_printf( |
|
|
2890 | "prev street_name:%s", prev->way.name1); |
|
|
2891 | return 1; |
|
|
2892 | } |
|
|
2893 | case 4: |
|
|
2894 | this_->debug_idx++; |
|
|
2895 | if (prev) |
|
|
2896 | { |
|
|
2897 | this_->str = attr->u.str = g_strdup_printf( |
|
|
2898 | "prev street_name_systematic:%s", |
|
|
2899 | prev->way.name2); |
|
|
2900 | return 1; |
|
|
2901 | } |
|
|
2902 | case 5: |
|
|
2903 | this_->debug_idx++; |
|
|
2904 | if (prev) |
|
|
2905 | { |
|
|
2906 | this_->str = attr->u.str = g_strdup_printf( |
|
|
2907 | "prev angle:(%d -) %d", prev->way.angle2, |
|
|
2908 | prev->angle_end); |
|
|
2909 | return 1; |
|
|
2910 | } |
|
|
2911 | case 6: |
|
|
2912 | this_->debug_idx++; |
2119 | this_->ways=itm->way.next; |
2913 | this_->ways = itm->way.next; |
2120 | if (prev) { |
2914 | if (prev) |
2121 | this_->str=attr->u.str=g_strdup_printf("prev item type:%s", item_to_name(prev->way.item.type)); |
2915 | { |
|
|
2916 | this_->str = attr->u.str = g_strdup_printf( |
|
|
2917 | "prev item type:%s", |
|
|
2918 | item_to_name(prev->way.item.type)); |
|
|
2919 | return 1; |
|
|
2920 | } |
|
|
2921 | case 7: |
|
|
2922 | if (this_->ways && prev) |
|
|
2923 | { |
|
|
2924 | this_->str |
|
|
2925 | = attr->u.str |
|
|
2926 | = g_strdup_printf( |
|
|
2927 | "other item angle:%d delta:%d flags:%d dir:%d type:%s id:(0x%x,0x%x)", |
|
|
2928 | this_->ways->angle2, |
|
|
2929 | angle_delta(prev->angle_end, |
|
|
2930 | this_->ways->angle2), |
|
|
2931 | this_->ways->flags, |
|
|
2932 | this_->ways->dir, |
|
|
2933 | item_to_name( |
|
|
2934 | this_->ways->item.type), |
|
|
2935 | this_->ways->item.id_hi, |
|
|
2936 | this_->ways->item.id_lo); |
|
|
2937 | this_->ways = this_->ways->next; |
|
|
2938 | return 1; |
|
|
2939 | } |
|
|
2940 | this_->debug_idx++; |
|
|
2941 | case 8: |
|
|
2942 | this_->debug_idx++; |
|
|
2943 | if (prev) |
|
|
2944 | { |
|
|
2945 | int delta = 0; |
|
|
2946 | char *reason = NULL; |
|
|
2947 | maneuver_required2(this_->nav, prev, itm, &delta, |
|
|
2948 | &reason); |
|
|
2949 | this_->str = attr->u.str = g_strdup_printf("reason:%s", |
|
|
2950 | reason); |
|
|
2951 | return 1; |
|
|
2952 | } |
|
|
2953 | |
|
|
2954 | default: |
|
|
2955 | this_->attr_next = attr_none; |
|
|
2956 | return 0; |
|
|
2957 | } |
|
|
2958 | case attr_any: |
|
|
2959 | while (this_->attr_next != attr_none) |
|
|
2960 | { |
|
|
2961 | if (navigation_map_item_attr_get(priv_data, this_->attr_next, |
|
|
2962 | attr)) |
2122 | return 1; |
2963 | return 1; |
2123 | } |
2964 | } |
2124 | case 7: |
|
|
2125 | if (this_->ways && prev) { |
|
|
2126 | this_->str=attr->u.str=g_strdup_printf("other item angle:%d delta:%d flags:%d dir:%d type:%s id:(0x%x,0x%x)", this_->ways->angle2, angle_delta(prev->angle_end, this_->ways->angle2), this_->ways->flags, this_->ways->dir, item_to_name(this_->ways->item.type), this_->ways->item.id_hi, this_->ways->item.id_lo); |
|
|
2127 | this_->ways=this_->ways->next; |
|
|
2128 | return 1; |
2965 | return 0; |
2129 | } |
|
|
2130 | this_->debug_idx++; |
|
|
2131 | case 8: |
|
|
2132 | this_->debug_idx++; |
|
|
2133 | if (prev) { |
|
|
2134 | int delta=0; |
|
|
2135 | char *reason=NULL; |
|
|
2136 | maneuver_required2(this_->nav, prev, itm, &delta, &reason); |
|
|
2137 | this_->str=attr->u.str=g_strdup_printf("reason:%s",reason); |
|
|
2138 | return 1; |
|
|
2139 | } |
|
|
2140 | |
|
|
2141 | default: |
2966 | default: |
2142 | this_->attr_next=attr_none; |
2967 | attr->type = attr_none; |
2143 | return 0; |
2968 | return 0; |
2144 | } |
2969 | } |
2145 | case attr_any: |
|
|
2146 | while (this_->attr_next != attr_none) { |
|
|
2147 | if (navigation_map_item_attr_get(priv_data, this_->attr_next, attr)) |
|
|
2148 | return 1; |
|
|
2149 | } |
|
|
2150 | return 0; |
|
|
2151 | default: |
|
|
2152 | attr->type=attr_none; |
|
|
2153 | return 0; |
|
|
2154 | } |
|
|
2155 | } |
2970 | } |
2156 | |
2971 | |
2157 | static struct item_methods navigation_map_item_methods = { |
2972 | static struct item_methods navigation_map_item_methods = |
2158 | NULL, |
2973 | { NULL, navigation_map_item_coord_get, NULL, navigation_map_item_attr_get, }; |
2159 | navigation_map_item_coord_get, |
|
|
2160 | NULL, |
|
|
2161 | navigation_map_item_attr_get, |
|
|
2162 | }; |
|
|
2163 | |
2974 | |
2164 | |
|
|
2165 | static void |
|
|
2166 | navigation_map_destroy(struct map_priv *priv) |
2975 | static void navigation_map_destroy(struct map_priv *priv) |
2167 | { |
2976 | { |
2168 | g_free(priv); |
2977 | g_free(priv); |
2169 | } |
2978 | } |
2170 | |
2979 | |
2171 | static void |
|
|
2172 | navigation_map_rect_init(struct map_rect_priv *priv) |
2980 | static void navigation_map_rect_init(struct map_rect_priv *priv) |
2173 | { |
2981 | { |
2174 | priv->cmd_next=priv->nav->cmd_first; |
2982 | priv->cmd_next = priv->nav->cmd_first; |
2175 | priv->cmd_itm_next=priv->itm_next=priv->nav->first; |
2983 | priv->cmd_itm_next = priv->itm_next = priv->nav->first; |
2176 | } |
2984 | } |
2177 | |
2985 | |
2178 | static struct map_rect_priv * |
2986 | static struct map_rect_priv * |
2179 | navigation_map_rect_new(struct map_priv *priv, struct map_selection *sel) |
2987 | navigation_map_rect_new(struct map_priv *priv, struct map_selection *sel) |
2180 | { |
2988 | { |
2181 | struct navigation *nav=priv->navigation; |
2989 | struct navigation *nav = priv->navigation; |
2182 | struct map_rect_priv *ret=g_new0(struct map_rect_priv, 1); |
2990 | struct map_rect_priv *ret=g_new0(struct map_rect_priv, 1); |
2183 | ret->nav=nav; |
2991 | ret->nav = nav; |
2184 | navigation_map_rect_init(ret); |
2992 | navigation_map_rect_init(ret); |
2185 | ret->item.meth=&navigation_map_item_methods; |
2993 | ret->item.meth = &navigation_map_item_methods; |
2186 | ret->item.priv_data=ret; |
2994 | ret->item.priv_data = ret; |
2187 | #ifdef DEBUG |
2995 | #ifdef DEBUG |
2188 | ret->show_all=1; |
2996 | ret->show_all=1; |
2189 | #endif |
2997 | #endif |
2190 | return ret; |
2998 | return ret; |
2191 | } |
2999 | } |
2192 | |
3000 | |
2193 | static void |
|
|
2194 | navigation_map_rect_destroy(struct map_rect_priv *priv) |
3001 | static void navigation_map_rect_destroy(struct map_rect_priv *priv) |
2195 | { |
3002 | { |
2196 | g_free(priv); |
3003 | g_free(priv); |
2197 | } |
3004 | } |
2198 | |
3005 | |
2199 | static struct item * |
3006 | static struct item * |
2200 | navigation_map_get_item(struct map_rect_priv *priv) |
3007 | navigation_map_get_item(struct map_rect_priv *priv) |
2201 | { |
3008 | { |
2202 | struct item *ret=&priv->item; |
3009 | struct item *ret = &priv->item; |
2203 | int delta; |
3010 | int delta; |
2204 | if (!priv->itm_next) |
3011 | if (!priv->itm_next) |
2205 | return NULL; |
3012 | return NULL; |
2206 | priv->itm=priv->itm_next; |
3013 | priv->itm = priv->itm_next; |
2207 | priv->cmd=priv->cmd_next; |
3014 | priv->cmd = priv->cmd_next; |
2208 | priv->cmd_itm=priv->cmd_itm_next; |
3015 | priv->cmd_itm = priv->cmd_itm_next; |
2209 | if (!priv->cmd) |
3016 | if (!priv->cmd) |
2210 | return NULL; |
3017 | return NULL; |
2211 | if (!priv->show_all && priv->itm->prev != NULL) |
3018 | if (!priv->show_all && priv->itm->prev != NULL) |
2212 | priv->itm=priv->cmd->itm; |
3019 | priv->itm = priv->cmd->itm; |
2213 | priv->itm_next=priv->itm->next; |
3020 | priv->itm_next = priv->itm->next; |
2214 | if (priv->itm->prev) |
3021 | if (priv->itm->prev) |
2215 | ret->type=type_nav_none; |
3022 | ret->type = type_nav_none; |
2216 | else |
3023 | else |
2217 | ret->type=type_nav_position; |
3024 | ret->type = type_nav_position; |
2218 | if (priv->cmd->itm == priv->itm) { |
3025 | if (priv->cmd->itm == priv->itm) |
|
|
3026 | { |
2219 | priv->cmd_itm_next=priv->cmd->itm; |
3027 | priv->cmd_itm_next = priv->cmd->itm; |
2220 | priv->cmd_next=priv->cmd->next; |
3028 | priv->cmd_next = priv->cmd->next; |
2221 | if (priv->cmd_itm_next && !priv->cmd_itm_next->next) |
3029 | if (priv->cmd_itm_next && !priv->cmd_itm_next->next) |
2222 | ret->type=type_nav_destination; |
3030 | ret->type = type_nav_destination; |
2223 | else { |
3031 | else |
2224 | if (priv->itm && priv->itm->prev && !(priv->itm->way.flags & AF_ROUNDABOUT) && (priv->itm->prev->way.flags & AF_ROUNDABOUT)) { |
3032 | { |
|
|
3033 | if (priv->itm && priv->itm->prev && !(priv->itm->way.flags |
|
|
3034 | & AF_ROUNDABOUT) && (priv->itm->prev->way.flags |
|
|
3035 | & AF_ROUNDABOUT)) |
|
|
3036 | { |
2225 | enum item_type r=type_none,l=type_none; |
3037 | enum item_type r = type_none, l = type_none; |
2226 | switch (((180+22)-priv->cmd->roundabout_delta)/45) { |
3038 | switch (((180 + 22) - priv->cmd->roundabout_delta) / 45) |
|
|
3039 | { |
2227 | case 0: |
3040 | case 0: |
2228 | case 1: |
3041 | case 1: |
2229 | r=type_nav_roundabout_r1; |
3042 | r = type_nav_roundabout_r1; |
2230 | l=type_nav_roundabout_l7; |
3043 | l = type_nav_roundabout_l7; |
2231 | break; |
3044 | break; |
2232 | case 2: |
3045 | case 2: |
2233 | r=type_nav_roundabout_r2; |
3046 | r = type_nav_roundabout_r2; |
2234 | l=type_nav_roundabout_l6; |
3047 | l = type_nav_roundabout_l6; |
2235 | break; |
3048 | break; |
2236 | case 3: |
3049 | case 3: |
2237 | r=type_nav_roundabout_r3; |
3050 | r = type_nav_roundabout_r3; |
2238 | l=type_nav_roundabout_l5; |
3051 | l = type_nav_roundabout_l5; |
2239 | break; |
3052 | break; |
2240 | case 4: |
3053 | case 4: |
2241 | r=type_nav_roundabout_r4; |
3054 | r = type_nav_roundabout_r4; |
2242 | l=type_nav_roundabout_l4; |
3055 | l = type_nav_roundabout_l4; |
2243 | break; |
3056 | break; |
2244 | case 5: |
3057 | case 5: |
2245 | r=type_nav_roundabout_r5; |
3058 | r = type_nav_roundabout_r5; |
2246 | l=type_nav_roundabout_l3; |
3059 | l = type_nav_roundabout_l3; |
2247 | break; |
3060 | break; |
2248 | case 6: |
3061 | case 6: |
2249 | r=type_nav_roundabout_r6; |
3062 | r = type_nav_roundabout_r6; |
2250 | l=type_nav_roundabout_l2; |
3063 | l = type_nav_roundabout_l2; |
2251 | break; |
3064 | break; |
2252 | case 7: |
3065 | case 7: |
2253 | r=type_nav_roundabout_r7; |
3066 | r = type_nav_roundabout_r7; |
2254 | l=type_nav_roundabout_l1; |
3067 | l = type_nav_roundabout_l1; |
2255 | break; |
3068 | break; |
2256 | case 8: |
3069 | case 8: |
2257 | r=type_nav_roundabout_r8; |
3070 | r = type_nav_roundabout_r8; |
2258 | l=type_nav_roundabout_l8; |
3071 | l = type_nav_roundabout_l8; |
2259 | break; |
3072 | break; |
2260 | } |
3073 | } |
2261 | dbg(1,"delta %d\n",priv->cmd->delta); |
3074 | dbg(1, "delta %d\n", priv->cmd->delta); |
2262 | if (priv->cmd->delta < 0) |
3075 | if (priv->cmd->delta < 0) |
2263 | ret->type=l; |
3076 | ret->type = l; |
2264 | else |
3077 | else |
2265 | ret->type=r; |
3078 | ret->type = r; |
|
|
3079 | } |
2266 | } else { |
3080 | else |
|
|
3081 | { |
2267 | delta=priv->cmd->delta; |
3082 | delta = priv->cmd->delta; |
2268 | if (delta < 0) { |
3083 | if (delta < 0) |
|
|
3084 | { |
2269 | delta=-delta; |
3085 | delta = -delta; |
2270 | if (delta < 45) |
3086 | if (delta < 45) |
2271 | ret->type=type_nav_left_1; |
3087 | ret->type = type_nav_left_1; |
2272 | else if (delta < 105) |
3088 | else if (delta < 105) |
2273 | ret->type=type_nav_left_2; |
3089 | ret->type = type_nav_left_2; |
2274 | else if (delta < 165) |
3090 | else if (delta < 165) |
2275 | ret->type=type_nav_left_3; |
3091 | ret->type = type_nav_left_3; |
2276 | else |
3092 | else |
2277 | ret->type=type_none; |
3093 | ret->type = type_none; |
|
|
3094 | } |
2278 | } else { |
3095 | else |
|
|
3096 | { |
2279 | if (delta < 45) |
3097 | if (delta < 45) |
2280 | ret->type=type_nav_right_1; |
3098 | ret->type = type_nav_right_1; |
2281 | else if (delta < 105) |
3099 | else if (delta < 105) |
2282 | ret->type=type_nav_right_2; |
3100 | ret->type = type_nav_right_2; |
2283 | else if (delta < 165) |
3101 | else if (delta < 165) |
2284 | ret->type=type_nav_right_3; |
3102 | ret->type = type_nav_right_3; |
2285 | else |
3103 | else |
2286 | ret->type=type_none; |
3104 | ret->type = type_none; |
2287 | } |
3105 | } |
2288 | } |
3106 | } |
2289 | } |
3107 | } |
2290 | } |
3108 | } |
2291 | priv->ccount=0; |
3109 | priv->ccount = 0; |
2292 | priv->debug_idx=0; |
3110 | priv->debug_idx = 0; |
2293 | priv->attr_next=attr_navigation_short; |
3111 | priv->attr_next = attr_navigation_short; |
2294 | |
3112 | |
2295 | ret->id_lo=priv->itm->dest_count; |
3113 | ret->id_lo = priv->itm->dest_count; |
2296 | dbg(1,"type=%d\n", ret->type); |
3114 | dbg(1, "type=%d\n", ret->type); |
2297 | return ret; |
3115 | return ret; |
2298 | } |
3116 | } |
2299 | |
3117 | |
2300 | static struct item * |
3118 | static struct item * |
2301 | navigation_map_get_item_byid(struct map_rect_priv *priv, int id_hi, int id_lo) |
3119 | navigation_map_get_item_byid(struct map_rect_priv *priv, int id_hi, int id_lo) |
2302 | { |
3120 | { |
2303 | struct item *ret; |
3121 | struct item *ret; |
2304 | navigation_map_rect_init(priv); |
3122 | navigation_map_rect_init(priv); |
2305 | while ((ret=navigation_map_get_item(priv))) { |
3123 | while ((ret = navigation_map_get_item(priv))) |
|
|
3124 | { |
2306 | if (ret->id_hi == id_hi && ret->id_lo == id_lo) |
3125 | if (ret->id_hi == id_hi && ret->id_lo == id_lo) |
2307 | return ret; |
3126 | return ret; |
2308 | } |
3127 | } |
2309 | return NULL; |
3128 | return NULL; |
2310 | } |
3129 | } |
2311 | |
3130 | |
2312 | static struct map_methods navigation_map_meth = { |
3131 | static struct map_methods navigation_map_meth = |
2313 | projection_mg, |
3132 | { projection_mg, "utf-8", navigation_map_destroy, navigation_map_rect_new, |
2314 | "utf-8", |
3133 | navigation_map_rect_destroy, navigation_map_get_item, |
2315 | navigation_map_destroy, |
3134 | navigation_map_get_item_byid, NULL, NULL, NULL, }; |
2316 | navigation_map_rect_new, |
|
|
2317 | navigation_map_rect_destroy, |
|
|
2318 | navigation_map_get_item, |
|
|
2319 | navigation_map_get_item_byid, |
|
|
2320 | NULL, |
|
|
2321 | NULL, |
|
|
2322 | NULL, |
|
|
2323 | }; |
|
|
2324 | |
3135 | |
2325 | static struct map_priv * |
3136 | static struct map_priv * |
2326 | navigation_map_new(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl) |
3137 | navigation_map_new(struct map_methods *meth, struct attr **attrs, |
|
|
3138 | struct callback_list *cbl) |
2327 | { |
3139 | { |
2328 | struct map_priv *ret; |
3140 | struct map_priv *ret; |
2329 | struct attr *navigation_attr; |
3141 | struct attr *navigation_attr; |
2330 | |
3142 | |
2331 | navigation_attr=attr_search(attrs, NULL, attr_navigation); |
3143 | navigation_attr = attr_search(attrs, NULL, attr_navigation); |
2332 | if (! navigation_attr) |
3144 | if (!navigation_attr) |
2333 | return NULL; |
|
|
2334 | ret=g_new0(struct map_priv, 1); |
3145 | return NULL;ret=g_new0(struct map_priv, 1); |
2335 | *meth=navigation_map_meth; |
3146 | *meth = navigation_map_meth; |
2336 | ret->navigation=navigation_attr->u.navigation; |
3147 | ret->navigation = navigation_attr->u.navigation; |
2337 | |
3148 | |
2338 | return ret; |
3149 | return ret; |
2339 | } |
3150 | } |
2340 | |
3151 | |
2341 | void |
|
|
2342 | navigation_set_route(struct navigation *this_, struct route *route) |
3152 | void navigation_set_route(struct navigation *this_, struct route *route) |
2343 | { |
3153 | { |
2344 | struct attr callback; |
3154 | struct attr callback; |
2345 | this_->route=route; |
3155 | this_->route = route; |
2346 | this_->route_cb=callback_new_attr_1(callback_cast(navigation_update), attr_route_status, this_); |
3156 | this_->route_cb = callback_new_attr_1(callback_cast(navigation_update), |
|
|
3157 | attr_route_status, this_); |
2347 | callback.type=attr_callback; |
3158 | callback.type = attr_callback; |
2348 | callback.u.callback=this_->route_cb; |
3159 | callback.u.callback = this_->route_cb; |
2349 | route_add_attr(route, &callback); |
3160 | route_add_attr(route, &callback); |
2350 | } |
3161 | } |
2351 | |
3162 | |
2352 | void |
|
|
2353 | navigation_init(void) |
3163 | void navigation_init(void) |
2354 | { |
3164 | { |
2355 | plugin_register_map_type("navigation", navigation_map_new); |
3165 | plugin_register_map_type("navigation", navigation_map_new); |
2356 | } |
3166 | } |