I'm trying to take a series of GeoJSON Line Strings and put them on a map. My jBuilder and Rails controller combination is not producing correctly formatted json for putting on a web map. Here's the relevant code.
overview_data.json.builder
json.type "FeatureCollection"
json.features #segments do |street|
if (street.extent_json) # only if item has a line drawn
json.type "Feature"
json.properties do
json.title "Was #{street.prevName} before #{street.dateEarliest} and now is #{street.currentName} #{street.dateLatest})"
end
json.geometry do
# json.type "LineString"
json.coordinates street.extent_json
end # json.geometry
end # if
end # json.features
overview_controller.rb
class OverviewController < ApplicationController
def index
end
def overview_data
#segments = Street.all
end
end
street.extent_json as it appears in a web form and in the database (Postgres via pgAdmin)
{"type":"LineString",
"coordinates":[[-118.25712423772116,34.01007010760971],
[-118.25649456380442,34.01016443793837],
[-118.25584971702219,34.01016443793837],
[-118.25427932544667,34.0102021700405],
[-118.25213995141625,34.010227324765935]]}
Output as seen in http://localhost:3000/overview/overview_data.json. At present there are about ten items that have extent_json. Below are the first few:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"title": "Was 10th St. before 1903 and now is part of E. 9th Place (21). 1908)"
},
"geometry": {
"coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.24982816353442,34.035546195508864],[-118.25104052200915,34.03663976724366]]}"
}
},
{
"type": "Feature",
"properties": {
"title": "Was 37th St before 1903 and now is part of E. 40th Place 1928)"
},
"geometry": {
"coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.25712423772116,34.01007010760971],[-118.25649456380442,34.01016443793837],[-118.25584971702219,34.01016443793837],[-118.25427932544667,34.0102021700405],[-118.25213995141625,34.010227324765935]]}"
}
},
{
"type": "Feature",
"properties": {
"title": "Was Brook before 1903 and now is part of S. Toluca St. (26). and second block south gone 1908)"
},
"geometry": {
"coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.25862396508458,34.06087254304104],[-118.25933206826451,34.05994816216629]]}"
}
},
{
"type": "Feature",
"properties": {
"title": "Was Auto Pl before 1928 and now is Commonwealth Pl and a portion abandoned 1930)"
},
"geometry": {
"coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.28558737412096,34.07543021182353],[-118.28369373455645,34.07646106299854]]}"
}
},
{
"type": "Feature",
"properties": {
"title": "Was 3rd St before 1921 and now is Miramar St. One block abandoned )"
},
"geometry": {
"coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.26117539280003,34.05901974362122],[-118.2593849946753,34.05823410691563],[-118.25815599257271,34.05768101430694],[-118.25759459655055,34.05717191451128],[-118.25663111959356,34.05654339202722]]}"
}
},
{
"type": "Feature",
"properties": {
"title": "Was Gregory Way before and now is Gregory Way 2017)"
},
"geometry": {
"coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.37295765057208,34.06188579510917],[-118.37272698059681,34.06172580874592],[-118.37264114990832,34.06161026285129],[-118.3725660480559,34.06146805230318],[-118.37253386154772,34.061414723286084],[-118.37249631062151,34.06118363049104]]}"
}
},
The problem is the added "{\"type\":\"LineString\",\"coordinates\" and closing }". Otherwise I think it's OK.
In the jBuilder I originally had json.type "LineString" in the json.geometry do loop and it's even worse adding: "geometry":{"type":"LineString","coordinates":"{\"type\":\"LineString\",\"coordinates\".
As Зелёный pointed out json.coordinates JSON.parse(street.extent_json) replacing similar line was needed. As he also pointed out I must have had some malformed json inputs which I did. Once that was cleaned up everything is working.
He also pointed out "in jbuilder template all things must be in plain Ruby, but you pass a json string(which comes from database) as result Rails tried to convert json string to json again."
But output still has an error, here's the first item:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"title": "Was 10th St. before 1903 and now is part of E. 9th Place (21). 1908)"
},
"geometry": {
"coordinates": {
"type": "LineString",
"coordinates": [
[
-118.24982816353442,
34.035546195508864
],
[
-118.25104052200915,
34.03663976724366
]
]
}
}
},
An extra {
"coordinates": after geometry.
The problem is in extent_json method, it returns an object as json string. To resolve your issue, avoid the double call to_json.
To restate the problem: take a series of GeoJSONs from a database and use jBuilder to compile all the items that meet a certain criteria into a GeoJSON (for use in a Mapbox/Leaflet web map). https://stackoverflow.com/users/2057388/Зелёный provided the answer offline, but I want to document it to make sure I understand it and help anyone else with a similar problem. It helps to consider the jsons as hashes and that jbuilder is making another hash.
The input has two keys: type and coordinates.
The output has keys of type, properties, and geometry.
The properties value is a key title;
the geometry values are two keys type and coordinates. So overview_data.json.builder becomes:
extent = JSON.parse(street.extent_json) # the GeoJSON
json.type "Feature"
json.properties do
json.title h("Was #{street.prevName} before #{street.dateEarliest} and now is #{street.currentName} #{street.dateLatest}.")
end
json.geometry do
json.type "LineString"
json.coordinates extent["coordinates"]
end
Looks straightforward once it's laid out. Except for other key points. One was parsing extent_json to convert the string to a hash object. Then coordinates are extracted from that hash to put into the output json.
Related
I have strings like
POLYGON ((32.5 39.2, 32.6 39.4 .... ))
POINT (32.4 39.2)
using Leaflet, React is there a way to convert these string to GeoJSON like:
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
}
in JavaScript?
These strings are called WKT (https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry).
There are quite a few parsers out there:
https://www.npmjs.com/search?q=wkt
"wellknown" and "wicket" can output GeoJSON, probably there are other modules that support this too.
Note that WKT represents just "geometry" field in GeoJSON, content of "properties" field should come from somewhere else (say if this was CSV - from other CSV columns).
I tried to manipulate an object GEOjson to display it in my map OpenLayers. But my GEOjson is invalid.
First, in my API I request to my database to recover the geometry, then I parse it thanks to GEOjson.parse : GeoJSON.parse(data, {GeoJSON : 'geometry'});
the data looks like this :
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[0.699526704561417,49.5855766259652],[0.699132813373672,49.5855472259388],[0.698829663954256,49.5852457878428],[0.698308423811369,49.5855523688003],[0.699127661396565,49.5862481964213],[0.699752271011022,49.5859030239836],[0.699526704561417,49.5855766259652]]]]}",
"properties": {
"libgeo": "Bois-Himont",
"nature": "Parcelle bâtie"
}
},
{
"type": "Feature",
"geometry": "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[0.696220319484454,49.581274516207],[0.696272071456392,49.5820438187077],[0.697147417334422,49.5815673912038],[0.697102005023975,49.5814546891317],[0.697047441685103,49.5812624281067],[0.6969844037675,49.5812621313821],[0.696220319484454,49.581274516207]]]]}",
"properties": {
"libgeo": "Bois-Himont",
"nature": "Parcelle bâtie"
}
}, etc...
Then in my script.js (that files had the aim to display the map and the GEOjson) I parse the data thanks to JSON.parse, but the line geometry is invalid because there is an extra " and the type and the coordinates is surrounded by ".
How can I delete the extra " and delete the " for the type and the coordinates ?
The geometry is a string when it should be an object. After the first parse you will need loop through the features and parse each geometry string into an object.
var myGeoJSON = JSON.parse(myText);
myGeoJSON.features.forEach( function(feature) { feature.geometry = JSON.parse(feature.geometry) });
currently my webAPI method returns to me a long string for a GeoJSON layer that i need to parse through and separate out into mutliple variables that allows for me to create my necessary GeoJSON layer. Can i accomplish this easily through the str.split function or is a there another route that i need to take
The returned string from the webAPI looks like this:
{"type":"FeatureCollection","bbox":[1108864.9370570681,507099.9482870581,1109064.5346246646,507455.89728260477],"features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[1109035.4443840273,507308.60334444791],[1108893.4509952962,507307.23951566964],[1108893.1628068388,507337.23816090077],[1109035.1562700756,507338.60198967904],[1109035.4443840273,507308.60334444791]]]},"properties":{"twp":"01","map_num":"8.0","sec":"33.00","qtr_sec":"003","map_block":"007","parcel":"008.00","pid":"018.033.00003007008.00","gis_acres":"0.0977962","debbie_ac":"0.10c","misc":"","scan_deeds":"T:\\Images\\Hyperlinked_Deeds\\00203","latitude":"37.2227488237","longitude":"-89.5082666075","name":"O'RILEY PROPERTIES LLC","site_addre":"519 MADISON ST","shape_leng":"344.000009295","shape_area":"4260.00340015","card_ac":"0.00c 0.00d","date":"1/1/0001 12:00:00 AM","ParcelId":"203","ParcelNumber":"0180330000300700800","_hg_layer":"PARCELS"}}
The features section of the string has an array of features but for use in this example i only copied of one specific feature that. the format I'm looking to set this up in is as follows:
var geojsonObject = {
'type': 'FeatureCollection',
'crs': {
'type': 'name',
'properties': {
//'name': 'EPSG:3857'
}
},
'features': [
{
"type": "Feature", "geometry":
{
"type": "Polygon", "coordinates": [[[1109035.4443840273, 507308.60334444791],
[1108893.4509952962, 507307.23951566964],
[1108893.1628068388, 507337.23816090077],
[1109035.1562700756, 507338.60198967904],
[1109035.4443840273, 507308.60334444791]]]
, "properties": {
"twp": "01",
"map_num": "8.0",
"sec": "33.00",
"qtr_sec": "003",
"map_block": "007",
"parcel": "008.00",
"pid": "018.033.00003007008.00",
"gis_acres": "0.0977962",
"debbie_ac": "0.10c",
"misc": "",
"scan_deeds": "T:\\Images\\Hyperlinked_Deeds\\00203",
"latitude": "37.2227488237",
"longitude": "-89.5082666075",
"name": "O'RILEY PROPERTIES LLC",
"site_addre": "519 MADISON ST",
"shape_leng": "344.000009295",
"shape_area": "4260.00340015",
"card_ac": "0.00c 0.00d",
"date": "1/1/0001 12:00:00 AM",
"ParcelId": "203",
"ParcelNumber": "0180330000300700800",
"_hg_layer": "PARCELS"
}
}
}
Again the features section of this code in my example just shows one specific feature but i will actually have several features that i need to display.
is parsing through this long string the easiest route to go or do i need to restructure the string that my WebAPI actually sends back to me
I am trying to list all my features from a GeoJSON file in a table on a website and i am stuck figuring out how to achieve this.
As a first step i built a Leaflet map showing all locations loaded from the GeoJSON file which works pretty good.
What i would like to have in addition to the map is a rating system on a second page, which features all the locations from the GeoJSON in a table (I only need names for now, the rating system would be a different problem...).
Note that i am an absolute beginner and need a very detailed "tutorial" for this.
My GeoJSON looks like this:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ x,y ]
},
"properties": {
"FID":0,
"Shape *":"Point",
"Name":"XXX",
"Ditrict":"Dist1",
"Str_No":"Street 1",
"ZIP":"Some ZIP",
"Phone":"Some Number",
"Rating":4.5
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ x,y ]
}, and so on
I hope that there is a simple solution for this.
Thank you in advance!
If your GeoJSON object is var geoJSON, you can get all the names for each feature by doing the following:
var featureNames = [];
for (var i = 0; i < geoJSON.features.length; i++) {
var currentFeature = geoJSON.features[i];
var featureName = currentFeature.properties.Name;
var featureId = currentFeature.properties.FID;
console.log(featureName);
featureNames.push({ featureId: featureId, featureName : featureName });
}
So featureNames will have each feature object with it's name in an array.
To put them all in a table, I'm going to use jQuery DataTables. If I have a <div id="myTable">, then:
$('#myTable').DataTable( {
"columnDefs": [
{ "title": "Feature Names", "targets": 0 }
]
data: featureNames,
scrollY: 300,
paging: false
} );
I'm new to Javascript and hence I'm a little lost. I am able to read from a GeoJSON file; however, I do not understand how to iterate through the file to get the Lat-Long of the points, and then display those points as markers in Leaflet. I am hoping to also use the plugin Awesome Markers (based on font-awesome, for Leaflet)
This is a sample of my GeoJSON file:
{ "type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": { "Street Nam": "Aljunied Avenue 2", " Block": "118 Aljunied Avenue 2", " Postal Co": "380118", " Latitude": 1.320440, "Longitude": 103.887575 },
"geometry": { "type": "Point", "coordinates": [ 103.887575, 1.320440 ] } }
,
{ "type": "Feature", "properties": { "Street Nam": "Aljunied Crescent", " Block": "97A Aljunied Crescent", " Postal Co": "381097", " Latitude": 1.321107, "Longitude": 103.886127 },
"geometry": { "type": "Point", "coordinates": [ 103.886127, 1.321107 ] } }
]
}
Thank you for your attention and time =)
Process the geojson as described in the leaflet documentation. Specify a pointToLayer function which creates a marker with an awesome icon:
L.geoJson(geoJson, {
pointToLayer: function (feature, latlng) {
return L.marker(latlng,
{icon: L.AwesomeMarkers.icon(
<< options based on feature.properties >>
)});
}
}).addTo(map);
After reading the file, you should have a javascript object that represents all the data in the file:
var geoData = JSON.parse(fileContents);
var features = geoData.features;
and so on. The parsed data will be converted to objects or arrays depending on whether they are key/value dictionaries or just lists. So from the above
var feature = geoData.features[0];
will get you a reference to the first feature object in the list. If you write
console.log(geoData);
and run with any recent browser you should be able to see an expandable description of the data to help make sense of it all.