Last active
November 20, 2024 07:16
-
-
Save rene-d/67d2d36e143e753de4f459e00b6f5565 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import typing as t | |
from dataclasses import dataclass | |
from pathlib import Path | |
import gpxpy.gpx | |
import matplotlib.pyplot as plt | |
import numpy as np | |
from geopy.distance import geodesic, great_circle | |
from scipy import optimize | |
@dataclass | |
class Position: | |
rank: int | |
"""Rank.""" | |
boat: int | |
"""Boat ID.""" | |
pos: t.Tuple[float, float] | |
"""(latitude,longitude).""" | |
dtf: float | |
"""Distance To Finish.""" | |
# situation à 2024-11-19 18:00:00Z | |
boats = [ | |
(1, 100, (11.38819, -29.69734), 21898.62), | |
(2, 112, (12.29817, -28.87315), 21942.12), | |
(3, 59, (11.90237, -32.12561), 21962.91), | |
(4, 79, (12.33021, -30.47561), 21963.93), | |
(5, 29, (13.31248, -23.19468), 21981.4), | |
(6, 85, (12.46197, -31.18362), 21981.4), | |
(7, 24, (12.83107, -30.36251), 21991.72), | |
(8, 17, (13.03418, -29.82524), 21996.75), | |
(9, 109, (13.12718, -29.47032), 21997.88), | |
(10, 3, (13.04665, -30.4648), 22005.68), | |
(11, 15, (13.24158, -29.79702), 22008.57), | |
(12, 8, (13.36931, -30.3552), 22023.13), | |
(13, 2030, (13.55294, -31.22079), 22045.5), | |
(14, 13, (15.01302, -29.69932), 22111.45), | |
(15, 9, (14.75602, -31.11975), 22114.32), | |
(16, 777, (14.6393, -31.84201), 22117.56), | |
(17, 1297, (15.30331, -31.1623), 22146.86), | |
(18, 64, (15.5461, -20.21022), 22150.58), | |
(19, 83, (15.86659, -28.71502), 22150.83), | |
(20, 10, (15.2953, -31.69812), 22153.72), | |
(21, 5, (16.07474, -28.7498), 22163.48), | |
(22, 30, (16.10143, -29.05133), 22168.25), | |
(23, 14, (16.23872, -28.53493), 22170.96), | |
(24, 27, (15.83012, -30.84266), 22173.47), | |
(25, 18, (16.03118, -30.41587), 22179.88), | |
(26, 172, (16.01677, -31.02538), 22186.76), | |
(27, 1000, (16.36148, -30.19907), 22196.62), | |
(28, 34, (17.06822, -27.10704), 22207.26), | |
(29, 1461, (17.02256, -27.80812), 22210.35), | |
(30, 1, (16.83, -29.30191), 22213.93), | |
(31, 22, (16.82604, -30.60685), 22228.85), | |
(32, 56, (17.32101, -28.82298), 22237.85), | |
(33, 1101, (17.11098, -30.76336), 22247.49), | |
(34, 7, (18.10653, -27.17554), 22269.61), | |
(35, 71, (17.9222, -30.9677), 22297.58), | |
(36, 49, (20.08421, -26.79358), 22385.4), | |
(37, 26, (20.27418, -30.45783), 22429.58), | |
(38, 5005, (21.44229, -27.90038), 22473.51), | |
(39, 23, (26.48877, -15.8225), 22851.54), | |
(40, 53, (39.20913, -13.00027), 23619.75), | |
] | |
boats = [Position(*p) for p in boats] | |
leader = boats[0] | |
# dtl = dtf - min(dtf) | |
# min(dtf) <=> leader | |
def dist_to_leader(boat, marque): | |
# return (great_circle(marque, boat.pos).meters - great_circle(marque, leader.pos).meters) / 1852 | |
return (geodesic(marque, boat.pos).meters - geodesic(marque, leader.pos).meters) / 1852 | |
def dichotomie(lat, lon_a, lon_b, d_cible, boat): | |
while (lon_b - lon_a) > 0.1: | |
lon = (lon_a + lon_b) / 2 | |
d = dist_to_leader(boat, (lat, lon)) | |
if d <= d_cible: | |
lon_b = lon | |
else: | |
lon_a = lon | |
lon = round((lon_a + lon_b) / 2, 6) | |
return (lat, lon) | |
marque = (-34.994004, 19.335938) # Le Cap | |
marque = (-4.313546, -25.587158) | |
for boat in boats[1:]: | |
dtl_calc = dist_to_leader(boat, marque) | |
dtl = boat.dtf - leader.dtf | |
e = round(abs(dtl_calc - dtl) / dtl * 100, 1) | |
print(f"{boat.boat:4} {dtl_calc:8.3f} {dtl:8.3f} {e:g}") | |
exit() | |
for i in range(35, 40): | |
boat = boats[i] | |
gpx = gpxpy.gpx.GPX() | |
gpx_track = gpxpy.gpx.GPXTrack(name="test") | |
gpx.tracks.append(gpx_track) | |
gpx_segment = gpxpy.gpx.GPXTrackSegment() | |
gpx_track.segments.append(gpx_segment) | |
lon_w = -45 | |
lon_e = 22 | |
lon = (lon_w + lon_e) / 2 | |
for lat in range(-32, 8, 4): | |
###### | |
def f(lon): | |
return dist_to_leader(boat, (lat, lon)) | |
dtl = boat.dtf - leader.dtf | |
x = np.linspace(lon_w, lon_e, 100) | |
y = [f(lon) for lon in x] | |
plt.plot(x, y, color="red") | |
plt.axhline(y=dtl, color="blue", linestyle="-") | |
plt.show() | |
roots = optimize.fsolve(lambda x: f(x) - dtl, lon) | |
lon = roots[0] | |
###### | |
print(f"{lat},{lon}") | |
gpx_segment.points.append(gpxpy.gpx.GPXTrackPoint(lat, lon)) | |
Path(f"hyperboule{i}.gpx").write_text(gpx.to_xml()) | |
os.system(f"open -a GPXSee dicho{i}.gpx") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment