Picking opengl(glut) / interpolation bézier,b-spline,catmulrom version python

Description

version Python du programme en c++ de la page:
http://www.cppfrance.com/codes/PICKING-OPENGL-GLUT-INTERPOLATION-BEZIER-SPLINE-CATMULROM_33230.aspx#addcomment
Opengl (GLUT) et picking avec tracé de courbe de bezier, spline et catmulrom.

Source / Exemple :


# Code initialement en c++ écrit par luhtor :
#http://www.cppfrance.com/codes/PICKING-OPENGL-GLUT-INTERPOLATION-BEZIER-SPLINE-CATMULROM_33230.aspx#addcomment
# converti en python par nahiene

from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
from numpy import floor, ceil

BUFFER_SIZE =128
DEFAULT_PRECISION =40
SCR_X =640
SCR_Y =480

class point:
    def __init__ (self,_x=0.0,_y=0.0,_r=0.0,_g=0.0,_b=1.0):
        self.x = _x 
        self.y = _y 
        self.r = _r 
        self.g = _g 
        self.b = _b 
    def draw_point(self):
        glColor3f(self.r,self.g,self.b) 
        glBegin(GL_POINTS) 
        glVertex2f(self.x,self.y) 
        glEnd() 
    def move(self, mx,  my):
        self.x += mx 
        self.y += my 
    def set_color(self, _r,  _g,  _b):
        self.r = _r 
        self.g = _g 
        self.b = _b 

#==================================================================================================

class selection:
    def __init__(self,newlist=[]):
        self.mylist=newlist 
    def add_point(self,mypoint):
        if mypoint in self.mylist: return 
        self.mylist.append(mypoint) 
        mypoint.set_color(1.0,0.0,0.0) 
    def remove_point(self,mypoint):
        self.mylist.remove(mypoint) 
        mypoint.set_color(0.0,0.0,1.0)
    def find(self,mypoint):
        if mypoint in self.mylist: return True 
        return False 
    def clear(self):
        for mypoint in self.mylist:
            mypoint.set_color(0.0,0.0,1.0)            
        self.mylist=[]
    def move(self, mx,  my):
        for mypoint in self.mylist:
            mypoint.move(mx,my)
    def add_selection (self, myselection):
        for mypoint in myselection.mylist:
            self.add_point(mypoint)
        myselection.mylist=[]

#==================================================================================================

class point_list:
    def __init__(self, newlist=[]):
        self.mylist=newlist
    def draw_all_point(self, mod=GL_RENDER ):
        for index, mypoint in enumerate(self.mylist):
            if(mod==GL_SELECT): glLoadName(index)
            mypoint.draw_point()
    def draw_point(self,which): #il a l'air inutilisé
        self.mylist[wich].draw_point() 
    def get_point(self,which):# on devrait s'en passer mais on méditera sur l'optimisation du code plus tard
        return self.mylist[which]
    def add_point(self,mypoint):
        self.mylist.append(mypoint)

