package safeluck.drive.evaluation.fragment;
|
|
import android.content.Context;
|
import android.graphics.Canvas;
|
import android.graphics.Color;
|
import android.graphics.DashPathEffect;
|
import android.graphics.Paint;
|
import android.graphics.Path;
|
import android.os.Bundle;
|
import android.util.Log;
|
import android.view.LayoutInflater;
|
import android.view.SurfaceHolder;
|
import android.view.SurfaceView;
|
import android.view.View;
|
import android.view.ViewGroup;
|
|
import androidx.annotation.NonNull;
|
import androidx.annotation.Nullable;
|
|
import com.anyun.exam.lib.MyLog;
|
import com.google.gson.Gson;
|
import com.google.gson.reflect.TypeToken;
|
|
import java.lang.reflect.Type;
|
import java.math.BigDecimal;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.Executors;
|
import java.util.concurrent.LinkedBlockingQueue;
|
|
import me.yokeyword.fragmentation.SupportFragment;
|
import safeluck.drive.evaluation.Constant;
|
import safeluck.drive.evaluation.bean.RealTimeCarPos;
|
import safeluck.drive.evaluation.bean.RoadExamMap;
|
import safeluck.drive.evaluation.cEventCenter.CEventCenter;
|
import safeluck.drive.evaluation.cEventCenter.ICEventListener;
|
import safeluck.drive.evaluation.util.FileUtil;
|
|
public class RoadDriveMapFragment extends SupportFragment implements SurfaceHolder.Callback {
|
|
private static final String TAG = RoadDriveMapFragment.class.getSimpleName();
|
private static final int ALL_MAP = 100;//总图
|
|
private SurfaceView mSurfaceView;
|
private SurfaceHolder mSurfaceHolder;
|
private boolean flag = false;//控制绘制线程drawThread
|
private Canvas mCanvas;
|
private Canvas bitMapCanvas;
|
private Paint mPaint;
|
private Path mPath;
|
private StringBuffer buffer;//存放地图的buffer
|
private Gson gson = new Gson();
|
private double gpsSpeed = 0;
|
private int map_id = -1;
|
|
|
private String osdHeading = null;
|
private String osdMoveDirect = null;
|
private String osdRtkSpeed = null;
|
private String osdQf = null;
|
double car[][] = {{8.278, 1.467}, {7.2780000000000009, 1.467}, {7.2780000000000009, -1.533}, {8.278, -1.533}
|
, {9.278, -1.5330000000000004}, {9.277999999999999, 1.467000000000001}};
|
double map[][]={};
|
|
private LinkedBlockingQueue queue = new LinkedBlockingQueue(100);
|
|
private int avaliableWidth,avaliableHeight;
|
|
private int x = 50, y = 50, r = 10; // 圆的坐标和半径
|
float [] pts={50,100,100,200,200,300,300,400};
|
|
private ExecutorService generateData = Executors.newSingleThreadExecutor();//产生数据(主要是车辆数据)
|
private ExecutorService drawThread = Executors.newSingleThreadExecutor();//绘制线程
|
|
|
/**
|
* 接收远程服务发过来的车辆位置信息
|
*/
|
private ICEventListener icEventListener = new ICEventListener() {
|
@Override
|
public void onCEvent(String topic, final int msgCode, int resultCode, final Object obj) {
|
|
|
generateData.execute(new Runnable() {
|
@Override
|
public void run() {
|
queue.offer(new MessageRemoteService(msgCode,obj));
|
}
|
});
|
|
|
}
|
};
|
|
public static RoadDriveMapFragment newInstance(){
|
return new RoadDriveMapFragment();
|
}
|
|
@Nullable
|
@Override
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
mSurfaceView = new SurfaceView(_mActivity);
|
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
|
|
mSurfaceView.setLayoutParams(layoutParams);
|
mSurfaceView.getHolder().addCallback(this);
|
mSurfaceHolder = mSurfaceView.getHolder();
|
avaliableHeight = mSurfaceView.getHeight();
|
avaliableWidth = mSurfaceView.getWidth();
|
Log.i(TAG,"可用宽度="+avaliableWidth+"可用高度="+avaliableHeight);
|
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
mPaint.setStyle(Paint.Style.STROKE);
|
mPaint.setStrokeWidth(1.5f);
|
mPath = new Path();
|
|
int widhtpixels =getResources().getDisplayMetrics().widthPixels;
|
int heightpixels =getResources().getDisplayMetrics().heightPixels;
|
Log.i(TAG,"widhtpixels="+widhtpixels+" heig="+heightpixels);
|
return mSurfaceView;
|
}
|
|
@Override
|
public void surfaceCreated(SurfaceHolder holder) {
|
// mCanvas = holder.lockCanvas();
|
// int screen_width = mCanvas.getWidth();
|
// int screen_height = mCanvas.getHeight();
|
// Bitmap bmp = Bitmap.createBitmap(screen_width, screen_height, Bitmap.Config.ARGB_8888);
|
// bitMapCanvas = new Canvas(bmp);
|
// bitMapCanvas.drawColor(Color.WHITE);
|
//
|
// mPaint = new Paint();
|
//
|
// mPaint.setTextSize(30);
|
// mPaint.setColor(Color.BLACK);
|
// mPaint.setStrokeWidth(1.5f);
|
// mPaint.setAntiAlias(true);
|
// mPaint.setStyle(Paint.Style.STROKE);
|
//
|
// mCanvas.drawBitmap(bmp,0,0,mPaint);
|
// holder.unlockCanvasAndPost(mCanvas);
|
|
|
flag = true;
|
|
drawThread.execute(new DrawRunnable());
|
}
|
|
@Override
|
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
|
|
}
|
|
@Override
|
public void surfaceDestroyed(SurfaceHolder holder) {
|
flag = false;
|
}
|
|
RoadExamMap examMaps ;
|
|
/**
|
* 主要是这个方法,进行坐标点计算,使用mPath画图,可能要用到Canvas
|
* 最好只使用path
|
*/
|
private void calculate() {
|
int map_line = 0,line = 0;
|
MessageRemoteService messageRemoteService = (MessageRemoteService) queue.peek();
|
if (messageRemoteService == null){
|
Log.i(TAG,"messageRemoteService ==null");
|
|
try {
|
Thread.sleep(100);
|
} catch (InterruptedException e) {
|
e.printStackTrace();
|
}
|
}
|
messageRemoteService = (MessageRemoteService) queue.poll();
|
if (messageRemoteService != null){
|
MyLog.i(TAG, messageRemoteService.json);
|
|
|
RealTimeCarPos timeCarPos = gson.fromJson((String) messageRemoteService.json, RealTimeCarPos.class);
|
List<Double> points = timeCarPos.getPoint();
|
switch (timeCarPos.getMove()){
|
case 0:
|
osdMoveDirect = "停车";
|
break;
|
case 1:
|
osdMoveDirect = "前进";
|
break;
|
case -1:
|
osdMoveDirect = "后退";
|
break;
|
}
|
osdHeading="方向角"+String.valueOf(timeCarPos.getHeading());
|
|
BigDecimal bd = new BigDecimal(timeCarPos.getSpeed());
|
bd = bd.setScale(3, BigDecimal.ROUND_HALF_UP);
|
osdRtkSpeed = "计算速度:" + bd;
|
|
osdQf = "QF:" + String.valueOf(timeCarPos.getQf());
|
|
|
|
car = new double[points.size()/2][2];
|
|
for (int i = 0; i < points.size(); i++) {
|
if ((i % 2) == 0) {
|
car[line][0] = points.get(i);
|
} else {
|
double value = 0 - points.get(i);
|
car[line][1] = value;
|
line++;
|
}
|
|
}
|
map_id = timeCarPos.getMap_id();
|
|
List<Double> mainAnt = timeCarPos.getMain_ant();
|
List<Integer> tire1 = timeCarPos.getLeft_front_tire();
|
List<Integer> tire2 = timeCarPos.getRight_front_tire();
|
List<Integer> tire3 = timeCarPos.getLeft_rear_tire();
|
List<Integer> tire4 = timeCarPos.getRight_rear_tire();
|
|
List<Integer> body = timeCarPos.getBody();
|
|
List<Integer> tire = new ArrayList<>();
|
|
tire.add(tire1.get(0));
|
tire.add(tire2.get(0));
|
tire.add(tire3.get(0));
|
tire.add(tire4.get(0));
|
|
|
|
|
if (buffer == null){
|
|
buffer = FileUtil.readAssetTxtFile(_mActivity, Constant.ROAD_MAP);
|
Log.i(TAG,"ditu="+buffer.toString().trim());
|
}
|
Type type = new TypeToken<RoadExamMap>(){}.getType();
|
if (buffer != null){
|
examMaps= gson.fromJson(buffer.toString().trim(), type);
|
}
|
if (examMaps!=null){
|
|
points = examMaps.getPoints();
|
if (points != null){
|
map = new double[points.size()/2][2];
|
for (int i = 0; i < points.size(); i++) {
|
if ((i % 2) == 0){
|
map[map_line][0] = points.get(i);
|
|
}else{
|
double value = 0-points.get(i);
|
map[map_line][1] = value;
|
map_line++;
|
}
|
}
|
}
|
}
|
|
onDrawMap(map,examMaps.getMaps(),car,body,tire,mainAnt);
|
|
}
|
|
|
|
|
|
|
|
|
|
// mPaint.reset();
|
// mPaint.setStyle(Paint.Style.FILL);
|
// mPaint.setColor(Color.RED);
|
// mPath.addCircle(x,y,r, Path.Direction.CCW);
|
//
|
// mCanvas.drawPath(mPath,mPaint);
|
//
|
//
|
// mPaint.reset();
|
// mPaint.setStyle(Paint.Style.FILL);
|
// mPaint.setColor(Color.GREEN);
|
// mCanvas.drawCircle(x+100,y+100,70,mPaint);
|
//
|
//
|
// mPaint.reset();
|
// mPath = new Path();
|
// mPaint.setColor(Color.GREEN);
|
// mPaint.setStyle(Paint.Style.STROKE);
|
// mPaint.setStrokeWidth(1.5f);
|
//
|
// mPath.moveTo(pts[0],pts[1]);
|
// mPath.lineTo(pts[2],pts[3]);
|
// mCanvas.drawPath(mPath,mPaint);
|
|
|
|
if (mCanvas != null){
|
//释放canvas对象并提交画布
|
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
|
}
|
|
}
|
|
|
private void onDrawMap(final double[][] map, List<RoadExamMap.MapsBean> maps,final double[][] car,
|
List<Integer>body, List<Integer> tire,List<Double> mainAnt){
|
double base_x = 300, base_y = 20;
|
double max_x = 0, min_x = 0, max_y = 0, min_y = 0;
|
|
Log.d(TAG, "DrawMap map size " + map.length + " car size " );
|
|
for (int i = 0; i < map.length; i++) {
|
if (i == 0) {
|
max_x = map[0][0];
|
min_x = map[0][0];
|
max_y = map[0][1];
|
min_y = map[0][1];
|
} else {
|
if (max_x < map[i][0]) {
|
max_x = map[i][0];
|
}
|
if (min_x > map[i][0]) {
|
min_x = map[i][0];
|
}
|
if (max_y < map[i][1]) {
|
max_y = map[i][1];
|
}
|
if (min_y > map[i][1]) {
|
min_y = map[i][1];
|
}
|
}
|
}
|
for (int i = 0; i < car.length; i++) {
|
if (max_x < car[i][0]) {
|
max_x = car[i][0];
|
}
|
if (min_x > car[i][0]) {
|
min_x = car[i][0];
|
}
|
if (max_y < car[i][1]) {
|
max_y = car[i][1];
|
}
|
if (min_y > car[i][1]) {
|
min_y = car[i][1];
|
}
|
}
|
|
long scale_x = Math.round((mCanvas.getWidth() - base_x - 10) / (max_x - min_x));
|
long scale_y = Math.round((mCanvas.getHeight() - base_y - 10) / (max_y - min_y));
|
|
if (scale_x >= scale_y) {
|
scale_x = scale_y;
|
} else {
|
scale_y = scale_x;
|
}
|
|
mPaint.reset();
|
mPaint.setAntiAlias(true);
|
mPaint.setColor(Color.BLUE);
|
mPaint.setStrokeWidth(1.5f);
|
|
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
|
mCanvas.drawCircle((float) (base_x + (mainAnt.get(0) - min_x) * scale_x), (float) (base_y + (0 - mainAnt.get(1) - min_y) * scale_y), 2, mPaint);
|
|
mPaint.setColor(Color.RED);
|
mCanvas.drawCircle((float) (base_x + (car[tire.get(0)][0] - min_x) * scale_x), (float) (base_y + (car[tire.get(0)][1] - min_y) * scale_y), 2.5f, mPaint);
|
mCanvas.drawCircle((float) (base_x + (car[tire.get(1)][0] - min_x) * scale_x), (float) (base_y + (car[tire.get(1)][1] - min_y) * scale_y), 2.5f, mPaint);
|
mCanvas.drawCircle((float) (base_x + (car[tire.get(2)][0] - min_x) * scale_x), (float) (base_y + (car[tire.get(2)][1] - min_y) * scale_y), 2.5f, mPaint);
|
mCanvas.drawCircle((float) (base_x + (car[tire.get(3)][0] - min_x) * scale_x), (float) (base_y + (car[tire.get(3)][1] - min_y) * scale_y), 2.5f, mPaint);
|
|
mPaint.setStyle(Paint.Style.STROKE);
|
mPaint.setColor(Color.BLACK);
|
|
if (map.length > 9) {
|
if (maps != null&& maps.size()>0){
|
for (int i = 0; i < maps.size(); i++) {
|
RoadExamMap.MapsBean mapItem = maps.get(i);
|
if (mapItem.getItem() == ALL_MAP){
|
List<List<Integer>> redLines= mapItem.getRed_line();
|
List<List<Integer>> greenLines = mapItem.getGreen_line();
|
mPaint.reset();
|
mPaint.setStyle(Paint.Style.STROKE);
|
mPaint.setStrokeWidth(1.5f);
|
mPaint.setAntiAlias(true);
|
mPaint.setColor(Color.RED);
|
Log.i(TAG,"redLinesSize"+redLines.size());
|
for (List<Integer> redline: redLines
|
) {
|
for (int j = 0; j < redline.size(); j++) {
|
Log.i(TAG,"redLiSize"+redline.size());
|
int pos = redline.get(j);
|
if (j == 0){
|
mPath.moveTo((float) (base_x + (map[pos][0] - min_x) * scale_x), (float) (base_y + (map[pos][1] - min_y) * scale_y));
|
}
|
mPath.lineTo((float) (base_x + (map[pos][0] - min_x) * scale_x), (float) (base_y + (map[pos][1] - min_y) * scale_y));
|
Log.i(TAG,String.format("map[%d][0]=%f,map[%d][1]=%f,line to (%f,%f)",pos,map[pos][0],pos,map[pos][1],
|
(float) (base_x + (map[pos][0] - min_x) * scale_x),(float) (base_y + (map[pos][1] - min_y) * scale_y)));
|
|
}
|
}
|
mCanvas.drawPath(mPath,mPaint);
|
//画虚线(分道线)
|
mPaint.reset();
|
mPaint.setStyle(Paint.Style.STROKE);
|
mPaint.setStrokeWidth(1.5f);
|
mPaint.setAntiAlias(true);
|
mPaint.setColor(Color.WHITE);
|
mPath = new Path();
|
mPaint.setPathEffect(new DashPathEffect(new float[] {15, 15}, 0));
|
for (List<Integer> greenline:
|
greenLines){
|
for (int j = 0; j < greenline.size(); j++) {
|
int pos = greenline.get(j);
|
if (j == 0){
|
mPath.moveTo((float) (base_x + (map[pos][0] - min_x) * scale_x), (float) (base_y + (map[pos][1] - min_y) * scale_y));
|
}
|
mPath.lineTo((float) (base_x + (map[pos][0] - min_x) * scale_x), (float) (base_y + (map[pos][1] - min_y) * scale_y));
|
Log.i(TAG,String.format("map[%d][0]=%f,map[%d][1]=%f,line to (%f,%f)",pos,map[pos][0],pos,map[pos][1],
|
(float) (base_x + (map[pos][0] - min_x) * scale_x),(float) (base_y + (map[pos][1] - min_y) * scale_y)));
|
}
|
}
|
mCanvas.drawPath(mPath,mPaint);
|
|
}
|
}
|
|
mPath.moveTo((float) (base_x + (car[body.get(0)][0] - min_x) * scale_x), (float) (base_y + (car[body.get(0)][1] - min_y) * scale_y));
|
for (int k = 1; k < body.size(); k++){
|
Log.d(TAG, "for 循环 DrawMap to X = " + (float) (base_x + (car[body.get(k)][0] - min_x) * scale_x)+ " Y = " + (float) (base_y + (car[body.get(k)][1] - min_y) * scale_y));
|
mPath.lineTo((float) (base_x + (car[body.get(k)][0] - min_x) * scale_x), (float) (base_y + (car[body.get(k)][1] - min_y) * scale_y));
|
}
|
|
mPath.close();
|
|
mCanvas.drawPath(mPath, mPaint);
|
|
|
|
}
|
|
}
|
|
|
//mPaint.reset();
|
// mPath = new Path();
|
// mPaint.setStyle(Paint.Style.STROKE);
|
// mPaint.setStrokeWidth(1.5f);
|
//
|
// for (int i = 0; i < map.length; i++) {
|
// if (i<map.length-3){
|
// mPath.moveTo((float) (base_x + (map[i][0] - min_x) * scale_x), (float) (base_y + (map[i][1] - min_y) * scale_y));
|
// mPath.lineTo((float) (base_x + (map[i+3][0] - min_x) * scale_x), (float) (base_y + (map[i+3][1] - min_y) * scale_y));
|
// }else{
|
// break;
|
// }
|
//
|
// i++;
|
// }
|
// mCanvas.drawPath(mPath,mPaint);
|
}
|
|
/**
|
* 绘制
|
*/
|
private void drawMap() {
|
try {
|
//获得canvas对象
|
mCanvas = mSurfaceHolder.lockCanvas();
|
//绘制背景
|
mCanvas.drawColor(Color.WHITE);
|
Log.i(TAG,"width="+mCanvas.getWidth()+"height:"+mCanvas.getHeight());
|
//绘制路径
|
mCanvas.drawPath(mPath, mPaint);
|
}catch (Exception e){
|
|
}finally {
|
// if (mCanvas != null){
|
// mCanvas.restore();
|
// //释放canvas对象并提交画布
|
// mSurfaceHolder.unlockCanvasAndPost(mCanvas);
|
// }
|
}
|
|
}
|
|
class DrawRunnable implements Runnable{
|
|
@Override
|
public void run() {
|
while(flag){
|
|
drawMap();
|
calculate();
|
try {
|
Thread.sleep(50);
|
} catch (InterruptedException e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
}
|
|
|
|
class MessageRemoteService{
|
public int msgCode;
|
public String json;
|
|
public MessageRemoteService(int msgCode, Object obj) {
|
this.json = (String) obj;
|
this.msgCode = msgCode;
|
}
|
}
|
|
|
@Override
|
public void onAttach(Context context) {
|
super.onAttach(context);
|
CEventCenter.onBindEvent(true, icEventListener, Constant.REAL_TIME_POS_CAR_TOPIC);
|
CEventCenter.onBindEvent(true, speedListener, Constant.BIND_RTK_SPEED_TOPIC);
|
}
|
@Override
|
public void onDetach() {
|
super.onDetach();
|
generateData.shutdown();
|
drawThread.shutdown();
|
CEventCenter.onBindEvent(false, icEventListener, Constant.REAL_TIME_POS_CAR_TOPIC);
|
CEventCenter.onBindEvent(false, speedListener, Constant.BIND_RTK_SPEED_TOPIC);
|
}
|
private ICEventListener speedListener = new ICEventListener() {
|
@Override
|
public void onCEvent(String topic, int msgCode, int resultCode, Object obj) {
|
if (msgCode == Constant.RTK_INFO){
|
gpsSpeed = (double)obj;
|
}
|
}
|
};
|
|
}
|