Skip to content

Commit

Permalink
Geo attribute: support FeatureCollection geoJson type
Browse files Browse the repository at this point in the history
  • Loading branch information
SteRiccio committed Nov 14, 2024
1 parent ff6b1a6 commit 6cb540e
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 15 deletions.
15 changes: 10 additions & 5 deletions webapp/components/geo/GeoPolygonInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ const formatNumber = (value) => Numbers.formatDecimal(Numbers.roundToPrecision(v
export const GeoPolygonInfo = (props) => {
const { geoJson } = props

const areaInSquareMeters = GeoJsonUtils.area(geoJson)
const perimeterInMeters = GeoJsonUtils.perimeter(geoJson)
const areaInSquareMeters = useMemo(() => GeoJsonUtils.area(geoJson), [geoJson])

const areaInUnit = useCallback(
(unit) => `${formatNumber(squareMetersToUnit(unit)(areaInSquareMeters))} ${abbreviationByUnit[unit]}`,
Expand All @@ -32,25 +31,31 @@ export const GeoPolygonInfo = (props) => {
[areaInUnit]
)

const perimeterInMeters = useMemo(() => GeoJsonUtils.perimeter(geoJson), [geoJson])

const perimeterInUnit = useCallback(
(unit) => `${formatNumber(metersToUnit(unit)(perimeterInMeters))} ${abbreviationByUnit[unit]}`,
[perimeterInMeters]
)

const perimeterTooltipContent = useMemo(() => [lengthUnits.foot].map(perimeterInUnit).join('<br>'), [perimeterInUnit])

const verticesCount = useMemo(() => GeoJsonUtils.countVertices(geoJson), [geoJson])
const area = useMemo(() => areaInUnit(areaUnits.hectare), [areaInUnit])
const perimeter = useMemo(() => perimeterInUnit(lengthUnits.meter), [perimeterInUnit])

return (
<div className="geo-polygon-info">
<FormItem label="geo.vertices">{GeoJsonUtils.countVertices(geoJson)}</FormItem>
{verticesCount ? <FormItem label="geo.vertices">{verticesCount}</FormItem> : null}
<FormItem label="geo.area">
<div className="row">
{areaInUnit(areaUnits.hectare)}
{area}
<ButtonIconInfo isTitleMarkdown title={areaTooltipContent} />
</div>
</FormItem>
<FormItem label="geo.perimeter">
<div className="row">
{perimeterInUnit(lengthUnits.meter)}
{perimeter}
<ButtonIconInfo title={perimeterTooltipContent} />
</div>
</FormItem>
Expand Down
36 changes: 29 additions & 7 deletions webapp/utils/geoJsonUtils.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import { PointFactory } from '@openforis/arena-core'
import area from '@turf/area'
import centroid from '@turf/centroid'
import turfCentroid from '@turf/centroid'
import length from '@turf/length'

const countVertices = (geoJson) => {
const polygon = geoJson.type === 'Feature' ? geoJson.geometry : geoJson
return polygon?.coordinates?.[0]?.length ?? 0
const Type = {
Feature: 'Feature',
FeatureCollection: 'FeatureCollection',
}

const centroidFeature = turfCentroid

const centroidPoint = (geoJson) => pointFeatureToPoint(centroidFeature(geoJson))

const countVertices = (geoJsonOrGeometry) => {
const geometry = geoJsonOrGeometry.type === Type.Feature ? geoJsonOrGeometry.geometry : geoJsonOrGeometry
return geometry?.coordinates?.[0]?.length ?? 0
}

const parse = (geoJsonText) => {
Expand All @@ -20,14 +30,26 @@ const parse = (geoJsonText) => {
const pointFeatureToPoint = (pointFeature) => {
if (!pointFeature) return null
const [x, y] = pointFeature.geometry?.coordinates ?? []
return { x, y }
return PointFactory.createInstance({ x, y })
}

const validateFeature = (geoJson) => geoJson?.type === 'Feature' && !!geoJson.geometry
const validateFeature = (geoJson) => {
const { features, geometry, type } = geoJson ?? {}
if (!type) return false
switch (type) {
case Type.Feature:
return !!geometry
case Type.FeatureCollection:
return !!features
default:
return false
}
}

export const GeoJsonUtils = {
area,
centroid,
centroidFeature,
centroidPoint,
countVertices,
parse,
perimeter: length,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ const pointExtractorByNodeDefType = {
},
[NodeDef.nodeDefType.geo]: ({ attributeValue }) => {
const geoJson = JSON.parse(attributeValue)

const centroidFeaturePoint = GeoJsonUtils.centroid(geoJson.geometry)
const point = GeoJsonUtils.pointFeatureToPoint(centroidFeaturePoint)
const point = GeoJsonUtils.centroidPoint(geoJson)
return { point, properties: { data: geoJson } }
},
}
Expand Down

0 comments on commit 6cb540e

Please sign in to comment.