Support FeatureCollection and MultiPolygon in geozones
We're reworking the format validation to correctly interpret feature collection, feature, and geometry, according to RFC 7946 [1]. Since Leaflet interprets GeoJSON format, we're rendering the GeoJSON as a layer instead of as a set of points. For that, we're normalizing the GeoJSON to make sure it contains either a Feature or a FeatureCollection. We're also adding the Leaflet images to the assets path so the markers used for point geometries are rendered correctly. Note we no longer allow a GeoJSON containing a geometry but not a defined type. Since there might be invalid GeoJSON in existing Consul Democracy databases, we're normalizing these existing geometry objects to be part of a feature object. We're also wrapping the outline points in a FeatureCollection object because most of the large GIS systems eg ArcGIS, QGIS export geojson as a complete FeatureCollection. [1] https://datatracker.ietf.org/doc/html/rfc7946 Co-authored-by: Javi Martín <javim@elretirao.net>
This commit is contained in:
@@ -18,10 +18,20 @@ describe Geozone do
|
||||
end
|
||||
|
||||
it "is not valid with invalid geojson file format" do
|
||||
geozone.geojson = '{"geo\":{"type":"Incorrect key","coordinates": [
|
||||
[40.8792937308316, -3.9259027239257],
|
||||
[40.8788966596619, -3.9249047078766],
|
||||
[40.8789131852224, -3.9247799675785]]}}'
|
||||
geozone.geojson = <<~JSON
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Incorrect",
|
||||
"coordinates": [
|
||||
[40.8792937308316, -3.9259027239257],
|
||||
[40.8788966596619, -3.9249047078766],
|
||||
[40.8789131852224, -3.9247799675785]
|
||||
]
|
||||
}
|
||||
}
|
||||
JSON
|
||||
|
||||
expect(geozone).not_to be_valid
|
||||
end
|
||||
|
||||
@@ -54,99 +64,149 @@ describe Geozone do
|
||||
end
|
||||
|
||||
describe "#outline_points" do
|
||||
it "returns empty array when geojson is nil" do
|
||||
expect(geozone.outline_points).to eq([])
|
||||
it "returns nil when geojson is nil" do
|
||||
geozone.geojson = nil
|
||||
|
||||
expect(geozone.outline_points).to be nil
|
||||
end
|
||||
|
||||
it "returns coordinates array when geojson is not nil" do
|
||||
geozone = build(:geozone, geojson: '{
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[40.8792937308316, -3.9259027239257],
|
||||
[40.8788966596619, -3.9249047078766],
|
||||
[40.8789131852224, -3.9247799675785]
|
||||
]
|
||||
it "returns normalized feature collection when geojson is a valid FeatureCollection" do
|
||||
geozone.geojson = <<~JSON
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[
|
||||
[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224],
|
||||
[-3.9259027239257, 40.8792937308316]
|
||||
]]
|
||||
}
|
||||
}]
|
||||
}
|
||||
}')
|
||||
JSON
|
||||
|
||||
expect(geozone.outline_points).to eq(
|
||||
[[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224]]
|
||||
)
|
||||
expected = {
|
||||
type: "FeatureCollection",
|
||||
features: [{
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "Polygon",
|
||||
coordinates: [[
|
||||
[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224],
|
||||
[-3.9259027239257, 40.8792937308316]
|
||||
]]
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
expect(geozone.outline_points).to eq expected.to_json
|
||||
end
|
||||
|
||||
it "handles coordinates with three-dimensional arrays" do
|
||||
geozone = build(:geozone, geojson: '{
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[[40.8792937308316, -3.9259027239257],
|
||||
[40.8788966596619, -3.9249047078766],
|
||||
[40.8789131852224, -3.9247799675785]]]
|
||||
it "returns normalized feature collection when geojson is a valid Feature" do
|
||||
geozone.geojson = <<~JSON
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[
|
||||
[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224],
|
||||
[-3.9259027239257, 40.8792937308316]
|
||||
]]
|
||||
}
|
||||
}
|
||||
}')
|
||||
JSON
|
||||
|
||||
expect(geozone.outline_points).to eq(
|
||||
[[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224]]
|
||||
)
|
||||
expected = {
|
||||
type: "FeatureCollection",
|
||||
features: [{
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "Polygon",
|
||||
coordinates: [[
|
||||
[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224],
|
||||
[-3.9259027239257, 40.8792937308316]
|
||||
]]
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
expect(geozone.outline_points).to eq expected.to_json
|
||||
end
|
||||
|
||||
it "handles coordinates with three-dimensional arrays with spaces between brackets" do
|
||||
geozone = build(:geozone, geojson: '{
|
||||
"geometry": {
|
||||
it "returns normalized feature collection when geojson is a valid Geometry object" do
|
||||
geozone.geojson = <<~JSON
|
||||
{
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[
|
||||
[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224],
|
||||
[-3.9259027239257, 40.8792937308316]
|
||||
]]
|
||||
}
|
||||
}
|
||||
JSON
|
||||
|
||||
expected = {
|
||||
type: "FeatureCollection",
|
||||
features: [{
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "Polygon",
|
||||
coordinates: [[
|
||||
[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224],
|
||||
[-3.9259027239257, 40.8792937308316]
|
||||
]]
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
expect(geozone.outline_points).to eq expected.to_json
|
||||
end
|
||||
|
||||
it "returns normalized feature collection when geojson is a valid top-level Geometry object" do
|
||||
geozone.geojson = <<~JSON
|
||||
{
|
||||
"type": "Polygon",
|
||||
"coordinates": [[
|
||||
[40.8792937308316, -3.9259027239257],
|
||||
[40.8788966596619, -3.9249047078766],
|
||||
[40.8789131852224, -3.9247799675785]
|
||||
[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224],
|
||||
[-3.9259027239257, 40.8792937308316]
|
||||
]]
|
||||
}
|
||||
}')
|
||||
JSON
|
||||
|
||||
expect(geozone.outline_points).to eq(
|
||||
[[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224]]
|
||||
)
|
||||
end
|
||||
expected = {
|
||||
type: "FeatureCollection",
|
||||
features: [{
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "Polygon",
|
||||
coordinates: [[
|
||||
[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224],
|
||||
[-3.9259027239257, 40.8792937308316]
|
||||
]]
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
it "handles coordinates with four-dimensional arrays" do
|
||||
geozone = build(:geozone, geojson: '{
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[[[40.8792937308316, -3.9259027239257],
|
||||
[40.8788966596619, -3.9249047078766],
|
||||
[40.8789131852224, -3.9247799675785]]]]
|
||||
}
|
||||
}')
|
||||
|
||||
expect(geozone.outline_points).to eq(
|
||||
[[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224]]
|
||||
)
|
||||
end
|
||||
|
||||
it "handles coordinates with four-dimensional arrays with spaces between brackets" do
|
||||
geozone = build(:geozone, geojson: '{
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[[
|
||||
[40.8792937308316, -3.9259027239257],
|
||||
[40.8788966596619, -3.9249047078766],
|
||||
[40.8789131852224, -3.9247799675785]
|
||||
]]]
|
||||
}
|
||||
}')
|
||||
|
||||
expect(geozone.outline_points).to eq(
|
||||
[[-3.9259027239257, 40.8792937308316],
|
||||
[-3.9249047078766, 40.8788966596619],
|
||||
[-3.9247799675785, 40.8789131852224]]
|
||||
)
|
||||
expect(geozone.outline_points).to eq expected.to_json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user