add aw navigation
[apps/navigation.git] / app / navigation.qml
diff --git a/app/navigation.qml b/app/navigation.qml
new file mode 100755 (executable)
index 0000000..ffc0ded
--- /dev/null
@@ -0,0 +1,804 @@
+/*
+ * Copyright (C) 2016 The Qt Company Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import QtQuick 2.6
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 2.0
+import QtWebSockets 1.0
+import QtLocation 5.9
+import QtPositioning 5.6
+
+ApplicationWindow {
+       id: root
+       visible: true
+       width: 1080
+    height: 1488
+//    height: 680 //debug
+       title: qsTr("navigation")
+
+    property real car_position_lat: fileOperation.getLatitude()     // WestGate as default
+    property real car_position_lon: fileOperation.getLongitude()
+    property real car_direction: 0  //North
+    property real car_driving_speed: fileOperation.getSpeed()  // set Km/h
+    property real prev_car_direction: 0
+    property bool st_heading_up: false
+    property real default_zoom_level : 18
+    property real default_car_direction : 0
+    property real car_accumulated_distance : 0
+    property real positionTimer_interval : fileOperation.getInterval() // set millisecond
+    property real car_moving_distance : (car_driving_speed / 3.6) / (1000/positionTimer_interval) // Metric unit
+
+    Map{
+               id: map
+        property int pathcounter : 0
+        property int segmentcounter : 0
+        property int waypoint_count: -1
+               property int lastX : -1
+               property int lastY : -1
+               property int pressX : -1
+               property int pressY : -1
+               property int jitterThreshold : 30
+        property variant currentpostion : QtPositioning.coordinate(car_position_lat, car_position_lon)
+        property var poiArray: new Array
+        property int last_segmentcounter : -1
+
+        signal qmlSignalRouteInfo(double srt_lat,double srt_lon,double end_lat,double end_lon);
+        signal qmlSignalPosInfo(double lat,double lon,double drc,double dst);
+        signal qmlSignalStopDemo();
+        signal qmlSignalArrvied();
+
+        width: parent.width
+        height: parent.height
+               plugin: Plugin {
+                       name: "mapboxgl"
+                       PluginParameter { name: "mapboxgl.access_token";
+                       value: fileOperation.getMapAccessToken() }
+               }
+        center: QtPositioning.coordinate(car_position_lat, car_position_lon)
+        zoomLevel: default_zoom_level
+        bearing: 0
+        objectName: "map"
+
+               GeocodeModel {
+                       id: geocodeModel
+                       plugin: map.plugin
+                       onStatusChanged: {
+                               if ((status == GeocodeModel.Ready) || (status == GeocodeModel.Error))
+                                       map.geocodeFinished()
+                       }
+                       onLocationsChanged:
+                       {
+                               if (count == 1) {
+                                       map.center.latitude = get(0).coordinate.latitude
+                                       map.center.longitude = get(0).coordinate.longitude
+                               }
+                       }
+            //coordinate: poiTheQtComapny.coordinate
+            //anchorPoint: Qt.point(-poiTheQtComapny.sourceItem.width * 0.5,poiTheQtComapny.sourceItem.height * 1.5)
+        }
+               MapItemView {
+                       model: geocodeModel
+                       delegate: pointDelegate
+               }
+               Component {
+                       id: pointDelegate
+
+                       MapCircle {
+                               id: point
+                               radius: 1000
+                               color: "#46a2da"
+                               border.color: "#190a33"
+                               border.width: 2
+                               smooth: true
+                               opacity: 0.25
+                               center: locationData.coordinate
+                       }
+               }
+
+               function geocode(fromAddress)
+               {
+                       // send the geocode request
+                       geocodeModel.query = fromAddress
+                       geocodeModel.update()
+               }
+               
+        MapQuickItem {
+            id: poi
+            sourceItem: Rectangle { width: 14; height: 14; color: "#e41e25"; border.width: 2; border.color: "white"; smooth: true; radius: 7 }
+            coordinate {
+                latitude: 36.136261
+                longitude: -115.151254
+            }
+            opacity: 1.0
+            anchorPoint: Qt.point(sourceItem.width/2, sourceItem.height/2)
+        }
+        MapQuickItem {
+            sourceItem: Text{
+                text: "Westgate"
+                color:"#242424"
+                font.bold: true
+                styleColor: "#ECECEC"
+                style: Text.Outline
+            }
+            coordinate: poi.coordinate
+            anchorPoint: Qt.point(-poi.sourceItem.width * 0.5, poi.sourceItem.height * 1.5)
+        }
+        MapQuickItem {
+            id: car_position_mapitem
+            sourceItem: Image {
+                id: car_position_mapitem_image
+                width: 32
+                height: 32
+                source: "images/240px-Red_Arrow_Up.svg.png"
+
+                transform: Rotation {
+                    id: car_position_mapitem_image_rotate
+                    origin.x: car_position_mapitem_image.width/2
+                    origin.y: car_position_mapitem_image.height/2
+                    angle: car_direction
+                }
+            }
+            anchorPoint: Qt.point(car_position_mapitem_image.width/2, car_position_mapitem_image.height/2)
+            coordinate: map.currentpostion
+
+
+            states: [
+                State {
+                    name: "HeadingUp"
+                    PropertyChanges { target: car_position_mapitem_image_rotate; angle: 0 }
+                },
+                State {
+                    name: "NorthUp"
+                    PropertyChanges { target: car_position_mapitem_image_rotate; angle: root.car_direction }
+                }
+            ]
+            transitions: Transition {
+                RotationAnimation { properties: "angle"; easing.type: Easing.InOutQuad }
+            }
+        }
+
+        MapQuickItem {
+            id: icon_start_point
+            anchorPoint.x: icon_start_point_image.width/2
+            anchorPoint.y: icon_start_point_image.height
+            sourceItem: Image {
+                id: icon_start_point_image
+                width: 32
+                height: 32
+                source: "images/240px-HEB_project_flow_icon_04_checkered_flag.svg.png"
+            }
+        }
+
+        MapQuickItem {
+            id: icon_end_point
+            anchorPoint.x: icon_end_point_image.width/2
+            anchorPoint.y: icon_end_point_image.height
+            sourceItem: Image {
+                id: icon_end_point_image
+                width: 32
+                height: 32
+                source: "images/Map_marker_icon_–_Nicolas_Mollet_–_Flag_–_Tourism_–_Classic.png"
+            }
+        }
+
+        MapQuickItem {
+            id: icon_segment_point
+            anchorPoint.x: icon_segment_point_image.width/2 - 5
+            anchorPoint.y: icon_segment_point_image.height/2 + 25
+            sourceItem: Image {
+                id: icon_segment_point_image
+                width: 64
+                height: 64
+                source: "images/Map_symbol_location_02.png"
+            }
+        }
+
+               RouteModel {
+                       id: routeModel
+                       plugin: Plugin {
+                               name: "mapbox"
+                               PluginParameter { name: "mapbox.access_token";
+                               value: fileOperation.getMapAccessToken() }
+                       }
+                       query:  RouteQuery {
+                               id: routeQuery
+                       }
+                       onStatusChanged: {
+                               if (status == RouteModel.Ready) {
+                                       switch (count) {
+                                       case 0:
+                                               // technically not an error
+                                       //      map.routeError()
+                                               break
+                                       case 1:
+                                               map.pathcounter = 0
+                                               map.segmentcounter = 0
+//                                             console.log("1 route found")
+//                                             console.log("path: ", get(0).path.length, "segment: ", get(0).segments.length)
+//                                             for(var i = 0; i < get(0).path.length; i++){
+//                                                     console.log("", get(0).path[i])
+//                                             }
+                        console.log("1st instruction: ", get(0).segments[map.segmentcounter].maneuver.instructionText)
+                        for( var i = 0; i < routeModel.get(0).segments.length; i++){
+//                            console.log("segments[",i,"].maneuver.direction:" ,routeModel.get(0).segments[i].maneuver.direction)
+//                            console.log("segments[",i,"].maneuver.instructionText:" ,routeModel.get(0).segments[i].maneuver.instructionText)
+//                            console.log("segments[",i,"].maneuver.path[0]:" ,routeModel.get(0).segments[i].path[0].latitude,",",routeModel.get(0).segments[i].path[0].longitude)
+//                            markerModel.addMarker(routeModel.get(0).segments[i].path[0]) // for debug
+                        }
+                        break
+                                       }
+                               } else if (status == RouteModel.Error) {
+                               //      map.routeError()
+                               }
+                       }
+               }
+               
+               Component {
+                       id: routeDelegate
+
+                       MapRoute {
+                               id: route
+                               route: routeData
+                               line.color: "#4658da"
+                               line.width: 10
+                               smooth: true
+                               opacity: 0.8
+                       }
+               }
+               
+               MapItemView {
+                       model: routeModel
+                       delegate: routeDelegate
+               }
+
+        MapItemView{
+            model: markerModel
+            delegate: mapcomponent
+        }
+
+        Component {
+            id: mapcomponent
+            MapQuickItem {
+                id: icon_destination_point
+                anchorPoint.x: icon_destination_point_image.width/4
+                anchorPoint.y: icon_destination_point_image.height
+                coordinate: position
+
+                sourceItem: Image {
+                    id: icon_destination_point_image
+                    width: 32
+                    height: 32
+                    source: "images/200px-Black_close_x.svg.png"
+                }
+            }
+        }
+
+        function addDestination(coord){
+            if( waypoint_count < 0 ){
+                initDestination()
+            }
+
+            if(waypoint_count == 0)  {
+                // set icon_start_point
+                icon_start_point.coordinate = currentpostion
+                map.addMapItem(icon_start_point)
+            }
+
+            if(waypoint_count < 9){
+                routeQuery.addWaypoint(coord)
+                waypoint_count += 1
+
+                btn_guidance.sts_guide = 1
+                btn_guidance.state = "Routing"
+
+                var waypointlist = routeQuery.waypoints
+                for(var i=1; i<waypoint_count; i++) {
+                    markerModel.addMarker(waypointlist[i])
+
+//                    map.addPoiIconSLOT(waypointlist[i].latitude,waypointlist[i].longitude,i % 5) // for Debug
+                }
+
+                routeModel.update()
+                map.qmlSignalRouteInfo(car_position_lat, car_position_lon,coord.latitude,coord.longitude)
+
+                // update icon_end_point
+                icon_end_point.coordinate = coord
+                map.addMapItem(icon_end_point)
+            }
+        }
+
+        function initDestination(){
+            routeModel.reset();
+            console.log("initWaypoint")
+
+            // reset currentpostion
+            map.currentpostion = QtPositioning.coordinate(car_position_lat, car_position_lon)
+            car_accumulated_distance = 0
+            map.qmlSignalPosInfo(car_position_lat, car_position_lon,car_direction,car_accumulated_distance)
+
+            routeQuery.clearWaypoints();
+            routeQuery.addWaypoint(map.currentpostion)
+            routeQuery.travelModes = RouteQuery.CarTravel
+            routeQuery.routeOptimizations = RouteQuery.FastestRoute
+            for (var i=0; i<9; i++) {
+                routeQuery.setFeatureWeight(i, 0)
+            }
+            waypoint_count = 0
+            pathcounter = 0
+            segmentcounter = 0
+            routeModel.update();
+            markerModel.removeMarker();
+            map.removeMapItem(markerModel);
+
+            // remove MapItem
+            map.removeMapItem(icon_start_point)
+            map.removeMapItem(icon_end_point)
+            map.removeMapItem(icon_segment_point)
+
+            // for Debug
+//            while(poiArray.length>0)
+//                map.removeMapItem(poiArray.pop())
+
+            // update car_position_mapitem angle
+            root.car_direction = root.default_car_direction
+
+        }
+
+               function calculateMarkerRoute()
+               {
+            var startCoordinate = QtPositioning.coordinate(car_position_lat, car_position_lon)
+
+                       console.log("calculateMarkerRoute")
+                       routeQuery.clearWaypoints();
+            routeQuery.addWaypoint(startCoordinate)
+            routeQuery.addWaypoint(mouseArea.lastCoordinate)
+                       routeQuery.travelModes = RouteQuery.CarTravel
+                       routeQuery.routeOptimizations = RouteQuery.FastestRoute
+                       for (var i=0; i<9; i++) {
+                               routeQuery.setFeatureWeight(i, 0)
+                       }
+                       routeModel.update();
+               }
+
+        // Calculate direction from latitude and longitude between two points
+        function calculateDirection(lat1, lon1, lat2, lon2) {
+            var curlat = lat1 * Math.PI / 180;
+            var curlon = lon1 * Math.PI / 180;
+            var taglat = lat2 * Math.PI / 180;
+            var taglon = lon2 * Math.PI / 180;
+
+            var Y  = Math.sin(taglon - curlon);
+            var X  = Math.cos(curlat) * Math.tan(taglat) - Math.sin(curlat) * Math.cos(Y);
+            var direction = 180 * Math.atan2(Y,X) / Math.PI;
+            if (direction < 0) {
+              direction = direction + 360;
+            }
+            return direction;
+        }
+
+        // Calculate distance from latitude and longitude between two points
+        function calculateDistance(lat1, lon1, lat2, lon2)
+        {
+            var radLat1 = lat1 * Math.PI / 180;
+            var radLon1 = lon1 * Math.PI / 180;
+            var radLat2 = lat2 * Math.PI / 180;
+            var radLon2 = lon2 * Math.PI / 180;
+
+            var r = 6378137.0;
+
+            var averageLat = (radLat1 - radLat2) / 2;
+            var averageLon = (radLon1 - radLon2) / 2;
+            var result = r * 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(averageLat), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(averageLon), 2)));
+            return Math.round(result);
+        }
+
+        // Setting the next car position from the direction and demonstration mileage
+        function setNextCoordinate(curlat,curlon,direction,distance)
+        {
+            var radian = direction * Math.PI / 180
+            var lat_per_meter = 111319.49079327358;
+            var lat_distance = distance * Math.cos(radian);
+            var addlat = lat_distance / lat_per_meter
+            var lon_distance = distance * Math.sin(radian)
+            var lon_per_meter = (Math.cos( (curlat+addlat) / 180 * Math.PI) * 2 * Math.PI * 6378137) / 360;
+            var addlon = lon_distance / lon_per_meter
+            map.currentpostion = QtPositioning.coordinate(curlat+addlat, curlon+addlon);
+        }
+
+        function addPoiIconSLOT(lat,lon,type) {
+            console.log("called addPoiIcon")
+            var poiItem;
+            switch(type){
+                case 0:
+                    poiItem = Qt.createQmlObject("
+                            import QtQuick 2.0;
+                            import QtLocation 5.9;
+                            MapQuickItem {
+                                id: poi_icon;
+                                anchorPoint.x: icon_flag_liteblue_image.width/2;
+                                anchorPoint.y: icon_flag_liteblue_image.height;
+                                sourceItem: Image {
+                                    id: icon_flag_liteblue_image;
+                                    width: 32;
+                                    height: 37;
+                                    source: \"images/Flag-export_lightblue.png\";
+                                }
+                            }
+                        ",map,"dynamic");
+                    break;
+                case 1:
+                    poiItem = Qt.createQmlObject("
+                            import QtQuick 2.0;
+                            import QtLocation 5.9;
+                            MapQuickItem {
+                                id: poi_icon;
+                                anchorPoint.x: icon_building_image.width/2;
+                                anchorPoint.y: icon_building_image.height;
+                                sourceItem: Image {
+                                    id: icon_building_image;
+                                    width: 32;
+                                    height: 37;
+                                    source: \"images/BuildingIcon.png\";
+                                }
+                            }
+                        ",map,"dynamic");
+                    break;
+                case 2:
+                    poiItem = Qt.createQmlObject("
+                            import QtQuick 2.0;
+                            import QtLocation 5.9;
+                            MapQuickItem {
+                                id: poi_icon;
+                                anchorPoint.x: icon_church_image.width/2;
+                                anchorPoint.y: icon_church_image.height;
+                                sourceItem: Image {
+                                    id: icon_church_image;
+                                    width: 32;
+                                    height: 37;
+                                    source: \"images/ChurchIcon.png\";
+                                }
+                            }
+                        ",map,"dynamic");
+                    break;
+                case 3:
+                    poiItem = Qt.createQmlObject("
+                            import QtQuick 2.0;
+                            import QtLocation 5.9;
+                            MapQuickItem {
+                                id: poi_icon;
+                                anchorPoint.x: icon_restaurant_image.width/2;
+                                anchorPoint.y: icon_restaurant_image.height;
+                                sourceItem: Image {
+                                    id: icon_restaurant_image;
+                                    width: 32;
+                                    height: 37;
+                                    source: \"images/RestaurantMapIcon.png\";
+                                }
+                            }
+                        ",map,"dynamic");
+                    break;
+                case 4:
+                    poiItem = Qt.createQmlObject("
+                            import QtQuick 2.0;
+                            import QtLocation 5.9;
+                            MapQuickItem {
+                                id: poi_icon;
+                                anchorPoint.x: icon_supermarket_image.width/2;
+                                anchorPoint.y: icon_supermarket_image.height;
+                                sourceItem: Image {
+                                    id: icon_supermarket_image;
+                                    width: 32;
+                                    height: 37;
+                                    source: \"images/SupermarketMapIcon.png\";
+                                }
+                            }
+                        ",map,"dynamic");
+                    break;
+                default:
+                    poiItem = null;
+                    break;
+            }
+
+            if(poiItem === null) {
+               console.log("error creating object" +  poiItem.errorString());
+               return false;
+            }
+
+            poiItem.coordinate = QtPositioning.coordinate(lat, lon);
+            map.addMapItem(poiItem);
+            poiArray.push(poiItem);
+//            console.log("success creating object");
+            return true;
+        }
+
+               MouseArea {
+                       id: mouseArea
+                       property variant lastCoordinate
+                       anchors.fill: parent
+                       acceptedButtons: Qt.LeftButton | Qt.RightButton
+                       
+                       onPressed : {
+                               map.lastX = mouse.x
+                               map.lastY = mouse.y
+                               map.pressX = mouse.x
+                               map.pressY = mouse.y
+                               lastCoordinate = map.toCoordinate(Qt.point(mouse.x, mouse.y))
+                       }
+                       
+                       onPositionChanged: {
+                if (mouse.button === Qt.LeftButton) {
+                                       map.lastX = mouse.x
+                                       map.lastY = mouse.y
+                               }
+                       }
+                       
+                       onPressAndHold:{
+                if(btn_guidance.state !== "onGuide")
+                {
+                    if (Math.abs(map.pressX - mouse.x ) < map.jitterThreshold
+                            && Math.abs(map.pressY - mouse.y ) < map.jitterThreshold) {
+                        map.addDestination(lastCoordinate)
+                    }
+                }
+
+                       }
+               }
+        gesture.onFlickStarted: {
+            btn_present_position.state = "Optional"
+        }
+        gesture.onPanStarted: {
+            btn_present_position.state = "Optional"
+        }
+               function updatePositon()
+               {
+//                     console.log("updatePositon")
+            if(pathcounter <= routeModel.get(0).path.length - 1){
+//                console.log("path: ", pathcounter, "/", routeModel.get(0).path.length - 1, " segment: ", segmentcounter, "/", routeModel.get(0).segments.length - 1)
+//                console.log("from_to:",map.currentpostion.latitude,",",map.currentpostion.longitude,",",routeModel.get(0).path[pathcounter].latitude,",",routeModel.get(0).path[pathcounter].longitude)
+                // calculate distance
+                var next_distance = calculateDistance(map.currentpostion.latitude,
+                                                      map.currentpostion.longitude,
+                                                      routeModel.get(0).path[pathcounter].latitude,
+                                                      routeModel.get(0).path[pathcounter].longitude);
+//                console.log("next_distance:",next_distance);
+
+                // calculate direction
+                var next_direction = calculateDirection(map.currentpostion.latitude,
+                                                        map.currentpostion.longitude,
+                                                        routeModel.get(0).path[pathcounter].latitude,
+                                                        routeModel.get(0).path[pathcounter].longitude);
+//                console.log("next_direction:",next_direction);
+
+                // calculate next cross distance
+                var next_cross_distance = calculateDistance(map.currentpostion.latitude,
+                                                            map.currentpostion.longitude,
+                                                            routeModel.get(0).segments[segmentcounter].path[0].latitude,
+                                                            routeModel.get(0).segments[segmentcounter].path[0].longitude);
+//                console.log("next_cross_distance:",next_cross_distance);
+                // set next coordidnate
+                if(next_distance < (root.car_moving_distance * 1.5))
+                {
+                    map.currentpostion = routeModel.get(0).path[pathcounter]
+                    if(pathcounter != 0){
+                        car_accumulated_distance += next_distance
+                    }
+                    map.qmlSignalPosInfo(map.currentpostion.latitude, map.currentpostion.longitude,next_direction,car_accumulated_distance)
+                    if(pathcounter < routeModel.get(0).path.length - 1){
+                        pathcounter++
+                    }
+                    else
+                    {
+                        // Arrive at your destination
+                        btn_guidance.sts_guide = 0
+                        map.qmlSignalArrvied()
+                    }
+                }else{
+                    setNextCoordinate(map.currentpostion.latitude, map.currentpostion.longitude,next_direction,root.car_moving_distance)
+                    if(pathcounter != 0){
+                        car_accumulated_distance += root.car_moving_distance
+                    }
+                    map.qmlSignalPosInfo(map.currentpostion.latitude, map.currentpostion.longitude,next_direction,car_accumulated_distance)
+                }
+//                console.log("NextCoordinate:",map.currentpostion.latitude,",",map.currentpostion.longitude)
+
+                // car_position_mapitem angle
+                root.prev_car_direction = root.car_direction
+                root.car_direction = next_direction
+
+                if(btn_present_position.state === "Flowing")
+                {
+                    // update map.center
+                    map.center = map.currentpostion
+
+                    rotateMapSmooth()
+                }
+
+                // report a new instruction if current position matches with the head position of the segment
+                if(segmentcounter <= routeModel.get(0).segments.length - 1){
+                     if(next_cross_distance < 2){
+//                      console.log("new segment instruction: ", routeModel.get(0).segments[segmentcounter].maneuver.instructionText)
+                        progress_next_cross.setProgress(0)
+                        if(segmentcounter < routeModel.get(0).segments.length - 1){
+                            segmentcounter++
+                        }
+                        if(segmentcounter === routeModel.get(0).segments.length - 1){
+                            img_destination_direction.state = "12"
+                            map.removeMapItem(icon_segment_point)
+                        }else{
+                            img_destination_direction.state = routeModel.get(0).segments[segmentcounter].maneuver.direction
+                            icon_segment_point.coordinate = routeModel.get(0).segments[segmentcounter].path[0]
+                            map.addMapItem(icon_segment_point)
+                            // console.log(routeModel.get(0).segments[segmentcounter].maneuver.instructionText)
+                            // guidanceModule.guidance(routeModel.get(0).segments[segmentcounter].maneuver.instructionText)
+                        }
+                    }else{
+                        if(next_cross_distance <= 330 && last_segmentcounter != segmentcounter) {
+                            last_segmentcounter = segmentcounter
+                            console.log(routeModel.get(0).segments[segmentcounter].maneuver.instructionText)
+                            guidanceModule.guidance(routeModel.get(0).segments[segmentcounter].maneuver.instructionText)
+                        }
+                        // update progress_next_cross
+                        progress_next_cross.setProgress(next_cross_distance)
+                    }
+                }
+            }
+               }
+        function removePoiIconsSLOT(category_id){
+            console.log("called removePoiIcons")
+            while(poiArray.length>0)
+                map.removeMapItem(poiArray.pop())
+        }
+
+        function doGetRouteInfoSlot(){
+            if(btn_guidance.sts_guide == 0){ // idle
+                console.log("called doGetRouteInfoSlot sts_guide == idle")
+                map.qmlSignalPosInfo(car_position_lat, car_position_lon,car_direction,car_accumulated_distance);
+            }else if(btn_guidance.sts_guide == 1){ // Routing
+                console.log("called doGetRouteInfoSlot sts_guide == Routing")
+                map.qmlSignalPosInfo(car_position_lat, car_position_lon,car_direction,car_accumulated_distance);
+                map.qmlSignalRouteInfo(car_position_lat, car_position_lon,routeQuery.waypoints[1].latitude,routeQuery.waypoints[1].longitude);
+            }else if(btn_guidance.sts_guide == 2){ // onGuide
+                console.log("called doGetRouteInfoSlot sts_guide == onGuide")
+                map.qmlSignalRouteInfo(car_position_lat, car_position_lon,routeQuery.waypoints[1].latitude,routeQuery.waypoints[1].longitude);
+            }
+        }
+
+        function rotateMapSmooth(){
+            var prev = root.prev_car_direction
+            var now = root.car_direction
+            var diff
+
+            if(root.st_heading_up){
+
+                diff = now - prev
+
+                if ( 180 < diff ){
+                    diff = diff - 360.0
+                } else if ( diff < -180 ){
+                    diff = diff + 360.0
+                }
+
+                //console.log("prev:", prev, ", now:", now, ", diff:", diff)
+
+                if( 0 < diff ){
+                    rot_anim.direction = RotationAnimation.Clockwise
+                } else {
+                    rot_anim.direction = RotationAnimation.Counterclockwise
+                }
+
+                map.state = "none"
+                map.state = "smooth_rotate"
+            }else{
+                diff = 0 - prev
+
+                if ( 180 < diff ){
+                    diff = diff - 360.0
+                } else if ( diff < -180 ){
+                    diff = diff + 360.0
+                }
+
+                //console.log("prev:", prev, ", now:", now, ", diff:", diff)
+                if( 0 < diff ){
+                    rot_anim.direction = RotationAnimation.Clockwise
+                } else {
+                    rot_anim.direction = RotationAnimation.Counterclockwise
+                }
+
+                map.state = "smooth_rotate_north"
+            }
+        }
+
+        states: [
+            State {
+                name: "none"
+            },
+            State {
+                name: "smooth_rotate"
+                PropertyChanges { target: map; bearing: root.car_direction }
+            },
+            State {
+                name: "smooth_rotate_north"
+                PropertyChanges { target: map; bearing: 0 }
+            }
+        ]
+
+        transitions: Transition {
+            NumberAnimation { properties: "center"; easing.type: Easing.InOutQuad }
+            RotationAnimation {
+                id: rot_anim
+                property: "bearing"
+                easing.type: Easing.InOutQuad
+                duration: 200
+            }
+        }
+    }
+               
+    BtnPresentPosition {
+        id: btn_present_position
+        anchors.right: parent.right
+        anchors.rightMargin: 125
+        anchors.bottom: parent.bottom
+        anchors.bottomMargin: 125
+    }
+
+       BtnMapDirection {
+        id: btn_map_direction
+        anchors.top: parent.top
+        anchors.topMargin: 25
+        anchors.left: parent.left
+        anchors.leftMargin: 25
+       }
+
+    BtnGuidance {
+        id: btn_guidance
+        anchors.top: parent.top
+        anchors.topMargin: 25
+        anchors.right: parent.right
+        anchors.rightMargin: 125
+       }
+
+       BtnShrink {
+        id: btn_shrink
+        anchors.left: parent.left
+        anchors.leftMargin: 25
+        anchors.bottom: parent.bottom
+        anchors.bottomMargin: 250
+       }
+
+       BtnEnlarge {
+        id: btn_enlarge
+        anchors.left: parent.left
+        anchors.leftMargin: 25
+        anchors.bottom: parent.bottom
+        anchors.bottomMargin: 125
+       }
+
+       ImgDestinationDirection {
+        id: img_destination_direction
+        anchors.top: parent.top
+        anchors.topMargin: 25
+        anchors.left: parent.left
+        anchors.leftMargin: 150
+       }
+
+    ProgressNextCross {
+        id: progress_next_cross
+        anchors.top: parent.top
+        anchors.topMargin: 25
+        anchors.left: img_destination_direction.right
+        anchors.leftMargin: 20
+       }
+}