e2D 1.3.3__tar.gz → 1.3.4__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.
- {e2D-1.3.3 → e2D-1.3.4}/PKG-INFO +1 -1
- e2D-1.3.4/e2D/plots.py +272 -0
- {e2D-1.3.3 → e2D-1.3.4}/e2D.egg-info/PKG-INFO +1 -1
- {e2D-1.3.3 → e2D-1.3.4}/setup.cfg +1 -1
- e2D-1.3.3/e2D/plots.py +0 -159
- {e2D-1.3.3 → e2D-1.3.4}/LICENSE +0 -0
- {e2D-1.3.3 → e2D-1.3.4}/README.md +0 -0
- {e2D-1.3.3 → e2D-1.3.4}/e2D/__init__.py +0 -0
- {e2D-1.3.3 → e2D-1.3.4}/e2D/envs.py +0 -0
- {e2D-1.3.3 → e2D-1.3.4}/e2D/utils.py +0 -0
- {e2D-1.3.3 → e2D-1.3.4}/e2D.egg-info/SOURCES.txt +0 -0
- {e2D-1.3.3 → e2D-1.3.4}/e2D.egg-info/dependency_links.txt +0 -0
- {e2D-1.3.3 → e2D-1.3.4}/e2D.egg-info/requires.txt +0 -0
- {e2D-1.3.3 → e2D-1.3.4}/e2D.egg-info/top_level.txt +0 -0
- {e2D-1.3.3 → e2D-1.3.4}/pyproject.toml +0 -0
{e2D-1.3.3 → e2D-1.3.4}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: e2D
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.4
|
|
4
4
|
Summary: Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
|
|
5
5
|
Home-page: https://github.com/marick-py/e2D
|
|
6
6
|
Author: Riccardo Mariani
|
e2D-1.3.4/e2D/plots.py
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from .envs import *
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
def no_error_complex_function(function, args) -> V2|Vector2D:
|
|
6
|
+
res :complex= function(args)
|
|
7
|
+
return V2(res.real, res.imag)
|
|
8
|
+
|
|
9
|
+
sign = lambda value: -1 if value < 0 else (1 if value > 0 else 0)
|
|
10
|
+
|
|
11
|
+
class Function:
|
|
12
|
+
def __init__(self, function, color) -> None:
|
|
13
|
+
self.plot : Plot
|
|
14
|
+
self.color = color
|
|
15
|
+
self.function = function
|
|
16
|
+
|
|
17
|
+
def update_points(self) -> None:
|
|
18
|
+
self.update_function(self.function)
|
|
19
|
+
|
|
20
|
+
def get_points(self) -> list:
|
|
21
|
+
signs_self = np.sign(self.function(*self.plot.meshgrid))
|
|
22
|
+
signs_sum = signs_self + np.roll(signs_self, axis=1, shift=1) + np.roll(signs_self, axis=0, shift=-1) + np.roll(signs_self, axis=(1,0), shift=(1,-1))
|
|
23
|
+
return np.column_stack(np.where(((-4 < signs_sum) & (signs_sum < 4))[:-1, 1:])[::-1]) / self.plot.scale()
|
|
24
|
+
|
|
25
|
+
def update_function(self, new_function) -> None:
|
|
26
|
+
self.function = new_function
|
|
27
|
+
self.points = self.get_points()
|
|
28
|
+
self.render()
|
|
29
|
+
|
|
30
|
+
def render(self) -> None:
|
|
31
|
+
self.__layer_surface__.fill((0,0,0,0))
|
|
32
|
+
offset = self.plot.dragging - self.plot.start_dragging if (self.plot.dragging != None) and (not self.plot.settings.get("use_real_time_rendering")) else None
|
|
33
|
+
if any(x < 1 for x in self.plot.scale):
|
|
34
|
+
for point in self.points:
|
|
35
|
+
# radius = max(min(self.plot.pixel_size)*.5, 1)
|
|
36
|
+
# pg.draw.circle(self.plot.canvas, self.color, (point + self.plot.pixel_size*.5)(), radius)
|
|
37
|
+
pg.draw.rect(self.__layer_surface__, self.color, (point.tolist() + (offset if offset != None else V2z))() + self.plot.pixel_size()) #type: ignore
|
|
38
|
+
else:
|
|
39
|
+
for point in self.points:
|
|
40
|
+
point = point.astype(int).tolist()
|
|
41
|
+
if self.plot.dragging != None:
|
|
42
|
+
point = round(point + offset)()
|
|
43
|
+
self.__layer_surface__.set_at(point, self.color)
|
|
44
|
+
|
|
45
|
+
def draw(self) -> None:
|
|
46
|
+
self.plot.canvas.blit(self.__layer_surface__, (0,0))
|
|
47
|
+
|
|
48
|
+
# class ComplexFunction:
|
|
49
|
+
# def __init__(self, function, plot:"Plot", starting_t:float=-10, ending_t:float=10, step=.01, color=(255,255,255), auto_connect_treshold=float("inf"), points_radius=2, points_color=None) -> None:
|
|
50
|
+
# self.auto_connect_treshold = auto_connect_treshold
|
|
51
|
+
# self.plot = plot
|
|
52
|
+
# self.starting_t = starting_t
|
|
53
|
+
# self.ending_t = ending_t
|
|
54
|
+
# self.color = color
|
|
55
|
+
# self.step = step
|
|
56
|
+
# self.points_color = points_color
|
|
57
|
+
# self.points_radius = points_radius
|
|
58
|
+
# self.update_function(function)
|
|
59
|
+
|
|
60
|
+
# def update_points(self) -> None:
|
|
61
|
+
# self.update_function(self.function)
|
|
62
|
+
|
|
63
|
+
# def update_function(self, new_function) -> None:
|
|
64
|
+
# self.function = new_function
|
|
65
|
+
# self.points :list[V2|Vector2D]= [point for t in range(int(self.starting_t / self.step), int(self.ending_t / self.step)) if (self.plot.bottom_right_y < (point:=no_error_complex_function(new_function, t * self.step)).y < self.plot.top_left_y) and (self.plot.top_left_x < point.x < self.plot.bottom_right_x)]
|
|
66
|
+
# self.full_auto_connect = not any(point.distance_to(self.points[i]) > self.auto_connect_treshold for i,point in enumerate(self.points[1:]))
|
|
67
|
+
|
|
68
|
+
# def draw(self) -> None:
|
|
69
|
+
# if self.points_radius:
|
|
70
|
+
# for point in self.points:
|
|
71
|
+
# pg.draw.circle(self.plot.canvas, self.color if self.points_color == None else self.points_color, self.plot.__plot2real__(point)(), self.points_radius)
|
|
72
|
+
|
|
73
|
+
# if len(self.points) < 2: return
|
|
74
|
+
# if self.full_auto_connect:
|
|
75
|
+
# pg.draw.lines(self.plot.canvas, self.color, False, [self.plot.__plot2real__(point)() for point in self.points])
|
|
76
|
+
# else:
|
|
77
|
+
# real_points = [self.plot.__plot2real__(point)() for point in self.points]
|
|
78
|
+
# for i,(point, real_point) in enumerate(zip(self.points[1:], real_points[1:])):
|
|
79
|
+
# if point.distance_to(self.points[i]) < self.auto_connect_treshold:
|
|
80
|
+
# pg.draw.line(self.plot.canvas, self.color, real_points[i], real_point) #type: ignore
|
|
81
|
+
|
|
82
|
+
class __PlotSettings__:
|
|
83
|
+
def __init__(self, plot:Plot) -> None:
|
|
84
|
+
self.plot = plot
|
|
85
|
+
self.settings :dict[str: bool|V2|Vector2D|int|float]= {
|
|
86
|
+
"use_real_time_rendering" : True,
|
|
87
|
+
"show_corners_coords" : True,
|
|
88
|
+
|
|
89
|
+
"use_inter_pixel_correction" : True,
|
|
90
|
+
|
|
91
|
+
"show_zoom_info": True,
|
|
92
|
+
"top_left_info_position" : self.plot.position + V2(20, 100),
|
|
93
|
+
"info_spacing" : V2(0, 32),
|
|
94
|
+
"info_precision" : 2,
|
|
95
|
+
|
|
96
|
+
"distance_to_axis_for_scalar_zoom" : 10,
|
|
97
|
+
|
|
98
|
+
"bg_color" : (25, 25, 25),
|
|
99
|
+
"axes_default_color" : (100, 100, 100),
|
|
100
|
+
"x_axis_color" : None,
|
|
101
|
+
"y_axis_color" : None,
|
|
102
|
+
|
|
103
|
+
"axes_default_width" : 5,
|
|
104
|
+
"x_axis_width" : None,
|
|
105
|
+
"y_axis_width" : None,
|
|
106
|
+
|
|
107
|
+
"show_cursor_coords" : False,
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
def print_current_settings(self) -> None:
|
|
111
|
+
longest_key = max(map(len, self.settings))
|
|
112
|
+
longest_type = max(map(lambda setting: len(str(type(setting)).split("'")[1]), self.settings.values()))
|
|
113
|
+
for setting in self.settings:
|
|
114
|
+
print(f"{setting}{' '*(longest_key-len(setting))} :{str(type(self.settings[setting])).split("'")[1]}{' '*(longest_type-len(str(type(self.settings[setting])).split("'")[1]))}=\t{self.settings[setting]}")
|
|
115
|
+
|
|
116
|
+
def set(self, key:str, new_value) -> None:
|
|
117
|
+
if not (key in self.settings): raise ValueError(f"The key [{key}] does not exist...")
|
|
118
|
+
self.settings[key] = new_value
|
|
119
|
+
|
|
120
|
+
def multiple_set(self, keys:list[str], new_values:list) -> None:
|
|
121
|
+
for key, new_value in zip(keys, new_values):
|
|
122
|
+
self.set(key, new_value)
|
|
123
|
+
|
|
124
|
+
def get(self, key:str) -> bool|V2|Vector2D|int|float:
|
|
125
|
+
return self.settings[key]
|
|
126
|
+
|
|
127
|
+
def multiple_set(self, keys:list[str]) -> list[bool|V2|Vector2D|int|float]:
|
|
128
|
+
return [self.get(key) for key in keys]
|
|
129
|
+
|
|
130
|
+
class Plot:
|
|
131
|
+
__top_left_multiplier__ = V2(1, -1)
|
|
132
|
+
__bottop_right_multiplier__ = V2(1, -1)
|
|
133
|
+
def __init__(self, rootEnv:"RootEnv", plot_position:V2|Vector2D, plot_size:V2|Vector2D, top_left_plot_coord:V2|Vector2D, bottom_right_plot_coord: V2|Vector2D, scale:V2|Vector2D=V2one) -> None:
|
|
134
|
+
self.rootEnv = rootEnv
|
|
135
|
+
|
|
136
|
+
self.top_left_plot_coord = top_left_plot_coord
|
|
137
|
+
self.bottom_right_plot_coord = bottom_right_plot_coord
|
|
138
|
+
|
|
139
|
+
self.position = plot_position
|
|
140
|
+
self.size = plot_size
|
|
141
|
+
self.scale = scale
|
|
142
|
+
|
|
143
|
+
self.settings = __PlotSettings__(self)
|
|
144
|
+
|
|
145
|
+
self.current_zoom = V2one * -np.log2(10)*10
|
|
146
|
+
self.current_offset = V2(0,0)
|
|
147
|
+
self.update_grid(True)
|
|
148
|
+
|
|
149
|
+
self.functions :list[Function]= []
|
|
150
|
+
|
|
151
|
+
self.canvas = pg.Surface(self.size())
|
|
152
|
+
self.dragging = None
|
|
153
|
+
self.start_dragging = V2z
|
|
154
|
+
self.is_mouse_in_rect = False
|
|
155
|
+
|
|
156
|
+
def set_borders_by_position_and_zoom(self) -> None:
|
|
157
|
+
self.top_left_plot_coord = self.current_offset - (.5**(.1*self.current_zoom)) * self.__top_left_multiplier__
|
|
158
|
+
self.bottom_right_plot_coord = self.current_offset + (.5**(.1*self.current_zoom)) * self.__bottop_right_multiplier__
|
|
159
|
+
self.top_left_x, self.top_left_y = self.top_left_plot_coord
|
|
160
|
+
self.bottom_right_x, self.bottom_right_y = self.bottom_right_plot_coord
|
|
161
|
+
|
|
162
|
+
def update_grid(self, update_step_grid=False) -> None:
|
|
163
|
+
self.set_borders_by_position_and_zoom()
|
|
164
|
+
if update_step_grid:
|
|
165
|
+
self.step = (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size / self.scale
|
|
166
|
+
X, Y = np.arange(self.top_left_plot_coord.x, self.bottom_right_plot_coord.x, self.step.x), np.arange(self.top_left_plot_coord.y, self.bottom_right_plot_coord.y, self.step.y)
|
|
167
|
+
self.meshgrid = np.meshgrid(X, Y)
|
|
168
|
+
self.pixel_size = abs(self.size / (self.bottom_right_plot_coord - self.top_left_plot_coord) * (self.step * -1))
|
|
169
|
+
if self.settings.get("use_inter_pixel_correction"):
|
|
170
|
+
self.pixel_size += V2one
|
|
171
|
+
|
|
172
|
+
def load_function(self, function:Function) -> None:
|
|
173
|
+
function.plot = self
|
|
174
|
+
function.__layer_surface__ = pg.Surface(self.size(), pg.SRCALPHA, 32).convert_alpha()
|
|
175
|
+
function.update_function(function.function)
|
|
176
|
+
self.functions.append(function)
|
|
177
|
+
|
|
178
|
+
def __plot2real__(self, plot_position:V2|Vector2D) -> V2|Vector2D:
|
|
179
|
+
return (plot_position + self.top_left_plot_coord * -1) * self.size / (self.bottom_right_plot_coord - self.top_left_plot_coord)
|
|
180
|
+
|
|
181
|
+
def __real2plot__(self, real_position:V2|Vector2D) -> V2|Vector2D:
|
|
182
|
+
return (real_position - self.position) * (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size + self.top_left_plot_coord
|
|
183
|
+
|
|
184
|
+
def render(self) -> None:
|
|
185
|
+
self.canvas.fill(self.settings.get("bg_color"))
|
|
186
|
+
if self.top_left_x < 0 < self.bottom_right_x:
|
|
187
|
+
pg.draw.line(self.canvas,
|
|
188
|
+
self.settings.get("axes_default_color") if (x_color:=self.settings.get("x_axis_color"))==None else x_color,
|
|
189
|
+
self.__plot2real__(V2(0, self.top_left_y))(),
|
|
190
|
+
self.__plot2real__(V2(0, self.bottom_right_y))(),
|
|
191
|
+
self.settings.get("axes_default_width") if (x_width:=self.settings.get("x_axis_width"))==None else x_width)
|
|
192
|
+
if self.bottom_right_y < 0 < self.top_left_y:
|
|
193
|
+
pg.draw.line(self.canvas,
|
|
194
|
+
self.settings.get("axes_default_color") if (y_color:=self.settings.get("y_axis_color"))==None else y_color,
|
|
195
|
+
self.__plot2real__(V2(self.top_left_x, 0))(),
|
|
196
|
+
self.__plot2real__(V2(self.bottom_right_x, 0))(),
|
|
197
|
+
self.settings.get("axes_default_width") if (y_width:=self.settings.get("y_axis_width"))==None else y_width)
|
|
198
|
+
|
|
199
|
+
for function in self.functions: function.draw()
|
|
200
|
+
|
|
201
|
+
pg.draw.rect(self.canvas, (255,255,255), V2z() + self.size(), 5) #type: ignore
|
|
202
|
+
|
|
203
|
+
center = self.size * .5
|
|
204
|
+
aimer_radius = 15
|
|
205
|
+
pg.draw.line(self.canvas, (100,100,100), (center + aimer_radius)(), (center - aimer_radius)(), 1)
|
|
206
|
+
pg.draw.line(self.canvas, (100,100,100), (center + self.__top_left_multiplier__ * aimer_radius)(), (center - self.__top_left_multiplier__ * aimer_radius)(), 1)
|
|
207
|
+
pg.draw.circle(self.canvas, (100,100,100), (self.size * .5)(), 15, 1)
|
|
208
|
+
|
|
209
|
+
if self.settings.get("show_corners_coords"):
|
|
210
|
+
self.rootEnv.print(str(self.top_left_plot_coord.__round__(.1)), V2z.copy(), bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
211
|
+
self.rootEnv.print(str(V2(self.top_left_plot_coord.x, self.bottom_right_plot_coord.y).__round__(.1)), self.size * V2(0, 1), fixed_sides=TEXT_FIXED_SIDES_BOTTOM_LEFT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
212
|
+
self.rootEnv.print(str(self.bottom_right_plot_coord.__round__(.1)), self.size.copy(), fixed_sides=TEXT_FIXED_SIDES_BOTTOM_RIGHT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
213
|
+
self.rootEnv.print(str(V2(self.bottom_right_plot_coord.x, self.top_left_plot_coord.y).__round__(.1)), self.size * V2(1, 0), fixed_sides=TEXT_FIXED_SIDES_TOP_RIGHT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
214
|
+
|
|
215
|
+
def update(self) -> None:
|
|
216
|
+
self.plot_mouse_position = self.__real2plot__(self.rootEnv.mouse.position)
|
|
217
|
+
self.plot_center_real_position = self.__plot2real__(V2z) + self.position
|
|
218
|
+
|
|
219
|
+
self.is_mouse_in_rect = self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and \
|
|
220
|
+
self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
|
|
221
|
+
|
|
222
|
+
if self.rootEnv.mouse.just_released[0] and self.dragging != None:
|
|
223
|
+
self.dragging = None
|
|
224
|
+
self.update_grid(True)
|
|
225
|
+
for function in self.functions:
|
|
226
|
+
function.update_points()
|
|
227
|
+
self.render()
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
if self.is_mouse_in_rect:
|
|
231
|
+
for event in self.rootEnv.events:
|
|
232
|
+
if event.type == pg.MOUSEWHEEL:
|
|
233
|
+
|
|
234
|
+
range_n = self.settings.get("distance_to_axis_for_scalar_zoom")
|
|
235
|
+
scalar = V2(0 if abs(self.plot_center_real_position.x - self.rootEnv.mouse.position.x) < range_n else 1, 0 if abs(self.plot_center_real_position.y - self.rootEnv.mouse.position.y) < range_n else 1)
|
|
236
|
+
self.current_zoom += event.y * scalar
|
|
237
|
+
|
|
238
|
+
self.update_grid(True)
|
|
239
|
+
for function in self.functions:
|
|
240
|
+
function.update_points()
|
|
241
|
+
self.render()
|
|
242
|
+
|
|
243
|
+
if self.rootEnv.mouse.just_pressed[0] and self.dragging == None:
|
|
244
|
+
self.dragging = self.rootEnv.mouse.position.copy()
|
|
245
|
+
self.start_dragging = self.dragging.copy()
|
|
246
|
+
|
|
247
|
+
if self.dragging:
|
|
248
|
+
offset = (self.dragging - self.rootEnv.mouse.position)* V2(1, -1) * (abs(self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size)
|
|
249
|
+
self.dragging = self.rootEnv.mouse.position.copy()
|
|
250
|
+
self.current_offset += offset
|
|
251
|
+
|
|
252
|
+
if self.settings.get("use_real_time_rendering"):
|
|
253
|
+
self.update_grid(True)
|
|
254
|
+
for function in self.functions: function.update_points()
|
|
255
|
+
else:
|
|
256
|
+
self.update_grid()
|
|
257
|
+
self.render()
|
|
258
|
+
|
|
259
|
+
def draw(self) -> None:
|
|
260
|
+
self.rootEnv.screen.blit(self.canvas, self.position())
|
|
261
|
+
if self.is_mouse_in_rect and self.settings.get("show_cursor_coords"):
|
|
262
|
+
self.rootEnv.print(str(round(self.plot_mouse_position, .1)), self.rootEnv.mouse.position, fixed_sides=TEXT_FIXED_SIDES_BOTTOM_MIDDLE)
|
|
263
|
+
|
|
264
|
+
data = [
|
|
265
|
+
[f"ZOOM:", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
|
|
266
|
+
[f" x: {self.current_zoom.x:.{self.settings.get("info_precision")}f};", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
|
|
267
|
+
[f" y: {self.current_zoom.y:.{self.settings.get("info_precision")}f};", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
|
|
268
|
+
]
|
|
269
|
+
|
|
270
|
+
for i, (d, fixed_side, show) in enumerate(data):
|
|
271
|
+
if show:
|
|
272
|
+
self.rootEnv.print(d, self.settings.get("top_left_info_position") + self.settings.get("info_spacing") * i, fixed_sides=fixed_side)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: e2D
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.4
|
|
4
4
|
Summary: Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
|
|
5
5
|
Home-page: https://github.com/marick-py/e2D
|
|
6
6
|
Author: Riccardo Mariani
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[metadata]
|
|
2
2
|
name = e2D
|
|
3
|
-
version = 1.3.
|
|
3
|
+
version = 1.3.4
|
|
4
4
|
author = Riccardo Mariani
|
|
5
5
|
author_email = ricomari2006@gmail.com
|
|
6
6
|
description = Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
|
e2D-1.3.3/e2D/plots.py
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
from .envs import *
|
|
3
|
-
import numpy as np
|
|
4
|
-
|
|
5
|
-
def no_error_complex_function(function, args) -> V2|Vector2D:
|
|
6
|
-
res :complex= function(args)
|
|
7
|
-
return V2(res.real, res.imag)
|
|
8
|
-
|
|
9
|
-
sign = lambda value: -1 if value < 0 else (1 if value > 0 else 0)
|
|
10
|
-
|
|
11
|
-
class Function:
|
|
12
|
-
def __init__(self, function, plot:"Plot", color) -> None:
|
|
13
|
-
self.plot = plot
|
|
14
|
-
self.color = color
|
|
15
|
-
self.update_function(function)
|
|
16
|
-
|
|
17
|
-
def update_points(self) -> None:
|
|
18
|
-
self.update_function(self.function)
|
|
19
|
-
|
|
20
|
-
def get_points(self) -> list:
|
|
21
|
-
signs_self = np.sign(self.function(*self.plot.meshgrid))
|
|
22
|
-
signs_sum = signs_self + np.roll(signs_self, axis=1, shift=1) + np.roll(signs_self, axis=0, shift=-1) + np.roll(signs_self, axis=(1,0), shift=(1,-1))
|
|
23
|
-
return np.column_stack(np.where(((-4 < signs_sum) & (signs_sum < 4))[:-1, 1:])[::-1]) / self.plot.scale()
|
|
24
|
-
|
|
25
|
-
def update_function(self, new_function) -> None:
|
|
26
|
-
self.function = new_function
|
|
27
|
-
self.points = self.get_points()
|
|
28
|
-
|
|
29
|
-
def draw(self) -> None:
|
|
30
|
-
# pg.draw.aalines(self.plot.canvas, self.color, False, self.points)
|
|
31
|
-
for point in self.points:
|
|
32
|
-
self.plot.canvas.set_at(list(map(int, point)), self.color)
|
|
33
|
-
|
|
34
|
-
# class ComplexFunction:
|
|
35
|
-
# def __init__(self, function, plot:"Plot", starting_t:float=-10, ending_t:float=10, step=.01, color=(255,255,255), auto_connect_treshold=float("inf"), points_radius=2, points_color=None) -> None:
|
|
36
|
-
# self.auto_connect_treshold = auto_connect_treshold
|
|
37
|
-
# self.plot = plot
|
|
38
|
-
# self.starting_t = starting_t
|
|
39
|
-
# self.ending_t = ending_t
|
|
40
|
-
# self.color = color
|
|
41
|
-
# self.step = step
|
|
42
|
-
# self.points_color = points_color
|
|
43
|
-
# self.points_radius = points_radius
|
|
44
|
-
# self.update_function(function)
|
|
45
|
-
|
|
46
|
-
# def update_points(self) -> None:
|
|
47
|
-
# self.update_function(self.function)
|
|
48
|
-
|
|
49
|
-
# def update_function(self, new_function) -> None:
|
|
50
|
-
# self.function = new_function
|
|
51
|
-
# self.points :list[V2|Vector2D]= [point for t in range(int(self.starting_t / self.step), int(self.ending_t / self.step)) if (self.plot.bottom_right_y < (point:=no_error_complex_function(new_function, t * self.step)).y < self.plot.top_left_y) and (self.plot.top_left_x < point.x < self.plot.bottom_right_x)]
|
|
52
|
-
# self.full_auto_connect = not any(point.distance_to(self.points[i]) > self.auto_connect_treshold for i,point in enumerate(self.points[1:]))
|
|
53
|
-
|
|
54
|
-
# def draw(self) -> None:
|
|
55
|
-
# if self.points_radius:
|
|
56
|
-
# for point in self.points:
|
|
57
|
-
# pg.draw.circle(self.plot.canvas, self.color if self.points_color == None else self.points_color, self.plot.__plot2real__(point)(), self.points_radius)
|
|
58
|
-
|
|
59
|
-
# if len(self.points) < 2: return
|
|
60
|
-
# if self.full_auto_connect:
|
|
61
|
-
# pg.draw.lines(self.plot.canvas, self.color, False, [self.plot.__plot2real__(point)() for point in self.points])
|
|
62
|
-
# else:
|
|
63
|
-
# real_points = [self.plot.__plot2real__(point)() for point in self.points]
|
|
64
|
-
# for i,(point, real_point) in enumerate(zip(self.points[1:], real_points[1:])):
|
|
65
|
-
# if point.distance_to(self.points[i]) < self.auto_connect_treshold:
|
|
66
|
-
# pg.draw.line(self.plot.canvas, self.color, real_points[i], real_point) #type: ignore
|
|
67
|
-
|
|
68
|
-
class Plot:
|
|
69
|
-
__top_left_multiplier__ = V2(1, -1)
|
|
70
|
-
__bottop_right_multiplier__ = V2(1, -1)
|
|
71
|
-
def __init__(self, rootEnv:"RootEnv", plot_position:V2|Vector2D, plot_size:V2|Vector2D, top_left_plot_coord:V2|Vector2D, bottom_right_plot_coord: V2|Vector2D, scale:V2|Vector2D=V2one) -> None:
|
|
72
|
-
self.rootEnv = rootEnv
|
|
73
|
-
|
|
74
|
-
self.top_left_plot_coord = top_left_plot_coord
|
|
75
|
-
self.bottom_right_plot_coord = bottom_right_plot_coord
|
|
76
|
-
|
|
77
|
-
self.position = plot_position
|
|
78
|
-
self.size = plot_size
|
|
79
|
-
self.scale = scale
|
|
80
|
-
|
|
81
|
-
self.current_zoom = V2one * -np.log2(10)*10
|
|
82
|
-
self.current_offset = V2(0,0)
|
|
83
|
-
self.update_grid(True)
|
|
84
|
-
|
|
85
|
-
self.functions :list[Function]= []
|
|
86
|
-
|
|
87
|
-
self.canvas = pg.Surface(self.size())
|
|
88
|
-
self.dragging = None
|
|
89
|
-
self.is_mouse_in_rect = False
|
|
90
|
-
|
|
91
|
-
def set_borders_by_position_and_zoom(self) -> None:
|
|
92
|
-
self.top_left_plot_coord = self.current_offset - (.5**(.1*self.current_zoom)) * self.__top_left_multiplier__
|
|
93
|
-
self.bottom_right_plot_coord = self.current_offset + (.5**(.1*self.current_zoom)) * self.__bottop_right_multiplier__
|
|
94
|
-
self.top_left_x, self.top_left_y = self.top_left_plot_coord
|
|
95
|
-
self.bottom_right_x, self.bottom_right_y = self.bottom_right_plot_coord
|
|
96
|
-
|
|
97
|
-
def update_grid(self, update_step_grid=False) -> None:
|
|
98
|
-
self.set_borders_by_position_and_zoom()
|
|
99
|
-
if update_step_grid:
|
|
100
|
-
self.step = (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size / self.scale
|
|
101
|
-
X, Y = np.arange(self.top_left_plot_coord.x, self.bottom_right_plot_coord.x, self.step.x), np.arange(self.top_left_plot_coord.y, self.bottom_right_plot_coord.y, self.step.y)
|
|
102
|
-
self.meshgrid = np.meshgrid(X, Y)
|
|
103
|
-
|
|
104
|
-
def load_function(self, function:Function) -> None:
|
|
105
|
-
self.functions.append(function)
|
|
106
|
-
|
|
107
|
-
def __plot2real__(self, plot_position:V2|Vector2D) -> V2|Vector2D:
|
|
108
|
-
return (plot_position + self.top_left_plot_coord * -1) * self.size / (self.bottom_right_plot_coord - self.top_left_plot_coord)
|
|
109
|
-
|
|
110
|
-
def __real2plot__(self, real_position:V2|Vector2D) -> V2|Vector2D:
|
|
111
|
-
return (real_position - self.position) * (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size + self.top_left_plot_coord
|
|
112
|
-
|
|
113
|
-
def render(self) -> None:
|
|
114
|
-
self.canvas.fill((0,0,0))
|
|
115
|
-
if self.bottom_right_y < 0 < self.top_left_y: pg.draw.line(self.canvas, (100,100,100), self.__plot2real__(V2(self.top_left_x, 0))(), self.__plot2real__(V2(self.bottom_right_x, 0))())
|
|
116
|
-
if self.top_left_x < 0 < self.bottom_right_x: pg.draw.line(self.canvas, (100,100,100), self.__plot2real__(V2(0, self.top_left_y))(), self.__plot2real__(V2(0, self.bottom_right_y))())
|
|
117
|
-
|
|
118
|
-
for function in self.functions: function.draw()
|
|
119
|
-
|
|
120
|
-
pg.draw.rect(self.canvas, (255,255,255), V2z() + self.size(), 5) #type: ignore
|
|
121
|
-
self.rootEnv.print(str(self.top_left_plot_coord.__round__(.1)), V2z.copy(), bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
122
|
-
self.rootEnv.print(str(V2(self.top_left_plot_coord.x, self.bottom_right_plot_coord.y).__round__(.1)), self.size * V2(0, 1), fixed_sides=TEXT_FIXED_SIDES_BOTTOM_LEFT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
123
|
-
self.rootEnv.print(str(self.bottom_right_plot_coord.__round__(.1)), self.size.copy(), fixed_sides=TEXT_FIXED_SIDES_BOTTOM_RIGHT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
124
|
-
self.rootEnv.print(str(V2(self.bottom_right_plot_coord.x, self.top_left_plot_coord.y).__round__(.1)), self.size * V2(1, 0), fixed_sides=TEXT_FIXED_SIDES_TOP_RIGHT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
125
|
-
|
|
126
|
-
def update(self) -> None:
|
|
127
|
-
self.is_mouse_in_rect = self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and \
|
|
128
|
-
self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
|
|
129
|
-
|
|
130
|
-
if self.rootEnv.mouse.just_released[0] and self.dragging != None:
|
|
131
|
-
self.dragging = None
|
|
132
|
-
self.update_grid(True)
|
|
133
|
-
for function in self.functions:
|
|
134
|
-
function.update_points()
|
|
135
|
-
self.render()
|
|
136
|
-
|
|
137
|
-
if self.is_mouse_in_rect:
|
|
138
|
-
for event in self.rootEnv.events:
|
|
139
|
-
if event.type == pg.MOUSEWHEEL:
|
|
140
|
-
self.current_zoom += event.y
|
|
141
|
-
self.update_grid(True)
|
|
142
|
-
for function in self.functions:
|
|
143
|
-
function.update_points()
|
|
144
|
-
self.render()
|
|
145
|
-
|
|
146
|
-
if self.rootEnv.mouse.just_pressed[0] and self.dragging == None:
|
|
147
|
-
self.dragging = self.rootEnv.mouse.position.copy()
|
|
148
|
-
|
|
149
|
-
if self.dragging:
|
|
150
|
-
offset = (self.dragging - self.rootEnv.mouse.position)* V2(1, -1) * (abs(self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size)
|
|
151
|
-
self.dragging = self.rootEnv.mouse.position.copy()
|
|
152
|
-
self.current_offset += offset
|
|
153
|
-
self.update_grid()
|
|
154
|
-
self.render()
|
|
155
|
-
|
|
156
|
-
def draw(self) -> None:
|
|
157
|
-
self.rootEnv.screen.blit(self.canvas, self.position())
|
|
158
|
-
if self.is_mouse_in_rect:
|
|
159
|
-
self.rootEnv.print(str(round(self.__real2plot__(self.rootEnv.mouse.position), .1)), self.rootEnv.mouse.position, fixed_sides=TEXT_FIXED_SIDES_BOTTOM_MIDDLE)
|
{e2D-1.3.3 → e2D-1.3.4}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|