jpcad/SketchWidget.py
2011-03-31 22:46:02 -04:00

134 lines
4.2 KiB
Python

import math
import gtk
import gtk.gtkgl
from OpenGL.GL import *
from Line import Line
from Circle import Circle
class SketchWidget:
def __init__(self, sketch):
self.sketch = sketch
try:
# try double-buffered
self.glconfig = gtk.gdkgl.Config(mode = (gtk.gdkgl.MODE_RGB |
gtk.gdkgl.MODE_DOUBLE |
gtk.gdkgl.MODE_DEPTH))
except gtk.gdkgl.NoMatches:
# try single-buffered
self.glconfig = gtk.gdkgl.Config(mode = (gtk.gdkgl.MODE_RGB |
gtk.gdkgl.MODE_DEPTH))
self.widget = gtk.gtkgl.DrawingArea(self.glconfig)
self.widget.connect_after('realize', self.init)
self.widget.connect('configure_event', self.reshape)
self.widget.connect('expose_event', self.draw)
def init(self, glarea):
# get GLContext and GLDrawable
glcontext = glarea.get_gl_context()
gldrawable = glarea.get_gl_drawable()
# GL calls
if not gldrawable.gl_begin(glcontext): return
# glEnable(GL_BLEND)
# glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
# glEnable(GL_POLYGON_SMOOTH)
# glEnable(GL_LINE_SMOOTH)
gldrawable.gl_end()
def reshape(self, glarea, event):
# get GLContext and GLDrawable
glcontext = glarea.get_gl_context()
gldrawable = glarea.get_gl_drawable()
# GL calls
if not gldrawable.gl_begin(glcontext): return
x, y, width, height = glarea.get_allocation()
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glOrtho(-2, 2, -1.5, 1.5, 1.0, -1.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gldrawable.gl_end()
return True
def draw(self, glarea, event):
# get GLContext and GLDrawable
glcontext = glarea.get_gl_context()
gldrawable = glarea.get_gl_drawable()
# GL calls
if not gldrawable.gl_begin(glcontext): return
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
for shape in self.sketch:
if isinstance(shape, Line):
self.drawLine(shape, 0.03)
elif isinstance(shape, Circle):
self.drawCircle(shape, 0.03)
if gldrawable.is_double_buffered():
gldrawable.swap_buffers()
else:
glFlush()
gldrawable.gl_end()
return True
def drawLine(self, shape, size):
self.drawFilledLine(shape.vars[0], shape.vars[1],
shape.vars[2], shape.vars[3], size)
def drawCircle(self, shape, size):
steps = 16
step = 2 * math.pi / steps
for i in range(steps + 1):
angle = i * step
next_angle = (i + 1) * step
x0 = shape.vars[0] + shape.vars[2] * math.cos(angle)
y0 = shape.vars[1] + shape.vars[2] * math.sin(angle)
x1 = shape.vars[0] + shape.vars[2] * math.cos(next_angle)
y1 = shape.vars[1] + shape.vars[2] * math.sin(next_angle)
self.drawFilledLineUncapped(x0, y0, x1, y1, size)
self.drawFilledCircle(x0, y0, size, 8)
def drawFilledLine(self, x0, y0, x1, y1, size):
self.drawFilledLineUncapped(x0, y0, x1, y1, size)
self.drawFilledCircle(x0, y0, size, 16)
self.drawFilledCircle(x1, y1, size, 16)
def drawFilledLineUncapped(self, x0, y0, x1, y1, size):
glBegin(GL_QUADS)
angle = math.atan2(y1 - y0, x1 - x0)
ninety = math.pi / 2
x_left = size * math.cos(angle + ninety)
y_left = size * math.sin(angle + ninety)
x_right = size * math.cos(angle - ninety)
y_right = size * math.sin(angle - ninety)
glVertex(x0 + x_left, y0 + y_left)
glVertex(x0 + x_right, y0 + y_right)
glVertex(x1 + x_right, y1 + y_right)
glVertex(x1 + x_left, y1 + y_left)
glEnd()
def drawFilledCircle(self, x, y, radius, steps):
glBegin(GL_TRIANGLE_FAN)
glVertex(x, y)
for i in range(steps + 1):
angle = i * 2 * math.pi / steps
glVertex(x + radius * math.cos(angle), y + radius * math.sin(angle))
glEnd()