Input data given to 'drone' is not a valid GeoJSON object - javascript

I am trying to render a polygon from a webservice to a mapbox map as a proof of concept.
My webservice gives me the following geojson with some mock data:
{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[9.750441312789917,52.350087018909683],[9.7523081302642822,52.34896634765532],[9.7523403167724609,52.350106679555289],[9.750441312789917,52.350087018909683]]]},"properties":{"test1":"value1"}}]}
But mapbox gives me the error I can see in the browser console:
Input data given to 'drone' is not a valid GeoJSON object.
http://geojson.io and http://geojsonlint.com/ understand that geojson my webservice was generating.
It is send as content-type "text/plain; charset=utf-8"
because as application/json it gets a lot of \ characters, which is not working.
Below you can see the html code I am using for this test.
So what am I doing wrong here?
I checked that the geojson is correctly formatted and I added the same geojson directly as a source and it worked. See below.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Add multiple geometries from one GeoJSON source</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.2.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.2.0/mapbox-gl.css' rel='stylesheet' />
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
mapboxgl.accessToken = 'pk.xxxxxx';
var map = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/streets-v11",
center: [9.754206, 52.355394],
zoom: 14
});
var url = 'https://localhost:44337/api/resource';
map.on('load', function () {
map.addSource('drone', { type: 'geojson', data: url });
map.addLayer({
"id": "drone",
"type": "fill",
"source": "drone",
'layout': {},
'paint': {
'fill-color': '#088',
'fill-opacity': 0.8
}
});
});
</script>
</body>
</html>
I expect that there is some polygon on the map, like it is if I put the geojson directly into the code:
map.on('load', function () {
map.addLayer({
'id': 'maine',
'type': 'fill',
'source': {
'type': 'geojson',
'data':
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
9.750441312789917,
52.350087018909683
],
[
9.7523081302642822,
52.34896634765532
],
[
9.7523403167724609,
52.350106679555289
],
[
9.750441312789917,
52.350087018909683
]
]
]
},
"properties": {
"test1": "value1"
}
}
]
}
},
'layout': {},
'paint': {
'fill-color': '#088',
'fill-opacity': 0.8
}
});
});

Maybe you should try to fetch your geoJSON from your API manually and see if that works, passing a URL as a geoJSON object to mapbox seems to work as well, but maybe something is wrong with your API, so I would do a manual fetch and see if anything goes wrong. Furthermore, you should definitely change your content-type header back to application/json, the following snippet assumes you did that!
map.on('load', async function() {
let response = await fetch(url);
let data = await (
response.headers.get('content-type').includes('json')
? response.json() // this will parse your JSON if the proper content-type header is set!
: response.text()
);
map.addSource('drone', { type: 'geojson', data: data });
map.addLayer({
"id": "drone",
"type": "fill",
"source": "drone",
'layout': {},
'paint': {
'fill-color': '#088',
'fill-opacity': 0.8
}
});
});

Ok, I reckon mapboxgl is doing call this, but if it helps, this is the asp.net core backend snippet:
// GET: api/resource
[HttpGet]
public JsonResult GetResources()
{
var poly = _context.Resources.First().Polygon;
AttributesTable attributes = new AttributesTable();
attributes.Add("test1", "value1");
IFeature feature = new Feature(poly, attributes);
FeatureCollection featureCollection = new FeatureCollection(new Collection<IFeature> { feature });
var gjw = new GeoJsonWriter();
gjw.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
string actual = gjw.Write(featureCollection);
return new JsonResult(actual);
}
I am using NetTopologySuite.
And poly is a SQL Server Geography type Polygon.
EDIT: Ok I figured it out myself:
I had to do this:
return Content(actual, "application/json", Encoding.UTF8);
and use ContentResult as a return type.
My Json seemed to get serialized twice, since it got too many characters.
Ah and the fetch and response.json() parsing exside proposed is not needed with the correct geojson response. But it is also working with it. ;)
Thanks though.

Related

Gmap vue save polyline, polygon and load geojson onto google map

