wgs84 és eov koordinátákat megjelenítő kártyák, eov magasság

This commit is contained in:
torok.istvan 2026-06-07 11:45:15 +02:00
parent 497821bb41
commit b85cdb2596
9 changed files with 422 additions and 1 deletions

View File

@ -0,0 +1,88 @@
enum Wgs84CoordinateFormat {
decimalDegrees,
degreesDecimalMinutes,
degreesMinutesSeconds
}
extension Wgs84CoordinateFormatLabel on Wgs84CoordinateFormat {
String get label {
switch (this) {
case Wgs84CoordinateFormat.decimalDegrees:
return 'Tizedes fok';
case Wgs84CoordinateFormat.degreesDecimalMinutes:
return 'Fok + tizedes perc';
case Wgs84CoordinateFormat.degreesMinutesSeconds:
return 'Fok - perc - másodperc';
}
}
String get shortLabel {
switch (this) {
case Wgs84CoordinateFormat.decimalDegrees:
return 'DD';
case Wgs84CoordinateFormat.degreesDecimalMinutes:
return 'DM';
case Wgs84CoordinateFormat.degreesMinutesSeconds:
return 'DMS';
}
}
}
class Wgs84CoordinateFormatter {
static String formatLatitude(
double? value,
Wgs84CoordinateFormat format,
) {
return _format(
value: value,
format: format,
positiveHemisphere: 'N',
negativeHemisphere: 'S',
);
}
static String formatLongitude(
double? value,
Wgs84CoordinateFormat format,
) {
return _format(
value: value,
format: format,
positiveHemisphere: 'E',
negativeHemisphere: 'W',
);
}
static String _format({
required double? value,
required Wgs84CoordinateFormat format,
required String positiveHemisphere,
required String negativeHemisphere,
}) {
if (value == null || value.isNaN || value.isInfinite) {
return '-';
}
final hemisphere = value >= 0 ? positiveHemisphere : negativeHemisphere;
final absValue = value.abs();
switch (format) {
case Wgs84CoordinateFormat.decimalDegrees:
return '${absValue.toStringAsFixed(8)}° $hemisphere';
case Wgs84CoordinateFormat.degreesDecimalMinutes:
final deg = absValue.floor();
final minutes = (absValue - deg) * 60.0;
return '$deg° ${minutes.toStringAsFixed(5)} $hemisphere';
case Wgs84CoordinateFormat.degreesMinutesSeconds:
final deg = absValue.floor();
final fullMinutes = (absValue - deg) * 60.0;
final min = fullMinutes.floor();
final sec = (fullMinutes - min) * 60.0;
return '$deg° $min ${sec.toStringAsFixed(3)}$hemisphere';
}
}
}

View File

@ -18,6 +18,7 @@ import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:terepi_seged/controls/geoid_grid.dart';
import 'package:terepi_seged/controls/wgs84_coordinate_formatter.dart';
import 'package:terepi_seged/enums/map_survey_mode.dart';
import 'package:terepi_seged/eov/convert_coordinate.dart';
import 'package:terepi_seged/eov/eov.dart';
@ -65,6 +66,10 @@ class MapSurveyController extends GetxController {
bool get gpsIsConnected =>
_gnss.connectionState.value == GnssConnectionState.connected;
final wgs84CoordinateFormat = Wgs84CoordinateFormat.decimalDegrees.obs;
final showWgs84Card = true.obs;
final showEovCard = true.obs;
// NTRIP állapot
RxBool get ntripIsConnected => _ntrip.isConnected;
RxInt get ntripDataPacketNumbers => _ntrip.packetCount;
@ -781,4 +786,26 @@ class MapSurveyController extends GetxController {
targetEovX.value = x;
mode.value = MapSurveyMode.stakeout;
}
void setWgs84CoordinateFormat(Wgs84CoordinateFormat format) {
wgs84CoordinateFormat.value = format;
}
void toggleShowWgs84Card() {
showWgs84Card.value = !showWgs84Card.value;
}
void toggleShowEovCard() {
showEovCard.value = !showEovCard.value;
}
String get latitudeText {
return Wgs84CoordinateFormatter.formatLatitude(
gpsLatitude.value, wgs84CoordinateFormat.value);
}
String get longitudeText {
return Wgs84CoordinateFormatter.formatLongitude(
gpsLongitude.value, wgs84CoordinateFormat.value);
}
}

View File

@ -9,6 +9,7 @@ import 'package:terepi_seged/pages/map_survey/presentations/views/settings_dialo
import 'package:terepi_seged/utils/rive_utils.dart';
import 'package:terepi_seged/widgets/coordinate_panel.dart';
import 'package:terepi_seged/widgets/map_bottom_panel.dart';
import 'package:terepi_seged/widgets/map_info_card_column.dart';
import 'package:terepi_seged/widgets/save_point_fab.dart';
import 'package:terepi_seged/widgets/shared_map_widgets.dart';
@ -32,7 +33,13 @@ class MapSurveyView extends GetView<MapSurveyController> {
],
),
Positioned(
top: 8,
top: 12,
left: 12,
child: MapInfoCardColumn(controller: controller),
),
Positioned(
top: 300,
right: 60,
left: 8,
child: CoordinatePanel(

View File

@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
class CoordinateRow extends StatelessWidget {
final String label;
final String value;
const CoordinateRow({
required this.label,
required this.value,
});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 34,
child: Text(
label,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: colorScheme.onSurfaceVariant,
fontWeight: FontWeight.w600,
),
),
),
Expanded(
child: SelectableText(
value,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontFeatures: const [
FontFeature.tabularFigures(),
],
fontWeight: FontWeight.w600,
),
),
),
],
);
}
}

