Git Product home page Git Product logo

geojson.jl's People

Contributors

alex-s-gardner avatar andygreenwell avatar asinghvi17 avatar cmcaine avatar connectedsystems avatar dependabot[bot] avatar erickchacon avatar evetion avatar garborg avatar github-actions[bot] avatar jbn avatar juliatagbot avatar juliohm avatar meggart avatar rafaqz avatar visr avatar yeesian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

geojson.jl's Issues

Issues trying to read a geojson file

Hi there. I'm new to GeoJSON. I'm having issues trying to load the following json file:
https://github.com/finiterank/mapa-colombia-js/blob/master/colombia-municipios.json

I downloaded it to my computer. This is how I'm trying to read the file:

using GeoJSON, GeoMakie, GLMakie

# Use local geojson file
# Source: https://github.com/finiterank/mapa-colombia-js/blob/master/colombia-municipios.json
filepath = joinpath(@__DIR__, "colombia-municipios.json")
geo = GeoJSON.read(read(filepath)) # TODO: does not work

The issue is that nothing get's loaded (Nothing literally gets stored in geo).

I've investigated a little to see if I could discover what is going wrong.

I actually managed to read and plot the following geojson file:
https://observablehq.com/@john-guerra/spike-map-of-colombian-cities-by-population

I compared the content of both files and I found differences. For example, the one that fails to be read does not have a FeatureCollection or Features in it. However, I find it strange that GitHub is able to visualize it correctly.

Could it be that the first geojson file has a different format that is not supported by GeoJSON.jl?

geo2dict replacement function

Hello,

The older version of the package had a geo2dict function to convert the continents json into a dictionary.
What is the alternative way to doing that with the new updates to the package ?

GeoJSON.read(read(joinpath(@__DIR__,"..","data","continents","continents.json")))
 conts = geo2dict(continents)
 coords = conts["features"][id]["geometry"]["coordinates"]

Thanks

CRS correctness

#sdsl23

We should at least warn if you provide a spatial thing with a (defined?) crs other than wgs84.

Support constructing FeatureCollection from Tables

Right now we can convert FeatureCollection to DataFrames, but not back:

julia> using GeoJSON, DataFrames

julia> p = GeoJSON.Point(coordinates = [1.1, 2.2])
Point([1.1, 2.2])

julia> f = GeoJSON.Feature(p; properties = (a = 1, geometry = "g", b = 2))
Feature with a Point and 3 properties: (:geometry, :a, :b)

julia> features = [f]
1-element Vector{GeoJSON.Feature{NamedTuple{(:type, :geometry, :properties), Tuple{String, GeoJSON.Point{NamedTuple{(:type, :coordinates), Tuple{String, Vector{Float64}}}}, NamedTuple{(:a, :geometry, :b), Tuple{Int64, String, Int64}}}}}}:
 Feature with a Point and 3 properties: (:geometry, :a, :b)

julia> fc = GeoJSON.FeatureCollection(features)
FeatureCollection with 1 Features

julia> df = DataFrame(fc)
1×3 DataFrame
 Row │ geometry           a      b
     │ Geometry           Int64  Int64
─────┼─────────────────────────────────
   1Point([1.1, 2.2])      1      2

julia> GeoJSON.FeatureCollection(df)
ERROR: ArgumentError: column name :features not found in the data frame

It would be nice if this worked. We could also test with GeoDataFrames, and also look at that package for how to identify geometry columns (GeoInterface.geometrycolumns).

Provide support for Geospatial Operations?

I had been porting the functionality for Turf in a separate repository, but that codebase had been designed for javascript apps, and there's [significant] overlap in functionality with DataFrames-type operations, and other packages (in interpolations, etc).

