f166c7a0856de60179b71aa20f84ff5c34718c81
[platform/core/location/maps-plugin-here.git] / src / here_route.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "here_route.h"
18
19 HERE_PLUGIN_BEGIN_NAMESPACE
20
21 HereRoute::HereRoute(void *pCbFunc, void *pUserData, int nReqId)
22 {
23         m_pQuery = NULL;
24
25         m_pCbFunc = pCbFunc;
26         m_pUserData = pUserData;
27         m_nReqId = nReqId;
28
29         m_eDistanceUnit = MAPS_DISTANCE_UNIT_M;
30 }
31
32 HereRoute::~HereRoute()
33 {
34         if (m_pQuery)
35         {
36                 delete m_pQuery;
37                 m_pQuery = NULL;
38         }
39 }
40
41 here_error_e HereRoute::PrepareQuery()
42 {
43         if (m_pQuery)
44                 return HERE_ERROR_PERMISSION_DENIED;
45
46         GeoCoordinates origCoord, destCoord;
47         m_pQuery = new (std::nothrow) GeoRouteQuery(origCoord, destCoord);
48
49         if (!m_pQuery)
50                 return HERE_ERROR_OUT_OF_MEMORY;
51         else
52                 return HERE_ERROR_NONE;
53 }
54
55 here_error_e HereRoute::PrepareWaypoint(maps_coordinates_h hOrigin, maps_coordinates_h hDestination)
56 {
57         if (!m_pQuery)
58                 return HERE_ERROR_OUT_OF_MEMORY;
59
60         if (!hOrigin || !hDestination)
61                 return HERE_ERROR_INVALID_PARAMETER;
62
63
64         const int nWaypointNum = 2;
65         maps_coordinates_h hWaypointList[nWaypointNum];
66         hWaypointList[0] = hOrigin;
67         hWaypointList[1] = hDestination;
68
69         return PrepareWaypoint(hWaypointList, nWaypointNum);
70 }
71
72 here_error_e HereRoute::PrepareWaypoint(const maps_coordinates_h* hWaypointList, int nWaypointNum)
73 {
74         if (!m_pQuery)
75                 return HERE_ERROR_OUT_OF_MEMORY;
76
77         if (!hWaypointList || nWaypointNum <= 0)
78                 return HERE_ERROR_INVALID_PARAMETER;
79
80         GeoCoordinateList hereCoordList;
81         GeoCoordinates hereCoord;
82         double dLatitude, dLongitude;
83
84         for (int index = 0; index < nWaypointNum; index++)
85         {
86                 if (hWaypointList[index] != NULL) {
87                         maps_coordinates_get_latitude(hWaypointList[index], &dLatitude);
88                         maps_coordinates_get_longitude(hWaypointList[index], &dLongitude);
89
90                         //MAPS_LOGD("Waypoint --> Lat : %f, Long : %f", dLatitude, dLongitude);
91
92                         hereCoord = GeoCoordinates(dLatitude, dLongitude);
93
94                         if (!HereUtils::IsValid(hereCoord))
95                                 return HERE_ERROR_INVALID_PARAMETER;
96
97                         hereCoordList.push_back(hereCoord);
98                 }
99         }
100
101         m_pQuery->SetWaypoints(hereCoordList);
102
103         return HERE_ERROR_NONE;
104 }
105
106 here_error_e HereRoute::PreparePreference(maps_preference_h hPref)
107 {
108         if (!m_pQuery)
109                 return HERE_ERROR_OUT_OF_MEMORY;
110
111         if (!hPref)
112                 return HERE_ERROR_NONE;
113
114 /*
115         SegmentDetail aSegmentDetail;
116         ManeuverDetail aMneuverDetail;
117         m_pQuery->SetSegmentDetail(aSegmentDetail);
118         m_pQuery->SetManeuverDetail(aMneuverDetail);
119 */
120
121         /* transport mode */
122         maps_route_transport_mode_e eTransMode;
123         if (maps_preference_get_route_transport_mode(hPref, &eTransMode) == MAPS_ERROR_NONE)
124         {
125                 m_pQuery->SetTravelModes(HereUtils::Convert(eTransMode));
126         }
127
128         /* eFeature */
129         maps_route_feature_e eFeature;
130         maps_route_feature_weight_e eFeatureWeight;
131         if (maps_preference_get_route_feature(hPref, &eFeature) == MAPS_ERROR_NONE &&
132             maps_preference_get_route_feature_weight(hPref, &eFeatureWeight) == MAPS_ERROR_NONE)
133         {
134                 m_pQuery->SetFeatureWeight(HereUtils::Convert(eFeature),
135                         HereUtils::Convert(eFeatureWeight));
136         }
137
138         /* exclude areas */
139         char *szAreaToAvoid;
140         if (maps_preference_get(hPref, MAPS_ROUTE_RECT_AREA_TO_AVOID, &szAreaToAvoid) == MAPS_ERROR_NONE)
141         {
142                 GeoBoundingBox gbBox;
143                 GeoBoundingBoxList gbBoxList;
144                 gbBoxList.push_back(HereUtils::Convert(szAreaToAvoid, gbBox));
145                 m_pQuery->SetExcludeAreas(gbBoxList);
146                 g_free(szAreaToAvoid);
147         }
148
149         /* optimization */
150         GeoRouteQuery::RouteOptimization hereOpt;
151         maps_route_optimization_e mapsOpt;
152         if (maps_preference_get_route_optimization(hPref, &mapsOpt) == MAPS_ERROR_NONE)
153         {
154                 switch (mapsOpt)
155                 {
156                 case MAPS_ROUTE_TYPE_FASTEST:  hereOpt = GeoRouteQuery::RO_FastestRoute;  break;
157                 case MAPS_ROUTE_TYPE_SHORTEST: hereOpt = GeoRouteQuery::RO_ShortestRoute; break;
158                 default:                       hereOpt = GeoRouteQuery::RO_FastestRoute;  break;
159                 }
160                 m_pQuery->SetRouteOptimization(hereOpt);
161         }
162
163         /* Metric System */
164         GeoRouteQuery::MetricSystem eMetric;
165         maps_distance_unit_e eUnit;
166         if (maps_preference_get_distance_unit(hPref, &eUnit) == MAPS_ERROR_NONE)
167         {
168                 switch (eUnit)
169                 {
170                 case MAPS_DISTANCE_UNIT_M:  eMetric = GeoRouteQuery::DIST_metric;   break;
171                 case MAPS_DISTANCE_UNIT_KM: eMetric = GeoRouteQuery::DIST_metric;   break;
172                 default:                    eMetric = GeoRouteQuery::DIST_imperial; break;
173                 }
174                 m_eDistanceUnit = eUnit;
175                 m_pQuery->SetMetricSystem(eMetric);
176         }
177
178         char *szViewBounds;
179         if (maps_preference_get(hPref, MAPS_ROUTE_GEOMETRY_BOUNDING_BOX, &szViewBounds) == MAPS_ERROR_NONE)
180         {
181                 GeoBoundingBox gbBox;
182                 HereUtils::Convert(szViewBounds, gbBox);
183                 m_pQuery->SetViewBounds(gbBox);
184                 g_free(szViewBounds);
185         }
186
187         bool is_alternatives_enabled = false;
188         if (maps_preference_get_route_alternatives_enabled(hPref, &is_alternatives_enabled) == MAPS_ERROR_NONE)
189         {
190                 if (is_alternatives_enabled)
191                 {
192                         m_pQuery->SetAlternatives(2);
193                 }
194         }
195
196         char *szRealtimeTraffic;
197         if (maps_preference_get(hPref, MAPS_ROUTE_REALTIME_TRAFFIC, &szRealtimeTraffic) == MAPS_ERROR_NONE)
198         {
199                 if (!strcmp(szRealtimeTraffic, "true") || !strcmp(szRealtimeTraffic, "enabled"))
200                 {
201                         m_pQuery->SetRealtimeTraffic(1);
202                 }
203                 else if (!strcmp(szRealtimeTraffic, "false") || !strcmp(szRealtimeTraffic, "disabled"))
204                 {
205                         m_pQuery->SetRealtimeTraffic(2);
206                 }
207                 else
208                 {
209                         m_pQuery->SetRealtimeTraffic(0);
210                 }
211                 g_free(szRealtimeTraffic);
212         }
213
214         return HERE_ERROR_NONE;
215 }
216
217 here_error_e HereRoute::StartRoute(void)
218 {
219         if (!m_pQuery)
220                 return HERE_ERROR_OUT_OF_MEMORY;
221
222         m_nRestReqId = m_pQuery->Execute(*this, NULL);
223
224         return (m_nRestReqId > 0 ? HERE_ERROR_NONE : HERE_ERROR_INVALID_OPERATION);
225 }
226
227 void HereRoute::OnRouteReply(const GeoRouteReply& Reply)
228 {
229         if (m_bCanceled || !m_pCbFunc || !m_pQuery) // ignore call back if it was cancelled.
230         {
231                 delete this;
232                 return;
233         }
234
235         maps_route_h mapsRoute;
236         maps_error_e error;
237         GeoRouteList hereRouteList = Reply.GetRoutes();
238         int nReplyIdx = 0, nReplyNum = hereRouteList.size();
239         GeoRouteList::iterator hereRoute;
240
241         if (nReplyNum == 0)
242         {
243                 ((maps_service_search_route_cb)m_pCbFunc)(MAPS_ERROR_NOT_FOUND, m_nReqId,
244                         0, 0, NULL, m_pUserData);
245                 delete this;
246                 return;
247         }
248
249         for (hereRoute = hereRouteList.begin() ; hereRoute != hereRouteList.end() ; hereRoute++)
250         {
251                 error = (maps_error_e)maps_route_create(&mapsRoute);
252
253                 if (error == MAPS_ERROR_NONE)
254                 {
255                         /* route id */
256                         if (!hereRoute->GetRouteId().empty())
257                                 maps_route_set_route_id(mapsRoute, (char*)hereRoute->GetRouteId().c_str());
258
259                         /* distance */
260                         maps_route_set_total_distance(mapsRoute,
261                                 HereUtils::ConvertDistance(hereRoute->GetDistance(), m_eDistanceUnit));
262
263                         /* distance unit */
264                         maps_route_set_distance_unit(mapsRoute, m_eDistanceUnit);
265
266                         /* duration */
267                         if (m_pQuery->GetRealtimeTraffic() == 1)
268                                 maps_route_set_total_duration(mapsRoute, hereRoute->GetTrafficTime());
269                         else
270                                 maps_route_set_total_duration(mapsRoute, hereRoute->GetTravelTime());
271
272
273                         /* travel mode */
274                         maps_route_transport_mode_e eTransportMode;
275                         eTransportMode = HereUtils::Convert(hereRoute->GetTravelMode());
276                         maps_route_set_transport_mode(mapsRoute, eTransportMode);
277
278                         /* path */
279                         GeoCoordinateList herePathList = hereRoute->GetPath();
280                         maps_item_list_h mapsPathList;
281                         maps_coordinates_h mapsPath;
282
283                         if (maps_item_list_create(&mapsPathList) == MAPS_ERROR_NONE)
284                         {
285                                 GeoCoordinateList::iterator herePath;
286                                 for (herePath = herePathList.begin(); herePath != herePathList.end(); herePath++)
287                                 {
288                                         double dLat = herePath->GetLatitude();
289                                         double dLng = herePath->GetLongitude();
290
291                                         if(maps_coordinates_create(dLat, dLng, &mapsPath) == MAPS_ERROR_NONE)
292                                         {
293                                                 if (herePath == herePathList.begin())
294                                                         maps_route_set_origin(mapsRoute, mapsPath);
295                                                 else if (herePath == herePathList.end()-1)
296                                                         maps_route_set_destination(mapsRoute, mapsPath);
297                                                 else
298                                                         maps_item_list_append(mapsPathList, mapsPath, maps_coordinates_clone);
299
300                                                 maps_coordinates_destroy(mapsPath);
301                                         }
302                                 }
303
304                                 if (maps_item_list_items(mapsPathList))
305                                 {
306                                         maps_route_set_path(mapsRoute, mapsPathList);
307                                         maps_item_list_remove_all(mapsPathList, maps_coordinates_destroy);
308                                 }
309                                 maps_item_list_destroy(mapsPathList);
310                         }
311
312                         /* bounding box */
313                         maps_area_h hMapsArea = NULL;
314                         HereUtils::Convert(hereRoute->GetBounds(), hMapsArea);
315                         if (hMapsArea)
316                         {
317                                 maps_route_set_bounding_box(mapsRoute, hMapsArea);
318                                 maps_area_destroy(hMapsArea);
319                         }
320
321                         /* segments */
322                         ProcessSegments(mapsRoute, hereRoute->GetRouteSegmentList());
323                 }
324
325                 if (m_bCanceled)
326                 {
327                         maps_route_destroy(mapsRoute);
328                         break;
329                 }
330                 else
331                 {
332                         if (((maps_service_search_route_cb)m_pCbFunc)(error, m_nReqId,
333                                 nReplyIdx++, nReplyNum, mapsRoute, m_pUserData) == FALSE)
334                         {
335                                 delete this;
336                                 return;
337                         }
338                         //maps_route_destroy(mapsRoute);
339                 }
340         }
341
342         if(nReplyIdx >= nReplyNum)
343                 delete this;
344 }
345
346 void HereRoute::OnRouteFailure(const GeoRouteReply& Reply)
347 {
348         if (!m_bCanceled && m_pCbFunc)
349                 ((maps_service_search_route_cb)m_pCbFunc)((maps_error_e)GetErrorCode(Reply), m_nReqId, 0, 0, NULL, m_pUserData);
350         delete this;
351 }
352
353 maps_error_e HereRoute::ProcessSegments(maps_route_h mapsRoute, const RouteSegmentList& hereSegmList)
354 {
355         maps_item_list_h mapsSegmList;
356         maps_route_segment_h mapsSegm;
357         maps_error_e error;
358
359         if (hereSegmList.empty()) return MAPS_ERROR_NOT_FOUND;
360
361         if ((error = (maps_error_e)maps_item_list_create(&mapsSegmList)) != MAPS_ERROR_NONE)
362                 return error;
363
364         RouteSegmentList::const_iterator hereSegm;
365         for (hereSegm = hereSegmList.begin() ; hereSegm != hereSegmList.end() ; hereSegm++)
366         {
367                 if (maps_route_segment_create(&mapsSegm) != MAPS_ERROR_NONE) continue;
368
369                 /* distance */
370                 maps_route_segment_set_distance(mapsSegm,
371                         HereUtils::ConvertDistance(hereSegm->GetDistance(), m_eDistanceUnit));
372
373                 /* tranvel time */
374                 maps_route_segment_set_duration(mapsSegm, hereSegm->GetTravelTime());
375
376                 /* origin, destination */
377                 GeoCoordinateList herePathList = hereSegm->GetPath();
378                 int here_path_list_size = herePathList.size();
379
380                 if (here_path_list_size > 0)
381                 {
382                         GeoCoordinates hereOrig = herePathList.at(0);
383                         GeoCoordinates hereDest = herePathList.at(here_path_list_size-1);
384
385                         maps_coordinates_h mapsOrig, mapsDest;
386                         maps_coordinates_create(hereOrig.GetLatitude(),
387                                                 hereOrig.GetLongitude(), &mapsOrig);
388                         maps_coordinates_create(hereDest.GetLatitude(),
389                                                 hereDest.GetLongitude(), &mapsDest);
390                         maps_route_segment_set_origin(mapsSegm, mapsOrig);
391                         maps_route_segment_set_destination(mapsSegm, mapsDest);
392                         maps_coordinates_destroy(mapsOrig);
393                         maps_coordinates_destroy(mapsDest);
394                 }
395
396                 /* maneuver */
397                 ProcessManeuver(mapsSegm, hereSegm->GetManeuverList());
398
399                 maps_item_list_append(mapsSegmList, mapsSegm, maps_route_segment_clone);
400                 maps_route_segment_destroy(mapsSegm);
401         }
402
403         if (maps_item_list_items(mapsSegmList))
404         {
405                 maps_route_set_segments(mapsRoute, mapsSegmList);
406                 maps_item_list_remove_all(mapsSegmList, maps_route_segment_destroy);
407         }
408         maps_item_list_destroy(mapsSegmList);
409
410         return MAPS_ERROR_NONE;
411 }
412
413 maps_error_e HereRoute::ProcessManeuver(maps_route_segment_h mapsSegm, const ManeuverList& hereManeList)
414 {
415         maps_item_list_h mapsManeList;
416         maps_route_maneuver_h mapsManeuver;
417         maps_coordinates_h mapsCoord;
418         maps_error_e error;
419
420         if (hereManeList.empty()) return MAPS_ERROR_NOT_FOUND;
421
422         if ((error = (maps_error_e)maps_item_list_create(&mapsManeList)) != MAPS_ERROR_NONE)
423                 return error;
424
425         ManeuverList::const_iterator hereMane;
426         for (hereMane = hereManeList.begin() ; hereMane != hereManeList.end() ; hereMane++)
427         {
428                 if (maps_route_maneuver_create(&mapsManeuver) != MAPS_ERROR_NONE) continue;
429
430                 /* position */
431                 if (maps_coordinates_create(hereMane->GetPosition().GetLatitude(),
432                         hereMane->GetPosition().GetLongitude(), &mapsCoord) == MAPS_ERROR_NONE)
433                 {
434                         maps_route_maneuver_set_position(mapsManeuver, mapsCoord);
435                         maps_coordinates_destroy(mapsCoord);
436                 }
437
438                 /* instruction */
439                 if (!hereMane->GetInstructionText().empty())
440                         maps_route_maneuver_set_instruction_text(mapsManeuver,
441                                 (char*)hereMane->GetInstructionText().c_str());
442
443                 /* length */
444                 maps_route_maneuver_set_distance_to_next_instruction(mapsManeuver,
445                         HereUtils::ConvertDistance(hereMane->GetDistanceToNextInstruction(), m_eDistanceUnit));
446
447                 /* travel time */
448                 maps_route_maneuver_set_time_to_next_instruction(mapsManeuver,
449                         hereMane->GetTimeToNextInstruction());
450
451                 /* direction -> turn type */
452                 maps_route_maneuver_set_turn_type(mapsManeuver,
453                         HereUtils::Convert(hereMane->GetDirection()));
454
455                 maps_item_list_append(mapsManeList, mapsManeuver, maps_route_maneuver_clone);
456                 maps_route_maneuver_destroy(mapsManeuver);
457         }
458
459         if (maps_item_list_items(mapsManeList))
460         {
461                 maps_route_segment_set_maneuvers(mapsSegm, mapsManeList);
462                 maps_item_list_remove_all(mapsManeList, maps_route_maneuver_destroy);
463         }
464         maps_item_list_destroy(mapsManeList);
465
466         return MAPS_ERROR_NONE;
467 }
468
469 HERE_PLUGIN_END_NAMESPACE
470