gnssview_old/lib/sky/skyPlot.dart
tanlinxing 553bde932c getx
2024-07-31 19:04:11 +08:00

251 lines
8.7 KiB
Dart

import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:gnss/gnss.dart';
import '../Controller/gnssController.dart';
class DrawSkyPlot {
double width = 500;
double height = 500;
late Canvas ctx;
Map legend = {};
final Paint _paint = Paint();
Path path = Path();
bool isPortrait = false;
late LocationData locationData;
late SignalData signalData;
late GnssController controller;
// final GnssController controller;
final bool isDarkMode;
Color color = Colors.black;
DrawSkyPlot(op, this.isDarkMode, this.controller) {
// controller = Get.find<GnssController>(tag: 'gnss');
ctx = op['ctx']; // canvas dom 对象
height = op['height']; // 画布高
width = op['width']; // 画布宽
if (isDarkMode) {
color = Colors.white;
} else {
color = Colors.black;
}
_paint
..color = color
..strokeWidth = 3
..style = PaintingStyle.stroke;
MediaQueryData mediaQueryData =
MediaQueryData.fromView(WidgetsBinding.instance.window);
final orientation = mediaQueryData.orientation;
// 横屏竖屏宽高重新设置
if (orientation == Orientation.portrait) {
height = op['width'];
isPortrait = true;
} else {
width = op['height'];
isPortrait = false;
}
}
//外圈
drawSkyPlotCircle() {
double x = (width / 2) + 50;
double y = (height / 2) - 15;
double r = height / 2.5;
ctx.drawCircle(Offset(x, y), r, _paint);
ctx.drawCircle(Offset(x, y), r * 2 / 3, _paint);
ctx.drawCircle(Offset(x, y), r / 3, _paint);
path.moveTo(x - r, y);
path.lineTo(x + r, y);
path.moveTo(x, y - r);
path.lineTo(x, y + r);
path.moveTo(x + cos(30 * (pi / 180)) * r, y + sin(30 * (pi / 180)) * r);
path.lineTo(x - cos(30 * (pi / 180)) * r, y - sin(30 * (pi / 180)) * r);
path.moveTo(x + cos(60 * (pi / 180)) * r, y + sin(60 * (pi / 180)) * r);
path.lineTo(x - cos(60 * (pi / 180)) * r, y - sin(60 * (pi / 180)) * r);
path.moveTo(x + cos(60 * (pi / 180)) * r, y - sin(60 * (pi / 180)) * r);
path.lineTo(x - cos(60 * (pi / 180)) * r, y + sin(60 * (pi / 180)) * r);
path.moveTo(x - cos(60 * (pi / 180)) * r, y + sin(60 * (pi / 180)) * r);
path.lineTo(x + cos(60 * (pi / 180)) * r, y - sin(60 * (pi / 180)) * r);
path.moveTo(x + cos(30 * (pi / 180)) * r, y - sin(30 * (pi / 180)) * r);
path.lineTo(x - cos(30 * (pi / 180)) * r, y + sin(30 * (pi / 180)) * r);
path.moveTo(x - cos(30 * (pi / 180)) * r, y + sin(30 * (pi / 180)) * r);
path.lineTo(x + cos(30 * (pi / 180)) * r, y - sin(30 * (pi / 180)) * r);
ctx.drawPath(path, _paint);
Map textList = {
'0': Offset(x, y - r - 25),
'30': Offset(
x + cos(60 * (pi / 180)) * r, y - sin(60 * (pi / 180)) * r - 25),
'60': Offset(
x + cos(30 * (pi / 180)) * r + 10, y - sin(30 * (pi / 180)) * r - 10),
'90': Offset(x + r + 10, y - 5),
'120': Offset(
x + cos(30 * (pi / 180)) * r, y + sin(30 * (pi / 180)) * r + 5),
'150': Offset(
x + cos(60 * (pi / 180)) * r, y + sin(60 * (pi / 180)) * r + 5),
'180': Offset(x - 10, y + r),
'210': Offset(
x - cos(60 * (pi / 180)) * r - 20, y + sin(60 * (pi / 180)) * r + 10),
'240': Offset(
x - cos(30 * (pi / 180)) * r - 30, y + sin(30 * (pi / 180)) * r + 5),
'270': Offset(x - r - 35, y - 5),
'300': Offset(
x - cos(30 * (pi / 180)) * r - 37, y - sin(30 * (pi / 180)) * r - 20),
'330': Offset(
x - cos(60 * (pi / 180)) * r - 30, y - sin(60 * (pi / 180)) * r - 25)
};
textList.forEach((key, offset) {
TextPainter(
text: TextSpan(text: key, style: TextStyle(color: color, fontSize: 20)),
textDirection: TextDirection.ltr,
)
..layout()
..paint(ctx, offset);
});
}
getCircles() {
legend = {};
double radius = height / 2.5;
double r = 15;
if (controller.signalData == null) {
return;
}
var signalData = controller.signalData!;
if (controller.selectedSignal['GPS'] == true) {
for (int i = 0; i < signalData.GPS.length; i++) {
SignalGPS item = controller.signalData!.GPS![i];
double elev = item.elevation * pi / 180; // 将仰角转换为弧度
double maxr = radius * cos(elev); // 计算该点到圆心的距离
double azi = (90 - item.azimuth) * pi / 180; // 将方位角转换为弧度
double cx = (maxr) * cos(azi); // 计算 x 坐标
double cy = -(maxr) * sin(azi); // 计算 y
_paint.color = Colors.blue;
_paint.style = PaintingStyle.fill;
// 绘制卫星位置
ctx.drawCircle(Offset(cx, cy), r, _paint);
}
} else if (controller.selectedSignal['BDS'] == true) {
for (int i = 0; i < signalData.BDS.length; i++) {
SignalBDS item = controller.signalData!.BDS![i];
double elev = item.elevation * pi / 180; // 将仰角转换为弧度
double maxr = radius * cos(elev); // 计算该点到圆心的距离
double azi = (90 - item.azimuth) * pi / 180; // 将方位角转换为弧度
double cx = (maxr) * cos(azi); // 计算 x 坐标
double cy = -(maxr) * sin(azi); // 计算 y
_paint.color = Colors.red;
_paint.style = PaintingStyle.fill;
// 绘制卫星位置
ctx.drawCircle(Offset(cx, cy), r, _paint);
}
} else if (controller.selectedSignal['GLO'] == true) {
for (int i = 0; i < signalData.GLO.length; i++) {
SignalGLO item = controller.signalData!.GLO![i];
double elev = item.elevation * pi / 180; // 将仰角转换为弧度
double maxr = radius * cos(elev); // 计算该点到圆心的距离
double azi = (90 - item.azimuth) * pi / 180; // 将方位角转换为弧度
double cx = (maxr) * cos(azi); // 计算 x 坐标
double cy = -(maxr) * sin(azi); // 计算 y
_paint.color = Colors.green;
_paint.style = PaintingStyle.fill;
// 绘制卫星位置
ctx.drawCircle(Offset(cx, cy), r, _paint);
}
} else if (controller.selectedSignal['ALS'] == true) {
for (int i = 0; i < signalData.GAL.length; i++) {
SignalGAL item = controller.signalData!.GAL![i];
double elev = item.elevation * pi / 180; // 将仰角转换为弧度
double maxr = radius * cos(elev); // 计算该点到圆心的距离
double azi = (90 - item.azimuth) * pi / 180; // 将方位角转换为弧度
double cx = (maxr) * cos(azi); // 计算 x 坐标
double cy = -(maxr) * sin(azi); // 计算 y
_paint.color = Colors.orange;
_paint.style = PaintingStyle.fill;
// 绘制卫星位置
ctx.drawCircle(Offset(cx, cy), r, _paint);
}
}
}
}
class SkyPlotPage extends StatelessWidget {
late final GnssController controller;
// Map<String, ui.Image> imageList = {};
@override
SkyPlotPage() {
controller = Get.find<GnssController>(tag: 'gnss');
}
Future<ui.Image> loadImage(String path) async {
ByteData data = await rootBundle.load(path);
ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
ui.FrameInfo fi = await codec.getNextFrame();
return fi.image;
}
@override
Widget build(BuildContext context) {
bool isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Obx(() {
controller.singnalUpdate;
return CustomPaint(
painter: DrawSky(controller, context, isDarkMode),
);
});
}
}
class DrawSky extends CustomPainter {
final BuildContext context;
final GnssController controller;
final bool isDarkMode;
// late SignalData signalData;
DrawSky(this.controller, this.context, this.isDarkMode);
@override
void paint(Canvas canvas, Size size) {
canvas.translate(0, -15);
final bool isPortrait =
MediaQuery.of(context).orientation == Orientation.portrait;
DrawSkyPlot skyPlot = DrawSkyPlot({
'ctx': canvas,
'height': size.height,
'width': size.width,
}, isDarkMode, controller);
if (!isPortrait) {
canvas.translate(-30, 0);
}
skyPlot.drawSkyPlotCircle();
// if (controller.chartData.value.time != 0) {
if (isPortrait) {
canvas.translate(size.width / 2, size.height / 2);
} else {
canvas.translate(size.width / 2, size.height / 2);
}
skyPlot.getCircles();
if (isPortrait) {
canvas.translate(-size.width / 2, -size.height / 2);
} else {
canvas.translate(-size.width / 2, -size.height / 2);
}
// }
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}