Skip to content

Commit

Permalink
ui-manchette-with-spacetime-chart: story: zoom on manchette + spacetime
Browse files Browse the repository at this point in the history
Signed-off-by: Valentin Chanas <[email protected]>
  • Loading branch information
anisometropie committed Mar 6, 2025
1 parent fd7c036 commit 083f0c5
Show file tree
Hide file tree
Showing 12 changed files with 735 additions and 147 deletions.
3 changes: 1 addition & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,65 +1,115 @@
import { describe, it, expect } from 'vitest';
import { describe, it, test, expect } from 'vitest';

import { BASE_WAYPOINT_HEIGHT } from '../consts';
import { computeWaypointsToDisplay, getScales } from '../helpers';
import { BASE_WAYPOINT_HEIGHT, MAX_ZOOM_Y, MIN_ZOOM_Y } from '../consts';
import {
computeWaypointsToDisplay,
getScales,
getExtremaScales,
spaceScaleToZoomValue,
zoomValueToSpaceScale,
} from '../helpers';

// Assuming these types from your code

// Mock data for the tests
const mockedWaypoints = [
{ position: 0, id: 'waypoint-1' },
{ position: 10, id: 'waypoint-2' },
{ position: 20, id: 'waypoint-3' },
{ position: 100_000_000, id: 'waypoint-2' },
{ position: 200_000_000, id: 'waypoint-3' },
];
const minZoomMillimetrePerPx = 500_000;
const maxZoomMillimetrePerPx = 1_000;

