wgs84 és eov koordinátákat megjelenítő kártyák, eov magasság
This commit is contained in:
parent
497821bb41
commit
b85cdb2596
88
lib/controls/wgs84_coordinate_formatter.dart
Normal file
88
lib/controls/wgs84_coordinate_formatter.dart
Normal 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';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,6 +18,7 @@ import 'package:path_provider/path_provider.dart';
|
|||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
import 'package:terepi_seged/controls/geoid_grid.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/enums/map_survey_mode.dart';
|
||||||
import 'package:terepi_seged/eov/convert_coordinate.dart';
|
import 'package:terepi_seged/eov/convert_coordinate.dart';
|
||||||
import 'package:terepi_seged/eov/eov.dart';
|
import 'package:terepi_seged/eov/eov.dart';
|
||||||
@ -65,6 +66,10 @@ class MapSurveyController extends GetxController {
|
|||||||
bool get gpsIsConnected =>
|
bool get gpsIsConnected =>
|
||||||
_gnss.connectionState.value == GnssConnectionState.connected;
|
_gnss.connectionState.value == GnssConnectionState.connected;
|
||||||
|
|
||||||
|
final wgs84CoordinateFormat = Wgs84CoordinateFormat.decimalDegrees.obs;
|
||||||
|
final showWgs84Card = true.obs;
|
||||||
|
final showEovCard = true.obs;
|
||||||
|
|
||||||
// NTRIP állapot
|
// NTRIP állapot
|
||||||
RxBool get ntripIsConnected => _ntrip.isConnected;
|
RxBool get ntripIsConnected => _ntrip.isConnected;
|
||||||
RxInt get ntripDataPacketNumbers => _ntrip.packetCount;
|
RxInt get ntripDataPacketNumbers => _ntrip.packetCount;
|
||||||
@ -781,4 +786,26 @@ class MapSurveyController extends GetxController {
|
|||||||
targetEovX.value = x;
|
targetEovX.value = x;
|
||||||
mode.value = MapSurveyMode.stakeout;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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/utils/rive_utils.dart';
|
||||||
import 'package:terepi_seged/widgets/coordinate_panel.dart';
|
import 'package:terepi_seged/widgets/coordinate_panel.dart';
|
||||||
import 'package:terepi_seged/widgets/map_bottom_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/save_point_fab.dart';
|
||||||
import 'package:terepi_seged/widgets/shared_map_widgets.dart';
|
import 'package:terepi_seged/widgets/shared_map_widgets.dart';
|
||||||
|
|
||||||
@ -32,7 +33,13 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 8,
|
top: 12,
|
||||||
|
left: 12,
|
||||||
|
child: MapInfoCardColumn(controller: controller),
|
||||||
|
),
|
||||||
|
|
||||||
|
Positioned(
|
||||||
|
top: 300,
|
||||||
right: 60,
|
right: 60,
|
||||||
left: 8,
|
left: 8,
|
||||||
child: CoordinatePanel(
|
child: CoordinatePanel(
|
||||||
|
|||||||
43
lib/widgets/coordinate_row.dart
Normal file
43
lib/widgets/coordinate_row.dart
Normal 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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
54
lib/widgets/eov_coordinate_card.dart
Normal file
54
lib/widgets/eov_coordinate_card.dart
Normal 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) ?? '-',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
44
lib/widgets/format_menu_button.dart
Normal file
44
lib/widgets/format_menu_button.dart
Normal 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),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
55
lib/widgets/map_info_card.dart
Normal file
55
lib/widgets/map_info_card.dart
Normal 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,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
51
lib/widgets/map_info_card_column.dart
Normal file
51
lib/widgets/map_info_card_column.dart
Normal 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)
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
52
lib/widgets/wgs84_coordinate_card.dart
Normal file
52
lib/widgets/wgs84_coordinate_card.dart
Normal 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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user