Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 21 additions & 22 deletions app/components/csv-preview/CsvPreviewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,34 +77,33 @@ function autoDetectSeparator(content: string): string {
return best;
}

function splitLine(line: string): string[] {
if (!separator.value) {
return [line];
}
const result = [];
let current = "";
let inQuotes = false;
for (const char of line) {
if (char === '"') {
inQuotes = !inQuotes;
} else if (char === separator.value && !inQuotes) {
result.push(current.trim());
current = "";
} else {
current += char;
}
}
result.push(current.trim());
return result;
}

function parseContent(): string[] {
if (!rawContent.value) {
return [];
}

const allLines = rawContent.value.split(/\r?\n/u).filter((line) => line.trim() !== "");

function splitLine(line: string): string[] {
if (!separator.value) {
return [line];
}
const result = [];
let current = "";
let inQuotes = false;
for (const char of line) {
if (char === '"') {
inQuotes = !inQuotes;
} else if (char === separator.value && !inQuotes) {
result.push(current.trim());
current = "";
} else {
current += char;
}
}
result.push(current.trim());
return result;
}

const headerLine = allLines[headerRow.value];
const rawHeaders = headerLine ? splitLine(headerLine) : [];

Expand Down
2 changes: 2 additions & 0 deletions app/stores/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export const useAppStore = defineStore("app", () => {
getExtensionEnabled,
} = useAppExtensions();

// oxlint-disable-next-line unicorn/consistent-function-scoping
async function upload(file: Readonly<File>, callbacks: RequestHandlers = {}): Promise<unknown> {
const store = useAppStore();
const schema = opengeodeweb_front_schemas.api.local.extensions.upload;
Expand All @@ -163,6 +164,7 @@ export const useAppStore = defineStore("app", () => {
}

// `TResult` is asserted, not verified, at the single `return result as TResult` boundary below: the backend response is only checked against `schema` at runtime, so callers' `TResult` is a contract with the schema, not something this function can prove.
// oxlint-disable-next-line unicorn/consistent-function-scoping
async function request<TResult = unknown>(
{
schema,
Expand Down
1 change: 1 addition & 0 deletions app/stores/viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const useViewerStore = defineStore(
function toggle_picking_mode(value: boolean): void {
picking_mode.value = value;
}
// oxlint-disable-next-line unicorn/consistent-function-scoping
async function request(
{
schema,
Expand Down
16 changes: 12 additions & 4 deletions internal/stores/hybrid_viewer/camera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,21 @@ function centerCameraOnPosition(
if (!camera || !pickedPosition) {
return;
}
const focalPoint = camera.getFocalPoint();
const position = camera.getPosition();
const directionOfProjection = camera.getDirectionOfProjection();
const distance = dot(
[
pickedPosition[0] - position[0],
pickedPosition[1] - position[1],
pickedPosition[2] - position[2],
],
directionOfProjection,
);
camera.setFocalPoint(...pickedPosition);
camera.setPosition(
position[0] + pickedPosition[0] - focalPoint[0],
position[1] + pickedPosition[1] - focalPoint[1],
position[2] + pickedPosition[2] - focalPoint[2],
pickedPosition[0] - distance * directionOfProjection[0],
pickedPosition[1] - distance * directionOfProjection[1],
pickedPosition[2] - distance * directionOfProjection[2],
);
}

Expand Down
12 changes: 3 additions & 9 deletions internal/stores/hybrid_viewer/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useHybridViewerCore } from "./core";
import { useViewerStore } from "@ogw_front/stores/viewer";
import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json";

async function performSetClippingPlanes(ids: string[], planes: unknown): Promise<void> {
async function setClippingPlanes(ids: string[], planes: unknown): Promise<void> {
const viewerStore = useViewerStore();
const { remoteRender } = useHybridViewerCore();
const schema = viewer_schemas.opengeodeweb_viewer.viewer.clipping_planes;
Expand All @@ -16,7 +16,7 @@ async function performSetClippingPlanes(ids: string[], planes: unknown): Promise
});
await remoteRender();
}
async function performSetShrink(ids: string[], shrink_factor: number): Promise<void> {
async function setShrink(ids: string[], shrink_factor: number): Promise<void> {
const viewerStore = useViewerStore();
const { remoteRender } = useHybridViewerCore();
const schema = viewer_schemas.opengeodeweb_viewer.viewer.shrink;
Expand All @@ -34,15 +34,9 @@ function useHybridViewerFilters(): {
setClippingPlanes: (ids: string[], planes: unknown) => Promise<void>;
setShrink: (ids: string[], shrink_factor: number) => Promise<void>;
} {
async function setClippingPlanes(ids: string[], planes: unknown): Promise<void> {
await performSetClippingPlanes(ids, planes);
}
async function setShrink(ids: string[], shrink_factor: number): Promise<void> {
await performSetShrink(ids, shrink_factor);
}
return {
setClippingPlanes,
setShrink,
};
}
export { performSetClippingPlanes, performSetShrink, useHybridViewerFilters };
export { useHybridViewerFilters };
14 changes: 4 additions & 10 deletions internal/stores/hybrid_viewer/viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface HybridViewerViewport {
viewStream: Ref<ViewStreamLike | undefined>;
}

async function performResize(width: number, height: number): Promise<void> {
async function resize(width: number, height: number): Promise<void> {
const { genericRenderWindow, remoteRender, status, viewStream } = useHybridViewerCore();
const viewerStore = useViewerStore();
if (viewerStore.status !== Status.CONNECTED || status.value !== Status.CREATED) {
Expand Down Expand Up @@ -77,7 +77,7 @@ function performClickPicking(event: MouseEvent, containerElement: HTMLElement):
);
}

function performSetContainer(container: ContainerRef | undefined): void {
function setContainer(container: ContainerRef | undefined): void {
if (!container || !container.value) {
return;
}
Expand All @@ -102,7 +102,7 @@ function performSetContainer(container: ContainerRef | undefined): void {
transition: "opacity 0.1s ease-in",
zIndex: 1,
});
void performResize(containerElement.offsetWidth, containerElement.offsetHeight);
void resize(containerElement.offsetWidth, containerElement.offsetHeight);
let has_dragged = false;
useMousePressed({
target: containerElement,
Expand Down Expand Up @@ -167,17 +167,11 @@ function performSetContainer(container: ContainerRef | undefined): void {
}
function useHybridViewerViewport(): HybridViewerViewport {
const { viewStream } = useHybridViewerCore();
function setContainer(container: ContainerRef | undefined): void {
performSetContainer(container);
}
async function resize(width: number, height: number): Promise<void> {
await performResize(width, height);
}
return {
setContainer,
resize,
viewStream,
};
}
export { performClickPicking, performResize, performSetContainer, useHybridViewerViewport };
export { performClickPicking, useHybridViewerViewport };
export type { ViewStreamLike } from "./vtk_types";
37 changes: 37 additions & 0 deletions tests/unit/stores/hybrid_viewer_camera.nuxt.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { describe, expect, test } from "vitest";

import type { Vector3 } from "@ogw_internal/stores/hybrid_viewer/vtk_types";
import { centerCameraOnPosition } from "@ogw_internal/stores/hybrid_viewer/camera";
import { newInstance as vtkCamera } from "@kitware/vtk.js/Rendering/Core/Camera";

const INITIAL_CAMERA_Z = 100;
const PICKED_X = 20;
const PICKED_Y = 30;
const PICKED_Z = 80;

describe("centerCameraOnPosition helper", () => {
test("preserves distance along view direction and centers on picked position", () => {
const camera = vtkCamera();
camera.setPosition(0, 0, INITIAL_CAMERA_Z);
camera.setFocalPoint(0, 0, 0);

const pickedPosition: Vector3 = [PICKED_X, PICKED_Y, PICKED_Z];
centerCameraOnPosition(camera, pickedPosition);

expect(camera.getFocalPoint()).toStrictEqual(pickedPosition);
expect(camera.getPosition()).toStrictEqual([PICKED_X, PICKED_Y, INITIAL_CAMERA_Z]);
expect(camera.getDirectionOfProjection()).toStrictEqual([0, 0, -1]);
});

test("handles undefined inputs gracefully", () => {
const camera = vtkCamera();
camera.setPosition(0, 0, INITIAL_CAMERA_Z);
camera.setFocalPoint(0, 0, 0);

centerCameraOnPosition(undefined, [1, 2, 3]);
centerCameraOnPosition(camera, undefined);

expect(camera.getPosition()).toStrictEqual([0, 0, INITIAL_CAMERA_Z]);
expect(camera.getFocalPoint()).toStrictEqual([0, 0, 0]);
});
});
Loading