I am have a vuejs/nuxtjs application using the gmap-vue package which is a fork of vue-google-maps. I have followed the drawing manager with slot example which is working as shown on the document, good times!
But...
I would like to do two more things
Save the data that I added to the map, how do I access it?
How to load geojson onto the map and then edit it.
Examle below:
More information from further investigation.
I am trying to build up data in the form of geojson
let shapes = [];
for(let shape in this.shapes){
let tmp = {
"type": "Feature",
"properties": {
"id": this.shapes[shape].id || null,
"zIndex": this.shapes[shape].zIndex || null
},
"geometry": {
"type": this.shapes[shape].type,
"coordinates": // where to find shape coordinates?
}
};
shapes.push(tmp)
}
console.log(JSON.stringify(shapes));
displays the following in the console.log
[
{
"type":"Feature",
"properties":{
"id":null,
"zIndex":null
},
"geometry":{
"type":"polygon",
"coordinates": // where to find coordinates?
}
}
]
console.log[this.shapes[shape]];
returns
{__ob__: Observer}
overlay: (...)
type: (...)
How can I access the coordinates?
For anyone else looking for an answer, I hope this helps you out.
const newShapes = [];
this.shapes.forEach((shape) => {
const coords = [];
shape.overlay.latLngs.getArray().forEach((latLng) => {
coords.push([latLng.lat, latLng.lng]);
});
newShapes.push({
type: 'Feature',
geometry: {
type: shape.type,
coordinates: coords,
},
});
});
As shown here: https://diegoazh.github.io/gmap-vue/#getting-a-map-reference
this.$refs.mapRef.$mapPromise.then((map) => {
map.panTo({lat: 1.38, lng: 103.80})
})
is working pretty great.
<gmap-drawing-manager ref="drawingRef">
and
<gmap-drawing-manager :shapes="shapes" ref="drawingRef">
allows to access the same information with this.shapes!

how to fix the error:Cannot read property 'mapmatching' of undefined

I use mapbox-match.js locally without use http request to match the route on map . but I have problem in matching and the error message
"Cannot read property 'mapmatching' of undefined"
shown. how to solve this?
this is for map visualization with local host map. running http server, html and javascript. I use d3-js and mapbox to render set of coords as geojson data on a map to visualize a route
<head>
<meta charset='utf-8' />
<script src='MAPBOX/mapbox-gl.js'></script>
<link href='MAPBOX/mapbox-gl.css' rel='stylesheet' />
<script src='mapbox.js-publisher-production/src/mapbox.js'></script>
<script src='mapbox-match.js-master/src/match.js'></script>
</head>
<body>
<script>
function updateRoute(newCoords) {
// Set the profile
var profile = "driving";
L.mapbox.mapmatching(Coords, profile);
}
L.mapbox.mapmatching(Coords, profile, function(error, layer) {
layer.addTo(map);
layer.setStyle({
color: '#9a0202',
weight: 4,
opacity: 0.8
});
layer.addLayer({
"id": "route",
"type": "line",
"source": {
"type": "geojson",
"data": {
"type": "Feature",
"properties": {},
"geometry": coords
}
},
"layout": {
"line-join": "round",
"line-cap": "round"
},
"paint": {
"line-color": "#33C9EB",
"line-width": 3
}
});
});
}
</script>
</body>
after debugging code the error shown "TypeError: Cannot read property 'mapmatching' of undefined"

How to add new layer to client mapbox map on button click with JS/jQuery?

