Home > other >  How to draw SVG polygon on openStreetMap programitically in flutter
How to draw SVG polygon on openStreetMap programitically in flutter

Time:06-16

Hello I want to use this api nominatim.org to find svg shape and latLng coordiante of one address. I called this api in flutter and try to show it by Polygon in my flutter code in open street map this is my code

late PolyEditor polyEditor;

List<Polygon> polygons = [];
var testPolygon = Polygon(
  color: Colors.black.withOpacity(0.3),
  points: [],
  borderColor: Colors.black,
  isFilled: true,
  borderStrokeWidth: 1.0);

@override
void initState() {
super.initState();

polyEditor = PolyEditor(
  addClosePathMarker: true,
  points: testPolygon.points,
  pointIcon: const Icon(
    Icons.lens,
    size: 15,
    color: Colors.black,
  ),
  intermediateIcon: const Icon(Icons.lens, size: 15, color: Colors.black),
  callbackRefresh: () => {setState(() {})},
);

polygons.add(testPolygon);
}

SearchController searchController = Get.put(SearchController());

@override
Widget build(BuildContext context) {
return Scaffold(
  body: Stack(
    alignment: Alignment.center,
    children: [
      Center(
        child: FlutterMap(
          options: MapOptions(
            allowPanningOnScrollingParent: false,
            onTap: (_, ll) {
              print(ll);

              polyEditor.add(testPolygon.points, ll);
            },
            plugins: [
              DragMarkerPlugin(),
            ],
            center: LatLng(32.5231, 51.6765),
            zoom: 9.4,
          ),
          layers: [
            TileLayerOptions(
                urlTemplate:
                    'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
                subdomains: ['a', 'b', 'c']),
            PolygonLayerOptions(polygons: polygons),
            DragMarkerPluginOptions(markers: polyEditor.edit()),
          ],
        ),
      ),

I called this api and tried to show this svg as a polygon

"svg": "M 13.397511 -52.517283599999999 L 13.397829400000001 -52.517299800000004 
 13.398131599999999 -52.517315099999998 13.398159400000001 -52.517112099999999 13.3975388 
-52.517080700000001 Z",

but I dont know how to convert this svg string of coordinate to Polygon and show it on map when called this api and recieve this svg

I used this plugin

import 'package:flutter_map_line_editor/polyeditor.dart';

the result should be like this see this picture

CodePudding user response:

You're facing several problems:

  1. The retrieved svg data from nominatim is not a polygon but a path
  2. Besides it describes a single point i.e. it doesn't have any height or width.
  3. Quite likely, the polyeditor expects a proper polygon based on an array of geodata based coordinates.

Change nominatim query to get polygon coordinates

You could change the query to something like this:
https://nominatim.openstreetmap.org/search?q=London&format=json&polygon_geojson=1

Most address search queries won't return a polygon unless they are a sight or public building like "London Downing street 10".
If you're searching for a city, county, state, district or sight, the json response will include polygon coordinates describing the border of the queried region.

polygon_geojson=1 parameter will return an array polygon coordinates that could be displayed on you map.
Unfortunately, you need to change the order of coordinates to use them in leaflet since geojson will return [lon, lng] instead of [lat, lon]

Js example fetching polygon from nominatim

You might translate this example to work with flutter.

function initMap(lat, lon, zoom, coords = [], bBox = []) {
  var map = L.map("map").setView([lat, lon], zoom);
  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    maxZoom: 19,
    attribution: "© OpenStreetMap"
  }).addTo(map);
  var marker = L.marker([lat, lon]).addTo(map);

  if (coords.length) {
    let polygonPoints = [];
    //change coordinate order from [lon, lat] to [lat, lon]
    for (let i = 0; i < coords.length; i  ) {
      let p = coords[i];
      let [lat, lon] = [p[1], p[0]];
      polygonPoints.push([lat, lon]);
    }
    var polygon = L.polygon(polygonPoints).addTo(map);
  }

  var southWest = new L.LatLng(bBox[0], bBox[2]),
    northEast = new L.LatLng(bBox[1], bBox[3]),
    bounds = new L.LatLngBounds(southWest, northEast);
  map.fitBounds(bounds);
}

let query = "City-of-London";
query = "London Downing street 10";
let url = `https://nominatim.openstreetmap.org/search?q=${query}&format=json&polygon_geojson=1`;
fetchJson(url);

function fetchJson(url) {
  fetch(url)
    .then((response) => response.json())
    .then(function(data) {
      let result = data[0];
      let type = result.osm_type;
      if (type != 'relation') {
        result = data[1];
      }
      let [lat, lon] = [result.lat, result.lon];
      let coords = result["geojson"]["coordinates"][0];
      let bBox = result.boundingbox ? result.boundingbox : [];
      initMap(lat, lon, 10, coords, bBox);
    })
    .catch(function(error) {
      console.error(error);
    });
}
#map {
  height: 90vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.8.0/leaflet.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<h3>Query: London Downing street 10</h3>
<div id="map"></div>

  • Related