From dcfd9c626836e5f441605cb2733b25c2ac5f068e Mon Sep 17 00:00:00 2001 From: Holy Date: Wed, 31 Jul 2024 23:37:51 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ssController.dart => gnss_controller.dart} | 25 +- lib/main.dart | 15 +- lib/quality/singlebutton.dart | 2 +- lib/sky/mulbutton.dart | 18 +- lib/sky/skyInfo.dart | 120 ------- lib/sky/skyPlot.dart | 250 ------------- lib/sky/sky_info.dart | 122 +++++++ lib/sky/sky_plot.dart | 336 ++++++++++++++++++ pubspec.lock | 10 +- pubspec.yaml | 2 +- 10 files changed, 499 insertions(+), 401 deletions(-) rename lib/Controller/{gnssController.dart => gnss_controller.dart} (57%) delete mode 100644 lib/sky/skyInfo.dart delete mode 100644 lib/sky/skyPlot.dart create mode 100644 lib/sky/sky_info.dart create mode 100644 lib/sky/sky_plot.dart diff --git a/lib/Controller/gnssController.dart b/lib/Controller/gnss_controller.dart similarity index 57% rename from lib/Controller/gnssController.dart rename to lib/Controller/gnss_controller.dart index e926e96..8144f31 100644 --- a/lib/Controller/gnssController.dart +++ b/lib/Controller/gnss_controller.dart @@ -1,26 +1,30 @@ -import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:get/get.dart'; import 'package:gnss/gnss.dart'; class GnssController extends GetxController { - late Gnss gnss; + late final Gnss gnss; LocationData? locationData; SignalData? signalData; var locationUpdate = 0.obs; var singnalUpdate = 0.obs; - // var _selectedSignal = []; - Map selectedSignal = {}; - // List get selectedSignal => _selectedSignal; - // set selectedSignal(Set value) { - // _selectedSignal = value; - // update(); - // } + + // Map selectedSignal = { + // "GPS": true, + // "GLONASS": true, + // "GALILEO": true, + // "BEIDOU": true, + // "QZSS": true, + // "SBAS": true, + // }.obs; + final selectedSignal = [true, true, true, true, true, true].obs; @override void onInit() async { super.onInit(); - gnss = Gnss(port: "/dev/ttysWK2", baudrate: 115200); + // gnss = Gnss(port: "/dev/ttysWK2", baudrate: 115200); + gnss = Gnss(port: "COM1", baudrate: 115200); gnss.start(); gnss.locationStream.listen((location) { locationData = location; @@ -34,7 +38,6 @@ class GnssController extends GetxController { @override void dispose() { - // TODO: implement dispose gnss.dispose(); super.dispose(); } diff --git a/lib/main.dart b/lib/main.dart index 2e33f74..8a83730 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,11 +1,10 @@ -import 'dart:math'; - import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:gnss/gnss.dart'; +// import 'package:gnss/gnss.dart'; -import 'sky/skyplot.dart'; -import 'Controller/gnssController.dart'; // Import the correct file location for GnssController +import 'sky/sky_plot.dart'; +import 'sky/sky_info.dart'; +import 'Controller/gnss_controller.dart'; // Import the correct file location for GnssController // void main() { // Get.lazyPut(() => GnssController(), tag: 'gnss'); @@ -44,7 +43,7 @@ import 'Controller/gnssController.dart'; // Import the correct file location for // } void main() { - Get.lazyPut(() => GnssController(), tag: 'gnss'); + Get.put(GnssController()); runApp(MyApp()); } @@ -71,13 +70,13 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { - final con = Get.find(tag: 'gnss'); + // final con = Get.find(); return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('天空图'), ), - body: SkyPlotPage(), + body: SkyInfo(), )); } } diff --git a/lib/quality/singlebutton.dart b/lib/quality/singlebutton.dart index 4c817e1..295e661 100644 --- a/lib/quality/singlebutton.dart +++ b/lib/quality/singlebutton.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; class SingleButton extends StatefulWidget { - final controller = Get.find(tag: 'gnss'); + // final controller = Get.find(tag: 'gnss'); final List colors; final Function(Color) onSelectionChanged; diff --git a/lib/sky/mulbutton.dart b/lib/sky/mulbutton.dart index 17cae08..5ff7de3 100644 --- a/lib/sky/mulbutton.dart +++ b/lib/sky/mulbutton.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; class MulButton extends StatefulWidget { - final controller = Get.find(tag: 'gnss'); + // final controller = Get.find(tag: 'gnss'); final List colors; - final Function(List) onSelectionChanged; + final Function(int, bool) onSelectionChanged; MulButton({ required this.colors, @@ -27,13 +27,13 @@ class _MulButtonState extends State { void updateSelection(int index, bool value) { setState(() { selectedColors[index] = value; - List selected = []; - for (int i = 0; i < selectedColors.length; i++) { - if (selectedColors[i]) { - selected.add(widget.colors[i]); - } - } - widget.onSelectionChanged(selected); // 通知父组件 + // List selected = []; + // for (int i = 0; i < selectedColors.length; i++) { + // if (selectedColors[i]) { + // selected.add(widget.colors[i]); + // } + // } + widget.onSelectionChanged(index, value); // 通知父组件 }); } diff --git a/lib/sky/skyInfo.dart b/lib/sky/skyInfo.dart deleted file mode 100644 index cd8a54a..0000000 --- a/lib/sky/skyInfo.dart +++ /dev/null @@ -1,120 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:gnssview/sky/device_type.dart'; -import '../Controller/gnssController.dart'; -import 'mulbutton.dart'; - -class SkyInfo extends StatelessWidget { - late GnssController controller; - // final String lat; // 纬度 - // final String lon; // 经度 - // final String hdop; // 高程 - // final int status; // 定位状态 - // final int view; // 可见 - // final int use; // 使用 - // final String time; // 时间 - - SkyInfo() { - controller = Get.find(tag: 'gnss'); - } - - @override - Widget build(BuildContext context) { - final isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; - - return Theme( - data: ThemeData( - textTheme: const TextTheme( - titleLarge: TextStyle( - fontSize: 30, - fontWeight: FontWeight.normal, - ), - ), - ), - child: Container( - margin: const EdgeInsets.only(left: 5), - padding: const EdgeInsets.symmetric(vertical: 20), - alignment: Alignment.centerLeft, - child: - Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - // 创建行项的函数 - rowItem(context, "北纬:", '${controller.locationData?.latitude} '), - rowItem(context, "东经:", '${controller.locationData?.longitude}'), - rowItem(context, "高程:", '${controller.locationData?.altitude}'), - rowItem(context, "水平定位精度:", '${controller.locationData?.hdop}'), - rowItem(context, "垂直定位精度:", '${controller.locationData?.vdop}'), - rowItem(context, "定位状态:", '${controller.locationData?.fixQuality}'), - rowItem(context, "可见卫星数:", '${controller.locationData?.numberSv}'), - rowItem(context, "使用卫星数:", '${controller.locationData?.numberSa}'), - rowItem(context, "时间:", '${controller.locationData?.time}'), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - MulButton( - colors: const [ - Colors.blue, - Colors.red, - Colors.green, - Colors.orange - ], - onSelectionChanged: (selectedColors) { - // 处理选中的颜色 - print('选中的颜色: $selectedColors'); - }, - ), - ], - ), - ]), - )); - } - - Widget rowItem(BuildContext context, String title, String text) => Row( - children: [ - FixedWidthTextWidget( - width: 80, - text: title, - style: Theme.of(context).textTheme.titleLarge, - ), - Text( - text, - style: Theme.of(context).textTheme.titleLarge, - ), - ], - ); -} - -class FixedWidthTextWidget extends StatelessWidget { - final String text; - final double width; - final TextStyle? style; - - FixedWidthTextWidget({ - super.key, - required this.text, - this.width = 80, - this.style, - }); - TextStyle? textStyle; - @override - Widget build(BuildContext context) { - final deviceType = getDeviceType(context); - double dynamicWidth = deviceType == DeviceType.mobile ? 0 : 50; - - if (style != null) { - textStyle = - style!.copyWith(fontSize: deviceType == DeviceType.mobile ? 16 : 20); - } else { - textStyle = - TextStyle(fontSize: deviceType == DeviceType.mobile ? 16 : 20); - } - return Container( - margin: const EdgeInsets.symmetric(horizontal: 3), - width: width + dynamicWidth, - child: Text( - text, - style: textStyle, - ), - ); - } -} diff --git a/lib/sky/skyPlot.dart b/lib/sky/skyPlot.dart deleted file mode 100644 index 6f4272f..0000000 --- a/lib/sky/skyPlot.dart +++ /dev/null @@ -1,250 +0,0 @@ -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(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 imageList = {}; - @override - SkyPlotPage() { - controller = Get.find(tag: 'gnss'); - } - Future 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; -} diff --git a/lib/sky/sky_info.dart b/lib/sky/sky_info.dart new file mode 100644 index 0000000..9edbc28 --- /dev/null +++ b/lib/sky/sky_info.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:intl/intl.dart'; +import 'package:gnssview/sky/device_type.dart'; +import '../Controller/gnss_controller.dart'; +import 'mulbutton.dart'; + +class SkyInfo extends StatelessWidget { + late final GnssController controller; + + SkyInfo({super.key}) { + controller = Get.find(); + } + + @override + Widget build(BuildContext context) { + final isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + + return Theme( + data: ThemeData( + textTheme: const TextTheme( + titleLarge: TextStyle( + fontSize: 30, + fontWeight: FontWeight.normal, + ), + ), + ), + child: Container( + margin: const EdgeInsets.only(left: 5), + padding: const EdgeInsets.symmetric(vertical: 20), + alignment: Alignment.centerLeft, + child: Obx(() { + controller.locationUpdate.value; + final location = controller.locationData; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 创建行项的函数 + rowItem(context, "纬度:", '${location?.latitude}'), + rowItem(context, "经度:", '${location?.longitude}'), + rowItem(context, "高程:", '${location?.altitude}'), + rowItem(context, "水平精度:", '${location?.hdop}'), + rowItem(context, "垂直精度:", '${location?.vdop}'), + rowItem(context, "定位状态:", '${location?.fixQuality}'), + rowItem(context, "可见卫星数:", '${location?.numberSv}'), + rowItem(context, "使用卫星数:", '${location?.numberSa}'), + rowItem( + context, + "时间:", + location == null + ? 'null' + : DateFormat('yyyy-MM-dd HH:mm:ss') + .format(location.time)), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + MulButton( + colors: const [ + Colors.blue, + Colors.red, + Colors.green, + Colors.orange + ], + onSelectionChanged: (int index, bool value) { + controller.selectedSignal[index] = value; + }, + ), + ], + ), + ]); + }))); + } + + Widget rowItem(BuildContext context, String title, String text) => Row( + children: [ + FixedWidthText( + width: 80, + text: title, + style: Theme.of(context).textTheme.titleLarge, + ), + Text( + text, + style: Theme.of(context).textTheme.titleLarge, + ), + ], + ); +} + +class FixedWidthText extends StatelessWidget { + final String text; + final double width; + final TextStyle? style; + const FixedWidthText({ + super.key, + required this.text, + this.width = 80, + this.style, + }); + + @override + Widget build(BuildContext context) { + final deviceType = getDeviceType(context); + double dynamicWidth = deviceType == DeviceType.mobile ? 0 : 50; + TextStyle textStyle; + if (style != null) { + textStyle = + style!.copyWith(fontSize: deviceType == DeviceType.mobile ? 16 : 20); + } else { + textStyle = + TextStyle(fontSize: deviceType == DeviceType.mobile ? 16 : 20); + } + return Container( + margin: const EdgeInsets.symmetric(horizontal: 3), + width: width + dynamicWidth, + child: Text( + text, + style: textStyle, + ), + ); + } +} diff --git a/lib/sky/sky_plot.dart b/lib/sky/sky_plot.dart new file mode 100644 index 0000000..eec7008 --- /dev/null +++ b/lib/sky/sky_plot.dart @@ -0,0 +1,336 @@ +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:flutter/widgets.dart'; +import 'package:get/get.dart'; +import 'package:gnss/gnss.dart'; + +import '../Controller/gnss_controller.dart'; + +const signalNameList = ["GPS", "GLONASS", "GALILEO", "BEIDOU", "QZSS"]; +const List signalColorList = [ + Color.fromARGB(255, 255, 0, 0), + Color.fromARGB(255, 0, 255, 0), + Color.fromARGB(255, 0, 0, 255), + Color.fromARGB(255, 255, 255, 0), + Color.fromARGB(255, 0, 255, 255) +]; + +// 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(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 imageList = {}; + @override + SkyPlotPage({super.key}) { + controller = Get.find(); + } + Future 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; + final signalGNSS = [ + controller.signalData?.GPS, + controller.signalData?.GLO, + controller.signalData?.GAL, + controller.signalData?.BDS, + controller.signalData?.QZSS, + ]; + return CustomPaint( + painter: SkyPlotPainter(signalGNSS, controller.selectedSignal), + ); + }); + } +} + +// 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 { + final List?> signalGNSS; + final List selectedSignal; + final satelliteRadius = 20.0; + SkyPlotPainter(this.signalGNSS, this.selectedSignal); + + @override + void paint(Canvas canvas, Size size) { + final paint = Paint() + ..color = Colors.blue + ..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); + } + + // Draw satellite positions + final satellitePaint = Paint()..style = PaintingStyle.fill; + + for (int i = 0; i < signalGNSS.length; i++) { + final signalData = signalGNSS[i]; + if (!selectedSignal[i] || signalData == null) { + continue; + } + satellitePaint.color = signalColorList[i]; + drawGnssSignal(canvas, center, radius, signalData, satellitePaint); + } + } + + void drawGnssSignal( + Canvas canvas, + Offset center, + double radius, + List signals, + Paint paint, + ) { + for (final signal in signals) { + final int el = signal.elevation; + final double az = signal.azimuth * pi / 180; + + 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); + } + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) { + return false; + } +} diff --git a/pubspec.lock b/pubspec.lock index a323c16..49e53f7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -120,10 +120,18 @@ packages: description: path: "." ref: main - resolved-ref: "6e4c9b35dc86d027a0f0bfbc65747a4813d92a2c" + resolved-ref: "05b6cd1985ad7f13a487820f4cfa1e9622e2daae" url: "https://git.mcxa.cn:89/flutter/gnss.git" source: git version: "0.0.1" + intl: + dependency: "direct main" + description: + name: intl + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" + source: hosted + version: "0.17.0" leak_tracker: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9466211..98401ac 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -34,7 +34,7 @@ dependencies: git: url: https://git.mcxa.cn:89/flutter/gnss.git ref: main - + intl: ^0.17.0 # libserialport: # path: plugins/libserialport