front_idill/src/search/js/curvesDetector.js
changeset 45 0e29ae4568a0
child 46 9d7a2aa112fb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/src/search/js/curvesDetector.js	Thu Jul 05 16:04:33 2012 +0200
@@ -0,0 +1,341 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : curvesDetector.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Détecteur de courbes de recherche, appelé par la classe de création du canvas de recherche.
+ */
+
+/*
+ * Détecteur de courbes (lignes droites, arcs de cercles et cercles).
+*/
+function curvesDetector(divisions, sizeTreshold, dictionary, mosaic)
+{
+	//Précision de la détection de direction en divisions (par défaut 12, selon une modélisation horaire et non mathématique).
+	this.divisions = divisions;
+	//Taille limite pour un segment/courbe pour être considéré comme tel en px.
+	this.sizeTreshold = sizeTreshold;
+	
+	this.dictionary = dictionary;
+	
+	this.mosaic = mosaic;
+	
+	//Code actuel généré. Il représente la structure de la courbe de recherche.
+	this.actualCode = '';
+	
+	this.joints = [];
+	this.jInc = 0;
+	
+	//Longueur totale de la courbe.
+	this.MPTotalDist = 0;
+	this.SPTotalDist = 0;
+	//Longueur de la partie actuelle (après début ou changement de direction).
+	this.MPActualDist = 0;
+	this.SPActualDist = 0;
+	//Angles actuels.
+	this.MPActualAngle = -1;
+	this.SPActualAngle = -1;
+	
+	//Centre du repère du pointeur principal.
+	this.MPrepX;
+	this.MPrepY;
+	//Centre du repère du pointeur secondaire.
+	this.SPrepX;
+	this.SPrepY;
+	
+	//Coordonnées actuelles du/des pointeur/s.
+	this.MPx = 0;
+	this.MPy = 0;
+	this.SPx = 0;
+	this.SPy = 0;
+	//Coordonnées précédentes du/des pointeur/s.
+	this.MPpx = 0;
+	this.MPpy = 0;
+	this.SPpx = 0;
+	this.SPpy = 0;
+	
+	//Si les paramètres sont incorrects, on leur donne une valeur par défaut.
+	if(isNaN(divisions) || divisions < 1 || divisions > 360)
+	{
+		this.divisions = 12;
+	}
+	if(sizeTreshold < 1)
+	{
+		sizeTreshold = 30;
+	}
+}
+
+/*
+ * Reinit les paramètres du détecteur.
+*/
+curvesDetector.prototype.reinit = function()
+{
+	this.MPrepX = 0;
+	this.MPrepY = 0;
+	this.MPpx = 0;
+	this.MPpy = 0;
+	this.MPActualAngle = -1;
+	this.SPActualAngle = -1;
+	this.actualCode = '';
+	
+	for(var i = 0 ; i < this.joints.length ; i++)
+	{
+		if(this.joints[i])
+		{
+			this.joints[i].remove();
+		}
+	}
+	
+	this.jInc = 0;
+	this.MPActualDist = 0;
+	this.MPTotalDist = 0;
+}
+
+/*
+ * Met à jour les positions des pointeurs
+*/
+curvesDetector.prototype.updatePos = function(mpx, mpy, spx, spy)
+{
+	//On met à jour les coordonnées récentes.
+	this.MPx = mpx;
+	this.MPy = mpy;
+	
+	//Si les coordonnées précédentes n'existent pas, alors on les met à jour.
+	if(!this.MPpx)
+	{
+		this.MPpx = mpx;
+	}
+	if(!this.MPpy)
+	{
+		this.MPpy = mpy;
+	}
+	if(!this.MPrepX)
+	{
+		this.MPrepX = mpx;
+	}
+	if(!this.MPrepY)
+	{
+		this.MPrepY = mpy;
+	}
+	
+	//Si on a un second pointeur.
+	if(spx && spy)
+	{
+		//On met les coordonnées à jour.
+		this.SPx = spx;
+		this.SPy = spy;
+		
+		//Si les coordonnées précédentes n'existent pas, alors on les met à jour.
+		if(!this.SPpx)
+		{
+			this.SPpx = spx;
+		}
+		if(!this.SPpy)
+		{
+			this.SPpy = spy;
+		}
+	}
+	
+	this.updateDists();
+}
+
+/*
+ * Met à jour les distances parcourues.
+*/
+curvesDetector.prototype.updateDists = function()
+{
+	var foundGestures;
+	
+	//Si on a de quoi calculer les distances.
+	if(this.MPx && this.MPy && this.MPpx && this.MPpy && this.MPrepX && this.MPrepY)
+	{
+		var MPDist = Math.floor(Math.sqrt((this.MPx - this.MPpx) * (this.MPx - this.MPpx) + (this.MPy - this.MPpy) * (this.MPy - this.MPpy)));
+		this.MPTotalDist += MPDist;
+		this.MPActualDist += MPDist;
+		
+		var MPCurrentA = -1;
+		
+		if(MPDist > 0)
+		{
+			MPCurrentA = this.currentAngle(this.MPrepX, this.MPrepY, this.MPx, this.MPy);
+			// console.log(MPCurrentA);//, this.MPActualDist);
+		}
+		
+		if(this.MPActualDist > this.sizeTreshold && MPCurrentA != -1)
+		{
+			console.log(this.MPActualAngle, MPCurrentA, this.MPActualAngle != -1, this.MPActualAngle != MPCurrentA);
+			if(this.MPActualAngle == -1 || this.MPActualAngle != MPCurrentA)
+			{
+				this.MPActualAngle = MPCurrentA;
+				this.actualCode += 'D' + MPCurrentA;
+				this.mosaic.actualCode = this.actualCode;
+				
+				foundGestures = this.codeToGestures(this.actualCode);
+				
+				console.log(+this.jInc+1, this.MPActualDist);
+				console.log(this.actualCode);
+				console.log(foundGestures);
+				
+				if(foundGestures.length == 0 || foundGestures.split(';').length != 1)
+				{
+					console.log('many curves');
+					this.mosaic.curvesGesturesFound = true;
+					$('.notifications').remove();
+					this.mosaic.curvesGestures(foundGestures);
+				}
+				else
+				{
+					// console.log(this.mosaic.currentMode);
+					this.mosaic.currentSearchGesture = foundGestures;
+					
+					if(this.mosaic.currentMode == "SEARCH" && this.mosaic.playerIsReady)
+					{
+						this.mosaic.player.widgets[0].searchByGesture(foundGestures);
+						this.mosaic.isCurrentlyInASearchByGesture = this.mosaic.player.widgets[0].isCurrentlyInASearchByGesture;
+						
+						$('.notifications').remove();
+						this.mosaic.searchGesture(foundGestures, 'valid');
+						
+						foundGestures = '';
+						this.mosaic.curvesGesturesFound = false;
+						
+						this.mosaic.isSearchByCurvesOn = false;
+						this.mosaic.leaveSearch();
+					}
+					else if(this.mosaic.currentMode == "FILTER")
+					{
+						if(this.mosaic.isMosaicFiltered)
+						{
+							console.log('1 curve : ' + foundGestures);
+							$('.notifications').remove();
+							this.mosaic.filterSearchedType = foundGestures;
+							this.mosaic.filterGesture(foundGestures, 'valid');
+							this.mosaic.searchFilter(foundGestures);
+							foundGestures = '';
+							this.mosaic.curvesGesturesFound = false;
+							
+							this.mosaic.isSearchByCurvesOn = false;
+							this.mosaic.leaveSearch();
+						}
+					}
+				}
+				
+				this.MPActualDist = 0;
+				this.jInc++
+			}
+			else
+			{
+				this.MPrepX = this.MPpx;
+				this.MPrepY = this.MPpy;
+				
+				if(this.joints[this.jInc])
+				{
+					this.joints[this.jInc].remove();
+				}
+				this.joints[this.jInc] = new paper.Path.Circle(new paper.Point(this.MPrepX, this.MPrepY), 10);
+				this.joints[this.jInc].strokeColor = 'black';
+				this.joints[this.jInc].fillColor = 'green';
+			}
+			
+			if(this.MPActualAngle == -1)
+			{
+				this.MPActualAngle = MPCurrentA;
+			}
+		}
+		
+		//On met à jour les coordonnées précédentes.
+		if(this.MPpx != this.MPx)
+		{
+			this.MPpx = this.MPx;
+		}
+		if(this.MPpy != this.MPy)
+		{
+			this.MPpy = this.MPy;
+		}
+	}
+	//Idem au cas où on aurait un deuxième pointeur.
+	if(this.SPx && this.SPy && this.SPpx && this.SPpy)
+	{
+		var SPDist = Math.floor(Math.sqrt((this.SPx - this.SPpx) * (this.SPx - this.SPpx) + (this.SPy - this.SPpy) * (this.SPy - this.SPpy)));
+		this.SPTotalDist += SPDist;
+		this.SPActualDist += SPDist;
+		
+		if(SPDist > 0)
+		{
+			this.currentAngle(this.SPpx, this.SPpy, this.SPx, this.SPy);
+		}
+		
+		//On met à jour les coordonnées précédentes.
+		if(this.SPpx != this.SPx)
+		{
+			this.SPpx = this.SPx;
+		}
+		if(this.SPpy != this.SPy)
+		{
+			this.SPpy = this.SPy;
+		}
+	}
+}
+
+/*
+ * Renvoie les noms de gestures du dictionnaire qui ont un code qui commence par le code en entrée.
+*/
+curvesDetector.prototype.codeToGestures = function(code)
+{
+	//Variable qui va stocker tous les noms trouvés.
+	var retNames = '';
+	
+	//Pour tout le dictionnaire.
+	for(var i = 0 ; i < this.dictionary.length ; i++)
+	{
+		//Pour touts les codes de chaque gesture du dictionnaire.
+		for(var j = 0 ; j < this.dictionary[i].codes.length ; j++)
+		{
+			//Si le code en entrée est une partie début d'un des codes.
+			if(this.dictionary[i].codes[j].indexOf(code) == 0)
+			{
+				//On ajoute le nom de la gesture et on passe à la gesture suivante.
+				retNames += this.dictionary[i].name + ';';
+				break;
+			}
+		}
+	}
+	//Comme on sépare chaque nom par un ;, il faut supprimer le dernier si au moins un nom a été trouvé.
+	if(retNames.length > 0)
+	{
+		retNames = retNames.substring(0, retNames.length-1);
+	}
+	
+	//On renvoit les noms.
+	return retNames;
+}
+
+/*
+ * Calcule l'angle emprunté par le morceau de segment actuel. On prend A va vers B.
+*/
+curvesDetector.prototype.currentAngle = function(xa, ya, xb, yb)
+{
+	//On calcule l'angle de la droite AB et des abscisses, et on effectue une rotation de 90° vers la gauche.
+	var angleRad = Math.atan2((ya - yb), (xa - xb)) - Math.PI / 2;
+	//On traduit les radians en divisions en passant de [-PI/2 ; PI/2] à [0 ; divisions - 1].
+	var angleDiv = Math.floor((angleRad > 0 ? angleRad : (2*Math.PI + angleRad)) * this.divisions / (2*Math.PI));
+	
+	//L'angle initial est 0.
+	if(angleDiv == this.divisions)
+	{
+		angleDiv = 0;
+	}
+	
+	return angleDiv;
+}
\ No newline at end of file