from dataclasses import dataclass from typing import List, Dict, Any import numpy as np @dataclass class GeoJSONGeometry: type: str coordinates: List[tuple[float, float]] @classmethod def from_dict(cls, data: Dict[str, Any]) -> 'GeoJSONGeometry': return cls( type=data['type'], coordinates=data['coordinates'] ) def find_longest_straight(self, window_size=5) -> (List[float], List[float]): """Find the longest approximately straight section of the track, including wrap-around.""" max_distance = 0 best_start_idx = 0 n = len(self.coordinates) # Helper function to check straightness def is_straight(points, start, end, length): direction = (end - start) / length distances = [] for point in points: projection = start + np.dot(point - start, direction) * direction distance = np.linalg.norm(point - projection) distances.append(distance) return max(distances) < length * 0.05 # 5% tolerance # Check all possible segments, including wrap-around for i in range(n): # Get window_size points, handling wrap-around segment = [] for j in range(window_size): idx = (i + j) % n segment.append(np.array(self.coordinates[idx])) start = np.array(segment[0]) end = np.array(segment[-1]) length = np.linalg.norm(end - start) if length > max_distance: # Check if all points are roughly on the line if is_straight(segment, start, end, length): max_distance = length best_start_idx = i # Return indices that might wrap around end_idx = (best_start_idx + window_size) % len(self.coordinates) return self.coordinates[best_start_idx], self.coordinates[end_idx]