Terepbejárás oldalon vonal és terület tulajdonságainak szerkesztése, mentés
This commit is contained in:
@@ -8,6 +8,7 @@ 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_polygon_editor/polygon_editor/polygon_editor_controller.dart';
|
||||
// import 'package:flutter_map_geojson/flutter_map_geojson.dart';
|
||||
import 'package:flutter_map_polywidget/flutter_map_polywidget.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
@@ -20,6 +21,7 @@ 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_edit_tool.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';
|
||||
@@ -35,6 +37,7 @@ 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';
|
||||
import 'package:terepi_seged/widgets/map_edit_tools/map_feature_save_sheet.dart';
|
||||
|
||||
class MapSurveyController extends GetxController {
|
||||
static MapSurveyController get to => Get.find();
|
||||
@@ -159,6 +162,26 @@ class MapSurveyController extends GetxController {
|
||||
// ── Supabase ──────────────────────────────────────────────────────
|
||||
RealtimeChannel? _supaChannel;
|
||||
|
||||
// ------- Map edit ----------------
|
||||
final activeEditTool = MapEditTool.none.obs;
|
||||
final editorPointCount = 0.obs;
|
||||
final pointNotes = <Marker>[].obs;
|
||||
final polylineNotes = <Polyline<Object>>[].obs;
|
||||
final polygonNotes = <Polygon<Object>>[].obs;
|
||||
|
||||
late final PolygonEditorController polygonEditorController;
|
||||
|
||||
final activeEditColor = const Color(0xFF185FA5).obs;
|
||||
final activeEditOpacity = 0.5.obs;
|
||||
final activeEditStrokeWidth = 3.0.obs;
|
||||
final activeEditStrokeColor = const Color(0xFFFFD700).obs;
|
||||
final activeEditLabel = ''.obs;
|
||||
|
||||
final PolygonLabelPlacementCalculator _labelPlacementCalculator =
|
||||
const PolygonLabelPlacementCalculator.centroid();
|
||||
|
||||
bool get isMapEditing => activeEditTool.value != MapEditTool.none;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
// Lifecycle
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
@@ -190,6 +213,12 @@ class MapSurveyController extends GetxController {
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
polygonEditorController =
|
||||
PolygonEditorController(mode: PolygonEditorMode.polygon);
|
||||
polygonEditorController.addListener(() {
|
||||
editorPointCount.value = polygonEditorController.points.length;
|
||||
});
|
||||
|
||||
mapIsInitialized.value = true;
|
||||
}
|
||||
|
||||
@@ -214,6 +243,7 @@ class MapSurveyController extends GetxController {
|
||||
gpsHeightController.dispose();
|
||||
pointPrefixController.dispose();
|
||||
pointPostfixController.dispose();
|
||||
polygonEditorController.dispose();
|
||||
|
||||
super.onClose();
|
||||
}
|
||||
@@ -846,4 +876,202 @@ class MapSurveyController extends GetxController {
|
||||
|
||||
return '${value.toStringAsFixed(1)}m';
|
||||
}
|
||||
|
||||
// --------- Térkép szerkesztési műveletek
|
||||
IconData get activeEditToolIcon {
|
||||
switch (activeEditTool.value) {
|
||||
case MapEditTool.point:
|
||||
return Icons.add_location_alt_outlined;
|
||||
case MapEditTool.line:
|
||||
return Icons.polyline_outlined;
|
||||
case MapEditTool.polygon:
|
||||
return Icons.border_outer_outlined;
|
||||
case MapEditTool.none:
|
||||
return Icons.edit_location_alt_outlined;
|
||||
}
|
||||
}
|
||||
|
||||
String get activeEditToolTitle {
|
||||
switch (activeEditTool.value) {
|
||||
case MapEditTool.point:
|
||||
return 'Pont hozzáadása';
|
||||
case MapEditTool.line:
|
||||
return 'Vonal rögzítése';
|
||||
case MapEditTool.polygon:
|
||||
return 'Terület rögzítése';
|
||||
case MapEditTool.none:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
String get activeEditToolHint {
|
||||
switch (activeEditTool.value) {
|
||||
case MapEditTool.point:
|
||||
return 'Koppints a térképre a pont helyéhez.';
|
||||
case MapEditTool.line:
|
||||
return 'Hosszan nyomj a térképre a töréspontokhoz';
|
||||
case MapEditTool.polygon:
|
||||
return 'Hosszan nyomj a térképre a sarokpontokhoz.';
|
||||
case MapEditTool.none:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
bool get canFinishGeometry {
|
||||
switch (activeEditTool.value) {
|
||||
case MapEditTool.point:
|
||||
return editorPointCount == 1;
|
||||
case MapEditTool.line:
|
||||
return editorPointCount >= 2;
|
||||
case MapEditTool.polygon:
|
||||
return editorPointCount >= 3;
|
||||
case MapEditTool.none:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String get finishButtonText {
|
||||
switch (activeEditTool.value) {
|
||||
case MapEditTool.point:
|
||||
return 'Kész';
|
||||
case MapEditTool.line:
|
||||
return 'Kész';
|
||||
case MapEditTool.polygon:
|
||||
return 'Lezárás';
|
||||
case MapEditTool.none:
|
||||
return 'Kész';
|
||||
}
|
||||
}
|
||||
|
||||
void startPointTool() {
|
||||
activeEditTool.value = MapEditTool.point;
|
||||
}
|
||||
|
||||
void startLineTool() {
|
||||
polygonEditorController.clear();
|
||||
polygonEditorController.setMode(PolygonEditorMode.line);
|
||||
activeEditTool.value = MapEditTool.line;
|
||||
}
|
||||
|
||||
void startPolygonTool() {
|
||||
polygonEditorController.clear();
|
||||
polygonEditorController.setMode(PolygonEditorMode.polygon);
|
||||
activeEditTool.value = MapEditTool.polygon;
|
||||
}
|
||||
|
||||
void cancelEditing() {
|
||||
polygonEditorController.clear();
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
}
|
||||
|
||||
void openFeatureList() {
|
||||
// TODO: DraggableScrollableSheet / bottom sheet lista
|
||||
}
|
||||
|
||||
void openLayerPanel() {
|
||||
// TODO: rétegek sheet
|
||||
}
|
||||
|
||||
void finishGeometry() {
|
||||
if (!canFinishGeometry) return;
|
||||
|
||||
// Itt nyisd majd meg a szerkesztő sheetet:
|
||||
// openFeatureEditorSheet();
|
||||
|
||||
// Példa:
|
||||
// Get.bottomSheet(
|
||||
// FeatureEditorSheet(
|
||||
// tool: activeTool.value,
|
||||
// points: List<LatLng>.from(draftPoints),
|
||||
// ),
|
||||
// isScrollControlled: true,
|
||||
// );
|
||||
|
||||
Get.bottomSheet(
|
||||
DraggableScrollableSheet(
|
||||
initialChildSize: 0.52,
|
||||
minChildSize: 0.35,
|
||||
maxChildSize: 0.85,
|
||||
snap: true,
|
||||
snapSizes: const [0.35, 0.52, 0.85],
|
||||
expand: false,
|
||||
builder: (_, scrollCtrl) =>
|
||||
MapFeatureSaveSheet(ctrl: this, scrollCtrl: scrollCtrl)),
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
ignoreSafeArea: false);
|
||||
|
||||
//activeEditTool.value = MapEditTool.none;
|
||||
//draftPoints.clear();
|
||||
}
|
||||
|
||||
Future<void> finishDraft() async {
|
||||
if (polygonEditorController.mode == PolygonEditorMode.line) {
|
||||
print("Points number in line: ${polygonEditorController.points.length}");
|
||||
print(
|
||||
"1. point coords: ${polygonEditorController.points[0].latitude} - ${polygonEditorController.points[0].longitude}");
|
||||
if (polygonEditorController.points.length < 2) return;
|
||||
|
||||
Polyline polyline = Polyline(
|
||||
points: List.from(polygonEditorController.points),
|
||||
color: activeEditColor.value,
|
||||
strokeWidth: activeEditStrokeWidth.value,
|
||||
// hitValue: (
|
||||
// title: 'Purple Line',
|
||||
// subtitle: 'Nothing really special here...',
|
||||
// ),
|
||||
);
|
||||
polylineNotes.add(polyline);
|
||||
// polylineNotes.refresh();
|
||||
|
||||
print("Points number in polylineNotes: ${polylineNotes.length}");
|
||||
print(
|
||||
"1. point coords of polyline: ${polyline.points[0].latitude} - ${polyline.points[0].longitude}");
|
||||
|
||||
polygonEditorController.clear();
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
}
|
||||
if (polygonEditorController.mode == PolygonEditorMode.polygon) {
|
||||
print(
|
||||
"Points number in polygon: ${polygonEditorController.points.length}");
|
||||
|
||||
Polygon polygon = Polygon(
|
||||
points: List.from(polygonEditorController.points),
|
||||
color: activeEditColor.value.withValues(alpha: activeEditOpacity.value),
|
||||
borderColor: activeEditStrokeColor.value,
|
||||
borderStrokeWidth: activeEditStrokeWidth.value,
|
||||
label: activeEditLabel.value,
|
||||
labelPlacementCalculator: _labelPlacementCalculator,
|
||||
// hitValue: (
|
||||
// title: 'Basic Filled Polygon',
|
||||
// subtitle: 'Nothing really special here...',
|
||||
);
|
||||
|
||||
polygonNotes.add(polygon);
|
||||
//polygonNotes.refresh();
|
||||
//update();
|
||||
|
||||
print("Points number in polygonNotes: ${polygonNotes.length}");
|
||||
|
||||
polygonEditorController.clear();
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
}
|
||||
}
|
||||
|
||||
void saveEditedPoint({required LatLng point}) {
|
||||
Marker marker = Marker(
|
||||
point: point,
|
||||
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)),
|
||||
));
|
||||
pointNotes.add(marker);
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map_polygon_editor/polygon_editor/polygon_editor.dart';
|
||||
import 'package:flutter_map_polywidget/flutter_map_polywidget.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:terepi_seged/enums/map_edit_tool.dart';
|
||||
import 'package:terepi_seged/enums/map_survey_mode.dart';
|
||||
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
|
||||
import 'package:terepi_seged/pages/map_survey/presentations/views/settings_dialog.dart';
|
||||
@@ -10,6 +12,8 @@ import 'package:terepi_seged/pages/tracking/presentation/controllers/tracking_co
|
||||
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_edit_tools/map_edit_drawing_toolbar.dart';
|
||||
import 'package:terepi_seged/widgets/map_edit_tools/map_edit_toolbar.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';
|
||||
@@ -28,6 +32,15 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
||||
onZoomIn: controller.mapZoomIn,
|
||||
onZoomOut: controller.mapZoomOut,
|
||||
onCenterOnGps: controller.isMapMoveToCenter,
|
||||
onLongPress: (tapPosition, point) {
|
||||
if (controller.activeEditTool.value == MapEditTool.point) {
|
||||
controller.saveEditedPoint(point: point);
|
||||
}
|
||||
if (controller.activeEditTool.value == MapEditTool.line ||
|
||||
controller.activeEditTool.value == MapEditTool.polygon) {
|
||||
controller.polygonEditorController.addPoint(point);
|
||||
}
|
||||
},
|
||||
layers: [
|
||||
Obx(() =>
|
||||
MarkerLayer(markers: controller.currentLocationMarker.toList())),
|
||||
@@ -41,6 +54,36 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
||||
} else {
|
||||
return _buildTrackLayer();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return PolygonEditor(
|
||||
controller: controller.polygonEditorController,
|
||||
throttleDuration: Duration.zero);
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return MarkerLayer(markers: [...controller.pointNotes]);
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return PolylineLayer(polylines: [...controller.polylineNotes]);
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return PolygonLayer(
|
||||
polygons: [...controller.polygonNotes], useAltRendering: true);
|
||||
})
|
||||
],
|
||||
),
|
||||
@@ -50,23 +93,40 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
||||
child: MapInfoCardColumn(controller: controller),
|
||||
),
|
||||
|
||||
Positioned(
|
||||
top: 390,
|
||||
right: 60,
|
||||
left: 8,
|
||||
child: CoordinatePanel(
|
||||
eovY: controller.eovY,
|
||||
eovX: controller.eovX,
|
||||
horError: controller.gpsLatitudeError,
|
||||
vertError: controller.gpsAltitudeError,
|
||||
altitudeMsl: controller.gpsAltitude,
|
||||
geoidSeparation: controller.gpsGeoidSeparation,
|
||||
ntripConnected: controller.ntripIsConnected,
|
||||
ntripBytes: controller.ntripReceivedData,
|
||||
ntripPackets: controller.ntripDataPacketNumbers,
|
||||
ggaPackets: controller.ggaSenDataPacketNumber,
|
||||
),
|
||||
),
|
||||
// Positioned(
|
||||
// top: 390,
|
||||
// right: 60,
|
||||
// left: 8,
|
||||
// child: CoordinatePanel(
|
||||
// eovY: controller.eovY,
|
||||
// eovX: controller.eovX,
|
||||
// horError: controller.gpsLatitudeError,
|
||||
// vertError: controller.gpsAltitudeError,
|
||||
// altitudeMsl: controller.gpsAltitude,
|
||||
// geoidSeparation: controller.gpsGeoidSeparation,
|
||||
// ntripConnected: controller.ntripIsConnected,
|
||||
// ntripBytes: controller.ntripReceivedData,
|
||||
// ntripPackets: controller.ntripDataPacketNumbers,
|
||||
// ggaPackets: controller.ggaSenDataPacketNumber,
|
||||
// ),
|
||||
// ),
|
||||
Obx(() {
|
||||
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
if (controller.activeEditTool.value == MapEditTool.none) {
|
||||
return Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: MapEditCompactToolbar(controller: controller));
|
||||
}
|
||||
return Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: MapEditDrawingToolbar(controller: controller));
|
||||
})
|
||||
// Positioned(top: 8, left: 0, right: 0, child: _ModeSelector()),
|
||||
// Positioned(
|
||||
// bottom: 80,
|
||||
|
||||
Reference in New Issue
Block a user