Skip to content

Commit

Permalink
Kew tree crown data - map view
Browse files Browse the repository at this point in the history
  • Loading branch information
paulthatjazz committed Jan 9, 2025
1 parent 0746ed7 commit 1fc82ac
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 18 deletions.
10 changes: 7 additions & 3 deletions app/javascript/projects/layer_palette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { CompiledDatasetRecord } from './saved_dataset'
import { designations } from './modelling/designations'
import { IMDProperties } from './reify_layer/imd'
import { ProjectPermissions } from './project_editor'
import { KewPointOptions } from './reify_layer/kew'
import { KewPointOptions, KewTreeCrownOptions } from './reify_layer/kew'
import { seasonYearOptions } from './modelling/components/kew_samples_component'
import { natmap_outputs } from './modelling/components/natmap_soil_component'

Expand Down Expand Up @@ -131,7 +131,9 @@ export const LayerPalette = ({ addLayer, hide, dbModels, getTeamDatasets, teamNa
identifier: "kew:bl_crown_3857",
visible: true,
opacity: 1,
color: { stroke: [160,82,45, 1], fill: [160,82,45, 1] }
color: { stroke: [160,82,45, 1], fill: [160,82,45, 1] },
fill: "jet",
metric: KewTreeCrownOptions[0]
}}
/>
}
Expand All @@ -144,7 +146,9 @@ export const LayerPalette = ({ addLayer, hide, dbModels, getTeamDatasets, teamNa
identifier: "kew:conifer_crown_3857",
visible: true,
opacity: 1,
color: { stroke: [34,139,34, 1], fill: [34,139,34, 1] }
color: { stroke: [34,139,34, 1], fill: [34,139,34, 1] },
fill: "jet",
metric: KewTreeCrownOptions[0]
}}
/>
}
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/projects/modelling/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export function createDefaultComponents(saveMapLayer: SaveMapLayer, saveModel: S
if (permissions.DefraHedgerows) restrictedComponents.push(new HedgerowComponent(projectProps))
if (permissions.KewSamples) {
restrictedComponents.push(new KewSamplesComponent(projectProps))
restrictedComponents.push(new KewHabsComponent(projectProps))
//restrictedComponents.push(new KewHabsComponent(projectProps))
restrictedComponents.push(new KewTreesComponent(projectProps))
}
if (permissions.NATMAPSoil) restrictedComponents.push(new NatmapSoilComponent(projectProps))
Expand Down
72 changes: 61 additions & 11 deletions app/javascript/projects/reify_layer/kew.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import BaseLayer from "ol/layer/Base"
import { KewLayer, KewOption, KewPointLayer, KewShapeLayer } from "../state"
import VectorLayer from "ol/layer/Vector"
import { memoize } from "lodash"
import { get, memoize } from "lodash"
import VectorSource from "ol/source/Vector"
import GeoJSON from "ol/format/GeoJSON"
import { bbox } from "ol/loadingstrategy"
Expand All @@ -11,6 +11,41 @@ import { getColorStops } from "./model_output"
import { findColor } from "../analysis_panel_tools/subsection"
import { numericDataSocket } from "../modelling/socket_types"

export const KewTreeCrownOptions: any[] = [
{
name: "none",
label: "None"
},
{
name: "height",
label: "Height"
},
{
name: "npoints",
label: "N Points"
},
{
name: "canpy_d",
label: "Canopy Diameter"
},
{
name: "jckr_gb",
label: "AGB (Jucker)"
},
{
name: "wake_gb",
label: "AGB (Wakehurst)"
},
{
name: "p25",
label: "P 25"
},
{
name: "p75",
label: "P 75"
}
]

export const KewPointOptions: KewOption[] = [
{
value: "carbon",
Expand Down Expand Up @@ -216,6 +251,22 @@ const getPointStyle = (map: Map, layer: KewPointLayer, min: number | null, max:
}
)

const getShapeStyle = (layer: KewShapeLayer, min: number, max: number, col: [r: number, g: number, b: number, a: number], colMap: any[]) => (
(feature) => {
const metric = layer.metric.name !== "none" ? feature.getProperties()[layer.metric.name] : -99999
const c = metric !== -99999 ? findColor((metric - min) / (max - min), colMap) : col

return new Style({
stroke: new Stroke({
color: `rgba(0, 0, 0, .6)`,
width: .2
}),
fill: new Fill({
color: `rgba(${c[0]}, ${c[1]}, ${c[2]}, 1)`
})
})
}
)

export function reifyKewLayer (layer: KewLayer, existingLayer: BaseLayer | null , map: Map) {

Expand Down Expand Up @@ -335,17 +386,16 @@ export function reifyKewPointLayer(layer: KewPointLayer, existingLayer: BaseLaye
export function reifyKewShapeLayer(layer: KewShapeLayer, existingLayer: BaseLayer | null, map: Map) {

const col = layer.color.fill
const colMap = getColorStops(layer.fill, 100).reverse()
const vectorSource = getSource(layer.identifier)
const { min, max } = layer.metric.name !== "none" ? getMinMaxMetric(vectorSource, layer.metric.name) : { min: 0, max: 100 }

// update sidebar
layer.min = min ?? 0
layer.max = max ?? 0

return new VectorLayer({
source: getSource(layer.identifier),
style: new Style({
stroke: new Stroke({
color: `rgba(0, 0, 0, 1)`,
width: 1
}),
fill: new Fill({
color: `rgba(${col[0]}, ${col[1]}, ${col[2]}, 1)`
})
})
source: vectorSource,
style: getShapeStyle(layer, min!, max!, col, colMap)
})
}
58 changes: 55 additions & 3 deletions app/javascript/projects/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import * as React from 'react'
import './sidebar.css'
import { ReactSortable } from 'react-sortablejs'
import { nevoLevelNames, nevoPropertyNames } from './nevo'
import { AtiLayer, CropMapLayer, DatasetLayer, IMDLayer, KewLayer, KewPointLayer, Layer, ModelOutputLayer, NevoLayer, OverlayLayer, ShapeLayer, State, WFSLayer } from './state'
import { AtiLayer, CropMapLayer, DatasetLayer, IMDLayer, KewLayer, KewPointLayer, KewShapeLayer, Layer, ModelOutputLayer, NevoLayer, OverlayLayer, ShapeLayer, State, WFSLayer } from './state'
import { iconForLayerType } from "./util"
import { getColorStops } from './reify_layer/model_output'
import { TileGridProps, tileGridStats } from './modelling/tile_grid'
import { IMDProperties } from './reify_layer/imd'
import { KewPointOptions } from './reify_layer/kew'
import { KewPointOptions, KewTreeCrownOptions } from './reify_layer/kew'
import { natmap_outputs } from './modelling/components/natmap_soil_component'

const colMapList = <>
Expand Down Expand Up @@ -317,6 +317,11 @@ interface KewPointLayerSettingsProps {
mutate: (data: any) => void
}

interface KewShapeLayerSettingsProps {
layer: KewShapeLayer
mutate: (data: any) => void
}

const KewPointLayerSettings = ({ layer, mutate }: KewPointLayerSettingsProps) => {

return (
Expand Down Expand Up @@ -395,6 +400,33 @@ const KewLayerSettings = ({ layer, mutate }: KewLayerSettingsProps) => {
)
}

const KewShapeLayerSettings = ({ layer, mutate }: KewShapeLayerSettingsProps) => {
return <>
<div className="d-flex align-items-center mt-3">
Property
<select className="custom-select ml-3" value={layer.metric.name} onChange={e => mutate({ metric: KewTreeCrownOptions.filter(f => f.name === e.target.value)[0] })}>
{
KewTreeCrownOptions.map(opt =>
<option key={opt.name} value={opt.name}>
{opt.label}
</option>
)

}
</select>
</div>
{
layer.metric.name != "none" &&
<div className="d-flex align-items-center mt-3">
Fill
<select className="custom-select ml-3" value={layer.fill} onChange={e => mutate({ fill: e.target.value })}>
{colMapList}
</select>
</div>
}
</>
}

export function ZoomData({zoom, area, length, units}) {
const unit = area < 1 ? "cm²" : (area > 1000000 ? "km²" : "m²")
length = area < 1 ? length * 100 : (area > 1000000 ? length / 1000 : length)
Expand Down Expand Up @@ -841,7 +873,7 @@ export const Sidebar = ({ state, selectLayer, mutateLayer, deleteLayer, setLayer
</ReactSortable>
</div>
{
(selectedLayer?.type == "ModelOutputLayer" || selectedLayer?.type == "DatasetLayer" || selectedLayer?.type == "IMDLayer" || selectedLayer?.type == "KewPointLayer" || selectedLayer?.type == "WFSLayer") &&
(selectedLayer?.type == "ModelOutputLayer" || selectedLayer?.type == "DatasetLayer" || selectedLayer?.type == "IMDLayer" || selectedLayer?.type == "KewPointLayer" || selectedLayer?.type == "WFSLayer" || (selectedLayer?.type == "KewShapeLayer" && selectedLayer.metric.name !== "none")) &&
(
<div className="px-3 py-2 border-top border-bottom bg-light d-flex justify-content-between align-items-center">
<span className="flex-grow-1">Layer legend</span>
Expand Down Expand Up @@ -893,6 +925,16 @@ export const Sidebar = ({ state, selectLayer, mutateLayer, deleteLayer, setLayer
toggle={isLegCollapsed}
/>
}
{
selectedLayer?.type == "KewShapeLayer" &&
selectedLayer.metric.name !== "none" &&
<GenericLegend
min={`${selectedLayer.min?.toFixed(4) ?? "Least"}`}
max={`${selectedLayer.max?.toFixed(4) ?? "Most"}`}
fill={selectedLayer.fill}
toggle={isLegCollapsed}
/>
}
<div className="px-3 py-2 border-top border-bottom bg-light">Layer settings</div>
<div className="p-3 bg-white text-nowrap" style={{ maxHeight: "50vh", overflowY: "auto" }}>
{
Expand Down Expand Up @@ -993,6 +1035,16 @@ export const Sidebar = ({ state, selectLayer, mutateLayer, deleteLayer, setLayer
}
/>
}
{
selectedLayer?.type == "KewShapeLayer" &&
<KewShapeLayerSettings
layer={selectedLayer}
mutate={
data => state.selectedLayer !== undefined &&
mutateLayer(state.selectedLayer, data)
}
/>
}
{
selectedLayer?.type == "ORValLayer" &&
<>
Expand Down
9 changes: 9 additions & 0 deletions app/javascript/projects/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ export interface KewOption {
socket?: Socket
}

export interface KewCrownOption {
name: string
label: string
}

type fillType = "greyscale" | "heatmap" | "jet" | "hsv" | "hot" | "cool" | "spring" | "summer" | "autumn" | "winter" | "copper" | "WIGnBu" | "greens" | "YIOrRd" | "bluered" | "RdBu" | "picnic" | "rainbow" | "portland" | "blackbody" | "earth" | "electric" | "viridis" | "inferno" | "magma" | "plasma" | "warm" | "cool" | "rainbow-soft" | "bathymetry" | "cdom" | "chlorophyll" | "density" | "freesurface-blue" | "freesurface-red" | "oxygen" | "par" | "phase" | "salinity" | "temperature" | "turbidity" | "velocity-blue" | "velocity-green" | "cubehelix"

export interface OsmLayer extends BaseLayer {
Expand Down Expand Up @@ -99,6 +104,10 @@ export interface KewShapeLayer extends BaseLayer {
type: "KewShapeLayer"
identifier: string
color: StrokeFill
fill: fillType
metric: KewCrownOption
min?: number
max?: number
}

export interface NevoLayer extends BaseLayer {
Expand Down

0 comments on commit 1fc82ac

Please sign in to comment.