How to save a GeoJSON into file using javascript - javascript

I am wondering if I have a GeoJSON object such as
var geoJSONLoc= {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"timeReported": "2013-01-22 08:42:26+01"
},
"geometry": {
"type": "Point",
"coordinates": [
7.582512743,
51.933292258,
1
]
}
},
{
"type": "Feature",
"properties": {
"timeReported": "2013-01-22 10:00:26+01"
},
"geometry": {
"type": "Point",
"coordinates": [
7.602516645,
51.94962073,
1
]
}
}]}
How can I save this into a .json file for future use?
I am trying to use
localStorage.setItem('geoJSONLoc.json', geoJSONLoc);
but it doesnt seem to be the right answer.

I've done a little work in NodeJS, so this maybe way off base.
But couldn't you use the fs module for this?
something like
var fs = require('fs')
fs.writeFile('geoJSONLoc.json', geoJSONLoc, function(err){
if(err){
console.log(err);
}
});

Related

How to convert JSON to GeoJson JavaScript

I've got a JSON from a database but now I need to convert it into GeoJson to use it in my map
I found this solution but it shows an undefined array.
$.getJSON("./origin/neworigin.json", function(jsonData) {
var outGeoJson = {}
outGeoJson['properties'] = jsonData
outGeoJson['type']= "Feature"
outGeoJson['geometry']= {"type": "Point", "coordinates":
[jsonData['latitude'], jsonData['longitude']]}
console.log(outGeoJson)
});
This is an example from myJSON
[{"station":"BORJA","institution":"SENCICO","longitude":"-77.0064","latitude":"-12.0855"},
{"station":"SCARQ","institution":"SENCICO","longitude":"-71.5408","latitude":"-16.385"},
{"station":"SCAR2","institution":"SENCICO","longitude":"-71.5364","latitude":"-16.3934"},...
in browser
Check if the array is empty or not.
Try change the variable names.
OR
Provide more details.
You have two options to create a valid GeoJSON form JSON.
create GeoJSON.Point array and GeoJSON.FeatureCollection
create GeoJSON.MultiPoint object
Here are code snippets:
const jsonData = [{
"station": "BORJA",
"institution": "SENCICO",
"longitude": "-77.0064",
"latitude": "-12.0855"
},
{
"station": "SCARQ",
"institution": "SENCICO",
"longitude": "-71.5408",
"latitude": "-16.385"
},
{
"station": "SCAR2",
"institution": "SENCICO",
"longitude": "-71.5364",
"latitude": "-16.3934"
}
];
// to GeoJSON.Point array
const geoJSONPointArr = jsonData.map(row => {
return {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [row.longitude, row.latitude]
},
"properties": row
}
});
console.log(geoJSONPointArr);
// to GeoJSON.FeatureCollection
const pointArrFeatureCollection = {
"type": "FeatureCollection",
"features": geoJSONPointArr
}
console.log(pointArrFeatureCollection);
// to GeoJSON.MultiPoint
const geoJSONMultiPoint = {
"type": "Feature",
"geometry": {
"type": "MultiPoint",
"coordinates": jsonData.map(row => [row.longitude, row.latitude])
},
"properties": {
originalData: jsonData
}
}
console.log(geoJSONMultiPoint);
I would also recommend using the turf library, which is very convenient when working with the GeoJSON format.

Convert javascript to json?