#==================================================================================================
# COURBE Catmul-rom 
#==================================================================================================
#P est un point du plan. Et Px le point de controle d'indice x.
#P(t) = 1/2 * [ t^3,t^2,t,1 ] * [ -1  3 -3  1  ] * [ Pi-3 ]
#                               [  2 -5  4 -1  ]   [ Pi-2 ]
#                               [ -1  0  1  0  ]   [ Pi-1 ]
#                               [  0  2  0  0  ]   [ Pi   ]
class cat_curve:
    def __init__(self, which=point_list()):
        self.plist = which 
        self.curve_point = [] 
        self.nb_curve_point = 0 
        self.nb_point = len(self.plist.mylist) 
        self.precision = DEFAULT_PRECISION 
        self.draw_number = True 
    def compute(self):
        if (self.curve_point != []): self.curve_point=[] 
        self.nb_curve_point = self.precision+1 
        t=1.0
        p = float(self.nb_point-3.0)/float(self.precision) 
        for k in range(self.nb_curve_point):
            self.curve_point.append(point()) 
            i = int(floor(t)) 
            ti = float(i) 
            if (i!= self.nb_point-2):
                self.curve_point[k].x = (3.0*self.plist.mylist[i].x-3.0*self.plist.mylist[i+1].x+self.plist.mylist[i+2].x-self.plist.mylist[i-1].x)*pow(t-ti,3)/2.0+( 2.0*self.plist.mylist[i-1].x - 5.0*self.plist.mylist[i].x + 4.0*self.plist.mylist[i+1].x - self.plist.mylist[i+2].x)*pow(t-ti,2)/2.0+( self.plist.mylist[i+1].x - self.plist.mylist[i-1].x ) *(t-ti)/2.0 + self.plist.mylist[i].x 
                self.curve_point[k].y = (3.0*self.plist.mylist[i].y-3.0*self.plist.mylist[i+1].y+self.plist.mylist[i+2].y-self.plist.mylist[i-1].y)*pow(t-ti,3)/2.0+( 2.0*self.plist.mylist[i-1].y - 5.0*self.plist.mylist[i].y + 4.0*self.plist.mylist[i+1].y - self.plist.mylist[i+2].y)*pow(t-ti,2)/2.0+( self.plist.mylist[i+1].y - self.plist.mylist[i-1].y ) *(t-ti)/2.0 + self.plist.mylist[i].y 
            else:
                self.curve_point[k].x = self.plist.mylist[i].x 
                self.curve_point[k].y = self.plist.mylist[i].y 
            t += p 
    def draw(self):
        glColor3f(0.8,0.6,0.0) 
        glBegin(GL_LINE_STRIP) 
        for  i in range(self.nb_curve_point) :
            glVertex2f(self.curve_point[i].x, self.curve_point[i].y) 
        glEnd() 
        if (self.draw_number):
            glColor3f(0.0,0.0,0.0) 
            for i in range(self.nb_point):	  
                glRasterPos2f(self.plist.mylist[i].x - 8.0, self.plist.mylist[i].y + 8.0) 
                ch=repr(int(i)) 
                drawString(ch) 
    def Inc_Precision(self) : self.precision *= 2.0 
    def Dec_Precision(self) : self.precision = int(ceil(float(self.precision/2.0)))  
    def Toggle_Number(self):
        self.draw_number = not self.draw_number 
        return self.draw_number 

#==================================================================================================

# COURBE B Spline uniforme 

# Fonction de pondération pour les B splines uniformes

def spline_uniform( t,  x): # fonction allure Gauss, maximum en x = t
    t -= float(2.0) 
    if ((x < t+1.0) and  (x >= t)):
        return pow(x - t,3)/6.0 
    elif ((x < t+2.0) and (x >= t+1.0)) :
        return  1.0/6.0 * (3.0*t*t*t-3.0*t*t*(3.0*x-4.0)+3.0*t*(3.0*x*x-8.0*x+4.0)-3.0*x*x*x+12.0*x*(x-1.0)+4.0) 
    elif ((x < t+3.0) and (x >= t+2.0)) :
        return -1.0/6.0 * (3.0*t*t*t-3.0*t*t*(3.0*x-8.0)+3.0*t*(3.0*x*x-16.0*x+20.0)-3.0*x*x*x+24.0*x*x-60.0*x+44.0) 
    elif ((x < t+4.0) and (x >= t+3.0)) :
        return  1.0/6.0 * (t*t*t - 3.0*t*t*(x-4.0)+3.0*t*(x*x-8.0*x+16.0)-x*x*x+12.0*x*x-48.0*x+64.0) 
    else:
        return 0.0 

