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