|
- 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]
|