class spline_curve:
    def __init__ (self, which=point_list()):
        self.plist = which 
        self.curve_point = [] 
        self.nb_curve_point = 0 
        self.nb_point = len(self.plist.mylist) 
        self.precision = DEFAULT_PRECISION 
        self.draw_number = True 
        self.draw_rep = True 
        self.rep_point = [] 
    def compute(self):
        if (self.curve_point != []) : self.curve_point=[] 
        if (self.rep_point != []) : self.rep_point=[] 
        self.nb_curve_point = self.precision+1 
        u=1.0
        p = (float(self.nb_point-3.0))/float(self.precision) 
        for i in range(self.nb_curve_point):
            self.curve_point.append(point()) #en remplacement de la fonction new
            tx = 0.0 
            ty = 0.0
            for j in range(1,self.nb_point+1): 
                tb = spline_uniform(j-1,u) 
                tx += tb*self.plist.mylist[j-1].x 
                ty += tb*self.plist.mylist[j-1].y 
            tb = 0 
            u += p 
            self.curve_point[i].x = tx 
            self.curve_point[i].y = ty 
        u=1.0 
        for i in range(self.nb_point-2):
            self.rep_point.append(point()) #en remplacement de la fonction new
            tx = 0.0 
            ty = 0.0 
            tb = 0.00 
            for j in range(1,self.nb_point+1):
                tb = spline_uniform(j-1,u) 
                tx += tb*self.plist.mylist[j-1].x 
                ty += tb*self.plist.mylist[j-1].y 
            tb = 0.0 
            u += 1.0 
            self.rep_point[i].x = tx 
            self.rep_point[i].y = ty 
    def draw(self):
        glColor3f(0.0,0.0,1.0) 
        glBegin(GL_LINE_STRIP) 
        for  i in range(self.nb_curve_point):
            glVertex2f(self.curve_point[i].x, self.curve_point[i].y) 
        glEnd() 
        if (self.draw_number):
            glColor3f(0.0,0.0,0.0) 
            for i in range(self.nb_point):
                glRasterPos2f(self.plist.mylist[i].x - 8.0, self.plist.mylist[i].y + 8.0) 
                ch=repr(int(i)) 
                drawString(ch) 
        if (self.draw_rep):
            glColor3f(1.0,0.0,0.0) 
            glPointSize(3.0) 
            glBegin(GL_POINTS) 
            for  i in range(self.nb_point-2): glVertex2f(self.rep_point[i].x, self.rep_point[i].y) 
            glEnd() 
            glPointSize(4.0) 
    def Inc_Precision(self):  self.precision *= 2.0  
    def Dec_Precision(self):  self.precision = int(ceil(float(self.precision/2.0))) 
    def Toggle_Number(self):
        self.draw_number = not self.draw_number 
        return self.draw_number 
    def Toggle_Rep(self):
        self.draw_rep = not self.draw_rep 
        return self.draw_rep 
    

#==================================================================================================

# COURBE de Bézier 

def factoriel(x): # no comment
    r = 1 
    for  i in range(2, x+1): r*=i 
    return r 

def Berstein(i, n, u): # i ème polynome de Berstein d'ordre n+1 évalué en u (appartenant à 0..1)
    iu = 1.0-u 
    return factoriel(n)/(factoriel(i)*factoriel(n-i))*pow(u,i)*pow(iu,n-i)  # tres lourd en calcul, mais c'est suffisant, et ca reste lisible

class bezier_curve:
    def __init__(self , which=point_list()):
        self.plist = which 
        self.curve_point = [] 
        self.nb_curve_point = 0 
        self.nb_point = len(self.plist.mylist) 
        self.precision = DEFAULT_PRECISION 
        self.draw_tangeante = True 
        self.draw_number = True 
    def compute(self):
        if (self.curve_point != []) :self.curve_point=[] 
        self.nb_curve_point = self.precision+1 
        u=0.0
        p = 1.0/float(self.precision) 
        for i in range(self.nb_curve_point):
            self.curve_point.append(point()) #en remplacement de  new en C++
            tx = 0 
            ty = 0 
            tb = 0 
            for  j in range(self.nb_point):
                tb = Berstein(j, self.nb_point-1, u) 
                tx += tb * self.plist.mylist[j].x 
                ty += tb * self.plist.mylist[j].y 
            u += p 
            self.curve_point[i].x = tx 
            self.curve_point[i].y = ty 
    def draw(self):
        glColor3f(0.0,1.0,0.0) 
        glBegin(GL_LINE_STRIP) 
        for i in range(self.nb_curve_point):  glVertex2f(self.curve_point[i].x, self.curve_point[i].y) 
        glEnd() 
        if (self.draw_tangeante):
            glColor3f(1.0,0.0,0.0) 
            glBegin(GL_LINES) 
            glVertex2f(self.plist.mylist[0].x, self.plist.mylist[0].y) 
            glVertex2f(self.plist.mylist[1].x, self.plist.mylist[1].y) 
            glVertex2f(self.plist.mylist[self.nb_point-1].x, self.plist.mylist[self.nb_point-1].y) 
            glVertex2f(self.plist.mylist[self.nb_point-2].x, self.plist.mylist[self.nb_point-2].y) 
            glEnd() 
        if (self.draw_number):
            glColor3f(0.0,0.0,0.0) 
            for i in range(self.nb_point):
                glRasterPos2f(self.plist.mylist[i].x - 8.0, self.plist.mylist[i].y + 8.0) 
                ch=repr(int(i)) 
                drawString(ch) 
    def Inc_Precision(self) : self.precision *= 2  
    def Dec_Precision(self) : self.precision = int(ceil(float(self.precision/2.0)))  
    def Toggle_Tangeante(self):
        self.draw_tangeante = not self.draw_tangeante 
        return self.draw_tangeante 
    def Toggle_Number(self):
        self.draw_number = not  self.draw_number 
        return self.draw_number 
    

