saving mapbox polygon coordinates to .geojson - mapbox

Can the Mapbox GL API get geojson data to external .geojson file?
I use the Mapbox GL API for maps. The user draws the polygon, and send it to contact form in geojson code
example:
{ "type": "FeatureCollection", "features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
27.66357421875,
48.48748647988415
],
[
37.79296875,
48.004625021133904
] }

Related

Mapbox: Find POIs with defined radius

The task I need is:
input: geolocation coordinates from gps, radius
ouput: list of pois (just names) to user can choose
just need analogue for google nearby search (since their cost is too high for a production)
questions:
1) what API is more preferable for this? examples are appreciated
2) do I need own data for pois or there is build in date in mapbox for these purposes?
The Mapbox Tilequery API lets you do exactly this. Here is a step-by-step tutorial explaining how to work with this API, and this API playground lets you experiment with the API. The data queried by the API is determined by the tileset passed as a parameter to your API request. As noted in the linked documentation, tutorial, and playground, you can either use existing Mapbox tilesets are create your own tileset with custom data, depending on your use case.
Note that, depending on the structure of the underlying data in the tileset you use, you might need to do a little extra work to convert a feature returned by the Tilequery API into a name of a POI. For example, consider the response body for below API request which makes use of the default mapbox.mapbox-streets-v8 tileset:
https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/tilequery/-93.1204,44.9472.json?radius=25&limit=5&dedupe&access_token=YOUR_MAPBOX_ACCESS_TOKEN
One particular feature returned by the response body is:
{
"type": "Feature",
"id": 4,
"geometry": {
"type": "Point",
"coordinates": [
-93.12041537130386,
44.947199821761615
]
},
"properties": {
"extrude": "true",
"height": 3,
"min_height": 0,
"type": "house",
"underground": "false",
"tilequery": {
"distance": 1.2132887872688276,
"geometry": "polygon",
"layer": "building"
}
}
}
Although there is no POI name here, you could use the returned coordinates in conjunction with the Mapbox reverse geocoding API endpoint to retrieve names and other relevant POI properties for the POI located at said coordinate.
conversation with Mapbox support
Hi Artemii​,
It's Alex from Mapbox Support, happy to help!
You will want to use the Mapbox Tilequery API. The option you will want to utilize is radius​. Please be advised that queries will use tiles from the maximum zoom of the tileset, and will only include the intersecting tile plus eight surrounding tiles when searching for nearby features. That means that if your tileset has a maximum extent of z20, the maximum radius that you can search is only a few meters. Here is an API playground that you can test the API out with.
I hope this was helpful!
Hi Alex,
thanks for the quick reply, one more question:
request:
https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/tilequery/55.9414,54.7295.json?radius=25&limit=50&dedupe&geometry=point&access_token=YOUR_MAPBOX_ACCESS_TOKEN
response:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": 8,
"geometry": {
"type": "Point",
"coordinates": [
55.94845533370972,
54.72732387401962
]
},
"properties": {
"house_num": "32",
"tilequery": {
"distance": 8.949637333832088,
"geometry": "point",
"layer": "housenum_label"
}
}
},
{
"type": "Feature",
"id": 23629792230,
"geometry": {
"type": "Point",
"coordinates": [
55.948566645383835,
54.72761119224691
]
},
"properties": {
"class": "general",
"filterrank": 4,
"maki": "marker",
"name": "Башинформсвязь",
"name_script": "Cyrillic",
"sizerank": 16,
"type": "Telecommunication",
"tilequery": {
"distance": 23.898768437893523,
"geometry": "point",
"layer": "poi_label"
}
}
}
]
}
question: I understand that I can find info about places I got in the response using reverse geocoding API, but is there another approach to do this? Ideally, I would like to get poi's names from one tilquery request, because in case of using two API's (tilquery + geocoding) I will have to query 4-5 queries instead of only 1 (just worrying because it impacts on cost).
Hi Artemii​,
There is a parameter in the Tilequery API called layers that you can use to target a specific layer of your style.
https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/tilequery/55.9414,54.7295.json?radius=25&limit=50&dedupe&geometry=point&layers=poi_label&access_token=
Which gets this response:
{ "type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": 32316157590,
"geometry": {
"type": "Point",
"coordinates": [
55.94142526388168,
54.7295828683082
]
},
"properties": {
"category_en": "Supermarket",
"category_zh-Hans": "超市",
"class": "food_and_drink_stores",
"filterrank": 1,
"maki": "grocery",
"name": "Магнит",
"name_script": "Cyrillic",
"sizerank": 16,
"type": "Supermarket",
"tilequery": {
"distance": 9.367370433680872,
"geometry": "point",
"layer": "poi_label"
}
}
}
]
}
You can take this response object and return all the information from the POI. The "name" property is the name of the POI. Was there other properties that you were looking for from the reverse geocoding that are not being returned by the tilequery? It would be helpful for you to share a full example of a workflow using both tilequery and reverse geocoding, and to hear more about your exact use case, and how this tilequery/reverse geocoding operation fits into your larger application workflow.
Hi Alex,
request (without poi label since it doesn't find few bars I know. But if you add this label you only see one result) : https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/tilequery/55.9485,54.7275.json?radius=14&limit=50&dedupe&access_token=YOUR_MAPBOX_ACCESS_TOKEN request
response:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": 5,
"geometry": {
"type": "Point",
"coordinates": [
55.9485,
54.7275
]
},
"properties": {
"extrude": "true",
"height": 15,
"min_height": 0,
"type": "building",
"underground": "false",
"tilequery": {
"distance": 0,
"geometry": "polygon",
"layer": "building"
}
}
},
{
"type": "Feature",
"id": 1297495121,
"geometry": {
"type": "Point",
"coordinates": [
55.94833781213748,
54.727526546045794
]
},
"properties": {
"class": "path",
"iso_3166_1": "RU",
"iso_3166_2": "RU-BA",
"len": 4450,
"oneway": "false",
"structure": "none",
"surface": "paved",
"type": "footway",
"tilequery": {
"distance": 10.859473551200084,
"geometry": "linestring",
"layer": "road"
}
}
},
{
"type": "Feature",
"id": 23629792230,
"geometry": {
"type": "Point",
"coordinates": [
55.948566645383835,
54.72761119224691
]
},
"properties": {
"class": "general",
"filterrank": 4,
"maki": "marker",
"name": "Башинформсвязь",
"name_script": "Cyrillic",
"sizerank": 16,
"type": "Telecommunication",
"tilequery": {
"distance": 13.10152056398561,
"geometry": "point",
"layer": "poi_label"
}
}
},
{
"type": "Feature",
"id": 7,
"geometry": {
"type": "Point",
"coordinates": [
55.94869895433047,
54.7274698331467
]
},
"properties": {
"extrude": "true",
"height": 3,
"min_height": 0,
"type": "building",
"underground": "false",
"tilequery": {
"distance": 13.251093067012334,
"geometry": "polygon",
"layer": "building"
}
}
}
]
}
If we decode the first pair of coordinates(55.9485, 54.7275) using reverse geocoding (https://docs.mapbox.com/search-playground), we get Smoky People, ул. Ленина, 32, Уфа, Республика Башкирия 450077, Russia and if we decode all pairs, we will be able to find more cafes and bars (poi's).
Hey Artemii,
The reason for the varied results are the sources of the queries.
The Tilequery API searches for things that are on our Mapbox Streets v8 tileset (which our Mapbox Streets v11 style uses). The data in this tileset majorly comes from OpenStreetMap. If there are missing or outdated places on the map, this is the perfect opportunity to help us improve our map! If you do want to add or edit anything, head to openstreetmap.org, create an account, and make improvements directly. You'll have the option to go through an interactive tutorial to get you started. There are more details for advanced editing here as well: https://labs.mapbox.com/mapping. The Mapbox Streets tileset is updated regularly as features are edited or added to the map, which means that if you edit OpenStreetMap, you will eventually see your changes reflected on your Mapbox map.
The Geocoding API contains data sources from governments, open data projects, and private companies. In some cases, results from the Geocoding API may differ from Mapbox Streets or OpenStreetMap data. Check out this documentation on how geocoding works at Mapbox.
I think the best way to reduce the amount of API calls you make would be to pick one API, either reverse geocoding or Tilequery, and stick with it. With OpenStreetMaps, as tedious as it sounds, you do have the ability to add any POIs you know are missing, or cross reference other sources to add POIs to the map, which will make the place visible on the map as well as appear in your tilequery. With the Geocoding API, due to the nature of some sources and licensing, not all the places that you can search are visible on the map.

How can I take coordinates for a polygon from a geojson file and extrude a 3D polygon from that?

I am trying to build a custom polygon and extrude it to the desired height using a geojson format for the data of the layer. I cannot, however, get the layer to appear on the map.
Here is what my code currently looks like:
map.on('load', function() {
map.addLayer({
"id": "points",
"type": "fill-extrusion",
"source": {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"height": 20
},
"geometry": {
"type": "Polygon",
"coordinates": [[-77.95156674578604,43.21028611031018],[-77.9515685764367,43.21023621803456],[-77.95164127121708,43.21023640149863],[-77.95163950226289,43.20994159756599],[-77.95156746849948,43.20994229766657],[-77.95156608216422,43.20984647340193],[-77.95163884784701,43.2098471878642],[-77.95163818870492,43.20974779426955],[-77.95156665824665,43.20974844351096],[-77.95156615562892,43.2096483942845],[-77.95163707195606,43.20964807835471],[-77.95163793551596,43.20955241242493],[-77.95156647756606,43.20955241987652],[-77.9515664774183,43.2094545892833],[-77.95163793511105,43.20945458922404],[-77.95163696894726,43.20935746267753],[-77.95156551159552,43.20935675861833],[-77.95156647716871,43.20929763788168],[-77.95105728862093,43.20929848258431],[-77.95105728634326,43.20935651174059],[-77.95094326166087,43.20935664235909],[-77.9509445324407,43.2094533024724],[-77.95105528277132,43.20945365396392], [-77.95105519319713,43.20955170962569],[-77.9509434596672,43.20955220425741],[-77.95094421091157,43.20964816606944],[-77.95105501443713,43.20964756032618],[-77.95105491497931,43.20974624410085], [-77.95094329958742,43.20974576773256],[-77.95094365714365,43.20984690983914],[-77.95105721793563,43.20984632462195],[-77.95105737381726,43.20994209364298], [-77.95094302334114,43.2099429224098], [-77.95094306509297,43.21003748562214],[-77.95105440575118,43.21003746846881],[-77.95105570050066,43.21013103703177],[-77.95094276571092,43.21013059432006],[-77.95094112502309,43.21023730976442],[-77.95105416431622,43.21023720143463],[-77.95105549775089,43.21028580291442],[-77.95156674578604,43.21028611031018]]
}
}]
}
},
"paint": {
"fill-extrusion-color": "#aaa",
"fill-extrusion-height": ['get', 'height']
}
});
});
Polygon is an array of LineStrings in GeoJSON (see https://en.wikipedia.org/wiki/GeoJSON#Geometries, for instance). So in your case the coordinates should look like this:
"coordinates": [[[-77.95156674578604,43.21028611031018],[-77.9515685764367,43.21023621803456],[-77.95164127121708,43.21023640149863],[-77.95163950226289,43.20994159756599],[-77.95156746849948,43.20994229766657],[-77.95156608216422,43.20984647340193],[-77.95163884784701,43.2098471878642],[-77.95163818870492,43.20974779426955],[-77.95156665824665,43.20974844351096],[-77.95156615562892,43.2096483942845],[-77.95163707195606,43.20964807835471],[-77.95163793551596,43.20955241242493],[-77.95156647756606,43.20955241987652],[-77.9515664774183,43.2094545892833],[-77.95163793511105,43.20945458922404],[-77.95163696894726,43.20935746267753],[-77.95156551159552,43.20935675861833],[-77.95156647716871,43.20929763788168],[-77.95105728862093,43.20929848258431],[-77.95105728634326,43.20935651174059],[-77.95094326166087,43.20935664235909],[-77.9509445324407,43.2094533024724],[-77.95105528277132,43.20945365396392], [-77.95105519319713,43.20955170962569],[-77.9509434596672,43.20955220425741],[-77.95094421091157,43.20964816606944],[-77.95105501443713,43.20964756032618],[-77.95105491497931,43.20974624410085], [-77.95094329958742,43.20974576773256],[-77.95094365714365,43.20984690983914],[-77.95105721793563,43.20984632462195],[-77.95105737381726,43.20994209364298], [-77.95094302334114,43.2099429224098], [-77.95094306509297,43.21003748562214],[-77.95105440575118,43.21003746846881],[-77.95105570050066,43.21013103703177],[-77.95094276571092,43.21013059432006],[-77.95094112502309,43.21023730976442],[-77.95105416431622,43.21023720143463],[-77.95105549775089,43.21028580291442],[-77.95156674578604,43.21028611031018]]]

Heatmap from geojson points in leaflet

I am attempting to create a simple heatmap from a feature collection of points using leaflet's heatmap plugin. After successfully getting the json data from an ajax call, I create an empty coords array and push coordinates from each feature.
However, this method does not work and neither does the geojson2heat function. There are no errors in the console. What am I doing wrong and does anyone know of a workaround?
var map = L.map('map').setView([50.0647, 19.9450], 12);
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
}).addTo(map);
var geojsonLayer = new L.GeoJSON.AJAX("newmap.geojson");
coords = [];
function onEachFeature(feature, layer) {
coords.push(feature.geometry.coordinates);
};
L.GeoJSON(geojsonLayer, {
onEachFeature: onEachFeature
})
var heat = L.heatLayer(coords).addTo(map);
The structure of the geojson is standard:
{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "st_x": 19.952030181884801, "st_y": 50.055513141929701 }, "geometry": { "type": "Point", "coordinates": [ 19.952030181884801, 50.055513141929701 ] } },
{ "type": "Feature", "properties": { "st_x": 18.672015, "st_y": 50.287181666666697 }, "geometry": { "type": "Point", "coordinates": [ 18.672015, 50.287181666666697 ] } },
I am mostly doing the same as you but with Mapbox, which is based on Leaflet.
The problem I had is that the latitude and longitude coordinates of the GeoJSON were reversed. There were no errors on console either- points were just not showing on map. So, you need:
"coordinates": [ longitude, latitude ]
Hope that's the issue.

