diff -r a446351f08c0 -r 50de8e8f44d7 middleware/src/Tracking/Search/Segmenter.cs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/middleware/src/Tracking/Search/Segmenter.cs Thu Mar 29 14:39:21 2012 +0200
@@ -0,0 +1,284 @@
+/*
+* This file is part of the TraKERS\Middleware package.
+*
+* (c) IRI
+*
+* For the full copyright and license information, please view the LICENSE_MIDDLEWARE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : MIDDLEWARE
+ * Sous-Module : Search
+ * Classe : Segmenter
+ *
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ *
+ * Fonctionnalités : Permet d'extraire à la volée les segments du tracé en cours.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Media.Media3D;
+
+namespace Trakers.Tracking.Search
+{
+ public class Segmenter
+ {
+ //Accès à la classe de détection principale pour les paramètres.
+ private KinectMain kinectMain;
+ //Stocke les positions d'une main au cours du temps.
+ private List handPointerHistory;
+ //Point précédent.
+ private Point3D prevPt;
+ //Ratio : on prend 1/ratio points.
+ private int ratio;
+ //Indique le numéro du point actuellement enregistré (pour le ratio).
+ private int currentPointNumber;
+ //Extremums enregistrés parmi les 3 axes pour détecter les changements de sens.
+ private double Xmax, Ymax, Zmax;
+ private double Xmin, Ymin, Zmin;
+ //On établit une distance en nombre de points entre le point actuel l'extremum
+ //local détecté dans les 3 axes (pour copier le segment : points de 0 à id de l'extremum).
+ private int distToXmax, distToYmax, distToZmax;
+ private int distToXmin, distToYmin, distToZmin;
+ //Points critiques.
+ private Point3D minPt, maxPt;
+ //Tendance actuelle du tracé.
+ private bool XtowardRight, YtowardUp, ZtowardFront;
+ //Limites de différences à partir desquelles .
+ private int directionChangeTresholdXY;
+ private float directionChangeTresholdZ;
+
+ /*
+ * Initialisation du segmenter.
+ * Coupe une courbe en deux dès qu'il repère un changement important de trajectoire.
+ */
+ public Segmenter(int _ratio, KinectMain _kinectMain)
+ {
+ kinectMain = _kinectMain;
+ directionChangeTresholdXY = kinectMain.getDirectionChangeTresholdXY();
+ directionChangeTresholdZ = kinectMain.getDirectionChangeTresholdZ();
+ handPointerHistory = new List();
+ ratio = _ratio;
+ currentPointNumber = 1;
+ prevPt = new Point3D(0, 0, 0);
+
+ Xmax = Ymax = Zmax = Xmin = Ymin = Zmin = -1;
+ distToXmax = distToYmax = distToZmax = distToXmin = distToYmin = distToZmin = -1;
+ }
+
+ /*
+ * Getters et setters.
+ */
+ public void SetRatio(int _ratio)
+ {
+ ratio = _ratio;
+ }
+ public void SetDirectionChangeTresholdXY(int _directionChangeTresholdXY)
+ {
+ directionChangeTresholdXY = _directionChangeTresholdXY;
+ }
+ public void SetDirectionChangeTresholdZ(float _directionChangeTresholdZ)
+ {
+ directionChangeTresholdZ = _directionChangeTresholdZ;
+ }
+
+ public int GetRatio()
+ {
+ return ratio;
+ }
+ public int SetDirectionChangeTresholdXY()
+ {
+ return directionChangeTresholdXY;
+ }
+ public float SetDirectionChangeTresholdZ()
+ {
+ return directionChangeTresholdZ;
+ }
+
+ /*
+ * On charge tous les paramètres d'un coup.
+ */
+ public void setParams(int _ratio, int _directionChangeTresholdXY, float _directionChangeTresholdZ)
+ {
+ ratio = _ratio;
+ directionChangeTresholdXY = _directionChangeTresholdXY;
+ directionChangeTresholdZ = _directionChangeTresholdZ;
+ }
+
+ /*
+ * Enregistre le point passé en paramètre d'après le ratio.
+ */
+ public void RecordPoint(Point3D pt)
+ {
+ //Indique l'ID du point à couper.
+ int whereToCut;
+ //Si le ratio est excédé, on peut enregistrer.
+ if (currentPointNumber > ratio)
+ currentPointNumber = 1;
+
+ //Si le point précédent est à une position différente du point actuel.
+ if(prevPt.X != pt.X || prevPt.Y != pt.Y || prevPt.Z != pt.Z)
+ {
+ //Si le numéro est 1 (début ou ratio atteint), on enregistre.
+ if(currentPointNumber == 1)
+ handPointerHistory.Add(pt);
+
+ //Si le point précédent a été initialisé avec un vrai point.
+ if (prevPt.X > 0 && prevPt.Y > 0 && prevPt.Z > 0)
+ {
+ //Appel aux detecteurs d'extremums.
+ if ((whereToCut = DetectDirectionChangeAtXAxis(pt)) > 0)
+ Segment(whereToCut);
+ else if((whereToCut = DetectDirectionChangeAtYAxis(pt)) > 0)
+ Segment(whereToCut);
+ else if ((whereToCut = DetectDirectionChangeAtZAxis(pt)) > 0)
+ Segment(whereToCut);
+ }
+ //On met à jour le point précédent.
+ prevPt = pt;
+ //On passe au numéro suivant (jusqu'à atteindre le ration plus tard).
+ currentPointNumber++;
+ }
+ }
+
+ /*
+ * Détecte un changement de sens (extremum) dans l'axe X.
+ */
+ public int DetectDirectionChangeAtXAxis(Point3D pt)
+ {
+ //ID où couper en cas d'extremum.
+ int whereToCut = -1;
+
+ //Mise à jour des extremums.
+ if (Xmax == -1 || Xmax < pt.X)
+ {
+ //Si le point est plus grand en X que Xmax, alors il est remplacé et on réinitialise la
+ //distance au dernier maximum en X.
+ Xmax = pt.X;
+ maxPt = pt;
+ distToXmax = 0;
+ }
+ else
+ distToXmax++;
+ if (Xmin == -1 || Xmin > pt.X)
+ {
+ //Si le point est plus petit en X que Xmin, alors il est remplacé et on réinitialise la
+ //distance au dernier minimum en X.
+ Xmin = pt.X;
+ minPt = pt;
+ distToXmin = 0;
+ }
+ else
+ distToXmin++;
+
+ //Si X max est plus grand que la position actuelle additionnée du seuil
+ //et que l'extremum n'est pas le premier point sauvegardé.
+ if (Xmax > pt.X + directionChangeTresholdXY && maxPt != handPointerHistory.First())
+ whereToCut = currentPointNumber - distToXmax;
+ //Si X min est plus petit que la position actuelle à laquelle on a retiré le seuil
+ //et que l'extremum n'est pas le premier point sauvegardé.
+ if (Xmin < pt.X - directionChangeTresholdXY && minPt != handPointerHistory.First())
+ whereToCut = currentPointNumber - distToXmin;
+
+ return whereToCut;
+ }
+
+ /*
+ * Détecte un changement de sens (extremum) dans l'axe Y.
+ */
+ public int DetectDirectionChangeAtYAxis(Point3D pt)
+ {
+ //ID où couper en cas d'extremum.
+ int whereToCut = -1;
+
+ //Mise à jour des extremums.
+ if (Ymax == -1 || Ymax < pt.Y)
+ {
+ //Si le point est plus grand en Y que Ymax, alors il est remplacé et on réinitialise la
+ //distance au dernier maximum en Y.
+ Ymax = pt.Y;
+ maxPt = pt;
+ distToYmax = 0;
+ }
+ else
+ distToYmax++;
+ if (Ymin == -1 || Ymin > pt.Y)
+ {
+ //Si le point est plus petit en Y que Ymin, alors il est remplacé et on réinitialise la
+ //distance au dernier minimum en Y.
+ Ymin = pt.Y;
+ minPt = pt;
+ distToYmin = 0;
+ }
+ else
+ distToYmin++;
+
+ //Si Y max est plus grand que la position actuelle additionnée du seuil
+ //et que l'extremum n'est pas le premier point sauvegardé.
+ if (Ymax > pt.Y + directionChangeTresholdXY && maxPt != handPointerHistory.First())
+ whereToCut = currentPointNumber - distToYmax;
+ //Si Y min est plus petit que la position actuelle à laquelle on a retiré le seuil
+ //et que l'extremum n'est pas le premier point sauvegardé.
+ if (Ymin < pt.Y - directionChangeTresholdXY && minPt != handPointerHistory.First())
+ whereToCut = currentPointNumber - distToYmin;
+
+ return whereToCut;
+ }
+
+ /*
+ * Détecte un changement de sens (extremum) dans l'axe Z.
+ */
+ public int DetectDirectionChangeAtZAxis(Point3D pt)
+ {
+ //ID où couper en cas d'extremum.
+ int whereToCut = -1;
+
+ //Mise à jour des extremums.
+ if (Zmax == -1 || Zmax < pt.Z)
+ {
+ //Si le point est plus grand en Z que Ymax, alors il est remplacé et on réinitialise la
+ //distance au dernier maximum en Z.
+ Zmax = pt.Z;
+ maxPt = pt;
+ distToZmax = 0;
+ }
+ else
+ distToZmax++;
+ if (Zmin == -1 || Zmin > pt.Z)
+ {
+ //Si le point est plus petit en Z que Zmin, alors il est remplacé et on réinitialise la
+ //distance au dernier minimum en Z.
+ Zmin = pt.Z;
+ minPt = pt;
+ distToZmin = 0;
+ }
+ else
+ distToZmin++;
+
+ //Si Z max est plus grand que la position actuelle additionnée du seuil
+ //et que l'extremum n'est pas le premier point sauvegardé.
+ if (Zmax > pt.Z + directionChangeTresholdXY && maxPt != handPointerHistory.First())
+ whereToCut = currentPointNumber - distToZmax;
+ //Si Z min est plus petit que la position actuelle à laquelle on a retiré le seuil
+ //et que l'extremum n'est pas le premier point sauvegardé.
+ if (Zmin < pt.Z - directionChangeTresholdXY && minPt != handPointerHistory.First())
+ whereToCut = currentPointNumber - distToZmin;
+
+ return whereToCut;
+ }
+
+ /*
+ * Découpe le tracé en cours en segment allant du premier point au premier extremum trouvé.
+ */
+ public void Segment(int whereToCut)
+ {
+ handPointerHistory.RemoveRange(0, whereToCut);
+ currentPointNumber -= whereToCut;
+ }
+ }
+}