Commit 50665695 authored by juminet's avatar juminet

[client/geothermie] graph: add a input box for depth values and display the...

[client/geothermie] graph: add a input box for depth values and display the conductivity value a the given depth
parent 238373e9
import * as io from 'io-ts';
import { DIV, IMG } from 'sdi/components/elements';
import { DIV, IMG, INPUT, SPAN } from 'sdi/components/elements';
import { formatNumber } from 'sdi/locale';
import { getGraphSnapXy, getGraphWidth, getDiagramHeight } from '../../queries/geothermie';
import { getGraphSnapXy, getGraphWidth, getDiagramHeight, getGraphXy, getBedrockDepth } from '../../queries/geothermie';
import { setGraphXy, setGraphSnapXy } from '../../events/geothermie';
import { getLayersTotalDepth } from '../../queries/geothermie';
import { graph, GRAPH_LEFT_MARGIN, GRAPH_TOP_MARGIN, MAX_CONDUCTIVITY_VALUE } from './engine';
import { formatDepth } from './format';
export const GraphXYIO = io.interface({
......@@ -49,58 +48,85 @@ const depthToY = (depth: number) =>
depth / getLayersTotalDepth() * (getGraphHeight() - GRAPH_TOP_MARGIN) + GRAPH_TOP_MARGIN;
const setXyFromGraph = (e: React.MouseEvent<HTMLElement>, depths:number[], values:number[], _width:number, _height:number) => {
const rect = document.getElementById('graph')!.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
setGraphXy({x, y});
const snapXy = (depths:number[], values: number[], cumulValues: number[]) => {
const y = getGraphXy().fold(0, xy => xy.y)
let notNullDepths: number[] = [];
let notNullValues: number[] = [];
let notNullCumulValues: number[] = [];
depths.map((d, i) => {
if (depths[i - 1] !== depths[i]) {
notNullDepths.push(d);
notNullValues.push(values[i]);
notNullCumulValues.push(cumulValues[i]);
}
});
let xSnap: number;
const depthValue = yToDepth(y);
if (depthValue < notNullDepths[0]) {
setGraphSnapXy({x: valueToX(notNullValues[0]), y: y});
/*
* we set the conductivity value (xToValue(xSnap)) equal to the first value (no interpolation)
*/
setGraphSnapXy({x: valueToX(notNullCumulValues[0]), y: y});
} else {
let snapIndex: number;
notNullDepths.map((d,i) => {
if (depthValue >= d && depthValue <= notNullDepths[i + 1]) {
snapIndex = i;
const x1 = valueToX(notNullValues[snapIndex]);
const y1 = depthToY(notNullDepths[snapIndex]);
const x2 = valueToX(notNullValues[snapIndex + 1]);
const y2 = depthToY(notNullDepths[snapIndex + 1]);
const a = isNaN((y1 - y2) / (x1 - x2)) ? 0 : (y1 - y2) / (x1 - x2);
const b = y1 - a * x1;
xSnap = (y - b) / a;
setGraphSnapXy({x: xSnap, y: y});
if (depthValue > notNullDepths[notNullDepths.length - 1]) {
/*
* we extrapole the conductivity value (xToValue(xSnap)) below the bedrock depth.
* For depth (y) >>> bedrockDepth, xSnap ~= condBedrock
*/
const cumulCondAtTopBedrock = valueToX(notNullCumulValues[notNullCumulValues.length - 1]);
const condBedrock = valueToX(values[values.length - 1]);
const bedrockDepthToY = depthToY(getBedrockDepth());
xSnap = (cumulCondAtTopBedrock * bedrockDepthToY + condBedrock * (y - bedrockDepthToY)) / y
setGraphSnapXy({x: xSnap, y: y});
} else {
/*
* we interpolate the conductivity value (xToValue(xSnap)) between each geology interface
* by building a linear function between the bottom and the top of the layer.
*/
let snapIndex: number;
notNullDepths.map((d,i) => {
if (depthValue >= d && depthValue <= notNullDepths[i + 1]) {
snapIndex = i;
const x1 = valueToX(notNullCumulValues[snapIndex]);
const y1 = depthToY(notNullDepths[snapIndex]);
const x2 = valueToX(notNullCumulValues[snapIndex + 1]);
const y2 = depthToY(notNullDepths[snapIndex + 1]);
const a = isNaN((y1 - y2) / (x1 - x2)) ? 0 : (y1 - y2) / (x1 - x2);
const b = y1 - a * x1;
xSnap = (y - b) / a;
setGraphSnapXy({x: xSnap, y: y});
}
}
}
)};
)}
};
};
const onClickOnGraph = (e: React.MouseEvent<HTMLElement>, depths: number[], values: number[], cumulValues: number[]) => {
const rect = document.getElementById('graph')!.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
setGraphXy({x, y});
snapXy(depths, values, cumulValues)
};
const formatXYValues =
(xy: GraphXY) =>
`${formatNumber(xToValue(xy.x))} W/m.K at ${formatDepth(yToDepth(xy.y))} m.`
const updateDepth = (e: React.FormEvent<HTMLInputElement>, depths: number[], values: number[], cumulValues: number[]) => {
setGraphXy({x: getGraphXy().fold(0, xy => xy.x), y: depthToY(Number(e.currentTarget.value))});
snapXy(depths, values, cumulValues);
};
const render =
(depthValues: number[], values: number[], cumulValues: number[]) =>
DIV({ className: 'graph' },
IMG({
id: 'graph',
onClick: e => setXyFromGraph(e, depthValues, cumulValues, getGraphWidth(), getGraphHeight()),
onClick: e => onClickOnGraph(e, depthValues, values, cumulValues),
src: getImage(
getGraphWidth(),
getGraphHeight(),
......@@ -109,10 +135,20 @@ const render =
cumulValues,
)
}),
DIV({ className: '~graph-reader' }, getGraphSnapXy().fold(
'',
xy => formatXYValues(xy),
))
DIV({ className: 'graph__reader' },
INPUT({
className: '',
type: 'number',
onChange: e => updateDepth(e, depthValues, values, cumulValues),
value: Math.round(yToDepth(getGraphSnapXy().fold(GRAPH_TOP_MARGIN, xy => xy.y))),
defaultValue: '0'
}),
SPAN({}, 'meter'),
DIV( { className: 'graph__reader__value' },
formatNumber(xToValue(getGraphSnapXy().fold(GRAPH_LEFT_MARGIN, xy => xy.x))),
' W/m.K'
),
)
);
export default render;
......@@ -123,3 +123,21 @@ div.table--hydro {
}
}
}
div.graph {
display: flex;
flex-direction: column;
align-items: center;
div.graph__reader {
position: absolute;
top: 0px;
width: fit-content;
margin-left: 1.3em;
div.graph__reader__value{
display: flex;
}
input {
width: 5em;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment