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