View File

@ -0,0 +1,54 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
import 'package:terepi_seged/widgets/map_info_card.dart';
import 'coordinate_row.dart';
class EovCoordinateCard extends StatelessWidget {
final MapSurveyController controller;
const EovCoordinateCard({
super.key,
required this.controller,
});
@override
Widget build(BuildContext context) {
return Obx(() {
return MapInfoCard(
onClose: controller.toggleShowEovCard,
title: Row(
children: [
const Icon(Icons.grid_on, size: 18),
const SizedBox(width: 6),
Text(
'EOV',
style: Theme.of(context).textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.w700,
),
),
],
),
child: Column(
children: [
CoordinateRow(
label: 'Y',
value: controller.eovY.value.toStringAsFixed(3),
),
const SizedBox(height: 4),
CoordinateRow(
label: 'X',
value: controller.eovX.value.toStringAsFixed(3),
),
const SizedBox(height: 4),
CoordinateRow(
label: 'Z',
value: controller.eovHeight.value?.toStringAsFixed(3) ?? '-',
),
],
),
);
});
}
}

View File

@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:terepi_seged/controls/wgs84_coordinate_formatter.dart';
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
class FormatMenuButton extends StatelessWidget {
final MapSurveyController controller;
const FormatMenuButton({
required this.controller,
});
@override
Widget build(BuildContext context) {
return PopupMenuButton<Wgs84CoordinateFormat>(
tooltip: 'Koordinátaformátum',
initialValue: controller.wgs84CoordinateFormat.value,
onSelected: controller.setWgs84CoordinateFormat,
itemBuilder: (context) {
return Wgs84CoordinateFormat.values.map((format) {
return CheckedPopupMenuItem<Wgs84CoordinateFormat>(
value: format,
checked: controller.wgs84CoordinateFormat.value == format,
child: Text(format.label),
);
}).toList();
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
controller.wgs84CoordinateFormat.value.shortLabel,
style: Theme.of(context).textTheme.labelMedium?.copyWith(
fontWeight: FontWeight.w700,
),
),
const Icon(Icons.arrow_drop_down, size: 18),
],
),
),
);
}
}

View File

@ -0,0 +1,55 @@
import 'package:flutter/material.dart';
class MapInfoCard extends StatelessWidget {
final Widget title;
final Widget child;
final VoidCallback? onClose;
const MapInfoCard({
super.key,
required this.title,
required this.child,
this.onClose,
});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final screenWidth = MediaQuery.sizeOf(context).width;
return Material(
elevation: 6,
color: colorScheme.surface.withOpacity(0.64),
borderRadius: BorderRadius.circular(18),
child: Container(
width: screenWidth - 60,
padding: const EdgeInsets.fromLTRB(6, 2, 6, 2),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18),
border: Border.all(
color: colorScheme.outlineVariant.withOpacity(0.7),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
Expanded(child: title),
if (onClose != null)
IconButton(
visualDensity: VisualDensity.compact,
tooltip: 'Kártya bezárása',
icon: const Icon(Icons.close, size: 18),
onPressed: onClose,
),
],
),
const SizedBox(height: 6),
child,
],
),
),
);
}
}

View File

@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
import 'package:terepi_seged/widgets/wgs84_coordinate_card.dart';
import 'eov_coordinate_card.dart';
class MapInfoCardColumn extends StatelessWidget {
final MapSurveyController controller;
const MapInfoCardColumn({
super.key,
required this.controller,
});
@override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.sizeOf(context).height;
final screenWidth = MediaQuery.sizeOf(context).width;
return Obx(() {
final cards = <Widget>[];
if (controller.showWgs84Card.value) {
cards.add(Wgs84CoordinateCard(controller: controller));
}
if (controller.showEovCard.value) {
cards.add(EovCoordinateCard(controller: controller));
}
if (cards.isEmpty) {
return const SizedBox.shrink();
}
return ConstrainedBox(
constraints: BoxConstraints(
maxWidth: screenWidth - 50, maxHeight: screenHeight * 0.55),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
for (var i = 0; i < cards.length; i++) ...[
cards[i],
if (i != cards.length - 1) const SizedBox(height: 8)
]
],
),
));
});
}
}

View File

@ -0,0 +1,52 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
import 'map_info_card.dart';
import 'format_menu_button.dart';
import 'coordinate_row.dart';
class Wgs84CoordinateCard extends StatelessWidget {
final MapSurveyController controller;
const Wgs84CoordinateCard({
super.key,
required this.controller,
});
@override
Widget build(BuildContext context) {
return Obx(() {
return MapInfoCard(
onClose: controller.toggleShowWgs84Card,
title: Row(
children: [
const Icon(Icons.public, size: 18),
const SizedBox(width: 6),
Text(
'WGS84',
style: Theme.of(context).textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.w700,
),
),
const Spacer(),
FormatMenuButton(controller: controller),
],
),
child: Column(
children: [
CoordinateRow(
label: 'Lat',
value: controller.latitudeText,
),
const SizedBox(height: 4),
CoordinateRow(
label: 'Lon',
value: controller.longitudeText,
),
],
),
);
});
}
}