Transformations complexes

Contenu du snippet

Ce code affiche des figures (cercles, lignes, ...) et l'image de leurs transformations via une fonction complexes.

Commandes :

t : changer de fonctions complexes
c : changer de figures
p/m : agrandir/rétrécir (via une homothétie)

Approfondissements/sources :

http://xavier.hubaut.info/coursmath/com/complexe.htm
https://en.wikipedia.org/wiki/Joukowsky_transform
http://mathfaculty.fullerton.edu/mathews/c2003/JoukowskiTransMod.html

Le code :

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

###################################
#                                 #
#       COURBES COMPLEXES         #
#                                 #
#                                 #
#                                 #
#      langage : Python 2.7       #
#          API : Pygame           #
#         date : 18/08/16         #
#          version : 1.0          #
#        auteur : ringo73         #
#                                 #
###################################

import pygame as pg
from pygame.locals import *
from math import pi, cos, sin
from os import popen, environ, name
from pygame.draw import line
try:
	from ctypes import windll
except ImportError:
	print "Importation non possible de windll."

def getSystemResolutionOnWin():
	return windll.user32.GetSystemMetrics(0), windll.user32.GetSystemMetrics(1)

def getSystemResolutionOnLin():
	screen = popen("xrandr -q -d :0").readlines()[0]
	tmp = screen.split()
	return int( tmp[7] ), int( tmp[9][:-1] )
	
def formulae(t,x,y):
	if t == JOUKOWSKY :
		if x ** 2 - y ** 2 != 0 :
			res = [ x / ( x ** 2 + y ** 2 ) + x , -y / ( x ** 2 + y ** 2 ) + y ]
		else:
			res = None
	elif t == SQUARE :
		res = [ x ** 2 - y ** 2 , 2 * x * y ]
	elif t == IDENTITY :
		res = [ x , y ]
	elif t == REVERSE :
		if x ** 2 - y ** 2 != 0 :
			res = [ x / ( x ** 2 + y ** 2 ) , -y / ( x ** 2 + y ** 2 ) ]
		else:
			res = None
	elif t == CUBE :
		res = [ x ** 3 - 3 * x * y ** 2 , 3 * x ** 2 * y - y ** 3 ]
	return res
		
def change_repere(x, y):
	x = int(x) + WIN_WIDTH // 2
	y = int(-y) + WIN_HEIGH // 2
	return [x,y]
	
def circle_points(r,n,o):
	tb = []
	theta = 2 * pi / n
	for i in range(n) :
		tb.append( [ o[X] + r * cos( theta * i ) , o[Y] + r * sin( theta * i ) ] )
	
	return tb
	