I'm working with leaflets and I've noticed that many examples use a separate js file where a variable is set to a JSON stream.
How would I be able to modify the following example so that it can read off a json file with the geojson and not have the variable declaration in the javascript?
The code looks like this:
<script type="text/javascript">
var geoJsonData = {
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "id":"1", "properties": { "address": "2" }, "geometry": { "type": "Point", "coordinates": [175.2209316333,-37.8210922667 ] } },
{ "type": "Feature", "id":"2", "properties": { "address": "151" }, "geometry": { "type": "Point", "coordinates": [175.2238417833,-37.80975435 ] } },
{ "type": "Feature", "id":"3", "properties": { "address": "21" }, "geometry": { "type": "Point", "coordinates": [175.2169955667,-37.818193 ] } },
{ "type": "Feature", "id":"4", "properties": { "address": "14" }, "geometry": { "type": "Point", "coordinates": [175.2240856667,-37.8216963 ] } },
{ "type": "Feature", "id":"5", "properties": { "address": "38B" }, "geometry": { "type": "Point", "coordinates": [175.2196982333,-37.8188702167 ] } },
{ "type": "Feature", "id":"6", "properties": { "address": "38" }, "geometry": { "type": "Point", "coordinates": [175.2209942 ,-37.8192782833 ] } }
]
};
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '© OpenStreetMap contributors'
});
var map = L.map('map')
.addLayer(tiles);
var markers = L.markerClusterGroup();
var geoJsonLayer = L.geoJson(geoJsonData, {
onEachFeature: function (feature, layer) {
layer.bindPopup(feature.properties.address);
}
});
markers.addLayer(geoJsonLayer);
map.addLayer(markers);
map.fitBounds(markers.getBounds());
</script>
I know it can be done with $.getJSON, but I would prefer using L.geoJson, if possible.
To read JSON data from a file you can use the fetch function (read more).
Here is an example:
fetch('http://example.com/movies.json')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
// Do something with the JSON data
console.table(myJson);
});
In your case:
function doSomething(geoJsonData) {
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '© OpenStreetMap contributors'
});
var map = L.map('map')
.addLayer(tiles);
var markers = L.markerClusterGroup();
var geoJsonLayer = L.geoJson(geoJsonData, {
onEachFeature: function (feature, layer) {
layer.bindPopup(feature.properties.address);
}
});
markers.addLayer(geoJsonLayer);
map.addLayer(markers);
map.fitBounds(markers.getBounds());
}
fetch('http://myserver.com/myfile.json')
.then(function(response) {
return response.json();
})
.then(doSomething)
.catch(function(err) {
// In case of error, display the error message
console.error(err);
});
Notice that I put your code inside a callback function, as the fetch function is asynchronous.
You can store the geoJSON variable in a separate .js file and import it into the main logic .js file. Try pasting your var geoJsonData in a file called geoJsonData.js, then at the bottom of that file add "module.exports = geoJsonData;". Then on your logic file (ie scripts.js), you can import the variable as is by adding "var geoJsonData = require("./geoJsonData.js"); at the top. Then your call to add the points to the map would be
function geoJsonMarkers() {
$.getJSON(geoJsonData, function (data) {
// this adds the GeoJSON layer to the map once the file is loaded
L.geoJson(data).addTo(mymap);
}
}
I know it can be done with $.getJSON, but I would prefer using L.geoJson, if possible.
You seem to not realize that these 2 functions provide different steps of your workflow, as illustrated by the 2 other answers.
You may be misled by other libraries that provide utility functions which perform both steps for you.
jQuery's $.getJSON is to fetch / retrieve data from your server.
Once you have the resulting JS object, you feed it into Leaflet's L.geoJSON factory to have it converted into Leaflet layers.

How to make MarkerClusterGroup cluster polygons

I am trying to show clusters using markerclustergroups with Polygons. Right now the polygons are shown but the clusters aren't. I have been trying to use center of mass for the polygons because it seems like markerclustergroup doesn't like polygons but that doesn't really work since the animation of markerclustergroup will be set on the centroids and not the actual polygon.
My polygons all vary in amount of coordinates. Some have +10 sets others have 3.
How would I use markerclustergroup for polygons?
Below my code can be seen:
// Create variable to hold map element, give initial settings to map
var map = L.map('map', {
center: [23.70489, 43.90137],
zoom: 5
});
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
}).addTo(map);
var ojStyle = {
"color": "#ff7800",
"weight": 5,
"opacity": 0.65
};
// Hardcoded polygons as GeoJSON
var polygons = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[37.99896240234376, 21.55017532555692],
[39.39422607421876, 21.476073444092435],
[38.88336181640626, 22.56582956966297],
[38.023681640625, 22.611475436593366],
[37.43591308593751, 21.99908185836153],
[37.28485107421876, 21.624239377938288],
[37.28485107421876, 21.624239377938288],
[37.99896240234376, 21.55017532555692]
]
]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[38.50708007812501, 21.453068633086783],
[39.20745849609376, 21.37124437061832],
[39.10858154296876, 20.876776727727016],
[38.80920410156251, 20.912700155617568],
[38.49884033203126, 20.94604992010052],
[38.50708007812501, 21.453068633086783]
]
]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[50.57830810546875, 25.980268007469803],
[50.77606201171876, 25.956809920555312],
[50.780181884765625, 25.69970044378398],
[50.56457519531251, 25.822144306879686],
[50.56182861328126, 25.945696562830516],
[50.57830810546875, 25.980268007469803]
]
]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[54.37408447265626, 24.51963836811676],
[54.29443359375001, 24.40963901896311],
[54.25872802734375, 24.449649897759667],
[54.32739257812501, 24.539627918861232],
[54.37133789062501, 24.559614286039903],
[54.37408447265626, 24.51963836811676]
]
]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[54.40155029296876, 24.463400705082282],
[54.41940307617188, 24.489648077028683],
[54.45785522460938, 24.462150693715266],
[54.43450927734376, 24.43839812102505],
[54.40155029296876, 24.463400705082282]
]
]
}
}]
}
var polygonArray = []
for (i = 0; i < polygons.features.length; i++) {
polygonArray.push(polygons.features[i]);
}
var markers = L.markerClusterGroup().addTo(map);
var geoJsonLayer = L.geoJson(polygonArray);
markers.addLayer(geoJsonLayer);
map.fitBounds(markers.getBounds());
http://js.do/code/165930 - Shows how clustering doesn't work for the polygons
I am looking for a solution like this: http://jsfiddle.net/ve2huzxw/237/
You can do it very much like in this GIS post: Is it possible to cluster polygons in Leaflet?
// Compute a polygon "center", use your favourite algorithm (centroid, etc.)
L.Polygon.addInitHook(function() {
this._latlng = this._bounds.getCenter();
});
// Provide getLatLng and setLatLng methods for
// Leaflet.markercluster to be able to cluster polygons.
L.Polygon.include({
getLatLng: function() {
return this._latlng;
},
setLatLng: function() {} // Dummy method.
});
Updated live example: http://js.do/code/166021

