1057 lines
39 KiB
Java
1057 lines
39 KiB
Java
package com.mogo.map;
|
||
|
||
import static com.mogo.map.uicontroller.VisualAngleMode.MAP_STYLE_VR_ANGLE_300;
|
||
import static com.mogo.map.uicontroller.VisualAngleMode.MAP_STYLE_VR_ANGLE_CROSS;
|
||
import static com.mogo.map.uicontroller.VisualAngleMode.MAP_STYLE_VR_ANGLE_TOP;
|
||
import static com.mogo.map.uicontroller.VisualAngleMode.MODE_CLOSE_SIGHT;
|
||
import static com.mogo.map.uicontroller.VisualAngleMode.MODE_LONG_SIGHT;
|
||
import static com.mogo.map.uicontroller.VisualAngleMode.MODE_MEDIUM_SIGHT;
|
||
|
||
import android.content.Context;
|
||
import android.graphics.Point;
|
||
import android.graphics.Rect;
|
||
import android.location.Location;
|
||
import android.os.Bundle;
|
||
import android.os.Trace;
|
||
import android.util.Log;
|
||
import android.view.MotionEvent;
|
||
import android.view.View;
|
||
|
||
import com.mogo.commons.constants.SharedPrefsConstants;
|
||
import com.mogo.commons.debug.DebugConfig;
|
||
import com.mogo.eagle.core.data.config.HdMapBuildConfig;
|
||
import com.mogo.eagle.core.data.map.MogoLatLng;
|
||
import com.mogo.eagle.core.data.map.MogoLocation;
|
||
import com.mogo.eagle.core.function.call.map.CallerMapDataCollectorManager;
|
||
import com.mogo.eagle.core.function.call.map.CallerMapLocationListenerManager;
|
||
import com.mogo.eagle.core.function.call.map.CallerMapStyleListenerManager;
|
||
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
|
||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||
import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr;
|
||
import com.mogo.eagle.core.utilcode.mogo.toast.TipToast;
|
||
import com.mogo.eagle.core.utilcode.util.GsonUtils;
|
||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||
import com.mogo.map.listener.MogoMapListenerHandler;
|
||
import com.mogo.map.navi.MogoCarLocationChangedListenerRegister;
|
||
import com.mogo.map.uicontroller.CarCursorOption;
|
||
import com.mogo.map.uicontroller.EnumMapUI;
|
||
import com.mogo.map.uicontroller.IMogoMapUIController;
|
||
import com.mogo.map.uicontroller.MapCameraPosition;
|
||
import com.mogo.map.uicontroller.MapControlResult;
|
||
import com.mogo.map.uicontroller.VisualAngleMode;
|
||
import com.mogo.map.utils.MogoMapUtils;
|
||
import com.mogo.map.utils.ObjectUtils;
|
||
import com.mogo.map.utils.PointInterpolatorUtil;
|
||
import com.mogo.map.utils.ResIdCache;
|
||
import com.zhidaoauto.map.sdk.open.MapAutoApi;
|
||
import com.zhidaoauto.map.sdk.open.abs.MapStatusListener;
|
||
import com.zhidaoauto.map.sdk.open.abs.OnCameraChangeListener;
|
||
import com.zhidaoauto.map.sdk.open.abs.OnMapClickListener;
|
||
import com.zhidaoauto.map.sdk.open.abs.OnMapLoadedListener;
|
||
import com.zhidaoauto.map.sdk.open.abs.OnMapStyleListener;
|
||
import com.zhidaoauto.map.sdk.open.abs.OnMapTouchListener;
|
||
import com.zhidaoauto.map.sdk.open.abs.OnMapViewVisualAngleChangeListener;
|
||
import com.zhidaoauto.map.sdk.open.camera.CameraPosition;
|
||
import com.zhidaoauto.map.sdk.open.camera.CameraUpdateFactory;
|
||
import com.zhidaoauto.map.sdk.open.camera.LatLngBounds;
|
||
import com.zhidaoauto.map.sdk.open.data.MapDataApi;
|
||
import com.zhidaoauto.map.sdk.open.data.SinglePointRoadInfo;
|
||
import com.zhidaoauto.map.sdk.open.location.LocationListener;
|
||
import com.zhidaoauto.map.sdk.open.location.MyLocationStyle;
|
||
import com.zhidaoauto.map.sdk.open.location.RTKAutopilotLocationBean;
|
||
import com.zhidaoauto.map.sdk.open.marker.BitmapDescriptorFactory;
|
||
import com.zhidaoauto.map.sdk.open.marker.Marker;
|
||
import com.zhidaoauto.map.sdk.open.marker.OnMarkClickListener;
|
||
import com.zhidaoauto.map.sdk.open.query.LonLatPoint;
|
||
import com.zhidaoauto.map.sdk.open.tools.MapTools;
|
||
import com.zhidaoauto.map.sdk.open.view.MapAutoView;
|
||
import com.zhidaoauto.map.sdk.open.view.MapAutoViewHelper;
|
||
|
||
import org.jetbrains.annotations.NotNull;
|
||
import org.jetbrains.annotations.Nullable;
|
||
import org.json.JSONObject;
|
||
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
import java.util.concurrent.ConcurrentHashMap;
|
||
|
||
import mogo.telematics.pad.MessagePad;
|
||
|
||
public class AMapViewWrapper implements IMogoMapView,
|
||
IMogoMapUIController,
|
||
LocationListener,
|
||
OnMapLoadedListener,
|
||
MapStatusListener,
|
||
OnCameraChangeListener,
|
||
OnMapClickListener,
|
||
OnMapTouchListener,
|
||
OnMarkClickListener,
|
||
OnMapStyleListener,
|
||
MapStyleController.IMapStyleAutoChangedListener, OnMapViewVisualAngleChangeListener {
|
||
|
||
private static final String TAG = "AMapViewWrapper";
|
||
private final MapAutoView mMapView;
|
||
private final IMogoMap mIMap;
|
||
private AMapMarkerClickHandler mMarkerClickHandler;
|
||
|
||
private final CarCursorOption DEFAULT_OPTION = new CarCursorOption.Builder()
|
||
.carCursorRes(R.drawable.map_api_ic_current_location2)
|
||
.naviCursorRes(R.drawable.ic_amap_navi_cursor)
|
||
.build();
|
||
private CarCursorOption mCarCursorOption = DEFAULT_OPTION;
|
||
private EnumMapUI mCurrentCarUIMode;
|
||
private EnumMapUI mCurrentUI;
|
||
private VisualAngleMode mVisualAngleMode = MODE_MEDIUM_SIGHT;
|
||
|
||
private int mLockZoom = 16;
|
||
private long startTime;
|
||
private float mDefaultZoomLevel = 16.0f;
|
||
private boolean mIsCarLocked = false;
|
||
private boolean mIsLightStyle = false;
|
||
private boolean mMapLoaded = false;
|
||
private boolean mIsFirstLocated = true;
|
||
private boolean mIsDelayed = false;
|
||
|
||
public AMapViewWrapper(MapAutoView mMapView) {
|
||
startTime = System.currentTimeMillis();
|
||
CallerLogger.INSTANCE.i(TAG, "autoop--AMapViewWrapper: init");
|
||
this.mMapView = mMapView;
|
||
initViews();
|
||
initListeners();
|
||
this.mIMap = new AMapWrapper(this.mMapView.getMapAutoViewHelper(), this.mMapView, this);
|
||
}
|
||
|
||
private void initViews() {
|
||
|
||
}
|
||
|
||
private void initMapView() {
|
||
if (mMapView == null) {
|
||
return;
|
||
}
|
||
MapAutoViewHelper options = mMapView.getMapAutoViewHelper();
|
||
if (options != null) {
|
||
//设置手势是否可以缩放 isCanZoom true 可缩放 false 不可缩放
|
||
options.setZoomGesturesEnabled(true);
|
||
options.setScaleVRMode(true);
|
||
if (options.getMyLocationStyle() != null) {
|
||
options.getMyLocationStyle().setDisplayAnimEnable(false);
|
||
}
|
||
//修改自车模型,未来需区分车的类型
|
||
options.setMyLocationStyle(options.getMyLocationStyle().myLocationIcon(HdMapBuildConfig.currentCarVrIconRes, true));
|
||
// MapAutoApi.INSTANCE.getMyLocationStyle().myLocationIcon(HdMapBuildConfig.currentCarVrIconRes, true);
|
||
}
|
||
}
|
||
|
||
private void initListeners() {
|
||
|
||
mMapView.setOnMarkClickListener(this);
|
||
mMarkerClickHandler = AMapMarkerClickHandler.getInstance();
|
||
mMapView.setOnMapLoadedListener(this);
|
||
mMapView.setOnMapTouchListener(this);
|
||
mMapView.setOnMapClickListener(this);
|
||
mMapView.getLocationClient().registerListener(this);
|
||
mMapView.registerListener(this, MapAutoApi.LISTENER_TYPE_ZOOM);
|
||
mMapView.registerListener(this, MapAutoApi.LISTENER_TYPE_ROTATE);
|
||
mMapView.registerListener(this, MapAutoApi.LISTENER_TYPE_3D);
|
||
mMapView.setOnCameraChangeListener(this);
|
||
mMapView.setOnMapStyleListener(this);
|
||
mMapView.setOnMapViewVisualAngleChangeListener(this);
|
||
CallerLogger.INSTANCE.d(TAG, "styleop - initListeners - setOnMapStyleListener - view " + mMapView);
|
||
}
|
||
|
||
private Context getContext() {
|
||
return mMapView.getContext();
|
||
}
|
||
|
||
@Override
|
||
public View getMapView() {
|
||
return mMapView;
|
||
}
|
||
|
||
@Override
|
||
public IMogoMap getMap() {
|
||
return mIMap;
|
||
}
|
||
|
||
@Override
|
||
public void onCreate(Bundle bundle) {
|
||
if (mMapView != null) {
|
||
mMapView.onCreate(bundle);
|
||
CallerLogger.INSTANCE.d(TAG, "map onCreate");
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onResume() {
|
||
if (mMapView != null) {
|
||
mMapView.onResume();
|
||
CallerLogger.INSTANCE.d(TAG, "map onResume");
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onPause() {
|
||
if (mMapView != null) {
|
||
mMapView.onPause();
|
||
CallerLogger.INSTANCE.d(TAG, "map onPause");
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onDestroy() {
|
||
if (mMapView != null) {
|
||
mMapView.onDestroy();
|
||
mMapView.setOnMarkClickListener(null);
|
||
mMapView.setOnMapLoadedListener(null);
|
||
mMapView.setOnMapTouchListener(null);
|
||
mMapView.setOnMapClickListener(null);
|
||
mMapView.getLocationClient().unRegisterListener(this);
|
||
mMapView.setOnCameraChangeListener(null);
|
||
CallerLogger.INSTANCE.d(TAG, "map onDestroy");
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onSaveInstanceState(Bundle outState) {
|
||
if (mMapView != null) {
|
||
mMapView.onSaveInstanceState(outState);
|
||
CallerLogger.INSTANCE.d(TAG, "map onSaveInstanceState");
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onLowMemory() {
|
||
|
||
}
|
||
|
||
@Override
|
||
public void setTrafficEnabled(boolean visible) {
|
||
if (checkAMapView()) {
|
||
// mMapView.getMapAutoViewHelper().setTraffic( visible );
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public MapControlResult changeZoom(boolean zoom) {
|
||
if (checkAMapView()) {
|
||
mDefaultZoomLevel = (getMap().getZoomLevel() + 0.5f);
|
||
if (zoom) {
|
||
if (mDefaultZoomLevel >= 20f) {
|
||
return MapControlResult.TARGET;
|
||
}
|
||
} else {
|
||
if (mDefaultZoomLevel <= 7f) {
|
||
return MapControlResult.TARGET;
|
||
}
|
||
}
|
||
|
||
if (zoom) {
|
||
mDefaultZoomLevel += 1f;
|
||
if (mDefaultZoomLevel > 19f) {
|
||
mDefaultZoomLevel = 19f;
|
||
}
|
||
} else {
|
||
mDefaultZoomLevel -= 1f;
|
||
if (mDefaultZoomLevel < 8f) {
|
||
mDefaultZoomLevel = 8f;
|
||
}
|
||
}
|
||
changeZoom(mDefaultZoomLevel);
|
||
}
|
||
return MapControlResult.SUCCESS;
|
||
}
|
||
|
||
@Override
|
||
public MapControlResult changeZoom(float zoom) {
|
||
if (mCurrentUI == EnumMapUI.Type_VR) {
|
||
return MapControlResult.ERROR;
|
||
}
|
||
CallerLogger.INSTANCE.d(TAG, "changeZoom : " + zoom);
|
||
if (DebugConfig.isDebug()) {
|
||
CallerLogger.INSTANCE.d(TAG, Log.getStackTraceString(new Throwable()));
|
||
}
|
||
getMap().changeZoom(zoom);
|
||
return MapControlResult.SUCCESS;
|
||
}
|
||
|
||
@Override
|
||
public void changeMapMode(EnumMapUI ui) {
|
||
if (ui == null) {
|
||
return;
|
||
}
|
||
|
||
CallerLogger.INSTANCE.d(TAG, "设置的样式 :" + ui);
|
||
if (checkAMapView()) {
|
||
mMapView.getMapAutoViewHelper().setScaleVRMode(true);
|
||
mMapView.getMapAutoViewHelper().setMapStyle(MapAutoApi.MAP_STYLE_VR);
|
||
// TODO 这里临时修改关闭2D
|
||
// switch (ui) {
|
||
// case CarUp_2D:
|
||
// case CarUp_3D:
|
||
// case NorthUP_2D:
|
||
// setUIMode(ui);
|
||
// break;
|
||
// case Type_VR:
|
||
// mMapView.getMapAutoViewHelper().setScaleVRMode(true);
|
||
// mMapView.getMapAutoViewHelper().setMapStyle(MapAutoApi.MAP_STYLE_VR);
|
||
// return;
|
||
// case Type_Light:
|
||
// mMapView.getMapAutoViewHelper().setAutoSwitchStyle(false);
|
||
// mMapView.getMapAutoViewHelper().setMapStyle(MapAutoApi.MAP_STYLE_DAY);
|
||
// mIsLightStyle = true;
|
||
// break;
|
||
// case Type_Night:
|
||
// mMapView.getMapAutoViewHelper().setAutoSwitchStyle(false);
|
||
// mMapView.getMapAutoViewHelper().setMapStyle(MapAutoApi.MAP_STYLE_NIGHT);
|
||
// mIsLightStyle = false;
|
||
// break;
|
||
// case Type_AUTO_LIGHT_Night:
|
||
// mMapView.getMapAutoViewHelper().setAutoSwitchStyle(true);
|
||
// break;
|
||
// }
|
||
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void changeMapVisualAngle(VisualAngleMode angelMode, MogoLatLng mogoLatLng) {
|
||
MapAutoViewHelper mapAutoViewHelper = mMapView.getMapAutoViewHelper();
|
||
if (mapAutoViewHelper != null) {
|
||
mVisualAngleMode = angelMode;
|
||
if (angelMode == MODE_CLOSE_SIGHT) {
|
||
if (mogoLatLng == null) {
|
||
CallerLogger.INSTANCE.e(TAG, "切换地图近景需要传入要移动的经纬度数据");
|
||
return;
|
||
}
|
||
// 近景传入经纬度为点击地图上静态marker经纬度数据,为GPS坐标点。
|
||
mapAutoViewHelper.setNearViewAnglePosition(new LonLatPoint(mogoLatLng.lon, mogoLatLng.lat), true);
|
||
} else {
|
||
mapAutoViewHelper.setMapViewVisualAngle(angelMode.getCode());
|
||
}
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public VisualAngleMode getCurrentMapVisualAngle() {
|
||
return mVisualAngleMode;
|
||
}
|
||
|
||
@Override
|
||
public void moveToCenter(MogoLatLng latLng) {
|
||
moveToCenter(latLng, true);
|
||
}
|
||
|
||
private boolean checkAMapView() {
|
||
if (mMapView == null || mMapView.getMapAutoViewHelper() == null) {
|
||
CallerLogger.INSTANCE.e(TAG, "自研mapView实例为空,请检查");
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
@Override
|
||
public void moveToCenter(MogoLatLng latLng, boolean animate) {
|
||
CallerLogger.INSTANCE.d(TAG, "move to center " + latLng);
|
||
if (latLng == null || latLng.lat == 0.0d || latLng.lon == 0.0d) {
|
||
CallerLogger.INSTANCE.e(TAG, "latlng = null or is illegal");
|
||
return;
|
||
}
|
||
if (DebugConfig.isDebug()) {
|
||
CallerLogger.INSTANCE.d(TAG, Log.getStackTraceString(new Throwable()));
|
||
}
|
||
loseLockMode();
|
||
mMapView.getMapAutoViewHelper().animateCamera(new LonLatPoint(latLng.lon, latLng.lat));
|
||
}
|
||
|
||
@Override
|
||
public void showMyLocation(boolean visible) {
|
||
CallerLogger.INSTANCE.d(TAG, "showMyLocation1 " + visible);
|
||
// 如果是VR模式
|
||
if (mCurrentUI == EnumMapUI.Type_VR) {
|
||
return;
|
||
}
|
||
// 不是VR模式情况强制刷新下
|
||
if (checkAMapView()) {
|
||
MyLocationStyle style = mMapView.getMapAutoViewHelper().getMyLocationStyle();
|
||
if (visible) {
|
||
// 强制刷新一遍车标
|
||
style.myLocationIcon(mCarCursorOption.getCarCursorRes());
|
||
}
|
||
mMapView.getMapAutoViewHelper().setMyLocationStyle(style);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void showMyLocation(View view) {
|
||
if (DebugConfig.isDebug()) {
|
||
CallerLogger.INSTANCE.d(TAG, Log.getStackTraceString(new Throwable()));
|
||
}
|
||
if (checkAMapView()) {
|
||
MyLocationStyle style = mMapView.getMapAutoViewHelper().getMyLocationStyle();
|
||
style.myLocationIcon(BitmapDescriptorFactory.INSTANCE.convertViewToBitmap(view));
|
||
mMapView.getMapAutoViewHelper().setMyLocationStyle(style);
|
||
}
|
||
}
|
||
|
||
public void initMyLocation() {
|
||
if (checkAMapView()) {
|
||
mMapView.getMapAutoViewHelper().setMyLocationEnabled(true);
|
||
MyLocationStyle style = mMapView.getMapAutoViewHelper().getMyLocationStyle();
|
||
style.setLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER);
|
||
style.interval(1000);
|
||
// style.anchor( 0.5F, 0.5F );
|
||
// style.strokeColor( Color.TRANSPARENT );
|
||
// style.strokeWidth( 0 );
|
||
// style.radiusFillColor( Color.TRANSPARENT );
|
||
mMapView.getMapAutoViewHelper().setMyLocationStyle(style);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void recoverLockMode() {
|
||
if (checkAMapView()) {
|
||
if (mCurrentUI == EnumMapUI.Type_VR) {
|
||
return;
|
||
}
|
||
CallerLogger.INSTANCE.d(TAG, "锁车");
|
||
mMapView.getMapAutoViewHelper().setLockMode(true);
|
||
mIsCarLocked = true;
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void loseLockMode() {
|
||
if (mCurrentUI == EnumMapUI.Type_VR) {
|
||
return;
|
||
}
|
||
CallerLogger.INSTANCE.d(TAG, "解锁锁车");
|
||
mMapView.getMapAutoViewHelper().setLockMode(false);
|
||
mIsCarLocked = false;
|
||
}
|
||
|
||
@Override
|
||
public void setLockZoom(int var1) {
|
||
mLockZoom = var1;
|
||
}
|
||
|
||
@Override
|
||
public void displayOverview(Rect bounds) {
|
||
|
||
}
|
||
|
||
@Override
|
||
public float getScalePerPixel() {
|
||
return getMap().getScalePerPixel();
|
||
}
|
||
|
||
@Override
|
||
public float getZoomLevel() {
|
||
return getMap().getZoomLevel();
|
||
}
|
||
|
||
@Override
|
||
public float getRoadWidth(double lon, double lat, float angle, boolean isGpsLocation, boolean isRTK) {
|
||
return getMap().getRoadWidth(lon, lat, angle, isGpsLocation, isRTK);
|
||
}
|
||
|
||
@Override
|
||
public MogoLatLng getCameraNorthEastPosition() {
|
||
return ObjectUtils.fromAMap(MapTools.INSTANCE.getVisibleRegion().getRightTopPoint());
|
||
}
|
||
|
||
@Override
|
||
public MogoLatLng getCameraSouthWestPosition() {
|
||
try {
|
||
return ObjectUtils.fromAMap(MapTools.INSTANCE.getVisibleRegion().getLeftBottomPoint());
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
}
|
||
return null;
|
||
}
|
||
|
||
@Override
|
||
public MogoLatLng getWindowCenterLocation() {
|
||
try {
|
||
return ObjectUtils.fromAMap(mMapView.getMapAutoViewHelper().getCenter());
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
}
|
||
return null;
|
||
}
|
||
|
||
@Override
|
||
public void setPointToCenter(double mapCenterX, double mapCenterY) {
|
||
if (checkAMapView()) {
|
||
if (mCurrentUI == EnumMapUI.Type_VR) {
|
||
return;
|
||
}
|
||
CallerLogger.INSTANCE.d(TAG, "setPointToCenter x : " + mapCenterX + " y : " + mapCenterY);
|
||
mMapView.getMapAutoViewHelper().setPointToCenter((float) mapCenterX, (float) mapCenterY);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public Point getLocationPointInScreen(MogoLatLng latLng) {
|
||
if (checkAMapView()) {
|
||
try {
|
||
return MapTools.INSTANCE.toScreenLocation(ObjectUtils.fromMogo(latLng));
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
return null;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
@Override
|
||
public MogoLatLng getLocationMogoLatLngInScreen(Point point) {
|
||
if (checkAMapView()) {
|
||
try {
|
||
return ObjectUtils.fromAMap(
|
||
MapTools.INSTANCE.fromScreenLocation(point));
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
return null;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
@Override
|
||
public void setRenderFps(int fps) {
|
||
if (checkAMapView()) {
|
||
if (mMapView.getMapAutoViewHelper() != null) {
|
||
mMapView.getMapAutoViewHelper().setRenderFps(fps);
|
||
CallerLogger.INSTANCE.d(TAG, "设置刷新帧率 fps = " + fps);
|
||
}
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void showBounds(String tag, MogoLatLng carPosition, List<MogoLatLng> lonLats, Rect bound, boolean lockCarPosition) {
|
||
if (!checkAMapView()) {
|
||
return;
|
||
}
|
||
if (mCurrentUI == EnumMapUI.Type_VR) {
|
||
CallerLogger.INSTANCE.w(TAG, "vr 模式下忽略该设置");
|
||
return;
|
||
}
|
||
CallerLogger.INSTANCE.i(TAG, "showBounds : " + tag + " , " + carPosition.toString() + " , " + bound.toShortString() + " , " + lockCarPosition);
|
||
try {
|
||
LatLngBounds latLngBounds = MogoMapUtils.getLatLngBounds(carPosition, lonLats, lockCarPosition);
|
||
if (!lockCarPosition) {
|
||
loseLockMode();
|
||
}
|
||
mMapView.getMapAutoViewHelper().setCenter(ObjectUtils.fromMogo(carPosition));
|
||
mMapView.getMapAutoViewHelper().moveCamera(CameraUpdateFactory.INSTANCE.newLatLngBounds(latLngBounds, bound.left, bound.right, bound.top, bound.bottom));
|
||
} catch (Exception e) {
|
||
CallerLogger.INSTANCE.e(TAG, "tag : " + tag + " error : " + e);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void forceRender() {
|
||
if (checkAMapView()) {
|
||
mMapView.getMapAutoViewHelper().runOnDrawFrame();
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public float calculateLineDistance(MogoLatLng p1, MogoLatLng p2) throws Exception {
|
||
if (p1 == null || p2 == null) {
|
||
throw new Exception("计算距离的点不能为 null");
|
||
}
|
||
return MogoMapUtils.calculateLineDistance(ObjectUtils.fromMogo(p1), ObjectUtils.fromMogo(p2));
|
||
}
|
||
|
||
|
||
@Override
|
||
public EnumMapUI getCurrentUiMode() {
|
||
return mCurrentCarUIMode;
|
||
}
|
||
|
||
@Override
|
||
public void changeMyLocation(Location location) {
|
||
}
|
||
|
||
@Override
|
||
public synchronized boolean isCarLocked() {
|
||
return mMapView.getMapAutoViewHelper().getLockMode();
|
||
}
|
||
|
||
@Override
|
||
public void setCarCursorOption(CarCursorOption option) {
|
||
if (mCurrentUI == EnumMapUI.Type_VR) {
|
||
return;
|
||
}
|
||
if (mCarCursorOption != null && mCarCursorOption != DEFAULT_OPTION) {
|
||
mCarCursorOption.destroy();
|
||
}
|
||
if (option != null) {
|
||
try {
|
||
mCarCursorOption = option.clone();
|
||
} catch (Exception e) {
|
||
mCarCursorOption = DEFAULT_OPTION;
|
||
}
|
||
} else {
|
||
mCarCursorOption = DEFAULT_OPTION;
|
||
}
|
||
if (!checkAMapView()) {
|
||
return;
|
||
}
|
||
|
||
if (mMapView.getMapAutoViewHelper() == null) {
|
||
return;
|
||
}
|
||
MyLocationStyle style = mMapView.getMapAutoViewHelper().getMyLocationStyle();
|
||
if (mCarCursorOption.getCarCursorBmp() != null && !mCarCursorOption.getCarCursorBmp().isRecycled()) {
|
||
style.myLocationIcon(mCarCursorOption.getCarCursorBmp());
|
||
} else {
|
||
if (mCarCursorOption.getCarCursorRes() != 0) {
|
||
style.myLocationIcon(mCarCursorOption.getCarCursorRes());
|
||
}
|
||
}
|
||
mMapView.getMapAutoViewHelper().setMyLocationStyle(style);
|
||
}
|
||
|
||
@Override
|
||
public MapCameraPosition getMapCameraPosition() {
|
||
if (checkAMapView()) {
|
||
CameraPosition cameraPosition = mMapView.getMapAutoViewHelper().getCameraPosition();
|
||
return ObjectUtils.fromAMap(cameraPosition);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
@Override
|
||
public void changeBearing(float bearing) {
|
||
if (checkAMapView()) {
|
||
mMapView.getMapAutoViewHelper().setMapViewRotation(bearing);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void changeMapViewAngle(int type) {
|
||
if (checkAMapView()) {
|
||
//mMapView.getMapAutoViewHelper().testMapViewAngle(type);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void changeCurrentIcon(int iconId) {
|
||
if (checkAMapView()) {
|
||
mMapView.getMapAutoViewHelper().getMyLocationStyle().myLocationIcon(iconId, true);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public long getTileId(double lon, double lat) {
|
||
return getMap().getUIController().getTileId(lon, lat);
|
||
}
|
||
|
||
@Override
|
||
public int getSpeedLimmit(double lon, double lat, float angle) {
|
||
return MapDataApi.INSTANCE.getLimitSpeed(lon, lat, angle);
|
||
}
|
||
|
||
@Override
|
||
public void onLocationChanged(@NotNull com.zhidaoauto.map.sdk.open.location.MogoLocation location) {
|
||
MogoLocation mLastLocation = ObjectUtils.fromLocation(location);
|
||
UiThreadHandler.post(() -> CallerMapLocationListenerManager.INSTANCE.invokeMapLocationChangeListener(mLastLocation));
|
||
|
||
Location sysLocation = new Location(location.getProvider());
|
||
sysLocation.setAltitude(location.getAltitude());
|
||
sysLocation.setLatitude(location.getLat());
|
||
sysLocation.setLongitude(location.getLon());
|
||
sysLocation.setProvider(location.getProvider());
|
||
sysLocation.setAccuracy(location.getAcceleration());
|
||
sysLocation.setTime(location.getDuration());
|
||
sysLocation.setBearing((float) location.getHeading());
|
||
sysLocation.setSpeed(location.getSpeed());
|
||
|
||
// 将有效经纬度暂存本地,提供给下一次的Http-DNS使用,防止首次请求位置获取不到
|
||
if (location.getLat() > 0) {
|
||
SharedPrefsMgr.getInstance(mMapView.getContext())
|
||
.putString(SharedPrefsConstants.LOCATION_CITY_CODE, location.getCityCode());
|
||
SharedPrefsMgr.getInstance(mMapView.getContext())
|
||
.putString(SharedPrefsConstants.LOCATION_LATITUDE, String.valueOf(location.getLat()));
|
||
SharedPrefsMgr.getInstance(mMapView.getContext())
|
||
.putString(SharedPrefsConstants.LOCATION_LONGITUDE, String.valueOf(location.getLon()));
|
||
}
|
||
|
||
|
||
if (MogoCarLocationChangedListenerRegister.getInstance().getListener() != null) {
|
||
MogoCarLocationChangedListenerRegister.getInstance().getListener().onCarLocationChanged2(sysLocation);
|
||
}
|
||
if (checkAMapView() && mMapLoaded) {
|
||
// 地图初始化完成后,每隔5s自动判断当前地图的模式
|
||
if (mIsFirstLocated) {
|
||
if (!mIsDelayed) {
|
||
mIsDelayed = true;
|
||
UiThreadHandler.postDelayed(() -> {
|
||
//CallerLogger.INSTANCE.d(TAG, "倒计时结束");
|
||
mIsFirstLocated = false;
|
||
}, 5_000L);
|
||
}
|
||
} else {
|
||
mIsFirstLocated = true;
|
||
mIsDelayed = false;
|
||
CallerLogger.INSTANCE.d(TAG, "同步定位:" + GsonUtils.toJson(location));
|
||
MapStyleController.getInstance().onLocationChanged(location, this);
|
||
}
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onMapClick(@Nullable LonLatPoint lonLatPoint) {
|
||
MogoMapListenerHandler.getInstance().onMapClick(ObjectUtils.fromAMap(lonLatPoint));
|
||
}
|
||
|
||
|
||
@Override
|
||
public void onMapInit() {
|
||
CallerLogger.INSTANCE.i(TAG, "autoop--onMapInit: ");
|
||
MogoMapListenerHandler.getInstance().onMapLoaded();
|
||
}
|
||
|
||
@Override
|
||
public void onMapLoaded() {
|
||
CallerLogger.INSTANCE.i(TAG, "autoop--onMapLoaded: ");
|
||
mMapLoaded = true;
|
||
CameraPosition cameraPosition = mMapView.getMapAutoViewHelper().getCameraPosition();
|
||
Trace.beginSection("timer.onCameraChangeFinish");
|
||
MogoMapListenerHandler.getInstance().onMapChanged(ObjectUtils.fromAMap(cameraPosition.getTarget()),
|
||
cameraPosition.getZoom(),
|
||
cameraPosition.getTilt(),
|
||
cameraPosition.getBearing());
|
||
Trace.endSection();
|
||
initMapView();
|
||
initMyLocation();
|
||
}
|
||
|
||
@Override
|
||
public boolean onTouch(@Nullable MotionEvent motionEvent) {
|
||
MogoMapListenerHandler.getInstance().onTouch(motionEvent);
|
||
return false;
|
||
}
|
||
|
||
@Override
|
||
public void onMarkClick(@NotNull Marker markerInfo) {
|
||
mMarkerClickHandler.handleMarkerClicked(markerInfo);
|
||
}
|
||
|
||
@Override
|
||
public void onRoadLoaded(@Nullable String s) {
|
||
CallerLogger.INSTANCE.i(TAG, "autoop--onMapLoaded: ");
|
||
|
||
}
|
||
|
||
@Override
|
||
public void onMapStatusChanged(int type, int value) {
|
||
//CallerLogger.INSTANCE.i(TAG, "mapop--onMapStatusChanged-: " + type + "," + value);
|
||
}
|
||
|
||
@Override
|
||
public void onMapViewVisualAngleChange(int i) {
|
||
CallerLogger.INSTANCE.d(TAG, " 地图自动更改视距 currentThread : " + Thread.currentThread().getName());
|
||
mVisualAngleMode = getVisualAngleMode(i);
|
||
MogoMapListenerHandler.getInstance().onMapVisualAngleChanged(mVisualAngleMode);
|
||
}
|
||
|
||
private VisualAngleMode getVisualAngleMode(int mode) {
|
||
switch (mode) {
|
||
case 0:
|
||
return MODE_CLOSE_SIGHT;
|
||
case 1:
|
||
return MODE_MEDIUM_SIGHT;
|
||
case 2:
|
||
return MODE_LONG_SIGHT;
|
||
case 3:
|
||
return MAP_STYLE_VR_ANGLE_300;
|
||
case 4:
|
||
return MAP_STYLE_VR_ANGLE_TOP;
|
||
case 5:
|
||
return MAP_STYLE_VR_ANGLE_CROSS;
|
||
default:
|
||
throw new IllegalStateException("mode is unCorrect");
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onCameraChange(int type, int value) {
|
||
//CallerLogger.INSTANCE.i(TAG, "mapop--onCameraChange-: " + type + "," + value);
|
||
}
|
||
|
||
@Override
|
||
public void onCameraChangeFinish(@Nullable CameraPosition cameraPosition) {
|
||
// CallerLogger.INSTANCE.i( TAG, "mapop--onCameraChangeFinish-: " + cameraPosition + "cost:" + ( System.currentTimeMillis() - startTime ) );
|
||
if (cameraPosition != null) {
|
||
Trace.beginSection("timer.onCameraChangeFinish");
|
||
MogoMapListenerHandler.getInstance().onMapChanged(ObjectUtils.fromAMap(cameraPosition.getTarget()),
|
||
cameraPosition.getZoom(),
|
||
cameraPosition.getTilt(),
|
||
cameraPosition.getBearing());
|
||
Trace.endSection();
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void emphasizeMyLocation() {
|
||
|
||
}
|
||
|
||
@Override
|
||
public void onChangeMapStyle(int styleId) {
|
||
|
||
EnumMapUI last = mCurrentUI;
|
||
CallerLogger.INSTANCE.d(TAG, "currentMapStyle = " + styleId);
|
||
|
||
if (styleId == MapAutoApi.MAP_STYLE_DAY
|
||
|| styleId == MapAutoApi.MAP_STYLE_DAY_NAV) {
|
||
mCurrentUI = EnumMapUI.Type_Light;
|
||
} else if (styleId == MapAutoApi.MAP_STYLE_NIGHT
|
||
|| styleId == MapAutoApi.MAP_STYLE_NIGHT_NAV) {
|
||
mCurrentUI = EnumMapUI.Type_Night;
|
||
} else if (styleId == MapAutoApi.MAP_STYLE_VR) {
|
||
mCurrentUI = EnumMapUI.Type_VR;
|
||
// 进入vr模式的时候自动切换到车头朝上
|
||
change2CarUp();
|
||
}
|
||
|
||
if (last == mCurrentUI) {
|
||
CallerLogger.INSTANCE.d(TAG, "currentUI is same as last = " + mCurrentUI);
|
||
return;
|
||
}
|
||
|
||
// vr 模式切换到普通模式下,保持之前的白天模式 wtf.
|
||
if (last == EnumMapUI.Type_VR && mCurrentUI != EnumMapUI.Type_Light) {
|
||
if (mIsLightStyle) {
|
||
changeMapMode(EnumMapUI.Type_Light);
|
||
return;
|
||
}
|
||
}
|
||
CallerLogger.INSTANCE.d(TAG, Log.getStackTraceString(new Throwable()));
|
||
if (mCurrentUI != null) {
|
||
UiThreadHandler.post(() -> {
|
||
try {
|
||
CallerLogger.INSTANCE.d(TAG, "currentUI = " + mCurrentUI);
|
||
MogoMapListenerHandler.getInstance().onMapModeChanged(mCurrentUI);
|
||
CallerMapStyleListenerManager.INSTANCE.invokeMapStyleChange(styleId);
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 切换到车头朝上
|
||
*/
|
||
private void change2CarUp() {
|
||
mMapView.getMapAutoViewHelper().setMapViewPerspective(MapAutoApi.MAP_PERSPECTIVE_UP_CAR);
|
||
}
|
||
|
||
|
||
@Override
|
||
public void onStyleAutoChanged(boolean isVrMode) {
|
||
if (isVrMode) {
|
||
if (mCurrentUI != EnumMapUI.Type_VR) {
|
||
CallerLogger.INSTANCE.d(TAG, "自动切换为vr模式");
|
||
changeMapMode(EnumMapUI.Type_VR);
|
||
}
|
||
} else {
|
||
if (mCurrentUI == EnumMapUI.Type_VR) {
|
||
CallerLogger.INSTANCE.d(TAG, "自动切换为2D模式");
|
||
if (mIsLightStyle) {
|
||
changeMapMode(EnumMapUI.Type_Light);
|
||
} else {
|
||
changeMapMode(EnumMapUI.Type_Night);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private boolean mRtkEnable = false;
|
||
|
||
@Override
|
||
public void rtkEnable(boolean enable) {
|
||
try {
|
||
mRtkEnable = !mRtkEnable;
|
||
TipToast.shortTip(mRtkEnable ? "已开启rtk道路匹配" : "已开启gps道路匹配");
|
||
mMapView.getLocationClient().rtkEnable(mRtkEnable);
|
||
} catch (Exception e) {
|
||
CallerLogger.INSTANCE.e(TAG, "rtkEnable has exception : " + e);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void syncLocation2Map(JSONObject data) {
|
||
if (!checkAMapView()) {
|
||
return;
|
||
}
|
||
if (data == null) {
|
||
CallerLogger.INSTANCE.d(TAG, "停止使用rtk定位数据");
|
||
return;
|
||
}
|
||
double lon = data.optDouble("lon", -1);
|
||
double lat = data.optDouble("lat", -1);
|
||
double alt = data.optDouble("alt", -1);
|
||
double heading = data.optDouble("heading", -1);
|
||
double acceleration = data.optDouble("acceleration", -1);
|
||
double yawRate = data.optDouble("yawRate", -1);
|
||
double speed = data.optDouble("speed", -1);
|
||
long systemTime = data.optLong("systemTime");
|
||
long satelliteTime = data.optLong("satelliteTime");
|
||
|
||
if (lon == -1) {
|
||
return;
|
||
}
|
||
RTKAutopilotLocationBean bean = new RTKAutopilotLocationBean();
|
||
bean.setYaw_rate(yawRate);
|
||
bean.setHeading(heading);
|
||
bean.setAcceleration(acceleration);
|
||
bean.setAlt(alt);
|
||
bean.setSystemTime(systemTime);
|
||
bean.setSatelliteTime(satelliteTime);
|
||
bean.setLon(lon);
|
||
bean.setGnss_speed(((float) speed));
|
||
bean.setLat(lat);
|
||
// 使用外部定位数据修改自车位置
|
||
mMapView.getLocationClient().updateRTKAutoPilotLocation(bean);
|
||
CallerMapUIServiceManager.INSTANCE.getSingletonLocationClient(getContext()).updateLocation(bean);
|
||
CallerMapDataCollectorManager.INSTANCE.setIsInit();
|
||
}
|
||
|
||
@Override
|
||
public void syncLocation2Map(MessagePad.GnssInfo gnssInfo) {
|
||
if (!checkAMapView()) {
|
||
return;
|
||
}
|
||
if (gnssInfo.getLongitude() == -1) {
|
||
return;
|
||
}
|
||
RTKAutopilotLocationBean bean = new RTKAutopilotLocationBean();
|
||
bean.setYaw_rate(gnssInfo.getYawRate());
|
||
bean.setHeading(gnssInfo.getHeading());
|
||
bean.setAcceleration(gnssInfo.getAcceleration());
|
||
bean.setAlt(gnssInfo.getAltitude());
|
||
bean.setSystemTime(Double.valueOf(gnssInfo.getSystemTime()).longValue());
|
||
bean.setSatelliteTime(Double.valueOf(gnssInfo.getSatelliteTime()).longValue());
|
||
bean.setLon(gnssInfo.getLongitude());
|
||
bean.setLat(gnssInfo.getLatitude());
|
||
bean.setGnss_speed(((float) gnssInfo.getGnssSpeed()));
|
||
// 使用外部定位数据修改自车位置
|
||
mMapView.getLocationClient().updateRTKAutoPilotLocation(bean);
|
||
CallerMapUIServiceManager.INSTANCE.getSingletonLocationClient(getContext()).updateLocation(bean);
|
||
CallerMapDataCollectorManager.INSTANCE.setIsInit();
|
||
}
|
||
|
||
@Override
|
||
public void openVrMode(boolean zoomGestureEnable) {
|
||
try {
|
||
mMapView.getMapAutoViewHelper().setZoomGesturesEnabled(zoomGestureEnable);
|
||
mMapView.getMapAutoViewHelper().setMapStyle(MapAutoApi.MAP_STYLE_VR);
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
Map<String, RoadCacheWrapper> roadCacheMap = new ConcurrentHashMap<>();
|
||
private final RoadCacheWrapper noCache = new RoadCacheWrapper(null);
|
||
|
||
@Override
|
||
public void clearRoadCacheById(String id) {
|
||
roadCacheMap.remove(id);
|
||
}
|
||
|
||
@Override
|
||
public double[] matchRoad(String id, double lon, double lat, double angle, boolean isGpsLocation, boolean isRTK) {
|
||
return matchRoad(id, lon, lat, angle, isGpsLocation, isRTK, true);
|
||
}
|
||
|
||
/**
|
||
* 带缓存的道路匹配算法
|
||
* <p>
|
||
* 使用{@link MapDataApi#INSTANCE#getSinglePointMatchRoad()}这个方法获取道路数据会存在一定耗时,目前是4-10ms,因为请求频繁,为了
|
||
* 减小这部分耗时,使用一个ConcurrentHashMap{@link #roadCacheMap}缓存道路数据,此缓存是以目标车id为key,道路数据为value,以此减少
|
||
* 道路数据获取次数。
|
||
* <p>
|
||
* 当出现道路改变的情况,需要重新获取道路数据,采用递归的方式重获道路数据以及添加缓存,为了避免一直获取不到道路数据,一直递归,增加useCache参数跳出递归。
|
||
* <p>
|
||
* 道路改变的情况主要分为:
|
||
* 1. 目标车距离道路中心线距离超过阈值 matchThreshold(取路宽的1/4为阈值);
|
||
* 2. 目标车到道路中心线的映射点不在道路上(此判断在{@link PointInterpolatorUtil#mergeToRoad(double, double, List)}),也就是说已经驶出了这条道路
|
||
*
|
||
* @param id 目标车唯一标识
|
||
* @param lon 目标车经度
|
||
* @param lat 目标车纬度
|
||
* @param angle 目标车角度
|
||
* @param isGpsLocation true-使用gps定位数据
|
||
* @param isRTK true-使用rtk数据
|
||
* @param usdCache true-使用道路缓存 false-不使用道路缓存
|
||
* @return double[]{匹配后经度,匹配后纬度,目标车距离车道中心线距离},若匹配后经纬度值为-1,则没有匹配成功
|
||
*/
|
||
private double[] matchRoad(String id, double lon, double lat, double angle, boolean isGpsLocation, boolean isRTK, boolean usdCache) {
|
||
double[] wgs = new double[]{lon, lat};
|
||
long start = System.currentTimeMillis();
|
||
|
||
RoadCacheWrapper roadCache = roadCacheMap.get(id);
|
||
double matchThreshold = -1;
|
||
if (roadCache == null || roadCache == noCache) {
|
||
SinglePointRoadInfo singlePointRoadInfo = MapDataApi.INSTANCE.getSinglePointMatchRoad(((float) wgs[0]), ((float) wgs[1]), ((float) angle), isGpsLocation, isRTK);
|
||
if (singlePointRoadInfo != null && singlePointRoadInfo.getCoords() != null && !singlePointRoadInfo.getCoords().isEmpty()) {
|
||
roadCache = new RoadCacheWrapper(singlePointRoadInfo.getCoords());
|
||
roadCache.setLaneWidth(singlePointRoadInfo.getLaneWidth());
|
||
}
|
||
}
|
||
|
||
if (roadCache != null
|
||
&& roadCache.getRoad() != null
|
||
&& !roadCache.getRoad().isEmpty()) {
|
||
// 未获取到道路中心线数据
|
||
start = System.currentTimeMillis();
|
||
matchThreshold = roadCache.getLaneWidth() / 4;
|
||
|
||
double[] matchedPoint = PointInterpolatorUtil.mergeToRoad(wgs[0], wgs[1], roadCache.getRoad());
|
||
if (matchThreshold > 0 && matchedPoint[2] > 0 && matchedPoint[2] <= matchThreshold) {
|
||
// 目标车在阈值范围内
|
||
roadCacheMap.put(id, roadCache);
|
||
// CallerLogger.INSTANCE.i("timer-matchRoad-3", "cost " + (System.currentTimeMillis() - start) + "ms");
|
||
return matchedPoint;
|
||
// CallerLogger.INSTANCE.i("timer-matchRoad-2", "cost " + (System.currentTimeMillis() - start) + "ms roadId: "+roadCache.getLastLat());
|
||
} else if (matchedPoint[2] > matchThreshold && matchedPoint[2] < 1.5) {
|
||
// 目标车在阈值范围外,也就是说距离道路中心线太远了,就不吸附了
|
||
return null;
|
||
} else {
|
||
// 目标车到道路中心线的映射点不在道路上,也就是已经使出了缓存的那条道路,需要重新获取一条道路,用useCache这个参数来避免重复递归
|
||
roadCacheMap.put(id, noCache);
|
||
// CallerLogger.INSTANCE.i("timer-matchRoad-2", "cost " + (System.currentTimeMillis() - start) + "ms roadId: " + roadCache.getLastLat());
|
||
if (usdCache) {
|
||
return matchRoad(id, lon, lat, angle, isGpsLocation, isRTK, false);
|
||
} else {
|
||
return null;
|
||
}
|
||
}
|
||
}
|
||
roadCacheMap.put(id, noCache);
|
||
return null;
|
||
}
|
||
|
||
@Override
|
||
public String getMarkerInfoResName(String speedVal) {
|
||
return ResIdCache.getVal(speedVal);
|
||
}
|
||
|
||
@Override
|
||
public void setMarkerInfoResName(String speedVal, String val) {
|
||
ResIdCache.putVal(speedVal, val);
|
||
}
|
||
|
||
@Override
|
||
public void setMapDAngle(float angle) {
|
||
mMapView.getMapAutoViewHelper().setMapDAngle(angle);
|
||
}
|
||
|
||
}
|