Problem:
I am working on project where I use node.js server that communicate with my spatial DB in PG and my client uses mapbox to vizualize map on his side. After hitting a button, the request is send to server, server to psql, psql to server as result query and then through socket.io back to client, where I want to put my geoJSON / new geometry as new layer on his map after that client buttonclick occurs. Map on client side in HTML is well working and I can interact with it. I use JS inside of HTML page of my client. From there I need to update mapbox map with new geometry after button click.
Code sample:
But I tried this code, but this do nothing after button click and will show no errors in devTool Chrome console:
<script>
mapboxgl.accessToken = 'secretToken-I-have-just-for-ilustr--this-is-working';
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/streets-v10',
center: [17.10, 48.14], // starting position on Bratislava
zoom: 11 // starting zoom
});
// Add zoom and rotation controls to the map.
map.addControl(new mapboxgl.NavigationControl());
// later SOCKET PROCESSING
$(document).ready(function(){
$('#buttonRun').click(function(e){
map.on('load', function () {
alert("got HERE") // this is working, alert shows itself
map.addLayer({
"id": "route",
"type": "line",
"source": {
"type": "geojson",
"data": {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[-122.48369693756104, 37.83381888486939],
[-122.48348236083984, 37.83317489144141],
[-122.48339653015138, 37.83270036637107],
[-122.48356819152832, 37.832056363179625],
[-122.48404026031496, 37.83114119107971],
[-122.48404026031496, 37.83049717427869],
[-122.48348236083984, 37.829920943955045],
[-122.48356819152832, 37.82954808664175],
[-122.48507022857666, 37.82944639795659],
[-122.48610019683838, 37.82880236636284],
[-122.48695850372314, 37.82931081282506],
[-122.48700141906738, 37.83080223556934],
[-122.48751640319824, 37.83168351665737],
[-122.48803138732912, 37.832158048267786],
[-122.48888969421387, 37.83297152392784],
[-122.48987674713133, 37.83263257682617],
[-122.49043464660643, 37.832937629287755],
[-122.49125003814696, 37.832429207817725],
[-122.49163627624512, 37.832564787218985],
[-122.49223709106445, 37.83337825839438],
[-122.49378204345702, 37.83368330777276]
]
}
}
},
"layout": {
"line-join": "round",
"line-cap": "round"
},
"paint": {
"line-color": "#888",
"line-width": 8
}
});
});
});
});
</script>
Even this is not working - even if I set data in click function in a static way, but this data will later change dynamically. If I add that layer out of click event function scope, it is working and layer loads on client map.
Settings / versions:
Windows10 Pro - 64-bit
Google Chrome - Version 69.0.3497.100 (Official Build) (64-bit)
Node.js - v10.11.0
mapbox-gl.js v0.49.0
Q:
Is there any way how to add layer to mapbox map dynamically, please? And later to remove without page refresh? (I still not found answer, even here)
Solution
Okay, I found something I before did not see, concretely this.
I better read documentation, and it is impossible to setup new layers dynamically, but now it is working as follows / you need to:
Out of all scopes define your variables, for example geoJson1, and geoJson2 that you can later edit / fill with function
Setup your layer in advance on map with your ID (as in code below) and fill it for example with goeJson1 or with empty []
In your on click listener function call this: map.getSource('data-update').setData(geojson2);
You just can setup as many layers in advance as you need, and later you can update them.
Code result:
<script>
mapboxgl.accessToken = 'token-from-your-registered-account';
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/streets-v10',
center: [17.10, 48.14], // starting position on Bratislava
zoom: 11 // starting zoom
});
var geojson = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-122.48369693756104, 37.83381888486939],
[-122.48348236083984, 37.83317489144141],
[-122.48339653015138, 37.83270036637107],
[-122.48356819152832, 37.832056363179625],
[-122.48404026031496, 37.83114119107971]
]
}
}]
};
var geojson2 = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-122.48369693756104, 37.83381888486939],
[-122.48348236083984, 37.83317489144141],
[-122.48339653015138, 37.83270036637107],
[-122.48356819152832, 37.832056363179625],
[-122.48404026031496, 37.83114119107971],
[-122.48404026031496, 37.83049717427869],
[-122.48348236083984, 37.829920943955045],
[-122.48356819152832, 37.82954808664175],
[-122.48507022857666, 37.82944639795659],
[-122.48610019683838, 37.82880236636284],
[-122.48695850372314, 37.82931081282506],
[-122.48700141906738, 37.83080223556934],
[-122.48751640319824, 37.83168351665737],
[-122.48803138732912, 37.832158048267786],
[-122.48888969421387, 37.83297152392784],
[-122.48987674713133, 37.83263257682617],
[-122.49043464660643, 37.832937629287755],
[-122.49125003814696, 37.832429207817725],
[-122.49163627624512, 37.832564787218985],
[-122.49223709106445, 37.83337825839438],
[-122.49378204345702, 37.83368330777276]
]
}
}]
};
map.on('load', function () {
map.addLayer({
"id": "data-update",
"type": "line",
"source": {
"type": "geojson",
"data": geojson // your previously defined variable
},
"layout": {
"line-join": "round",
"line-cap": "round"
},
"paint": {
"line-color": "#888",
"line-width": 8
}
});
});
$(document).ready(function(){
$('#buttonRun').click(function(e){
map.getSource('data-update').setData(geojson2);
});
});
</script>

