xy2pct 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- xy2pct-0.1.0/LICENSE +21 -0
- xy2pct-0.1.0/PKG-INFO +48 -0
- xy2pct-0.1.0/README.md +6 -0
- xy2pct-0.1.0/pyproject.toml +34 -0
- xy2pct-0.1.0/setup.cfg +4 -0
- xy2pct-0.1.0/src/xy2pct/__init__.py +7 -0
- xy2pct-0.1.0/src/xy2pct/mapgeneration/belgiumtrackmap.py +32 -0
- xy2pct-0.1.0/src/xy2pct/mapgeneration/generatelaparray.py +79 -0
- xy2pct-0.1.0/src/xy2pct/mapgeneration/parselaparray.py +93 -0
- xy2pct-0.1.0/src/xy2pct/xy2pct.py +117 -0
- xy2pct-0.1.0/src/xy2pct.egg-info/PKG-INFO +48 -0
- xy2pct-0.1.0/src/xy2pct.egg-info/SOURCES.txt +13 -0
- xy2pct-0.1.0/src/xy2pct.egg-info/dependency_links.txt +1 -0
- xy2pct-0.1.0/src/xy2pct.egg-info/requires.txt +2 -0
- xy2pct-0.1.0/src/xy2pct.egg-info/top_level.txt +1 -0
xy2pct-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JUSAAATIN
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
xy2pct-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xy2pct
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Convert track coordinates to percentages along a lap
|
|
5
|
+
Author-email: jusaaatin <jusaaatin@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 JUSAAATIN
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
Keywords: xy2pct,f1,percentages,coordinates,track,lap,data,analysis
|
|
28
|
+
Classifier: Development Status :: 4 - Beta
|
|
29
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
30
|
+
Classifier: Programming Language :: Python
|
|
31
|
+
Classifier: Programming Language :: Python :: 3
|
|
32
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
33
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
34
|
+
Classifier: Intended Audience :: Education
|
|
35
|
+
Classifier: Intended Audience :: Developers
|
|
36
|
+
Requires-Python: >=3.10
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
License-File: LICENSE
|
|
39
|
+
Requires-Dist: numpy
|
|
40
|
+
Requires-Dist: matplotlib
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
|
|
43
|
+
workflow:
|
|
44
|
+
|
|
45
|
+
1. use [generatelaparray.py](https://github.com/jusaaatin/f1-xy2pct/blob/main/generatelaparray.py) to spit out a file with x, y, and z coordinates for the track
|
|
46
|
+
2. manually delete extra data points and assign relevant ones to pit lane
|
|
47
|
+
3. use [parselaparray.py](https://github.com/jusaaatin/f1-xy2pct/blob/main/parselaparray.py) to check work (sample code to also go from file to array)
|
|
48
|
+
4. use [xy2pct.py](https://github.com/jusaaatin/f1-xy2pct/blob/main/xy2pct.py) to convert any coordinate to a percentage along the track
|
xy2pct-0.1.0/README.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
workflow:
|
|
2
|
+
|
|
3
|
+
1. use [generatelaparray.py](https://github.com/jusaaatin/f1-xy2pct/blob/main/generatelaparray.py) to spit out a file with x, y, and z coordinates for the track
|
|
4
|
+
2. manually delete extra data points and assign relevant ones to pit lane
|
|
5
|
+
3. use [parselaparray.py](https://github.com/jusaaatin/f1-xy2pct/blob/main/parselaparray.py) to check work (sample code to also go from file to array)
|
|
6
|
+
4. use [xy2pct.py](https://github.com/jusaaatin/f1-xy2pct/blob/main/xy2pct.py) to convert any coordinate to a percentage along the track
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "xy2pct"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Convert track coordinates to percentages along a lap"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [{ name = "jusaaatin", email = "jusaaatin@gmail.com" }]
|
|
11
|
+
license = { file = "LICENSE" }
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 4 - Beta",
|
|
14
|
+
"License :: OSI Approved :: MIT License",
|
|
15
|
+
"Programming Language :: Python",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Operating System :: MacOS :: MacOS X",
|
|
18
|
+
"Operating System :: Microsoft :: Windows",
|
|
19
|
+
"Intended Audience :: Education",
|
|
20
|
+
"Intended Audience :: Developers"
|
|
21
|
+
]
|
|
22
|
+
keywords = ["xy2pct", "f1", "percentages", "coordinates", "track", "lap", "data", "analysis"]
|
|
23
|
+
requires-python = ">=3.10"
|
|
24
|
+
dependencies = [
|
|
25
|
+
"numpy",
|
|
26
|
+
"matplotlib",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[tool.setuptools]
|
|
30
|
+
package-dir = {"" = "src"}
|
|
31
|
+
|
|
32
|
+
[tool.setuptools.packages.find]
|
|
33
|
+
where = ["src"]
|
|
34
|
+
|
xy2pct-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from urllib.request import urlopen
|
|
2
|
+
import json
|
|
3
|
+
import numpy as np
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
|
|
6
|
+
allx = []
|
|
7
|
+
ally = []
|
|
8
|
+
|
|
9
|
+
response = urlopen('https://api.openf1.org/v1/location?session_key=9939&date>2025-07-27T13:00:00.000&date<2025-07-27T13:20:00.000')
|
|
10
|
+
data = json.loads(response.read().decode('utf-8'))
|
|
11
|
+
for each in data:
|
|
12
|
+
allx.append(each['x'])
|
|
13
|
+
ally.append(each['y'])
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def plot(x, y):
|
|
18
|
+
x_values = np.asarray(x)
|
|
19
|
+
y_values = np.asarray(y)
|
|
20
|
+
plt.plot(x_values, y_values, 'o')
|
|
21
|
+
plt.axhline(0, color='black', linewidth=0.5, linestyle='--')
|
|
22
|
+
plt.axvline(0, color='black', linewidth=0.5, linestyle='--')
|
|
23
|
+
plt.show()
|
|
24
|
+
|
|
25
|
+
command = input("Type 'stop' to terminate: ")
|
|
26
|
+
if command == 'stop':
|
|
27
|
+
#stop application
|
|
28
|
+
print("Terminating application.")
|
|
29
|
+
exit()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
plot(allx, ally)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from urllib.request import urlopen
|
|
2
|
+
import json
|
|
3
|
+
import numpy as np
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
from datetime import datetime, timedelta
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
circuit_short_name = 'Singapore'
|
|
9
|
+
clearanceGap = 50
|
|
10
|
+
|
|
11
|
+
# get session id, date start, and date end
|
|
12
|
+
def getSessionInfo(circuit_short_name):
|
|
13
|
+
baselink = f'https://api.openf1.org/v1/sessions?circuit_short_name={circuit_short_name}&session_type=Qualifying&year=2025'
|
|
14
|
+
response = urlopen(baselink)
|
|
15
|
+
data = json.loads(response.read().decode('utf-8'))
|
|
16
|
+
session_id = data[0]['session_key']
|
|
17
|
+
date_start = data[0]['date_start']
|
|
18
|
+
print(date_start)
|
|
19
|
+
return session_id, date_start
|
|
20
|
+
|
|
21
|
+
# uses sessionid and start date to spit out array of coordinates in a lap
|
|
22
|
+
def getCoordinateArray(session_id, date_start):
|
|
23
|
+
date_end = datetime.fromisoformat(date_start) + timedelta(minutes=30)
|
|
24
|
+
coordinates = []
|
|
25
|
+
link = f'https://api.openf1.org/v1/location?driver_number=4&session_key={session_id}&date>{date_start}&date<{date_end.isoformat()}'
|
|
26
|
+
response = urlopen(link)
|
|
27
|
+
data = json.loads(response.read().decode('utf-8'))
|
|
28
|
+
for item in data:
|
|
29
|
+
datapack = 'x: {x}, y: {y}, z: {z}'.format(x=item['x'], y=item['y'], z=item['z'])
|
|
30
|
+
#delete all x=0 y=0 pairs
|
|
31
|
+
if item['x'] == 0 and item['y'] == 0:
|
|
32
|
+
continue
|
|
33
|
+
#make it so that datapack checks that each x y pair is not in +-clearanceGap of any in coordinates
|
|
34
|
+
is_unique = True
|
|
35
|
+
for existing in coordinates:
|
|
36
|
+
existing_x, existing_y, *_ = existing.split(', ')
|
|
37
|
+
if abs(float(existing_x.split(': ')[1]) - float(item['x'])) <= clearanceGap and abs(float(existing_y.split(': ')[1]) - float(item['y'])) <= clearanceGap:
|
|
38
|
+
is_unique = False
|
|
39
|
+
break
|
|
40
|
+
if is_unique:
|
|
41
|
+
coordinates.append(datapack)
|
|
42
|
+
return coordinates
|
|
43
|
+
|
|
44
|
+
# plots lap
|
|
45
|
+
def plot(coordinates):
|
|
46
|
+
x_values = []
|
|
47
|
+
y_values = []
|
|
48
|
+
for coordinate in coordinates:
|
|
49
|
+
x, y, *_ = coordinate.split(', ')
|
|
50
|
+
x_values.append(float(x.split(': ')[1]))
|
|
51
|
+
y_values.append(float(y.split(': ')[1]))
|
|
52
|
+
#make first and last color red and the rest gradient from light blue to dark blue
|
|
53
|
+
colors = ['red'] + [plt.cm.viridis(i) for i in np.linspace(0, 1, len(x_values) - 2)] + ['orange']
|
|
54
|
+
for i in range(len(x_values)):
|
|
55
|
+
plt.scatter(x_values[i], y_values[i], c=[colors[i]], marker='o')
|
|
56
|
+
plt.axhline(0, color='black', linewidth=0.5, linestyle='--')
|
|
57
|
+
plt.axvline(0, color='black', linewidth=0.5, linestyle='--')
|
|
58
|
+
plt.title(f"{circuit_short_name} Lap Array")
|
|
59
|
+
plt.show()
|
|
60
|
+
|
|
61
|
+
#generates file with track and pit lane coordinates
|
|
62
|
+
def exportToFile(coordinates, circuit_short_name):
|
|
63
|
+
folder = Path("expy")
|
|
64
|
+
folder.mkdir(exist_ok=True)
|
|
65
|
+
filename = folder / f"{circuit_short_name}.txt"
|
|
66
|
+
with open(filename, "w") as f:
|
|
67
|
+
f.write("Track\n")
|
|
68
|
+
f.write("\n".join(coordinates))
|
|
69
|
+
f.write("\n\nPit Lane")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def generateLapArray():
|
|
74
|
+
coordinatearray = getCoordinateArray(*getSessionInfo(circuit_short_name))
|
|
75
|
+
exportToFile(coordinatearray, circuit_short_name)
|
|
76
|
+
|
|
77
|
+
plot(coordinatearray)
|
|
78
|
+
|
|
79
|
+
generateLapArray()
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import numpy as np
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
from matplotlib.widgets import Button
|
|
5
|
+
|
|
6
|
+
circuit_short_name = "Belgium"
|
|
7
|
+
|
|
8
|
+
#imports expy files and turns them into separate track and pitlane coordinate arrays
|
|
9
|
+
def fileToArray(circuit_short_name):
|
|
10
|
+
folder = Path("expy")
|
|
11
|
+
folder.mkdir(exist_ok=True)
|
|
12
|
+
file_path = folder / f"{circuit_short_name}.txt"
|
|
13
|
+
|
|
14
|
+
if not file_path.exists():
|
|
15
|
+
print(f"File {file_path} does not exist.")
|
|
16
|
+
return [], []
|
|
17
|
+
|
|
18
|
+
with open(file_path, "r") as file:
|
|
19
|
+
lines = file.readlines()
|
|
20
|
+
|
|
21
|
+
track_coordinates = []
|
|
22
|
+
pit_lane_coordinates = []
|
|
23
|
+
current_section = None
|
|
24
|
+
|
|
25
|
+
for line in lines:
|
|
26
|
+
line = line.strip()
|
|
27
|
+
|
|
28
|
+
if line == "":
|
|
29
|
+
continue #ignore blank lines
|
|
30
|
+
if line == "Track":
|
|
31
|
+
current_section = "track"
|
|
32
|
+
elif line == "Pit Lane":
|
|
33
|
+
current_section = "pit_lane"
|
|
34
|
+
elif current_section == "track":
|
|
35
|
+
track_coordinates.append(line)
|
|
36
|
+
elif current_section == "pit_lane":
|
|
37
|
+
pit_lane_coordinates.append(line)
|
|
38
|
+
|
|
39
|
+
return track_coordinates, pit_lane_coordinates
|
|
40
|
+
|
|
41
|
+
# plots track and pit lane coordinates
|
|
42
|
+
def draw_plot(ax, track_coordinates, pit_lane_coordinates):
|
|
43
|
+
ax.clear()
|
|
44
|
+
|
|
45
|
+
x_values = []
|
|
46
|
+
y_values = []
|
|
47
|
+
|
|
48
|
+
for coordinate in track_coordinates:
|
|
49
|
+
x, y, *_ = coordinate.split(", ")
|
|
50
|
+
x_values.append(float(x.split(": ")[1]))
|
|
51
|
+
y_values.append(float(y.split(": ")[1]))
|
|
52
|
+
|
|
53
|
+
for coordinate in pit_lane_coordinates:
|
|
54
|
+
x, y, *_ = coordinate.split(", ")
|
|
55
|
+
x_values.append(float(x.split(": ")[1]))
|
|
56
|
+
y_values.append(float(y.split(": ")[1]))
|
|
57
|
+
|
|
58
|
+
point_colors = (
|
|
59
|
+
[plt.cm.winter(i) for i in np.linspace(0, 1, len(track_coordinates))]
|
|
60
|
+
+ [plt.cm.autumn(i) for i in np.linspace(0, 1, len(pit_lane_coordinates))]
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
for i in range(len(x_values)):
|
|
64
|
+
ax.scatter(x_values[i], y_values[i], c=[point_colors[i]], marker="o")
|
|
65
|
+
|
|
66
|
+
ax.axhline(0, color="black", linewidth=0.5, linestyle="--")
|
|
67
|
+
ax.axvline(0, color="black", linewidth=0.5, linestyle="--")
|
|
68
|
+
ax.set_title(f"{circuit_short_name} Track and Pit Lane")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def plot(circuit_short_name):
|
|
72
|
+
fig, ax = plt.subplots()
|
|
73
|
+
plt.subplots_adjust(bottom=0.2)
|
|
74
|
+
|
|
75
|
+
track_coordinates, pit_lane_coordinates = fileToArray(circuit_short_name)
|
|
76
|
+
draw_plot(ax, track_coordinates, pit_lane_coordinates)
|
|
77
|
+
|
|
78
|
+
button_ax = plt.axes([0.4, 0.05, 0.2, 0.075])
|
|
79
|
+
reload_button = Button(button_ax, "Reload")
|
|
80
|
+
|
|
81
|
+
def reload(event):
|
|
82
|
+
track_coordinates, pit_lane_coordinates = fileToArray(circuit_short_name)
|
|
83
|
+
draw_plot(ax, track_coordinates, pit_lane_coordinates)
|
|
84
|
+
fig.canvas.draw_idle()
|
|
85
|
+
|
|
86
|
+
reload_button.on_clicked(reload)
|
|
87
|
+
|
|
88
|
+
plt.show()
|
|
89
|
+
|
|
90
|
+
def parseLapArray():
|
|
91
|
+
plot(circuit_short_name)
|
|
92
|
+
|
|
93
|
+
parseLapArray()
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import numpy as np
|
|
3
|
+
import re
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
from matplotlib.widgets import Button
|
|
6
|
+
|
|
7
|
+
circuit_short_name = "Spa-Francorchamps"
|
|
8
|
+
debug = True
|
|
9
|
+
x = -3930
|
|
10
|
+
y = -1640
|
|
11
|
+
z = 0
|
|
12
|
+
|
|
13
|
+
def fileToArray(circuit_short_name):
|
|
14
|
+
folder = Path("expy")
|
|
15
|
+
folder.mkdir(exist_ok=True)
|
|
16
|
+
file_path = folder / f"{circuit_short_name}.txt"
|
|
17
|
+
|
|
18
|
+
if not file_path.exists():
|
|
19
|
+
print(f"File {file_path} does not exist.")
|
|
20
|
+
return [], []
|
|
21
|
+
|
|
22
|
+
with open(file_path, "r") as file:
|
|
23
|
+
lines = file.readlines()
|
|
24
|
+
|
|
25
|
+
track_coordinates = []
|
|
26
|
+
pit_lane_coordinates = []
|
|
27
|
+
current_section = None
|
|
28
|
+
|
|
29
|
+
for line in lines:
|
|
30
|
+
line = line.strip()
|
|
31
|
+
|
|
32
|
+
if line == "":
|
|
33
|
+
continue
|
|
34
|
+
if line == "Track":
|
|
35
|
+
current_section = "track"
|
|
36
|
+
elif line == "Pit Lane":
|
|
37
|
+
current_section = "pit_lane"
|
|
38
|
+
elif current_section == "track":
|
|
39
|
+
track_coordinates.append(line)
|
|
40
|
+
elif current_section == "pit_lane":
|
|
41
|
+
pit_lane_coordinates.append(line)
|
|
42
|
+
|
|
43
|
+
return track_coordinates, pit_lane_coordinates
|
|
44
|
+
|
|
45
|
+
def to_xyz_array(coords):
|
|
46
|
+
return np.array([
|
|
47
|
+
[float(x), float(y), float(z) if z is not None else 0.0]
|
|
48
|
+
for x, y, z in re.findall(
|
|
49
|
+
r"x:\s*(-?\d+(?:\.\d+)?),\s*y:\s*(-?\d+(?:\.\d+)?)(?:,\s*z:\s*(-?\d+(?:\.\d+)?))?",
|
|
50
|
+
"\n".join(coords),
|
|
51
|
+
)
|
|
52
|
+
])
|
|
53
|
+
|
|
54
|
+
def xy2pct(x, y, z=None, circuit_short_name=None): #takes coordinates and finds the % along the track/pit lane it is
|
|
55
|
+
if isinstance(z, str) and circuit_short_name is None:
|
|
56
|
+
circuit_short_name = z
|
|
57
|
+
z = None
|
|
58
|
+
|
|
59
|
+
if circuit_short_name is None:
|
|
60
|
+
circuit_short_name = globals()["circuit_short_name"]
|
|
61
|
+
|
|
62
|
+
track_coordinates, pit_lane_coordinates = fileToArray(circuit_short_name)
|
|
63
|
+
track = to_xyz_array(track_coordinates)
|
|
64
|
+
pit = to_xyz_array(pit_lane_coordinates)
|
|
65
|
+
|
|
66
|
+
if z is None:
|
|
67
|
+
point = np.array([x, y])
|
|
68
|
+
track_compare = track[:, :2]
|
|
69
|
+
pit_compare = pit[:, :2]
|
|
70
|
+
else:
|
|
71
|
+
point = np.array([x, y, z])
|
|
72
|
+
track_compare = track
|
|
73
|
+
pit_compare = pit
|
|
74
|
+
|
|
75
|
+
track_i = np.argmin(np.sum((track_compare - point) ** 2, axis=1))
|
|
76
|
+
pit_i = np.argmin(np.sum((pit_compare - point) ** 2, axis=1))
|
|
77
|
+
|
|
78
|
+
track_dist = np.sum((track_compare[track_i] - point) ** 2)
|
|
79
|
+
pit_dist = np.sum((pit_compare[pit_i] - point) ** 2)
|
|
80
|
+
|
|
81
|
+
onTrack = track_dist <= pit_dist
|
|
82
|
+
|
|
83
|
+
coords = track if onTrack else pit
|
|
84
|
+
index = track_i if onTrack else pit_i
|
|
85
|
+
|
|
86
|
+
highlighted = coords[index]
|
|
87
|
+
percentage = index / len(coords) * 100
|
|
88
|
+
|
|
89
|
+
if z is None:
|
|
90
|
+
print(f"highlighted coordinate: x={highlighted[0]}, y={highlighted[1]}")
|
|
91
|
+
else:
|
|
92
|
+
print(f"highlighted coordinate: x={highlighted[0]}, y={highlighted[1]}, z={highlighted[2]}")
|
|
93
|
+
print(f"onTrack: {onTrack}")
|
|
94
|
+
|
|
95
|
+
if debug:
|
|
96
|
+
return onTrack, percentage, highlighted
|
|
97
|
+
else:
|
|
98
|
+
return onTrack, percentage
|
|
99
|
+
|
|
100
|
+
def plot(x, y, highlighted, track_coordinates, pit_lane_coordinates):
|
|
101
|
+
track = to_xyz_array(track_coordinates)
|
|
102
|
+
pit = to_xyz_array(pit_lane_coordinates)
|
|
103
|
+
|
|
104
|
+
plt.scatter(track[:, 0], track[:, 1], color='blue', label='Track')
|
|
105
|
+
plt.scatter(pit[:, 0], pit[:, 1], color='green', label='Pit Lane')
|
|
106
|
+
plt.scatter(x, y, color='red', label='Input Point', zorder=5)
|
|
107
|
+
plt.scatter(highlighted[0], highlighted[1], color='orange', label='Highlighted Point', zorder=5)
|
|
108
|
+
plt.axhline(0, color='black', linewidth=0.5, linestyle='--')
|
|
109
|
+
plt.axvline(0, color='black', linewidth=0.5, linestyle='--')
|
|
110
|
+
plt.legend()
|
|
111
|
+
plt.show()
|
|
112
|
+
|
|
113
|
+
print(xy2pct(x, y, z, circuit_short_name))
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
if debug:
|
|
117
|
+
plot(x, y, xy2pct(x, y, z, circuit_short_name)[2], *fileToArray(circuit_short_name))
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xy2pct
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Convert track coordinates to percentages along a lap
|
|
5
|
+
Author-email: jusaaatin <jusaaatin@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 JUSAAATIN
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
Keywords: xy2pct,f1,percentages,coordinates,track,lap,data,analysis
|
|
28
|
+
Classifier: Development Status :: 4 - Beta
|
|
29
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
30
|
+
Classifier: Programming Language :: Python
|
|
31
|
+
Classifier: Programming Language :: Python :: 3
|
|
32
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
33
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
34
|
+
Classifier: Intended Audience :: Education
|
|
35
|
+
Classifier: Intended Audience :: Developers
|
|
36
|
+
Requires-Python: >=3.10
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
License-File: LICENSE
|
|
39
|
+
Requires-Dist: numpy
|
|
40
|
+
Requires-Dist: matplotlib
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
|
|
43
|
+
workflow:
|
|
44
|
+
|
|
45
|
+
1. use [generatelaparray.py](https://github.com/jusaaatin/f1-xy2pct/blob/main/generatelaparray.py) to spit out a file with x, y, and z coordinates for the track
|
|
46
|
+
2. manually delete extra data points and assign relevant ones to pit lane
|
|
47
|
+
3. use [parselaparray.py](https://github.com/jusaaatin/f1-xy2pct/blob/main/parselaparray.py) to check work (sample code to also go from file to array)
|
|
48
|
+
4. use [xy2pct.py](https://github.com/jusaaatin/f1-xy2pct/blob/main/xy2pct.py) to convert any coordinate to a percentage along the track
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/xy2pct/__init__.py
|
|
5
|
+
src/xy2pct/xy2pct.py
|
|
6
|
+
src/xy2pct.egg-info/PKG-INFO
|
|
7
|
+
src/xy2pct.egg-info/SOURCES.txt
|
|
8
|
+
src/xy2pct.egg-info/dependency_links.txt
|
|
9
|
+
src/xy2pct.egg-info/requires.txt
|
|
10
|
+
src/xy2pct.egg-info/top_level.txt
|
|
11
|
+
src/xy2pct/mapgeneration/belgiumtrackmap.py
|
|
12
|
+
src/xy2pct/mapgeneration/generatelaparray.py
|
|
13
|
+
src/xy2pct/mapgeneration/parselaparray.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
xy2pct
|