# Interaction of GeoJSON with GeoInterface methods

**URL:** <https://discourse.julialang.org/t/interaction-of-geojson-with-geointerface-methods/96535>\
**Category:** Geo\
**Tags:** question\
**Created:** [March 23, 2023, 8:27pm UTC](https://discourse.julialang.org/t/interaction-of-geojson-with-geointerface-methods/96535 "2023-03-23T20:27:11Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)\
**Post date:** [March 23, 2023, 8:27pm UTC](https://discourse.julialang.org/t/interaction-of-geojson-with-geointerface-methods/96535/1 "2023-03-23T20:27:11Z")

</div>

Hi,

I’d like to read a `.geojson` file and perform some geometrical operations on the geometries (union, contains, etc.).  
Using LibGEOS or ArchGDAL works fine, but i’ve got some troubles with `GeoJSON` (maybe I’m missing something).

Say I have a `featureCollection` named `col`:

```julia
julia> typeof(col)
GeoJSON.FeatureCollection{GeoJSON.Feature{JSON3.Object{Vector{UInt8}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}}, JSON3.Object{Vector{UInt8}, Vector{UInt64}}, JSON3.Array{JSON3.Object, Vector{UInt8}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}}

```

When I try to perform a `GI.contains` check, I get:

```julia
julia> import GeoInterface as GI
julia> GI.contains(col.geometry[2], col.geometry[1])
ERROR: MethodError: no method matching contains(::GeoInterface.PointTrait, ::GeoInterface.PointTrait, ::GeoJSON.Point{JSON3.Object{Vector{UInt8}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}}, ::GeoJSON.Point{JSON3.Object{Vector{UInt8}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}})
Closest candidates are:
  contains(::Union{GeoInterface.CircularStringTrait, GeoInterface.CompoundCurveTrait, GeoInterface.CurvePolygonTrait, GeoInterface.GeometryCollectionTrait, GeoInterface.LineStringTrait, GeoInterface.LinearRingTrait, GeoInterface.MultiLineStringTrait, GeoInterface.MultiPointTrait, GeoInterface.MultiPolygonTrait, GeoInterface.MultiSurfaceTrait, GeoInterface.PointTrait, GeoInterface.PolygonTrait, GeoInterface.PolyhedralSurfaceTrait, GeoInterface.TINTrait, GeoInterface.TriangleTrait}, ::Union{GeoInterface.CircularStringTrait, GeoInterface.CompoundCurveTrait, GeoInterface.CurvePolygonTrait, GeoInterface.GeometryCollectionTrait, GeoInterface.LineStringTrait, GeoInterface.LinearRingTrait, GeoInterface.MultiLineStringTrait, GeoInterface.MultiPointTrait, GeoInterface.MultiPolygonTrait, GeoInterface.MultiSurfaceTrait, GeoInterface.PointTrait, GeoInterface.PolygonTrait, GeoInterface.PolyhedralSurfaceTrait, GeoInterface.TINTrait, GeoInterface.TriangleTrait}, ::ArchGDAL.AbstractGeometry, ::ArchGDAL.AbstractGeometry) at ~/.julia/packages/ArchGDAL/pPZyn/src/geointerface.jl:184
  contains(::GeoInterface.AbstractGeometryTrait, ::GeoInterface.AbstractGeometryTrait, ::LibGEOS.AbstractGeometry, ::LibGEOS.AbstractGeometry) at ~/.julia/packages/LibGEOS/Wbmhr/src/geo_interface.jl:145
  contains(::Any, ::Any) at ~/.julia/packages/GeoInterface/246K4/src/interface.jl:485
Stacktrace:
 [1] contains(a::GeoJSON.Point{JSON3.Object{Vector{UInt8}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}}, b::GeoJSON.Point{JSON3.Object{Vector{UInt8}, SubArray{UInt64, 1, Vector{UInt64}, Tuple{UnitRange{Int64}}, true}}})
   @ GeoInterface ~/.julia/packages/GeoInterface/246K4/src/interface.jl:485
 [2] top-level scope
   @ REPL[270]:1

```

Otherwise, it works fine with e.g. `ArchGDAL`:

```julia
julia> typeof(p)
ArchGDAL.IGeometry{ArchGDAL.wkbPolygon}

julia> GI.contains(p, p)
true

```

Before I fill an issue on Github, any ideas?  
Or maybe I’m trying to do something out of the package’s scope?

As a workaround, I currently load the `geojson` using `GeoDataFrames`. That’s a bit of a heavy machinery for that simple task.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [March 23, 2023, 9:32pm UTC](https://discourse.julialang.org/t/interaction-of-geojson-with-geointerface-methods/96535/2 "2023-03-23T21:32:47Z")

</div>

Try master of GeoJSON.jl. we are about to register major changes.

---

<div class="post-metadata">

**Author:** ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)\
**Post date:** [March 23, 2023, 10:14pm UTC](https://discourse.julialang.org/t/interaction-of-geojson-with-geointerface-methods/96535/3 "2023-03-23T22:14:32Z")

</div>

Thanks for the quick answer.  
Unfortunately, this doesn’t change the outcome:

```julia
julia> using GeoJSON

julia> poi = GeoJSON.read(read("test.geojson"))
FeatureCollection with 1 Features

julia> poi[1].geometry
2D Polygonwith 1 sub-geometries

julia> import GeoInterface as GI

julia> GI.geomtrait(poi[1].geometry)
GeoInterface.PolygonTrait()

julia> GI.contains(poi[1].geometry, poi[1].geometry)
ERROR: MethodError: no method matching contains(::GeoInterface.PolygonTrait, ::GeoInterface.PolygonTrait, ::GeoJSON.Polygon{2, Float32}, ::GeoJSON.Polygon{2, Float32})
Closest candidates are:
  contains(::Any, ::Any) at ~/.julia/packages/GeoInterface/246K4/src/interface.jl:485
Stacktrace:
 [1] contains(a::GeoJSON.Polygon{2, Float32}, b::GeoJSON.Polygon{2, Float32})
   @ GeoInterface ~/.julia/packages/GeoInterface/246K4/src/interface.jl:485
 [2] top-level scope
   @ REPL[5]:1

```

The error message is different, though.

BTW, I’m running on v1.8.5.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [March 23, 2023, 10:27pm UTC](https://discourse.julialang.org/t/interaction-of-geojson-with-geointerface-methods/96535/4 "2023-03-23T22:27:56Z")

</div>

Oh sorry I misunderstood.

`contains` is not defined for GeoJSON.jl. There is no default method.

So you have to choose a package method. I have PRs to both LibGeos and ArchGDAL so you can do `ArchGDAL.contains` or `LibGEOS.contains` for GeoJSON.jl or any other geometries. But they are not merged because they need the GeoInterface wrappers PR, which is nearly done.

But there is a lot of machinery to orchestrate here so l these nethods can just work on any possible object, and its not finished.

@evetion this situation is pretty confusing still I guess

---

<div class="post-metadata">

**Author:** ![evetion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evetion/32/22679_2.png) [@evetion](https://discourse.julialang.org/u/evetion)\
**Post date:** [March 24, 2023, 7:27am UTC](https://discourse.julialang.org/t/interaction-of-geojson-with-geointerface-methods/96535/5 "2023-03-24T07:27:46Z")

</div>

Hmm yeah, this is sorta expected, but not documented for end-users.  
And being able to test an interface would be nice for us developers.

From what I understand, you will now let ArchGDAL and LibGEOS now about wrapper types, and then we can add a generic fallback to a wrapper convert for the API? I’m not sure how the last part would work generically.

Besides, ideally we also want `GI.intersects`. Do we want to try and solve this via pkg extensions, or how Plots solves it with `pyplot()` to choose a backend?

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [March 24, 2023, 7:57am UTC](https://discourse.julialang.org/t/interaction-of-geojson-with-geointerface-methods/96535/6 "2023-03-24T07:57:45Z")

</div>

The wrappers are just for the conversion tests, but I also used them to make sure the wrappers are useful.

There are generic methods to convert from any geometry types.

But yeah we have just avoided the backend problem so far, but Im not sure if its better than just doing e.g. `LibGEOS.intersects`. Basically all of those methods are covered by my PRs.

---

<div class="post-metadata">

**Author:** ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)\
**Post date:** [March 24, 2023, 9:25am UTC](https://discourse.julialang.org/t/interaction-of-geojson-with-geointerface-methods/96535/7 "2023-03-24T09:25:35Z")

</div>

Thanks guys for your supports.

Being able to choose a backend (with a default, of course) would allow to be readily compatible with your geometric library of choice, and simplify the maintenance of `GeoJSON` regarding support of geometric entities (i.e. no need to reinvent the wheel one more time).

You may already be aware of that of course, but it’s just to say, from my point of view (as an end-user), this would make a lot of sense.

Also, this may allow GeoDataFrames to defer the responsibility of `.geojson` parsing to `GeoJSON`?
