Merge pull request #5594 from tchak/fix-geometry-errors
Fix geometry errors
This commit is contained in:
commit
b4ae7e4492
5 changed files with 120 additions and 22 deletions
|
@ -45,12 +45,20 @@ module ChampHelper
|
||||||
"Culture : #{geo_area.culture} - Surface : #{geo_area.surface} ha"
|
"Culture : #{geo_area.culture} - Surface : #{geo_area.surface} ha"
|
||||||
when GeoArea.sources.fetch(:selection_utilisateur)
|
when GeoArea.sources.fetch(:selection_utilisateur)
|
||||||
if geo_area.polygon?
|
if geo_area.polygon?
|
||||||
|
if geo_area.area.present?
|
||||||
capture do
|
capture do
|
||||||
concat "Une aire de surface #{geo_area.area} m"
|
concat "Une aire de surface #{geo_area.area} m"
|
||||||
concat content_tag(:sup, "2")
|
concat content_tag(:sup, "2")
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
"Une aire de surface inconnue"
|
||||||
|
end
|
||||||
elsif geo_area.line?
|
elsif geo_area.line?
|
||||||
|
if geo_area.length.present?
|
||||||
"Une ligne longue de #{geo_area.length} m"
|
"Une ligne longue de #{geo_area.length} m"
|
||||||
|
else
|
||||||
|
"Une ligne de longueur inconnue"
|
||||||
|
end
|
||||||
elsif geo_area.point?
|
elsif geo_area.point?
|
||||||
"Un point situé à #{geo_area.location}"
|
"Un point situé à #{geo_area.location}"
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
|
||||||
import mapboxgl from 'mapbox-gl';
|
import mapboxgl from 'mapbox-gl';
|
||||||
import ReactMapboxGl, { GeoJSONLayer, ZoomControl } from 'react-mapbox-gl';
|
import ReactMapboxGl, { GeoJSONLayer, ZoomControl } from 'react-mapbox-gl';
|
||||||
import DrawControl from 'react-mapbox-gl-draw';
|
import DrawControl from 'react-mapbox-gl-draw';
|
||||||
import { gpx, kml } from '@tmcw/togeojson/dist/togeojson.es.js';
|
|
||||||
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
|
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
|
||||||
|
|
||||||
import { getJSON, ajax, fire } from '@utils';
|
import { getJSON, ajax, fire } from '@utils';
|
||||||
|
@ -11,7 +10,11 @@ import { getJSON, ajax, fire } from '@utils';
|
||||||
import { getMapStyle, SwitchMapStyle } from '../MapStyles';
|
import { getMapStyle, SwitchMapStyle } from '../MapStyles';
|
||||||
|
|
||||||
import SearchInput from './SearchInput';
|
import SearchInput from './SearchInput';
|
||||||
import { polygonCadastresFill, polygonCadastresLine } from './utils';
|
import {
|
||||||
|
polygonCadastresFill,
|
||||||
|
polygonCadastresLine,
|
||||||
|
readGeoFile
|
||||||
|
} from './utils';
|
||||||
import {
|
import {
|
||||||
noop,
|
noop,
|
||||||
filterFeatureCollection,
|
filterFeatureCollection,
|
||||||
|
@ -149,19 +152,7 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const onFileImport = (e, inputId) => {
|
const onFileImport = (e, inputId) => {
|
||||||
const isGpxFile = e.target.files[0].name.includes('.gpx');
|
readGeoFile(e.target.files[0]).then(async (featureCollection) => {
|
||||||
let reader = new FileReader();
|
|
||||||
reader.readAsText(e.target.files[0], 'UTF-8');
|
|
||||||
reader.onload = async (event) => {
|
|
||||||
let featureCollection;
|
|
||||||
isGpxFile
|
|
||||||
? (featureCollection = gpx(
|
|
||||||
new DOMParser().parseFromString(event.target.result, 'text/xml')
|
|
||||||
))
|
|
||||||
: (featureCollection = kml(
|
|
||||||
new DOMParser().parseFromString(event.target.result, 'text/xml')
|
|
||||||
));
|
|
||||||
|
|
||||||
const resultFeatureCollection = await getJSON(
|
const resultFeatureCollection = await getJSON(
|
||||||
`${url}/import`,
|
`${url}/import`,
|
||||||
featureCollection,
|
featureCollection,
|
||||||
|
@ -196,7 +187,7 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
updateFeaturesList(resultFeatureCollection.features);
|
updateFeaturesList(resultFeatureCollection.features);
|
||||||
setImportInputs(setInputs);
|
setImportInputs(setInputs);
|
||||||
setBbox(resultFeatureCollection.bbox);
|
setBbox(resultFeatureCollection.bbox);
|
||||||
};
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const addInputFile = (e) => {
|
const addInputFile = (e) => {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { gpx, kml } from '@tmcw/togeojson/dist/togeojson.es.js';
|
||||||
|
|
||||||
export const polygonCadastresFill = {
|
export const polygonCadastresFill = {
|
||||||
'fill-color': '#EC3323',
|
'fill-color': '#EC3323',
|
||||||
'fill-opacity': 0.3
|
'fill-opacity': 0.3
|
||||||
|
@ -8,3 +10,81 @@ export const polygonCadastresLine = {
|
||||||
'line-width': 4,
|
'line-width': 4,
|
||||||
'line-dasharray': [1, 1]
|
'line-dasharray': [1, 1]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function normalizeFeatureCollection(featureCollection) {
|
||||||
|
const features = [];
|
||||||
|
for (const feature of featureCollection.features) {
|
||||||
|
switch (feature.geometry.type) {
|
||||||
|
case 'MultiPoint':
|
||||||
|
for (const coordinates of feature.geometry.coordinates) {
|
||||||
|
features.push({
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: {
|
||||||
|
type: 'Point',
|
||||||
|
coordinates
|
||||||
|
},
|
||||||
|
properties: feature.properties
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'MultiLineString':
|
||||||
|
for (const coordinates of feature.geometry.coordinates) {
|
||||||
|
features.push({
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: {
|
||||||
|
type: 'LineString',
|
||||||
|
coordinates
|
||||||
|
},
|
||||||
|
properties: feature.properties
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'MultiPolygon':
|
||||||
|
for (const coordinates of feature.geometry.coordinates) {
|
||||||
|
features.push({
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: {
|
||||||
|
type: 'Polygon',
|
||||||
|
coordinates
|
||||||
|
},
|
||||||
|
properties: feature.properties
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'GeometryCollection':
|
||||||
|
for (const geometry of feature.geometry.geometries) {
|
||||||
|
features.push({
|
||||||
|
type: 'Feature',
|
||||||
|
geometry,
|
||||||
|
properties: feature.properties
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
features.push(feature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
featureCollection.features = features;
|
||||||
|
return featureCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function readGeoFile(file) {
|
||||||
|
const isGpxFile = file.name.includes('.gpx');
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
reader.onload = (event) => {
|
||||||
|
const xml = new DOMParser().parseFromString(
|
||||||
|
event.target.result,
|
||||||
|
'text/xml'
|
||||||
|
);
|
||||||
|
const featureCollection = normalizeFeatureCollection(
|
||||||
|
isGpxFile ? gpx(xml) : kml(xml)
|
||||||
|
);
|
||||||
|
|
||||||
|
resolve(featureCollection);
|
||||||
|
};
|
||||||
|
reader.readAsText(file, 'UTF-8');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -79,13 +79,13 @@ class GeoArea < ApplicationRecord
|
||||||
|
|
||||||
def area
|
def area
|
||||||
if polygon? && RGeo::Geos.supported?
|
if polygon? && RGeo::Geos.supported?
|
||||||
rgeo_geometry.area.round(1)
|
rgeo_geometry.area&.round(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def length
|
def length
|
||||||
if line? && RGeo::Geos.supported?
|
if line? && RGeo::Geos.supported?
|
||||||
rgeo_geometry.length.round(1)
|
rgeo_geometry.length&.round(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace :after_party do
|
||||||
|
|
||||||
geometry_collections = GeoArea.where("geometry -> 'type' = '\"GeometryCollection\"'")
|
geometry_collections = GeoArea.where("geometry -> 'type' = '\"GeometryCollection\"'")
|
||||||
multi_polygons = GeoArea.where("geometry -> 'type' = '\"MultiPolygon\"'")
|
multi_polygons = GeoArea.where("geometry -> 'type' = '\"MultiPolygon\"'")
|
||||||
|
multi_line_strings = GeoArea.where("geometry -> 'type' = '\"MultiLineString\"'")
|
||||||
|
|
||||||
def valid_geometry?(geometry)
|
def valid_geometry?(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)
|
||||||
|
@ -26,6 +27,24 @@ namespace :after_party do
|
||||||
end
|
end
|
||||||
progress.finish
|
progress.finish
|
||||||
|
|
||||||
|
progress = ProgressReport.new(multi_line_strings.count)
|
||||||
|
multi_line_strings.find_each do |multi_line_string|
|
||||||
|
multi_line_string.geometry['coordinates'].each do |coordinates|
|
||||||
|
geometry = {
|
||||||
|
type: 'LineString',
|
||||||
|
coordinates: coordinates
|
||||||
|
}
|
||||||
|
|
||||||
|
if valid_geometry?(geometry)
|
||||||
|
multi_line_string.champ.geo_areas.create!(geometry: geometry, source: 'selection_utilisateur')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
multi_line_string.destroy
|
||||||
|
progress.inc
|
||||||
|
end
|
||||||
|
progress.finish
|
||||||
|
|
||||||
progress = ProgressReport.new(multi_polygons.count)
|
progress = ProgressReport.new(multi_polygons.count)
|
||||||
multi_polygons.find_each do |multi_polygon|
|
multi_polygons.find_each do |multi_polygon|
|
||||||
multi_polygon.geometry['coordinates'].each do |coordinates|
|
multi_polygon.geometry['coordinates'].each do |coordinates|
|
||||||
|
|
Loading…
Reference in a new issue