diff --git a/src/components/plots/AnalysisInfo.tsx b/src/components/plots/AnalysisInfo.tsx
index feb61eeb..1473ae0c 100644
--- a/src/components/plots/AnalysisInfo.tsx
+++ b/src/components/plots/AnalysisInfo.tsx
@@ -8,25 +8,28 @@ import { parseLoc } from '@/utils/HelperFuncs'
const AnalysisInfo = ({loc, show, info, } : {loc: number[], show: boolean, info: number[]}) => {
- const {dimNames, dimUnits} = useGlobalStore(useShallow(state=>({dimNames: state.dimNames, dimUnits: state.dimUnits})))
+ const {axisDimNames, axisDimArrays, axisDimUnits} = useGlobalStore(useShallow(state=>({axisDimNames: state.axisDimNames, axisDimArrays:state.axisDimArrays, axisDimUnits: state.axisDimUnits})))
const axis = useAnalysisStore(state=> state.axis)
- const plotNames = useMemo(()=>{
- if (dimNames.length < 3){
- return [dimNames[0], dimNames[1]]
+ // This logic is weak and May not hold up with >3 dimensions
+ const plotInfo = useMemo(()=>{
+ let plotNames, plotUnits, plotArrays;
+ if (axisDimNames.length < 3){
+ plotNames = [axisDimNames[0], axisDimNames[1]]
+ plotUnits = [axisDimUnits[0], axisDimUnits[1]]
+ plotArrays = [axisDimArrays[0], axisDimArrays[1]]
}
else{
- return dimNames.filter((_val,idx)=> idx != axis)
+ plotNames = axisDimNames.filter((_val,idx)=> idx != axis)
+ plotUnits = axisDimUnits.filter((_val,idx)=> idx != axis)
+ plotArrays = axisDimArrays.filter((_val,idx)=> idx != axis)
}
- },[dimNames, axis])
-
- const plotUnits = useMemo(()=>{
- if (dimNames.length < 3){
- return [dimUnits[0], dimUnits[1]]
- }
- else{
- return dimUnits.filter((_val,idx)=> idx != axis)
- }
- },[dimUnits, axis])
+ return {plotNames, plotUnits, plotArrays}
+ },[axisDimNames, axisDimUnits, axisDimArrays, axis])
+ const {plotNames, plotUnits, plotArrays} = plotInfo;
+ const yArray = plotArrays[0]
+ const xArray = plotArrays[1]
+ const yCoord = yArray[Math.floor(info[0] * yArray.length)]
+ const xCoord = xArray[Math.floor(info[1] * xArray.length)]
return (
- {`${plotNames[0]}: ${show && parseLoc(info[0],plotUnits[0])}`}
- {`${plotNames[1]}: ${show && parseLoc(info[1],plotUnits[1])}`}
+ {`${plotNames[0]}: ${show && parseLoc(yCoord,plotUnits[0])}`}
+ {`${plotNames[1]}: ${show && parseLoc(xCoord,plotUnits[1])}`}
{`Value: ${Math.round(info[2] * 100)/100}`}
)
diff --git a/src/components/plots/DataCube.tsx b/src/components/plots/DataCube.tsx
index bae8dbd0..0a787b8b 100644
--- a/src/components/plots/DataCube.tsx
+++ b/src/components/plots/DataCube.tsx
@@ -86,7 +86,6 @@ export const DataCube = ({ volTexture: propVolTexture }: DataCubeProps ) => {
side: useOrtho ? THREE.FrontSide : THREE.BackSide,
}),[useFragOpt, useOrtho, volTexture, remapTexture]);
-
const geometry = useMemo(() => new THREE.BoxGeometry(shape.x, shape.y, shape.z), [shape]);
useEffect(() => {
if (shaderMaterial) {
@@ -120,10 +119,10 @@ export const DataCube = ({ volTexture: propVolTexture }: DataCubeProps ) => {
.invert();
})
return (
-
+
-
-
+
+
)
}
\ No newline at end of file
diff --git a/src/components/plots/FlatMap.tsx b/src/components/plots/FlatMap.tsx
index 47d48594..de2ff35c 100644
--- a/src/components/plots/FlatMap.tsx
+++ b/src/components/plots/FlatMap.tsx
@@ -1,6 +1,6 @@
"use client";
-import React, {useMemo, useEffect, useRef, useState} from 'react'
+import React, {useMemo, useEffect, useRef} from 'react'
import * as THREE from 'three'
import { useAnalysisStore } from '@/GlobalStates/AnalysisStore';
import { useGlobalStore } from '@/GlobalStates/GlobalStore';
@@ -10,6 +10,7 @@ import { vertShader } from '@/components/computation/shaders'
import { useShallow } from 'zustand/shallow'
import { ThreeEvent } from '@react-three/fiber';
import { coarsenFlatArray, GetCurrentArray, GetTimeSeries, parseUVCoords, deg2rad } from '@/utils/HelperFuncs';
+import { sampleCRS } from '../textures/ProjectionTexture';
import { evaluateColorMap } from '@/components/textures';
import { useCoordBounds } from '@/hooks/useCoordBounds';
import { flatFrag } from '../textures/shaders';
@@ -92,7 +93,6 @@ const FlatMap = ({textures: propTextures, infoSetters} : {textures : THREE.DataT
const geometry = useMemo(()=>new THREE.PlaneGeometry(2,2*shapeRatio),[shapeRatio])
const infoRef = useRef(false)
- const lastUV = useRef(new THREE.Vector2(0,0))
const rotateMap = analysisMode && axis == 2;
const sampleArray = useMemo(()=> analysisMode ? analysisArray : GetCurrentArray(),[analysisMode, analysisArray, textures])
const analysisDims = useMemo(() => {
@@ -117,67 +117,88 @@ const FlatMap = ({textures: propTextures, infoSetters} : {textures : THREE.DataT
const eventRef = useRef | null>(null);
const handleMove = (e: ThreeEvent) => {
if (infoRef.current && e.uv) {
- eventRef.current = e;
+ let {uv} = e;
+ if (!uv) return;
setLoc([e.clientX, e.clientY]);
- lastUV.current = e.uv;
- const { x, y } = e.uv;
+ eventRef.current = e;
+ if (remapTexture){
+ const [thisUV, isValid] = sampleCRS(remapTexture, uv.x, flipY ? 1-uv.y: uv.y) // Weird double flippiing of UVs with flipY. Has something to do with how projected data is done.
+ if (flipY) thisUV.y = 1-thisUV.y
+ if (isValid) uv = thisUV;
+ else{
+ val.current = NaN;
+ coords.current = [thisUV.y,thisUV.x]
+ return;
+ }
+ }
+
+ const { x, y } = uv;
const zSliceIdx = dimSlices.length > 2 ? 2 : 1;
const ySliceIdx = dimSlices.length > 2 ? 1 : 0;
const xSize = isFlat ? (analysisMode ? analysisDims[1].length : dimSlices[1].length) : dimSlices[zSliceIdx].length;
const ySize = isFlat ? (analysisMode ? analysisDims[0].length : dimSlices[0].length) : dimSlices[ySliceIdx].length;
- const xIdx = Math.round(x*xSize-.5)
- const yIdx = Math.round(y*ySize-.5)
- let dataIdx = xSize * yIdx + xIdx;
- dataIdx += isFlat ? 0 : Math.floor((dimSlices[0].length-1) * animProg) * xSize*ySize
+ const xId = Math.round(x*xSize-.5)
+ const yId = Math.round(y*ySize-.5)
+ let dataIdx = xSize * yId + xId;
+ dataIdx += isFlat ? 0 : Math.floor((dimSlices[zIdx].length-1) * animProg) * xSize*ySize
const dataVal = sampleArray ? sampleArray[dataIdx] : 0;
val.current = dataVal;
- coords.current = isFlat ? analysisMode ? [analysisDims[0][yIdx], analysisDims[1][xIdx]] : [dimSlices[0][yIdx], dimSlices[1][xIdx]] : [dimSlices[ySliceIdx][yIdx], dimSlices[zSliceIdx][xIdx]]
+ coords.current = [y,x]
}
}
-
// ----- TIMESERIES ----- //
function HandleTimeSeries(event: THREE.Intersection){
- const uv = event.uv;
- const normal = new THREE.Vector3(0,0,1)
- if(uv){
- const tsUV = flipY ? new THREE.Vector2(uv.x, 1-uv.y) : uv
- const tempTS = GetTimeSeries({data:analysisMode ? analysisArray : GetCurrentArray(), shape:dataShape, stride:strides},{uv:tsUV,normal})
- setPlotDim(0) //I think this 2 is only if there are 3-dims. Need to rework the logic
-
- const coordUV = parseUVCoords({normal:normal,uv:uv})
- let dimCoords = coordUV.map((val,idx)=>val ? dimSlices[idx][Math.round(val*dimSlices[idx].length)] : null)
- const thisDimNames = dimNames.filter((_,idx)=> dimCoords[idx] !== null)
- const thisDimUnits = dimUnits.filter((_,idx)=> dimCoords[idx] !== null)
- dimCoords = dimCoords.filter(val => val !== null)
- const tsID = `${dimCoords[0]}_${dimCoords[1]}`
- const tsObj = {
- color: evaluateColorMap(getColorIdx() / 10, 'Paired'),
- data: tempTS,
- normal,
- uv: tsUV,
- }
- incrementColorIdx();
- updateTimeSeries({ [tsID] : tsObj})
- const dimObj = {
- first:{
- name:thisDimNames[0],
- loc:dimCoords[0] ?? 0,
- units:thisDimUnits[0]
- },
- second:{
- name:thisDimNames[1],
- loc:dimCoords[1] ?? 0,
- units:thisDimUnits[1]
- },
- plot:{
- units:dimUnits[0]
- }
- }
- updateDimCoords({[tsID] : dimObj})
- }
+ const uv = event.uv;
+ if (!uv) return;
+ const tsUV = flipY ? new THREE.Vector2(uv.x, 1-uv.y) : uv
+ let newUV: THREE.Vector2 | undefined;
+ const normal = new THREE.Vector3(0,0,1)
+ if (remapTexture){
+ const [thisUV, isValid] = sampleCRS(remapTexture, uv.x, flipY ? 1-uv.y: uv.y) // Weird double flippiing of UVs with flipY. Has something to do with how projected data is done.
+ if (flipY) thisUV.y = 1-thisUV.y
+ if (isValid) newUV = thisUV;
+ else{
+ return;
}
+ }
+
+ const tempTS = GetTimeSeries({data:analysisMode ? analysisArray : GetCurrentArray(), shape:dataShape, stride:strides},{uv:newUV ?? tsUV,normal})
+ setPlotDim(0) //I think this 2 is only if there are 3-dims. Need to rework the logic
+
+ const coordUV = parseUVCoords({normal:normal,uv:uv})
+ let dimCoords = coordUV.map((val,idx)=>val ? dimSlices[idx][Math.round(val*dimSlices[idx].length)] : null)
+ const thisDimNames = dimNames.filter((_,idx)=> dimCoords[idx] !== null)
+ const thisDimUnits = dimUnits.filter((_,idx)=> dimCoords[idx] !== null)
+ dimCoords = dimCoords.filter(val => val !== null)
+ const tsID = `${dimCoords[0]}_${dimCoords[1]}`
+ const tsObj = {
+ color: evaluateColorMap(getColorIdx() / 10, 'Paired'),
+ data: tempTS,
+ normal,
+ uv: tsUV,
+ }
+ incrementColorIdx();
+ updateTimeSeries({ [tsID] : tsObj})
+ const dimObj = {
+ first:{
+ name:thisDimNames[0],
+ loc:dimCoords[0] ?? 0,
+ units:thisDimUnits[0]
+ },
+ second:{
+ name:thisDimNames[1],
+ loc:dimCoords[1] ?? 0,
+ units:thisDimUnits[1]
+ },
+ plot:{
+ units:dimUnits[0]
+ }
+ }
+ updateDimCoords({[tsID] : dimObj})
+
+ }
// ----- SHADER MATERIAL ----- //
const shaderMaterial = useMemo(()=>new THREE.ShaderMaterial({
glslVersion: THREE.GLSL3,
@@ -223,7 +244,10 @@ const FlatMap = ({textures: propTextures, infoSetters} : {textures : THREE.DataT
uniforms.fillValue.value = fillValue?? NaN
}
},[cScale, cOffset, colormap, animProg, nanColor, nanTransparency, latBounds, lonBounds, fillValue, maskValue, valueRange])
-
+ useEffect(()=>{
+ // This is duplicated. Probably shoud just move it to Plot.tsx
+ useGlobalStore.setState({timeSeries:{}, dimCoords:{}})
+ },[remapTexture])
return (
<>
diff --git a/src/components/plots/TransectMeshes.tsx b/src/components/plots/TransectMeshes.tsx
index 5f35d051..1a98cd97 100644
--- a/src/components/plots/TransectMeshes.tsx
+++ b/src/components/plots/TransectMeshes.tsx
@@ -5,6 +5,7 @@ import { useGlobalStore } from '@/GlobalStates/GlobalStore'
import { useShallow } from 'zustand/shallow'
import { deg2rad, parseUVCoords } from '@/utils/HelperFuncs'
import { useCoordBounds } from '@/hooks/useCoordBounds'
+import { useAxisIndices } from '@/hooks'
function remapToXYZ(uv: THREE.Vector2, latBounds: number[], lonBounds: number[]): THREE.Vector3 {
const u = 1 - uv.x;
@@ -44,6 +45,7 @@ function normalToPos(uv: THREE.Vector2, normal:THREE.Vector3, ratios:{depthRatio
}
function normalToScale(normal:THREE.Vector3, ratios:{depthRatio:number, aspectRatio:number}, steps:{xSteps:number, ySteps:number, zSteps:number}){
+ //This function scales meshes to match the observed size of the pixels
let scaleZ, scaleY, scaleX: number;
const {xSteps,ySteps,zSteps} = steps;
const {aspectRatio, depthRatio} = ratios;
@@ -64,20 +66,20 @@ function normalToScale(normal:THREE.Vector3, ratios:{depthRatio:number, aspectRa
}
export const SquareMeshes = () => {
- const {timeSeries, dataShape, shape, flipY} = useGlobalStore(useShallow(state=>({
+ const {timeSeries, dataShape, shape} = useGlobalStore(useShallow(state=>({
timeSeries:state.timeSeries,
dataShape: state.dataShape,
- shape: state.shape, flipY:state.flipY
+ shape: state.shape
})))
const {plotType} = usePlotStore(useShallow(state=>({
plotType: state.plotType
})))
const {lonBounds, latBounds} = useCoordBounds()
+ const {xIdx, yIdx} = useAxisIndices()
const meshes: THREE.Mesh[] = useMemo(() =>{
const meshes = []
- const dataLen = dataShape.length;
- const xSteps = dataShape[dataLen-1];
- const ySteps = dataShape[dataLen-2];
+ const xSteps = dataShape[xIdx];
+ const ySteps = dataShape[yIdx];
const normedXExtent = (lonBounds[1]-lonBounds[0])/360
const normedYExtent = (latBounds[1]-latBounds[0])/180
const isSphere = plotType == "sphere";
@@ -134,24 +136,29 @@ export const SquareMeshes = () => {
}
export const ColumnMeshes = () => {
- const {timeSeries, dataShape, shape} = useGlobalStore(useShallow(state=>({
+ const {timeSeries, dataShape, remapTexture} = useGlobalStore(useShallow(state=>({
timeSeries:state.timeSeries,
dataShape: state.dataShape,
- shape: state.shape
+ shape: state.shape,
+ remapTexture: state.remapTexture
})))
const {plotType} = usePlotStore(useShallow(state=>({
plotType: state.plotType
})))
-
+ const {xIdx, yIdx, zIdx} = useAxisIndices()
const meshes: THREE.Mesh[] = useMemo(()=>{
const meshes: THREE.Mesh[] = []
- const dataLen = dataShape.length;
- const xSteps = dataShape[dataLen-1];
- const ySteps = dataShape[dataLen-2];
- const zSteps = dataShape[dataLen-3];
- const aspectRatio = dataShape[dataLen-2]/dataShape[dataLen-1]
- const depthRatio = dataShape[dataLen-3]/dataShape[dataLen-1]
- for (const [tsID, tsObj] of Object.entries(timeSeries)){
+ const xSteps = remapTexture
+ ? remapTexture.image.width
+ : dataShape[xIdx];
+ const ySteps = remapTexture
+ ? remapTexture.image.height
+ : dataShape[yIdx];
+ const zSteps = dataShape[zIdx];
+ const aspectRatio = ySteps/xSteps; // This is not aspect ratio
+ const depthRatio = zSteps/xSteps;
+
+ for (const [_tsID, tsObj] of Object.entries(timeSeries)){
const {normal, uv, color} = tsObj
const position = normalToPos(uv, normal, {aspectRatio,depthRatio})
const meshScale = normalToScale(normal, {aspectRatio, depthRatio}, {xSteps, ySteps, zSteps})
diff --git a/src/components/plots/UVCube.tsx b/src/components/plots/UVCube.tsx
index 53ce51ec..83fe585d 100644
--- a/src/components/plots/UVCube.tsx
+++ b/src/components/plots/UVCube.tsx
@@ -1,6 +1,7 @@
import * as THREE from 'three'
import { useMemo, useState, useEffect, useRef } from 'react';
import { parseUVCoords, getUnitAxis, GetTimeSeries, GetCurrentArray } from '@/utils/HelperFuncs';
+import { sampleCRS } from '../textures/ProjectionTexture';
import { useAnalysisStore } from '@/GlobalStates/AnalysisStore';
import { useGlobalStore } from '@/GlobalStates/GlobalStore';
import { usePlotStore } from '@/GlobalStates/PlotStore';
@@ -58,7 +59,7 @@ const UpdateUVs = (
//Z-
updateFace(20, {pos:xPos, scale:xScale}, {pos:yPos, scale:yScale}, uvs)
- }
+}
export const UVCube = ( {scale} : {scale?:THREE.Vector3} )=>{
@@ -78,14 +79,16 @@ export const UVCube = ( {scale} : {scale?:THREE.Vector3} )=>{
analysisArray: state.analysisArray
})))
- const {shape, dataShape, strides, dimArrays,dimNames,dimUnits} = useGlobalStore(
+ const {shape, dataShape, strides, axisDimArrays,axisDimNames,axisDimUnits, remapTexture, flipY} = useGlobalStore(
useShallow(state=>({
shape:state.shape,
dataShape: state.dataShape,
strides: state.strides,
- dimArrays:state.dimArrays,
- dimNames:state.dimNames,
- dimUnits:state.dimUnits
+ axisDimArrays:state.axisDimArrays,
+ axisDimNames:state.axisDimNames,
+ axisDimUnits:state.axisDimUnits,
+ remapTexture: state.remapTexture,
+ flipY: state.flipY
})))
const {selectTS, xRange, yRange, zRange,getColorIdx, incrementColorIdx} = usePlotStore(useShallow(state => ({
@@ -100,13 +103,32 @@ export const UVCube = ( {scale} : {scale?:THREE.Vector3} )=>{
function HandleTimeSeries(event: THREE.Intersection){
const uv = event.uv!;
const normal = event.normal!;
+ let newUV: THREE.Vector2 | undefined;
+ if (remapTexture){ // Get new UV if reprojected and along z Axis
+ if (Math.abs(normal.z) > 0.5){ // If its along the Z just grab the full timeseries at new UV
+ const [thisUV, isValid] = sampleCRS(remapTexture, uv.x, flipY ? 1-uv.y: uv.y) // Weird double flippiing of UVs with flipY. Has something to do with how projected data is done.
+ if (flipY) thisUV.y = 1-thisUV.y
+ if (isValid) newUV = thisUV;
+ else{
+ return;
+ }
+ } else if (Math.abs(normal.x) > 0.5){ // If along Either X or y, we need a new function to resample the timeseries into the new CRS
+ // For later
+ } else {
+ //for later
+ }
+
+ }
const dimAxis = getUnitAxis(normal);
if (dimAxis != lastNormal.current){
setTimeSeries({}); //Clear timeseries if new axis
setDimCoords({});
}
lastNormal.current = dimAxis;
- const tempTS = GetTimeSeries({data: analysisMode ? analysisArray : GetCurrentArray(), shape: dataShape, stride: strides},{uv,normal})
+ const tempTS = GetTimeSeries(
+ { data: analysisMode ? analysisArray : GetCurrentArray(), shape: dataShape, stride: strides },
+ { uv: newUV ?? uv, normal }
+ )
const plotDim = (normal.toArray()).map((val, idx) => {
if (Math.abs(val) > 0) {
return idx;
@@ -114,16 +136,17 @@ export const UVCube = ( {scale} : {scale?:THREE.Vector3} )=>{
return null;}).filter(idx => idx !== null);
setPlotDim(2-plotDim[0]) //I think this 2 is only if there are 3-dims. Need to rework the logic
- const coordUV = parseUVCoords({normal:normal,uv:uv})
- let dimCoords = coordUV.map((val,idx)=>val ? dimArrays[idx][Math.round(val*dimArrays[idx].length)] : null)
- const thisDimNames = dimNames.filter((_,idx)=> dimCoords[idx] !== null)
- const thisDimUnits = dimUnits.filter((_,idx)=> dimCoords[idx] !== null)
+ const coordUV = parseUVCoords({normal:normal,uv})
+ let dimCoords = coordUV.map((val,idx)=>val ? axisDimArrays[idx][Math.round(val*axisDimArrays[idx].length)] : null)
+ const thisDimNames = axisDimNames.filter((_,idx)=> dimCoords[idx] !== null)
+ const thisDimUnits = axisDimUnits.filter((_,idx)=> dimCoords[idx] !== null)
dimCoords = dimCoords.filter(val => val !== null)
const tsID = `${dimCoords[0]}_${dimCoords[1]}`
const tsObj = {
color: evaluateColorMap(getColorIdx() / 10, 'Paired'),
normal,
uv,
+ newUV, // Delete this if never solve moving between projections. ATM is redundant
data: tempTS
}
updateTimeSeries({ [tsID] : tsObj})
@@ -132,20 +155,40 @@ export const UVCube = ( {scale} : {scale?:THREE.Vector3} )=>{
first:{
name:thisDimNames[0],
loc:dimCoords[0] ?? 0,
- units:thisDimUnits[0]
+ units:thisDimUnits[0] ?? ''
},
second:{
name:thisDimNames[1],
loc:dimCoords[1] ?? 0,
- units:thisDimUnits[1]
+ units:thisDimUnits[1] ?? ''
},
plot:{
- units:dimUnits[2-plotDim[0]]
+ units:axisDimUnits[2-plotDim[0]] ?? ''
}
}
+ console.log(dimObj)
updateDimCoords({[tsID] : dimObj})
}
+ useEffect(()=>{
+ // This effect gets the reprojected UVs for all points after reprojecting to move columns when switching to projection
+ // I can't quite get it to work so I will just clear the timeSeries for now.
+ // if (remapTexture){
+ // const newTimeSeries: Record> = {}
+ // const {timeSeries} = useGlobalStore.getState()
+ // for (const [tsID, tsObj] of Object.entries(timeSeries)){
+ // const {uv} = tsObj
+ // const [thisUV, _isValid] = sample2D(remapTexture, uv.x, flipY ? 1-uv.y: uv.y) // Should always be valid as either was plotted from original CRS, or invalid are not added in new CRS
+
+ // if (flipY) thisUV.y = 1-thisUV.y
+ // const newTSObj = {...tsObj, newUV:thisUV}
+ // newTimeSeries[tsID] = newTSObj
+ // }
+ // useGlobalStore.setState({timeSeries:newTimeSeries})
+ // }
+ useGlobalStore.setState({timeSeries:{}, dimCoords:{}})
+ },[remapTexture])
+
const {geometry, position} = useMemo(() => {
const xScale = (xRange[1] - xRange[0])/2
const yScale = (yRange[1] - yRange[0])/2
diff --git a/src/components/plots/plotarea/FixedTicks.tsx b/src/components/plots/plotarea/FixedTicks.tsx
index 5234690a..1fcd3388 100644
--- a/src/components/plots/plotarea/FixedTicks.tsx
+++ b/src/components/plots/plotarea/FixedTicks.tsx
@@ -41,10 +41,10 @@ export function FixedTicks({
const { camera, size } = useThree()
const initSize = useRef(size)
const [bounds, setBounds] = useState({ left: 0, right: 0, top: 0, bottom: 0 })
- const {dimCoords, dimArrays, plotDim, valueScales} = useGlobalStore(
+ const {dimCoords, axisDimArrays, plotDim, valueScales} = useGlobalStore(
useShallow(state=>({
dimCoords:state.dimCoords,
- dimArrays:state.dimArrays,
+ axisDimArrays:state.axisDimArrays,
plotDim:state.plotDim,
valueScales:state.valueScales
})))
@@ -57,11 +57,11 @@ export function FixedTicks({
const dimSlices = useMemo(() => {
return [
- dimArrays[zIdx]?.slice(zSlice[0], zSlice[1] ? zSlice[1] : undefined) ?? [],
- dimArrays[yIdx]?.slice(ySlice[0], ySlice[1] ? ySlice[1] : undefined) ?? [],
- dimArrays[xIdx]?.slice(xSlice[0], xSlice[1] ? xSlice[1] : undefined) ?? [],
+ axisDimArrays[zIdx]?.slice(zSlice[0], zSlice[1] ? zSlice[1] : undefined) ?? [],
+ axisDimArrays[yIdx]?.slice(ySlice[0], ySlice[1] ? ySlice[1] : undefined) ?? [],
+ axisDimArrays[xIdx]?.slice(xSlice[0], xSlice[1] ? xSlice[1] : undefined) ?? [],
]
- }, [dimArrays, xSlice, ySlice, zSlice, xIdx, yIdx, zIdx])
+ }, [axisDimArrays, xSlice, ySlice, zSlice, xIdx, yIdx, zIdx])
const xDimArray = useMemo(() => dimSlices[plotDim], [dimSlices, plotDim])
const xTickCount = 10;
const yTickCount = 8;
diff --git a/src/components/plots/plotarea/LinePlot.tsx b/src/components/plots/plotarea/LinePlot.tsx
index 7a0c356c..cac55f1a 100644
--- a/src/components/plots/plotarea/LinePlot.tsx
+++ b/src/components/plots/plotarea/LinePlot.tsx
@@ -19,12 +19,12 @@ interface pointInfo{
const MIN_HEIGHT = 10;
function PointInfo({pointID,pointLoc,showPointInfo, plotUnits}:pointInfo){
- const {plotDim, dimArrays, dimNames, dimUnits, timeSeries} = useGlobalStore(
+ const {plotDim, axisDimArrays, axisDimNames, axisDimUnits, timeSeries} = useGlobalStore(
useShallow(state=>({
plotDim:state.plotDim,
- dimArrays:state.dimArrays,
- dimNames:state.dimNames,
- dimUnits:state.dimUnits,
+ axisDimArrays:state.axisDimArrays,
+ axisDimNames:state.axisDimNames,
+ axisDimUnits:state.axisDimUnits,
timeSeries:state.timeSeries,
}))
);
@@ -33,7 +33,7 @@ function PointInfo({pointID,pointLoc,showPointInfo, plotUnits}:pointInfo){
if (Object.entries(pointID).length > 0 && Object.entries(timeSeries).length > 0){
const [tsID, idx] = pointID;
pointY = timeSeries[tsID]['data'][idx];
- pointX = dimArrays[plotDim][idx];
+ pointX = axisDimArrays[plotDim][idx];
}
const [divX,divY] = pointLoc;
@@ -59,7 +59,7 @@ function PointInfo({pointID,pointLoc,showPointInfo, plotUnits}:pointInfo){
}}
>
{`${pointY.toFixed(2)}${plotUnits??''}`}
- {`${dimNames[plotDim]}: ${parseLoc(pointX,dimUnits[plotDim])}
+ {`${axisDimNames[plotDim]}: ${parseLoc(pointX,axisDimUnits[plotDim])}
`}
}
>
diff --git a/src/components/textures/ProjectionTexture.ts b/src/components/textures/ProjectionTexture.ts
index e5821aac..259f7ca6 100644
--- a/src/components/textures/ProjectionTexture.ts
+++ b/src/components/textures/ProjectionTexture.ts
@@ -125,6 +125,24 @@ export function SetReprojectionTexture(dimArrays: Array[]){
useGlobalStore.setState({remapTexture});
}
+export function sampleCRS(tex: THREE.DataTexture, u:number, v:number): [THREE.Vector2, boolean] {
+ // Samples an array given UVs
+ const { data, width, height } = tex.image;
+ if (!data) return [new THREE.Vector2(u, v), true];
+
+ const x = Math.floor(u * (width - 1));
+ const y = Math.floor(v * (height - 1));
+
+ const idx = (y * width + x) * 4; // RGBA
+ const newU = THREE.DataUtils.fromHalfFloat(data[idx + 0])
+ const newV = THREE.DataUtils.fromHalfFloat(data[idx + 1])
+ const valid = THREE.DataUtils.fromHalfFloat(data[idx + 2])
+ return [
+ new THREE.Vector2(newU,newV),
+ valid > 0.5
+ ];
+}
+
export function reproject(resolution: number = 256){
const {nativeCRS, destCRS, plotType} = usePlotStore.getState()
if (!nativeCRS || !destCRS) return; // This shouldn't trigger as the button will be disabled for this same condition
@@ -198,7 +216,7 @@ export function reproject(resolution: number = 256){
targetWidth = width;
targetHeight = height;
xTicks = linspace(minX, maxX, targetWidth);
- yTicks = linspace(minY, maxY, targetHeight);
+ yTicks = flipY ? linspace(maxY, minY, targetHeight) : linspace(minY, maxY, targetHeight);
data = new Uint16Array(targetWidth * targetHeight * 4);
const xDiff = Math.abs(maxX - minX);
@@ -237,8 +255,7 @@ export function reproject(resolution: number = 256){
for (let i = 0; i < targetWidth; i++) {
const [lon, lat, valid] = safeInverse(proj, [xTicks[i], yTicks[j]]);
const u = xRangeDiff > 0 ? (isXDescending ? (xMax - lon) / xRangeDiff : (lon - xMin) / xRangeDiff) : 0;
- const v = yRangeDiff > 0 ? (isYDescending ? (yMax - lat) / yRangeDiff : (lat - yMin) / yRangeDiff) : 0;
-
+ const v = (isYDescending ? (yMax - lat) / yRangeDiff : (lat - yMin) / yRangeDiff)
// Check boundary bounds to avoid displaying clamped blocks outside the dataset area
const inBounds = lon >= xMin && lon <= xMax && lat >= yMin && lat <= yMax;
const validVal = (valid === 1 && inBounds) ? 1 : 0;
diff --git a/src/components/ui/MainPanel/AdjustPlot.tsx b/src/components/ui/MainPanel/AdjustPlot.tsx
index e0842be3..7e1e1a0a 100644
--- a/src/components/ui/MainPanel/AdjustPlot.tsx
+++ b/src/components/ui/MainPanel/AdjustPlot.tsx
@@ -22,6 +22,7 @@ import {Select, SelectTrigger, SelectContent, SelectItem, SelectValue} from '@/c
import { RiCloseLargeLine } from "react-icons/ri";
import { reproject } from '@/components/textures/ProjectionTexture';
import { Reprojection } from '../Elements/Reprojection';
+import { useAxisIndices } from '@/hooks';
function DeNorm(val : number, min : number, max : number){
const range = max-min;
@@ -92,17 +93,13 @@ const DimSlicer = () =>{
const defaultScales = {minVal: 0, maxVal: 0} //This is fed into MinMax as it is required but overwritten if an array is present
- const {dimArrays, dimNames, dimUnits, is4D} = useGlobalStore(useShallow(state => ({
- dimArrays : state.dimArrays,
- dimNames: state.dimNames,
- dimUnits: state.dimUnits,
+ const {axisDimArrays, axisDimNames, axisDimUnits, is4D} = useGlobalStore(useShallow(state => ({
+ axisDimArrays : state.axisDimArrays,
+ axisDimNames: state.axisDimNames,
+ axisDimUnits: state.axisDimUnits,
is4D: state.is4D
})))
-
- const theseDims = is4D ? dimNames.slice(1) : dimNames
- const theseUnits = is4D ? dimUnits.slice(1) : dimUnits
- const theseArrays = is4D ? dimArrays.slice(1) : dimArrays
-
+ const {xIdx, yIdx, zIdx} = useAxisIndices()
const [isSpatialOpen, setIsSpatialOpen] = useState(false);
return (
<>
@@ -129,33 +126,33 @@ const DimSlicer = () =>{
-
{theseDims[2]}
+ {axisDimNames[xIdx]}
-
{theseDims[1]}
+ {axisDimNames[yIdx]}
-
{theseDims[0]}
+ {axisDimNames[zIdx]}