优化显示逻辑

This commit is contained in:
wangcongtao
2021-03-22 15:10:55 +08:00
parent b7547a34aa
commit dca685532a
13 changed files with 395 additions and 712 deletions

View File

@@ -1,28 +1,23 @@
package com.mogo.module.common.drawer;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.map.MogoLatLng;
import com.mogo.map.marker.IMogoMarker;
import com.mogo.map.marker.MogoMarkerOptions;
import com.mogo.module.common.MogoApisHandler;
import com.mogo.module.common.R;
import com.mogo.module.common.constants.DataTypes;
import com.mogo.module.common.utils.SimpleHandlerThreadPool;
import com.mogo.realtime.entity.ADASRecognizedResult;
import com.mogo.realtime.entity.CloudRoadData;
import com.mogo.utils.WorkThreadHandler;
import com.mogo.utils.logger.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
public
@@ -38,81 +33,8 @@ class AdasRecognizedResultDrawer extends BaseDrawer {
private static volatile AdasRecognizedResultDrawer sInstance;
private final Context mContext;
private Handler mRenderThreadHandler = null;
public static final int MSG_MOVE_POINTS = 9;
public static final int MSG_MOVE_POINT = 10;
public static final int MSG_DISPLAY_SPEED = 11;
public AdasRecognizedResultDrawer() {
super();
mContext = AbsMogoApplication.getApp();
initHandler();
}
/**
* 初始化清理marker的线程
*/
private void initHandler() {
mRenderThreadHandler = new Handler( WorkThreadHandler.newInstance( "render-thread-" + new Random().nextLong() ).getLooper() ) {
@Override
public void handleMessage( Message msg ) {
super.handleMessage( msg );
if ( msg.what == MSG_MOVE_POINTS ) {
if ( msg.obj instanceof MovingPoints ) {
startSettingPointLooper( ( ( MovingPoints ) msg.obj ) );
}
} else if ( msg.what == MSG_MOVE_POINT ) {
if ( msg.obj instanceof MovingPoint ) {
moveMarker( ( ( MovingPoint ) msg.obj ), msg.arg1 );
}
} else if ( msg.what == MSG_DISPLAY_SPEED ) {
if ( msg.obj instanceof SpeedData ) {
showSpeed( ( SpeedData ) msg.obj );
}
}
}
};
}
/**
* 开启设置位置的循环
*
* @param data
*/
private void startSettingPointLooper( MovingPoints data ) {
List< MovingPoint > points = data.points;
for ( int i = 0; i < points.size(); i++ ) {
Message msg = Message.obtain();
msg.what = MSG_MOVE_POINT;
msg.obj = points.get( i );
if ( i == 0 || i == points.size() - 1 ) {
msg.arg1 = R.drawable.sr;
} else {
msg.arg1 = R.drawable.sy;
}
mRenderThreadHandler.sendMessageDelayed( msg, points.get( i ).delay );
}
}
/**
* 设置 marker 的点到新的位置
*
* @param pointData
*/
private void moveMarker( MovingPoint pointData, int drId ) {
if ( pointData == null ) {
return;
}
pointData.move();
}
private void showSpeed( SpeedData data ) {
if ( data == null ) {
return;
}
data.showSpeed();
}
private final Map< String, ADASRecognizedResult > mLastPositions = new ConcurrentHashMap<>();
@@ -147,7 +69,7 @@ class AdasRecognizedResultDrawer extends BaseDrawer {
* @param resultList
*/
public void renderAdasRecognizedResult( List< ADASRecognizedResult > resultList ) {
if ( resultList == null || resultList.isEmpty() || !DebugConfig.isUseAdasRecognize()) {
if ( resultList == null || resultList.isEmpty() || !DebugConfig.isUseAdasRecognize() ) {
clearOldMarker();
return;
}
@@ -158,32 +80,109 @@ class AdasRecognizedResultDrawer extends BaseDrawer {
}
Map< String, IMogoMarker > newAdasRecognizedMarkersCaches = new HashMap<>();
List< ADASRecognizedResult > newDiffSet = new ArrayList<>();
for ( ADASRecognizedResult recognizedListResult : resultList ) {
if ( recognizedListResult == null ) {
if ( isUselessValue( recognizedListResult ) ) {
continue;
}
renderAdasOneFrame( recognizedListResult, newAdasRecognizedMarkersCaches );
// 复用之前存在的 marker
String uniqueKey = recognizedListResult.uuid;
IMogoMarker marker = mMarkersCaches.remove( uniqueKey );
if ( marker != null && !marker.isDestroyed() ) {
renderAdasOneFrame( marker, uniqueKey, recognizedListResult, newAdasRecognizedMarkersCaches );
} else {
// 新增差集
newDiffSet.add( recognizedListResult );
}
}
removeUselessMarker();
// 能复用的 marker 数量
int cachedMarkerSize = mMarkersCaches.size();
// 需要新增的 marker 数量
int newDiffSetSize = newDiffSet.size();
// 能复用的数量
int size = cachedMarkerSize >= newDiffSetSize ? newDiffSetSize : cachedMarkerSize;
// 复用过期 marker
if ( newDiffSetSize > 0 ) {
Iterator< Map.Entry< String, IMogoMarker > > entryIterator = mMarkersCaches.entrySet().iterator();
for ( int i = 0; i < size; i++ ) {
ADASRecognizedResult recognizedListResult = newDiffSet.get( i );
String uniqueKey = recognizedListResult.uuid;
Map.Entry< String, IMogoMarker > entry = entryIterator.next();
entryIterator.remove();
ADASRecognizedResult old = mLastPositions.remove( entry.getKey() );
IMogoMarker marker = entry.getValue();
if ( marker == null ) {
continue;
}
// 更新资源内容
if ( old == null || old.type != recognizedListResult.type ) {
String resIdVal = null;
int resId = getModelRes( recognizedListResult.type );
resIdVal = resId + "";
String resName = mMarkerCachesResMd5Values.get( resIdVal );
if ( !TextUtils.isEmpty( resName ) ) {
if ( !TextUtils.equals( resName, marker.getMarkerResName() ) ) {
marker.use3DResource( resName );
}
} else {
resName = marker.use3DResource( resId );
mMarkerCachesResMd5Values.put( resIdVal, resName );
}
}
renderAdasOneFrame( marker, uniqueKey, recognizedListResult, newAdasRecognizedMarkersCaches );
}
// 复用过后还需新增的 marker
for ( int i = size; i < newDiffSetSize; i++ ) {
ADASRecognizedResult recognizedListResult = newDiffSet.get( i );
String uniqueKey = recognizedListResult.uuid;
IMogoMarker marker = drawAdasRecognizedDataMarker( recognizedListResult );
if ( marker == null ) {
continue;
}
renderAdasOneFrame( marker, uniqueKey, recognizedListResult, newAdasRecognizedMarkersCaches );
}
}
if ( cachedMarkerSize - size > 0 ) {
sendMessage( MSG_REMOVE_DIRTY_MARKERS, mMarkersCaches );
}
sendMessage( MSG_REMOVE_DIRTY_MARKERS, mMarkersCaches );
mMarkersCaches = newAdasRecognizedMarkersCaches;
}
private boolean isUselessValue( ADASRecognizedResult recognizedListResult ) {
if ( recognizedListResult == null ) {
return true;
}
if ( !isRenderType( recognizedListResult.type ) ) {
return true;
}
String uniqueKey = recognizedListResult.uuid;
if ( TextUtils.isEmpty( uniqueKey ) ) {
return true;
}
return false;
}
/**
* 绘制某个物体的一个数据
*
* @param recognizedListResult
* @param newAdasRecognizedMarkersCaches
*/
private void renderAdasOneFrame( ADASRecognizedResult recognizedListResult, Map< String, IMogoMarker > newAdasRecognizedMarkersCaches ) {
// 暂时只显示车辆
if ( !isRenderType( recognizedListResult.type ) ) {
return;
}
String uniqueKey = recognizedListResult.uuid;
if ( TextUtils.isEmpty( uniqueKey ) ) {
return;
}
private void renderAdasOneFrame( IMogoMarker marker,
String uniqueKey,
ADASRecognizedResult recognizedListResult,
Map< String, IMogoMarker > newAdasRecognizedMarkersCaches ) {
final long start = System.currentTimeMillis();
@@ -201,41 +200,32 @@ class AdasRecognizedResultDrawer extends BaseDrawer {
mLastPositions.put( uniqueKey, recognizedListResult );
Logger.d( "matchRoad", "cost = %s", System.currentTimeMillis() - start );
IMogoMarker marker = mMarkersCaches.remove( uniqueKey );
if ( marker == null || marker.isDestroyed() ) {
marker = drawAdasRecognizedDataMarker( recognizedListResult );
if ( marker == null ) {
return;
}
}
newAdasRecognizedMarkersCaches.put( uniqueKey, marker );
if ( lastPosition != null ) {
long interval = computeAnimDuration( lastPosition.systemTime, recognizedListResult.systemTime, lastPosition.satelliteTime, recognizedListResult.satelliteTime );
final IMogoMarker renderRef = marker;
final MogoLatLng renderLoc = new MogoLatLng( recognizedListResult.lat, recognizedListResult.lon );
long cost = System.currentTimeMillis() - start;
final long intervalRef = interval - cost;
SimpleHandlerThreadPool.getInstance().postRender( () -> {
renderRef.addDynamicAnchorPosition( renderLoc, ( float ) recognizedListResult.heading, intervalRef );
marker.addDynamicAnchorPosition( renderLoc, ( float ) recognizedListResult.heading, intervalRef );
} );
marker.setAnchorColor( getModelRenderColor(recognizedListResult.speed, recognizedListResult.lon, recognizedListResult.lat, recognizedListResult.heading) );
} else {
marker.setRotateAngle( ( ( float ) recognizedListResult.heading ) );
marker.setPosition( recognizedListResult.lat, recognizedListResult.lon );
}
marker.setAnchorColor( getModelRenderColor( recognizedListResult.speed, recognizedListResult.lon, recognizedListResult.lat, recognizedListResult.heading ) );
if ( shouldShowSpeed( recognizedListResult.type ) ) {
Message msg = new Message();
Message msg = mRenderThreadHandler.obtainMessage();
SpeedData obj = new SpeedData();
obj.context = mContext;
obj.marker = marker;
obj.speed = recognizedListResult.speed;
msg.obj = obj;
msg.what = MSG_DISPLAY_SPEED;
mRenderThreadHandler.sendMessage( msg );
msg.sendToTarget();
}
}
@@ -258,8 +248,7 @@ class AdasRecognizedResultDrawer extends BaseDrawer {
.anchor( 0.5f, 0.5f )
.set3DMode( true )
.gps( true )
// .anchorColor( getModelRenderColor( CloudRoadData.FROM_ADAS, recognizedListResult.type ) )
.anchorColor( getModelRenderColor(recognizedListResult.speed, recognizedListResult.lon, recognizedListResult.lat, recognizedListResult.heading) )
.anchorColor( getModelRenderColor( recognizedListResult.speed, recognizedListResult.lon, recognizedListResult.lat, recognizedListResult.heading ) )
.controlAngle( true )
.resName( mMarkerCachesResMd5Values.get( resIdVal ) )
.icon3DRes( resId )

View File

@@ -26,8 +26,10 @@ import com.mogo.utils.logger.Logger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import static java.lang.Math.PI;
@@ -41,33 +43,6 @@ public
*/
class BaseDrawer {
/**
* marker 单个点移动的对象
*/
public static class MovingPoint {
public MogoLatLng point;
public float angle;
public IMogoMarker marker;
public long delay;
public void move() {
try {
marker.setRotateAngle( angle );
marker.setPosition( point.lat, point.lon );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}
/**
* marker 平滑移动的对象
*/
public static class MovingPoints {
public List< MovingPoint > points;
}
/**
* 速度显示对象
*/
@@ -93,6 +68,11 @@ class BaseDrawer {
public static final int MSG_REMOVE_DIRTY_MARKERS = 9990;
public static final int MSG_REMOVE_ADAS_MARKERS = 9992;
/**
* 显示速度
*/
public static final int MSG_DISPLAY_SPEED = 11;
/**
* 地图刷新频率
*/
@@ -113,43 +93,86 @@ class BaseDrawer {
*/
protected Map< String, IMogoMarker > mMarkersCaches = new HashMap<>();
protected final Context mContext;
protected static Handler mRenderThreadHandler = null;
public BaseDrawer() {
if ( mWorkThreadHandler == null ) {
initWorkThreadHandler();
}
init();
mContext = AbsMogoApplication.getApp();
initWorkThreadHandler();
}
private static Handler mWorkThreadHandler;
/**
* 专门处理 adas 数据的线程
* 处理 marker 移除的线程
*/
private static void initWorkThreadHandler() {
if ( mWorkThreadHandler != null ) {
return;
}
mWorkThreadHandler = new Handler( WorkThreadHandler.newInstance( "3d-marker-work-thread" ).getLooper() ) {
@Override
public void handleMessage( Message msg ) {
super.handleMessage( msg );
if ( msg.what == MSG_REMOVE_DIRTY_MARKERS ) {
if ( msg.obj instanceof Map ) {
removeDirtyMarkers( ( ( Map ) msg.obj ) );
Set< String > key = ( ( Map ) msg.obj ).keySet();
for ( String id : key ) {
// 清除道路缓存
clearRoadCacheById( id );
if ( mWorkThreadHandler == null ) {
mWorkThreadHandler = new Handler( WorkThreadHandler.newInstance( "3d-marker-work-thread" ).getLooper() ) {
@Override
public void handleMessage( Message msg ) {
super.handleMessage( msg );
if ( msg.what == MSG_REMOVE_DIRTY_MARKERS ) {
if ( msg.obj instanceof Map ) {
removeDirtyMarkers( ( ( Map ) msg.obj ) );
Set< String > key = ( ( Map ) msg.obj ).keySet();
for ( String id : key ) {
// 清除道路缓存
clearRoadCacheById( id );
}
} else if ( msg.obj instanceof String ) {
MogoApisHandler.getInstance().getApis()
.getMapServiceApi()
.getMarkerManager( AbsMogoApplication.getApp() )
.removeMarkers( ( ( String ) msg.obj ) );
}
} else if ( msg.obj instanceof String ) {
MogoApisHandler.getInstance().getApis()
.getMapServiceApi()
.getMarkerManager( AbsMogoApplication.getApp() )
.removeMarkers( ( ( String ) msg.obj ) );
}
}
};
}
if ( mRenderThreadHandler == null ) {
mRenderThreadHandler = new Handler( WorkThreadHandler.newInstance( "render-thread-" + new Random().nextLong() ).getLooper() ) {
@Override
public void handleMessage( Message msg ) {
super.handleMessage( msg );
if ( msg.what == MSG_DISPLAY_SPEED ) {
if ( msg.obj instanceof SpeedData ) {
showSpeed( ( SpeedData ) msg.obj );
}
}
}
};
}
}
/**
* 显示速度
*
* @param data
*/
private static void showSpeed( SpeedData data ) {
if ( data == null ) {
return;
}
data.showSpeed();
}
/**
* 清除无效[为 null 或者 已被销毁]的 marker
*/
protected void removeUselessMarker() {
if ( mMarkersCaches == null || mMarkersCaches.isEmpty() ) {
return;
}
Iterator< IMogoMarker > iterator = mMarkersCaches.values().iterator();
while ( iterator.hasNext() ) {
IMogoMarker marker = iterator.next();
if ( marker == null || marker.isDestroyed() ) {
iterator.remove();
}
};
}
}
/**
@@ -159,9 +182,6 @@ class BaseDrawer {
* @param data
*/
public void sendMessage( int msg, Object data ) {
if ( mWorkThreadHandler == null ) {
initWorkThreadHandler();
}
Message message = Message.obtain();
message.what = msg;
message.obj = data;
@@ -222,37 +242,6 @@ class BaseDrawer {
return R.raw.people;
}
private void init() {
}
/**
* @param fromType {@link com.mogo.realtime.entity.CloudRoadData}
* @return
*/
protected String getModelRenderColor( int fromType, int modelType ) {
AdasRecognizedType recognizedType = AdasRecognizedType.valueFrom( modelType );
if ( recognizedType == AdasRecognizedType.classIdCar
|| recognizedType == AdasRecognizedType.classIdTrafficBus
|| recognizedType == AdasRecognizedType.classIdTrafficTruck ) {
if ( fromType == CloudRoadData.FROM_ADAS ) {
// 灰色
return "#5A8DFFFF";
} else if ( fromType == CloudRoadData.FROM_ROAD_UNIT ) {
// 绿色
return "#3FE792FF";
} else {
// 蓝色
return "#5A8DFFFF";
}
} else if ( recognizedType == AdasRecognizedType.classIdBicycle
|| recognizedType == AdasRecognizedType.classIdMoto ) {
// 灰色
return "#D8D8D8FF";
}
// 灰色
return "#D8D8D8FF";
}
/**
* 根据速度、经纬度计算距离判断车辆颜色
*
@@ -361,6 +350,7 @@ class BaseDrawer {
}
String speedVal = speedIntVal + "";
String infoResName = MogoApisHandler.getInstance().getApis().getMapServiceApi().getMapUIController().getMarkerInfoResName( speedVal );
mogoMarker.setInfoWindowOffset( 0, 20 );
if ( TextUtils.isEmpty( infoResName ) ) {
if ( mSpeedView == null ) {
mSpeedView = new TextView( context );
@@ -369,7 +359,6 @@ class BaseDrawer {
mSpeedView.setLayoutParams( new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT ) );
}
mSpeedView.setText( speedVal );
mogoMarker.setInfoWindowOffset( 0, 20 );
mogoMarker.updateInfoWindowView( mSpeedView );
MogoApisHandler.getInstance().getApis().getMapServiceApi().getMapUIController().setMarkerInfoResName( speedVal, mogoMarker.getMarkerInfoResName() );
} else {
@@ -465,45 +454,6 @@ class BaseDrawer {
return interval;
}
/**
* 在两点之间插值
*
* @param start
* @param end
* @return
*/
public static List< MovingPoint > interpolate( MovingPoint start, MovingPoint end, long duration ) {
if ( start == null || end == null ) {
return null;
}
int interpolateFrame = ( int ) ( duration / MAP_RENDER_FRAME_FREQUENCY );
if ( duration % MAP_RENDER_FRAME_FREQUENCY < MAP_RENDER_FRAME_FREQUENCY / 2 ) {
interpolateFrame -= 1;
}
List< MovingPoint > arrayList = new ArrayList<>();
double _angle = ( end.angle + start.angle ) / 2;
if ( Math.abs( end.angle - start.angle ) > 5 ) {
_angle = Math.atan2( Math.abs( start.point.lon - end.point.lon ), Math.abs( start.point.lat - end.point.lat ) ) * ( 180 / PI );
}
if ( interpolateFrame > 0 ) {
double lonStep = ( end.point.lon - start.point.lon ) / ( interpolateFrame + 1 );
double latStep = ( end.point.lat - start.point.lat ) / ( interpolateFrame + 1 );
for ( int i = 0; i < interpolateFrame; i++ ) {
double lon = start.point.lon + lonStep * ( i + 1 );
double lat = start.point.lat + latStep * ( i + 1 );
MovingPoint pd = new MovingPoint();
pd.point = new MogoLatLng( lat, lon );
pd.delay = ( i + i ) * MAP_MARKER_MOVE_INTERVAL;
pd.angle = ( float ) _angle;
pd.marker = start.marker;
arrayList.add( pd );
}
}
arrayList.add( end );
return arrayList;
}
/**
* 根据位置信息、车头朝向计算道路吸附
*

View File

@@ -2,6 +2,7 @@ package com.mogo.module.common.drawer;
import android.text.TextUtils;
import com.mogo.cloud.commons.utils.CoordinateUtils;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.map.MogoLatLng;
import com.mogo.map.marker.IMogoMarker;
@@ -239,35 +240,6 @@ class MarkerDrawer {
* @return 两坐标的距离 单位M
*/
public static float calculateLineDistance( double lon1, double lat1, double lon2, double lat2 ) {
try {
double var2 = lon1;
double var4 = lat1;
double var6 = lon2;
double var8 = lat2;
var2 *= 0.01745329251994329D;
var4 *= 0.01745329251994329D;
var6 *= 0.01745329251994329D;
var8 *= 0.01745329251994329D;
double var10 = Math.sin( var2 );
double var12 = Math.sin( var4 );
double var14 = Math.cos( var2 );
double var16 = Math.cos( var4 );
double var18 = Math.sin( var6 );
double var20 = Math.sin( var8 );
double var22 = Math.cos( var6 );
double var24 = Math.cos( var8 );
double[] var28 = new double[3];
double[] var29 = new double[3];
var28[0] = var16 * var14;
var28[1] = var16 * var10;
var28[2] = var12;
var29[0] = var24 * var22;
var29[1] = var24 * var18;
var29[2] = var20;
return ( float ) ( Math.asin( Math.sqrt( ( var28[0] - var29[0] ) * ( var28[0] - var29[0] ) + ( var28[1] - var29[1] ) * ( var28[1] - var29[1] ) + ( var28[2] - var29[2] ) * ( var28[2] - var29[2] ) ) / 2.0D ) * 1.27420015798544E7D );
} catch ( Throwable var26 ) {
var26.printStackTrace();
return 0.0F;
}
return CoordinateUtils.calculateLineDistance( lon1, lat1, lon2, lat2 );
}
}

View File

@@ -1,8 +1,7 @@
package com.mogo.module.common.drawer;
import android.content.Context;
import android.os.Message;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
@@ -28,6 +27,7 @@ import com.zhidao.carchattingprovider.MogoDriverInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -44,12 +44,10 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
private static volatile SnapshotSetDataDrawer sInstance;
private Context mContext;
private boolean mChangeCarModeStatus;
private SnapshotSetDataDrawer() {
super();
mContext = AbsMogoApplication.getApp();
MogoApisHandler.getInstance().getApis()
.getStatusManagerApi()
.registerStatusChangedListener( TAG, StatusDescriptor.VR_MODE, this );
@@ -75,9 +73,6 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
return sInstance;
}
// 云端 marker 缓存
private Map< String, IMogoMarker > mCloudSnapshotMarkersCaches = new ConcurrentHashMap<>();
private final Map< String, CloudRoadData > mLastPositions = new ConcurrentHashMap<>();
private boolean mIsVrMode = false;
@@ -86,8 +81,8 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
public void onStatusChanged( StatusDescriptor descriptor, boolean isTrue ) {
Logger.d( TAG, "%s - %s", descriptor, isTrue );
mChangeCarModeStatus = true;
sendMessage( MSG_REMOVE_ADAS_MARKERS, mCloudSnapshotMarkersCaches );
mCloudSnapshotMarkersCaches = new ConcurrentHashMap<>();
sendMessage( MSG_REMOVE_ADAS_MARKERS, mMarkersCaches );
mMarkersCaches = new HashMap<>();
if ( mLastPositions != null ) {
mLastPositions.clear();
}
@@ -114,11 +109,11 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
*/
private boolean clear( MogoSnapshotSetData data ) {
if ( !MogoApisHandler.getInstance().getApis().getStatusManagerApi().isMainPageLaunched() ) {
if ( mCloudSnapshotMarkersCaches == null ) {
if ( mMarkersCaches == null ) {
return false;
}
if ( mCloudSnapshotMarkersCaches != null ) {
mCloudSnapshotMarkersCaches.clear();
if ( mMarkersCaches != null ) {
mMarkersCaches.clear();
}
if ( mLastPositions != null ) {
mLastPositions.clear();
@@ -129,8 +124,8 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
if ( data == null || (
( data.getAllList() == null || data.getAllList().isEmpty() ) &&
( data.getNearList() == null || data.getNearList().isEmpty() ) ) ) {
if ( mCloudSnapshotMarkersCaches != null ) {
mCloudSnapshotMarkersCaches.clear();
if ( mMarkersCaches != null ) {
mMarkersCaches.clear();
}
if ( mLastPositions != null ) {
mLastPositions.clear();
@@ -141,8 +136,6 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
return false;
}
Map<String,String> cloudKeyCache = new ArrayMap<>();
/**
* mogo 他车、mogo 他车识别的社会车辆、路边单元识别的车辆
*
@@ -156,79 +149,158 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
List< CloudRoadData > allDatumsList = new ArrayList<>();
prepareData( data.getAllList(), allDatumsList );
Map< String, IMogoMarker > newMarkersCaches = new ArrayMap<>( allDatumsList.size() );
Map< String, IMogoMarker > newMarkersCaches = new HashMap<>( allDatumsList.size() );
List< CloudRoadData > newDiffSet = new ArrayList<>();
for ( CloudRoadData cloudRoadData : allDatumsList ) {
renderSnapshotOneFrame(cloudRoadData,newMarkersCaches);
if ( isUselessValue( cloudRoadData ) ) {
continue;
}
String uniqueKey = cloudRoadData.getUniqueKey();
IMogoMarker marker = mMarkersCaches.remove( uniqueKey );
if ( marker != null && !marker.isDestroyed() ) {
renderSnapshotOneFrame( marker, uniqueKey, cloudRoadData, newMarkersCaches );
} else {
newDiffSet.add( cloudRoadData );
}
}
sendMessage(MSG_REMOVE_DIRTY_MARKERS, mMarkersCaches );
removeUselessMarker();
// 能复用的 marker 数量
int cachedMarkerSize = mMarkersCaches.size();
// 需要新增的 marker 数量
int newDiffSetSize = newDiffSet.size();
// 能复用的数量
int size = cachedMarkerSize >= newDiffSetSize ? newDiffSetSize : cachedMarkerSize;
// 复用过期 marker
if ( newDiffSetSize > 0 ) {
Iterator< Map.Entry< String, IMogoMarker > > entryIterator = mMarkersCaches.entrySet().iterator();
for ( int i = 0; i < size; i++ ) {
CloudRoadData cloudRoadData = newDiffSet.get( i );
String uniqueKey = cloudRoadData.getUniqueKey();
Map.Entry< String, IMogoMarker > entry = entryIterator.next();
entryIterator.remove();
CloudRoadData old = mLastPositions.remove( entry.getKey() );
IMogoMarker marker = entry.getValue();
if ( marker == null ) {
continue;
}
// 更新资源内容
if ( old == null || old.getType() != cloudRoadData.getType() ) {
String resIdVal = null;
int resId = getModelRes( cloudRoadData.getType() );
resIdVal = resId + "";
String resName = mMarkerCachesResMd5Values.get( resIdVal );
if ( !TextUtils.isEmpty( resName ) ) {
if ( !TextUtils.equals( resName, marker.getMarkerResName() ) ) {
marker.use3DResource( resName );
}
} else {
resName = marker.use3DResource( resId );
mMarkerCachesResMd5Values.put( resIdVal, resName );
}
}
renderSnapshotOneFrame( marker, uniqueKey, cloudRoadData, newMarkersCaches );
}
// 复用过后还需新增的 marker
for ( int i = size; i < newDiffSetSize; i++ ) {
CloudRoadData cloudRoadData = newDiffSet.get( i );
String uniqueKey = cloudRoadData.getUniqueKey();
IMogoMarker marker = drawSnapshotDataMarker( cloudRoadData );
if ( marker == null ) {
continue;
}
renderSnapshotOneFrame( marker, uniqueKey, cloudRoadData, newMarkersCaches );
}
}
if ( cachedMarkerSize - size > 0 ) {
sendMessage( MSG_REMOVE_DIRTY_MARKERS, mMarkersCaches );
}
sendMessage( MSG_REMOVE_DIRTY_MARKERS, mMarkersCaches );
mMarkersCaches = newMarkersCaches;
}
/**
* 判断类型、uuid 等
*
* @param cloudRoadData
* @return
*/
private boolean isUselessValue( CloudRoadData cloudRoadData ) {
if ( cloudRoadData == null ) {
return true;
}
if ( !isRenderType( cloudRoadData.getType() ) ) {
return true;
}
String uniqueKey = cloudRoadData.getUniqueKey();
if ( TextUtils.isEmpty( uniqueKey ) ) {
return true;
}
return false;
}
/**
* 绘制某个物体的一个数据
*
* @param cloudRoadData
* @param newAdasRecognizedMarkersCaches
* @param newSnapshotCaches
*/
private void renderSnapshotOneFrame(final CloudRoadData cloudRoadData, Map< String, IMogoMarker > newAdasRecognizedMarkersCaches ) {
// 暂时只显示车辆
if ( !isRenderType( cloudRoadData.getType() ) ) {
return;
}
String uniqueKey = cloudRoadData.getUniqueKey();
if ( TextUtils.isEmpty( uniqueKey ) ) {
return;
}
private void renderSnapshotOneFrame( IMogoMarker marker, String uniqueKey, final CloudRoadData cloudRoadData, Map< String, IMogoMarker > newSnapshotCaches ) {
final long start = System.currentTimeMillis();
IMogoMarker marker = mMarkersCaches.remove( uniqueKey );
CloudRoadData lastPosition = mLastPositions.put( uniqueKey, cloudRoadData );
CloudRoadData lastPosition = mLastPositions.remove( uniqueKey );
double lastLon = -1;
double lastLat = -1;
if (lastPosition != null) {
if ( lastPosition != null ) {
lastLon = lastPosition.getWgslon();
lastLat = lastPosition.getWgslat();
}
double[] matchLonLat = getMatchLonLat(cloudRoadData.getUniqueKey(), cloudRoadData.getWgslon(), cloudRoadData.getWgslat(), cloudRoadData.getHeading(), lastLon, lastLat);
cloudRoadData.setWgslon(matchLonLat[0]);
cloudRoadData.setWgslat(matchLonLat[1]);
double[] matchLonLat = getMatchLonLat( cloudRoadData.getUniqueKey(), cloudRoadData.getWgslon(), cloudRoadData.getWgslat(), cloudRoadData.getHeading(), lastLon, lastLat );
cloudRoadData.setWgslon( matchLonLat[0] );
cloudRoadData.setWgslat( matchLonLat[1] );
if ( marker == null || marker.isDestroyed() ) {
marker = drawSnapshotDataMarker( cloudRoadData );
if ( marker == null ) {
return;
}
}
newAdasRecognizedMarkersCaches.put( uniqueKey, marker );
mLastPositions.put( uniqueKey, cloudRoadData );
newSnapshotCaches.put( uniqueKey, marker );
if ( lastPosition != null ) {
long interval = computeAnimDuration( lastPosition.getSystemTime(), cloudRoadData.getSystemTime(), lastPosition.getSatelliteTime(), cloudRoadData.getSatelliteTime() );
// method 1
final IMogoMarker renderRef = marker;
final MogoLatLng point = new MogoLatLng( cloudRoadData.getWgslat(), cloudRoadData.getWgslon() );
final MogoLatLng point = new MogoLatLng( cloudRoadData.getWgslat(), cloudRoadData.getWgslon() );
long cost = System.currentTimeMillis() - start;
final long intervalRef = interval - cost;
SimpleHandlerThreadPool.getInstance().postRender( () -> {
renderRef.addDynamicAnchorPosition( point, (float)cloudRoadData.getHeading(), intervalRef );
marker.addDynamicAnchorPosition( point, ( float ) cloudRoadData.getHeading(), intervalRef );
} );
// marker.setAnchorColor( getModelRenderColor(cloudRoadData.getSpeed(), cloudRoadData.getWgslon(), cloudRoadData.getWgslat(), cloudRoadData.getHeading()) );
} else {
marker.setRotateAngle( ( ( float ) cloudRoadData.getHeading() ) );
marker.setPosition( cloudRoadData.getWgslat(), cloudRoadData.getWgslon() );
}
marker.setAnchorColor( getModelRenderColor( cloudRoadData.getSpeed(), cloudRoadData.getWgslon(), cloudRoadData.getWgslat(), cloudRoadData.getHeading() ) );
if ( shouldShowSpeed( cloudRoadData.getType() ) ) {
Message msg = mRenderThreadHandler.obtainMessage();
SpeedData obj = new SpeedData();
obj.context = mContext;
obj.marker = marker;
obj.speed = cloudRoadData.getSpeed();
SimpleHandlerThreadPool.getInstance().postRender(obj::showSpeed);
msg.obj = obj;
msg.what = MSG_DISPLAY_SPEED;
msg.sendToTarget();
}
}
@@ -298,8 +370,7 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
String resIdVal = null;
if ( MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode() ) {
options.set3DMode( true );
options.anchorColor( getModelRenderColor( data.getFromType(), data.getType() ) );
// options.anchorColor( getModelRenderColor( data.getSpeed(), data.getWgslon(), data.getWgslat(), data.getHeading() ) );
options.anchorColor( getModelRenderColor( data.getSpeed(), data.getWgslon(), data.getWgslat(), data.getHeading() ) );
int resId = getModelRes( data.getType() );
resIdVal = resId + "";
options.resName( mMarkerCachesResMd5Values.get( resIdVal ) );
@@ -312,6 +383,11 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
}
IMogoMarker marker = MogoApisHandler.getInstance().getApis().getMapServiceApi().getMarkerManager( mContext ).addMarker( DataTypes.TYPE_MARKER_CLOUD_DATA, options );
cacheMarkerIconResMd5Val( resIdVal, marker );
if ( !TextUtils.isEmpty( data.getSn() ) ) {
bindClickListener( marker );
}
return marker;
}

View File

@@ -2,27 +2,6 @@ package com.mogo.module.common.utils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.ArrayMap;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.map.MogoLatLng;
import com.mogo.map.marker.IMogoMarker;
import com.mogo.module.common.MogoApisHandler;
import com.mogo.module.common.drawer.AdasRecognizedResultDrawer;
import com.mogo.module.common.drawer.BaseDrawer;
import com.mogo.module.common.drawer.SnapshotSetDataDrawer;
import com.mogo.realtime.entity.CloudRoadData;
import com.mogo.utils.logger.Logger;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static com.mogo.module.common.drawer.BaseDrawer.MSG_REMOVE_DIRTY_MARKERS;
/**
* 简单HandlerThread线程池实现
@@ -34,70 +13,9 @@ public class SimpleHandlerThreadPool {
private final HandlerThread renderThread = new HandlerThread( "one-frame-render-thread" );
private final Handler renderHandler;
public static final int MSG_POINTS_SETTING = 9;
public static final int MSG_SET_POINT = 10;
private SimpleHandlerThreadPool() {
renderThread.start();
renderHandler = new Handler( renderThread.getLooper() ){
@Override
public void handleMessage( Message msg ) {
super.handleMessage( msg );
if ( msg.what == MSG_POINTS_SETTING ) {
if ( msg.obj instanceof BaseDrawer.MovingPoints ) {
startSettingPointLooper( ( ( BaseDrawer.MovingPoints ) msg.obj ) );
}
} else if ( msg.what == MSG_SET_POINT ) {
if ( msg.obj instanceof BaseDrawer.MovingPoint ) {
moveMarker( ( ( BaseDrawer.MovingPoint ) msg.obj ) );
}
}
}
};
}
/**
* 开启设置位置的循环
*
* @param data
*/
private void startSettingPointLooper( BaseDrawer.MovingPoints data ) {
List< BaseDrawer.MovingPoint > points = data.points;
for ( int i = 0; i < points.size(); i++ ) {
Message msg = Message.obtain();
msg.what = MSG_SET_POINT;
msg.obj = points.get( i );
renderHandler.sendMessageDelayed( msg, points.get(i).delay );
}
}
private long startMove = 0;
private int lastIndex = 0;
private void slowTest(){
if (startMove == 0) {
startMove = SystemClock.uptimeMillis();
} else {
long diff = SystemClock.uptimeMillis() - startMove;
int index = (int) (diff / 30);
if (index - lastIndex > 1) {
Logger.e("MapRenderSlow", "miss " + (index - lastIndex) + " diff: " + diff);
}
lastIndex = index;
}
}
/**
* 设置 marker 的点到新的位置
*
* @param pointData
*/
private void moveMarker(BaseDrawer.MovingPoint pointData) {
if (pointData == null) {
return;
}
// slowTest();
pointData.move();
renderHandler = new Handler( renderThread.getLooper() );
}
private static final SimpleHandlerThreadPool INSTANCE = new SimpleHandlerThreadPool();
@@ -106,213 +24,7 @@ public class SimpleHandlerThreadPool {
return INSTANCE;
}
/**
* 默认线程数量
*/
private static final int DEFAULT_THREAD_COUNT = 3;
private int threadCount = DEFAULT_THREAD_COUNT;
public void setThreadCount( int threadCount ) {
this.threadCount = threadCount;
}
Map< String, WorkHandler > dataHandlerMap = new ArrayMap<>();
Map< Integer, WorkHandler > handlerPool = new ArrayMap<>();
private int lastUseThreadId = -1;
public void post( CloudRoadData cloudRoadData ) {
String uuid = cloudRoadData.getUniqueKey();
Message msg;
if ( dataHandlerMap.containsKey( uuid ) ) {
msg = dataHandlerMap.get( uuid ).obtainMessage();
} else {
if ( handlerPool.size() < threadCount ) {
// 新开线程
lastUseThreadId = handlerPool.size();
HandlerThread thread = new HandlerThread( "one-frame-work-thread-" + handlerPool.size() );
thread.start();
WorkHandler handler = new WorkHandler( thread.getLooper() );
handlerPool.put( handlerPool.size(), handler );
dataHandlerMap.put( uuid, handler );
msg = handler.obtainMessage();
} else {
// 复用线程
if ( lastUseThreadId == threadCount - 1 ) {
lastUseThreadId = 0;
} else {
lastUseThreadId++;
}
WorkHandler handler = handlerPool.get( lastUseThreadId );
dataHandlerMap.put( uuid, handler );
msg = handler.obtainMessage();
}
}
msg.obj = cloudRoadData;
msg.sendToTarget();
}
public void removeDirtyMarker( Collection< String > keys ) {
for ( WorkHandler handler : handlerPool.values() ) {
handler.removeDirtyMarker( keys );
}
}
class WorkHandler extends Handler {
public WorkHandler( Looper looper ) {
super( looper );
}
@Override
public void handleMessage( Message msg ) {
CloudRoadData cloudRoadData = ( CloudRoadData ) msg.obj;
renderCarOneFrame( cloudRoadData );
}
private final Map< String, IMogoMarker > markerCache = new ArrayMap<>();
private final Map< String, CloudRoadData > roadDataCache = new ArrayMap<>();
private final Map< String, Long > lastExecutionTimeCache = new ArrayMap<>();
private final Map< String, Boolean > isMatchStatusCache = new ArrayMap<>();
private void renderCarOneFrame( CloudRoadData cloudRoadData ) {
if ( cloudRoadData == null ) {
return;
}
// 暂时只显示车辆
if ( TextUtils.isEmpty( cloudRoadData.getSn() ) ) {
if ( !SnapshotSetDataDrawer.getInstance().isRenderType( cloudRoadData.getType() ) ) {
return;
}
}
String uniqueKey = cloudRoadData.getUniqueKey();
if ( TextUtils.isEmpty( uniqueKey )
// 本地过滤重复下发的adas识别车辆
|| AdasRecognizedResultDrawer.getInstance().hasCached( uniqueKey ) ) {
return;
}
final long start = System.currentTimeMillis();
IMogoMarker marker = markerCache.get( uniqueKey );
CloudRoadData lastPosition = roadDataCache.put( uniqueKey, cloudRoadData );
if ( marker == null || marker.isDestroyed() ) {
marker = SnapshotSetDataDrawer.getInstance().drawSnapshotDataMarker( cloudRoadData );
if ( marker == null ) {
return;
}
markerCache.put( uniqueKey, marker );
if ( !TextUtils.isEmpty( cloudRoadData.getSn() ) ) {
SnapshotSetDataDrawer.getInstance().bindClickListener( marker );
}
}
double[] matchedPoint = SnapshotSetDataDrawer.getInstance().matchRoad( cloudRoadData.getUniqueKey(),
cloudRoadData.getWgslon(),
cloudRoadData.getWgslat(),
cloudRoadData.getHeading(),
true
);
Boolean isMatch = isMatchStatusCache.get( uniqueKey );
if ( matchedPoint != null ) {
if ( ( isMatch == null || !isMatch ) ) {
if ( matchedPoint[2] < 0.5 ) {
isMatch = true;
}
} else {
if ( matchedPoint[2] > 1 ) {
isMatch = false;
}
}
if ( isMatch == null ) {
isMatch = false;
}
isMatchStatusCache.put( uniqueKey, isMatch );
if ( isMatch ) {
cloudRoadData.setLon( matchedPoint[0] );
cloudRoadData.setLat( matchedPoint[1] );
}
}
SnapshotSetDataDrawer.getInstance().changeIconResourceIfNecessary( cloudRoadData, marker );
final IMogoMarker finalMarker = marker;
Logger.d( TAG, "work in " + Thread.currentThread().getName() );
// if ( lastPosition != null ) {
// MogoLatLng endLatLon = new MogoLatLng( cloudRoadData.getWgslat(),cloudRoadData.getWgslon() );
// long interval = SnapshotSetDataDrawer.getInstance().computeAnimDuration( lastPosition.getSystemTime(), cloudRoadData.getSystemTime(), lastPosition.getSatelliteTime(), cloudRoadData.getSatelliteTime() );
//
// long cost = System.currentTimeMillis() - start;
// interval -= cost;
// MogoLatLng lastPoint = new MogoLatLng( lastPosition.getWgslat(), lastPosition.getWgslon() );
// BaseDrawer.MovingPoint endPoint = new BaseDrawer.MovingPoint();
// endPoint.point = endLatLon;
// endPoint.marker = marker;
// endPoint.delay = interval;
// endPoint.angle = ( float ) cloudRoadData.getHeading();
//
// BaseDrawer.MovingPoint startPoint = new BaseDrawer.MovingPoint();
// startPoint.point = lastPoint;
// startPoint.marker = marker;
// startPoint.delay = 0;
// startPoint.angle = ( float ) lastPosition.getHeading();
// List< BaseDrawer.MovingPoint > points = BaseDrawer.interpolate( startPoint, endPoint, interval );
// Message msg = new Message();
// BaseDrawer.MovingPoints obj = new BaseDrawer.MovingPoints();
// obj.points = points;
// startSettingPointLooper(obj);
//// msg.obj = obj;
//// msg.what = MSG_POINTS_SETTING;
//// renderHandler.sendMessage( msg );
//// marker.startSmoothInMs( points, interval );
//// marker.addDynamicAnchorPosition( endLatLon, interval );
// Logger.d( TAG, "anim duration: %s, points size = %s", interval, points.size() );
// } else {
// marker.setRotateAngle( ( ( float ) cloudRoadData.getHeading() ) );
// marker.setPosition(cloudRoadData.getWgslat(), cloudRoadData.getWgslon());
// }
// SnapshotSetDataDrawer.getInstance().showSelfSpeed( AbsMogoApplication.getApp(),
// marker,
// cloudRoadData.getSpeed(),
// MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()
// );
long interval = 0;
if(lastPosition!=null&& !lastPosition.equals( cloudRoadData )) {
long cost = System.currentTimeMillis() - start;
interval = cloudRoadData.getSystemTime() - lastPosition.getSystemTime() - cost;
}
final long finalInterval =interval;
renderHandler.post( () -> {
// 由于地图现在不支持addDynamicAnchorPosition并发所以工作线程仅做相关计算真正绘制发送到另外一条绘制线程中做
if ( lastPosition != null && !lastPosition.equals( cloudRoadData ) ) {
finalMarker.addDynamicAnchorPosition( new MogoLatLng( cloudRoadData.getWgslat(), cloudRoadData.getWgslon() ),(float)cloudRoadData.getHeading(), finalInterval );
Logger.d( TAG, "anim duration: %s in thread: %s", finalInterval, Thread.currentThread().getName() );
} else {
finalMarker.setRotateAngle( ( float ) cloudRoadData.getHeading() );
finalMarker.setPosition( cloudRoadData.getWgslat(), cloudRoadData.getWgslon() );
Logger.d( TAG, "设置点位置 in thread: %s", Thread.currentThread().getName() );
}
lastExecutionTimeCache.put( uniqueKey, SystemClock.uptimeMillis() );
SnapshotSetDataDrawer.getInstance().showSelfSpeed( AbsMogoApplication.getApp(), finalMarker, cloudRoadData.getSpeed(), MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode() );
} );
}
public void removeDirtyMarker( Collection< String > keys ) {
Map< String, IMogoMarker > result = new ArrayMap<>( keys.size() );
for ( String key : keys ) {
if ( markerCache.containsKey( key ) ) {
result.put( key, markerCache.remove( key ) );
}
}
SnapshotSetDataDrawer.getInstance().sendMessage( MSG_REMOVE_DIRTY_MARKERS, result );
}
}
public void postRender(Runnable runnable) {
renderHandler.post(runnable);
public void postRender( Runnable runnable ) {
renderHandler.post( runnable );
}
}