def circles_points(n,o):
	tb = []
	theta = 2 * pi / n
	for r in range(1,WIN_WIDTH//2,4) :
		for i in range(n) :
			tb.append( [ o[X] + r * cos( theta * i ) , o[Y] + r * sin( theta * i ) ] )
	
	return tb
	
def lines_ver_points(dx,dy):
	tb = []
	I, J = WIN_HEIGH // dy, WIN_WIDTH // dx
	x, y = 0, 0
	for j in range(-J//2,J//2) :
		x = j * dx
		for i in range(-I//2,I//2+1) :
			if j % 2 == 0 :
				y = i * dy
			else:
				y = -i * dy
			tb.append( [ x , y ] )
			
	return tb

def lines_hor_points(dx,dy):
	tb = []
	I, J = WIN_HEIGH // dy, WIN_WIDTH // dx
	x, y = 0, 0
	for i in range(-I//2,I//2) :
		y = i * -dy
		for j in range(-J//2,J//2+1) :
			if i % 2 == 0 :
				x = -j * dx
			else:
				x = j * dx
			tb.append( [ x , y ] )
			
	return tb
	
#def lines_hor_points(N,n):
	#tb = []
	#d = WIN_HEIGH / n
	#dd = WIN_WIDTH / N
	#x, y = 0, 0
	#for j in range(-n//2,n//2+1) :
		#y = j * d
		#for i in range(-N//2,N//2+1) :
			#if j % 2 == 0 :
				#x = i * dd
			#else:
				#x = -i * dd
			#tb.append( [ x , y ] )
			
	#return tb

def homo(p,k):
	return [ p[X] * k , p[Y] * k ]

def compute_fiber(t):
	fiber = []
	if t == CIRCLE :
		fiber = circle_points(1, 1000,(-0.08,0.08))
	elif t == CIRCLES :
		fiber = circles_points(100,(-0.08,0.08))
	elif t == LINES_HOR or t == LINES_ALL :
		fiber = lines_hor_points(3, 3)
	elif t == LINES_VER :
		fiber = lines_ver_points(3, 3)
	if t == LINES_ALL :
		fiber += lines_ver_points(3, 3)
	return fiber
	
def transform_and_print(bg, trans, k, tf):
	fiber = compute_fiber(tf)
	image = [ formulae(trans, *e) for e in fiber ]
	i = 0
	
	line(bg, BRIGHTBLUE, (0,WIN_HEIGH//2), (WIN_WIDTH-1,WIN_HEIGH//2), 2)
	line(bg, BRIGHTBLUE, (WIN_WIDTH//2,0), (WIN_WIDTH//2,WIN_HEIGH-1), 2)
	
	for i in range(1,len(fiber)) :
		line(bg, BLACK, change_repere(*homo(fiber[i-1],k)), change_repere(*homo(fiber[i],k)), 1)
	
	i = 0
	while i < len(image) :
		if image[i] == None :
			image.remove( image[i] )
		else:
			i += 1
	
	for i in range(1,len(image)) :
		line(bg, RED, change_repere(*homo(image[i-1],k)), change_repere(*homo(image[i],k)), 1)
	
def main():
	tps = [ 0.0 , 0.0 ]
	para = [ IDENTITY , 1.0 , LINES_ALL ]
	
	raffraichir = True
	zoom = 1.0
	
	# Initialisation de la fenêtre d'affichage
	environ['SDL_VIDEO_CENTERED'] = '1'
	pg.init()
	screen = pg.display.set_mode((WIN_WIDTH, WIN_HEIGH), pg.DOUBLEBUF | pg.HWSURFACE)
	pg.display.set_caption("Courbes complexes")
	pg.key.set_repeat (500, 30)

	bg = pg.Surface(screen.get_size())

	# Initialisation de l'horloge
	clock = pg.time.Clock()
	
	# Affichage d'un texte
	#font = pg.font.SysFont("arial", FONT_SIZE)
	#textpos = [ WIN_WIDTH * 0.05 , WIN_HEIGH * 0.07 ]
	
	# Boucle d'évènements
	while True :
		# S'assurer que le jeu ne fonctionne pas à plus de 60 images par secondes
		clock.tick(60)
		tps[PRES] = pg.time.get_ticks()
		
		for event in pg.event.get():
			if event.type == pg.QUIT or event.type == KEYDOWN and event.key == K_ESCAPE:
				exit()
			elif event.type == KEYDOWN and event.key == K_t :
				raffraichir = True
				para[0] = ( para[0] + 1 ) % 5
				if para[0] == SQUARE :
					para[1] = 1.0
					para[2] = LINES_ALL
				elif para[0] == CUBE :
					para[1] = 0.125
					para[2] = LINES_ALL
				elif para[0] == JOUKOWSKY :
					para[1] = 200.0
					para[2] = CIRCLE
			elif event.type == KEYDOWN and event.key == K_c :
				raffraichir = True
				para[2] = ( para[2] + 1 ) % 5
			elif event.type == KEYDOWN and event.key == K_p :
				raffraichir = True
				para[1] *= 2
			elif event.type == KEYDOWN and event.key == K_m :
				raffraichir = True
				para[1] /= 2

		if raffraichir :
			raffraichir = False
			bg.fill(WHITE)
			#bg.blit(font.render("Polyedre :  " + POLYEDRE[actual_poly], 1, BLACK), textpos)
			transform_and_print(bg, *para)
			print [ FUNCTIONS[para[0]] , "k = " + str(para[1]) , DRAWINGS[para[2]] ]
			screen.blit(bg, (0, 0))
			tps[PAST] = tps[PRES]
			pg.display.flip()

#############################
#########constantes##########
#############################
if name == "nt" :
	WIN_WIDTH, WIN_HEIGH = getSystemResolutionOnWin()
elif name == "posix" :
	WIN_WIDTH, WIN_HEIGH = getSystemResolutionOnLin()
else:
	WIN_WIDTH = 500
	WIN_HEIGH = 380
	
WIN_WIDTH = int( WIN_WIDTH * 0.8 )
WIN_HEIGH = int( WIN_HEIGH * 0.8 )

#FONT_SIZE = int( WIN_WIDTH * 0.05 )

#FREQ = 4

#Mouse Button, Scroll Wheel
MB_LEFT, MB_MIDDLE, MB_RIGHT, MBSW_UP, MBSW_DOWN = 1, 2, 3, 4, 5

#              R    G    B
WHITE      = (250, 250, 250)
BLACK      = ( 10,  10,  10)
GREEN      = (  0, 155,   0)
BRIGHTBLUE = (  0,  50, 255)
BROWN      = (174,  94,   0)
RED        = (200,   0,   0)

#############################
########enumerations#########
#############################
PRES, PAST, DELAY = 0, 1, 2
X, Y, Z = 0, 1, 2
IDENTITY, SQUARE, CUBE, JOUKOWSKY, REVERSE = 0, 1, 2, 3, 4
LINES_HOR, LINES_VER, LINES_ALL, CIRCLE, CIRCLES = 0, 1, 2, 3, 4

#############################
########dictionnaires########
#############################
DRAWINGS = { LINES_HOR : "LINES_HOR" , LINES_VER : "LINES_VER" , LINES_ALL : "LINES_ALL" , CIRCLE : "CIRCLE" , CIRCLES : "CIRCLES" }
FUNCTIONS = { CUBE : "CUBE" , JOUKOWSKY : "JOUKOWSKY" , IDENTITY : "IDENTITY" , SQUARE : "SQUARE" , REVERSE : "REVERSE" }

if __name__ == '__main__' : main()

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.