#==============================================================================

# Déclaration des variables globales
# Avec Glut, on a pas trop le choix

pt_list= point_list() 
sl_list=selection()
sweep_list=selection()

mouse_x=100
mouse_y=100
show_bezier = False 
show_spline = False 
show_cat = False 

b_curve = bezier_curve(point_list()) 
s_curve = spline_curve(point_list()) 
c_curve = cat_curve(point_list()) 

last_point_added = -1 

# booléens qui servent pour la gestion de la sélection
left_button_pressed = False 
something_clicked = False  # un point a été sélectionné
point_has_moved = False  # des pts ont été déplacé
ctrl_pressed = False 
shift_pressed = False 

selected = False  # il y a t il une sélection par glissement en cours
sl_x1 = 0.0 
sl_y1 = 0.0 

def drawString (s):
    for i in s:
        glutBitmapCharacter (GLUT_BITMAP_HELVETICA_10, ord(i)) # encore une difference avec le c++, en python il demande le numéro unicode du charactere 

def reshape( w,  h):
    glViewport(0, 0, w, h) 
    glMatrixMode(GL_PROJECTION) 
    glLoadIdentity() 
    gluOrtho2D(0.0, w, 0.0, h) 
    glMatrixMode(GL_MODELVIEW) 
    

def display():
    glClear(GL_COLOR_BUFFER_BIT) 
    pt_list.draw_all_point() 
    if (show_bezier) :b_curve.draw() 
    if (show_spline): s_curve.draw() 
    if (show_cat) :c_curve.draw() 
    
    viewport=glGetIntegerv (GL_VIEWPORT) 
    if (selected) :# affichage de la sélection par glissement
        glBegin(GL_QUADS) 
        glColor4f(0.0,0.0,1.0,0.4) 
        glVertex2f(sl_x1,sl_y1) 
        glVertex2f(mouse_x,sl_y1) 
        glColor4f(0.0,0.0,1.0,0.2) 
        glVertex2f(mouse_x,viewport[3] - mouse_y) 
        glVertex2f(sl_x1,viewport[3] - mouse_y) 
        glEnd() 
        glColor4f(0.0,0.0,1.0,0.8) 
        glBegin(GL_LINE_LOOP) 
        glVertex2f(sl_x1,sl_y1) 
        glVertex2f(mouse_x,sl_y1) 
        glVertex2f(mouse_x,viewport[3] - mouse_y) 
        glVertex2f(sl_x1,viewport[3] - mouse_y) 
        glEnd() 
        glColor4f(0.0,0.0,1.0,1.0) 
    glColor3f(0.0, 0.0, 0.0) 
    glRasterPos2i(5, viewport[3] - 10) 
    pos=repr(mouse_x) 
    drawString(pos) 
    glRasterPos2i(5, viewport[3] - 20) 
    pos=repr(mouse_y) 
    drawString(pos) 
    glutSwapBuffers() 
    glFlush() 

