MobilApp/lib/pages/map_survey/presentations/controllers/map_survey_controller.dart

812 lines
29 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_map/flutter_map.dart';
// import 'package:flutter_map_geojson/flutter_map_geojson.dart';
import 'package:flutter_map_polywidget/flutter_map_polywidget.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
// import 'package:location/location.dart';
import 'package:latlong2/latlong.dart';
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';
import 'package:terepi_seged/models/point_to_measure.dart';
import 'package:terepi_seged/models/point_with_description_model.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:terepi_seged/pages/map_survey/presentations/views/measured_points_table_dialog.dart';
import 'package:terepi_seged/pages/ntrip_settings/presentation/controllers/ntrip_settings_controller.dart';
import 'package:terepi_seged/pages/ntrip_settings/presentation/views/ntrip_settings_sheet.dart';
import 'package:terepi_seged/services/coord_converter_service.dart';
import 'package:terepi_seged/services/gnss/gnss_connection.dart';
import 'package:terepi_seged/services/gnss/gnss_device_service.dart';
import 'package:terepi_seged/services/gnss/gnss_service.dart';
import 'package:terepi_seged/services/ntrip_service.dart';
class MapSurveyController extends GetxController {
static MapSurveyController get to => Get.find();
// ── Függőségek (service-ek) ───────────────────────────────────────
GnssService get _gnss => GnssService.to;
NtripService get _ntrip => NtripService.to;
final mode = MapSurveyMode.measure.obs;
final targetName = ''.obs;
final targetEovX = 0.0.obs;
final targetEovY = 0.0.obs;
double get deltaY => eov.value.Y - targetEovY.value;
double get deltaX => eov.value.X - targetEovX.value;
double get distanceToTarget => sqrt(deltaX * deltaX + deltaY * deltaY);
bool get isOnTarget => distanceToTarget < 0.05;
// ── GPS állapot — rövidítések a GnssService-hez ──────────────────
// Ezeket a view-ban közvetlenül a service-ből is lehetne olvasni,
// de a controller-en keresztül is hozzáférhetők a meglévő view kódhoz.
RxDouble get gpsLatitude => _gnss.latitude;
RxDouble get gpsLongitude => _gnss.longitude;
RxDouble get gpsAltitude => _gnss.altitude;
RxDouble get gpsGeoidSeparation => _gnss.geoidSeparation;
RxInt get gpsQuality => _gnss.gpsQuality;
RxDouble get gpsLatitudeError => _gnss.latitudeError;
RxDouble get gpsLongitudeError => _gnss.longitudeError;
RxDouble get gpsAltitudeError => _gnss.altitudeError;
Rx<DateTime> get gpsDateTime => _gnss.gpsDateTime;
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;
RxInt get ggaSenDataPacketNumber => _ntrip.ggaSentCount;
RxString get ggaSendLastTimeStr => _ntrip.ggaLastSentTime;
RxInt get ntripReceivedData => _ntrip.receivedBytes;
// ── Számformátumok ────────────────────────────────────────────────
final formatEov = NumberFormat('##0,000.0', 'hu-HU');
final formatEovZ = NumberFormat('###0.0', 'hu-HU');
final formatAltitudeError = NumberFormat('####0.000', 'hu-HU');
final formatEovForFile = NumberFormat('#####0.0', 'hu-HU');
final formatWgs84Sec = NumberFormat('00.000', 'hu-HU');
// ── EOV koordináták (számítottak) ─────────────────────────────────
Rx<Eov> eov = Eov(0, 0).obs;
Rx<double?> eovHeight = (0.0 as double?).obs;
final eovY = 0.0.obs;
final eovX = 0.0.obs;
// DMS formátum
RxInt latDegree = 0.obs;
RxInt latMin = 0.obs;
RxDouble latSec = 0.0.obs;
RxInt longDegree = 0.obs;
RxInt longMin = 0.obs;
RxDouble longSec = 0.0.obs;
// ── Térkép állapot ────────────────────────────────────────────────
static const double maxZoomValue = 25.0;
RxDouble currentLongitude = 0.0.obs;
RxDouble currentLatitude = 0.0.obs;
RxDouble currentZoom = 12.0.obs;
RxBool isMapMoveToCenter = true.obs;
RxBool mapIsInitialized = false.obs;
final MapController mapController = MapController();
final currentLocationMarker = <Marker>[].obs;
final pointNotesMarker = <Marker>[].obs;
final pointsToMeasureMarker = <Marker>[].obs;
final pointsToMeasureLabel = <PolyWidget>[].obs;
final pointsToMeasureDropDownMenuItem = <DropdownMenuItem<int>>[].obs;
// ── Pont adatok ───────────────────────────────────────────────────
final RxList<PointToMeasure> pointsToMeasure = <PointToMeasure>[].obs;
final RxList<PointWithDescription> pointWithDescriptionList =
<PointWithDescription>[].obs;
RxInt pointsToMeasureSelectedValue = (-1).obs;
RxDouble distance = 0.0.obs;
int pointId = 1;
String pointIdPrefix = '';
String pointIdPostfix = '';
Rx<bool> pointMeasuringDirectionForward = true.obs;
// ── Geoid grid ────────────────────────────────────────────────────
late GeoidGrid geoidGrid;
// ── Fájlok ────────────────────────────────────────────────────────
late Directory? directory;
late File dataFile;
// ── Telefon GPS fallback ──────────────────────────────────────────
StreamSubscription<Position>? _phoneLocationSub;
StreamSubscription<void>? _gnssUpdateSub;
// ── UI controllerek ───────────────────────────────────────────────
final pointIdController = TextEditingController();
final pointDescriptionController = TextEditingController();
final gpsHeightController = TextEditingController();
final pointPrefixController = TextEditingController();
final pointPostfixController = TextEditingController();
late SharedPreferences prefs;
Rx<bool> isShowPassword = false.obs;
// ── Supabase ──────────────────────────────────────────────────────
RealtimeChannel? _supaChannel;
// ─────────────────────────────────────────────────────────────────
// Lifecycle
// ─────────────────────────────────────────────────────────────────
@override
void onInit() {
super.onInit();
_initAsync();
}
Future<void> _initAsync() async {
prefs = await SharedPreferences.getInstance();
geoidGrid = await GeoidGrid.load('assets/Grids/geoid_eht2014.gtx');
NtripService.to.onRtcmData = (data) => GnssService.to.sendToReceiver(data);
_gnssUpdateSub = _gnss.onDataUpdated.listen((_) => _onGnssUpdate());
// ── Supabase realtime ─────────────────────────────────────────
_supaChannel = Supabase.instance.client
.channel('public:TerepiSeged_Receiver')
.onPostgresChanges(
event: PostgresChangeEvent.update,
schema: 'public',
table: 'TerepiSeged_Receiver',
callback: (payload) {
final id = payload.newRecord['pointNumber'] as int?;
if (id != null) updatePointStatus(id);
},
)
.subscribe();
mapIsInitialized.value = true;
}
@override
void onReady() async {
super.onReady();
await _initStorage();
gpsHeightController.text = '1.8';
}
@override
void onClose() {
_phoneLocationSub?.cancel();
_gnssUpdateSub?.cancel();
final f = _supaChannel?.unsubscribe();
if (f != null) unawaited(f);
pointIdController.dispose();
pointDescriptionController.dispose();
gpsHeightController.dispose();
pointPrefixController.dispose();
pointPostfixController.dispose();
super.onClose();
}
// ─────────────────────────────────────────────────────────────────
// GnssService frissítés kezelése
// ─────────────────────────────────────────────────────────────────
void _onGnssUpdate() {
if (!_gnss.hasValidData) return;
final lat = _gnss.latitude.value;
final lon = _gnss.longitude.value;
final alt = _gnss.altitude.value;
final sep = _gnss.geoidSeparation.value;
// EOV konverzió
final converted = ConvertCoordinate.ConvertWgsToEov(lat, lon);
eov.value = converted;
eovY.value = converted.Y.toDouble();
eovX.value = converted.X.toDouble();
eovHeight.value = geoidGrid.toEovHeight(lat, lon, alt, sep);
// DMS
latDegree.value = ConvertCoordinate.toDegree(lat);
latMin.value = ConvertCoordinate.toMinute(lat);
latSec.value = ConvertCoordinate.toSecond(lat);
longDegree.value = ConvertCoordinate.toDegree(lon);
longMin.value = ConvertCoordinate.toMinute(lon);
longSec.value = ConvertCoordinate.toSecond(lon);
// Távolság a kiválasztott ponthoz
if (pointsToMeasureSelectedValue.value >= 0 &&
pointsToMeasureSelectedValue.value < pointsToMeasure.length) {
final pt = pointsToMeasure[pointsToMeasureSelectedValue.value];
final wgs = CoordConverterService.to.eovToWgsPoint(pt.coordX, pt.coordY);
distance.value = calculateDistance(
LatLng(lat, lon),
LatLng(wgs.y, wgs.x),
);
}
// Térkép pozíció
currentLatitude.value = lat;
currentLongitude.value = lon;
_updateCurrentLocationMarker();
// NTRIP GGA küldés
NtripService.to.onGgaReceived(
_gnss.lastGgaLine.value,
_gnss.utcFix.value,
);
}
String _formatMeter(double? value, [int decimalSpace = 3]) {
if (value == null || value.isNaN || value.isInfinite) {
return '-';
}
return '${value.toStringAsFixed(decimalSpace)} m';
}
String get verticalAccuracyText {
return _formatMeter(gpsAltitudeError.value);
}
String get horizontalAccuracyText {
return _formatMeter(max(gpsLatitudeError.value, gpsLongitudeError.value));
}
void setMode(MapSurveyMode newMode) {
mode.value = newMode;
// Itt lehet módhoz kötött állapotokat állítani:
// - alsó panel tartalma
// - térképi tap viselkedés
// - aktív kártyák
// - track indítás/leállítás figyelmeztetés stb.
}
String get currentModeLabel {
switch (mode.value) {
case MapSurveyMode.browse:
return 'Térkép';
case MapSurveyMode.measure:
return 'Bemérés';
case MapSurveyMode.stakeout:
return 'Kitűzés';
case MapSurveyMode.fieldWalk:
return 'Bejárás';
}
}
IconData get currentModeIcon {
switch (mode.value) {
case MapSurveyMode.browse:
return Icons.map;
case MapSurveyMode.measure:
return Icons.add_location_alt;
case MapSurveyMode.stakeout:
return Icons.gps_fixed;
case MapSurveyMode.fieldWalk:
return Icons.hiking;
}
}
void openNtripsettings() {
if (!Get.isRegistered<NtripSettingsController>()) {
Get.put(NtripSettingsController());
}
Get.bottomSheet(const NtripSettingsSheet(),
isScrollControlled: true,
backgroundColor: Colors.transparent,
ignoreSafeArea: false);
}
void showNtripStatus() {
// Get.bottomSheet(
// const NtripStatusSheet(),
// isScrollControlled: true,
// backgroundColor: Colors.transparent,
// );
}
// ─────────────────────────────────────────────────────────────────
// Térkép vezérlők
// ─────────────────────────────────────────────────────────────────
void mapZoomIn() {
if (currentZoom.value >= maxZoomValue) return;
currentZoom.value++;
_moveMap();
}
void mapZoomOut() {
if (currentZoom.value <= 0) return;
currentZoom.value--;
_moveMap();
}
void setIsMapMoveToCenter() =>
isMapMoveToCenter.value = !isMapMoveToCenter.value;
void _moveMap() {
final lat = isMapMoveToCenter.value
? currentLatitude.value
: mapController.camera.center.latitude;
final lon = isMapMoveToCenter.value
? currentLongitude.value
: mapController.camera.center.longitude;
mapController.move(LatLng(lat, lon), currentZoom.value);
}
void _updateCurrentLocationMarker() {
currentLocationMarker.assignAll([
Marker(
point: LatLng(currentLatitude.value, currentLongitude.value),
width: 15.0,
height: 15.0,
child: Container(
width: 15.0,
height: 15.0,
decoration: BoxDecoration(
color: getCurrentLocationMarkerColor(_gnss.gpsQuality.value),
shape: BoxShape.circle,
border: Border.all(width: 1.5, color: Colors.white),
),
),
)
]);
if (isMapMoveToCenter.value) {
mapController.move(
LatLng(currentLatitude.value, currentLongitude.value),
currentZoom.value,
);
}
}
Color getCurrentLocationMarkerColor(int quality) => switch (quality) {
0 => Colors.black,
1 => Colors.red,
2 => Colors.blue,
4 => Colors.green,
5 => Colors.orange,
6 => Colors.yellow,
_ => Colors.white,
};
String getGpsQualityIndicator({required int quality}) => switch (quality) {
0 => 'Invalid',
1 => 'Standard GPS',
2 => 'Differential GPS',
4 => 'RTK Fix',
5 => 'RTK Float',
6 => 'Estimated (DR)',
_ => 'Invalid',
};
// ─────────────────────────────────────────────────────────────────
// Pont mentés dialóg
// ─────────────────────────────────────────────────────────────────
void showAddPointDialog() => onBottomNavigationBarTap(0);
void onBottomNavigationBarTap(int index) async {
if (index != 0) return;
if (pointsToMeasureSelectedValue.value >= 0 &&
pointsToMeasureSelectedValue.value < pointsToMeasure.length) {
pointIdController.text =
'${pointsToMeasure[pointsToMeasureSelectedValue.value].id}';
} else {
pointIdController.text = pointId.toString();
}
pointDescriptionController.text = '';
Get.dialog(
AlertDialog(
title: const Text('Pont rögzítése'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: pointIdController,
autofocus: true,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
border: OutlineInputBorder(), labelText: 'Azonosító'),
),
const SizedBox(height: 20),
TextField(
controller: pointDescriptionController,
decoration: const InputDecoration(
border: OutlineInputBorder(), labelText: 'Leírás'),
),
const SizedBox(height: 20),
TextField(
controller: gpsHeightController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
border: OutlineInputBorder(), labelText: 'GPS magasság'),
),
],
),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
OutlinedButton(
style:
OutlinedButton.styleFrom(minimumSize: const Size(120, 40)),
onPressed: () => Get.back(),
child:
const Text('Mégsem', style: TextStyle(color: Colors.red)),
),
OutlinedButton(
style:
OutlinedButton.styleFrom(minimumSize: const Size(120, 40)),
onPressed: _saveCurrentPoint,
child: const Text('Ment',
style: TextStyle(
color: Colors.green, fontWeight: FontWeight.bold)),
),
],
),
],
),
barrierDismissible: false,
);
}
Future<void> _saveCurrentPoint() async {
pointId = int.tryParse(pointIdController.text) ?? pointId;
// Helyi lista
pointWithDescriptionList.add(PointWithDescription(
pointId,
_gnss.gpsDateTime.value,
pointDescriptionController.text,
eov.value.Y,
eov.value.X,
_gnss.latitude.value,
_gnss.longitude.value,
max(_gnss.latitudeError.value, _gnss.longitudeError.value),
_gnss.altitudeError.value,
));
// Marker hozzáadása
pointNotesMarker.add(Marker(
point: LatLng(_gnss.latitude.value, _gnss.longitude.value),
width: 15.0,
height: 15.0,
child: Container(
width: 15.0,
height: 15.0,
decoration: BoxDecoration(
color: Colors.amber[700],
shape: BoxShape.circle,
border: Border.all(width: 1.0, color: Colors.black),
),
),
));
// Fájl mentés
await dataFile.writeAsString(
'$pointId;${_gnss.gpsDateTime.value};'
'${pointDescriptionController.text};'
'${formatEovForFile.format(eov.value.Y)};'
'${formatEovForFile.format(eov.value.X)};'
'${_gnss.latitude.value};${_gnss.longitude.value};'
'${_gnss.altitude.value};'
'${max(_gnss.latitudeError.value, _gnss.longitudeError.value)};'
'${_gnss.altitudeError.value};'
'${gpsHeightController.text}\r\n',
mode: FileMode.append,
);
// Supabase mentés
await Supabase.instance.client.from('TerepiSeged_MeasuredPoints').insert({
'pointNumber': pointId,
'gnssNumber': GnssDeviceService.to.selectedDevice.value?.name ?? '',
'latitude': _gnss.latitude.value,
'longitude': _gnss.longitude.value,
'altitude': _gnss.altitude.value,
'heightOfGeoid': _gnss.geoidSeparation.value,
'eovX': eov.value.X,
'eovY': eov.value.Y,
'poleHeight': double.tryParse(gpsHeightController.text),
'horizontalError':
max(_gnss.latitudeError.value, _gnss.longitudeError.value),
'verticalError': _gnss.altitudeError.value,
'description': pointDescriptionController.text,
'isDeleted': false,
'projectId': 2,
});
await Supabase.instance.client
.from('TerepiSeged_Receiver')
.update({'isMeasured': true}).eq('pointNumber', pointId);
// Következő pont léptetése
_advancePointSelection();
Get.back();
}
void _advancePointSelection() {
final len = pointsToMeasure.length;
if (len == 0) return;
if (pointMeasuringDirectionForward.isTrue) {
if (pointsToMeasureSelectedValue.value < len - 1) {
pointId++;
pointsToMeasureSelectedValue.value++;
} else {
_showNoMorePoints();
}
} else {
if (pointsToMeasureSelectedValue.value > 0) {
pointId--;
pointsToMeasureSelectedValue.value--;
} else {
_showNoMorePoints();
}
}
}
void _showNoMorePoints() {
ScaffoldMessenger.of(Get.context!).showSnackBar(
const SnackBar(content: Text('Nincs több bemérendő pont.')),
);
}
// ─────────────────────────────────────────────────────────────────
// Pont betöltés
// ─────────────────────────────────────────────────────────────────
void ReadPointsFromFile() async {
final result = await FilePicker.platform.pickFiles();
if (result == null) return;
final file = File(result.files.single.path!);
if (!await file.exists()) return;
_clearPoints();
final content = await file.readAsLines();
for (final (index, item) in content.indexed) {
if (index == 0) continue;
_addPointFromCsv(item, index - 1);
}
if (pointsToMeasure.isNotEmpty) {
pointsToMeasureSelectedValue.value = 0;
}
}
void readPointsFromSupa() async {
final data =
await Supabase.instance.client.from('TerepiSeged_Receiver').select();
_clearPoints();
for (int i = 0; i < data.length; i++) {
final item = data[i];
final id = item['pointNumber'];
final coordX = (item['eovX'] as num?)?.toDouble();
final coordY = (item['eovY'] as num?)?.toDouble();
if (id == null || coordX == null || coordY == null) continue;
_addPoint(id: id, coordX: coordX, coordY: coordY, listIndex: i);
}
if (pointsToMeasure.isNotEmpty) {
pointsToMeasureSelectedValue.value = 0;
}
}
void _clearPoints() {
pointsToMeasure.clear();
pointsToMeasureMarker.clear();
pointsToMeasureLabel.clear();
pointsToMeasureDropDownMenuItem.clear();
}
void _addPointFromCsv(String line, int listIndex) {
final parts = line.split(';');
if (parts.length < 3) return;
final id = int.tryParse(parts[0]);
final coordX = double.tryParse(parts[1].replaceAll(',', '.'));
final coordY = double.tryParse(parts[2].replaceAll(',', '.'));
if (id == null || coordX == null || coordY == null) return;
_addPoint(id: id, coordX: coordX, coordY: coordY, listIndex: listIndex);
}
void _addPoint({
required int id,
required double coordX,
required double coordY,
required int listIndex,
}) {
pointsToMeasure.add(PointToMeasure(id: id, coordX: coordX, coordY: coordY));
final wgs = CoordConverterService.to.eovToWgsPoint(coordX, coordY);
pointsToMeasureMarker.add(Marker(
point: LatLng(wgs.y, wgs.x),
width: 15.0,
height: 15.0,
child: Container(
width: 15.0,
height: 15.0,
decoration: BoxDecoration(
color: Colors.purple,
shape: BoxShape.circle,
border: Border.all(width: 1.0, color: Colors.black),
),
),
));
pointsToMeasureLabel.add(PolyWidget(
center: LatLng(wgs.y + 0.0000075, wgs.x + 0.0000075),
widthInMeters: 3,
heightInMeters: 3,
child: FittedBox(
child: Padding(
padding: const EdgeInsets.all(4),
child: Text(
' $id ',
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.yellow,
fontSize: 12,
),
),
),
),
));
pointsToMeasureDropDownMenuItem.add(DropdownMenuItem<int>(
value: listIndex,
child: Text('$id'),
));
}
void pointsToMeasureSelectedValueChanged(int value) =>
pointsToMeasureSelectedValue.value = value;
// ─────────────────────────────────────────────────────────────────
// Segédmetódusok
// ─────────────────────────────────────────────────────────────────
double calculateDistance(LatLng start, LatLng end) {
const r = 6371000.0;
final lat1 = start.latitude * (pi / 180);
final lon1 = start.longitude * (pi / 180);
final lat2 = end.latitude * (pi / 180);
final lon2 = end.longitude * (pi / 180);
final dLat = lat2 - lat1;
final dLon = lon2 - lon1;
final a = sin(dLat / 2) * sin(dLat / 2) +
cos(lat1) * cos(lat2) * sin(dLon / 2) * sin(dLon / 2);
return r * 2 * atan2(sqrt(a), sqrt(1 - a));
}
void updatePointStatus(int pointId) {}
void showMeasuredPointsTableDialog() =>
Get.to(() => MeasuredPointsTableDialog(), transition: Transition.fadeIn);
// ─────────────────────────────────────────────────────────────────
// Tárhely inicializálás
// ─────────────────────────────────────────────────────────────────
Future<void> _initStorage() async {
directory = await getExternalStorageDirectory();
if (directory != null && !await directory!.exists()) {
await directory!.create(recursive: true);
}
dataFile = File('${directory!.path}/data.txt');
if (!await dataFile.exists()) {
await dataFile.writeAsString(
'Id;DateTime;Description;EovX;EovY;Latitude;Longitude;Altitude;Hor.Err;Vert.Err\r\n',
);
}
}
// ─────────────────────────────────────────────────────────────────
// Export
// ─────────────────────────────────────────────────────────────────
Future<List> readMeasuredPoints() async => Supabase.instance.client
.from('TerepiSeged_MeasuredPoints')
.select()
.eq('projectId', 2)
.order('created_at');
void SaveMeasuredPointsToFile() async {
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/measuredsPoints.csv');
if (await file.exists()) await file.delete();
await file.create();
await file.writeAsString(
'Id;DateTime;Description;EovX;EovY;Altitude;Hor.Err;Vert.Err\r\n');
final data = await readMeasuredPoints();
for (final d in data) {
file.writeAsStringSync(
'${d['id']};${d['created_at']};${d['description']};'
'${formatEov.format(d['eovY'])};${formatEov.format(d['eovX'])};'
'${formatEovZ.format((d['altitude'] as num) - (d['poleHeight'] as num))};'
'${formatAltitudeError.format(d['horizontalError'])};'
'${formatAltitudeError.format(d['verticalError'])}\r\n',
mode: FileMode.append,
encoding: utf8,
);
}
await SharePlus.instance.share(ShareParams(
text: 'Mérési eredmények',
files: [XFile('${dir.path}/measuredsPoints.csv')],
subject: 'Mérési eredmények',
));
}
void switchMode(MapSurveyMode newMode) {
mode.value = newMode;
if (newMode == MapSurveyMode.measure) {
targetName.value = '';
targetEovY.value = 0;
targetEovX.value = 0;
}
}
void setTarget(String name, double y, double x) {
targetName.value = name;
targetEovY.value = y;
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);
}
}