describe('computeWaypointsToDisplay', () => {
it('should ensure that a empty array is returned when there is only 1 waypoint', () => {
const result = computeWaypointsToDisplay([mockedWaypoints[0]], {
height: 500,
isProportional: true,
yZoom: 1,
});
const result = computeWaypointsToDisplay(
[mockedWaypoints[0]],
{
height: 500,
isProportional: true,
yZoom: 1,
},
minZoomMillimetrePerPx,
maxZoomMillimetrePerPx
);
expect(result.length).toBe(0);
});

it('should display all points for non-proportional display', () => {
const result = computeWaypointsToDisplay(mockedWaypoints, {
height: 100,
isProportional: false,
yZoom: 1,
});
const result = computeWaypointsToDisplay(
mockedWaypoints,
{
height: 100,
isProportional: false,
yZoom: 1,
},
minZoomMillimetrePerPx,
maxZoomMillimetrePerPx
);
expect(result).toHaveLength(mockedWaypoints.length);
expect(result[0].styles?.height).toBe(`${BASE_WAYPOINT_HEIGHT}px`);
expect(result[1].styles?.height).toBe(`${BASE_WAYPOINT_HEIGHT}px`);
});

it('should correctly filter waypoints', () => {
const result = computeWaypointsToDisplay(mockedWaypoints, {
height: 100,
isProportional: true,
yZoom: 1,
});
const result = computeWaypointsToDisplay(
mockedWaypoints,
{
height: 100,
isProportional: true,
yZoom: 1,
},
minZoomMillimetrePerPx,
maxZoomMillimetrePerPx
);
expect(result).toHaveLength(2);
});

it('should return correct heights for proportional display', () => {
const result = computeWaypointsToDisplay(mockedWaypoints, {
height: 500,
isProportional: true,
yZoom: 2,
});
it('should return correct heights for proportional display, zoom 1', () => {
const result = computeWaypointsToDisplay(
mockedWaypoints,
{
height: 500,
isProportional: true,
yZoom: 1,
},
minZoomMillimetrePerPx,
maxZoomMillimetrePerPx
);
expect(result).toHaveLength(mockedWaypoints.length);
expect(result[0].styles?.height).toBe(`428px`);
expect(result[1].styles?.height).toBe(`428px`);
expect(result[0].styles?.height).toBe(`200px`);
expect(result[1].styles?.height).toBe(`200px`);
expect(result[2].styles?.height).toBe(`${BASE_WAYPOINT_HEIGHT}px`);
});

it('should return correct heights for proportional display, zoom 2', () => {
const result = computeWaypointsToDisplay(
mockedWaypoints,
{
height: 500,
isProportional: true,
yZoom: 2,
},
minZoomMillimetrePerPx,
maxZoomMillimetrePerPx
);
expect(result).toHaveLength(mockedWaypoints.length);
expect(result[0].styles?.height).toBe(`385px`);
expect(result[1].styles?.height).toBe(`385px`);
expect(result[2].styles?.height).toBe(`${BASE_WAYPOINT_HEIGHT}px`);
});

it('should ensure the last point is always displayed', () => {
const result = computeWaypointsToDisplay(mockedWaypoints, {
height: 100,
isProportional: true,
yZoom: 1,
});
const result = computeWaypointsToDisplay(
mockedWaypoints,
{
height: 100,
isProportional: true,
yZoom: 1,
},
minZoomMillimetrePerPx,
maxZoomMillimetrePerPx
);
expect(result.some((waypoint) => waypoint.id === 'waypoint-3')).toBe(true);
});
});
Expand All @@ -74,34 +124,82 @@ describe('getScales', () => {

it('Should ensure that a empty array is return when there is only 1 waypoint', () => {
const ops = [mockOpsWithPosition[0]];
const result = getScales(ops, {
height: 500,
isProportional: true,
yZoom: 1,
});
const result = getScales(
ops,
{
height: 500,
isProportional: true,
yZoom: 1,
},
minZoomMillimetrePerPx,
maxZoomMillimetrePerPx
);
expect(result).toHaveLength(0);
});

it('should return correct scale coefficients for proportional display', () => {
const result = getScales(mockOpsWithPosition, {
height: 500,
isProportional: true,
yZoom: 1,
});
expect(result).toHaveLength(1);
expect(result[0]).toHaveProperty('coefficient');
const result = getScales(
mockOpsWithPosition,
{
height: 500,
isProportional: true,
yZoom: 1,
},
minZoomMillimetrePerPx,
maxZoomMillimetrePerPx
);
expect(result).toEqual([{ from: 0, to: 200000000, coefficient: 500000 }]);
expect(result[0].size).not.toBeDefined();
});

it('should return correct size for non-proportional display', () => {
const result = getScales(mockOpsWithPosition, {
height: 500,
isProportional: false,
yZoom: 1,
});
const result = getScales(
mockOpsWithPosition,
{
height: 500,
isProportional: false,
yZoom: 1,
},
minZoomMillimetrePerPx,
maxZoomMillimetrePerPx
);

expect(result).toHaveLength(2);
expect(result[0].size).toBeDefined();
expect(result).toEqual([
{ from: 0, to: 100000000, size: 32 },
{ from: 100000000, to: 200000000, size: 32 },
]);
expect(result[0]).not.toHaveProperty('coefficient');
});
});

describe('space scale functions', () => {
const pathLength = 168056000; // mm
const manchettePxHeight = 528;
const heightBetweenFirstLastWaypoints = 489;

const { minZoomMillimetrePerPx, maxZoomMillimetrePerPx } = getExtremaScales(

Check warning on line 180 in ui-charts/src/manchette/useManchetteWithSpaceTimeChart/__tests__/helpers.spec.ts

View workflow job for this annotation

GitHub Actions / build

'minZoomMillimetrePerPx' is already declared in the upper scope on line 20 column 7

Check warning on line 180 in ui-charts/src/manchette/useManchetteWithSpaceTimeChart/__tests__/helpers.spec.ts

View workflow job for this annotation

GitHub Actions / build

'maxZoomMillimetrePerPx' is already declared in the upper scope on line 21 column 7
manchettePxHeight,
heightBetweenFirstLastWaypoints,
pathLength
);
expect(minZoomMillimetrePerPx).toBeCloseTo(343672.801);
expect(maxZoomMillimetrePerPx).toBeCloseTo(946.97);

test('zoomValueToSpaceScale', () => {
expect(
zoomValueToSpaceScale(minZoomMillimetrePerPx, maxZoomMillimetrePerPx, MIN_ZOOM_Y)
).toBeCloseTo(343672.801);
expect(
zoomValueToSpaceScale(minZoomMillimetrePerPx, maxZoomMillimetrePerPx, MAX_ZOOM_Y)
).toBeCloseTo(946.97);
});

test('spaceScaleToZoomValue', () => {
expect(
spaceScaleToZoomValue(minZoomMillimetrePerPx, maxZoomMillimetrePerPx, 343672.801)
).toBeCloseTo(MIN_ZOOM_Y);
expect(
spaceScaleToZoomValue(minZoomMillimetrePerPx, maxZoomMillimetrePerPx, 946.97)
).toBeCloseTo(MAX_ZOOM_Y);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ const ManchetteWithSpaceTimeChart = ({
>
<SpaceTimeChart
className="inset-0 absolute h-full"
spaceOrigin={0}
timeOrigin={Math.min(...projectPathTrainResult.map((p) => +p.departureTime))}
{...spaceTimeChartProps}
{...additionalSpaceTimeChartProps}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ export const BASE_WAYPOINT_HEIGHT = 32;
export const INITIAL_WAYPOINT_LIST_HEIGHT = 521;
export const INITIAL_SPACE_TIME_CHART_HEIGHT = INITIAL_WAYPOINT_LIST_HEIGHT + 40;

export const MIN_ZOOM_MS_PER_PX = 600000;
export const MIN_ZOOM_MS_PER_PX = 600_000;
export const MAX_ZOOM_MS_PER_PX = 625;
export const DEFAULT_ZOOM_MS_PER_PX = 7500;
export const DEFAULT_ZOOM_MS_PER_PX = 7_500;
export const MIN_ZOOM_X = 0;
export const MAX_ZOOM_X = 100;

export const MIN_ZOOM_Y = 1;
export const MAX_ZOOM_Y = 10.5;
export const ZOOM_Y_DELTA = 0.5;
export const MAX_ZOOM_MANCHETTE_HEIGHT_MILLIMETER = 500_000;

export const FOOTER_HEIGHT = 40; // height of the manchette footer
export const WAYPOINT_LINE_HEIGHT = 16;
Expand Down
Loading

0 comments on commit 083f0c5

Please sign in to comment.