Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/volumeobject.py
diff options
context:
space:
mode:
Diffstat (limited to 'volumeobject.py')
-rw-r--r--volumeobject.py111
1 files changed, 82 insertions, 29 deletions
diff --git a/volumeobject.py b/volumeobject.py
index 90c43aa..de86f5d 100644
--- a/volumeobject.py
+++ b/volumeobject.py
@@ -16,12 +16,15 @@
from objectarea import Object
from vector import Vector
from movableobject import MovableObject
+from faucetobject import FaucetObject
import gtk, math
class VolumeObject(MovableObject):
"""Quasi three-dimensional container object."""
+ FILL_RATE = 50000
+
def __init__(self, symbol, pos, height = 400, lower_radius = 50, upper_radius = 100):
MovableObject.__init__(self)
@@ -45,11 +48,15 @@ class VolumeObject(MovableObject):
self.water_height = 0
self.water_lower_radius = lower_radius
- self.water_upper_radius = lower_radius
self.pos = pos
self.volume = self.calculate_volume()
- self.water_volume = self.calculate_water_volume()
+ self.water_volume = 0
+
+ self.animated_water_volume = 0
+ self.animated_water_height = 0
+
+ self.filling_from_faucet = False
self.selectable = True
@@ -66,11 +73,11 @@ class VolumeObject(MovableObject):
return (math.pi * self.height / 3.0) * \
(self.lower_radius * self.lower_radius + self.lower_radius * self.upper_radius + self.upper_radius * self.upper_radius)
- def calculate_water_volume(self):
- return (math.pi * self.water_height / 3.0) * \
- (self.lower_radius * self.lower_radius + self.lower_radius * self.water_upper_radius + self.water_upper_radius * self.water_upper_radius)
-
- def fill_to_given_volume(self, volume):
+ #def calculate_water_volume(self):
+ # return (math.pi * self.water_height / 3.0) * \
+ # (self.lower_radius * self.lower_radius + self.lower_radius * self.water_upper_radius + self.water_upper_radius * self.water_upper_radius)
+
+ def calculate_water_height(self, volume):
a = (self.upper_radius - self.lower_radius)**2
b = 3.0 * self.lower_radius * (self.upper_radius - self.lower_radius)
c = 3.0 * self.lower_radius ** 2
@@ -80,14 +87,18 @@ class VolumeObject(MovableObject):
#if volume <= 0.0:
if volume <= 0.0001:
- self.water_height = 0.0
- self.water_upper_radius = self.lower_radius
+ return 0.0
else:
- self.water_height = solution[0] * self.height
- self.water_upper_radius = self.lower_radius + self.water_height * (self.upper_radius - self.lower_radius)/self.height
-
- self.water_volume = self.calculate_water_volume()
+ return solution[0] * self.height
+ def fill_to_given_volume(self, volume):
+ self.water_height = self.calculate_water_height(volume)
+
+ #self.water_volume = self.calculate_water_volume()
+ self.water_volume = volume
+
+ self.start_animating()
+
# Solve the cubic equation.
def cubic(self, a, b, c, d=None):
from math import cos
@@ -160,12 +171,33 @@ class VolumeObject(MovableObject):
cr.fill()
cr.restore();
+ def animate(self):
+ if self.animated_water_volume < self.water_volume:
+ self.animated_water_volume = min(self.animated_water_volume + VolumeObject.FILL_RATE, self.water_volume)
+ self.animated_water_height = self.calculate_water_height(self.animated_water_volume)
+ self.calculate_bounds()
+ self.queue_draw()
+
+ elif self.animated_water_volume > self.water_volume:
+ self.animated_water_volume = max(self.animated_water_volume - VolumeObject.FILL_RATE, self.water_volume)
+ self.animated_water_height = self.calculate_water_height(self.animated_water_volume)
+ self.calculate_bounds()
+ self.queue_draw()
+
+ else:
+ self.calculate_bounds()
+ self.queue_draw()
+ self.stop_animating()
+ self.filling_from_faucet = False
+
def draw(self, cr):
+ cr.save()
+
#cr.set_source_rgb(1, 0, 1)
#self_bounds_mn, self_bounds_mx = self.get_bounds()
#cr.rectangle(self_bounds_mn.x, self_bounds_mn.y, self_bounds_mx.x - self_bounds_mn.x, self_bounds_mx.y - self_bounds_mn.y)
#cr.fill()
-
+
cr.scale(self.scale, self.scale)
points = [
self.pos + Vector(-self.upper_radius, -self.height/2),
@@ -176,11 +208,11 @@ class VolumeObject(MovableObject):
# Transform the points.
water_points = points[:]
- water_points[0] = Vector(water_points[0].x + (self.upper_radius - self.lower_radius) * (self.height - self.water_height)/float(self.height), water_points[0].y - self.height + self.water_height)
- water_points[1] = Vector(water_points[1].x - (self.upper_radius - self.lower_radius) * (self.height - self.water_height)/float(self.height), water_points[1].y - self.height + self.water_height)
-
- water_points[0] = Vector(water_points[0].x, water_points[3].y - self.water_height)
- water_points[1] = Vector(water_points[1].x, water_points[2].y - self.water_height)
+ water_points[0] = Vector(water_points[0].x + (self.upper_radius - self.lower_radius) * (self.height - self.animated_water_height)/float(self.height), water_points[0].y - self.height + self.animated_water_height)
+ water_points[1] = Vector(water_points[1].x - (self.upper_radius - self.lower_radius) * (self.height - self.animated_water_height)/float(self.height), water_points[1].y - self.height + self.animated_water_height)
+
+ water_points[0] = Vector(water_points[0].x, water_points[3].y - self.animated_water_height)
+ water_points[1] = Vector(water_points[1].x, water_points[2].y - self.animated_water_height)
water_points[2] = Vector(water_points[2].x, water_points[2].y)
water_points[3] = Vector(water_points[3].x, water_points[3].y)
@@ -200,35 +232,49 @@ class VolumeObject(MovableObject):
# Fill in the lower ellipse.
cr.save()
- if not self.water_height == 0:
+ if not self.animated_water_height == 0:
#self.fill_ellipse(cr, self.pos.x - self.lower_radius, self.pos.y + self.height/2.0 - self.lower_radius/4.0, \
# 2.0 * self.lower_radius, self.lower_radius/2.0)
self.fill_ellipse(cr, points[3].x, points[3].y, \
2.0 * self.lower_radius, self.lower_radius/2.0)
cr.restore()
+ water_upper_radius = self.lower_radius + self.animated_water_height * (self.upper_radius - self.lower_radius)/self.height
+
# Fill in the upper ellipse.
cr.save()
- if not self.water_height == 0:
- #self.fill_ellipse(cr, self.pos.x - self.water_upper_radius, self.pos.y + self.height/2.0 - self.water_height - self.water_upper_radius/4.0, \
- #2.0 * self.water_upper_radius, self.water_upper_radius/2.0)
+ if not self.animated_water_height == 0:
+ #self.fill_ellipse(cr, self.pos.x - water_upper_radius, self.pos.y + self.height/2.0 - self.animated_water_height - water_upper_radius/4.0, \
+ #2.0 * water_upper_radius, water_upper_radius/2.0)
self.fill_ellipse(cr, water_points[0].x, water_points[0].y, \
- 2.0 * self.water_upper_radius, self.water_upper_radius/2.0)
+ 2.0 * water_upper_radius, water_upper_radius/2.0)
cr.restore()
# Draw the upper ellipse
- if not self.water_height == 0:
+ if not self.animated_water_height == 0:
+
cr.save()
cr.set_source_rgb(0.0, 0.0, 1.0)
cr.set_line_width(4.0)
- #self.draw_ellipse(cr, self.pos.x - self.water_upper_radius, \
- # self.pos.y + self.height/2.0 - self.water_height - self.water_upper_radius/4.0,
- # 2.0 * self.water_upper_radius, self.water_upper_radius/2.0)
+ #self.draw_ellipse(cr, self.pos.x - water_upper_radius, \
+ # self.pos.y + self.height/2.0 - self.animated_water_height - water_upper_radius/4.0,
+ # 2.0 * water_upper_radius, water_upper_radius/2.0)
self.draw_ellipse(cr, water_points[0].x, water_points[0].y, \
- 2.0 * self.water_upper_radius, self.water_upper_radius/2.0)
+ 2.0 * water_upper_radius, water_upper_radius/2.0)
cr.stroke()
cr.restore()
+
+ # Draw the faucet filling.
+ if self.filling_from_faucet:
+ stream_y = self.container.problem.faucet_object.pos.y + FaucetObject.STREAM_Y
+ cr.rectangle(self.container.problem.faucet_object.pos.x + FaucetObject.STREAM_X,
+ stream_y,
+ FaucetObject.STREAM_WIDTH, self.pos.y + self.height/2 - self.animated_water_height - stream_y)
+ #Draw the fill.
+ cr.set_source_rgb(0.37, 0.74, 1.0)
+ cr.fill()
+
# Done drawing the shape of the water.
# Now draw the shape of the container.
# Generate the shape.
@@ -282,6 +328,8 @@ class VolumeObject(MovableObject):
x_bearing, y_bearing, width, height = cr.text_extents(self.symbol)[:4]
cr.move_to(self.pos.x - x_bearing - width/2, self.pos.y - y_bearing - height/2)
cr.show_text(self.symbol)
+
+ cr.restore()
def calculate_bounds(self):
# Get the current width and height of the bounding rectangle.
@@ -297,6 +345,11 @@ class VolumeObject(MovableObject):
self.bounds_min -= Vector(2, 2 + self.upper_radius/4.)
self.bounds_max += Vector(2, 2 + self.lower_radius/4.)
+ # Include the stream when animating.
+ if self.filling_from_faucet:
+ stream_y = self.container.problem.faucet_object.pos.y + FaucetObject.STREAM_Y
+ self.bounds_min.y = stream_y
+
def get_bounds(self):
return self.bounds_min, self.bounds_max