Skip to content

Commit fd4f68e

Browse files
committed
Can handle 2D variables now
1 parent c8da807 commit fd4f68e

File tree

10 files changed

+104
-35
lines changed

10 files changed

+104
-35
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"next": "15.3.1",
4949
"next-themes": "^0.4.6",
5050
"quick-lru": "^7.0.1",
51+
"r3f-perf": "^7.2.3",
5152
"random-words": "^2.0.1",
5253
"rc-slider": "^11.1.8",
5354
"react": "^19.0.0",

src/components/computation/ComputeModule.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ const ComputeModule = ({arrays,values, setters}:ComputeModule) => {
107107
},[execute, axis, secondArray, firstArray, operation])
108108

109109
const shapeRatio = useMemo(()=>flipY ? planeShape[0]/planeShape[1]*-2 : planeShape[0]/planeShape[1]*2,[flipY,planeShape])
110-
console.log(shapeRatio)
111110
useEffect(()=>{
112111
if(GPUCompute){
113112
GPUCompute.dispose()

src/components/plots/FlatMap.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React, {useMemo, useEffect} from 'react'
2+
import * as THREE from 'three'
3+
import { useGlobalStore } from '@/utils/GlobalStates'
4+
import { fragShader, vertShader } from '@/components/computation/shaders'
5+
import { useShallow } from 'zustand/shallow'
6+
7+
8+
const FlatMap = ({texture} : {texture : THREE.DataTexture}) => {
9+
const {shape, flipY, colormap} = useGlobalStore(useShallow(state => ({shape: state.shape, flipY: state.flipY, colormap: state.colormap})))
10+
console.log(flipY)
11+
const shapeRatio = useMemo(()=> shape.x/shape.z, [shape])
12+
const geometry = useMemo(()=>new THREE.PlaneGeometry(2,shapeRatio),[shapeRatio])
13+
const material = new THREE.MeshBasicMaterial({color: 'red'})
14+
const shaderMaterial = new THREE.ShaderMaterial({
15+
glslVersion: THREE.GLSL3,
16+
uniforms:{
17+
data : {value: texture},
18+
cmap : { value : colormap},
19+
},
20+
vertexShader: vertShader,
21+
fragmentShader: fragShader,
22+
side: THREE.DoubleSide,
23+
})
24+
useEffect(()=>{
25+
geometry.dispose()
26+
},[geometry])
27+
return (
28+
29+
<mesh material={shaderMaterial} geometry={geometry} scale={[1, flipY ? -1 : 1 , 1]}/>
30+
)
31+
}
32+
33+
export {FlatMap}

src/components/plots/Plot.tsx

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ import { OrbitControls } from '@react-three/drei';
22
import React, { useMemo } from 'react';
33
import { useState, useEffect } from 'react';
44
import * as THREE from 'three';
5-
import { PointCloud, UVCube, DataCube } from '@/components/plots';
5+
import { PointCloud, UVCube, DataCube, FlatMap } from '@/components/plots';
66
import { Canvas, useThree } from '@react-three/fiber';
77
import { ArrayToTexture, DefaultCubeTexture } from '@/components/textures';
88
import { ZarrDataset } from '../zarr/ZarrLoaderLRU';
99
import { useGlobalStore, usePlotStore } from '@/utils/GlobalStates';
1010
import { useShallow } from 'zustand/shallow';
1111
import { Navbar, PlotLineButton } from '../ui';
1212

13-
1413
interface PlotParameters{
1514
values:{
1615
ZarrDS: ZarrDataset;
@@ -21,7 +20,6 @@ interface PlotParameters{
2120
}
2221

2322
const Plot = ({values,setShowLoading}:PlotParameters) => {
24-
2523
const {
2624
setShape,
2725
setFlipY,
@@ -39,11 +37,13 @@ const Plot = ({values,setShowLoading}:PlotParameters) => {
3937
setDimNames:state.setDimNames,
4038
setDimUnits:state.setDimUnits}
4139
)))
42-
const {colormap, variable} = useGlobalStore(useShallow(state=>({colormap: state.colormap, variable: state.variable})))
43-
40+
const {colormap, variable, isFlat, setIsFlat} = useGlobalStore(useShallow(state=>({
41+
colormap: state.colormap, variable: state.variable, isFlat: state.isFlat, setIsFlat: state.setIsFlat
42+
})))
4443
const {ZarrDS,canvasWidth} = values;
4544
const plotType = usePlotStore(state => state.plotType)
4645

46+
4747
const [texture, setTexture] = useState<THREE.DataTexture | THREE.Data3DTexture | null>(null)
4848
// const [currentBg, setCurrentBg] = useState(bgcolor || 'var(--background)')
4949
const [show, setShow] = useState<boolean>(true)
@@ -100,6 +100,12 @@ const Plot = ({values,setShowLoading}:PlotParameters) => {
100100
setValueScales(scaling as { maxVal: number; minVal: number });
101101

102102
}
103+
if (result.shape.length == 2){
104+
setIsFlat(true)
105+
}
106+
else{
107+
setIsFlat(false)
108+
}
103109
const shapeRatio = result.shape[1] / result.shape[2] * 2;
104110
setShape(new THREE.Vector3(2, shapeRatio, 2));
105111
setShowLoading(false)
@@ -110,10 +116,18 @@ const Plot = ({values,setShowLoading}:PlotParameters) => {
110116
setMetadata(result);
111117
const [dimArrs, dimMetas, dimNames] = ZarrDS.GetDimArrays()
112118
setDimArrays(dimArrs)
113-
if (dimArrs[1][1] < dimArrs[1][0])
114-
{setFlipY(true)}
115-
else
116-
{setFlipY(false)}
119+
if (dimArrs.length > 2){
120+
if (dimArrs[1][1] < dimArrs[1][0])
121+
{setFlipY(true)}
122+
else
123+
{setFlipY(false)}
124+
}
125+
else{
126+
if (dimArrs[0][1] < dimArrs[0][0])
127+
{setFlipY(true)}
128+
else
129+
{setFlipY(false)}
130+
}
117131
const tempDimUnits = []
118132
for (const meta of dimMetas){
119133
tempDimUnits.push(meta.units)
@@ -135,26 +149,33 @@ const Plot = ({values,setShowLoading}:PlotParameters) => {
135149
width: windowWidth - canvasWidth
136150
}}
137151
>
138-
{plotType == "volume" && <PlotLineButton />}
152+
{plotType == "volume" && !isFlat && <PlotLineButton />}
139153
<Nav />
140-
<Canvas camera={{ position: [-4.5, 3, 4.5], fov: 50 }}
154+
155+
{!isFlat && <>
156+
<Canvas camera={{ position: isFlat ? [0,0,5] : [-4.5, 3, 4.5], fov: 50 }}
141157
frameloop="demand"
142-
style={{
143-
// background: currentBg
144-
}}
145158
>
146-
{/* Volume Plots */}
147159
{plotType == "volume" && show && <>
148160
<DataCube volTexture={texture}/>
149161
<UVCube ZarrDS={ZarrDS} />
150162
</>}
151-
{/* Point Clouds */}
152163
{plotType == "point-cloud" && show && <PointCloud textures={{texture,colormap}} />}
153-
154-
<OrbitControls minPolarAngle={0} maxPolarAngle={Math.PI / 2} enablePan={false}
155-
maxDistance={50}
156-
/>
164+
<OrbitControls minPolarAngle={0} maxPolarAngle={Math.PI / 2} enablePan={false} maxDistance={50}/>
157165
</Canvas>
166+
</>}
167+
168+
169+
{isFlat && <>
170+
<Canvas camera={{ position: [0,0,5], zoom: 1000 }}
171+
frameloop="demand"
172+
orthographic
173+
>
174+
<FlatMap texture={texture as THREE.DataTexture} />
175+
<OrbitControls enableRotate={false} enablePan={true} maxDistance={50} minZoom={50} maxZoom={2000}/>
176+
</Canvas>
177+
</>}
178+
158179
</div>
159180
)
160181
}

src/components/plots/ThickLine.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,19 @@ const ThickLine = ({height, xScale, yScale, pointSetters} : ThickLineProps) => {
8383
return curve.getPoints(points.length*lineResolution-1)
8484
},[points, lineResolution])
8585

86+
const normedInterp = useMemo(() => {
87+
if (normed.length < 2) return [];
88+
const interp: number[] = [];
89+
for (let i = 0; i < linePoints.length; i++) {
90+
const t = i / (linePoints.length - 1);
91+
const idx = t * (normed.length - 1);
92+
const idx0 = Math.floor(idx);
93+
const idx1 = Math.min(normed.length - 1, Math.ceil(idx));
94+
const frac = idx - idx0;
95+
interp.push(normed[idx0] * (1 - frac) + normed[idx1] * frac);
96+
}
97+
return interp;
98+
}, [normed, linePoints.length]);
8699
const geometry = useMemo(() => {
87100
if (linePoints.length < 2) return new THREE.BufferGeometry(); // Need at least 2 points
88101
// Step 2: Duplicate vertices and compute attributes
@@ -103,7 +116,7 @@ const ThickLine = ({height, xScale, yScale, pointSetters} : ThickLineProps) => {
103116
directions.push(1.0, -1.0);
104117
previous.push(...prevPoint, ...prevPoint);
105118
next.push(...nextPoint, ...nextPoint);
106-
normValues.push(...Array(lineResolution).fill(normed[i]),...Array(lineResolution).fill(normed[i]))
119+
normValues.push(normedInterp[i], normedInterp[i]);
107120
}
108121

109122

src/components/plots/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export {FixedTicks} from './FixedTicks'
77
export {Plot} from './Plot'
88
export {Analysis} from './Analysis';
99
export {ThickLine} from './ThickLine'
10-
export {PlotPoints} from './PlotPoints'
10+
export {PlotPoints} from './PlotPoints'
11+
export {FlatMap} from './FlatMap'

src/components/textures/TextureMakers.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@ function ArrayTo2D(array: Array){
1313
//We assume there is no slicing here. That will occur in the ZarrLoader stage. This is just pure data transfer
1414
const shape = array.shape;
1515
const data = Array.from(array.data);
16-
17-
const width = shape[0];
18-
const height = shape[1];
19-
16+
const width = shape[1];
17+
const height = shape[0];
2018
const [minVal,maxVal] = ArrayMinMax(data)
2119

2220
const normed = data.map((i)=>(i-minVal)/(maxVal-minVal))
@@ -47,7 +45,6 @@ export function ArrayTo3D(array: Array){
4745
volTexture.format = THREE.RedFormat;
4846
volTexture.minFilter = THREE.NearestFilter;
4947
volTexture.magFilter = THREE.NearestFilter;
50-
// volTexture.unpackAlignment = 1;
5148
volTexture.needsUpdate = true;
5249
return [volTexture, {maxVal,minVal}]
5350

src/components/ui/Navbar.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,14 @@ const ColorMaps = ({cmap, setCmap} : {cmap : string, setCmap : React.Dispatch<Re
105105
}
106106

107107
const Navbar = React.memo(function Navbar(){
108-
const {setInitStore, setVariable, setColormap, setTimeSeries} = useGlobalStore(
108+
const {setInitStore, setVariable, setColormap, setTimeSeries, isFlat, plotOn} = useGlobalStore(
109109
useShallow(state=>({
110110
setInitStore : state.setInitStore,
111111
setVariable : state.setVariable,
112112
setColormap : state.setColormap,
113-
setTimeSeries: state.setTimeSeries
113+
setTimeSeries: state.setTimeSeries,
114+
isFlat: state.isFlat,
115+
plotOn: state.plotOn
114116
})))
115117

116118
const variables = useGlobalStore(useShallow(state=>state.variables))
@@ -149,7 +151,6 @@ const Navbar = React.memo(function Navbar(){
149151
</DropdownMenuItem>
150152
</DropdownMenuGroup>
151153
<DropdownMenuSeparator />
152-
<DropdownMenuLabel>Plot Options</DropdownMenuLabel>
153154
<DropdownMenuSub>
154155
<DropdownMenuSubTrigger>Plot Type</DropdownMenuSubTrigger>
155156
<DropdownMenuPortal>
@@ -161,7 +162,6 @@ const Navbar = React.memo(function Navbar(){
161162
</DropdownMenuSub>
162163
<DropdownMenuSeparator />
163164
<DropdownMenuSub>
164-
<DropdownMenuLabel>Colormap</DropdownMenuLabel>
165165
<ColorMaps cmap={cmap} setCmap={setCmap}/>
166166
<Button className="w-[100%] h-[20px] cursor-[pointer]" variant="destructive" onClick={()=>setFlipCmap(x=>!x)}>Flip Colormap</Button>
167167
</DropdownMenuSub>
@@ -189,7 +189,7 @@ const Navbar = React.memo(function Navbar(){
189189
</SelectContent>
190190
</Select>
191191

192-
<PlotTweaker/>
192+
{!isFlat && <PlotTweaker/>}
193193
</div>
194194
<ThemeSwitch />
195195
<AboutButton />

src/components/ui/PlotTweaker.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ const VolumeTweaks = () => {
9595
const [yScales, setYScales] = useState<{minVal: number, maxVal: number}>({minVal: 0, maxVal: 0})
9696
const [zScales, setZScales] = useState<{minVal: number, maxVal: number}>({minVal: 0, maxVal: 0})
9797

98-
const {valueScales, dimArrays} = useGlobalStore(useShallow(state => ({valueScales : state.valueScales, dimArrays : state.dimArrays})))
98+
const {valueScales, dimArrays} = useGlobalStore(useShallow(state => ({valueScales : state.valueScales, dimArrays : state.dimArrays, isFlat: state.isFlat})))
9999

100100
useEffect(()=>{
101-
if (dimArrays){
101+
if (dimArrays.length === 3){
102102
const [xMin, xMax] = ArrayMinMax(dimArrays[2]);
103103
const [yMin, yMax] = ArrayMinMax(dimArrays[1]);
104104
const [zMin, zMax] = ArrayMinMax(dimArrays[0]);

src/utils/GlobalStates.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type StoreState = {
3333
variable: string;
3434
variables: string[];
3535
plotOn: boolean;
36+
isFlat: boolean;
3637

3738
setShape: (shape: THREE.Vector3) => void;
3839
setValueScales: (valueScales: { maxVal: number; minVal: number }) => void;
@@ -51,6 +52,7 @@ type StoreState = {
5152
setVariable: (variable: string) => void;
5253
setVariables: (variables: string[]) => void;
5354
setPlotOn: (plotOn: boolean) => void;
55+
setIsFlat: (isFlat: boolean) => void;
5456

5557
};
5658

@@ -73,6 +75,7 @@ export const useGlobalStore = create<StoreState>((set) => ({
7375
variable: 'Default',
7476
variables: [],
7577
plotOn: false,
78+
isFlat:false,
7679

7780
setShape: (shape) => set({ shape }),
7881
setValueScales: (valueScales) => set({ valueScales }),
@@ -91,6 +94,7 @@ export const useGlobalStore = create<StoreState>((set) => ({
9194
setVariable: (variable) => set({ variable }),
9295
setVariables: (variables) => set({variables}),
9396
setPlotOn: (plotOn) => set({ plotOn }),
97+
setIsFlat: (isFlat) => set({ isFlat})
9498
}));
9599

96100
type PlotState ={

0 commit comments

Comments
 (0)