inital commit, add lab1
This commit is contained in:
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
# .gitignore
|
||||
|
||||
# Python compilation
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# Distribution / packaging
|
||||
dist/
|
||||
build/
|
||||
*.egg-info/
|
||||
|
||||
# Virtual environments
|
||||
.venv/
|
||||
env/
|
||||
venv/
|
||||
|
||||
# IDE settings
|
||||
.vscode/
|
||||
|
||||
# OS generated files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
1
lab1/.python-version
Normal file
1
lab1/.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.14
|
||||
36
lab1/README.md
Normal file
36
lab1/README.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# CSE 5543 Lab 1: Interactive Bezier Curve Editor
|
||||
|
||||
Author: Zhe Yuan
|
||||
|
||||
## Create Environment
|
||||
|
||||
I use `uv` to create a virtual environment for this project. You can synchronize the environment by running:
|
||||
|
||||
```bash
|
||||
uv sync
|
||||
```
|
||||
|
||||
## Run the Code
|
||||
To run the interactive Bezier curve editor, execute the following command in your terminal:
|
||||
|
||||
```bash
|
||||
uv run ibezier.py <num_points> OR <filename>
|
||||
```
|
||||
|
||||
- `<num_points>`: An integer specifying the number of control points to create a new Bezier curve.
|
||||
- `<filename>`: A string specifying the path to a file containing control points to load an existing Bezier curve.
|
||||
|
||||
For example, to create a new Bezier curve with 5 control points, run:
|
||||
|
||||
```bash
|
||||
uv run ibezier.py 5
|
||||
```
|
||||
To load control points from a file named `control_points.txt`, run:
|
||||
|
||||
```bash
|
||||
uv run ibezier.py control_points.txt
|
||||
```
|
||||
|
||||
## Statement of AI Usage
|
||||
|
||||
I use Github Copilot's Auto Completion feature to help me write code and README faster. I ask Gemini to help me to debug GUI issues.
|
||||
8
lab1/bezier_circle.txt
Normal file
8
lab1/bezier_circle.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
BEZIER
|
||||
# Saved from ibezier.py
|
||||
2 5 4
|
||||
0.20376344086021506 0.7175324675324677
|
||||
0.2876344086021505 0.9951298701298703
|
||||
0.6290322580645161 0.5357142857142858
|
||||
0.14301075268817207 0.43262987012987014
|
||||
0.20376344086021506 0.7183441558441559
|
||||
10
lab1/bezier_figures.txt
Normal file
10
lab1/bezier_figures.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
BEZIER
|
||||
# Saved from ibezier.py
|
||||
2 7 6
|
||||
0.18655913978494623 0.5673701298701299
|
||||
0.21021505376344088 0.7297077922077924
|
||||
0.7161290322580646 0.16964285714285715
|
||||
0.5908602150537635 0.5349025974025974
|
||||
0.6827956989247312 0.9569805194805197
|
||||
0.25322580645161286 0.2865259740259741
|
||||
0.1849462365591398 0.5641233766233766
|
||||
10
lab1/controlpts.txt
Normal file
10
lab1/controlpts.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
BEZIER
|
||||
# Saved from ibezier.py
|
||||
2 7 3
|
||||
0.17795698924731182 0.3303571428571429
|
||||
0.21801075268817205 0.5564123376623378
|
||||
0.35080645161290325 0.6806006493506495
|
||||
0.5252688172043011 0.25892857142857145
|
||||
0.6446236559139785 0.7102272727272728
|
||||
0.8056451612903226 0.6156655844155845
|
||||
0.9021505376344087 0.4042207792207793
|
||||
6
lab1/examples/bezierA0_controlpts.txt
Normal file
6
lab1/examples/bezierA0_controlpts.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
BEZIER
|
||||
# {dimension} {number of points} {degree}
|
||||
2 3 2
|
||||
0.18172043 0.25649351
|
||||
0.39784946 0.69318182
|
||||
0.5827957 0.26623377
|
||||
6
lab1/examples/bezierA1_controlpts.txt
Normal file
6
lab1/examples/bezierA1_controlpts.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
BEZIER
|
||||
# {dimension} {number of points} {degree}
|
||||
2 3 2
|
||||
0.18172043 0.25649351
|
||||
0.39784946 0.69318182
|
||||
0.5827957 0.26623377
|
||||
7
lab1/examples/bezierA2_controlpts.txt
Normal file
7
lab1/examples/bezierA2_controlpts.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
BEZIER
|
||||
# 3 control points. Bezier curve degree is 2.
|
||||
# {dimension} {number of points} {degree}
|
||||
2 3 2
|
||||
0.18172043 0.25649351
|
||||
0.39784946 0.69318182
|
||||
0.5827957 0.26623377
|
||||
8
lab1/examples/bezierA3_controlpts.txt
Normal file
8
lab1/examples/bezierA3_controlpts.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
BEZIER
|
||||
# 3 control points. Bezier curve degree is 2.
|
||||
# Second comment line.
|
||||
# Third comment line.
|
||||
2 3 2
|
||||
0.18172043 0.25649351
|
||||
0.39784946 0.69318182
|
||||
0.5827957 0.26623377
|
||||
7
lab1/examples/bezierB0_controlpts.txt
Normal file
7
lab1/examples/bezierB0_controlpts.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
BEZIER
|
||||
2 5 4
|
||||
0.18387097 0.3262987
|
||||
0.29354839 0.65584416
|
||||
0.45053763 0.30519481
|
||||
0.59032258 0.60064935
|
||||
0.71182796 0.32467532
|
||||
8
lab1/examples/bezierB1_controlpts.txt
Normal file
8
lab1/examples/bezierB1_controlpts.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
BEZIER
|
||||
# {dimension} {number of points} {degree}
|
||||
2 5 4
|
||||
0.18387097 0.3262987
|
||||
0.29354839 0.65584416
|
||||
0.45053763 0.30519481
|
||||
0.59032258 0.60064935
|
||||
0.71182796 0.32467532
|
||||
9
lab1/examples/bezierB2_controlpts.txt
Normal file
9
lab1/examples/bezierB2_controlpts.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
BEZIER
|
||||
# 5 control points. Bezier curve degree is 4.
|
||||
# Second comment line.
|
||||
2 5 4
|
||||
0.18387097 0.3262987
|
||||
0.29354839 0.65584416
|
||||
0.45053763 0.30519481
|
||||
0.59032258 0.60064935
|
||||
0.71182796 0.32467532
|
||||
10
lab1/examples/bezierB3_controlpts.txt
Normal file
10
lab1/examples/bezierB3_controlpts.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
BEZIER
|
||||
# 5 control points. Bezier curve degree is 4.
|
||||
# Second comment line.
|
||||
# {dimension} {number of points} {degree}
|
||||
2 5 4
|
||||
0.18387097 0.3262987
|
||||
0.29354839 0.65584416
|
||||
0.45053763 0.30519481
|
||||
0.59032258 0.60064935
|
||||
0.71182796 0.32467532
|
||||
9
lab1/examples/bezierC_deg2_controlpts.txt
Normal file
9
lab1/examples/bezierC_deg2_controlpts.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
BEZIER
|
||||
# 5 control points.
|
||||
# Two Bezier curves, each of degree 2.
|
||||
2 5 2
|
||||
0.18387097 0.3262987
|
||||
0.29354839 0.65584416
|
||||
0.45053763 0.30519481
|
||||
0.59032258 0.60064935
|
||||
0.71182796 0.32467532
|
||||
9
lab1/examples/bezierC_deg4_controlpts.txt
Normal file
9
lab1/examples/bezierC_deg4_controlpts.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
BEZIER
|
||||
# 5 control points.
|
||||
# One degree 4 Bezier curve.
|
||||
2 5 4
|
||||
0.18387097 0.3262987
|
||||
0.29354839 0.65584416
|
||||
0.45053763 0.30519481
|
||||
0.59032258 0.60064935
|
||||
0.71182796 0.32467532
|
||||
10
lab1/examples/bezierD_deg3_controlpts.txt
Normal file
10
lab1/examples/bezierD_deg3_controlpts.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
BEZIER
|
||||
# Two Bezier curves, each of degree 3.
|
||||
2 7 3
|
||||
0.08709677 0.29058442
|
||||
0.21290323 0.65746753
|
||||
0.39354839 0.67045455
|
||||
0.4483871 0.25811688
|
||||
0.6172043 0.26461039
|
||||
0.75053763 0.66233766
|
||||
0.83870968 0.29707792
|
||||
11
lab1/examples/bezierD_deg6_controlpts.txt
Normal file
11
lab1/examples/bezierD_deg6_controlpts.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
BEZIER
|
||||
# 7 control points.
|
||||
# One degree 6 Bezier curve.
|
||||
2 7 6
|
||||
0.08709677 0.29058442
|
||||
0.21290323 0.65746753
|
||||
0.39354839 0.67045455
|
||||
0.4483871 0.25811688
|
||||
0.6172043 0.26461039
|
||||
0.75053763 0.66233766
|
||||
0.83870968 0.29707792
|
||||
13
lab1/examples/bezierE_deg2_controlpts.txt
Normal file
13
lab1/examples/bezierE_deg2_controlpts.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
BEZIER
|
||||
# 9 control points.
|
||||
# Four Bezier curves, each of degree 2.
|
||||
2 9 2
|
||||
0.11290323 0.25
|
||||
0.16989247 0.53733766
|
||||
0.30430108 0.68019481
|
||||
0.42150538 0.41883117
|
||||
0.54193548 0.23538961
|
||||
0.7 0.2012987
|
||||
0.85806452 0.45616883
|
||||
0.81505376 0.69155844
|
||||
0.57849462 0.74025974
|
||||
13
lab1/examples/bezierE_deg4_controlpts.txt
Normal file
13
lab1/examples/bezierE_deg4_controlpts.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
BEZIER
|
||||
# 9 control points.
|
||||
# Two Bezier curves, each of degree 4.
|
||||
2 9 4
|
||||
0.11290323 0.25
|
||||
0.16989247 0.53733766
|
||||
0.30430108 0.68019481
|
||||
0.42150538 0.41883117
|
||||
0.54193548 0.23538961
|
||||
0.7 0.2012987
|
||||
0.85806452 0.45616883
|
||||
0.81505376 0.69155844
|
||||
0.57849462 0.74025974
|
||||
13
lab1/examples/bezierE_deg8_controlpts.txt
Normal file
13
lab1/examples/bezierE_deg8_controlpts.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
BEZIER
|
||||
# 9 control points.
|
||||
# One degree 8 Bezier curve.
|
||||
2 9 8
|
||||
0.11290323 0.25
|
||||
0.16989247 0.53733766
|
||||
0.30430108 0.68019481
|
||||
0.42150538 0.41883117
|
||||
0.54193548 0.23538961
|
||||
0.7 0.2012987
|
||||
0.85806452 0.45616883
|
||||
0.81505376 0.69155844
|
||||
0.57849462 0.74025974
|
||||
608
lab1/ibezier.py
Normal file
608
lab1/ibezier.py
Normal file
@@ -0,0 +1,608 @@
|
||||
# Interactive plot of Bezier interpolation.
|
||||
# Interactively set polyline vertices or read vertices from a file.
|
||||
# Buttons to subdivide polygonal line.
|
||||
# Button to save vertices (points) to a file.
|
||||
# Created: 1/24/2026 - R. Wenger
|
||||
# Edited: 1/26/2026 - Zhe Yuan
|
||||
|
||||
|
||||
import sys
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.widgets import Button, TextBox
|
||||
|
||||
def ibezier(inputA):
|
||||
# Global variables
|
||||
global vX, vY, plot_center, text_message, fig, ax, save_message # fix: fig should be global
|
||||
global jv, iv_selected, numv
|
||||
global default_output_filename, filename_textbox
|
||||
global cid_bpress, cid_pick
|
||||
global save_message_xloc
|
||||
global num_sample
|
||||
global curve_degree, is_subdivided # add for bezier
|
||||
|
||||
# Compute a point on the Bezier curve at parameter t using de Casteljau's algorithm.
|
||||
# points: list of tuples/lists [(x0,y0), (x1,y1), ...]
|
||||
# Returns: (x, y) coordinates on the curve
|
||||
def deCasteljau(points, t):
|
||||
current_points = np.array(points)
|
||||
n = len(current_points) - 1 # degree
|
||||
|
||||
# Iterate r from 1 to n
|
||||
for r in range(1, n + 1):
|
||||
# Calculate next level of points
|
||||
# P_i^r = (1-t)*P_i^{r-1} + t*P_{i+1}^{r-1}
|
||||
new_points = []
|
||||
for i in range(len(current_points) - 1):
|
||||
x = (1 - t) * current_points[i][0] + t * current_points[i+1][0]
|
||||
y = (1 - t) * current_points[i][1] + t * current_points[i+1][1]
|
||||
new_points.append([x, y])
|
||||
current_points = np.array(new_points)
|
||||
|
||||
return (current_points[0][0], current_points[0][1])
|
||||
|
||||
# Perform subdivision at t=0.5
|
||||
# Input: List of control points for ONE Bezier curve segment.
|
||||
# Output: A tuple (left_points, right_points) where they share the middle point.
|
||||
def subdivide_points_algorithm(segment_x, segment_y):
|
||||
# Combine to (x,y)
|
||||
points = list(zip(segment_x, segment_y))
|
||||
n = len(points) - 1
|
||||
# structure: level 0 has n+1 points, level n has 1 point
|
||||
levels = [points]
|
||||
|
||||
# Run de Casteljau for t=0.5 and store all intermediate points
|
||||
current_points = points
|
||||
for r in range(1, n + 1):
|
||||
next_level = []
|
||||
for i in range(len(current_points) - 1):
|
||||
px = 0.5 * current_points[i][0] + 0.5 * current_points[i+1][0]
|
||||
py = 0.5 * current_points[i][1] + 0.5 * current_points[i+1][1]
|
||||
next_level.append((px, py))
|
||||
levels.append(next_level)
|
||||
current_points = next_level
|
||||
|
||||
# Left curve control points are the first point of each level (P0^0, P0^1, ..., P0^n)
|
||||
left_x = [level[0][0] for level in levels]
|
||||
left_y = [level[0][1] for level in levels]
|
||||
|
||||
# Right curve cpts are the last point of each level, reversed (P0^n, P1^{n-1}, ..., Pn^0)
|
||||
right_x = [level[-1][0] for level in levels]
|
||||
right_y = [level[-1][1] for level in levels]
|
||||
right_x.reverse()
|
||||
right_y.reverse()
|
||||
|
||||
return (left_x, left_y), (right_x, right_y)
|
||||
|
||||
# Draw the Bezier curve
|
||||
def drawBezierCurve(vX, vY):
|
||||
global num_sample, curve_degree
|
||||
# Number of points per segment = degree + 1
|
||||
nump = len(vX)
|
||||
num_segments = (nump - 1) // curve_degree
|
||||
for k in range(num_segments):
|
||||
start_idx = k * curve_degree
|
||||
end_idx = start_idx + curve_degree + 1
|
||||
segX = vX[start_idx:end_idx]
|
||||
segY = vY[start_idx:end_idx]
|
||||
points = list(zip(segX, segY))
|
||||
pX = []
|
||||
pY = []
|
||||
steps = np.linspace(0, 1, num_sample)
|
||||
for t in steps:
|
||||
(cx, cy) = deCasteljau(points, t)
|
||||
pX.append(cx)
|
||||
pY.append(cy)
|
||||
# Draw Bezier curve
|
||||
plt.plot(pX, pY, color="red", linewidth=1.5)
|
||||
# Draw control polygon
|
||||
plt.plot(vX, vY, '--', color='gray', linewidth=0.5)
|
||||
# Draw control points
|
||||
plt.plot(vX, vY, 'ob', picker=True, pickradius=5)
|
||||
return
|
||||
|
||||
# Redraw the entire plot
|
||||
def redrawPlot(vX, vY):
|
||||
global text_message, ax
|
||||
|
||||
plt.subplot(111)
|
||||
|
||||
# Store current axes limits
|
||||
xL, xR = ax.get_xlim()
|
||||
yB, yT = ax.get_ylim()
|
||||
|
||||
# Bug: Clearing the axes resets the navigation toolbar so you can't return
|
||||
# to previous states.
|
||||
# In particular, you can't return to the starting (0,0), (1,1) configuration.
|
||||
plt.cla()
|
||||
text_message=None
|
||||
|
||||
# Restore axes limits
|
||||
plt.xlim([xL,xR])
|
||||
plt.ylim([yB,yT])
|
||||
|
||||
drawBezierCurve(vX, vY)
|
||||
|
||||
outputPlotMessage("Drag and move control points")
|
||||
clearSaveMessage()
|
||||
plt.draw()
|
||||
return
|
||||
|
||||
# Output a message above the plot
|
||||
def outputPlotMessage(s):
|
||||
global text_message, ax
|
||||
|
||||
text_yloc=1.02
|
||||
|
||||
if text_message is None:
|
||||
text_message=plt.text(0.0, text_yloc, s, transform=ax.transAxes)
|
||||
else:
|
||||
text_message.set_text(s)
|
||||
|
||||
return
|
||||
|
||||
# Output the message: Select vertex str(j) location
|
||||
def outputSelectVertexLocation(j):
|
||||
s = "Select vertex " + str(j) + " location"
|
||||
outputPlotMessage(s)
|
||||
return
|
||||
|
||||
# Set a message related to saving control points to file
|
||||
def outputSaveMessage(s):
|
||||
global save_message, save_message_xloc
|
||||
text_yloc=1.02
|
||||
if save_message is not None:
|
||||
save_message.remove()
|
||||
|
||||
save_message=plt.text(save_message_xloc-0.14, text_yloc, s, transform=ax.transAxes)
|
||||
return
|
||||
|
||||
# Set the save message to ''
|
||||
def clearSaveMessage():
|
||||
global save_message
|
||||
|
||||
if save_message is not None:
|
||||
save_message.remove()
|
||||
save_message = None
|
||||
return
|
||||
|
||||
# CallbackS
|
||||
|
||||
# Subdivide curve
|
||||
def subdivideCallback(event):
|
||||
global vX, vY, curve_degree, is_subdivided, smooth_button
|
||||
|
||||
if len(vX) == 0: return
|
||||
|
||||
tempX = []
|
||||
tempY = []
|
||||
|
||||
# We must subdivide EVERY segment in the current curve
|
||||
num_segments = (len(vX) - 1) // curve_degree
|
||||
|
||||
for k in range(num_segments):
|
||||
start_idx = k * curve_degree
|
||||
end_idx = start_idx + curve_degree + 1
|
||||
|
||||
segX = vX[start_idx:end_idx]
|
||||
segY = vY[start_idx:end_idx]
|
||||
|
||||
# Get divided points
|
||||
(lx, ly), (rx, ry) = subdivide_points_algorithm(segX, segY)
|
||||
|
||||
if k == 0:
|
||||
tempX.extend(lx[:-1]) # Add all Left except last (shared)
|
||||
tempX.append(lx[-1]) # Add shared point
|
||||
tempX.extend(rx[1:]) # Add all Right except first (shared)
|
||||
tempY.extend(ly[:-1])
|
||||
tempY.append(ly[-1])
|
||||
tempY.extend(ry[1:])
|
||||
else:
|
||||
# For subsequent segments, the starting point is already in the list
|
||||
# lx[0] should equal tempX[-1]
|
||||
tempX.extend(lx[1:-1]) # Skip first, add middle
|
||||
tempX.append(lx[-1]) # Add shared middle
|
||||
tempX.extend(rx[1:]) # Skip first (shared), add rest
|
||||
|
||||
tempY.extend(ly[1:-1])
|
||||
tempY.append(ly[-1])
|
||||
tempY.extend(ry[1:])
|
||||
|
||||
vX = tempX
|
||||
vY = tempY
|
||||
|
||||
# Set flag to enable Smooth button
|
||||
is_subdivided = True
|
||||
# update bottom to distinguish enabled or not
|
||||
smooth_button.color = 'white'
|
||||
smooth_button.hovercolor = 'green'
|
||||
|
||||
redrawPlot(vX, vY)
|
||||
|
||||
return
|
||||
|
||||
# Smooth button callback
|
||||
def smoothCallback(event):
|
||||
global vX, vY, curve_degree, is_subdivided
|
||||
|
||||
if not is_subdivided:
|
||||
outputPlotMessage("Curve must be subdivided first.")
|
||||
plt.draw()
|
||||
return
|
||||
|
||||
# Iterate through join points.
|
||||
nump = len(vX)
|
||||
|
||||
changes = {} # Map index to new (x,y)
|
||||
|
||||
for i in range(1, nump - 1):
|
||||
if i % curve_degree == 0:
|
||||
# This is a junction point between two segments
|
||||
# q_i = (q_{i-1} + q_{i+1}) / 2
|
||||
nx = (vX[i-1] + vX[i+1]) / 2.0
|
||||
ny = (vY[i-1] + vY[i+1]) / 2.0
|
||||
changes[i] = (nx, ny)
|
||||
|
||||
# Apply changes
|
||||
for i, (nx, ny) in changes.items():
|
||||
vX[i] = nx
|
||||
vY[i] = ny
|
||||
|
||||
redrawPlot(vX, vY)
|
||||
outputPlotMessage("Curve smoothed at junctions.")
|
||||
# Don't disable smooth button again
|
||||
plt.draw()
|
||||
return
|
||||
|
||||
# Save control points to file
|
||||
def saveCallback(event):
|
||||
global vX, vY, filename_textbox, curve_degree
|
||||
|
||||
if len(vX) == 0: return
|
||||
|
||||
filename = filename_textbox.text
|
||||
|
||||
if (filename == '' or filename.isspace()):
|
||||
# Should pop up an error window/message, but the GUI code would become
|
||||
# even more complicated.
|
||||
outputSaveMessage('Illegal filename. Reset filename to default. No file saved.')
|
||||
filename_textbox.set_val(default_output_filename)
|
||||
plt.draw()
|
||||
else:
|
||||
# Prepare data for BEZIER format
|
||||
# Header:
|
||||
# BEZIER
|
||||
# # comments
|
||||
# {ndim} {nump} {ndegree}
|
||||
# coords...
|
||||
|
||||
try:
|
||||
with open(filename, 'w') as f:
|
||||
f.write("BEZIER\n")
|
||||
f.write(f"# Saved from ibezier.py\n")
|
||||
# ndim=2, nump=len(vX), ndegree=curve_degree
|
||||
f.write(f"2 {len(vX)} {curve_degree}\n")
|
||||
for i in range(len(vX)):
|
||||
f.write(f"{vX[i]} {vY[i]}\n")
|
||||
|
||||
outputSaveMessage('Saved to ' + filename)
|
||||
except Exception as e:
|
||||
outputSaveMessage('Error saving file.')
|
||||
print(e)
|
||||
|
||||
plt.draw()
|
||||
return
|
||||
|
||||
# Create TextBox containing output filename and
|
||||
# output message text box
|
||||
def createSaveTextBoxes(default_filename):
|
||||
global filename_textbox, save_message_xloc, fig
|
||||
|
||||
# *** DEBUG ***
|
||||
print("Creating save text box.")
|
||||
|
||||
ax_filename_textbox = fig.add_axes([save_message_xloc, 0.94, 0.3, 0.03])
|
||||
filename_textbox = TextBox(ax_filename_textbox, 'Output filename:', default_filename)
|
||||
plt.draw()
|
||||
|
||||
return
|
||||
|
||||
# Create buttons
|
||||
def createButtons(left_pos, button_width, button_height):
|
||||
global ax_subdivide_button, subdivide_button
|
||||
global ax_smooth_button, smooth_button
|
||||
global ax_save_button, save_button
|
||||
|
||||
# Colors
|
||||
inactive_color = 'lightgray'
|
||||
|
||||
# Subdivide
|
||||
ax_subdivide_button = plt.axes([left_pos, 0.8, button_width, button_height])
|
||||
subdivide_button = Button(ax_subdivide_button, "Subdivide")
|
||||
subdivide_button.on_clicked(subdivideCallback)
|
||||
subdivide_button.color = inactive_color
|
||||
subdivide_button.hovercolor = inactive_color
|
||||
|
||||
# Smooth
|
||||
ax_smooth_button = plt.axes([left_pos, 0.7, button_width, button_height])
|
||||
smooth_button = Button(ax_smooth_button, "Smooth")
|
||||
smooth_button.on_clicked(smoothCallback)
|
||||
smooth_button.color = inactive_color
|
||||
smooth_button.hovercolor = inactive_color
|
||||
|
||||
# Save
|
||||
ax_save_button = plt.axes([left_pos, 0.6, button_width, button_height])
|
||||
save_button = Button(ax_save_button, "Save")
|
||||
save_button.on_clicked(saveCallback)
|
||||
save_button.color = inactive_color
|
||||
save_button.hovercolor = inactive_color
|
||||
|
||||
createSaveTextBoxes(default_output_filename)
|
||||
return
|
||||
|
||||
# not enable all buttons as smooth needs subdivision first
|
||||
def enableButtons():
|
||||
global subdivide_button, smooth_button, save_button
|
||||
|
||||
subdivide_button.color = 'white'
|
||||
subdivide_button.hovercolor = 'green'
|
||||
save_button.color = 'white'
|
||||
save_button.hovercolor = 'green'
|
||||
plt.draw()
|
||||
return
|
||||
|
||||
# Add a vertex at (event.xdata, event.ydata)
|
||||
def addVertexCallback(event):
|
||||
global jv, vX, vY, numv, cid_bpress, fig, curve_degree
|
||||
|
||||
plt.subplot(111)
|
||||
x=event.xdata
|
||||
y=event.ydata
|
||||
|
||||
# Check that x and y are defined
|
||||
if (x is None) or (y is None): return
|
||||
|
||||
# get (again) plot lower left (LL) and upper right (UR)
|
||||
# (Coordinates can change if window is moved from one screen
|
||||
# to another.)
|
||||
axLL = ax.transData.transform((0,0));
|
||||
axUR = ax.transData.transform((1,1));
|
||||
|
||||
|
||||
# check that event.x and event.y are within draw region
|
||||
if ((event.x < axLL[0]) or (event.x > axUR[0])): return
|
||||
if ((event.y < axLL[1]) or (event.y > axUR[1])): return
|
||||
|
||||
if (jv < numv):
|
||||
vX.append(x)
|
||||
vY.append(y)
|
||||
plt.plot(x, y, 'ob')
|
||||
jv =jv+1
|
||||
|
||||
if (jv < numv):
|
||||
outputSelectVertexLocation(jv)
|
||||
plt.draw()
|
||||
else:
|
||||
# Disconnect button press callback before creating pick event
|
||||
fig.canvas.mpl_disconnect(cid_bpress)
|
||||
# Determine degree (n points => degree n-1)
|
||||
curve_degree = numv - 1
|
||||
drawBezierEnableButtonsPickEvent(vX, vY)
|
||||
enableButtons()
|
||||
return
|
||||
|
||||
# Pick and move a vertex
|
||||
def pickPointCallback(event):
|
||||
global iv_selected, cid_moveCallback
|
||||
|
||||
if (len(event.ind) < 1): return
|
||||
|
||||
if (event.ind[0] >= 0) and (event.ind[0] < len(vX)):
|
||||
iv_selected = event.ind[0]
|
||||
cid_moveCallback = \
|
||||
fig.canvas.mpl_connect('button_release_event', moveVertexCallback)
|
||||
|
||||
return
|
||||
|
||||
# Move selected vertex to location (event.xdata, event.ydata)
|
||||
def moveVertexCallback(event):
|
||||
global cid_moveCallback, iv_selected, vX, vY
|
||||
global points, polyline
|
||||
|
||||
plt.subplot(111)
|
||||
x=event.xdata
|
||||
y=event.ydata
|
||||
|
||||
# Check that x and y are defined
|
||||
if (x is None) or (y is None): return
|
||||
|
||||
# get (again) plot lower left (LL) and upper right (UR)
|
||||
# (Coordinates can change if window is moved from one screen
|
||||
# to another.)
|
||||
axLL = ax.transData.transform((0,0));
|
||||
axUR = ax.transData.transform((1,1));
|
||||
|
||||
# check that event.x and event.y are within draw region
|
||||
if ((event.x < axLL[0]) or (event.x > axUR[0])): return
|
||||
if ((event.y < axLL[1]) or (event.y > axUR[1])): return
|
||||
|
||||
vX[iv_selected] = x
|
||||
vY[iv_selected] = y
|
||||
redrawPlot(vX, vY)
|
||||
|
||||
fig.canvas.mpl_disconnect(cid_moveCallback)
|
||||
|
||||
# reset iv_selected
|
||||
iv_selected = -1
|
||||
return
|
||||
|
||||
# After control points are created or read, draw bezier
|
||||
# curve and enable buttons and pick event
|
||||
def drawBezierEnableButtonsPickEvent(vX, vY):
|
||||
global cid_pick, fig
|
||||
|
||||
plt.subplot(111)
|
||||
outputPlotMessage("Select and move vertices")
|
||||
redrawPlot(vX, vY)
|
||||
|
||||
cid_pick = fig.canvas.mpl_connect('pick_event', pickPointCallback)
|
||||
enableButtons()
|
||||
return
|
||||
|
||||
# load vX and vY from a textfile
|
||||
# edit for BEZIER format
|
||||
def loadTextFile(filename):
|
||||
global vX, vY, jv, numv, curve_degree
|
||||
|
||||
try:
|
||||
with open(filename, 'r') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
# Strip whitespace and remove empty lines
|
||||
lines = [l.strip() for l in lines if l.strip()]
|
||||
|
||||
if not lines:
|
||||
raise ValueError("Empty file")
|
||||
|
||||
if lines[0] != "BEZIER":
|
||||
raise ValueError("File must start with BEZIER")
|
||||
|
||||
# Find the line with dimension/nump/degree
|
||||
data_start_idx = 1
|
||||
header_vals = []
|
||||
|
||||
while data_start_idx < len(lines):
|
||||
line = lines[data_start_idx]
|
||||
if line.startswith('#'):
|
||||
data_start_idx += 1
|
||||
continue
|
||||
else:
|
||||
# Found the header line
|
||||
parts = line.split()
|
||||
if len(parts) < 3:
|
||||
raise ValueError("Invalid header line format")
|
||||
header_vals = [int(p) for p in parts]
|
||||
data_start_idx += 1
|
||||
break
|
||||
|
||||
if not header_vals:
|
||||
raise ValueError("Could not find data dimensions")
|
||||
|
||||
ndim = header_vals[0]
|
||||
nump = header_vals[1]
|
||||
ndegree = header_vals[2]
|
||||
|
||||
# Read points
|
||||
tempX = []
|
||||
tempY = []
|
||||
|
||||
for i in range(data_start_idx, len(lines)):
|
||||
line = lines[i]
|
||||
if line.startswith('#'): continue
|
||||
parts = line.split()
|
||||
if len(parts) >= 2:
|
||||
tempX.append(float(parts[0]))
|
||||
tempY.append(float(parts[1]))
|
||||
|
||||
if len(tempX) != nump:
|
||||
print(f"Warning: Expected {nump} points, found {len(tempX)}")
|
||||
|
||||
vX = tempX
|
||||
vY = tempY
|
||||
numv = len(vX)
|
||||
jv = numv
|
||||
curve_degree = ndegree
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error loading file: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Initialize global variables
|
||||
text_message = None
|
||||
save_message = None
|
||||
filename_textbox = None
|
||||
save_message_xloc = 0.5
|
||||
iv_selected = -1
|
||||
jv = 0
|
||||
plot_center = [ 0.5, 0.5 ]
|
||||
default_output_filename = 'controlpts.txt'
|
||||
num_sample = 100
|
||||
is_subdivided = False
|
||||
|
||||
|
||||
# If inputA is an integer, set number of vertices to inputA
|
||||
# If inputA is a string, read control points from inputA
|
||||
if isinstance(inputA, int):
|
||||
numv = inputA
|
||||
jv = 0
|
||||
vX = []
|
||||
vY = []
|
||||
elif isinstance(inputA, str):
|
||||
try:
|
||||
loadTextFile(inputA)
|
||||
except Exception as e:
|
||||
print(f"Error loading file: {e}")
|
||||
print('Unable to open filename: ', inputA)
|
||||
print('Check that file exists and that you have read permission.')
|
||||
print('Exiting.')
|
||||
return
|
||||
else:
|
||||
print('Illegal input: ', inputA)
|
||||
print('Exiting.')
|
||||
return
|
||||
|
||||
if (numv < 2):
|
||||
print('Illegal number of vertices: ', numv)
|
||||
print('Requires at least two vertices.')
|
||||
print('Exiting')
|
||||
return
|
||||
|
||||
fig, ax = plt.subplots(1, 1, figsize=(12, 8))
|
||||
plt.xlim([0.0, 1.0])
|
||||
plt.ylim([0.0, 1.0])
|
||||
plt.subplots_adjust(right=0.9)
|
||||
|
||||
outputSelectVertexLocation(0)
|
||||
|
||||
# get plot lower left (LL) and upper right (UR)
|
||||
axLL = ax.transData.transform((0,0));
|
||||
axUR = ax.transData.transform((1,1));
|
||||
|
||||
createButtons(0.91, 0.08, 0.05)
|
||||
|
||||
if (jv < numv):
|
||||
# User interactively selects vertices
|
||||
cid_bpress = fig.canvas.mpl_connect('button_press_event', addVertexCallback)
|
||||
else:
|
||||
# Vertices already read in from input file
|
||||
drawBezierEnableButtonsPickEvent(vX, vY)
|
||||
# Enable smooth for already loaded curve if cpts - 1 is multiple of degree
|
||||
# and cpts - 1 != degree
|
||||
if (len(vX) - 1) % curve_degree == 0 and curve_degree != len(vX) - 1:
|
||||
# Set flag to enable Smooth button
|
||||
is_subdivided = True
|
||||
# update bottom to distinguish enabled or not
|
||||
smooth_button.color = 'white'
|
||||
smooth_button.hovercolor = 'green'
|
||||
|
||||
plt.show()
|
||||
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python ibezier.py <num_points> OR <filename>")
|
||||
sys.exit()
|
||||
|
||||
arg = sys.argv[1]
|
||||
try:
|
||||
val = int(arg)
|
||||
ibezier(val)
|
||||
except ValueError:
|
||||
ibezier(arg)
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
sys.exit()
|
||||
10
lab1/pyproject.toml
Normal file
10
lab1/pyproject.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[project]
|
||||
name = "lab1"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.14"
|
||||
dependencies = [
|
||||
"matplotlib>=3.10.8",
|
||||
"numpy>=2.4.1",
|
||||
]
|
||||
253
lab1/uv.lock
generated
Normal file
253
lab1/uv.lock
generated
Normal file
@@ -0,0 +1,253 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.14"
|
||||
|
||||
[[package]]
|
||||
name = "contourpy"
|
||||
version = "1.3.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cycler"
|
||||
version = "0.12.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fonttools"
|
||||
version = "4.61.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ec/ca/cf17b88a8df95691275a3d77dc0a5ad9907f328ae53acbe6795da1b2f5ed/fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69", size = 3565756, upload-time = "2025-12-12T17:31:24.246Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/32/8f/4e7bf82c0cbb738d3c2206c920ca34ca74ef9dabde779030145d28665104/fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd", size = 2846094, upload-time = "2025-12-12T17:30:43.511Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/09/d44e45d0a4f3a651f23a1e9d42de43bc643cce2971b19e784cc67d823676/fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e", size = 2396589, upload-time = "2025-12-12T17:30:45.681Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/18/58c64cafcf8eb677a99ef593121f719e6dcbdb7d1c594ae5a10d4997ca8a/fonttools-4.61.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa646ecec9528bef693415c79a86e733c70a4965dd938e9a226b0fc64c9d2e6c", size = 4877892, upload-time = "2025-12-12T17:30:47.709Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/ec/9e6b38c7ba1e09eb51db849d5450f4c05b7e78481f662c3b79dbde6f3d04/fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75", size = 4972884, upload-time = "2025-12-12T17:30:49.656Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/87/b5339da8e0256734ba0dbbf5b6cdebb1dd79b01dc8c270989b7bcd465541/fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063", size = 4924405, upload-time = "2025-12-12T17:30:51.735Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/47/e3409f1e1e69c073a3a6fd8cb886eb18c0bae0ee13db2c8d5e7f8495e8b7/fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2", size = 5035553, upload-time = "2025-12-12T17:30:54.823Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/b6/1f6600161b1073a984294c6c031e1a56ebf95b6164249eecf30012bb2e38/fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c", size = 2271915, upload-time = "2025-12-12T17:30:57.913Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/7b/91e7b01e37cc8eb0e1f770d08305b3655e4f002fc160fb82b3390eabacf5/fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c", size = 2323487, upload-time = "2025-12-12T17:30:59.804Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/5c/908ad78e46c61c3e3ed70c3b58ff82ab48437faf84ec84f109592cabbd9f/fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa", size = 2929571, upload-time = "2025-12-12T17:31:02.574Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/41/975804132c6dea64cdbfbaa59f3518a21c137a10cccf962805b301ac6ab2/fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91", size = 2435317, upload-time = "2025-12-12T17:31:04.974Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/5a/aef2a0a8daf1ebaae4cfd83f84186d4a72ee08fd6a8451289fcd03ffa8a4/fonttools-4.61.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75c301f96db737e1c5ed5fd7d77d9c34466de16095a266509e13da09751bd19", size = 4882124, upload-time = "2025-12-12T17:31:07.456Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/33/d6db3485b645b81cea538c9d1c9219d5805f0877fda18777add4671c5240/fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba", size = 5100391, upload-time = "2025-12-12T17:31:09.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/d6/675ba631454043c75fcf76f0ca5463eac8eb0666ea1d7badae5fea001155/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7", size = 4978800, upload-time = "2025-12-12T17:31:11.681Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/33/d3ec753d547a8d2bdaedd390d4a814e8d5b45a093d558f025c6b990b554c/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118", size = 5006426, upload-time = "2025-12-12T17:31:13.764Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/40/cc11f378b561a67bea850ab50063366a0d1dd3f6d0a30ce0f874b0ad5664/fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5", size = 2335377, upload-time = "2025-12-12T17:31:16.49Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/ff/c9a2b66b39f8628531ea58b320d66d951267c98c6a38684daa8f50fb02f8/fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b", size = 2400613, upload-time = "2025-12-12T17:31:18.769Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/4e/ce75a57ff3aebf6fc1f4e9d508b8e5810618a33d900ad6c19eb30b290b97/fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371", size = 1148996, upload-time = "2025-12-12T17:31:21.03Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kiwisolver"
|
||||
version = "1.4.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5c/3c/85844f1b0feb11ee581ac23fe5fce65cd049a200c1446708cc1b7f922875/kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d", size = 97564, upload-time = "2025-08-10T21:27:49.279Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/32/6cc0fbc9c54d06c2969faa9c1d29f5751a2e51809dd55c69055e62d9b426/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386", size = 123806, upload-time = "2025-08-10T21:27:01.537Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/dd/2bfb1d4a4823d92e8cbb420fe024b8d2167f72079b3bb941207c42570bdf/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552", size = 66605, upload-time = "2025-08-10T21:27:03.335Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/69/00aafdb4e4509c2ca6064646cba9cd4b37933898f426756adb2cb92ebbed/kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3", size = 64925, upload-time = "2025-08-10T21:27:04.339Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/dc/51acc6791aa14e5cb6d8a2e28cefb0dc2886d8862795449d021334c0df20/kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58", size = 1472414, upload-time = "2025-08-10T21:27:05.437Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/bb/93fa64a81db304ac8a246f834d5094fae4b13baf53c839d6bb6e81177129/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4", size = 1281272, upload-time = "2025-08-10T21:27:07.063Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/e6/6df102916960fb8d05069d4bd92d6d9a8202d5a3e2444494e7cd50f65b7a/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df", size = 1298578, upload-time = "2025-08-10T21:27:08.452Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/47/e142aaa612f5343736b087864dbaebc53ea8831453fb47e7521fa8658f30/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6", size = 1345607, upload-time = "2025-08-10T21:27:10.125Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/89/d641a746194a0f4d1a3670fb900d0dbaa786fb98341056814bc3f058fa52/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5", size = 2230150, upload-time = "2025-08-10T21:27:11.484Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/6b/5ee1207198febdf16ac11f78c5ae40861b809cbe0e6d2a8d5b0b3044b199/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf", size = 2325979, upload-time = "2025-08-10T21:27:12.917Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/ff/b269eefd90f4ae14dcc74973d5a0f6d28d3b9bb1afd8c0340513afe6b39a/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5", size = 2491456, upload-time = "2025-08-10T21:27:14.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/d4/10303190bd4d30de547534601e259a4fbf014eed94aae3e5521129215086/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce", size = 2294621, upload-time = "2025-08-10T21:27:15.808Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/e0/a9a90416fce5c0be25742729c2ea52105d62eda6c4be4d803c2a7be1fa50/kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7", size = 75417, upload-time = "2025-08-10T21:27:17.436Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/10/6949958215b7a9a264299a7db195564e87900f709db9245e4ebdd3c70779/kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c", size = 66582, upload-time = "2025-08-10T21:27:18.436Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/79/60e53067903d3bc5469b369fe0dfc6b3482e2133e85dae9daa9527535991/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548", size = 126514, upload-time = "2025-08-10T21:27:19.465Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/d1/4843d3e8d46b072c12a38c97c57fab4608d36e13fe47d47ee96b4d61ba6f/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d", size = 67905, upload-time = "2025-08-10T21:27:20.51Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/ae/29ffcbd239aea8b93108de1278271ae764dfc0d803a5693914975f200596/kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c", size = 66399, upload-time = "2025-08-10T21:27:21.496Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/ae/d7ba902aa604152c2ceba5d352d7b62106bedbccc8e95c3934d94472bfa3/kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122", size = 1582197, upload-time = "2025-08-10T21:27:22.604Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/41/27c70d427eddb8bc7e4f16420a20fefc6f480312122a59a959fdfe0445ad/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64", size = 1390125, upload-time = "2025-08-10T21:27:24.036Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/42/b3799a12bafc76d962ad69083f8b43b12bf4fe78b097b12e105d75c9b8f1/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134", size = 1402612, upload-time = "2025-08-10T21:27:25.773Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/b5/a210ea073ea1cfaca1bb5c55a62307d8252f531beb364e18aa1e0888b5a0/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370", size = 1453990, upload-time = "2025-08-10T21:27:27.089Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/ce/a829eb8c033e977d7ea03ed32fb3c1781b4fa0433fbadfff29e39c676f32/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21", size = 2331601, upload-time = "2025-08-10T21:27:29.343Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/4b/b5e97eb142eb9cd0072dacfcdcd31b1c66dc7352b0f7c7255d339c0edf00/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a", size = 2422041, upload-time = "2025-08-10T21:27:30.754Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/be/8eb4cd53e1b85ba4edc3a9321666f12b83113a178845593307a3e7891f44/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f", size = 2594897, upload-time = "2025-08-10T21:27:32.803Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369", size = 2391835, upload-time = "2025-08-10T21:27:34.23Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891", size = 79988, upload-time = "2025-08-10T21:27:35.587Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lab1"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "matplotlib" },
|
||||
{ name = "numpy" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "matplotlib", specifier = ">=3.10.8" },
|
||||
{ name = "numpy", specifier = ">=2.4.1" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matplotlib"
|
||||
version = "3.10.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "contourpy" },
|
||||
{ name = "cycler" },
|
||||
{ name = "fonttools" },
|
||||
{ name = "kiwisolver" },
|
||||
{ name = "numpy" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pillow" },
|
||||
{ name = "pyparsing" },
|
||||
{ name = "python-dateutil" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8a/76/d3c6e3a13fe484ebe7718d14e269c9569c4eb0020a968a327acb3b9a8fe6/matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3", size = 34806269, upload-time = "2025-12-10T22:56:51.155Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/43/9c0ff7a2f11615e516c3b058e1e6e8f9614ddeca53faca06da267c48345d/matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f", size = 8262481, upload-time = "2025-12-10T22:56:10.885Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/ca/e8ae28649fcdf039fda5ef554b40a95f50592a3c47e6f7270c9561c12b07/matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b", size = 8151473, upload-time = "2025-12-10T22:56:12.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/6f/009d129ae70b75e88cbe7e503a12a4c0670e08ed748a902c2568909e9eb5/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d", size = 9553896, upload-time = "2025-12-10T22:56:14.432Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/26/4221a741eb97967bc1fd5e4c52b9aa5a91b2f4ec05b59f6def4d820f9df9/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008", size = 9824193, upload-time = "2025-12-10T22:56:16.29Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/f3/3abf75f38605772cf48a9daf5821cd4f563472f38b4b828c6fba6fa6d06e/matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c", size = 9615444, upload-time = "2025-12-10T22:56:18.155Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/a5/de89ac80f10b8dc615807ee1133cd99ac74082581196d4d9590bea10690d/matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11", size = 8272719, upload-time = "2025-12-10T22:56:20.366Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/ce/b006495c19ccc0a137b48083168a37bd056392dee02f87dba0472f2797fe/matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8", size = 8144205, upload-time = "2025-12-10T22:56:22.239Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/d9/b31116a3a855bd313c6fcdb7226926d59b041f26061c6c5b1be66a08c826/matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50", size = 8305785, upload-time = "2025-12-10T22:56:24.218Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/90/6effe8103f0272685767ba5f094f453784057072f49b393e3ea178fe70a5/matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908", size = 8198361, upload-time = "2025-12-10T22:56:26.787Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/65/a73188711bea603615fc0baecca1061429ac16940e2385433cc778a9d8e7/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a", size = 9561357, upload-time = "2025-12-10T22:56:28.953Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/3d/b5c5d5d5be8ce63292567f0e2c43dde9953d3ed86ac2de0a72e93c8f07a1/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1", size = 9823610, upload-time = "2025-12-10T22:56:31.455Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/4b/e7beb6bbd49f6bae727a12b270a2654d13c397576d25bd6786e47033300f/matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c", size = 9614011, upload-time = "2025-12-10T22:56:33.85Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/e6/76f2813d31f032e65f6f797e3f2f6e4aab95b65015924b1c51370395c28a/matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b", size = 8362801, upload-time = "2025-12-10T22:56:36.107Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f", size = 8192560, upload-time = "2025-12-10T22:56:38.008Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/24/62/ae72ff66c0f1fd959925b4c11f8c2dea61f47f6acaea75a08512cdfe3fed/numpy-2.4.1.tar.gz", hash = "sha256:a1ceafc5042451a858231588a104093474c6a5c57dcc724841f5c888d237d690", size = 20721320, upload-time = "2026-01-10T06:44:59.619Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/a7/ef08d25698e0e4b4efbad8d55251d20fe2a15f6d9aa7c9b30cd03c165e6f/numpy-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3869ea1ee1a1edc16c29bbe3a2f2a4e515cc3a44d43903ad41e0cacdbaf733dc", size = 16652046, upload-time = "2026-01-10T06:43:54.797Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/39/e378b3e3ca13477e5ac70293ec027c438d1927f18637e396fe90b1addd72/numpy-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e867df947d427cdd7a60e3e271729090b0f0df80f5f10ab7dd436f40811699c3", size = 12378858, upload-time = "2026-01-10T06:43:57.099Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/74/7ec6154f0006910ed1fdbb7591cf4432307033102b8a22041599935f8969/numpy-2.4.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:e3bd2cb07841166420d2fa7146c96ce00cb3410664cbc1a6be028e456c4ee220", size = 5207417, upload-time = "2026-01-10T06:43:59.037Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/b7/053ac11820d84e42f8feea5cb81cc4fcd1091499b45b1ed8c7415b1bf831/numpy-2.4.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:f0a90aba7d521e6954670550e561a4cb925713bd944445dbe9e729b71f6cabee", size = 6542643, upload-time = "2026-01-10T06:44:01.852Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/c4/2e7908915c0e32ca636b92e4e4a3bdec4cb1e7eb0f8aedf1ed3c68a0d8cd/numpy-2.4.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d558123217a83b2d1ba316b986e9248a1ed1971ad495963d555ccd75dcb1556", size = 14418963, upload-time = "2026-01-10T06:44:04.047Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/c0/3ed5083d94e7ffd7c404e54619c088e11f2e1939a9544f5397f4adb1b8ba/numpy-2.4.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2f44de05659b67d20499cbc96d49f2650769afcb398b79b324bb6e297bfe3844", size = 16363811, upload-time = "2026-01-10T06:44:06.207Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/68/42b66f1852bf525050a67315a4fb94586ab7e9eaa541b1bef530fab0c5dd/numpy-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:69e7419c9012c4aaf695109564e3387f1259f001b4326dfa55907b098af082d3", size = 16197643, upload-time = "2026-01-10T06:44:08.33Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/40/e8714fc933d85f82c6bfc7b998a0649ad9769a32f3494ba86598aaf18a48/numpy-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2ffd257026eb1b34352e749d7cc1678b5eeec3e329ad8c9965a797e08ccba205", size = 18289601, upload-time = "2026-01-10T06:44:10.841Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/9a/0d44b468cad50315127e884802351723daca7cf1c98d102929468c81d439/numpy-2.4.1-cp314-cp314-win32.whl", hash = "sha256:727c6c3275ddefa0dc078524a85e064c057b4f4e71ca5ca29a19163c607be745", size = 6005722, upload-time = "2026-01-10T06:44:13.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/bb/c6513edcce5a831810e2dddc0d3452ce84d208af92405a0c2e58fd8e7881/numpy-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:7d5d7999df434a038d75a748275cd6c0094b0ecdb0837342b332a82defc4dc4d", size = 12438590, upload-time = "2026-01-10T06:44:15.006Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/da/a598d5cb260780cf4d255102deba35c1d072dc028c4547832f45dd3323a8/numpy-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:ce9ce141a505053b3c7bce3216071f3bf5c182b8b28930f14cd24d43932cd2df", size = 10596180, upload-time = "2026-01-10T06:44:17.386Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/bc/ea3f2c96fcb382311827231f911723aeff596364eb6e1b6d1d91128aa29b/numpy-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4e53170557d37ae404bf8d542ca5b7c629d6efa1117dac6a83e394142ea0a43f", size = 12498774, upload-time = "2026-01-10T06:44:19.467Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/ab/ef9d939fe4a812648c7a712610b2ca6140b0853c5efea361301006c02ae5/numpy-2.4.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:a73044b752f5d34d4232f25f18160a1cc418ea4507f5f11e299d8ac36875f8a0", size = 5327274, upload-time = "2026-01-10T06:44:23.189Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/31/d381368e2a95c3b08b8cf7faac6004849e960f4a042d920337f71cef0cae/numpy-2.4.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:fb1461c99de4d040666ca0444057b06541e5642f800b71c56e6ea92d6a853a0c", size = 6648306, upload-time = "2026-01-10T06:44:25.012Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/e5/0989b44ade47430be6323d05c23207636d67d7362a1796ccbccac6773dd2/numpy-2.4.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:423797bdab2eeefbe608d7c1ec7b2b4fd3c58d51460f1ee26c7500a1d9c9ee93", size = 14464653, upload-time = "2026-01-10T06:44:26.706Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/a7/cfbe475c35371cae1358e61f20c5f075badc18c4797ab4354140e1d283cf/numpy-2.4.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:52b5f61bdb323b566b528899cc7db2ba5d1015bda7ea811a8bcf3c89c331fa42", size = 16405144, upload-time = "2026-01-10T06:44:29.378Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/a3/0c63fe66b534888fa5177cc7cef061541064dbe2b4b60dcc60ffaf0d2157/numpy-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42d7dd5fa36d16d52a84f821eb96031836fd405ee6955dd732f2023724d0aa01", size = 16247425, upload-time = "2026-01-10T06:44:31.721Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/2b/55d980cfa2c93bd40ff4c290bf824d792bd41d2fe3487b07707559071760/numpy-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7b6b5e28bbd47b7532698e5db2fe1db693d84b58c254e4389d99a27bb9b8f6b", size = 18330053, upload-time = "2026-01-10T06:44:34.617Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/12/8b5fc6b9c487a09a7957188e0943c9ff08432c65e34567cabc1623b03a51/numpy-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:5de60946f14ebe15e713a6f22850c2372fa72f4ff9a432ab44aa90edcadaa65a", size = 6152482, upload-time = "2026-01-10T06:44:36.798Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/a5/9f8ca5856b8940492fc24fbe13c1bc34d65ddf4079097cf9e53164d094e1/numpy-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:8f085da926c0d491ffff3096f91078cc97ea67e7e6b65e490bc8dcda65663be2", size = 12627117, upload-time = "2026-01-10T06:44:38.828Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/0d/eca3d962f9eef265f01a8e0d20085c6dd1f443cbffc11b6dede81fd82356/numpy-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:6436cffb4f2bf26c974344439439c95e152c9a527013f26b3577be6c2ca64295", size = 10667121, upload-time = "2026-01-10T06:44:41.644Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "26.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pillow"
|
||||
version = "12.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d0/02/d52c733a2452ef1ffcc123b68e6606d07276b0e358db70eabad7e40042b7/pillow-12.1.0.tar.gz", hash = "sha256:5c5ae0a06e9ea030ab786b0251b32c7e4ce10e58d983c0d5c56029455180b5b9", size = 46977283, upload-time = "2026-01-02T09:13:29.892Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/87/bdf971d8bbcf80a348cc3bacfcb239f5882100fe80534b0ce67a784181d8/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:5cb7bc1966d031aec37ddb9dcf15c2da5b2e9f7cc3ca7c54473a20a927e1eb91", size = 4062533, upload-time = "2026-01-02T09:12:20.791Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/4f/5eb37a681c68d605eb7034c004875c81f86ec9ef51f5be4a63eadd58859a/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:97e9993d5ed946aba26baf9c1e8cf18adbab584b99f452ee72f7ee8acb882796", size = 4138546, upload-time = "2026-01-02T09:12:23.664Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/6d/19a95acb2edbace40dcd582d077b991646b7083c41b98da4ed7555b59733/pillow-12.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:414b9a78e14ffeb98128863314e62c3f24b8a86081066625700b7985b3f529bd", size = 3601163, upload-time = "2026-01-02T09:12:26.338Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/36/2b8138e51cb42e4cc39c3297713455548be855a50558c3ac2beebdc251dd/pillow-12.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e6bdb408f7c9dd2a5ff2b14a3b0bb6d4deb29fb9961e6eb3ae2031ae9a5cec13", size = 5266086, upload-time = "2026-01-02T09:12:28.782Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/4b/649056e4d22e1caa90816bf99cef0884aed607ed38075bd75f091a607a38/pillow-12.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3413c2ae377550f5487991d444428f1a8ae92784aac79caa8b1e3b89b175f77e", size = 4657344, upload-time = "2026-01-02T09:12:31.117Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/6b/c5742cea0f1ade0cd61485dc3d81f05261fc2276f537fbdc00802de56779/pillow-12.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e5dcbe95016e88437ecf33544ba5db21ef1b8dd6e1b434a2cb2a3d605299e643", size = 6232114, upload-time = "2026-01-02T09:12:32.936Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/8f/9f521268ce22d63991601aafd3d48d5ff7280a246a1ef62d626d67b44064/pillow-12.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d0a7735df32ccbcc98b98a1ac785cc4b19b580be1bdf0aeb5c03223220ea09d5", size = 8042708, upload-time = "2026-01-02T09:12:34.78Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/eb/257f38542893f021502a1bbe0c2e883c90b5cff26cc33b1584a841a06d30/pillow-12.1.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c27407a2d1b96774cbc4a7594129cc027339fd800cd081e44497722ea1179de", size = 6347762, upload-time = "2026-01-02T09:12:36.748Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/5a/8ba375025701c09b309e8d5163c5a4ce0102fa86bbf8800eb0d7ac87bc51/pillow-12.1.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15c794d74303828eaa957ff8070846d0efe8c630901a1c753fdc63850e19ecd9", size = 7039265, upload-time = "2026-01-02T09:12:39.082Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/dc/cf5e4cdb3db533f539e88a7bbf9f190c64ab8a08a9bc7a4ccf55067872e4/pillow-12.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c990547452ee2800d8506c4150280757f88532f3de2a58e3022e9b179107862a", size = 6462341, upload-time = "2026-01-02T09:12:40.946Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/47/0291a25ac9550677e22eda48510cfc4fa4b2ef0396448b7fbdc0a6946309/pillow-12.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b63e13dd27da389ed9475b3d28510f0f954bca0041e8e551b2a4eb1eab56a39a", size = 7165395, upload-time = "2026-01-02T09:12:42.706Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/4c/e005a59393ec4d9416be06e6b45820403bb946a778e39ecec62f5b2b991e/pillow-12.1.0-cp314-cp314-win32.whl", hash = "sha256:1a949604f73eb07a8adab38c4fe50791f9919344398bdc8ac6b307f755fc7030", size = 6431413, upload-time = "2026-01-02T09:12:44.944Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/af/f23697f587ac5f9095d67e31b81c95c0249cd461a9798a061ed6709b09b5/pillow-12.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:4f9f6a650743f0ddee5593ac9e954ba1bdbc5e150bc066586d4f26127853ab94", size = 7176779, upload-time = "2026-01-02T09:12:46.727Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/36/6a51abf8599232f3e9afbd16d52829376a68909fe14efe29084445db4b73/pillow-12.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:808b99604f7873c800c4840f55ff389936ef1948e4e87645eaf3fccbc8477ac4", size = 2543105, upload-time = "2026-01-02T09:12:49.243Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/54/2e1dd20c8749ff225080d6ba465a0cab4387f5db0d1c5fb1439e2d99923f/pillow-12.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc11908616c8a283cf7d664f77411a5ed2a02009b0097ff8abbba5e79128ccf2", size = 5268571, upload-time = "2026-01-02T09:12:51.11Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/61/571163a5ef86ec0cf30d265ac2a70ae6fc9e28413d1dc94fa37fae6bda89/pillow-12.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:896866d2d436563fa2a43a9d72f417874f16b5545955c54a64941e87c1376c61", size = 4660426, upload-time = "2026-01-02T09:12:52.865Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/e1/53ee5163f794aef1bf84243f755ee6897a92c708505350dd1923f4afec48/pillow-12.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8e178e3e99d3c0ea8fc64b88447f7cac8ccf058af422a6cedc690d0eadd98c51", size = 6269908, upload-time = "2026-01-02T09:12:54.884Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/0b/b4b4106ff0ee1afa1dc599fde6ab230417f800279745124f6c50bcffed8e/pillow-12.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:079af2fb0c599c2ec144ba2c02766d1b55498e373b3ac64687e43849fbbef5bc", size = 8074733, upload-time = "2026-01-02T09:12:56.802Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/9f/80b411cbac4a732439e629a26ad3ef11907a8c7fc5377b7602f04f6fe4e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdec5e43377761c5dbca620efb69a77f6855c5a379e32ac5b158f54c84212b14", size = 6381431, upload-time = "2026-01-02T09:12:58.823Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/b7/d65c45db463b66ecb6abc17c6ba6917a911202a07662247e1355ce1789e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:565c986f4b45c020f5421a4cea13ef294dde9509a8577f29b2fc5edc7587fff8", size = 7068529, upload-time = "2026-01-02T09:13:00.885Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/96/dfd4cd726b4a45ae6e3c669fc9e49deb2241312605d33aba50499e9d9bd1/pillow-12.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43aca0a55ce1eefc0aefa6253661cb54571857b1a7b2964bd8a1e3ef4b729924", size = 6492981, upload-time = "2026-01-02T09:13:03.314Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/1c/b5dc52cf713ae46033359c5ca920444f18a6359ce1020dd3e9c553ea5bc6/pillow-12.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0deedf2ea233722476b3a81e8cdfbad786f7adbed5d848469fa59fe52396e4ef", size = 7191878, upload-time = "2026-01-02T09:13:05.276Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/26/c4188248bd5edaf543864fe4834aebe9c9cb4968b6f573ce014cc42d0720/pillow-12.1.0-cp314-cp314t-win32.whl", hash = "sha256:b17fbdbe01c196e7e159aacb889e091f28e61020a8abeac07b68079b6e626988", size = 6438703, upload-time = "2026-01-02T09:13:07.491Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/0e/69ed296de8ea05cb03ee139cee600f424ca166e632567b2d66727f08c7ed/pillow-12.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27b9baecb428899db6c0de572d6d305cfaf38ca1596b5c0542a5182e3e74e8c6", size = 7182927, upload-time = "2026-01-02T09:13:09.841Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/f5/68334c015eed9b5cff77814258717dec591ded209ab5b6fb70e2ae873d1d/pillow-12.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f61333d817698bdcdd0f9d7793e365ac3d2a21c1f1eb02b32ad6aefb8d8ea831", size = 2545104, upload-time = "2026-01-02T09:13:12.068Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.3.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
version = "2.9.0.post0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "six" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.17.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
|
||||
]
|
||||
Reference in New Issue
Block a user