User Tools

Site Tools


alelievre:homework_2
Critères & points attribués (/10)
Rappel du contexte 6
Résultats 10
Qualité du code (commentaires, structures utilisées, …) 8
Animation du dessin 9
Explication en dehors du code 6
Total (/50) 41

B.P. : Le réglage de la vitesse d'animation n'est pas simple. Votre code n'est pas trop commenté mais sa structure fait qu'il est facile à lire. Vos commentaires en dehors du code sont légers.

Homework 2 : Icicle plot algorithm with Tulip

L'objectif de ce travail était d'implémenter l'algorithme icicle plot. A partir d'un arbre généré aléatoirement sous Tulip, l'arbre devait être représenté sous la forme d'un icicle plot en animant la transition à l'aide d'un script Python. Dans l'icicle plot, les noeuds sont représentés sous forme rectangulaire, leurs tailles et position déterminent leur position dans l'arbre. La racine est le rectangle le plus large et est situé a la base, ses fils sont représentés en dessous et la somme des tailles des fils est égale à celle du père. L'arbre est parcouru comme dans l'algorithme de calcul de l'arbre couvrant, les positions (viewLayout)et les tailles (viewSize) des noeuds sont calculées en fonction de celles de leur père. Par exemple, si un noeud a deux fils, la largeur des fils sera la moitié de la largeur du père et les fils seront positionnés exactement sous leur père. Pour créer une animation de transition, chaque noeud augmente sa taille de pixel en pixel jusqu'a ce que sa taille soit celle désirée (fonction agrandirNoeud), il se deplace de la même manière suivant l'axe x puis l'axe y (fonction bougerNoeud). La visualisation est mise à jour plusieurs fois lors de ces changements. Ceci permet de visualiser l'agrandissment et le déplacement des noeuds. Une couleur différente a été utilisée (viewColor) à chaque niveau de l'arbre pour mieux différencier les noeuds adjacents. Dans cet algorithme, on ne prend pas en compte des arêtes pondérées. On pourrait le faire en calculant la taille des fils proportionnelement au poids de l'arête les reliant au père.

Charger un arbre aléatoire (random general tree), puis appliquer ce script à cet arbre. Fichier :

# Powered by Python 2.7

# To cancel the modifications performed by the script
# on the current graph, click on the undo button.

# Some useful keyboards shortcuts : 
#   * Ctrl + D : comment selected lines.
#   * Ctrl + Shift + D  : uncomment selected lines.
#   * Ctrl + I : indent selected lines.
#   * Ctrl + Shift + I  : unindent selected lines.
#   * Ctrl + Return  : run script.
#   * Ctrl + F  : find selected text.
#   * Ctrl + R  : replace selected text.
#   * Ctrl + Space  : show auto-completion dialog.

from tulip import *

# the updateVisualization(centerViews = True) function can be called
# during script execution to update the opened views

# the pauseScript() function can be called to pause the script execution.
# To resume the script execution, you will have to click on the "Run script " button.

# the runGraphScript(scriptFile, graph) function can be called to launch another edited script on a tlp.Graph object.
# The scriptFile parameter defines the script name to call (in the form [a-zA-Z0-9_]+.py)

# the main(graph) function must be defined 
# to run the script on the current graph


	
class IciclePlot():
	def __init__(self, graph):
		self.viewLayout =  graph.getLayoutProperty("viewLayout")
		self.select =  graph.getBooleanProperty("viewSelection")
		self.viewColor =  graph.getColorProperty("viewColor")
		self.viewShape =  graph.getIntegerProperty("viewShape")
		self.viewSize =  graph.getSizeProperty("viewSize")
		self.viewLabel =  graph.getStringProperty("viewLabel")
		self.viewLayout =  graph.getLayoutProperty("viewLayout")
		self.viewBorderColor =  graph.getColorProperty("viewBorderColor")
		self.graph = graph
		self.height = 100
		self.blue = tlp.Color(0,150,250)
		self.white= tlp.Color(255,255,255)
	
	#fonction pour animer le changement de coordonnes d'un noeud
	def bougerNoeud(self,n,x,y):
		nx=int(self.viewLayout[n].getX())
		ny=int(self.viewLayout[n].getY())
		dx=int(nx-x)
		dy=int(ny-y)
		while int(nx)!=x:
			self.viewLayout[n]=tlp.Coord(nx,ny,0)
			if dx<0:
				nx+=1
			else:
				nx-=1
			if int(nx)%5==0:
				updateVisualization(centerViews = True)
		updateVisualization(centerViews = True)
		while int(ny)!=y:
			self.viewLayout[n]=tlp.Coord(nx,ny,0)
			if dy<0:
				ny+=1
			else:
				ny-=1
			if int(ny)%5==0:
				updateVisualization(centerViews = True)
		updateVisualization(centerViews = True)
	
	# Focntion pour animer le changement de taille d'un noeud
	def agrandirNoeud(self,n,x,y):
		nx=0
		ny=0
		while (ny!=y or nx!=x): 
			if nx!=x:
				nx+=1		
			if ny!=y:
				ny+=1
			self.viewSize[n]=tlp.Size(nx,ny,0)
			updateVisualization(centerViews = True)
		updateVisualization(centerViews = True)	
		
		
	def run(self): 
		# Recherche de la racine de l'arbre, modification de sa taille, couleur, forme
		root = self.graph.getSource()
		widthRoot = self.graph.numberOfNodes()*30
		self.viewColor[root] = self.blue
		self.viewShape[root] = tlp.NodeShape.Square
		self.agrandirNoeud(root,widthRoot,self.height)
		self.select.setNodeValue(root,True)
		#self.viewLabel[root] = "Node " + str(root.id)
		self.viewBorderColor[root] = self.white

		#Parcours de l'arbre
		pile = []
		pile.append(root)
    		while (pile):
    			s = pile.pop()
    			fs=0 # nombre de fils de s
    			for v in graph.getInOutNodes(s):
    				if self.select.getNodeValue(v)==False:
    					fs+=1
    			if fs>0:
    				x = int(self.viewLayout[s].getX()-(self.viewSize[s].getW()/2)+(self.viewSize[s].getW()/(2*fs)))
    				y = int(self.viewLayout[s].getY()-self.height)
    			for v in graph.getInOutNodes(s):
    				if self.select.getNodeValue(v)==False:
    					pile.append(v)
    					if fs>0: 
    						wv = int((self.viewSize[s].getW())/fs) # calcul de la largeur de v
    					else :
    						wv = int(viewSize[s].getW())
    					#modification de la taille et des coordonnees
    					self.viewColor[v] = tlp.Color(self.viewColor[s].getR()+10,self.viewColor[s].getG()-10,self.viewColor[s].getB()-10)
    					self.viewShape[v] = tlp.NodeShape.Square
    					self.agrandirNoeud(v,int(wv),int(self.height))
    					self.bougerNoeud(v,int(x),int(y))
    					updateVisualization(centerViews = True)
    					x+=wv
    					self.select.setNodeValue(v,True)
    					#self.viewLabel[v] = "Node " + str(v.id)
    					self.viewBorderColor[v] = self.white
    		self.select.setAllNodeValue(False)
    		
# Il faut creer un arbre avant de pouvoir lancer le script
def main(graph): 
	ic = IciclePlot(graph)
	ic.run()
/net/html/perso/melancon/Visual_Analytics_Course/data/pages/alelievre/homework_2.txt · Last modified: 2012/10/22 16:57 by bpinaud