155 lines
4.5 KiB
Dart
155 lines
4.5 KiB
Dart
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';
|
||
|
||
const signalNameList = <String>["GPS", "GLO", "GAL", "BDS", "QZS"];
|
||
const Map<String, String> signalPrefixList = {
|
||
"GPS": "G",
|
||
"GLO": "N",
|
||
"GAL": "E",
|
||
"BDS": "B",
|
||
"QZS": "Q"
|
||
};
|
||
const Map<String, Color> signalColorMap = {
|
||
"GPS": Color.fromARGB(255, 255, 0, 0),
|
||
"GLO": Color.fromARGB(255, 0, 255, 0),
|
||
"GAL": Color.fromARGB(255, 0, 0, 255),
|
||
"BDS": Color.fromARGB(255, 146, 73, 206),
|
||
"QZS": Color.fromARGB(255, 13, 179, 179),
|
||
};
|
||
|
||
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;
|
||
final size = MediaQuery.of(context).size;
|
||
return Obx(() {
|
||
controller.signalUpdate.value;
|
||
return SizedBox(
|
||
width: size.width,
|
||
height: size.height,
|
||
child: CustomPaint(
|
||
painter:
|
||
SkyPlotPainter(controller.signalData, controller.selectedSignal),
|
||
),
|
||
);
|
||
});
|
||
}
|
||
}
|
||
|
||
class SkyPlotPainter extends CustomPainter {
|
||
final SignalData? signalData;
|
||
final Map<String, bool> selectedSignal;
|
||
final satelliteRadius = 12.0;
|
||
SkyPlotPainter(this.signalData, this.selectedSignal);
|
||
|
||
@override
|
||
void paint(Canvas canvas, Size size) {
|
||
final paint = Paint()
|
||
..color = const ui.Color.fromARGB(255, 0, 0, 0)
|
||
..style = PaintingStyle.stroke
|
||
..strokeWidth = 2.0; // 设置线条的粗细,这里设置为2.0
|
||
|
||
final double radius = min(size.width / 2.4, size.height / 2);
|
||
final Offset center = Offset(size.width / 2, size.height / 2 - 5);
|
||
|
||
// 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);
|
||
|
||
String text;
|
||
if (i == 0) {
|
||
text = ' N';
|
||
} else if (i == 180) {
|
||
text = 'S';
|
||
} else {
|
||
text = '${(i + 90) % 360}';
|
||
}
|
||
TextPainter textPainter = TextPainter(
|
||
text: TextSpan(
|
||
text: text,
|
||
style: const TextStyle(color: Colors.black, fontSize: 15)),
|
||
textDirection: TextDirection.ltr,
|
||
);
|
||
textPainter.layout(); // 布局文本
|
||
// 计算文本的位置并绘制
|
||
double textX = x + 14 * cos(radians); // 向外偏移
|
||
double textY = y + 14 * sin(radians); // 向外偏移
|
||
textPainter.paint(canvas, Offset(textX - 12, textY - 8));
|
||
}
|
||
if (signalData == null) {
|
||
return;
|
||
}
|
||
// Draw satellite positions
|
||
final satellitePaint = Paint()..style = PaintingStyle.fill;
|
||
signalData!.forEach((key, value) {
|
||
if (selectedSignal[key] == true) {
|
||
satellitePaint.color = signalColorMap[key] ?? Colors.yellow;
|
||
drawGnssSignal(canvas, center, radius, value, satellitePaint, key);
|
||
}
|
||
});
|
||
}
|
||
|
||
void drawGnssSignal(
|
||
Canvas canvas,
|
||
Offset center,
|
||
double radius,
|
||
List<SignalGNSS> signals,
|
||
Paint paint,
|
||
String neme,
|
||
) {
|
||
for (final signal in signals) {
|
||
final int el = signal.elevation;
|
||
|
||
final double az = (360 - signal.azimuth + 90) * 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);
|
||
TextPainter(
|
||
text: TextSpan(
|
||
text: signalPrefixList[neme]! + signal.prn.toString().padLeft(2, '0'),
|
||
style: const TextStyle(color: Colors.white, fontSize: 12),
|
||
),
|
||
textDirection: TextDirection.ltr,
|
||
)
|
||
..layout()
|
||
..paint(canvas, Offset(x - 9, y - 7));
|
||
}
|
||
}
|
||
|
||
@override
|
||
bool shouldRepaint(covariant CustomPainter oldDelegate) {
|
||
return true;
|
||
}
|
||
}
|