Rendering points with Leaflet from a `json.gz` file

I am using the SimpleHTTPServer for Python to display a basic Leaflet map.
I wish to create a series of points on the map, using a json.gz file as input.
The contents of this file (input.json.gz) look like this:
[[25.0153,55.45758],[25.01767,55.45569],[25.02065,55.45327],[25.02655,55.44846]]
My hardcoded code looks like this:
var pointA = new L.LatLng(25.146619, 55.225746);
var pointB = new L.LatLng(25.198696, 55.269794);
How do I read the json.gz file in javascript and iterate across it creating points? Ultimately I will collect these points into different pointLists and from this render a polyline. Full code below:
<!DOCTYPE html>
<html>
<head>
<title>Leaflet Web Map</title>
<!-- reference to Leaflet CSS -->
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<!-- reference to Leaflet JavaScript -->
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<!-- set width and height styles for map -->
<style>
html, body, #map {
height: 100%;
width: 100%;
}
/* css to customize Leaflet default styles */
.custom .leaflet-popup-tip,
.custom .leaflet-popup-content-wrapper {
background: #e93434;
color: #ffffff;
}
</style>
</head>
<body>
<!-- place holder for map -->
<div id="map"></div>
<script>
// create map object, tell it to live in 'map' div and give initial latitude, longitude, zoom values
var map = L.map('map', {scrollWheelZoom:false}).setView([25.198696, 55.269794], 15);
// add base map tiles from OpenStreetMap and attribution info to 'map' div
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var pointA = new L.LatLng(25.146619, 55.225746);
var pointB = new L.LatLng(25.198696, 55.269794);
var pointList = [pointA,pointB];
L.polyline(pointList,{icon: test_icon,color:'red','weight':10}).bindPopup(customPopup,customOptions).addTo(map);
</script>
</body>
</html>
EDIT
I have now reformatted my data into geojson format. Here is an exert:
{
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "LineString",
"coordinates": [
[
25.1167,
55.19259
],
[
25.11285,
55.18714
],
[
25.11141,
55.1851
],
[
25.11077,
55.18422
],
[
25.11001,
55.18311
],
[
25.10855,
55.18105
],
[
25.10722,
55.17914
],
[
25.10644,
55.17805
],
[
25.10572,
55.17712
]
]
},
"type": "Feature",
"properties": {
"url": "blah",
"name": "blue"
}
},
I then try and load it using AJAX.
var geojsonLayer = new L.GeoJSON.AJAX("polylines.geojson");
geojsonLayer.addTo(map);
I've also added <script src="./polylines.geojson" type="text/javascript"></script> to the top of the html file.
However, this returns file not found. I've the file located in the same directory as index.html
code 404, message File not found
127.0.0.1 - - [13/Mar/2017 14:52:40] "GET polylines.geojson HTTP/1.1" 404 -

Does anyone know how to remove geoJson polygon from a layer with mapboxgl?

I am running into some difficulties to remove a geojon polygon from a layer with mapboxGL.
Here the following code to add my geoson polygons where
array_geo is a polygon geometry. Adding the polygon works like a charm,
but I still did not find how to delete my polygons. The only trick I found is to use the removeLayer(id) function which delete the entire layer.
var id="mylayer";
itemObj = {
type:"Feature",
properties: {
description: description,
type: 23
},
geometry: {
type: "Polygon",
coordinates: array_geo
},
};
mpolygons.push(itemObj);
map.addSource(id,{
"type":"geojson",
"data":{
"type":"FeatureCollection",
"features":mypolygons
}
self.map.addLayer({
"id": id,
"source":id,
"type":"fill",
"layout": {'visibility':'visible'},
"paint": {
'fill-color': '#088',
//'fill-opacity': 0.8
}
})
Thanks !

Categories