def Mouse( button,  state,  x,  y):
    global pt_list 
    global sl_list
    global sweep_list
    global mouse_x
    global mouse_y
    global show_bezier 
    global show_spline 
    global show_cat 
    global b_curve
    global s_curve
    global c_curve
    global last_point_added 
    # booléens qui servent pour la gestion de la sélection
    global left_button_pressed 
    global something_clicked 
    global point_has_moved 
    global ctrl_pressed 
    global shift_pressed
    global selected 
    global sl_x1 
    global sl_y1 
    
    mouse_x = x 
    mouse_y = y 
    shift_pressed = False 
    ctrl_pressed = False 
    if glutGetModifiers()==GLUT_ACTIVE_SHIFT: # on détect l'appuis sur SHIFT ou CTRL
        shift_pressed = True 
    elif glutGetModifiers()==GLUT_ACTIVE_CTRL:
        ctrl_pressed = True 
    # picking standard d'openGL
    viewport=glGetIntegerv (GL_VIEWPORT) 
    glSelectBuffer(BUFFER_SIZE) # on définit la taille du tampon
    glRenderMode(GL_SELECT)  # on passe en mode sélection
    glInitNames()  # on reset le tampon
    glPushName(10000)  # on y insère un premier élément pour pouvoir utiliser la fonction glLoadName par la suite. Un élément qui n'existe pas.
    # on aura pas 10000 point a l'écran avec ce programme.
    glMatrixMode(GL_PROJECTION) 
    glPushMatrix()  # on sauvergarde la matrice courante de projection
    glLoadIdentity() 
    gluPickMatrix(x, (viewport[3] - y), 5.0, 5.0, viewport)  # On définit une matrice de picking. Cad on réduit la fenetre a un carré de 5x5 pixel centré sur la souris.
    gluOrtho2D(0.0, viewport[2], 0.0, viewport[3])  # matrice de projection 2D
    pt_list.draw_all_point(GL_SELECT)  # on réaffiche tous les points en mode sélection, tous les éléments qui y apparaissent, provoque un hit, et 4 informations par primitives sont placées dans le tampon définie précédemment pas glSelectBuffer.
    # Ici, on ne peut pas sélectionner de segment, donc inutile des les afficher. Seul les points nous intéressent.
    # je me sers de la 4ème information qui correspond au numéro du point, numéro qui est affiché à l'écran losrque l'option est activé.
    # Voir des sites de picking, ou le redbook d'openGL pour d'avantage d'info, sur le tampon.
    glMatrixMode(GL_PROJECTION) 
    glPopMatrix() 
    glFlush() 
    tampon = glRenderMode(GL_RENDER)  # on récupère le tampon. ATTENTION!! on est différent du C++ sur cette ligne
    nb_int= len(tampon)
    if nb_int==0:
        name=[]
    else:
        zmin, zmax, name=tampon[0]
        #print zmin, zmax, tampon,nb_int,len(tampon), len(tampon_provisoire)
    something_clicked = False 
    sl_x1 = mouse_x 
    sl_y1 = float(viewport[3] - mouse_y)  # toutes les opérations viewport[3] - x sont dues a l'inversion des coordonnées glut de openGL

    # toute la suite concerne la gestion de la sélection, sélection par glissement etc ...
    # au cas ou plusieurs objet sont sous le curseur, le premier qui a été tracé est sélectionné,
    # je ne gère pas les objets multiples. Il faudrait étudier les valeurs de profondeur qui sont stockés dans
    # le tampon
    if ((button == GLUT_LEFT_BUTTON)  and  (state == GLUT_DOWN)) :left_button_pressed = True 
    if ((button == GLUT_LEFT_BUTTON)  and  (state == GLUT_UP)): left_button_pressed = False 
    if ((nb_int == 0)  and  (not selected)): # si aucun objet se trouvait sous le curseur ( nb_int = 0 ) et qu'aucune sélection par glissement est en cours
        if ((button == GLUT_LEFT_BUTTON)  and  (state == GLUT_DOWN)   and  (not shift_pressed)):
            if  (not ctrl_pressed):
                sl_list.clear()  # alors on vide la sélection
        glutPostRedisplay() 
        return
    if ((button == GLUT_LEFT_BUTTON)  and  (state == GLUT_DOWN)):# si le bouton gauche de la souris a été pressé
        if (not shift_pressed): sl_list.clear()  # si shift n'est pas presse, on vide la sélection, et on ne selectionnera que le point juste selectionne
        if (not sl_list.find(pt_list.get_point(name[0]))): # si le point sélectionne n'est pas trouve, on l'ajoute a la selection
            sl_list.add_point(pt_list.get_point(name[0])) 
            last_point_added = name[0]  # on mémorise le dernier point ajouté.
        something_clicked = True 
    if ((button == GLUT_LEFT_BUTTON)  and  (state == GLUT_UP)  and  (not selected)  and  (last_point_added != int(name[0]))  and  (sl_list.find(pt_list.get_point(name[0])))  and  (not point_has_moved)): # si le bouton est laché, qu'une sélection par glissement n'est pas activé, et que le point en cours n'est pas celui qui vient d'etre ajouté lors de l'appel précédent de cette fonction. On vérifie que les points n'ont pas bougés.
        sl_list.remove_point(pt_list.get_point(name[0])) 
    elif ((button == GLUT_LEFT_BUTTON)  and  (state == GLUT_UP)  and  (selected)): # si une sélection par glissement est en cours, on la détruit, mais l'ajoute au préalable a la sélection normal.
        sl_list.add_selection(sweep_list) 
    if ((button == GLUT_LEFT_BUTTON)  and  (state == GLUT_UP)): last_point_added = -1  # dans tous les cas, aucun point n'a été sélectionné.
    selected = False 
    point_has_moved = False 
    glutPostRedisplay()   

