1. 程式人生 > >Amap【高德】/Google-開發,無人機航跡規劃演示

Amap【高德】/Google-開發,無人機航跡規劃演示

ps:又到了週五,才有時間來寫點部落格記錄下,這篇文章的所描述的內容是我2017年後 做的一個功能,也是我們的產品經理結合 航跡規劃 以及我們所提供的 能做到的一些地圖開發結合,做的一個自創性的 開發吧。其實開始做的時候挺不自信的,因為第一,地圖sdk 並不是非常瞭解,再說,裡面有好多效果和功能  ,主要是一個動態修改航點和航線這個效果,在評估的時候,著實讓我覺得頭疼。而且領導還說專案很急,讓我一週把航跡規劃和電子圍欄的開發 做完,我和ios 當初可是評估後給了 3個星期的工作日的。他要我們一週搞完,心裡挺虛的。 本身博主就是個菜雞,畢業才半年,雖說在公司實習到現在有一年了,但是畢竟改變不了菜的現實。沒辦法,頂頭幹吧。在開發中,越搞越happay  ,常常加班到11點,覺得蠻有意思的,顯然不是純粹的使用地圖的簡單功能來完成開發的,而是有點難度的。聽意外的,4個工作日,就把航跡規劃和電子圍欄 搞完了。滿有成就感的。

 博主以前是學文科的,廢話有點多,不要見怪。整個效果展示的比較長,但是呢,gif 又只能上傳2M 的圖,無奈只能一個一個截取了。fps 設定的也有點低,沒辦法,gif 2M 實在太小。將就看吧。

1.

2.

3.

一:這次只展示 航跡規劃這一個專案,電子圍欄,我已經在之前文章中寫過了。

二:本次功能要點我做個簡單的闡述。

①.要分清楚 你需要建立幾個集合 分別是:lList<Latlng>,List<Marker>,List<PolyLine>,代表的分別是,座標點,標記點,航線。

②.在UI 給的圖片上 繪製 標號,技術好的應該都會,我下面會把程式碼貼出來

③.就是吧Marker的.draggable(true),前提 先吧拖拽功能開啟。才可以操作

④重點是這個 線拖拽的問題,分別位2種情況

1)例如圖一  在沒有2 出現的情況下只有一種情況,拖拽 marker 1 將 線一拖動,

2)例如2 在拖拽2的時候會牽扯到 2根線,2根線要同步重新整理。

3)額外說的一個,我的電子圍欄中 更復雜一點,比如第一個點生成。 邏輯都和這個一樣,但是在最後一根線的時候,他要圍城一個圍欄,在沒圍成之前,拖拽marker 1的時候 只有一根線,拖拽2 會有2根,拖拽最後一個Marker 也只有一根,但是一旦確認 圍欄 形成,最後一個Marker會和第一個Marker 產生一條線,這時候在拖拽 1和最後一個marker 就需要聯動,所有的點都是 2根線 在動。這個 就從程式碼上沒什麼技術含量,但是邏輯上 需要思考好多。這次就不說這個,我下面會把程式碼貼出來。


開始貼程式碼了。

