Fix a crash in case of invalid geometry

This commit is contained in:
Paul Chavard 2020-05-05 10:26:13 +02:00
parent a1b32ae419
commit 6556df2a85
5 changed files with 83 additions and 38 deletions

View file

@ -58,8 +58,8 @@ class Champs::CarteChamp < Champ
bounding_box = RGeo::Cartesian::BoundingBox.new(factory) bounding_box = RGeo::Cartesian::BoundingBox.new(factory)
if geo_areas.present? if geo_areas.present?
geo_areas.each do |area| geo_areas.map(&:rgeo_geometry).compact.each do |geometry|
bounding_box.add(area.rgeo_geometry) bounding_box.add(geometry)
end end
elsif dossier.present? elsif dossier.present?
point = dossier.geo_position point = dossier.geo_position

View file

@ -723,8 +723,8 @@ class Dossier < ApplicationRecord
factory = RGeo::Geographic.simple_mercator_factory factory = RGeo::Geographic.simple_mercator_factory
bounding_box = RGeo::Cartesian::BoundingBox.new(factory) bounding_box = RGeo::Cartesian::BoundingBox.new(factory)
geo_areas.each do |area| geo_areas.map(&:rgeo_geometry).compact.each do |geometry|
bounding_box.add(area.rgeo_geometry) bounding_box.add(geometry)
end end
[bounding_box.max_point, bounding_box.min_point].compact.flat_map(&:coordinates) [bounding_box.max_point, bounding_box.min_point].compact.flat_map(&:coordinates)

View file

@ -49,6 +49,8 @@ class GeoArea < ApplicationRecord
def rgeo_geometry def rgeo_geometry
RGeo::GeoJSON.decode(geometry.to_json, geo_factory: RGeo::Geographic.simple_mercator_factory) RGeo::GeoJSON.decode(geometry.to_json, geo_factory: RGeo::Geographic.simple_mercator_factory)
rescue RGeo::Error::InvalidGeometry
nil
end end
def self.from_feature_collection(feature_collection) def self.from_feature_collection(feature_collection)

View file

@ -35,5 +35,28 @@ FactoryBot.define do
} }
end end
end end
trait :line_string do
geometry do
{
"type": "LineString",
"coordinates": [
[2.4282521009445195, 46.53841410755813],
[2.42824137210846, 46.53847314771794],
[2.428284287452698, 46.53847314771794],
[2.4284291267395024, 46.538491597754714]
]
}
end
end
trait :point do
geometry do
{
"type": "Point",
"coordinates": [2.428439855575562, 46.538476837725796]
}
end
end
end end
end end

View file

@ -1,50 +1,70 @@
RSpec.describe GeoArea, type: :model do RSpec.describe GeoArea, type: :model do
describe '#area' do describe '#area' do
let(:geo_area) do let(:geo_area) { create(:geo_area, :polygon) }
create(:geo_area, geometry: {
"type": "Polygon",
"coordinates": [
[
[2.428439855575562, 46.538476837725796],
[2.4284291267395024, 46.53842148758162],
[2.4282521009445195, 46.53841410755813],
[2.42824137210846, 46.53847314771794],
[2.428284287452698, 46.53847314771794],
[2.428364753723145, 46.538487907747864],
[2.4284291267395024, 46.538491597754714],
[2.428439855575562, 46.538476837725796]
]
]
})
end
it { expect(geo_area.area).to eq(219.0) } it { expect(geo_area.area).to eq(219.0) }
end end
describe '#length' do describe '#length' do
let(:geo_area) do let(:geo_area) { create(:geo_area, :line_string) }
create(:geo_area, geometry: {
"type": "LineString",
"coordinates": [
[2.4282521009445195, 46.53841410755813],
[2.42824137210846, 46.53847314771794],
[2.428284287452698, 46.53847314771794],
[2.4284291267395024, 46.538491597754714]
]
})
end
it { expect(geo_area.length).to eq(30.8) } it { expect(geo_area.length).to eq(30.8) }
end end
describe '#location' do describe '#location' do
let(:geo_area) do let(:geo_area) { create(:geo_area, :point) }
create(:geo_area, geometry: {
"type": "Point",
"coordinates": [2.428439855575562, 46.538476837725796]
})
end
it { expect(geo_area.location).to eq("2°25'42\"N 46°32'19\"E") } it { expect(geo_area.location).to eq("2°25'42\"N 46°32'19\"E") }
end end
describe '#rgeo_geometry' do
let(:geo_area) { create(:geo_area, geometry: geometry) }
context 'invalid' do
let(:geometry) do
{
"type" => "MultiPolygon",
"coordinates" => [
[
[
[5.894422531127931, 48.22810341752755],
[5.893049240112306, 48.22427237832278],
[5.892534255981446, 48.22593062452037],
[5.892791748046875, 48.2260449843468],
[5.894422531127931, 48.229933066408215],
[5.894422531127931, 48.22810341752755]
]
],
[
[
[5.8950233459472665, 48.229933066408215],
[5.893478393554688, 48.228961073585126],
[5.892791748046875, 48.228903896961775],
[5.892705917358398, 48.230390468407535],
[5.8950233459472665, 48.229933066408215]
]
],
[
[
[5.893220901489259, 48.229246955743626],
[5.893392562866212, 48.22884672027457],
[5.892705917358398, 48.22878954352343],
[5.892019271850587, 48.22856083588024],
[5.892019271850587, 48.2277031731152],
[5.890989303588868, 48.22787470681807],
[5.889959335327149, 48.22787470681807],
[5.890560150146485, 48.22838930447709],
[5.890645980834962, 48.22878954352343],
[5.890989303588868, 48.229018250144584],
[5.892362594604493, 48.22930413198368],
[5.893220901489259, 48.229246955743626]
]
]
]
}
end
it { expect(geo_area.rgeo_geometry).to be_nil }
end
end
end end