def MotionMouse( x,  y):
    global pt_list 
    global sl_list
    global sweep_list
    global mouse_x
    global mouse_y
    global show_bezier 
    global show_spline 
    global show_cat 
    global b_curve
    global s_curve
    global c_curve
    global last_point_added 
    # booléens qui servent pour la gestion de la sélection
    global left_button_pressed 
    global something_clicked 
    global point_has_moved 
    global ctrl_pressed 
    global shift_pressed
    global selected 
    global sl_x1 
    global sl_y1 

    
    selected = False  # on réinitialise les booléens qui seront, s'il le faut, remis a True.
    point_has_moved = False 
    if ((left_button_pressed)  and  ((something_clicked) or (ctrl_pressed))) :
        # si on maintient cliqué sur un point, ou si CTRL est pressé (ce qui permet de déplacé les points
        # sans forcément avoir cliqué dessus ce qui est tjs difficile si on veut aller vite), on déplace
        # l'ensemble de la sélection
        sl_list.move(float(x-mouse_x), -float(y-mouse_y)) 
        point_has_moved = True 
        # on recalcule pour un affichage dynamique
        if globals().has_key('b_curve'): b_curve.compute()  #on teste l'existence des variables
        if globals().has_key('s_curve'): s_curve.compute()  #on teste l'existence des variables
        if globals().has_key('c_curve'): c_curve.compute()  #on teste l'existence des variables
    elif ((left_button_pressed)  and  (not something_clicked)  and  (not ctrl_pressed)) :
        # sinon c'est que l'utilisateur déclenche une sélection par glissement
        selected = True 
        # le processus est le meme a part la zone de picking qui correspond au carré de sélection.
        viewport=glGetIntegerv (GL_VIEWPORT) # different du c++
        if ((sl_x1-mouse_x != 0.0)  and  (sl_y1-(viewport[3] - mouse_y) != 0.0)):
            sweep_list.clear() 
            glSelectBuffer(BUFFER_SIZE) 
            glRenderMode(GL_SELECT) 
            glInitNames() 
            glPushName(10000) 
            glMatrixMode(GL_PROJECTION) 
            glPushMatrix() 
            glLoadIdentity() 
            gluPickMatrix((sl_x1+mouse_x)/2.0, (sl_y1+(viewport[3] - mouse_y))/2.0, abs(sl_x1-mouse_x), abs(sl_y1-(viewport[3]-mouse_y)), viewport)  # on détecte tous ce qui se trouve dans la zone de sélection
            gluOrtho2D(0.0, viewport[2], 0.0, viewport[3]) 
            pt_list.draw_all_point(GL_SELECT) 
            glMatrixMode(GL_PROJECTION) 
            glPopMatrix() 
            glFlush() 
            tampon = glRenderMode(GL_RENDER) 
            nb_int= len(tampon)            
            for  hits in tampon:
                zmin, zmax, name=hits
                #print zmin, zmax,name, tampon,nb_int,len(tampon),len(name)
                sweep_list.add_point(pt_list.get_point(name[0]))
                # tous les points sélectionnés sont ajouté a la sélection par glissement (sweep_list)
    mouse_x = x 
    mouse_y = y 
    glutPostRedisplay() 

