Загрузка данных


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);
}