Does it make sense to

  • support a small set of core operations (union/convexhull/within/etc) on individual geometries in GeoJSON.jl, and
  • use DataFrames.jl (see #5) to perform more sophisticated queries/operations?

If so, I'll migrate the relevant portions of the code over from Turf.jl to this repo (to src/turf.jl) through a PR. Your thoughts?

cc @garborg

Migration to JuliaGeo

Migration steps:

  • Transfer ownership to org
  • Flip on coveralls for org (I think Travis is smart enough to handle the transfer automatically)
  • Update urls in README
  • Next time a version is tagged in METADATA, update the url as part of PR

Provide Tests

for

  • MultiLineString
  • MultiPoint
  • parsefile
  • bbox
  • named and linked CRS
  • print
  • keyword in constructors of AbstractGeoJSON objects

JSON3 Array doesn't work with GeoInterface

In the sense that an GeoInterface.coordinates will yield a JSON3 Array that no other package will parse as the coordinates they are.

julia> GeoInterface.coordinates(poly1)
1-element Vector{JSON3.Array}:
 JSON3.Array[[0.1, 0.0], [1.1, 0.2], [0, 1], [0.3, 0.0]]

MultiLineString is converted to Geometry when writing

A MultiLineString is currently being saved as a Polygon. This creates problems when interfacing with other geometry packages because MultiLineStrings are saved as invalid Polygons. So we obtain errors when trying to load this invalid Polygons. This is happening in our GeoTables.jl when intarfecing with GeoJSON.jl (JuliaEarth/GeoTables.jl#24).

Let's consider the following geometry:

d = """{
    "type": "Feature",
    "id": "1",
    "bbox": [-180.0, -90.0, 180.0, 90.0],
    "geometry": {"type": "MultiLineString", "coordinates": [[[3.75, 9.25], [-130.95, 1.52]], [[23.15, -34.25], [-1.35, -4.65], [3.45, 77.95]]]},
    "properties": {"title": "Dict 1"}
}"""
featu = GJS.read(d)

Given that featu is a GeoJSONT, writing to a file works well because it does not to use the _lower function.

GJS.write("nolower.json", featu)
# {"type":"Feature","id":"1","bbox":[-180.0,-90.0,180.0,90.0],"geometry":{"type":"MultiLineString","coordinates":[[[3.75,9.25],[-130.95,1.52]],[[23.15,-34.25],[-1.35,-4.65],[3.45,77.95]]]},"properties":{"title":"Dict 1"}}

However, if we use the _lower function, the MultiLineString is saved as a Polygon.

featul = GJS._lower(featu)
JSON3.write("lower.json", featul)
# {"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[3.75,9.25],[-130.95,1.52]],[[23.15,-34.25],[-1.35,-4.65],[3.45,77.95]]]},"properties":{"title":"Dict 1"},"bbox":[-180.0,-90.0,180.0,90.0]}

The outputs are different when the geometry type should actually be MultiLineString.

Support `Base.filter` on `FeatureCollection`

It would be convenient if you could do something like filter(f -> f.NAME == "France", collection), but currently filtering is not supported.

Right now, I'm naivley pirating this like so:

function Base.filter(f::Function, fc::GeoJSON.FeatureCollection)
    features = [feat for feat in fc if f(feat)]
    GeoJSON.FeatureCollection(; bbox=nothing, features, crs=getfield(fc, :crs))
end

But I'm sure there is potential for improvement.

Feature properties are kinda broken

help?> GI.properties
  GeoInterface.properties(feat) => properties

  Retrieve the properties of feat. This can be any Iterable that behaves like an AbstractRow. Ensures
  backwards compatibility with GeoInterface version 0.

But here we return a Dict which doesn't have getproperty like an AbstractRow

However you can call getproperty on the feature itself as a workaround, its' just confusing - and we cant standardise code accross feature types.

Propertynames of feature collection falsely taken from the first element

I do not know if all GeoJSON features should share the same properties. But if not, the following is a bit of a nuisance.

With GeoJSON 0.6.0

a = """{"type": "FeatureCollection", "features": [
    {"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [0.0, 0.0]]]}, "properties": {"foo": "pippo", "bar": "pluto"}},
    {"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[0.0, 0.0], [-1.0, 0.0], [0.0, -1.0], [0.0, 0.0]]]}, "properties": {"foo": "fulano"}}
]}"""
b = GeoJSON.read(a)

now propertynames(b) gives (:geometry, :bar, :foo).

This is same what I get when tab expanding

julia> b.<TAB>
bar       foo       geometry

There is b.foo

julia> b.foo
2-element Vector{String}:
 "pippo"
 "fulano"

but there is no b.bar

julia> b.bar
ERROR: KeyError: key :bar not found
Stacktrace:
  [1] getindex(h::Dict{Symbol, Int64}, key::Symbol)
    @ Base .\dict.jl:498
  [2] get(obj::JSON3.Object{Base.CodeUnits{UInt8, String}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}, key::Symbol)
    @ JSON3 C:\Users\jaakkor2\.julia\packages\JSON3\GoF7x\src\JSON3.jl:86
  [3] getproperty(obj::JSON3.Object{Base.CodeUnits{UInt8, String}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}, prop::Symbol)
    @ JSON3 C:\Users\jaakkor2\.julia\packages\JSON3\GoF7x\src\JSON3.jl:126
  [4] getproperty(f::GeoJSON.Feature{JSON3.Object{Base.CodeUnits{UInt8, String}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}}, nm::Symbol)
    @ GeoJSON C:\Users\jaakkor2\.julia\packages\GeoJSON\XejMl\src\features.jl:46
  [5] _broadcast_getindex_evalf
    @ .\broadcast.jl:670 [inlined]
  [6] _broadcast_getindex
    @ .\broadcast.jl:643 [inlined]
  [7] getindex
    @ .\broadcast.jl:597 [inlined]
  [8] copyto_nonleaf!(dest::Vector{String}, bc::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Tuple{Base.OneTo{Int64}}, typeof(getproperty), Tuple{Base.Broadcast.Extruded{GeoJSON.FeatureCollection{GeoJSON.Feature{JSON3.Object{Base.CodeUnits{UInt8, String}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}}, JSON3.Object{Base.CodeUnits{UInt8, String}, Vector{UInt64}}, JSON3.Array{JSON3.Object, Base.CodeUnits{UInt8, String}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}}, Tuple{Bool}, Tuple{Int64}}, Base.RefValue{Symbol}}}, iter::Base.OneTo{Int64}, state::Int64, count::Int64)
    @ Base.Broadcast .\broadcast.jl:1055
  [9] copy
    @ .\broadcast.jl:907 [inlined]
 [10] materialize
    @ .\broadcast.jl:860 [inlined]
 [11] getproperty(fc::GeoJSON.FeatureCollection{GeoJSON.Feature{JSON3.Object{Base.CodeUnits{UInt8, String}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}}, JSON3.Object{Base.CodeUnits{UInt8, String}, Vector{UInt64}}, JSON3.Array{JSON3.Object, Base.CodeUnits{UInt8, String}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}}, nm::Symbol)
    @ GeoJSON C:\Users\jaakkor2\.julia\packages\GeoJSON\XejMl\src\features.jl:103
 [12] top-level scope
    @ REPL[96]:1

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

Review departures in behavior from GeoJSON

Follow-up from #30: in that PR, we're made it clearer that

Note that GeoJSON.jl loads features into the GeoInterface.jl format and that this differs from GeoJSON in the following ways:

  • Julia Geometries do not provide a bbox and crs method. If you wish to provide a bbox or crs attribute, wrap the geometry into a Feature or FeatureCollection.
  • Features do not have special fields for id, bbox, and crs. These are to be provided (or found) in the properties field, under the keys featureid, bbox, and crs respectively (if they exist).

When saving GeoJSON, these transformations will be reversed: if properties has a key featureid, that will be removed from properties and a matching member id will be added to the Feature; similarly for crs and bbox.

There was the following question (which is left unaddressed):

I wonder if GeoJSON.jl should also warn or error if it would overwrite existing properties when doing these transformations. I think it should.

Opening this issue for discussions before we have a resolution for it.

geojson strips 'properties' field from a feature

When converting a geoJSON object to either a dict or printing a json string, the "properties" element of each Feature seems not to be included.

a = """{
    "properties": {
        "Ã": "Ã"
    },
    "type": "Feature",
    "geometry": null,
    "crs": {
        "type": "link",
        "properties": {
            "href": "data.crs",
            "type": "ogcwkt"
        }
    }
}"""

a = GeoJSON.parse(a)
geojson(a)

output:

"{\"geometry\":null,\"type\":\"Feature\",\"crs\":{\"properties\":{\"href\":\"data.crs\",\"type\":\"ogcwkt\"},\"type\":\"link\"}}"

Abstract types for compatibility with LibGEOS

If I have, say, a GeoJSON.LineString

ls_json = GeoJSON.LineString([[1.0,2.0],[3.0,4.0]])

and would like to convert it to a LibGEOS.LineString

LibGEOS.LineString(ls_json)

I get a MethodError

MethodError: Cannot `convert` an object of type GeoJSON.LineString to an object of type LibGEOS.LineString
This may have arisen from a call to the constructor LibGEOS.LineString(...),
since type constructors fall back to convert methods.

 in LibGEOS.LineString(::GeoJSON.LineString) at ./sysimg.jl:53

LibGEOS does have a method for converting any GeoInterface.AbstractLineString to a LibGEOS.LineString:

methods(LibGEOS.LineString)
# 4 methods for generic function "(::Type)":
…
LibGEOS.LineString{T<:GeoInterface.AbstractLineString}(obj::T) at ~/.julia/v0.5/LibGEOS/src/geos_types.jl:36
(::Type{T}){T}(arg) at sysimg.jl:53

but GeoJSON.LineString is not a GeoInterface.AbstractLineString

LibGEOS.LineString <: GeoInterface.AbstractLineString
true
GeoJSON.LineString <: GeoInterface.AbstractLineString
false

and so I end up having to do the conversion myself

LibGEOS.LineString(ls_json.coordinates)

which admittedly isn't the end of the world, but it would be convenient and elegant if GeoJSON.LineString were a subtype of GeoInterface.AbstractLineString.

Geometry coordinates aren't parsed as the same type

julia> a = """{"type": "FeatureCollection", "features": [
           {"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[0.1, 0.0], [1, 0.2], [0.0, 1.0], [0.3, 0.0]]]}}
           ]}"""
julia> poly1 = GeoJSON.read(a)[1].geometry
julia> poly1[1]
4-element JSON3.Array{JSON3.Array, Base.CodeUnits{UInt8, String}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}:
 [0.1, 0.0]
 Union{Float64, Int64}[1, 0.2]
 [0, 1]  # <-- Int64
 [0.3, 0.0]

Bring GeoInterface concrete types over here

The concrete types in GeoInterface.jl were written initially for this package and thus are a pretty good match. But if we want GeoInterface to support a wide selection of concrete types we probably need to move to an approach similar to Tables.jl, meaning we can take the concrete types out of GeoInterface.jl

Step one would be to move the types more or less as is. But possibly we directly switch the concrete types over to GeometryTypes, as suggested in JuliaGeo/GeoInterface.jl#24?

Geometries not being read properly

I've posted a question at Stackoverflow, but I guess I should post it here as well. In a nutshell, I'm reading a layer with census tracts, neighbourhoods, and districts in Barcelona and the census tracts aren't being read properly. It's not a problem with the data, since it reads fine in R. It looks like it's reading the polygon coordinates in the wrong order.
Here's the SO question with all the code and plots.
https://stackoverflow.com/questions/74126814/geojson-jl-reading-some-geometries-incorrectly

Use GeometryBasics types

When GeometryBasics works with GeoInterface, we will need to switch to using GeometryBasics.jl types here, as the GeoInterface types used currently will go away.

Does this make sense? Just adding this before I write it in case there are other opinions.

Extracting a set of features from FeatureCollection

For a given FeatureCollection, it would be useful to be able to retrieve a set of features, such as:

geodata = GeoJSON.read("some geojson file")

# This works
geodata[1]

# This is not supported
geodata[1:10]

I could submit a PR to do this if there is interest. I believe an additional function hooking into getindex in the general location below would do fine:

https://github.com/JuliaGeo/GeoJSON.jl/blob/f88f2c121bc7c6994fb055171fe663af46ad74a1/src/geojson_types.jl#L268C1-L268C71

Alternatively, if the above isn't desirable, what is the GeoJSON "way" of extracting a set of features?

Handle GeoFormatTypes `GeoJSON` objects

It would be good if an object we already know is GeoFormatTypes.GeoJSON would pass through GeoJSON.write. It will already be a Dict or String. The string is assumed to be correctly formatted JSON so would not need anything done. A Dict would go to JSON3.write.

We could even wrap the output as a GeoJSON string, but maybe that's going to far for now... It would be like JSString in WebIO.jl that wraps javascipt strings.

The use case for this is to allow users to pass in various objects that need different degrees of processing to be formatted as GeoJSON, and they all work.

Widen the scope of `GeoJSON.write`

It seems that write does not work with all AbstractGeometry. I'm not sure if that is intentional. But currently e.g. ArchGDAL.IGeometry does not work.

julia> using GADM, GeoJSON

julia> GeoJSON.write(GADM.get("MUS").geom[1])
ERROR: MethodError: no method matching write(::ArchGDAL.IGeometry{ArchGDAL.wkbMultiPolygon})
Closest candidates are:
  write(::AbstractFeatureCollection) at ~/.julia/packages/GeoJSON/JVqvX/src/GeoJSON.jl:40
  write(::AbstractGeometryCollection) at ~/.julia/packages/GeoJSON/JVqvX/src/GeoJSON.jl:40
  write(::AbstractFeature) at ~/.julia/packages/GeoJSON/JVqvX/src/GeoJSON.jl:40
  ...
Stacktrace:
 [1] top-level scope
   @ REPL[33]:1

In the docs we say that any AbstractGeometry will work:

help?> GeoJSON.write
  write(obj)

  Create a GeoJSON string from an object that implements the GeoInterface, either AbstractGeometry,
  AbstractFeature or AbstractFeatureCollection.

The current workaround is to wrap in a Feature.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.