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 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 mainAnt = timeCarPos.getMain_ant(); List tire1 = timeCarPos.getLeft_front_tire(); List tire2 = timeCarPos.getRight_front_tire(); List tire3 = timeCarPos.getLeft_rear_tire(); List tire4 = timeCarPos.getRight_rear_tire(); List body = timeCarPos.getBody(); List 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(){}.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 maps,final double[][] car, Listbody, List tire,List 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]; } } //绘制背景 清屏 mCanvas.drawColor(Color.WHITE); 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); mPaint.reset(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(1.5f); mPaint.setAntiAlias(true); mPaint.setColor(Color.BLACK); 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.i(TAG,String.format("car[%d][0]=%f,to X =%f,car[%d][1]=%f,to Y=%f",k,car[body.get(k)][0], (float) (base_x + (car[body.get(k)][0] - min_x) * scale_x),k,car[body.get(k)][1],(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); 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> redLines= mapItem.getRed_line(); List> greenLines = mapItem.getGreen_line(); mPaint.reset(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(1.5f); mPaint.setAntiAlias(true); mPaint.setColor(Color.RED); for (List redline: redLines ) { for (int j = 0; j < redline.size(); j++) { 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 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); } } } } } /** * 绘制 */ 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; } } }; }