import { IPosition, ISymbol } from "./frame.types"; export class Symbol implements ISymbol { table: string; // Symbol table identifier code: string; // Symbol code constructor(table: string, code?: string) { if (code === undefined) { if (table.length === 2) { this.code = table[1]; this.table = table[0]; } else { throw new Error(`Invalid symbol format: '${table}' (expected 2 characters if code is not provided)`); } } else { this.table = table; this.code = code; } } public toString(): string { return `${this.table}${this.code}`; } } export class Position implements IPosition { latitude: number; // Decimal degrees longitude: number; // Decimal degrees ambiguity?: number; // Position ambiguity (0-4) altitude?: number; // Meters speed?: number; // Speed in knots/kmh depending on source course?: number; // Course in degrees symbol?: Symbol; comment?: string; constructor(data: Partial) { this.latitude = data.latitude ?? 0; this.longitude = data.longitude ?? 0; this.ambiguity = data.ambiguity; this.altitude = data.altitude; this.speed = data.speed; this.course = data.course; if (typeof data.symbol === 'string') { this.symbol = new Symbol(data.symbol); } else if (data.symbol) { this.symbol = new Symbol(data.symbol.table, data.symbol.code); } this.comment = data.comment; } public toString(): string { const latStr = this.latitude.toFixed(5); const lonStr = this.longitude.toFixed(5); const altStr = this.altitude !== undefined ? `,${this.altitude}m` : ''; return `${latStr},${lonStr}${altStr}`; } public distanceTo(other: IPosition): number { const R = 6371e3; // Earth radius in meters const lat1 = this.latitude * Math.PI / 180; const lat2 = other.latitude * Math.PI / 180; const dLat = (other.latitude - this.latitude) * Math.PI / 180; const dLon = (other.longitude - this.longitude) * Math.PI / 180; const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon/2) * Math.sin(dLon/2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return R * c; // Distance in meters } }