Adding new paths to D3 Globe

I am working on an implementation of a D3 Globe. I am trying to add paths to the globe when the user clicks a button, but this is not proving successful. If I add all paths at once there is no issue, but if I try to add them after a trigger event then it fails. My jsfiddle: http://jsfiddle.net/Guill84/b6xvj76e/1/. I don't think there is an issue with the JSON, as it pops up in the console as expected.
The bit of the script that fails can be found right at the bottom of the fiddle. I paste it below for ease of reference:
$("#clickMe").click(function() {
data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"name": "path1"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": "[[[116.4551,40.2539],[117.5977,44.3408],[116.4551,40.2539]]]"
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path2"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": "[[[116.4551,40.2539],[122.3438,41.0889],[116.4551,40.2539]]]"
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path3"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": "[[[116.4551,40.2539],[105.9961,37.3096],[116.4551,40.2539]]]"
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path4"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": "[[[116.4551,40.2539],[109.5996,35.6396],[116.4551,40.2539]]]"
},
"id": "RML"
}]}
console.log(data);
var svg = d3.select("#body");
flows = svg.selectAll("path")
.data(data)
.enter().append("svg:path")
.attr("d", clip)
.style("stroke", "black")
.attr("id", function(d) {
return d.properties.name.split(' ').join('_')
});
});
The problems are three:
1) Your JSON structure has a problem: the arrays are specified in string format, thus causing an error when used by the clip function.
2) You are binding the data object directly, when you should instead binding data.features which is the array which contains the four paths you need to create.
3) The selection will select the already existing paths for countries. You can avoid this by adding a class to the new paths. For example, classing them as flow.
4) The flows paths are declared inside the scope of their rendering function, therefore they cannot be updated on the refresh function.
Here's your code with the three fixes:
$("#clickMe").click(function () {
// 1) Arrays: Fixed arrays for coordinates so they are not serialized in a string
var data = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "path1"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": [[[116.4551, 40.2539], [117.5977, 44.3408], [116.4551, 40.2539]]]
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path2"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": [[[116.4551, 40.2539], [122.3438, 41.0889], [116.4551, 40.2539]]]
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path3"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": [[[116.4551, 40.2539], [105.9961, 37.3096], [116.4551, 40.2539]]]
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path4"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": [[[116.4551, 40.2539], [109.5996, 35.6396], [116.4551, 40.2539]]]
},
"id": "RML"
}
]
};
console.log(data);
var svg = d3.select("#body");
// 3) Selection: Add a class to avoid collision with existing paths
// 4) Using var declared outside so it can be used on the update function
flows = svg.selectAll("path.flow")
// 2) Data binding: Bind the features property instead, which is an array
.data(data.features);
// 3) Enter nodes: When appending them, class them as flow so they keep separated
flows.enter().append("svg:path")
.classed("flow", true)
.attr("d", clip)
.style("stroke", "black")
.style("stroke-width", "1px")
.attr("id", function (d) {
return d.properties.name.split(' ').join('_')
});
});
Now it works, but I still cannot see the added paths on the globe. The path elements are for sure appended to the DOM of the svg element, though, which solves your initial problem ;)
- UPDATE -
As indicated on the comments, the added paths didn't follow the movement of the globe. That was due to the paths being added to the svg but not updated along the country shapes on the refresh() function (added point 4).
To do so, the selection for these paths should be made available inside the refresh() function (it suffices declaring the var flows at the top of the script), and then adding an update for this selection inside that function. Like this:
function refresh(duration) {
(duration ? feature.transition().duration(duration) : feature).attr("d", clip);
// 4) Added the flows to the paths selection whose d attribute will be updated (only when present)
flows && (duration ? flows.transition().duration(duration) : flows).attr("d", clip);
}
A complete version can be seen on this fiddle: http://jsfiddle.net/oscar_dr/0psy5udk/2/

Openlayers 3 z-ordering of features

I have a vector layer, which contains polygons and points loaded from GEOJSON source. It looks to me, points are always positioned above polygons regardless of their order in source GEOJSON file. See an example definition below. Is there a way, how to position points below polygons on the same layer?
The example:
Points are styled as white and red circle. Polygon is gray.
My GEOJSON looks like this (I even tried to reverse features order in the file):
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"radius": "1000"
},
"geometry": {
"type": "Point",
"coordinates": [
12.4,
50.08333
]
}
},
{
"type": "Feature",
"properties": {
"radius": "800"
},
"geometry": {
"type": "Point",
"coordinates": [
12.4,
50.08333
]
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[
12.4,
50.08333
],
...........
Use zIndex in the style objects.

Categories