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.javapackage 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 && GlobalVariable.GPS_Lon < 180) { LatLng latLng = new LatLng(GlobalVariable.GPS_Lat, GlobalVariable.GPS_Lon); handler.obtainMessage(0, latLng).sendToTarget(); preLat = GlobalVariable.GPS_Lat; prelon = GlobalVariable.GPS_Lon; } } }, 500, 500); } /** * 激活定位 */ @Override public void activate(OnLocationChangedListener onLocationChangedListener) { mListener = onLocationChangedListener; if (mLocationClient == null) { // 初始化定位 mLocationClient = new AMapLocationClient(getActivity()); //初始化定位参数 mLocationOption = new AMapLocationClientOption(); //设置定位回调监听 mLocationClient.setLocationListener(this); // 有成功回调 //设置为高精度定位模式 mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); mLocationOption.setNeedAddress(true); mLocationOption.setOnceLocation(false); //设置定位参数 mLocationClient.setLocationOption(mLocationOption); //启动定位 mLocationClient.startLocation(); } } /** * <p>定位成功后的回调</p> * * @param aMapLocation */ @Override public void onLocationChanged(AMapLocation aMapLocation) { // Toast.makeText(getActivity(), "ErrorCode:" + aMapLocation.getErrorCode() + "-lat:" + aMapLocation.getLatitude() + "-lon:" + aMapLocation.getLongitude(), Toast.LENGTH_SHORT).show(); if (mListener != null && aMapLocation != null) { if (aMapLocation.getErrorCode() == 0) { //保存当前定位坐标 SPUtils.put(getActivity(), SPUtils.AMAP_PHONE_LAST_LAT, aMapLocation.getLatitude() + ""); SPUtils.put(getActivity(), SPUtils.AMAP_PHONE_LAST_LON, aMapLocation.getLongitude() + ""); // 显示系统小蓝点 mListener.onLocationChanged(aMapLocation); // set 当前人的位置 LatLng currentphoneLatlng = new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude()); aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentphoneLatlng, 20)); // 保存当前 手机定位 并增加到 mPfLatLngList // addDroneLocation(); //第一个坐标点改为飞机的坐标 余浩 deactivate(); } else { BBLog.LogE("onLocationChanged", "定位失败," + aMapLocation.getErrorCode() + ": " + aMapLocation.getErrorInfo()); } } } /** * <p>地图加载回调</p> * <p>如果只想定位一次,那就将相机放在地图加载回调中</p> */ @Override public void onMapLoaded() { String phone_lat = SPUtils.getString(getActivity(), SPUtils.AMAP_PHONE_LAST_LAT); String phone_lon = SPUtils.getString(getActivity(), SPUtils.AMAP_PHONE_LAST_LON); if (!phone_lat.equals("") && !phone_lon.equals("")) { Double lastPostionLat = Double.valueOf(phone_lat); Double lastPostionLng = Double.valueOf(phone_lon); LatLng latLng = new LatLng(lastPostionLat, lastPostionLng); aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16)); } initPlanePosotion(); } Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0: refreshLatLng((LatLng) msg.obj); //刷新飞机的位置 break; case 1: mapMarkerTool.setPlaneAngle(msg.arg1); break; case UPLOAD_PATH_OK: //航迹规划上传成功 余浩 if (isRoutePlane) { ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.route_upload_success)); } else { ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.wall_upload_success)); // handler.postDelayed(new Runnable() { //上传成功后计时2s判断围栏点上传成功与否 // @Override // public void run() { // timeUP=true; // } // },2000); } isShowPlane = true; break; case UPLOAD_PATH_FAILE: //航迹规划上传失败 余浩 ToastFactory.toastShort(getActivity(),getActivity().getString(R.string.route_upload_faile)); // gduMapComm.controlPathPlan((byte) 0x04, new SocketCallBack() { //清除航迹规划 // @Override // public void callBack(byte code, GduFrame bean) { // // } // }); YhLog.LogE("航迹规划上传失败"); break; case ROUTE_PLANE_DOING: //航迹规划中 余浩 ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.routing)); YhLog.LogE("航迹规划中"); break; case ROUTE_PLANE_PAUSE: //暂停航迹规划 余浩 ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.pause_route)); YhLog.LogE("暂停航迹规划"); break; case ROUTE_PLANE_FAILE: //航迹规划失败 余浩 ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.route_faile)); YhLog.LogE("航迹规划失败"); break; case START_ROUTE: //开始航迹规划 余浩 ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.start_route)); YhLog.LogE("开始航迹规划"); break; case ROUTE_PLANE_COMPLETE: //航迹规划完成 余浩 ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.route_complete)); YhLog.LogE("航迹规划完成"); break; case NO_ROUTE: //未进行航迹规划 余浩 ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.no_route)); YhLog.LogE("未进行航迹规划"); break; case IN_WALL: //在围栏中 ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.in_wall)); break; case OUT_WALL: //在围栏外 ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.out_wall)); break; case CLEAR_WALL: //清除电子围栏 ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.clear_wall)); break; case EXIT_WALL: //退出电子围栏模式 ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.exit_wall)); break; case INVADITE_WALL: //无效电子围栏点 ToastFactory.toastShort(getActivity(), getActivity().getString(R.string.invalid_wall)); break; } } }; /** * 确认开始航迹飞行的提示 */ private void sureFly() { dialogUtils.createDialogWith2Btn("确定要启动航迹飞行吗" , "启动航迹飞行飞机将按照航迹自动飞行" , getString(R.string.Label_cancel) , getString(R.string.Label_Sure), new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.dialog_btn_cancel: dialogUtils.cancelDailog(); break; case R.id.dialog_btn_sure: gduMapComm.controlPathPlan((byte)0x01,goOnRoute); //开始航迹飞行 dialogUtils.cancelDailog(); break; } } } ); } private byte preState = -1; /** * @author 余浩 * 航迹规划的状态 */ private SocketCallBack sateRoutePlane = new SocketCallBack() { @Override public void callBack(byte code, GduFrame bean) { switch (bean.frame_content[0]) { case 0: if (preState != 0) { handler.sendEmptyMessage(NO_ROUTE); } break; case 1: if (preState != 1) { handler.sendEmptyMessage(ROUTE_PLANE_DOING); } break; case 2: if (preState != 2) { handler.sendEmptyMessage(ROUTE_PLANE_PAUSE); } break; case 3: if (preState != 3) { handler.sendEmptyMessage(ROUTE_PLANE_COMPLETE); } break; case 4: if (preState != 4) { handler.sendEmptyMessage(ROUTE_PLANE_FAILE); } break; } preState = bean.frame_content[0]; } }; private byte preStateWall = -1; /** * @author 余浩 * 电子围栏状态反馈 */ private SocketCallBack stateWall = new SocketCallBack() { @Override public void callBack(byte code, GduFrame bean) { switch (bean.frame_content[0]) { case 0: //围栏中 if (preStateWall != 0) { handler.sendEmptyMessage(IN_WALL); } break; case 1: //围栏外 if (preStateWall != 1) { handler.sendEmptyMessage(OUT_WALL); } break; case 2: //围栏被清除(手机发送清楚指令) if (preStateWall != 2) { handler.sendEmptyMessage(CLEAR_WALL); } break; case 3: //退出电子围栏模式 if (preStateWall != 3) { handler.sendEmptyMessage(EXIT_WALL); } break; case 4: //无效电子围栏 if (timeUP && bean.frame_content[1] != mErLatLngList.size()) { handler.sendEmptyMessage(INVADITE_WALL); gduMapComm.clearWallPoint(new SocketCallBack() { //发送清除指令取消围栏状态的周期反馈 @Override public void callBack(byte code, GduFrame bean) { } }); timeUP = false; } break; } preStateWall = bean.frame_content[0]; } }; /** * 航迹规划操作 */ private SocketCallBack goOnRoute = new SocketCallBack() { @Override public void callBack(byte code, GduFrame bean) { } }; /** * <p>获取无人机的位置,实况刷新</p> */ public void refreshLatLng(LatLng latLng) { if (latLng != null) { LatLng gpslatLng = GPSTranslateGuide.AmapTransform(latLng.latitude, latLng.longitude); LatLng latLng1 = GPSTranslateGuide.transform2Mars(latLng.latitude, latLng.longitude); //将坐标转换为火星坐标进行显示纠正偏移 receiveDroneLatlng(latLng1);// 绘制已经飞过的路径 updronelocation.refreshDroneLocation(latLng1);// 更新无人机 Marker 位置 UavStaticVar.droneCurLatLng = new LatLng(gpslatLng.latitude, gpslatLng.longitude); UavStaticVar.isGetuavCurLatLng = true; } } /** * <p>接受无人机端传递过来的经纬度绘制轨迹。</p> */ boolean isFirstReturn = true; public void receiveDroneLatlng(LatLng backLatLng) { // MainActivity mMainActivity = (MainActivity) getActivity(); // if (mMainActivity.sateliteNum > 6) { if (isFirstReturn) { if (!UavStaticVar.isGetuavCurLatLng) { UavStaticVar.droneCurLatLng = backLatLng; isFirstReturn = false; } } if (UavStaticVar.droneCurLatLng != null) { // 836 的意思是 原来1000 的显示是 *1.2 倍,显示时候需要显示正确的 米 反向除以 1.2后的位置是正确超过1000米的 if (AMapUtils.calculateLineDistance(UavStaticVar.droneCurLatLng, backLatLng) > 836) { txhToast.show(getString(R.string.Label_Map_FlightRoute_flight_dis_over_1000)); } } // 无人机第一个点位置替换 if (mPfLatLngList.isEmpty()) { mPfLatLngList.add(backLatLng); } else { mPfLatLngList.set(0, backLatLng); } //绘制飞机传回来的坐标并在飞的时候绘制飞过的线 updronelocation.drawRecievePolyLine(backLatLng); // 计算当前无人机最远飞了多远(人和无人机) if (UavStaticVar.droneCurLatLng != null) { EventBus.getDefault().post(new PfMostDisEvent((int) AMapUtils.calculateLineDistance(UavStaticVar.droneCurLatLng, backLatLng))); } } /** * <p>添加无人机 当前位置</p> */ private void addDroneLocation() { if (mPfLatLngList.isEmpty()) { // mPfLatLngList.add(UavStaticVar.droneCurLatLng); mPfLatLngList.add(currentphoneLatlng); } else { // mPfLatLngList.set(0, UavStaticVar.droneCurLatLng); mPfLatLngList.set(0, currentphoneLatlng); } } /** * 停止定位 */ @Override public void deactivate() { mListener = null; if (mLocationClient != null) { mLocationClient.stopLocation(); mLocationClient.onDestroy(); } mLocationClient = null; } /** * 以下是必须要重写的 */ @Override public void onResume() { mMapView.onResume(); super.onResume(); } @Override public void onPause() { mMapView.onPause(); super.onPause(); } @Override public void onSaveInstanceState(Bundle outState) { mMapView.onSaveInstanceState(outState); super.onSaveInstanceState(outState); } @Override public void onDestroy() { super.onDestroy(); timer.cancel(); timer.purge(); updronelocation.stopThread(); isElectronicRail_state = GduConfig.ErClose; isWayPointMode_state = GduConfig.FpClose; //预算的飞行距离 AllFlightDist = 0; if (mPfFlightDisList != null && mPfFlightDisList.size() > 0) { mPfFlightDisList = null; } //默认初始值 isOpenFlightRoutePlan = false; isOpenElectronicRail = false; // 电子围栏,矩形覆盖面 mapMarkerTool.cleanPolygonCover(); mapMarkerTool.isPfMode(GduConfig.NoMode); // 航迹规划 清除圆面 if (circle != null) { circle.remove(); circle = null; } if (warning_circle != null) { warning_circle.remove(); warning_circle = null; } if (mPfMarkerList != null && mPfMarkerList.size() > 0) { mPfMarkerList = null; } if (mPfPolylineList != null && mPfPolylineList.size() > 0) { mPfPolylineList = null; } // 电子围栏 if (mErLatLngList != null && mErLatLngList.size() > 0) { mErLatLngList = null; } if (mErMarkerList != null && mErMarkerList.size() > 0) { mErMarkerList = null; } if (mErPolylineList != null && mErPolylineList.size() > 0) { mErPolylineList = null; } mMapView.onDestroy(); aMap = null; // if (null != mLocationClient) { // mLocationClient.onDestroy(); // } } }
GuideMapMarkerTool.javapackage com.gdu.mvp_view.flightRouteplan; import android.app.Service; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint.Align; import android.os.Vibrator; import android.text.TextPaint; import android.util.TypedValue; import android.widget.TextView; import com.amap.api.maps.AMap; import com.amap.api.maps.AMap.OnMarkerClickListener; import com.amap.api.maps.AMapUtils; import com.amap.api.maps.model.BitmapDescriptor; 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.LatLngBounds; import com.amap.api.maps.model.LatLngBounds.Builder; import com.amap.api.maps.model.Marker; import com.amap.api.maps.model.MarkerOptions; import com.amap.api.maps.model.Polygon; import com.amap.api.maps.model.PolygonOptions; import com.amap.api.maps.model.Polyline; import com.amap.api.maps.model.PolylineOptions; import com.gdu.config.GduConfig; import com.gdu.config.UavStaticVar; import com.gdu.phonedrone.R; import com.gdu.util.BBLog; import com.gdu.util.StringUtils; import com.gdu.views.AngelaTXHToast; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import static com.gdu.mvp_view.flightRouteplan.GuideMapFragment.fp_validityRange; import static com.gdu.mvp_view.flightRouteplan.GuideMapFragment.isElectronicRail_state; import static com.gdu.mvp_view.flightRouteplan.GuideMapFragment.isWayPointMode_state; public class GuideMapMarkerTool implements AMap.OnMarkerDragListener, OnMarkerClickListener { private Context context; private AMap aMap; private AngelaTXHToast txhToast; //实时控制页面下滑提示 // init list 【航迹规划】 private ArrayList<Marker> mPfMarkerList; private ArrayList<LatLng> mPfLatLngList; private ArrayList<Polyline> mPfPolylineList; private ArrayList<Float> mPfFlightDisList; private TextView mTv_flightdis; // init list 【电子围栏】 private ArrayList<Marker> mErMarkerList; private ArrayList<LatLng> mErLatLngList; private ArrayList<Polyline> mErPolylineList; // Marker config private MarkerOptions options; // 围栏不规则 矩形 cover private Polygon polygon; // 小数点保留一位 private DecimalFormat df = new DecimalFormat("##.#"); // 红旗和空白图片资源 private BitmapDescriptor mFlagesource; private BitmapDescriptor mBlanksource; private ArrayList<BitmapDescriptor> mBitmapList; // 无人机端 Marker private Marker mPlaneMarker; // 手机端标志 Marker private Marker mPeopleMarker; // 旗子Marker public Marker mFlagMarker; // init data private boolean mLoopMode; private int mLoopCount; private int planeAngle = 0; private int mapAngle = 0; // 构造方法,传入需要用的值 public GuideMapMarkerTool(Context context, AngelaTXHToast txhToast, AMap aMap, ArrayList<Marker> pf_markersList, ArrayList<LatLng> pf_latLngList, ArrayList<Polyline> pf_polylineList, ArrayList<Float> pf_flightdisList, TextView tv_flightdis, ArrayList<Marker> er_markersList, ArrayList<LatLng> er_latLngList, ArrayList<Polyline> er_polylineList ) { initGuideMap(aMap); this.aMap = aMap; this.context = context; this.txhToast = txhToast; // 航迹规划 this.mPfMarkerList = pf_markersList; this.mPfLatLngList = pf_latLngList; this.mPfPolylineList = pf_polylineList; this.mPfFlightDisList = pf_flightdisList; this.mTv_flightdis = tv_flightdis; // 电子围栏 this.mErMarkerList = er_markersList; this.mErLatLngList = er_latLngList; this.mErPolylineList = er_polylineList; } 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); } // 设置循环圈数 public void setLoop(boolean loop, int count) { mLoopMode = loop; mLoopCount = count; } // 判断是否是循环状态 public boolean isLoop() { return mLoopMode; } // 获得循环圈数 public int getLoopCount() { return mLoopCount; } //刷新人的位置 public void updatePeopleMarker(LatLng lagLng) { if (mPeopleMarker != null) { mPeopleMarker.remove(); } // 手机端添加起点. mPeopleMarker = aMap.addMarker(new MarkerOptions() .position(lagLng) .anchor(0.5f, 1f) .draggable(false) .icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory .decodeResource(context.getResources(), R.drawable.bluepoint)))); } /** * <p>设置飞机角度</p> * * @param angle */ public void setPlaneAngle(int angle) { planeAngle = 0 - angle; if (mPlaneMarker != null) { mPlaneMarker.setRotateAngle(planeAngle + mapAngle); } } public void setPlaneAngle(float angle) { mapAngle = (int) angle; if (mPlaneMarker != null) { mPlaneMarker.setRotateAngle(planeAngle + mapAngle); } } //使得栈里面的点尽可能都在可视区域范围内 private void updateCamera() { Builder builder = new LatLngBounds.Builder(); for (int i = 0; i < mPfLatLngList.size(); i++) { LatLng latLng = mPfLatLngList.get(i); builder = builder.include(latLng); } LatLngBounds bounds = builder.build(); // aMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10)); } public void refreshPointNumber() { for (int i = 0; i < mPfMarkerList.size(); i++) { mPfMarkerList.get(i).setIcon( BitmapDescriptorFactory.fromBitmap(getBitMap(i + 1))); } } // dp转px public static int dp2px(Context context, int dp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()); } // -------------------航迹规划开始,更新无人机位置------------------- //更新无人机mark在地图上的位置 public void addPlaneMarker(LatLng latLng, LatLng lastLatLng) { if (mPlaneMarker != null) { mPlaneMarker.remove(); } MarkerOptions options = new MarkerOptions(); options.anchor(0.5f, 0.5f); options.position(latLng); options.icon(BitmapDescriptorFactory .fromResource(R.drawable.icon_plane)); mPlaneMarker = aMap.addMarker(options); mPlaneMarker.setRotateAngle(planeAngle + mapAngle); // 通过栈顶元素与当前的latLng 得到角度。 // if (mPfLatLngList.isEmpty()) { // return; // } // // double currentLatitue = lastLatLng.latitude; // double currentLongtitue = lastLatLng.longitude; // // double latitude = latLng.latitude; // double longtitue = latLng.longitude; // // double rotate = 0; // if (currentLatitue - latitude != 0) { // boolean flag1 = (longtitue - currentLongtitue) > 0; // double k = (longtitue - currentLongtitue) // / (latitude - currentLatitue); // boolean flag2 = k > 0; // // /* // * 下面计算的是无人机marker的角度。根据平面坐标系的四个象限知识, 第一象限对应右下角,第二象限对应 左下角, // * 第三象限对应左上角,第四象限对应右上角 。 // * // * mPlaneMarker.setRotateAngle 从正北开始,逆时钟计算 // */ // if (flag2) { // if (flag1) {// 第一象限 // rotate = 360 - Math.toDegrees(Math.atan(k)); // } else {// 第三象限 // rotate = 180 - Math.toDegrees(Math.atan(k)); // } // } else { // if (flag1) {// 第二象限 // rotate = 180 - Math.toDegrees(Math.atan(k)); // } else {// 第四象限 // rotate = Math.abs(Math.toDegrees(Math.atan(k))); // } // } // // mPlaneMarker.setRotateAngle((float) rotate); // } } // -----------绘制 Marker,number,Line --------------------- /** * <p>设置Marker 是否可移动,根据不同情况来 设置</p> * <p>默认设置可以移动</p> * * @param isMove 是否可以移动 */ public void MarkerIsMove(boolean isMove) { options.draggable(isMove); } /** * <P>给marker上绘制数字</P> * <P>限制最多 50个 </P> * * @param text * @return path_planning_point */ public Bitmap getBitMap(int text) { BBLog.LogE("getBitMap", text + ""); Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.path_planning_point).copy(Bitmap.Config.ARGB_8888, true); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight()); Canvas canvas = new Canvas(bitmap); // 设置文字样式,大小,颜色 TextPaint textPaint = new TextPaint(); textPaint.setAntiAlias(true); textPaint.setColor(Color.rgb(226, 138, 34)); textPaint.setTextSize(45f); textPaint.setFakeBoldText(true); textPaint.setTextAlign(Align.CENTER); canvas.drawText(String.valueOf(text), canvas.getWidth() / 2, canvas.getHeight() / 2, textPaint); return bitmap; } /** * <p>根据经纬度往地图上添加marker</p> * <p>[航迹规划]</p> * * @param lagLng 当前点击的 下的坐标 * @param markerNum 计数 * @return */ public Marker addPfMarker(LatLng lagLng, int markerNum) { options.anchor(0.5f, 1f) .position(lagLng) .icon(BitmapDescriptorFactory.fromBitmap(getBitMap(markerNum))); return aMap.addMarker(options); } /** * <p>根据经纬度往地图上添加marker</p> * <p>[终点Marker]</p> * <p>[静态Marker]</p> * * @param lagLng 当前点击的 下的坐标 * @return */ public Marker addEndMarker(LatLng lagLng) { if (mFlagMarker != null) { mFlagMarker.remove(); } options.anchor(0.5f, 1f) .position(lagLng) .draggable(false) .icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_map_end_point_activity)); mFlagMarker = aMap.addMarker(options); return mFlagMarker; } /** * <p>根据经纬度往地图上添加marker</p> * 刷新红旗的位置 * <p>小红旗闪烁</p> * <p>[终点Marker]</p> * <p>[动态Marker]</p> * * @param lagLng * @return */ public Marker updateFlagMarker(LatLng lagLng) { if (mFlagMarker != null) { mFlagMarker.remove(); } if (mBitmapList != null && !mBitmapList.isEmpty()) { mBitmapList.clear(); } System.gc(); // 设置小红旗闪烁 mFlagesource = BitmapDescriptorFactory.fromResource(R.drawable.icon_map_end_point_activity); mBlanksource = BitmapDescriptorFactory.fromResource(R.drawable.icon_map_end_point_default); mBitmapList = new ArrayList<BitmapDescriptor>(); mBitmapList.add(mFlagesource); mBitmapList.add(mBlanksource); if (UavStaticVar.screenWidth > 2000) { mFlagMarker = aMap.addMarker(new MarkerOptions().position(lagLng) .anchor(0.9f, 1.5f).period(20).icons(mBitmapList)); } else { mFlagMarker = aMap.addMarker(new MarkerOptions().position(lagLng) .anchor(0.5f, 1.0f).period(20).icons(mBitmapList)); } return mFlagMarker; } /** * <p>根据经纬度往地图上添加marker</p> * <p>[电子围栏]</p> * * @param lagLng 当前点击的 下的坐标 * @return */ public Marker addErMarker(LatLng lagLng) { options.anchor(0.5f, 1f) .position(lagLng) .icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_fence_point)); return aMap.addMarker(options); } /** * <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> * <p>实线</p> * * @param beginlatLng 起点 * @param endLatLng 终点 * @return */ public Polyline addPolySolidLine(LatLng beginlatLng, LatLng endLatLng) { PolylineOptions options = new PolylineOptions(); options.add(beginlatLng, endLatLng) .width(10) .color(Color.rgb(255, 121, 24)) .setDottedLine(false);// 实线 return aMap.addPolyline(options); } /** * <p>电子围栏区域</p> * <p>绘制多边形覆盖</p> */ public void drawpolygonCover() { if (polygon != null) { polygon.remove(); } PolygonOptions polygonOptions = new PolygonOptions(); polygonOptions.strokeWidth(5) .strokeColor(Color.argb(102, 255, 121, 24)) // 边框颜色 .fillColor(Color.argb(22, 226, 138, 34)); // 多边形的填充色 // 添加 多边形的每个顶点(顺序添加) for (int i = 0; i < mErLatLngList.size(); i++) { polygonOptions.add(mErLatLngList.get(i)); } polygon = aMap.addPolygon(polygonOptions); } /** * <p>清除电子围栏围成的区域</p> */ public void cleanPolygonCover() { if (polygon != null) polygon.remove(); } /** * <p>返回一个点是否在一个多边形区域内</p> * * @param mLatlng 多边形坐标点列表 * @param latLng 待判断点 * @return true 多边形包含这个点,false 多边形未包含这个点。 */ public boolean isPolygonContainsPoint(List<LatLng> mLatlng, LatLng latLng) { int i, j; boolean c = false; for (i = 0, j = mLatlng.size() - 1; i < mLatlng.size(); j = i++) { if (((mLatlng.get(i).longitude > latLng.longitude) != ((mLatlng.get(j).longitude > latLng.longitude)) && (latLng.latitude < (mLatlng.get(j).latitude - mLatlng.get(i).latitude) * (latLng.longitude - mLatlng.get(i).longitude) / (mLatlng.get(j).longitude - mLatlng.get(i).longitude) + mLatlng.get(i).latitude))) c = !c; } return c; } /** * <p>判断2根线是否相交</p> */ public boolean isPolygonIntersect(List<LatLng> mLatlng) { if (mLatlng.size() > 3) { for (int i = 0; i < mLatlng.size(); i++) { } } return false; } //-------------------Marker点击,长按,拖拽事件------------------ /** * <p>点击marker事件</p> * * @param arg0 * @return */ @Override public boolean onMarkerClick(Marker arg0) { // 航点信息此版本不需要,暂时屏蔽 // Marker marker = arg0; // if (null != inforPopupWindow) // { // inforPopupWindow.dismiss(); // inforPopupWindow = null; // } // if (marker != mFlagMarker) // { // initPointPopuptWindow(mGuideMapView, marker); // } return true; } /** * <p>是否是航迹规划模式</p> */ private int isPfMode;// 0 关闭 1 航迹规划模式 2 电子围栏模式 public void isPfMode(int ispfmode) { this.isPfMode = ispfmode; } /** * <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> * * @param marker */ private void BackDraggablePoint(Marker marker) { marker.setPosition(curMarkerPosition); drawTrackLine(marker);// 不满足要求 } /** * <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> */ private float dist; private void updateFlightDisEvent(int i, Marker marker) { // 航线距离问题 if (i == 0) { mPfFlightDisList.set(i, AMapUtils.calculateLineDistance(mPfLatLngList.get(0), marker.getPosition())); BBLog.LogE("updateFlightDisEvent-1", AMapUtils.calculateLineDistance(mPfLatLngList.get(0), marker.getPosition()) + ""); } else if (i == mPfMarkerList.size() - 1) { BBLog.LogE("updateFlightDisEvent-2", AMapUtils.calculateLineDistance(mPfLatLngList.get(0), marker.getPosition()) + ""); mPfFlightDisList.set(i, AMapUtils.calculateLineDistance(mPfLatLngList.get(i), marker.getPosition())); } else { BBLog.LogE("updateFlightDisEvent-3", AMapUtils.calculateLineDistance(mPfLatLngList.get(0), marker.getPosition()) + ""); if (i != mPfMarkerList.size() - 1) { mPfFlightDisList.set(i + 1, AMapUtils.calculateLineDistance(marker.getPosition(), mPfLatLngList.get(i + 2))); } mPfFlightDisList.set(i, AMapUtils.calculateLineDistance(marker.getPosition(), mPfLatLngList.get(i))); } // 重新计算所有的 飞行距离 for (int j = 0; j < mPfFlightDisList.size(); j++) { dist += mPfFlightDisList.get(j); } mTv_flightdis.setText(df.format(dist) + StringUtils.getUnit()); dist = 0; } // ---------在拖动Marker 时候 Circle 的状态判定 --------------- // 有效域 圆 private Circle normal_circle; // 无效域 圆 private Circle warning_circle; // 当前手机位置(圆心) private LatLng currentphoneLatlng; // 设置参数 public void setParameter(LatLng currentphoneLatlng, Circle warning_circle, Circle normal_circle) { this.currentphoneLatlng = currentphoneLatlng; this.warning_circle = warning_circle; this.normal_circle = normal_circle; } /** * <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); } } }
GPSTranslateGuide.javapackage com.gdu.mvp_view.flightRouteplan.helper; import com.amap.api.maps.model.LatLng; import java.util.HashMap; import java.util.Map; /** * <P>火星坐标和大地坐标的转换</P> */ public class GPSTranslateGuide { static double pi = 3.14159265358979324; static double a = 6378245.0; static double ee = 0.00669342162296594323; public static com.amap.api.maps.model.LatLng AmapTransform(double wgLat, double wgLon) { double dLat = transformLat(wgLon - 105.0, wgLat - 35.0); double dLon = transformLon(wgLon - 105.0, wgLat - 35.0); double radLat = wgLat / 180.0 * pi; double magic = Math.sin(radLat); magic = 1 - ee * magic * magic; double sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi); dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi); double mgLat = wgLat + dLat; double mgLon = wgLon + dLon; com.amap.api.maps.model.LatLng latLng = new com.amap.api.maps.model.LatLng(mgLat, mgLon); return latLng; } public static com.google.android.gms.maps.model.LatLng GoogleTransform(double wgLat, double wgLon) { double dLat = transformLat(wgLon - 105.0, wgLat - 35.0); double dLon = transformLon(wgLon - 105.0, wgLat - 35.0); double radLat = wgLat / 180.0 * pi; double magic = Math.sin(radLat); magic = 1 - ee * magic * magic; double sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi); dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi); double mgLat = wgLat + dLat; double mgLon = wgLon + dLon; com.google.android.gms.maps.model.LatLng latLng = new com.google.android.gms.maps.model.LatLng(mgLat, mgLon); return latLng; } //转换经纬度地纬度 static double transformLat(double x, double y) { double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x)); ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0; ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0; ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0; return ret; } //转换经纬度的纬度 static double transformLon(double x, double y) { double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)); ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0; ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0; ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0; return ret; } /** * <p>GCJ02坐标系:即火星坐标系</p> * <p>WGS坐标系:即地球坐标</p> * <p>火星坐标转地球坐标</p> * @param lon * @param lat * @return */ public static com.amap.api.maps.model.LatLng gcj2wgs(double lon, double lat) { double lontitude = lon - (((Double) transformtoWGS(lon, lat).get("lon")).doubleValue() - lon); double latitude = (lat - (((Double) (transformtoWGS(lon, lat)) .get("lat")).doubleValue() - lat)); com.amap.api.maps.model.LatLng latLng = new com.amap.api.maps.model.LatLng(latitude, lontitude); return latLng; } /** * <p>(地球)大地坐标</p> * * @param lon * @param lat * @return */ public static Map<String, Double> transformtoWGS(double lon, double lat) { HashMap<String, Double> localHashMap = new HashMap<String, Double>(); double dLat = transformLat(lon - 105.0, lat - 35.0); double dLon = transformLon(lon - 105.0, lat - 35.0); double radLat = lat / 180.0 * pi; double magic = Math.sin(radLat); magic = 1 - ee * magic * magic; double sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi); dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi); double mgLat = lat + dLat; double mgLon = lon + dLon; localHashMap.put("lon", mgLon); localHashMap.put("lat", mgLat); return localHashMap; } /** * @anthor yuhao * 大地坐标转火星坐标 * @param wgLat * @param wgLon * @return */ public static LatLng transform2Mars(double wgLat, double wgLon) { double dLat = transformLat(wgLon - 105.0, wgLat - 35.0); double dLon = transformLon(wgLon - 105.0, wgLat - 35.0); double radLat = wgLat / 180.0 * pi; double magic = Math.sin(radLat); magic = 1 - ee * magic * magic; double sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi); dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi); double mgLat = wgLat + dLat; double mgLon = wgLon + dLon; LatLng latLng = new LatLng(mgLat, mgLon); return latLng; } }
感谢各位大佬观看,哪里不对请指出,或者有疑问给我留言,可以交流。
下一期:展示几个动画和View 就是我们产品 给我定义的几个 自创 动画效果,如图一,本来我以为很难,我在一步一步摸索,然后简化后发现只需要2句代码就可以了。真的这个效果只需要2句代码。下期详细解释。