重點的幾個說完 就直接把所有的貼出來。

 private ArrayList<LatLng> mPfLatLngList = new ArrayList<>(); // latlng的數量比marker的數量多一,因為當前位置座標也記錄下來了
    private ArrayList<PathPlanBean> uploadList = new ArrayList<>(); //上傳航跡規劃列表的集合
    private ArrayList<Marker> mPfMarkerList = new ArrayList<>();
    private ArrayList<Polyline> mPfPolylineList = new ArrayList<>();
    
 /**
     * Marker地圖點選監聽事件
     *
     * @param latLng
     */
    @Override
    public void onMapClick(LatLng latLng) {
        LatLng curLatlng = latLng;
        // 航跡規劃
        if (isOpenFlightRoutePlan && mPfMarkerList.size() < 50 && isWayPointMode_state == GduConfig.FpClose) {
            LatLng lastLatlng;
            if (!mPfLatLngList.isEmpty()) { // 這裡判斷不為空,是保證已經 有飛機的座標點 已經新增
                if (AMapUtils.calculateLineDistance(currentphoneLatlng, curLatlng) > fp_validityRange) {
                    txhToast.show(getString(R.string.Label_Map_FlightRoute_flightpoit_invalidation));
                } else {
                    int tagNum = mPfLatLngList.size();//Marker 數_標
                    mPfMarkerList.add(mapMarkerTool.addPfMarker(curLatlng, tagNum));
                    mPfLatLngList.add(curLatlng);
                    mIv_Fp_state.setImageResource(R.drawable.bg_map_fp_go);
                    if (tagNum == 1) {
                        LatLng droneLat = mPfLatLngList.get(0);
                        mPfPolylineList.add(mapMarkerTool.addPolyDottedLine(droneLat, curLatlng));
                        mPfFlightDisList.add(calculateFlightDist(droneLat, curLatlng));
                    } else if (tagNum > 1) {
                        lastLatlng = mPfLatLngList.get(mPfLatLngList.size() - 2);
                        mPfPolylineList.add(mapMarkerTool.addPolyDottedLine(lastLatlng, curLatlng));
                        mPfFlightDisList.add(calculateFlightDist(lastLatlng, curLatlng));
                    }
                    setEraserState(true);//有Marker增加時候
                }
            }
        } else if (isOpenFlightRoutePlan && mPfMarkerList.size() == 50 && isWayPointMode_state == GduConfig.FpClose) {
            txhToast.show(getString(R.string.Label_Map_FlightRoute_flightpoit_overflow));
        } else if (isOpenFlightRoutePlan && mPfMarkerList.size() < 50 && isWayPointMode_state == GduConfig.FpGo) {
            // 即當開始航跡規劃,在點選地圖,無響應,不增加點
        }

在地圖上增加點 必須在onMapClick 中操作,在onMapClick 獲取最基本的Latlng 資料,並繪製 航線。

add  Marker 

 /**
     * <p>根據經緯度往地圖上新增marker</p>
     * <p>[航跡規劃]</p>
     *
     * @param lagLng    當前點選的 下的座標
     * @param markerNum 計數
     * @return
     */
    public Marker addPfMarker(LatLng lagLng, int markerNum) {
     MarkerOptions options= options = new MarkerOptions().draggable(true);
        options.anchor(0.5f, 1f)
                .position(lagLng)
                .icon(BitmapDescriptorFactory.fromBitmap(getBitMap(markerNum)));

        return aMap.addMarker(options);
    }

add  PolyLine
 /**
     * <p>繪製兩點之間線段</p>
     * <p>虛線</p>
     *
     * @param beginlatLng 起點
     * @param endLatLng   終點
     * @return
     */
    public Polyline addPolyDottedLine(LatLng beginlatLng, LatLng endLatLng) {

        PolylineOptions options = new PolylineOptions();
        options.add(beginlatLng, endLatLng)
                .width(10)
                .color(Color.rgb(255, 121, 24))
                .setDottedLine(true);// 虛線

        return aMap.addPolyline(options);
    }

計算距離:

    /**
     * <p>計算總的飛行距離</p>
     *
     * @param beginlatLng
     * @param endLatLng
     */
    private float calculateFlightDist(LatLng beginlatLng, LatLng endLatLng) {
        float onceDist = AMapUtils.calculateLineDistance(beginlatLng, endLatLng);
        AllFlightDist += onceDist;
        DecimalFormat df = new DecimalFormat("##.#");
        mTv_flightdis.setText(df.format(AllFlightDist) + StringUtils.getUnit());
        return Float.parseFloat(df.format(AllFlightDist));
    }

這是基本的 新增資料 在地圖上顯示,下面就讓他來動起來吧。

設定監聽。

    private void initGuideMap(AMap aMap) {
        // 設定marker可拖拽事件監聽器
        aMap.setOnMarkerDragListener(this);
        // 設定顯示marker資訊監聽,要想顯示資訊必須註冊
//        aMap.setInfoWindowAdapter(this);
        aMap.setOnMarkerClickListener(this);
//        aMap.setOnInfoWindowClickListener(this);
        // 初始化Marker配置
        options = new MarkerOptions().draggable(true);
    }
 
監聽回撥:
/**
     * <p>Marker 拖拽開始監聽</p>
     * <li>增加振盪器</li>
     * <li>獲取當前Marker 的起始座標並儲存</li>
     * <li>作用:當不滿足條件的時候,就可以使用起點座標</li>
     *
     * @param marker
     */
    private LatLng curMarkerPosition;

    @Override
    public void onMarkerDragStart(Marker marker) {
        Vibrator vibrator = (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE);
        vibrator.vibrate(150);
        if (isPfMode == GduConfig.FpMode) {
            for (int i = 0; i < mPfMarkerList.size(); i++) {
                if (marker.equals(mPfMarkerList.get(i))) {
                    curMarkerPosition = mPfLatLngList.get(i + 1);
                }
            }
        } else if (isPfMode == GduConfig.ErMode) {
            for (int i = 0; i < mErMarkerList.size(); i++) {
                if (marker.equals(mErMarkerList.get(i))) {
                    curMarkerPosition = mErLatLngList.get(i);
                }
            }
        }
    }

    /**
     * <p>拖拽過程中的監聽</p>
     *
     * @param marker
     */
    @Override
    public void onMarkerDrag(Marker marker) {
        drawTrackLine(marker);// 正常的Marker監聽中
    }

    /**
     * <p>拖拽完成後的監聽</p>
     * <li>當狀態為:航跡規劃進行中/電子圍欄已啟動 ,拖動點回歸原點</li>
     * <li>拖拽完成後檢查是否超過2000的判定</li>
     *
     * @param marker
     */
    @Override
    public void onMarkerDragEnd(Marker marker) {
        // 模式開啟,飛機在執行 指令操作,所有的點都不能生效

        if (isWayPointMode_state == GduConfig.FpGo || isWayPointMode_state == GduConfig.FpGoOn || isElectronicRail_state == GduConfig.ErStart) {
            BackDraggablePoint(marker);// 當前是:航跡規劃狀態/電子圍欄狀態
            return;
        }
        if (isPfMode == GduConfig.FpMode && AMapUtils.calculateLineDistance(mPfLatLngList.get(0), marker.getPosition()) > fp_validityRange) {
            txhToast.show(context.getString(R.string.Label_Map_FlightRoute_flightpoit_invalidation));
            BackDraggablePoint(marker);// 就是超過2000米 的判斷
        }
    }

繼續 上一個 程式碼中的方法
 /**
     * <p>畫航線</p>
     * <li>第一:分航跡規劃模式和圍欄模式</li>
     * <li>第二:圍欄模式分:圍欄模式已經啟動 -實線情況,圍欄模式未啟動 -虛線情況</li>
     * <li>第三:圍欄模式拖拽:分幾個特殊點 ① 起點 ②中間點 ③ 終點 </li>
     * <li>第四:圍欄模式拖拽:沒啟動圍欄模式前,是沒有最後一根線的,也就是說 5個點四根線 可拖拽的效果也是要分情況的 </li>
     * <li>不僅在拖拽的時候要實況改變預設航線,</li>
     * <li>還要在拖拽結束的時候判斷是否滿足航線規劃的要求</li>
     * <li>滿足就按照使用者的定義的來,不滿足就要回到起始點</li>
     */
    private void drawTrackLine(Marker marker) {
        if (isPfMode == GduConfig.FpMode) { // 航跡規劃
            boolean isExceed = AMapUtils.calculateLineDistance(mPfLatLngList.get(0), marker.getPosition()) > fp_validityRange;
            outofrangeCircle(isExceed);
            for (int i = 0; i < mPfMarkerList.size(); i++) {
                if (marker.equals(mPfMarkerList.get(i))) {
                    mPfLatLngList.set(i + 1, marker.getPosition()); // 第一個點是無人機的點,所以要  +1 ;
                    mPfPolylineList.get(i).remove();
                    mPfPolylineList.set(i,
                            addPolyDottedLine(mPfLatLngList.get(i),        //虛線
                                    mPfLatLngList.get(i + 1)));

                    if (i < mPfMarkerList.size() - 1) {
                        mPfPolylineList.get(i + 1).remove();
                        mPfPolylineList.set(i + 1,
                                addPolyDottedLine(mPfLatLngList.get(i + 1),//虛線
                                        mPfLatLngList.get(i + 2)));
                    }
                    updateFlightDisEvent(i, marker);//實況更新飛行距離的事件
                    return;
                }
            }
        } else if (isPfMode == GduConfig.ErMode) { // 電子圍欄
            for (int i = 0; i < mErMarkerList.size(); i++) {
                if (marker.equals(mErMarkerList.get(i))) {
                    if (mErMarkerList.size() > 1) {
                        mErLatLngList.set(i, marker.getPosition());// 沒有無人機的點,所以就按照第0點來
                        // 一根線  (點的後面那根)
                        if (isElectronicRail_state == GduConfig.ErStart) {   // 已經開啟電子圍欄模式
                            if (i == mErMarkerList.size() - 1) {  // 【特殊點】移動的是最後一個點就是【起點】,手動新增的 Polyline
                                mErPolylineList.get(i).remove();
                                mErPolylineList.set(i,
                                        addPolySolidLine(mErLatLngList.get(i),//實線
                                                mErLatLngList.get(0)));
                            } else {          // 移動的不是最後一個點
                                mErPolylineList.get(i).remove();
                                mErPolylineList.set(i,
                                        addPolySolidLine(mErLatLngList.get(i),//實線
                                                mErLatLngList.get(i + 1)));
                            }
                        } else {                       // 沒有開啟電子圍欄
                            if (i < mErPolylineList.size()) {
                                mErPolylineList.get(i).remove();
                                mErPolylineList.set(i,
                                        addPolyDottedLine(mErLatLngList.get(i),//虛線
                                                mErLatLngList.get(i + 1)));
                            }
                        }
                        // 二根線  (點的後前面那根)
                        if (isElectronicRail_state == GduConfig.ErStart) {  // 已經開啟電子圍欄模式
                            if (i == 0) {     //【特殊點】 移動終點
                                mErPolylineList.get(mErPolylineList.size() - 1).remove();
                                mErPolylineList.set(mErPolylineList.size() - 1,
                                        addPolySolidLine(mErLatLngList.get(i), //實線
                                                mErLatLngList.get(mErLatLngList.size() - 1)));
                            } else {
                                mErPolylineList.get(i - 1).remove();
                                mErPolylineList.set(i - 1,
                                        addPolySolidLine(mErLatLngList.get(i),//實線
                                                mErLatLngList.get(i - 1)));
                            }
                        } else {
                            if (i > 0) {
                                mErPolylineList.get(i - 1).remove();
                                mErPolylineList.set(i - 1,
                                        addPolyDottedLine(mErLatLngList.get(i),//虛線
                                                mErLatLngList.get(i - 1)));
                            }
                        }
                        return;
                    }
                }
            }
        }
    }

繼續上一個程式碼的方法
 /**
     * <p>回到拖拽的起點</p>
     * <li>當不滿足要求的時候,就會回到起始點</li>
     *
     * @param marker
     */
    private void BackDraggablePoint(Marker marker) {
        marker.setPosition(curMarkerPosition);
        drawTrackLine(marker);// 不滿足要求
    }
然後就是 有效域的判定
 我其實是事先做了2個 有效域  的圓形,根據 地圖的 距離計算,當大於2000 就隱藏第一個圓形 顯示下一個圓形,如果第二個沒有
就新建,如果存在就 顯示,
 boolean isExceed = AMapUtils.calculateLineDistance(mPfLatLngList.get(0), marker.getPosition()) > 2000;
有效域
 circle = aMap.addCircle(new CircleOptions()
                        .center(latLng)
                        .radius(fp_validityRange)
                        .fillColor(Color.argb(26, 0, 120, 255))  // 填充域顏色
                        .strokeColor(Color.argb(102, 0, 160, 233))// 邊框顏色
                        .strokeWidth(2));
警告域
 /**
     * <p>是否超出有效域,超出2000 有效域變色</p>
     * <p>是超出範圍的圈/p>
     */
    public void outofrangeCircle(boolean isExceed) {
        if (warning_circle == null) {
            warning_circle = aMap.addCircle(new CircleOptions()
                    .center(currentphoneLatlng)
                    .radius(fp_validityRange)
                    .fillColor(Color.argb(26, 255, 199, 65))  // 填充域顏色
                    .strokeColor(Color.argb(102, 255, 199, 65))// 邊框顏色
                    .strokeWidth(2));
        }
        if (isExceed) {
            warning_circle.setVisible(true);
            normal_circle.setVisible(false);
        } else {
            normal_circle.setVisible(true);
            warning_circle.setVisible(false);
        }
    }

基本 的重點都講完了,下面是我完整的 java 檔案
GuideMapFragment.java
package com.gdu.mvp_view.flightRouteplan;

import android.app.Fragment;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapOptions;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.TextureMapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.Circle;
import com.amap.api.maps.model.CircleOptions;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.maps.model.Polyline;
import com.gdu._enum.ConnStateEnum;
import com.gdu.beans.PathPlanBean;
import com.gdu.config.GduConfig;
import com.gdu.config.GlobalVariable;
import com.gdu.config.UavStaticVar;
import com.gdu.event.PfMostDisEvent;
import com.gdu.mvp_view.application.GduApplication;
import com.gdu.mvp_view.flightRouteplan.helper.GPSTranslateGuide;
import com.gdu.mvp_view.flightRouteplan.helper.UpDroneCurLocation;
import com.gdu.phonedrone.R;
import com.gdu.socket.GduFrame;
import com.gdu.socket.GduMapComm;
import com.gdu.socket.GduSocketConfig;
import com.gdu.socket.SocketCallBack;
import com.gdu.util.AnimationUtils;
import com.gdu.util.BBLog;
import com.gdu.util.DialogUtils;
import com.gdu.util.SPUtils;
import com.gdu.util.StringUtils;
import com.gdu.util.ToastFactory;
import com.gdu.util.YhLog;
import com.gdu.util.dialog.BlackGeneralDialog;
import com.gdu.util.dialog.GeneralDialog;
import com.gdu.views.AngelaTXHToast;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import de.greenrobot.event.EventBus;

/**
 * Created by shangbeibei on 2017/4/20.
 * <p>航跡規劃--高德地圖</p>
 */
public class GuideMapFragment extends Fragment implements
        AMap.OnMapLoadedListener
        , View.OnClickListener
        , LocationSource     // 回撥監聽
        , AMapLocationListener //定外監聽
        , AMap.OnMapClickListener {

    // init GuideMapFragment  mapview
    private AMap aMap;
    // init MapUtils
    private GuideMapMarkerTool mapMarkerTool;
    // init 定位樣式,定位藍點
    private MyLocationStyle myLocationStyle;
    //宣告AMapLocationClient類物件
    public AMapLocationClient mLocationClient = null;
    //宣告mLocationOption物件
    public AMapLocationClientOption mLocationOption = null;
    //重要的地圖工具,有 比例尺,有logo位置  有 縮放按鈕, 指南針。滑動手勢,縮放手勢
    private UiSettings mUiSettings;
    private OnLocationChangedListener mListener;//定位成功回撥
    // 定位當前手機的位置
    private LatLng currentphoneLatlng;
    // 有效域 圓
    private Circle circle;
    // 無效域 圓
    private Circle warning_circle;
    // 航跡規劃 【有效域範圍】半徑
    public static int fp_validityRange = 2000;

    //  init GuideMapFragment view
    private static GuideMapFragment guideMapFragment;
    private View view;
    // 高德地圖
    private TextureMapView mMapView;
    // 地圖控制檯
    private RelativeLayout mRl_MapControlPanel;
    // 清除航線規劃
    private ImageView mIv_fp_cleanroutePlan;
    // 電子圍欄
    private ImageView mIv_electronicRail_on2off;
    // 航跡規劃的開關
    private ImageView mIv_flightPlan_on2off;
    // 隱藏控制檯 iocn
    private ImageView mIv_hide_controlpanel;
    // 顯示控制檯 icon
    private ImageView mIv_show_controlpanel;
    // 地圖定位回撥
    private ImageView mIv_fp_maplocation;
    // 航跡規劃的狀態
    private ImageView mIv_Fp_state;
    // 電子圍欄的狀態
    private ImageView mIv_Er_state;
    // 地圖樣式切換 button
    private ImageView mIv_switch_mapstyle;
    // 地圖切換 樣式 的layout 選項框
    private LinearLayout mll_switch_maplayout;
    // (熱區域)點選地圖樣式,普通地圖
    private LinearLayout mll_click_mapstyle_normal;
    //  (熱區域)點選地圖樣式,衛星地圖
    private LinearLayout mll_click_mapstyle_satellite;
    // 點選後,普通地圖樣式被選擇的background 變化
    private LinearLayout mll_bg_maptype_normal;
    // 點選後,衛星地圖樣式被選擇的background 變化
    private LinearLayout mll_bg_maptype_satellite;
    // 點選後,普通地圖 Text 文字 顏色變化
    private TextView mTv_mapstyle_normal;
    //點選後,衛星地圖 Text 文字 顏色變化
    private TextView mTv_mapstyle_satellite;
    // 飛行距離 layout (顯示/隱藏)
    private LinearLayout mll_flight_distance;
    // 飛行距離 Values 的顯示
    private TextView mTv_flightdis;
    //init  Tools
    //更新無人機當前位置
    private UpDroneCurLocation updronelocation;
    //實時控制頁面下滑提示
    private AngelaTXHToast txhToast;
    // init  list (航跡規劃)
    private ArrayList<LatLng> mPfLatLngList = new ArrayList<>(); // latlng的數量比marker的數量多一,因為當前位置座標也記錄下來了
    private ArrayList<PathPlanBean> uploadList = new ArrayList<>(); //上傳航跡規劃列表的集合
    private ArrayList<Marker> mPfMarkerList = new ArrayList<>();
    private ArrayList<Polyline> mPfPolylineList = new ArrayList<>();
    private ArrayList<Float> mPfFlightDisList = new ArrayList<>();
    private ArrayList<Polyline> mReceivePolylineList = new ArrayList<>();
    //    private ArrayList<TSMWayPoint> tswayPoints = new ArrayList<>();
//    private ArrayList<TSMFlightFencePoint> fencePoints = new ArrayList<>();
    // init  list (電子圍欄)
    private ArrayList<LatLng> mErLatLngList = new ArrayList<>();
    private ArrayList<Marker> mErMarkerList = new ArrayList<>();
    private ArrayList<Polyline> mErPolylineList = new ArrayList<>();
    // init data
    // 是否可以收到飛機的下發航點,表示飛機gps 沒有問題。
    private boolean ishasReceiveLatlng;
    // 是否開啟航跡規劃
    private boolean isOpenFlightRoutePlan = false;
    // 是否處於航跡規劃進行的狀態中(正在按照規劃飛行)
    public static int isWayPointMode_state;
    // 是否開啟電子圍欄
    private boolean isOpenElectronicRail = false;
    // 是否處於電子圍欄 狀態中(已經上傳點,開始飛行)
    public static int isElectronicRail_state;
    //飛行距離的總規劃長度
    private double AllFlightDist;
    private double preLat;
    private double prelon;
    private GduMapComm gduMapComm;
    private final int UPLOAD_PATH_OK = 2;
    private final int UPLOAD_PATH_FAILE = 3;
    private final int ROUTE_PLANE_DOING = 4;
    private final int ROUTE_PLANE_PAUSE = 5;
    private final int ROUTE_PLANE_COMPLETE = 6;
    private final int ROUTE_PLANE_FAILE = 7;
    private final int START_ROUTE = 8;
    private final int NO_ROUTE = 9;
    private final int IN_WALL = 10;
    private final int OUT_WALL = 11;
    private final int CLEAR_WALL = 12;
    private final int EXIT_WALL = 13;
    private final int INVADITE_WALL = 14;
    private boolean isRoutePlane;
    private Timer timer;
    private boolean timeUP;
    private DialogUtils dialogUtils;

    public static synchronized GuideMapFragment getInstance() {
        if (guideMapFragment == null) {
            guideMapFragment = new GuideMapFragment();
        }
        return guideMapFragment;
    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_guide_map_layout, null);
        initFindView();
        initAmap(savedInstanceState);
        initAmapListener();
        initTools();
        initListener();
        gduMapComm = new GduMapComm(GduApplication.getSingleApp().gduCommunication.getGduSocket());
        return view;
    }


    /**
     * @author yuhao
     * <p/>
     * 初始化飛機的位置
     */
    private void initPlanePosotion() {
        GlobalVariable.GPS_Lat = 40.043519f;
        GlobalVariable.GPS_Lon = 116.291275f;  //TODO測試無人機座標為定值

        YhLog.LogE("GlobalVariable.latitude=" + GlobalVariable.GPS_Lat);
        YhLog.LogE("GlobalVariable.longitude=" + GlobalVariable.GPS_Lon);
        LatLng latLng1 = GPSTranslateGuide.transform2Mars(GlobalVariable.GPS_Lat, GlobalVariable.GPS_Lon);  //大地座標轉火星座標
        currentphoneLatlng = new LatLng(GlobalVariable.GPS_Lat, GlobalVariable.GPS_Lon);
        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng1, 20));
        updronelocation.refreshDroneLocation(latLng1);// 更新無人機 Marker 位置
        // 儲存當前 手機定位 並增加到 mPfLatLngList
        addDroneLocation();
    }


    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.iv_switch_map_icon://地圖樣式切換
                //TODO測試需要把切換按鈕改成確認航跡起飛的按鈕
                sureFly();
