import type { Point, UpdatableView } from './types';
export function updateViews(views: readonly UpdatableView[]): void {
for (const view of views) {
view.update();
}
}
export function getOrderedSideValue<T>(
startValue: T | null,
endValue: T | null,
startCoordinate: number | null,
endCoordinate: number | null,
side: 'start' | 'end',
): T | null {
if (startValue === null || endValue === null) {
return null;
}
if (startCoordinate === null || endCoordinate === null) {
return side === 'start' ? startValue : endValue;
}
const startFirst = startCoordinate <= endCoordinate;
if (side === 'start') {
return startFirst ? startValue : endValue;
}
return startFirst ? endValue : startValue;
}
export function drawRoundedRect(
context: CanvasRenderingContext2D,
x: number,
y: number,
width: number,
height: number,
radius: number,
): void {
const safeRadius = Math.min(radius, width / 2, height / 2);
context.moveTo(x + safeRadius, y);
context.arcTo(x + width, y, x + width, y + height, safeRadius);
context.arcTo(x + width, y + height, x, y + height, safeRadius);
context.arcTo(x, y + height, x, y, safeRadius);
context.arcTo(x, y, x + width, y, safeRadius);
context.closePath();
}
export function getDistanceToSegment(point: Point, startPoint: Point, endPoint: Point): number {
const dx = endPoint.x - startPoint.x;
const dy = endPoint.y - startPoint.y;
if (dx === 0 && dy === 0) {
return Math.hypot(point.x - startPoint.x, point.y - startPoint.y);
}
const t = Math.max(
0,
Math.min(1, ((point.x - startPoint.x) * dx + (point.y - startPoint.y) * dy) / (dx * dx + dy * dy)),
);
const projectionX = startPoint.x + t * dx;
const projectionY = startPoint.y + t * dy;
return Math.hypot(point.x - projectionX, point.y - projectionY);
}