Leaflet js geojson coordinates = Lat/lng from googlemap

I am new to leaflet js
Reading the geojson section of leaflet js web site.
A quick question, coordinates in the geojson format, is it same as the lay/lng, which we can get from google map ?
Jimmy
yes but you have to invert lat and lng.
For example if you click on Paris you will get following coordinates with GoogleMap: 48.857031, 2.346526
If you generate some geojson with http://geojson.io/ you will get:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
2.349529266357422,
48.856414043180365
]
}
}
]
}
Also note that GoogleMap only handles 6 decimals (which is ample)

How to add a GeoJSON layer in GraphHopper?

I have a GeoJSON file containing POIs that I'd like to be able to display within a separate GraphHopper layer. After several tries and search over internet, I just can't manage to get a way to do it.
This is a sample of the GeoJSON file (I checked the whole file with JSON validator and it was OK).
{"type": "Feature",
"properties": {
"fee": "no",
"bicycle_parking": "anchors",
"ref": "PVNAN23",
"address": "Rue Gabriel Goudy 44200 Nantes",
"name": "Pirmil P+R",
"capacity": "24",
"park_ride": "yes",
"amenity": "bicycle_parking",
"covered": "yes"
},
"geometry": {"type": "Point", "coordinates": [-1.5406709, 47.1960031]}},
{"type": "Feature",
"properties": {
"bicycle_parking": "stands",
"addr:postcode": "44000",
"addr:country": "FR",
"name": "Madeleine",
"capacity": "6",
"amenity": "bicycle_parking",
"addr:street": "chaussée de la Madeleine",
"note": "vérifié",
"addr:city": "Nantes",
"covered": "no",
"addr:housenumber": "35"
},
"geometry": {"type": "Point", "coordinates": [-1.55076671448, 47.21000114109]}}
]}
I tried what is explained in How to load external geojson file into leaflet map but I cannot get it working.
If your JSON is valid that doesn't mean you're working with a valid GeoJSON object. For instance: {"foo": "bar"} is perfectly valid JSON but in no way a valid GeoJSON object. L.GeoJSON, leaflet's GeoJSON layer expects a FeatureCollection or an array containing Features.
A valid FeatureCollection:
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"id": 1
},
"geometry": {
"type": "Point",
"coordinates": [0,0]
}
},{
"type": "Feature",
"properties": {
"id": 2
},
"geometry": {
"type": "Point",
"coordinates": [1,1]
}
}]
}
Or just the array with features:
[{
"type": "Feature",
"properties": {
"id": 1
},
"geometry": {
"type": "Point",
"coordinates": [0,0]
}
},{
"type": "Feature",
"properties": {
"id": 2
},
"geometry": {
"type": "Point",
"coordinates": [1,1]
}
}]
(Note that just an array of features isn't a valid GeoJSON object but Leaflet will handle it without problems)
To load these into a L.GeoJson layer you'll need to make them available in your script. You could simple declare the object before you create the layer. For example:
// Declare GeoJSON object
var geojson = {
type: "FeatureCollection",
features: [
// Features here
]
}
// Create a new GeoJSON layer with geojson object
// And add to map (assuming your map instance is assigned to "map")
var layer = new L.GeoJSON(geojson).addTo(map);
But that will become quite a mess when you've got lots of features and it's always better to keep your logic and data separated so you should put your data object in a separate file. So let's say you've got the object stored in a file called "geo.json", then you can load the file with XHR/AJAX solution of your choice. I'm using jQuery in the following example:
// Fetch geo.json file and assign the data to geojson variable
$.getJSON('geo.json', function (geojson) {
// Create a new GeoJSON layer with GeoJSON object
// And add to map (assuming your map instance is assigned to "map")
var layer = new L.GeoJSON(geojson).addTo(map);
});
Here a working example on Plunker: http://plnkr.co/edit/Mh8p4F?p=preview