//                showMapTypeWindow();
                break;
            case R.id.ll_mapstyle_normal_layout://normal 點選
                switchMapStyle(view);
                break;
            case R.id.ll_mapstyle_satellite_layout://satellite 點選
                switchMapStyle(view);
                break;
            case R.id.iv_flightplan_on2off://航跡規劃開啟/關閉
                initFlightPlanEvent();
                break;
            case R.id.iv_electronic_rail://電子圍欄 開啟/關閉
                initElectronicRail();
                break;
            case R.id.iv_flightplan_clean_route://清除航跡規劃
                CleanflightplanRoute();
                break;
            case R.id.iv_mapview_location://定位
                if (currentphoneLatlng != null) {
                    aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentphoneLatlng, 16));//V2.0
                } else {
                    txhToast.show(getString(R.string.Label_Map_FlightRoute_unrecive_plan));
                }
                break;
            case R.id.iv_map_right_menu_hide://隱藏地圖控制檯
                initControlPanelAnimation(false);
                break;
            case R.id.iv_map_right_menu_show://顯示地圖控制檯
                initControlPanelAnimation(true);
                break;
            case R.id.iv_flightplan_state://航跡規劃狀態
                initFpState_on2off();
                break;
            case R.id.iv_ElectronicRail_state://電子圍欄狀態
                initErState_on2off();
                break;
        }
    }

    /**
     * <p>開始,電子圍欄事件</p>
     */
    private void initElectronicRail() {
//        if (WifiConnConfig.IS_LINK_DRONE == WifiConnConfig.ConnType.Conn_Sucess && ishasReceiveLatlng) {// 測試關閉
        if (true && currentphoneLatlng != null) {
            if (!isOpenElectronicRail) {
                isOpenElectronicRail = true;
                //開啟電子圍欄
                mapMarkerTool.isPfMode(GduConfig.ErMode);
                mIv_Er_state.setVisibility(View.VISIBLE);
                mIv_Er_state.setImageResource(R.drawable.icon_map_er_start_gray);
                mIv_electronicRail_on2off.setImageResource(R.drawable.bg_map_electronic_on);
                txhToast.show(getString(R.string.Label_Map_ElectronicRail_Event_on));
                //航跡規劃需要禁掉
                mIv_flightPlan_on2off.setImageResource(R.drawable.icon_path_planning_no);
                mIv_flightPlan_on2off.setEnabled(false);
            } else if (isOpenElectronicRail) {
                isOpenElectronicRail = false;
                mapMarkerTool.isPfMode(GduConfig.NoMode);
                mapMarkerTool.cleanPolygonCover();// 清除圍欄Cover
                mIv_Er_state.setVisibility(View.GONE);
                mIv_electronicRail_on2off.setImageResource(R.drawable.bg_map_electronic_off);
                txhToast.show(getString(R.string.Label_Map_ElectronicRail_Event_off));
                //航跡規劃需要開啟
                mIv_flightPlan_on2off.setImageResource(R.drawable.bg_map_fp_off);
                mIv_flightPlan_on2off.setEnabled(true);
                // 地圖可以再次新增Marker
                isElectronicRail_state = GduConfig.ErClose;
                ClearMap();//再次點選電子圍欄 -清除
            }
        } else if (currentphoneLatlng != null) {
            if (GlobalVariable.connStateEnum == ConnStateEnum.Conn_None)
                txhToast.show(getString(R.string.DeviceNoConn));
            else if (GlobalVariable.connStateEnum == ConnStateEnum.Conn_MoreOne)
                txhToast.show(getString(R.string.Label_ConnMore));
        } else if (currentphoneLatlng == null) {
            txhToast.show(getString(R.string.Label_Map_FlightRoute_unrecive_plan));
        }
    }

    /**
     * <p>連線最後一根線,擴展出來一個不規則矩形</p>
     */
    private void connLastLine() {
        //先清除 虛線 換成 實體線
        for (int i = mErPolylineList.size() - 1; i > -1; i--) {
            mErPolylineList.get(i).remove();
            mErPolylineList.remove(i);
        }
        //在增加實體線
        for (int i = 1; i <= mErLatLngList.size(); i++) {
            if (i == mErLatLngList.size()) {
                mErPolylineList.add(mapMarkerTool.addPolySolidLine(mErLatLngList.get(mErLatLngList.size() - 1), mErLatLngList.get(0)));
            } else {
                mErPolylineList.add(mapMarkerTool.addPolySolidLine(mErLatLngList.get(i - 1), mErLatLngList.get(i)));
            }
        }
    }

    /**
     * <p>開始,航跡規劃事件</p>
     */
    private void initFlightPlanEvent() {
//        boolean isflyhint = SPUtils.getBoolean(getActivity(), SPUtils.ISFlyHint);
//        if (WifiConnConfig.IS_LINK_DRONE == WifiConnConfig.ConnType.Conn_Sucess && ishasReceiveLatlng) {// 測試關閉
        if (true && currentphoneLatlng != null) {
            if (!isOpenFlightRoutePlan) {
//                if (!isflyhint) openRoutePlanDialog();
                isOpenFlightRoutePlan = true;
                //開啟航跡規劃
                mapMarkerTool.isPfMode(GduConfig.FpMode);
                mIv_Fp_state.setVisibility(View.VISIBLE);
                mIv_Fp_state.setImageResource(R.drawable.icon_map_fp_go_gray);
                mIv_flightPlan_on2off.setImageResource(R.drawable.bg_map_fp_on);
                txhToast.show(getString(R.string.Label_Map_FlightRoute_Event_on));
                // 電子圍欄需要禁掉
                mIv_electronicRail_on2off.setImageResource(R.drawable.icon_fence_no);
                mIv_electronicRail_on2off.setEnabled(false);

                // 開啟航跡規劃,繪製航跡規劃的範圍
                initDrawCircle(true);
                //向MapTool 傳遞引數
                mapMarkerTool.setParameter(currentphoneLatlng, warning_circle, circle);
                //開啟航跡規劃,顯示距離Layout
                mll_flight_distance.setVisibility(View.VISIBLE);
            } else if (isOpenFlightRoutePlan) {
                isOpenFlightRoutePlan = false;
                // 關閉航跡規劃
                mapMarkerTool.isPfMode(GduConfig.NoMode);
                mIv_Fp_state.setVisibility(View.GONE);
                mIv_flightPlan_on2off.setImageResource(R.drawable.bg_map_fp_off);
                txhToast.show(getString(R.string.Label_Map_FlightRoute_Event_off));
                // 電子圍欄需要開啟
                mIv_electronicRail_on2off.setImageResource(R.drawable.bg_map_electronic_off);
                mIv_electronicRail_on2off.setEnabled(true);

                // 隱藏航跡規劃 有效域
                initDrawCircle(false);
                //開啟航跡規劃,顯示距離Layout
                mll_flight_distance.setVisibility(View.GONE);
                // 地圖可以再次新增Marker
                isWayPointMode_state = GduConfig.FpClose;
                ClearMap();   //再次點選航跡規劃 -清除
                gduMapComm.controlPathPlan((byte) 0x00, goOnRoute);  //停止航跡規劃
                gduMapComm.controlPathPlan((byte) 0x04, goOnRoute);
                uploadList.clear();
            }
        } else if (currentphoneLatlng != null) {
            if (GlobalVariable.connStateEnum == ConnStateEnum.Conn_None)
                txhToast.show(getString(R.string.DeviceNoConn));
            else if (GlobalVariable.connStateEnum == ConnStateEnum.Conn_MoreOne)
                txhToast.show(getString(R.string.Label_ConnMore));
        } else if (currentphoneLatlng == null) {
            txhToast.show(getString(R.string.Label_Map_FlightRoute_unrecive_plan));
        }
    }

    /**
     * Marker地圖點選監聽事件
     *
     * @param latLng
     */
    @Override
    public void onMapClick(LatLng latLng) {
        LatLng curLatlng = latLng;
        // 航跡規劃
        if (isOpenFlightRoutePlan && mPfMarkerList.size() < 50 && isWayPointMode_state == GduConfig.FpClose) {
            LatLng lastLatlng;
            if (!mPfLatLngList.isEmpty()) { // 這裡判斷不為空,是保證已經 有飛機的座標點 已經新增
                if (AMapUtils.calculateLineDistance(currentphoneLatlng, curLatlng) > fp_validityRange) {
                    txhToast.show(getString(R.string.Label_Map_FlightRoute_flightpoit_invalidation));
                } else {
                    int tagNum = mPfLatLngList.size();//Marker 數_標
                    mPfMarkerList.add(mapMarkerTool.addPfMarker(curLatlng, tagNum));
                    mPfLatLngList.add(curLatlng);
                    mIv_Fp_state.setImageResource(R.drawable.bg_map_fp_go);
                    if (tagNum == 1) {
                        LatLng droneLat = mPfLatLngList.get(0);
                        mPfPolylineList.add(mapMarkerTool.addPolyDottedLine(droneLat, curLatlng));
                        mPfFlightDisList.add(calculateFlightDist(droneLat, curLatlng));
                    } else if (tagNum > 1) {
                        lastLatlng = mPfLatLngList.get(mPfLatLngList.size() - 2);
                        mPfPolylineList.add(mapMarkerTool.addPolyDottedLine(lastLatlng, curLatlng));
                        mPfFlightDisList.add(calculateFlightDist(lastLatlng, curLatlng));
                    }
                    setEraserState(true);//有Marker增加時候
                }
            }
        } else if (isOpenFlightRoutePlan && mPfMarkerList.size() == 50 && isWayPointMode_state == GduConfig.FpClose) {
            txhToast.show(getString(R.string.Label_Map_FlightRoute_flightpoit_overflow));
        } else if (isOpenFlightRoutePlan && mPfMarkerList.size() < 50 && isWayPointMode_state == GduConfig.FpGo) {
            // 即當開始航跡規劃,在點選地圖,無響應,不增加點
        }
        // 電子圍欄
        if (isOpenElectronicRail && mErMarkerList.size() < 6 && isElectronicRail_state == GduConfig.ErClose) {
            LatLng lastLatlng;
            mErMarkerList.add(mapMarkerTool.addErMarker(curLatlng));
            mErLatLngList.add(curLatlng);
            int tagNum = mErLatLngList.size();//Marker 數_標
            if (tagNum > 2) {
                mIv_Er_state.setImageResource(R.drawable.bg_map_er_start);
            }

            if (tagNum > 1) {
                lastLatlng = mErLatLngList.get(mErLatLngList.size() - 2);
                BBLog.LogE("Point_畫線", "-------[" + tagNum + "]點");
                mErPolylineList.add(mapMarkerTool.addPolyDottedLine(lastLatlng, curLatlng));
            }
            setEraserState(true);//有Marker增加時候

        } else if (isOpenElectronicRail && mErMarkerList.size() == 6 && isElectronicRail_state == GduConfig.ErClose) {
            txhToast.show(getString(R.string.Label_Map_FlightRoute_flightpoit_overflow));
        } else if (isOpenElectronicRail && mErMarkerList.size() < 6 && isElectronicRail_state == GduConfig.ErStart) {
            // 即當開始電子圍欄,在點選地圖,無響應,不增加點
        }
    }

    /**
     * <p>電子圍欄狀態—開/關</p>
     */
    private void initErState_on2off() {
        if (isElectronicRail_state == GduConfig.ErClose) {
            boolean isContainsPoint = mapMarkerTool.isPolygonContainsPoint(mErLatLngList, mPfLatLngList.get(0));
            if (mErMarkerList.size() > 2 && isContainsPoint) {
                connLastLine();
                setEraserState(false);
                upElectronicFencePoint();
                isElectronicRail_state = GduConfig.ErStart;
                mIv_Er_state.setImageResource(R.drawable.bg_map_er_cancel);
                mapMarkerTool.drawpolygonCover();
            } else if (!isContainsPoint) {
                txhToast.show(getString(R.string.Label_Map_FlightRoute_electronicRail_invalidation));
            }
        } else if (isElectronicRail_state == GduConfig.ErStart) {
            initElectronicRail();
        }
    }

    /**
     * <p>航跡規劃狀態—開/關</p>
     */
    private void initFpState_on2off() {
        if (isWayPointMode_state == GduConfig.FpClose) {
            if (mPfMarkerList.size() != 0) {
                setFlightHei();
            }
        } else if (isWayPointMode_state == GduConfig.FpGo) {
            mIv_Fp_state.setImageResource(R.drawable.bg_map_fp_go_on);
            isWayPointMode_state = GduConfig.FpGoOn;
            gduMapComm.controlPathPlan((byte) 0x02, goOnRoute);
        } else if (isWayPointMode_state == GduConfig.FpGoOn) {
            mIv_Fp_state.setImageResource(R.drawable.bg_map_fp_pause);
            isWayPointMode_state = GduConfig.FpGo;
            gduMapComm.controlPathPlan((byte) 0x03, goOnRoute);
        }
    }

    /**
     * <p>獲取 </p>
     * <p>上傳飛行航跡點 </p>
     */
    private void upFlightPathPoint() {
        //TODO
        for (int i = 1; i < mPfLatLngList.size(); i++) {
            PathPlanBean pathPlanBean = new PathPlanBean();
            LatLng latLng = GPSTranslateGuide.gcj2wgs(mPfLatLngList.get(i).longitude, mPfLatLngList.get(i).latitude);//火星座標轉大地座標
            pathPlanBean.longitude = (int) (latLng.longitude * 10000000);
            pathPlanBean.latitude = (int) (latLng.latitude * 10000000);
            uploadList.add(pathPlanBean);
        }
        isRoutePlane = true;
        GduApplication.getSingleApp().gduCommunication.addCycleACKCB(GduSocketConfig.CycleACK_pathPlan, sateRoutePlane);
//        if (GlobalVariableTest.updatePlanPoints==0||GlobalVariableTest.updatePlanPoints==99){ //航點數量為0或99才能上傳航點
        //TODO  必須GPS有星時才能上傳航跡
//        if (GlobalVariable.satellite_drone>0&&GlobalVariable.satellite_drone!=98){  //必須GPS有星時才能上傳航跡
//
//        }
        uploadPath();
//        }else{
//            gduMapComm.controlPathPlan((byte) 0x04, new SocketCallBack() {   //否則先清除航點再上傳
//                @Override
//                public void callBack(byte code, GduFrame bean) {
//                    if (code==0){
//                        uploadPath();
//                    }
//                }
//            });
//        }
//        uploadList.clear();
    }


    /**
     * @author yuhao
     * 上傳航跡規劃
     */
    private void uploadPath() {
        gduMapComm.updatePlanPath(uploadList, new SocketCallBack() {   //上傳航跡規劃
            @Override
            public void callBack(byte code, GduFrame bean) {
                if (code == 0) {
                    YhLog.LogE("航跡上傳成功");
                    handler.sendEmptyMessage(UPLOAD_PATH_OK);
//                    handler.postDelayed(new Runnable() {  //上傳後等待3.5s判斷飛機收到的航點是否與傳送的一致
//                        @Override
//                        public void run() {
//                            if (GlobalVariableTest.updatePlanPoints == mPfLatLngList.size()) {
//                                handler.sendEmptyMessage(UPLOAD_PATH_OK);
//                            } else {
//                                handler.sendEmptyMessage(UPLOAD_PATH_FAILE);
//                            }
//                        }
//                    }, 3500);
                } else {
                    YhLog.LogE("航跡上傳失敗");
                    handler.sendEmptyMessage(UPLOAD_PATH_FAILE);
                }
            }
        });
    }


    int index = 0;
    private boolean isShowPlane;
    private TimerTask markPointRunner = new TimerTask() {
        @Override
        public void run() {
//            if (isShowPlane){
            YhLog.LogE("GlobalVariable.GPS_Lat=" + GlobalVariable.GPS_Lat + "     " + "GlobalVariable.GPS_Lon" + GlobalVariable.GPS_Lon);
            if (GlobalVariable.GPS_Lat < 90 && GlobalVariable.GPS_Lon < 180) {
                LatLng latLng = new LatLng(GlobalVariable.GPS_Lat, GlobalVariable.GPS_Lon);
                handler.obtainMessage(0, latLng).sendToTarget();
//                }
            }
        }
    };

    /**
     * <p>獲取 </p>
     * <p>上傳電子圍欄 </p>
     */
    private void upElectronicFencePoint() {
        //TODO
        for (int i = 0; i < mErLatLngList.size(); i++) {
            PathPlanBean pathPlanBean = new PathPlanBean();
            LatLng latLng = GPSTranslateGuide.gcj2wgs(mErLatLngList.get(i).longitude, mErLatLngList.get(i).latitude);//火星座標轉大地座標
            pathPlanBean.longitude = (int) (latLng.longitude * 10000000);
            pathPlanBean.latitude = (int) (latLng.latitude * 10000000);
//            pathPlanBean.longitude = (int) (mErLatLngList.get(i).longitude * 10000000);
//            pathPlanBean.latitude = (int) (mErLatLngList.get(i).latitude * 10000000);
//            pathPlanBean.longitude = (int) (latLng.longitude * 10000000);
//            pathPlanBean.latitude = (int) (latLng.latitude * 10000000);
//            YhLog.LogE("pathPlanBean.longitude="+pathPlanBean.longitude);
//            YhLog.LogE("pathPlanBean.latitude="+pathPlanBean.latitude);
            uploadList.add(pathPlanBean);
        }
//        PathPlanBean pathPlanBean = new PathPlanBean();
//        pathPlanBean.longitude = 1162969390;
//        pathPlanBean.latitude = 400431079;
//        uploadList.add(pathPlanBean);
//
//        PathPlanBean pathPlanBean1 = new PathPlanBean();
//        pathPlanBean1.longitude = 1162987400;
//        pathPlanBean1.latitude = 400437560;
//        uploadList.add(pathPlanBean1);
//
//        PathPlanBean pathPlanBean2 = new PathPlanBean();
//        pathPlanBean2.longitude = 1162969610;
//        pathPlanBean2.latitude = 400442200;
//        uploadList.add(pathPlanBean2);

        isRoutePlane = false;
//        GduApplication.getSingleApp().gduCommunication.addCycleACKCB(GduSocketConfig.CycleAck_wall,stateWall);  //監聽圍欄狀態
//        gduMapComm.clearWallPoint(new SocketCallBack() {
//            @Override
//            public void callBack(byte code, GduFrame bean) {
//                if (code==0){
        gduMapComm.updateWallPoints(uploadList, new SocketCallBack() {  //清理電子圍藍成功後再上傳電子圍欄
            @Override
            public void callBack(byte code, GduFrame bean) {
                YhLog.LogE("code==" + code);
                if (code == 0) {
                    handler.sendEmptyMessage(UPLOAD_PATH_OK);   //上傳電子圍欄成功  餘浩
//                                uploadList.clear();
                } else {
                    handler.sendEmptyMessage(UPLOAD_PATH_FAILE);
                }
            }
        });
//                }
//            }
//        });
//        uploadList.clear();
    }

    /**
     * <p>上傳航點前的飛行高度</p>
     * <p>設定飛行高度</p>
     */
    private void setFlightHei() {
        final BlackGeneralDialog dialog = new BlackGeneralDialog(getActivity(), R.style.NormalDialog) {
            @Override
            public void positiveOnClick() {
                isWayPointMode_state = GduConfig.FpGo;
                setLastMarkerIcon();
                setEraserState(false);
                upFlightPathPoint();
                mIv_Fp_state.setImageResource(R.drawable.bg_map_fp_pause);
                mll_flight_distance.setVisibility(View.GONE);
            }

            @Override
            public void negativeOnClick() {

            }
        };
        dialog.setTitleText(R.string.Label_Map_FlightRoute_setting_flightheight);
        dialog.setContentText(R.string.Label_Map_FlightRoute_plan_keepCurrentHeight_fly);
        dialog.setShowSeekBar(true);
        dialog.show();
    }

    /**
     * <p>繪製航跡規劃有效區域</p>
     * currentphoneLatlng (當前手機定位點)作為有效域的 中心
     * PS: 換算方法 argb
     * int alpha = (color & 0xff000000) >>> 24;
     * int red   = (color & 0x00ff0000) >> 16;
     * int green = (color & 0x0000ff00) >> 8;
     * int blue  = (color & 0x000000ff);
     *
     * @param isopen(開啟,關閉)
     */
    private void initDrawCircle(boolean isopen) {
        if (isopen) {
            LatLng latLng = GPSTranslateGuide.transform2Mars(currentphoneLatlng.latitude, currentphoneLatlng.longitude);  //大地座標轉火星座標
            aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18));
            if (circle != null) {
                circle.setVisible(true);
            } else {
                circle = aMap.addCircle(new CircleOptions()
                        .center(latLng)
                        .radius(fp_validityRange)
                        .fillColor(Color.argb(26, 0, 120, 255))  // 填充域顏色
                        .strokeColor(Color.argb(102, 0, 160, 233))// 邊框顏色
                        .strokeWidth(2));
            }
        } else {
            circle.setVisible(false);
        }
    }
    /**
     * <p>初始化(隱藏/顯示) 控制檯動畫</p>
     */
    private void initControlPanelAnimation(boolean isShow) {
        AnimationUtils.mapRightDisappearAnima(isShow, mRl_MapControlPanel, mIv_hide_controlpanel, mIv_show_controlpanel);
    }

    /**
     * <p>清除航跡規劃航點和航線</p>
     * <p>或者清除預設電子圍欄</p>
     */
    private void CleanflightplanRoute() {
        if (isWayPointMode_state == GduConfig.FpClose) {
            GeneralDialog dialog = new GeneralDialog(getActivity(), R.style.NormalDialog) {
                @Override
                public void positiveOnClick() {
                    ClearMap();// 清楚航跡規劃
                }

                @Override
                public void negativeOnClick() {

                }
            };
            dialog.setOnlycontent();
            dialog.setContentText(isOpenFlightRoutePlan ? R.string.Label_Map_FlightRoute_delete_wayPlan : R.string.Label_Map_FlightRoute_delete_electronicRail);
            dialog.show();
        } else if (isWayPointMode_state == GduConfig.FpGo || isWayPointMode_state == GduConfig.FpGoOn) {
            txhToast.show(getString(R.string.Label_Map_FlightRoute_noClean_WayPoint));
        }
    }

    /**
     * <p>清除地圖Marker 點</p>
     */
    private void ClearMap() {
        // 清除航跡規劃 LatLng 和 Marker 和 PolyLine
        if (mPfFlightDisList != null && !mPfLatLngList.isEmpty() && mPfLatLngList.size() != 1) {
            for (int i = mPfMarkerList.size() - 1; i > -1; i--) {
                mPfMarkerList.get(i).remove();
                mPfMarkerList.remove(i);
            }

            for (int i = mPfLatLngList.size() - 1; i > 0; i--) {
                mPfLatLngList.remove(i);
            }

            for (int i = mPfPolylineList.size() - 1; i > -1; i--) {
                mPfPolylineList.get(i).remove();
                mPfPolylineList.remove(i);
            }

            if (UavStaticVar.isDisplayFlightTrack && mReceivePolylineList != null) {
                for (int i = mReceivePolylineList.size() - 1; i > -1; i--) {
                    mReceivePolylineList.get(i).remove();
                    mReceivePolylineList.remove(i);
                }
            }

            mIv_Fp_state.setImageResource(R.drawable.icon_map_fp_go_gray);
            // 飛行距離
            AllFlightDist = 0;
            if (mPfFlightDisList != null)
                mPfFlightDisList = null;
            mTv_flightdis.setText(0 + StringUtils.getUnit());
        }

        // 清除電子圍欄 LatLng 和 Marker 和 PolyLine
        if (!mErLatLngList.isEmpty() && mErLatLngList.size() != 1) {

            for (int i = mErLatLngList.size() - 1; i > -1; i--) {
                mErLatLngList.remove(i);
            }
            for (int i = mErMarkerList.size() - 1; i > -1; i--) {
                mErMarkerList.get(i).remove();
                mErMarkerList.remove(i);
            }
            for (int i = mErPolylineList.size() - 1; i > -1; i--) {
                mErPolylineList.get(i).remove();
                mErPolylineList.remove(i);
            }
            mIv_Er_state.setImageResource(R.drawable.icon_map_er_start_gray);

            gduMapComm.clearWallPoint(new SocketCallBack() {
                @Override
                public void callBack(byte code, GduFrame bean) {
                    if (code == 0) {
                        YhLog.LogE("清除電子圍欄==" + bean.frame_content[0]);
                    }
                }
            });
            uploadList.clear();
        }
        setEraserState(false);// 清除航跡後
    }

    /**
     * <p>設定當前的飛機 狀態</p>
     * <p>設定橡皮擦狀態</p>
     *
     * @param isopen
     */
    private void setEraserState(boolean isopen) {
        mIv_fp_cleanroutePlan.setEnabled(isopen ? true : false);
        mIv_fp_cleanroutePlan.setImageResource(isopen ? R.drawable.bg_map_fp_clean : R.drawable.icon_cleanmap_no);
    }

    /**
     * <p>設定最後一個Marker 的Icon 圖</p>
     * <p>將帶數字的Icon 替換 終點標誌</p>
     */
    private void setLastMarkerIcon() {
        mPfMarkerList.get(mPfMarkerList.size() - 1).remove();
//        mPfMarkerList.add(mapMarkerTool.updateFlagMarker(mPfLatLngList.get(mPfLatLngList.size() - 1)));
        mPfMarkerList.add(mapMarkerTool.addEndMarker(mPfLatLngList.get(mPfLatLngList.size() - 1)));
    }

    /**
     * <p>開啟航跡規劃後的一個提示資訊</p>
     */
    private void openRoutePlanDialog() {

    }

    /**
     * <p>切換地圖樣式</p>
     *
     * @param view
     */
    private void switchMapStyle(View view) {
        if (view.getId() == R.id.ll_mapstyle_normal_layout) {
            aMap.setMapType(AMap.MAP_TYPE_NORMAL);
            SPUtils.put(getActivity(), SPUtils.MAPTYPE, 1);
            mMapView.invalidate();
        } else {
            aMap.setMapType(AMap.MAP_TYPE_SATELLITE);
            SPUtils.put(getActivity(), SPUtils.MAPTYPE, 2);
            mMapView.invalidate();
        }
        mll_switch_maplayout.setVisibility(View.GONE);
    }

    /**
     * <p>顯示地圖型別的Layout</p>
     */
    private void showMapTypeWindow() {
        if (mll_switch_maplayout.getVisibility() == View.GONE) {
            mll_switch_maplayout.setVisibility(View.VISIBLE);
        } else {
            mll_switch_maplayout.setVisibility(View.GONE);
        }
        //預設地圖背景
        if (AMap.MAP_TYPE_NORMAL == aMap.getMapType()) {
            mll_bg_maptype_normal.setBackgroundResource(R.color.pf_color_ffa030);
            mll_bg_maptype_satellite.setBackgroundResource(R.color.Transparent);
            mTv_mapstyle_normal.setTextColor(getResources().getColor(R.color.pf_color_ffa030));
            mTv_mapstyle_satellite.setTextColor(getResources().getColor(R.color.pf_color_ffffff));
        } else {
            mll_bg_maptype_normal.setBackgroundResource(R.color.Transparent);
            mll_bg_maptype_satellite.setBackgroundResource(R.color.pf_color_ffa030);
            mTv_mapstyle_normal.setTextColor(getResources().getColor(R.color.pf_color_ffffff));
            mTv_mapstyle_satellite.setTextColor(getResources().getColor(R.color.pf_color_ffa030));
        }
    }

    /**
     * <p>計算總的飛行距離</p>
     *
     * @param beginlatLng
     * @param endLatLng
     */
    private float calculateFlightDist(LatLng beginlatLng, LatLng endLatLng) {
        float onceDist = AMapUtils.calculateLineDistance(beginlatLng, endLatLng);
        AllFlightDist += onceDist;
        DecimalFormat df = new DecimalFormat("##.#");
        mTv_flightdis.setText(df.format(AllFlightDist) + StringUtils.getUnit());
        return Float.parseFloat(df.format(AllFlightDist));
    }

    // 載入地圖必要資料
    private void initAmap(Bundle savedInstanceState) {
        mMapView.onCreate(savedInstanceState);
        if (aMap == null) aMap = mMapView.getMap();
        myLocationStyle = new MyLocationStyle();// 初始化定位藍點樣式類
        initMyLocationStyle();
        initUiSettings();
        aMap.setMapType(AMap.MAP_TYPE_NORMAL);
    }

    /**
     * <p>初始化定位藍點樣式類</p>
     */
    private void initMyLocationStyle() {
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);// 定位一次,且將視角移動到地圖中心點
//        myLocationStyle.interval(2000);//設定連續定位模式下的定位間隔,只在連續定位模式下生效,單次定位模式下不會生效。單位為毫秒。
        myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.bluepoint));// 設定小藍點的圖示
        myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0)); //設定定位藍點精度圓圈的邊框顏色的方法。
        myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0));//設定定位藍點精度圓圈的填充顏色的方法。
        myLocationStyle.strokeWidth(0);                      //設定定位藍點精度圈的邊框寬度的方法。
        aMap.setMyLocationStyle(myLocationStyle);
    }

    private void initUiSettings() {
        mUiSettings = aMap.getUiSettings(); // 地圖工具
        mUiSettings.setLogoPosition(AMapOptions.LOGO_POSITION_BOTTOM_LEFT);// logo 位置
        mUiSettings.setScaleControlsEnabled(true);// 預設比例尺
        mUiSettings.setZoomControlsEnabled(false);// 預設縮放按鈕
        mUiSettings.setCompassEnabled(false);// 預設指南針
        mUiSettings.setScrollGesturesEnabled(true);// 預設滑動手勢
        mUiSettings.setZoomGesturesEnabled(true);//  預設縮放手勢
        mUiSettings.setMyLocationButtonEnabled(false);// 設定預設定位按鈕是否顯示
    }

    /**
     * 地圖的監聽事件 集合  都採用匿名內部類
     */
    private void initAmapListener() {
        aMap.setOnMapLoadedListener(this);// 地圖載入監聽
        aMap.setLocationSource(this);// 設定定位監聽 //  先設定定位監聽 ,在設定其他屬性, 衛星,模式
        aMap.setOnMapClickListener(this);   // 設定點選地圖事件監聽
        aMap.setMyLocationEnabled(true); // 設定為true表示啟動顯示定位藍點,false表示隱藏定位藍點並不進行定位,預設是false。
        aMap.setMyLocationType(AMap.LOCATION_TYPE_LOCATE);
        // 初始化載入地圖型別
        int i = SPUtils.getInt(getActivity(), SPUtils.MAPTYPE);
        if (!UavStaticVar.SetMapStyle && i == 0) {
            aMap.setMapType(AMap.MAP_TYPE_NORMAL); // 設定預設地圖為衛星
            UavStaticVar.SetMapStyle = false;
        } else {
            if (i == 1) {
                aMap.setMapType(AMap.MAP_TYPE_NORMAL); // 設定預設地圖為普通地圖
            } else if (i == 2) {
                aMap.setMapType(AMap.MAP_TYPE_SATELLITE); // 設定預設地圖為衛星
            }
        }
    }

    public void initListener() {
        mIv_switch_mapstyle.setOnClickListener(this);
        mIv_fp_maplocation.setOnClickListener(this);
        mIv_switch_mapstyle.setOnClickListener(this);
        mll_click_mapstyle_normal.setOnClickListener(this);
        mll_click_mapstyle_satellite.setOnClickListener(this);

        mIv_hide_controlpanel.setOnClickListener(this);
        mIv_show_controlpanel.setOnClickListener(this);
        mIv_fp_cleanroutePlan.setOnClickListener(this);
        mIv_electronicRail_on2off.setOnClickListener(this);
        mIv_flightPlan_on2off.setOnClickListener(this);
        mIv_fp_maplocation.setOnClickListener(this);
        mIv_Fp_state.setOnClickListener(this);
        mIv_Er_state.setOnClickListener(this);
    }

    /**
     * <p>初始化非地圖API 的工具類</p>
     */
    private void initTools() {
        // 控制欄提示Toast
        txhToast = AngelaTXHToast.getInstance(getActivity());
        mapMarkerTool = new GuideMapMarkerTool(getActivity(), txhToast, aMap, mPfMarkerList, mPfLatLngList, mPfPolylineList, mPfFlightDisList, mTv_flightdis, mErMarkerList, mErLatLngList, mErPolylineList);
        updronelocation = new UpDroneCurLocation(handler, aMap, mMapView, mapMarkerTool, mReceivePolylineList);
        // 初始化 ,航跡清除功能 為不可點選
        setEraserState(false);//初始化
        // 初始化 ,無人機Marker 位置
        if (GlobalVariable.GPS_Lat != -1 && GlobalVariable.GPS_Lon != -1) {
            LatLng gpslatLng = GPSTranslateGuide.AmapTransform(GlobalVariable.GPS_Lat, GlobalVariable.GPS_Lon);
            mapMarkerTool.addPlaneMarker(gpslatLng, null);//初始化
//            mapMarkerTool.addPlaneMarker(new LatLng(GlobalVariable.latitude,GlobalVariable.longitude), null);//初始化
        }
    }

    public void initFindView() {
        //init map
        mMapView = ((TextureMapView) view.findViewById(R.id.Ttmv_guide_mapview));
        // init layout
        mRl_MapControlPanel = ((RelativeLayout) view.findViewById(R.id.rl_map_Control_panel));
        // init ControlPanel view
        mIv_hide_controlpanel = ((ImageView) view.findViewById(R.id.iv_map_right_menu_hide));
        mIv_show_controlpanel = ((ImageView) view.findViewById(R.id.iv_map_right_menu_show));
        mIv_fp_cleanroutePlan = ((ImageView) view.findViewById(R.id.iv_flightplan_clean_route));
        mIv_electronicRail_on2off = ((ImageView) view.findViewById(R.id.iv_electronic_rail));
        mIv_flightPlan_on2off = ((ImageView) view.findViewById(R.id.iv_flightplan_on2off));
        mIv_fp_maplocation = ((ImageView) view.findViewById(R.id.iv_mapview_location));
        mIv_Fp_state = ((ImageView) view.findViewById(R.id.iv_flightplan_state));
        mIv_Er_state = ((ImageView) view.findViewById(R.id.iv_ElectronicRail_state));
        // init switch mapstyle
        mIv_switch_mapstyle = ((ImageView) view.findViewById(R.id.iv_switch_map_icon));
        mll_switch_maplayout = ((LinearLayout) view.findViewById(R.id.ll_switch_map_layout));
        mll_click_mapstyle_normal = ((LinearLayout) view.findViewById(R.id.ll_mapstyle_normal_layout));
        mll_click_mapstyle_satellite = ((LinearLayout) view.findViewById(R.id.ll_mapstyle_satellite_layout));
        mll_bg_maptype_normal = ((LinearLayout) view.findViewById(R.id.ll_mapstyle_normal));
        mll_bg_maptype_satellite = ((LinearLayout) view.findViewById(R.id.ll_mapstyle_satellite));
        mTv_mapstyle_normal = ((TextView) view.findViewById(R.id.tv_mapstyle_normal_text));
        mTv_mapstyle_satellite = ((TextView) view.findViewById(R.id.tv_mapstyle_satellite_text));
        //init flight distance
        mll_flight_distance = ((LinearLayout) view.findViewById(R.id.ll_map_flight_dis));
        mTv_flightdis = ((TextView) view.findViewById(R.id.tv_map_flight_distance));

        dialogUtils = new DialogUtils(getActivity());
        showFlyPosition();
    }

    /**
     * @author 餘浩
     * 實時重新整理飛機的位置
     */
    private void showFlyPosition() {
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
//                YhLog.LogE("GlobalVariable.GPS_Lat=" + GlobalVariable.GPS_Lat + "     " + "GlobalVariable.GPS_Lon" + GlobalVariable.GPS_Lon);
                if (GlobalVariable.GPS_Lat < 90 && Glob