--- /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