import type { Iwt2ArenaBounds, Iwt2Circle, Iwt2Vec2 } from './types' import { addVec2, clamp, clampVec2ToArena, distanceVec2, dotVec2, lengthSqVec2, normalizeVec2, scaleVec2, subtractVec2, } from './vector' export function circlesOverlap(a: Iwt2Circle, b: Iwt2Circle): boolean { const radiusSum = a.radius + b.radius return distanceVec2(a.position, b.position) <= radiusSum } export function distanceToSegment(point: Iwt2Vec2, start: Iwt2Vec2, end: Iwt2Vec2): number { const segment = subtractVec2(end, start) const segmentLengthSq = lengthSqVec2(segment) if (segmentLengthSq <= 0.0001) return distanceVec2(point, start) const pointOffset = subtractVec2(point, start) const t = clamp(dotVec2(pointOffset, segment) / segmentLengthSq, 0, 1) const projection = addVec2(start, scaleVec2(segment, t)) return distanceVec2(point, projection) } export function circleIntersectsSegment( circle: Iwt2Circle, start: Iwt2Vec2, end: Iwt2Vec2, width: number, ): boolean { return distanceToSegment(circle.position, start, end) <= circle.radius + width } export function separateCircles(moving: Iwt2Circle, fixed: Iwt2Circle, bounds: Iwt2ArenaBounds): Iwt2Vec2 { const offset = subtractVec2(moving.position, fixed.position) const minDistance = moving.radius + fixed.radius const distanceSq = lengthSqVec2(offset) if (distanceSq >= minDistance * minDistance) return moving.position const direction = distanceSq <= 0.0001 ? { x: 1, y: 0 } : normalizeVec2(offset) const resolved = addVec2(fixed.position, scaleVec2(direction, minDistance)) return clampVec2ToArena(resolved, moving.radius, bounds) }