diff -r 8393d3473b98 -r 0e29ae4568a0 front_idill/src/search/js/curvesDetector.js --- /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 +* +* 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