gnssview_old/lib/sky/sky_plot.dart

349 lines
12 KiB
Dart
Raw Normal View History

2024-07-31 23:37:51 +08:00
import 'dart:math';
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/gnss_controller.dart';
2024-08-01 15:13:18 +08:00
// const signalNameList = <String>["GPS", "GLONASS", "GALILEO", "BEIDOU", "QZSS"];
const Map<String, String> signalPrefixList = {
"GPS": "G",
"GLONASS": "N",
"GALILEO": "E",
"BEIDOU": "B",
"QZSS": "Q"
};
const Map<String, Color> signalColorMap = {
"GPS": Color.fromARGB(255, 255, 0, 0),
"GLONASS": Color.fromARGB(255, 0, 255, 0),
"GALILEO": Color.fromARGB(255, 0, 0, 255),
"BEIDOU": Color.fromARGB(255, 255, 255, 0),
"QZSS": Color.fromARGB(255, 0, 255, 255),
};
2024-07-31 23:37:51 +08:00
// 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({super.key}) {
controller = Get.find<GnssController>();
}
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;
2024-08-01 14:08:34 +08:00
final size = MediaQuery.of(context).size;
2024-07-31 23:37:51 +08:00
return Obx(() {
2024-08-01 14:08:34 +08:00
controller.singnalUpdate.value;
return SizedBox(
width: size.width,
height: size.height,
child: CustomPaint(
2024-08-01 15:13:18 +08:00
painter:
SkyPlotPainter(controller.signalData, controller.selectedSignal),
2024-08-01 14:08:34 +08:00
),
2024-07-31 23:37:51 +08:00
);
});
}
}
// class DrawSky extends CustomPainter {
// final BuildContext context;
// final GnssController controller;
// final radius = 20.0;
// 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;
// }
class SkyPlotPainter extends CustomPainter {
2024-08-01 15:13:18 +08:00
final SignalData? signalData;
final Map<String, bool> selectedSignal;
2024-08-01 14:08:34 +08:00
final satelliteRadius = 12.0;
2024-08-01 15:13:18 +08:00
SkyPlotPainter(this.signalData, this.selectedSignal);
2024-07-31 23:37:51 +08:00
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
2024-08-01 14:08:34 +08:00
..color = const ui.Color.fromARGB(255, 0, 0, 0)
2024-07-31 23:37:51 +08:00
..style = PaintingStyle.stroke;
final double radius = min(size.width / 2, size.height / 2);
final Offset center = Offset(size.width / 2, size.height / 2);
// Draw concentric circles for different elevation angles
for (int i = 0; i <= 90; i += 30) {
double r = radius * (90 - i) / 90;
canvas.drawCircle(center, r, paint);
}
// Draw lines for different azimuth angles
for (int i = 0; i < 360; i += 30) {
double radians = i * pi / 180;
double x = center.dx + radius * cos(radians);
double y = center.dy + radius * sin(radians);
canvas.drawLine(center, Offset(x, y), paint);
}
2024-08-01 15:13:18 +08:00
if (signalData == null) {
return;
}
2024-07-31 23:37:51 +08:00
// Draw satellite positions
final satellitePaint = Paint()..style = PaintingStyle.fill;
2024-08-01 15:13:18 +08:00
signalData!.forEach((key, value) {
if (selectedSignal[key] == true) {
satellitePaint.color = signalColorMap[key] ?? Colors.yellow;
drawGnssSignal(canvas, center, radius, value, satellitePaint, key);
2024-07-31 23:37:51 +08:00
}
2024-08-01 15:13:18 +08:00
});
2024-07-31 23:37:51 +08:00
}
void drawGnssSignal(
Canvas canvas,
Offset center,
double radius,
List<SignalGNSS> signals,
Paint paint,
2024-08-01 15:13:18 +08:00
String neme,
2024-07-31 23:37:51 +08:00
) {
for (final signal in signals) {
final int el = signal.elevation;
2024-08-01 14:08:34 +08:00
final double az = (360 - signal.azimuth + 90) * pi / 180;
2024-07-31 23:37:51 +08:00
final double r = radius * (90 - el) / 90;
final double x = center.dx + r * cos(az);
final double y = center.dy + r * sin(az);
canvas.drawCircle(Offset(x, y), satelliteRadius, paint);
2024-08-01 14:08:34 +08:00
TextPainter(
text: TextSpan(
2024-08-01 15:13:18 +08:00
text: signalPrefixList[neme] + signal.prn.toString().padLeft(2, '0'),
style: const TextStyle(color: Colors.white, fontSize: 12),
2024-08-01 14:08:34 +08:00
),
textDirection: TextDirection.ltr,
)
..layout()
..paint(canvas, Offset(x - 9, y - 7));
2024-07-31 23:37:51 +08:00
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
2024-08-01 14:08:34 +08:00
return true;
2024-07-31 23:37:51 +08:00
}
}