Exemple #1
0
def main():
	Maths.generateMathExpressions()
	print("Available operators:")
	for o in Maths.Expressions:
		print(Maths.Expressions[o].getAbbreviation())

	print("-------------------------")
	f = Function("cos(3*x)+6/4*(x+3)", False)
	print("RPN String", f.getRpnString())
	for x in range (2, 11):
		f.compute(x)

	print("-------------------------")

	f = Function("56*((6+2)/(8-x)*2^3", False)
	print("RPN String", f.getRpnString()) #should give 56 6 2 + 8 7 - / 2 3 ^ * *


	mainwindow = MainWindow("Function Drawer", 992, 512)
	fx = f.computeRange(0, 10)
	max_y = max(fx.values())
	min_y = min(fx.values())

	print(min_y, max_y)
	mainwindow.setCoords(-1, min_y, 11, max_y)
	for x in range(0, 11):
		print(fx[x])
		p = Point(x, fx[x])
		p.draw(mainwindow)

	input("Press a key to quit")
class GraphWidget:
	def __init__(self, pt_left_bot, pt_right_top, win):
		self.function = Function("0")
		self.p1 = pt_left_bot
		self.p2 = pt_right_top
		self.graph_area = Rectangle(self.p1, self.p2)
		self.win = win
		self.accuracy = 0.1
		self.objects_drawn = []

	def getFunction(self):
		return self.func
	def setFunction(self, func):
		self.function = func

	def draw(self, xa, xb):
		self.cleanGraph()
		#Compute function and draw it
		x_min = min(xa, xb)
		x_max = max(xa, xb)
		
		#Compute all the values for f functon, accuracy give the step for computation
		fx = self.function.computeRange(x_min, x_max, self.accuracy)
		y_max = max(fx.values())
		y_min = min(fx.values())
		print(y_max, y_min)
		self.win.setCoords(x_min-(1/10)*x_max, y_min-(1/10)*y_max, x_max+(1/10)*x_max, y_max+(4/10)*y_max)

		x = x_min
		end = x_max
		prevfx = fx[x]
		k = 0
		while x < (end+self.accuracy):
			#p = Point(x, fx)
			#p.draw(mainwindow)
			u = fx[x]
			if k > 0:
				self.drawLine(x-self.accuracy, prevfx, x, u)
			prevfx = u
			x += self.accuracy
			k += 1

		self.drawAxis(x_min, x_max, y_min, y_max)
		


	def drawLine(self, x1, y1, x2, y2):
		l = Line(Point(x1, y1), Point(x2, y2))
		self.objects_drawn.append(l)
		drawer = DrawerThread()
		l.setOutline("blue")
		drawer.run(l, self.win)
		return

	def drawAxis(self, x_min, x_max, y_min, y_max):
		#Draw axes
		#draw x axs first
		#we first consider we will draw it where y=0
		x_axis = Line(Point(x_min, 0), Point(x_max, 0))
		if y_max < 0:
			#if all the x values are under 0
			#then we draw the on the top
			x_axis = Line(Point(x_min, y_max), Point(x_max, y_max))
		elif y_min > 0:
			#if all the x values are over 0
			#then we draw it at the bottom
			x_axis = Line(Point(x_min, y_min), Point(x_max, y_min))
		drawer = DrawerThread()
		drawer.run(x_axis, self.win)
		self.objects_drawn.append(x_axis)

		#we consider we will draw where x=0
		y_axis = Line(Point(0, y_min), Point(0, y_max))
		if x_max < 0:
			#if all the y values are under 0
			#then we draw the on right
			y_axis = Line(Point(x_max, y_min), Point(x_max, y_max))
		elif x_min > 0:
			#if all the y values are over 0
			#then we draw it at the bottom
			y_axis = Line(Point(x_min, y_min), Point(x_min, y_max))
		
		drawer = DrawerThread()
		drawer.run(y_axis, self.win)
		self.objects_drawn.append(y_axis)

		#draw x labels
		y_ax = x_axis.getP1().getY()
		x_step = x_max*(0.1)
		x_size = y_max*.01
		#from 0 to x_max
		x = 0
		togo = x_max+0.1
		while x < togo:
			sign = Line(Point(x, y_ax-x_size), Point(x, y_ax+x_size))
			drawer = DrawerThread()
			drawer.run(sign, self.win)
			self.objects_drawn.append(sign)
			if x != 0:
				text = str(int(x))
				if abs(x) < 1:
					text = ("{0:.1f}").format(x)
				label = Text(Point(x, y_ax-6*x_size), text)
				label.setSize(8)
				label.draw(self.win)
				self.objects_drawn.append(label)
			x += x_step
		#from 0 to x_min
		x = 0
		togo = x_min-(0.1)
		while x > togo:
			sign = Line(Point(x, y_ax-x_size), Point(x, y_ax+x_size))
			drawer = DrawerThread()
			drawer.run(sign, self.win)
			self.objects_drawn.append(sign)
			if x != 0:
				text = str(int(x))
				if abs(x) < 1:
					text = ("{0:.1f}").format(x)
				label = Text(Point(x, y_ax-6*x_size), text)
				label.setSize(8)
				label.draw(self.win)
				self.objects_drawn.append(label)
			x -= x_step
		#draw y labels
		x_ax = y_axis.getP1().getX()
		y_step = y_max*(0.1)
		y_size = x_max*(0.01)
		#from 0 to y_max
		y = 0
		togo = y_max+0.1
		while y < togo:
			print(y)
			sign = Line(Point(x_ax-y_size, y), Point(x_ax+y_size, y))
			drawer = DrawerThread()
			drawer.run(sign, self.win)
			self.objects_drawn.append(sign)
			if y != 0:
				text = str(int(y))
				if abs(y) < 1:
					text = ("{0:.1f}").format(y)
					y = float(text)
				label = Text(Point(x_ax-6*y_size, y), text)
				label.setSize(8)
				label.draw(self.win)
				self.objects_drawn.append(label)
			y = y+y_step
		#from 0 to y_min
		y = 0
		print(y_max, y)
		togo = y_min-0.1
		while y > togo:
			sign = Line(Point(x_ax-y_size, y), Point(x_ax+y_size, y))
			drawer = DrawerThread()
			drawer.run(sign, self.win)
			self.objects_drawn.append(sign)
			if y != 0:
				text = str(int(y))
				if abs(y) < 1:
					text = ("{0:.1f}").format(y)
					y = float(text)
				label = Text(Point(x_ax-6*y_size, y), text)
				label.setSize(8)
				label.draw(self.win)
				self.objects_drawn.append(label)
			y = y-y_step

	def cleanGraph(self):
		undrawer = UndrawerThread()
		undrawer.run(self.objects_drawn)
		self.objects_drawn = []

	def drawWuLine(self, x1, y1, x2, y2):
		xd = x2-x1
		yd = y2-y1
		if xd == 0 or yd == 0:
			print("Normal line")
			self.drawLine(x1, y1, x2, y2)

		else:
			if abs(xd) > abs(yd):
				#this is a vertical line
				#so we switch x and y

				if x1 < x2: #algorithm works only from min to max
					swap(x1, x2)
					swap(y1, y2)
		
				grad = yd/xd

				#first end point
				xend = round(x1)
				yend = y1+grad+(xend-x1)
				xgap = rfpart(x1+0.5)
				ix1 = round(xend)
				iy1 = int(yend)
				self.drawPixel(ix1, iy1, rfpart(yend)*xgap)
				self.drawPixel(ix1, iy1+1, fpart(yend)*xgap)
				yf = yend+grad

				#second end point
				xend = round(x2)
				yend = y2+grad*(xend-x2)
				xgap = fpart(x2+0.5)
				ix2 = round(xend)
				iy2 = int(yend)
				self.drawPixel(ix2, iy2, rfpart(yend)*xgap)
				self.drawPixel(ix2, iy2+1, fpart(yend)*xgap)

				#main loop
				x = ix1+1
				while x<(ix2-1):
					self.drawPixel(x, int(yf), rfpart(yf))
					self.drawPixel(x, int(yf)+1, fpart(yf))
					yf += grad
					x += 1
			elif abs(xd) < abs(yd):
				#this is a vertical line
				#so we switch x and y

				if y1 < y2: #algorithm works only from min to max
					swap(x1, x2)
					swap(y1, y2)
		
				grad = xd/yd

				#first end point
				yend = round(y1)
				xend = x1+grad+(yend-y1)
				ygap = rfpart(y1+0.5)
				iy1 = round(yend)
				ix1 = int(xend)
				self.drawPixel(ix1, iy1, rfpart(yend)*ygap)
				self.drawPixel(ix1, iy1+1, fpart(yend)*ygap)
				xf = xend+grad

				#second end point
				yend = round(y2)
				xend = x2+grad*(yend-y2)
				ygap = fpart(y2+0.5)
				iy2 = round(yend)
				ix2 = int(xend)
				self.drawPixel(ix2, iy2, rfpart(xend)*ygap)
				self.drawPixel(ix2, iy2+1, fpart(xend)*ygap)

				#main loop
				y = iy1+1
				while y<(iy2-1):
					self.drawPixel(int(xf), y, rfpart(xf))
					self.drawPixel(int(xf)+1, y, fpart(xf))
					xf += grad
					y += 1			

	def drawPixel(self, x, y, c):
   		p = Point(x, y)
   		#we convert the transparence c(0 to 1) to a rgb value(0 to 255)
   		c = math.floor(255*(1-c))
   		p.draw(self.win)