You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
4.5 KiB
145 lines
4.5 KiB
5 months ago
|
from time import perf_counter
|
||
|
|
||
|
|
||
|
import pyglet.gl as pgl
|
||
|
|
||
|
from sympy.plotting.pygletplot.managed_window import ManagedWindow
|
||
|
from sympy.plotting.pygletplot.plot_camera import PlotCamera
|
||
|
from sympy.plotting.pygletplot.plot_controller import PlotController
|
||
|
|
||
|
|
||
|
class PlotWindow(ManagedWindow):
|
||
|
|
||
|
def __init__(self, plot, antialiasing=True, ortho=False,
|
||
|
invert_mouse_zoom=False, linewidth=1.5, caption="SymPy Plot",
|
||
|
**kwargs):
|
||
|
"""
|
||
|
Named Arguments
|
||
|
===============
|
||
|
|
||
|
antialiasing = True
|
||
|
True OR False
|
||
|
ortho = False
|
||
|
True OR False
|
||
|
invert_mouse_zoom = False
|
||
|
True OR False
|
||
|
"""
|
||
|
self.plot = plot
|
||
|
|
||
|
self.camera = None
|
||
|
self._calculating = False
|
||
|
|
||
|
self.antialiasing = antialiasing
|
||
|
self.ortho = ortho
|
||
|
self.invert_mouse_zoom = invert_mouse_zoom
|
||
|
self.linewidth = linewidth
|
||
|
self.title = caption
|
||
|
self.last_caption_update = 0
|
||
|
self.caption_update_interval = 0.2
|
||
|
self.drawing_first_object = True
|
||
|
|
||
|
super().__init__(**kwargs)
|
||
|
|
||
|
def setup(self):
|
||
|
self.camera = PlotCamera(self, ortho=self.ortho)
|
||
|
self.controller = PlotController(self,
|
||
|
invert_mouse_zoom=self.invert_mouse_zoom)
|
||
|
self.push_handlers(self.controller)
|
||
|
|
||
|
pgl.glClearColor(1.0, 1.0, 1.0, 0.0)
|
||
|
pgl.glClearDepth(1.0)
|
||
|
|
||
|
pgl.glDepthFunc(pgl.GL_LESS)
|
||
|
pgl.glEnable(pgl.GL_DEPTH_TEST)
|
||
|
|
||
|
pgl.glEnable(pgl.GL_LINE_SMOOTH)
|
||
|
pgl.glShadeModel(pgl.GL_SMOOTH)
|
||
|
pgl.glLineWidth(self.linewidth)
|
||
|
|
||
|
pgl.glEnable(pgl.GL_BLEND)
|
||
|
pgl.glBlendFunc(pgl.GL_SRC_ALPHA, pgl.GL_ONE_MINUS_SRC_ALPHA)
|
||
|
|
||
|
if self.antialiasing:
|
||
|
pgl.glHint(pgl.GL_LINE_SMOOTH_HINT, pgl.GL_NICEST)
|
||
|
pgl.glHint(pgl.GL_POLYGON_SMOOTH_HINT, pgl.GL_NICEST)
|
||
|
|
||
|
self.camera.setup_projection()
|
||
|
|
||
|
def on_resize(self, w, h):
|
||
|
super().on_resize(w, h)
|
||
|
if self.camera is not None:
|
||
|
self.camera.setup_projection()
|
||
|
|
||
|
def update(self, dt):
|
||
|
self.controller.update(dt)
|
||
|
|
||
|
def draw(self):
|
||
|
self.plot._render_lock.acquire()
|
||
|
self.camera.apply_transformation()
|
||
|
|
||
|
calc_verts_pos, calc_verts_len = 0, 0
|
||
|
calc_cverts_pos, calc_cverts_len = 0, 0
|
||
|
|
||
|
should_update_caption = (perf_counter() - self.last_caption_update >
|
||
|
self.caption_update_interval)
|
||
|
|
||
|
if len(self.plot._functions.values()) == 0:
|
||
|
self.drawing_first_object = True
|
||
|
|
||
|
iterfunctions = iter(self.plot._functions.values())
|
||
|
|
||
|
for r in iterfunctions:
|
||
|
if self.drawing_first_object:
|
||
|
self.camera.set_rot_preset(r.default_rot_preset)
|
||
|
self.drawing_first_object = False
|
||
|
|
||
|
pgl.glPushMatrix()
|
||
|
r._draw()
|
||
|
pgl.glPopMatrix()
|
||
|
|
||
|
# might as well do this while we are
|
||
|
# iterating and have the lock rather
|
||
|
# than locking and iterating twice
|
||
|
# per frame:
|
||
|
|
||
|
if should_update_caption:
|
||
|
try:
|
||
|
if r.calculating_verts:
|
||
|
calc_verts_pos += r.calculating_verts_pos
|
||
|
calc_verts_len += r.calculating_verts_len
|
||
|
if r.calculating_cverts:
|
||
|
calc_cverts_pos += r.calculating_cverts_pos
|
||
|
calc_cverts_len += r.calculating_cverts_len
|
||
|
except ValueError:
|
||
|
pass
|
||
|
|
||
|
for r in self.plot._pobjects:
|
||
|
pgl.glPushMatrix()
|
||
|
r._draw()
|
||
|
pgl.glPopMatrix()
|
||
|
|
||
|
if should_update_caption:
|
||
|
self.update_caption(calc_verts_pos, calc_verts_len,
|
||
|
calc_cverts_pos, calc_cverts_len)
|
||
|
self.last_caption_update = perf_counter()
|
||
|
|
||
|
if self.plot._screenshot:
|
||
|
self.plot._screenshot._execute_saving()
|
||
|
|
||
|
self.plot._render_lock.release()
|
||
|
|
||
|
def update_caption(self, calc_verts_pos, calc_verts_len,
|
||
|
calc_cverts_pos, calc_cverts_len):
|
||
|
caption = self.title
|
||
|
if calc_verts_len or calc_cverts_len:
|
||
|
caption += " (calculating"
|
||
|
if calc_verts_len > 0:
|
||
|
p = (calc_verts_pos / calc_verts_len) * 100
|
||
|
caption += " vertices %i%%" % (p)
|
||
|
if calc_cverts_len > 0:
|
||
|
p = (calc_cverts_pos / calc_cverts_len) * 100
|
||
|
caption += " colors %i%%" % (p)
|
||
|
caption += ")"
|
||
|
if self.caption != caption:
|
||
|
self.set_caption(caption)
|