# gestion des menus de GLUT actionné pour le bouton droit de la souris.
def glut_bezier_menu(i):

    global b_curve

    
    if i==1:
        b_curve.Inc_Precision() 
        b_curve.compute() 
        #break 
    elif i==2:
        b_curve.Dec_Precision() 
        b_curve.compute() 
        #break 
    elif i==3:
        if (b_curve.Toggle_Tangeante()):
            glutChangeToMenuEntry(3, "Masquer tangeantes", 3) 
        else:
            glutChangeToMenuEntry(3, "Afficher tangeantes", 3) 
        #break 
    elif i==4:
        if (b_curve.Toggle_Number()):
            glutChangeToMenuEntry(4, "Masquer numéros", 4) 
        else :
            glutChangeToMenuEntry(4, "Afficher numéros", 4) 
        #break 
    glutPostRedisplay() 
    
   
def glut_spline_menu(i):

    global s_curve

    if i == 1:
        s_curve.Inc_Precision() 
        s_curve.compute() 
        #break 
    elif i== 2:
        s_curve.Dec_Precision() 
        s_curve.compute() 
        #break 
    elif i== 3:
        if (s_curve.Toggle_Number()):
            glutChangeToMenuEntry(3, "Masquer numéros", 3) 
        else :
            glutChangeToMenuEntry(3, "Afficher numéros", 3) 
        #break 
    elif i== 4:
        if (s_curve.Toggle_Rep()) :
            glutChangeToMenuEntry(4, "Masquer repères", 4) 
        else:
            glutChangeToMenuEntry(4, "Afficher repères", 4) 
        #break 
    glutPostRedisplay() 

    

def glut_cat_menu( i):

    global c_curve

    if i == 1:
      c_curve.Inc_Precision() 
      c_curve.compute() 
      #break 
    elif i== 2:
      c_curve.Dec_Precision() 
      c_curve.compute() 
      #break 
    elif i== 3:
      if (c_curve.Toggle_Number()) :
          glutChangeToMenuEntry(3, "Masquer numéros", 3) 
      else :
          glutChangeToMenuEntry(3, "Afficher numéros", 3) 
      #break 
    glutPostRedisplay() 

      
 
def glut_main_menu( i):

    global show_bezier 
    global show_spline 
    global show_cat 
    global b_curve
    global s_curve
    global c_curve

    
    if i == 7:
        del b_curve 
        del s_curve 
        del c_curve 
        exit(0) 
        #break 
    elif i== 6:
        if (show_cat):
            show_cat = not show_cat
            glutChangeToMenuEntry(6, "Masquer courbe Cattmul-rom",6) 
        else :
            show_cat = not show_cat
            glutChangeToMenuEntry(6, "Afficher courbe Cattmul-rom", 6) 
        #break 
    elif i== 5:
        if (show_spline ):
            show_spline = not show_spline
            glutChangeToMenuEntry(5, "Masquer courbe Spline",5) 
        else:
            show_spline = not show_spline
            glutChangeToMenuEntry(5, "Afficher courbe Spline", 5) 
        #break 
    elif i== 4:
        if (show_bezier ) :
            show_bezier = not show_bezier
            glutChangeToMenuEntry(4, "Masquer courbe Bézier", 4) 
        else :
            show_bezier = not show_bezier
            glutChangeToMenuEntry(4, "Afficher courbe Bézier", 4) 
        #break 
    glutPostRedisplay() 

    
