diff --git a/lib/controls/geojson_parser.dart b/lib/controls/geojson_parser.dart new file mode 100644 index 0000000..12e925a --- /dev/null +++ b/lib/controls/geojson_parser.dart @@ -0,0 +1,414 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; + +import 'package:flutter_map/flutter_map.dart'; +import 'package:latlong2/latlong.dart'; + +typedef MarkerCreationCallback = Marker Function( + LatLng point, Map properties); +typedef CircleMarkerCreationCallback = CircleMarker Function( + LatLng point, Map properties); +typedef PolylineCreationCallback = Polyline Function( + List points, Map properties); +typedef PolygonCreationCallback = Polygon Function(List points, + List>? holePointsList, Map properties); +typedef FilterFunction = bool Function(Map properties); + +/// GeoJsonParser parses the GeoJson and fills three lists of parsed objects +/// which are defined in flutter_map package +/// - list of [Marker]s +/// - list of [CircleMarker]s +/// - list of [Polyline]s +/// - list of [Polygon]s +/// +/// One should pass these lists when creating adequate layers in flutter_map. +/// For details see example. +/// +/// Currently GeoJson parser supports only FeatureCollection and not GeometryCollection. +/// See the GeoJson Format specification at: https://www.rfc-editor.org/rfc/rfc7946 +/// +/// For creation of [Marker], [Polyline], [CircleMarker] and [Polygon] objects the default callback functions +/// are provided which are used in case when no user-defined callback function is provided. +/// To fully customize the [Marker], [Polyline], [CircleMarker] and [Polygon] creation one has to write his own +/// callback functions. As a template the default callback functions can be used. +/// +class GeoJsonParser { + /// list of [Marker] objects created as result of parsing + final List markers = []; + + /// list of [Polyline] objects created as result of parsing + final List polylines = []; + + /// list of [Polygon] objects created as result of parsing + final List polygons = []; + + /// list of [CircleMarker] objects created as result of parsing + final List circles = []; + + /// user defined callback function that creates a [Marker] object + MarkerCreationCallback? markerCreationCallback; + + /// user defined callback function that creates a [Polyline] object + PolylineCreationCallback? polyLineCreationCallback; + + /// user defined callback function that creates a [Polygon] object + PolygonCreationCallback? polygonCreationCallback; + + /// user defined callback function that creates a [Polygon] object + CircleMarkerCreationCallback? circleMarkerCreationCallback; + + /// default [Marker] color + Color? defaultMarkerColor; + + /// default [Marker] icon + IconData? defaultMarkerIcon; + + /// default [Polyline] color + Color? defaultPolylineColor; + + /// default [Polyline] stroke + double? defaultPolylineStroke; + + /// default [Polygon] border color + Color? defaultPolygonBorderColor; + + /// default [Polygon] fill color + Color? defaultPolygonFillColor; + + /// default [Polygon] border stroke + double? defaultPolygonBorderStroke; + + /// default flag if [Polygon] is filled (default is true) + bool? defaultPolygonIsFilled; + + /// default [CircleMarker] border color + Color? defaultCircleMarkerColor; + + /// default [CircleMarker] border stroke + Color? defaultCircleMarkerBorderColor; + + /// default flag if [CircleMarker] is filled (default is true) + bool? defaultCircleMarkerIsFilled; + + /// user defined callback function called when the [Marker] is tapped + void Function(Map)? onMarkerTapCallback; + + /// user defined callback function called when the [CircleMarker] is tapped + void Function(Map)? onCircleMarkerTapCallback; + + /// user defined callback function called during parse for filtering + FilterFunction? filterFunction; + + /// default constructor - all parameters are optional and can be set later with setters + GeoJsonParser({ + this.markerCreationCallback, + this.polyLineCreationCallback, + this.polygonCreationCallback, + this.circleMarkerCreationCallback, + this.filterFunction, + this.defaultMarkerColor, + this.defaultMarkerIcon, + this.onMarkerTapCallback, + this.defaultPolylineColor, + this.defaultPolylineStroke, + this.defaultPolygonBorderColor, + this.defaultPolygonFillColor, + this.defaultPolygonBorderStroke, + this.defaultPolygonIsFilled, + this.defaultCircleMarkerColor, + this.defaultCircleMarkerBorderColor, + this.defaultCircleMarkerIsFilled, + this.onCircleMarkerTapCallback, + }); + + /// parse GeJson in [String] format + void parseGeoJsonAsString(String g) { + return parseGeoJson(jsonDecode(g) as Map); + } + + /// set default [Marker] color + set setDefaultMarkerColor(Color color) { + defaultMarkerColor = color; + } + + /// set default [Marker] icon + set setDefaultMarkerIcon(IconData ic) { + defaultMarkerIcon = ic; + } + + /// set default [Marker] tap callback function + void setDefaultMarkerTapCallback( + Function(Map f) onTapFunction) { + onMarkerTapCallback = onTapFunction; + } + + /// set default [CircleMarker] color + set setDefaultCircleMarkerColor(Color color) { + defaultCircleMarkerColor = color; + } + + /// set default [CircleMarker] tap callback function + void setDefaultCircleMarkerTapCallback( + Function(Map f) onTapFunction) { + onCircleMarkerTapCallback = onTapFunction; + } + + /// set default [Polyline] color + set setDefaultPolylineColor(Color color) { + defaultPolylineColor = color; + } + + /// set default [Polyline] stroke + set setDefaultPolylineStroke(double stroke) { + defaultPolylineStroke = stroke; + } + + /// set default [Polygon] fill color + set setDefaultPolygonFillColor(Color color) { + defaultPolygonFillColor = color; + } + + /// set default [Polygon] border stroke + set setDefaultPolygonBorderStroke(double stroke) { + defaultPolygonBorderStroke = stroke; + } + + /// set default [Polygon] border color + set setDefaultPolygonBorderColorStroke(Color color) { + defaultPolygonBorderColor = color; + } + + /// set default [Polygon] setting whether polygon is filled + set setDefaultPolygonIsFilled(bool filled) { + defaultPolygonIsFilled = filled; + } + + /// main GeoJson parsing function + void parseGeoJson(Map g) { + // set default values if they are not specified by constructor + markerCreationCallback ??= createDefaultMarker; + circleMarkerCreationCallback ??= createDefaultCircleMarker; + polyLineCreationCallback ??= createDefaultPolyline; + polygonCreationCallback ??= createDefaultPolygon; + filterFunction ??= defaultFilterFunction; + defaultMarkerColor ??= Colors.red.withOpacity(0.8); + defaultMarkerIcon ??= Icons.location_pin; + defaultPolylineColor ??= Colors.blue.withOpacity(0.8); + defaultPolylineStroke ??= 3.0; + defaultPolygonBorderColor ??= Colors.black.withOpacity(0.8); + defaultPolygonFillColor ??= Colors.black.withOpacity(0.1); + defaultPolygonIsFilled ??= true; + defaultPolygonBorderStroke ??= 1.0; + defaultCircleMarkerColor ??= Colors.blue.withOpacity(0.25); + defaultCircleMarkerBorderColor ??= Colors.black.withOpacity(0.8); + defaultCircleMarkerIsFilled ??= true; + + // loop through the GeoJson Map and parse it + for (Map f in g['features'] as List) { + String geometryType = f['geometry']['type'].toString(); + // check if this spatial object passes the filter function + if (!filterFunction!(f['properties'] as Map)) { + continue; + } + switch (geometryType) { + case 'Point': + { + markers.add( + markerCreationCallback!( + LatLng(f['geometry']['coordinates'][1] as double, + f['geometry']['coordinates'][0] as double), + f['properties'] as Map), + ); + } + break; + case 'Circle': + { + circles.add( + circleMarkerCreationCallback!( + LatLng(f['geometry']['coordinates'][1] as double, + f['geometry']['coordinates'][0] as double), + f['properties'] as Map), + ); + } + break; + case 'MultiPoint': + { + for (final point in f['geometry']['coordinates'] as List) { + markers.add( + markerCreationCallback!( + LatLng(point[1] as double, point[0] as double), + f['properties'] as Map), + ); + } + } + break; + case 'LineString': + { + final List lineString = []; + for (final coords in f['geometry']['coordinates'] as List) { + lineString.add(LatLng(coords[1] as double, coords[0] as double)); + } + polylines.add(polyLineCreationCallback!( + lineString, f['properties'] as Map)); + } + break; + case 'MultiLineString': + { + for (final line in f['geometry']['coordinates'] as List) { + final List lineString = []; + for (final coords in line as List) { + lineString + .add(LatLng(coords[1] as double, coords[0] as double)); + } + polylines.add(polyLineCreationCallback!( + lineString, f['properties'] as Map)); + } + } + break; + case 'Polygon': + { + final List outerRing = []; + final List> holesList = []; + int pathIndex = 0; + for (final path in f['geometry']['coordinates'] as List) { + final List hole = []; + for (final coords in path as List) { + if (pathIndex == 0) { + // add to polygon's outer ring + outerRing + .add(LatLng(coords[1] as double, coords[0] as double)); + } else { + // add it to current hole + hole.add(LatLng(coords[1] as double, coords[0] as double)); + } + } + if (pathIndex > 0) { + // add hole to the polygon's list of holes + holesList.add(hole); + } + pathIndex++; + } + polygons.add(polygonCreationCallback!( + outerRing, holesList, f['properties'] as Map)); + } + break; + case 'MultiPolygon': + { + for (final polygon in f['geometry']['coordinates'] as List) { + final List outerRing = []; + final List> holesList = []; + int pathIndex = 0; + for (final path in polygon as List) { + List hole = []; + for (final coords in path as List) { + if (pathIndex == 0) { + // add to polygon's outer ring + outerRing + .add(LatLng(coords[1] as double, coords[0] as double)); + } else { + // add it to a hole + hole.add(LatLng(coords[1] as double, coords[0] as double)); + } + } + if (pathIndex > 0) { + // add to polygon's list of holes + holesList.add(hole); + } + pathIndex++; + } + polygons.add(polygonCreationCallback!(outerRing, holesList, + f['properties'] as Map)); + } + } + break; + } + } + return; + } + + /// default function for creating tappable [Marker] + Widget defaultTappableMarker(Map properties, + void Function(Map) onMarkerTap) { + return MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () { + onMarkerTap(properties); + }, + child: Icon(defaultMarkerIcon, color: defaultMarkerColor), + ), + ); + } + + /// default callback function for creating [Marker] + Marker createDefaultMarker(LatLng point, Map properties) { + return Marker( + point: point, + child: defaultTappableMarker(properties, markerTapped), + ); + } + + // /// default callback function for creating [Marker] + // Marker createDefaultMarker(LatLng point, Map properties) { + // return Marker( + // point: point, + // child: MouseRegion( + // cursor: SystemMouseCursors.click, + // child: GestureDetector( + // onTap: () { + // markerTapped(properties); + // }, + // child: Icon(defaultMarkerIcon, color: defaultMarkerColor), + // ), + // ), + // width: 60, + // height: 60, + // ); + // } + + /// default callback function for creating [Polygon] + CircleMarker createDefaultCircleMarker( + LatLng point, Map properties) { + return CircleMarker( + point: point, + radius: properties["radius"].toDouble(), + useRadiusInMeter: true, + color: defaultCircleMarkerColor!, + borderColor: defaultCircleMarkerBorderColor!, + ); + } + + /// default callback function for creating [Polyline] + Polyline createDefaultPolyline( + List points, Map properties) { + return Polyline( + points: points, + color: defaultPolylineColor!, + strokeWidth: defaultPolylineStroke!); + } + + /// default callback function for creating [Polygon] + Polygon createDefaultPolygon(List outerRing, + List>? holesList, Map properties) { + return Polygon( + points: outerRing, + holePointsList: holesList, + borderColor: defaultPolygonBorderColor!, + color: defaultPolygonFillColor!, + // isFilled: defaultPolygonIsFilled!, + borderStrokeWidth: defaultPolygonBorderStroke!, + ); + } + + /// the default filter function returns always true - therefore no filtering + bool defaultFilterFunction(Map properties) { + return true; + } + + /// default callback function called when tappable [Marker] is tapped + void markerTapped(Map map) { + if (onMarkerTapCallback != null) { + onMarkerTapCallback!(map); + } + } +} diff --git a/lib/pages/home/presentation/views/home_view.dart b/lib/pages/home/presentation/views/home_view.dart index 3d0dcb7..7f8cbb6 100644 --- a/lib/pages/home/presentation/views/home_view.dart +++ b/lib/pages/home/presentation/views/home_view.dart @@ -65,11 +65,16 @@ class HomeView extends GetView { Get.toNamed("/field_trip"); }, child: Text('Field trip')), + // TextButton( + // onPressed: () async { + // Get.toNamed("/tracking"); + // }, + // child: Text('Tracking')), TextButton( onPressed: () async { - Get.toNamed("/tracking"); + Get.toNamed("/map"); }, - child: Text('Tracking')) + child: Text('Kitűzés')) ])), Padding( padding: const EdgeInsets.only(top: 10.0), diff --git a/lib/pages/map/presentation/controllers/map_controller.dart b/lib/pages/map/presentation/controllers/map_controller.dart index 87d1494..01b985d 100644 --- a/lib/pages/map/presentation/controllers/map_controller.dart +++ b/lib/pages/map/presentation/controllers/map_controller.dart @@ -29,6 +29,7 @@ import 'package:terepi_seged/models/point_to_measure.dart'; import 'package:terepi_seged/models/point_with_description_model.dart'; import 'package:proj4dart/proj4dart.dart' as proj4; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:terepi_seged/pages/map/presentation/views/measured_points_table_dialog.dart'; class MapViewController extends GetxController { // String gpsAddress = "E8:31:CD:14:8B:B2"; @@ -59,6 +60,8 @@ class MapViewController extends GetxController { DateTime.now().add(const Duration(seconds: -30)); NumberFormat formatEov = NumberFormat("##0,000.0", "hu-HU"); + NumberFormat formatEovZ = NumberFormat("###0.0", "hu-HU"); + NumberFormat formatAltitudeError = NumberFormat("####0.000", "hu-HU"); NumberFormat formatEovForFile = NumberFormat("#####0.0", "hu-HU"); NumberFormat formatWgs84Sec = NumberFormat('00.000', 'hu-HU'); @@ -128,6 +131,8 @@ class MapViewController extends GetxController { // late StateMachineController riveGpsIconController; late SharedPreferences prefs; + Rx isShowPassword = false.obs; + final passwordFieldFocusNode = FocusNode(); late AuthResponse authResponse; late Session? session; @@ -1062,4 +1067,63 @@ class MapViewController extends GetxController { } void updatePointStatus(int pointId) {} + + void toggleShowPassword() { + isShowPassword.value = !isShowPassword.value; + if (passwordFieldFocusNode.hasPrimaryFocus) return; + passwordFieldFocusNode.canRequestFocus = false; + } + + void showMeasuredPointsTableDialog() { + Get.to(() => MeasuredPointsTableDialog(), transition: Transition.fadeIn); + } + + Future readMeasuredPoints() async { + var response = await Supabase.instance.client + .from('TerepiSeged_MeasuredPoints') + .select() + .eq('projectId', 2) + .order('created_at'); + + print(response); + + return response; + } + + void SaveMeasuredPointsToFile() async { + var pointsDirectory = await getExternalStorageDirectory(); + print(directory!.path); + // String newPath = ''; + // List folders = directory!.path.split("/"); + // for (int i = 1; i < folders.length; i++) { + // String folder = folders[i]; + // if (folder != "Android") { + // newPath += "/" + folder; + // } else { + // break; + // } + // } + // newPath = newPath + "/TerepisSegedApp"; + // directory = Directory(newPath); + if (!await pointsDirectory!.exists()) { + await pointsDirectory.create(recursive: true); + } + var measuredPointsFile = File("${directory!.path}/measuredsPoints.csv"); + + if (await pointsDirectory.exists()) { + if (!await measuredPointsFile.exists()) { + measuredPointsFile.writeAsString( + "Id;DateTime;Description;EovX;EovY;Latitude;Longitude;Altitude;Hor.Err;Vert.Err\r\n"); + } + } + + var data = await readMeasuredPoints(); + + data.forEach((d) { + print("Data EovX: ${d['EovX']}"); + print("Data EovY: $d[EovY]"); + }); + + print('Number of data: ${data.length}'); + } } diff --git a/lib/pages/map/presentation/views/map_view.dart b/lib/pages/map/presentation/views/map_view.dart index 18c13f7..1e90145 100644 --- a/lib/pages/map/presentation/views/map_view.dart +++ b/lib/pages/map/presentation/views/map_view.dart @@ -458,14 +458,7 @@ class MapView extends GetView { FloatingActionButton( onPressed: () { // controller.isMapMoveToCenter(); - // controller.addMeasuredPoint(); - ScaffoldMessenger.of(context).showSnackBar(const SnackBar( - content: Text( - "Fejlesztlés alatt", - style: TextStyle(fontWeight: FontWeight.bold), - ), - backgroundColor: Colors.black54, - )); + controller.showMeasuredPointsTableDialog(); }, heroTag: 'Database test', tooltip: 'Pont bemérése', diff --git a/lib/pages/map/presentation/views/measured_points_table_dialog.dart b/lib/pages/map/presentation/views/measured_points_table_dialog.dart new file mode 100644 index 0000000..34eec2e --- /dev/null +++ b/lib/pages/map/presentation/views/measured_points_table_dialog.dart @@ -0,0 +1,124 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:terepi_seged/pages/map/presentation/controllers/map_controller.dart'; + +class MeasuredPointsTableDialog extends StatelessWidget { + final controller = Get.find(); + MeasuredPointsTableDialog({super.key}); + + Widget build(BuildContext context) { + return Scaffold( + body: Padding( + padding: const EdgeInsets.only(top: 20.0), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row(children: [ + IconButton( + onPressed: () { + Get.back(); + }, + icon: const Icon(Icons.close)), + SizedBox( + width: 10, + ), + IconButton( + onPressed: () { + controller.SaveMeasuredPointsToFile(); + }, + icon: const Icon(Icons.save)), + ]), + TextButton( + style: ButtonStyle( + overlayColor: + MaterialStateProperty.all(Colors.transparent)), + onPressed: () { + Get.back(); + }, + child: const Text( + 'Bezár', + style: TextStyle(color: Colors.blue, fontSize: 14.0), + )) + ], + ), + ), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 40.0), + child: Text( + 'Bemért pontok', + style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold), + ), + ), + const SizedBox(height: 5), + Expanded( + child: FutureBuilder>( + future: controller.readMeasuredPoints(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Center(child: CircularProgressIndicator()); + } + + if (snapshot.hasError) { + return Center( + child: Text( + snapshot.error.toString(), + ), + ); + } + if (!snapshot.hasData) { + return const Center( + child: Text("No Data available.\n Create new Data")); + } + // print(snapshot.data); + // return const Center(child: Text("Data available.")); + return ListView.builder( + itemCount: snapshot.data!.length, + shrinkWrap: true, + itemBuilder: (context, int index) { + var data = snapshot.data![index]; + print("snapshot data:"); + print(data); + return ListTile( + leading: CircleAvatar( + backgroundColor: const Color(0xff764abc), + child: Text((index + 1).toString())), + title: Text(data['pointNumber'].toString(), + style: TextStyle(fontWeight: FontWeight.bold)), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(data['description'], + style: TextStyle( + fontStyle: FontStyle.italic, + color: Colors.grey.shade700)), + Text( + "EovX: ${controller.formatEov.format(data['eovY'])} - EovY: ${controller.formatEov.format(data['eovX'])}", + style: TextStyle( + fontStyle: FontStyle.italic, + color: Colors.grey.shade400)), + Text( + "EovZ: ${controller.formatEovZ.format(data['altitude'] - data['poleHeight'])} (m)", + style: TextStyle( + fontStyle: FontStyle.italic, + color: Colors.grey.shade400)), + Text( + "H.hiba: ${controller.formatAltitudeError.format(data['horizontalError'])} (m) - V.hiba: ${controller.formatAltitudeError.format(data['verticalError'])} (m)", + style: TextStyle( + fontStyle: FontStyle.italic, + color: Colors.grey.shade400)), + ], + )); + }); + }, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/map/presentation/views/settings_dialog.dart b/lib/pages/map/presentation/views/settings_dialog.dart index 47128d1..87aac8e 100644 --- a/lib/pages/map/presentation/views/settings_dialog.dart +++ b/lib/pages/map/presentation/views/settings_dialog.dart @@ -330,26 +330,54 @@ class SettingsDialog extends StatelessWidget { height: 40, child: TextField( controller: controller.ntripUsernameController, - decoration: const InputDecoration( - border: OutlineInputBorder(), + enableSuggestions: false, + autocorrect: false, + decoration: InputDecoration( + floatingLabelBehavior: FloatingLabelBehavior.never, + isDense: true, + filled: true, + fillColor: Colors.grey.shade300, + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(12)), labelText: 'Felhasználónév', - icon: Icon(Icons.account_circle_rounded)), + prefixIcon: Icon(Icons.account_circle_rounded)), ), ), const SizedBox(height: 10), - SizedBox( - height: 40, - child: TextField( - obscureText: true, - enableSuggestions: false, - autocorrect: false, - controller: controller.ntripPasswordController, - decoration: const InputDecoration( - border: OutlineInputBorder(), - labelText: 'Jelszó', - icon: Icon( - Icons.lock, - )), + Obx( + () => SizedBox( + height: 40, + child: TextField( + keyboardType: TextInputType.visiblePassword, + obscureText: !controller.isShowPassword.value, + focusNode: controller.passwordFieldFocusNode, + enableSuggestions: false, + autocorrect: false, + controller: controller.ntripPasswordController, + decoration: InputDecoration( + floatingLabelBehavior: FloatingLabelBehavior.never, + isDense: true, + filled: true, + fillColor: Colors.grey.shade300, + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(12)), + labelText: 'Jelszó', + prefixIcon: Icon( + Icons.lock_rounded, + size: 24, + ), + suffixIcon: Padding( + padding: const EdgeInsets.fromLTRB(0, 0, 4, 0), + child: GestureDetector( + onTap: controller.toggleShowPassword, + child: Icon( + controller.isShowPassword.value + ? Icons.visibility_rounded + : Icons.visibility_off_rounded, + size: 24)))), + ), ), ), const SizedBox(height: 20) diff --git a/lib/pages/navigation/presentation/controllers/navigation_controller.dart b/lib/pages/navigation/presentation/controllers/navigation_controller.dart index 7af6398..ae76757 100644 --- a/lib/pages/navigation/presentation/controllers/navigation_controller.dart +++ b/lib/pages/navigation/presentation/controllers/navigation_controller.dart @@ -22,6 +22,7 @@ import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart' as permission_handler; import 'package:supabase_flutter/supabase_flutter.dart'; +import 'package:terepi_seged/controls/geojson_parser.dart'; import 'package:terepi_seged/eov/convert_coordinate.dart'; import 'package:terepi_seged/eov/eov.dart'; import 'package:terepi_seged/gnss_sentences/gngga.dart'; @@ -116,7 +117,7 @@ class NavigationViewController extends GetxController { late proj4.Projection eovProj, wgsProj; RxBool mapIsInitialized = false.obs; - // GeoJsonParser parser = GeoJsonParser(defaultMarkerColor: Colors.yellow); + GeoJsonParser parser = GeoJsonParser(defaultMarkerColor: Colors.yellow); final CollectionReference _vibratorTracker = FirebaseFirestore.instance.collection('vibratorTracker'); @@ -1028,10 +1029,10 @@ class NavigationViewController extends GetxController { } if (await file!.exists()) { String data = await file.readAsString(); - // parser.defaultPolylineColor = Colors.orangeAccent; - // parser.defaultPolylineStroke = 5.0; - // parser.parseGeoJsonAsString(data); - // pathLayer = parser.polylines; + parser.defaultPolylineColor = Colors.orangeAccent; + parser.defaultPolylineStroke = 5.0; + parser.parseGeoJsonAsString(data); + pathLayer = parser.polylines; } } diff --git a/lib/pages/navigation/presentation/views/navigation_view.dart b/lib/pages/navigation/presentation/views/navigation_view.dart index 95d0a4e..be9aeb6 100644 --- a/lib/pages/navigation/presentation/views/navigation_view.dart +++ b/lib/pages/navigation/presentation/views/navigation_view.dart @@ -256,8 +256,8 @@ class NavigationView extends GetView { PolylineLayer(polylines: controller.pathLayer), MarkerLayer( markers: controller.pointsToMeasureMarker), - // PolylineLayer( - // polylines: controller.parser.polylines), + PolylineLayer( + polylines: controller.parser.polylines), PolyWidgetLayer( polyWidgets: controller.pointsToMeasureLabel), ], diff --git a/pubspec.yaml b/pubspec.yaml index 448c4e7..3d2b088 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,6 +31,7 @@ dependencies: flutter_map: ^8.2.2 flutter_map_polygon_editor: ^0.1.2 flutter_bluetooth_serial: ^0.4.0 + flutter_map_geojson2: ^1.0.2 get: ^4.7.2 latlong2: ^0.9.1 nmea: ^3.3.2 @@ -66,6 +67,7 @@ dependencies: widget_zoom: ^0.0.4 supabase_flutter: ^2.10.2 appwrite: ^20.0.0 + # share_plus: ^12.0.1 flutter: sdk: flutter