def main():
    global pt_list 
    global sl_list
    global sweep_list
    global mouse_x
    global mouse_y
    global show_bezier 
    global show_spline 
    global show_cat 
    global b_curve
    global s_curve
    global c_curve
    global last_point_added 
    # booléens qui servent pour la gestion de la sélection
    global left_button_pressed 
    global something_clicked 
    global point_has_moved 
    global ctrl_pressed 
    global shift_pressed
    global selected 
    global sl_x1 
    global sl_y1 

    pt_list.add_point( point(30.0,30.0)) 
    pt_list.add_point( point(100.0,30.0)) 
    pt_list.add_point( point(200.0,200.0)) 
    pt_list.add_point( point(250.0,200.0)) 
    pt_list.add_point( point(300.0,200.0)) 
    pt_list.add_point( point(400.0,300.0)) 
    pt_list.add_point( point(500.0,300.0)) 
    pt_list.add_point( point(600.0,400.0)) 

    b_curve = bezier_curve(pt_list) 
    b_curve.compute() 

    s_curve = spline_curve(pt_list) 
    s_curve.compute() 

    c_curve = cat_curve(pt_list) 
    c_curve.compute() 

    glutInit(sys.argv) 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA) 
    glutInitWindowSize(SCR_X,SCR_Y) 
    glutInitWindowPosition(100,100) 
    glutCreateWindow("Catmul-Rom") 
    
    # initialisation d'openGL

    glClearColor(1.0, 1.0, 1.0, 0.0) 
    
    glEnable(GL_LINE_SMOOTH) 
    glEnable(GL_BLEND) 
    #glEnable(GL_COLOR) 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
    
    glPointSize(4.0) 
    
    # fonction callback de GLUT

    glutDisplayFunc(display) 
    glutReshapeFunc(reshape) 
    #glutIdleFunc(Idle) 
    glutMouseFunc(Mouse) 
    glutMotionFunc(MotionMouse) 

    # création du menu sous GLUT

    bezier_menu = glutCreateMenu(glut_bezier_menu) 
    glutAddMenuEntry("Précision du calcul x2",1) 
    glutAddMenuEntry("Précision du calcul /2",2) 
    glutAddMenuEntry("Masquer tangeantes",3) 
    glutAddMenuEntry("Masquer numéro", 4) 

    spline_menu = glutCreateMenu(glut_spline_menu) 
    glutAddMenuEntry("Précision du calcul x2",1) 
    glutAddMenuEntry("Précision du calcul /2",2) 
    glutAddMenuEntry("Masquer numéros", 3) 
    glutAddMenuEntry("Masquer repères", 4) 

    cat_menu = glutCreateMenu(glut_cat_menu) 
    glutAddMenuEntry("Précision du calcul x2",1) 
    glutAddMenuEntry("Précision du calcul /2",2) 
    glutAddMenuEntry("Masquer numéros", 3) 

    main_menu = glutCreateMenu(glut_main_menu) 
    glutAddSubMenu("Courbe de Bézier",bezier_menu) 
    glutAddSubMenu("Courbe Spline",spline_menu) 
    glutAddSubMenu("Courbe Cattmulrom",cat_menu) 

    glutAddMenuEntry("Afficher courbe de Bézier", 4) 
    glutAddMenuEntry("Afficher courbe Spline", 5) 
    glutAddMenuEntry("Afficher courbe Cattmulrom", 6) 
    glutAddMenuEntry("Quitter",7) 
    glutAttachMenu(GLUT_RIGHT_BUTTON)  # quel bouton de la souris active le menu.
  
    glutMainLoop() 
    

main()

Conclusion :


Ce code est intéressant non seulement parce qu'on comprends mieux un code en python qu'en c++, mais aussi pour mettre en valeur des différences dans l'opengl python et c++. Exemples:
viewport=glGetIntegerv(GL_VIEWPORT) acquisition du viewport
glSelectBuffer(BUFFER_SIZE) dimensionnement du buffer différent en python qu'en c++
glRenderMode(GL_RENDER) ne retourne pas le nombre de hit mais le buffer
glutBitmapCharacter (GLUT_BITMAP_HELVETICA_10, ord(i)) il fallait le voir celui là!! en c++ il mange du char alors qu'en python il prend l'unicode du charactere, d'où l'utilisation de la fonction ord

Codes Sources

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.