middleware/src/Tracking/Search/Segmenter.cs
changeset 13 50de8e8f44d7
equal deleted inserted replaced
12:a446351f08c0 13:50de8e8f44d7
       
     1 /*
       
     2 * This file is part of the TraKERS\Middleware package.
       
     3 *
       
     4 * (c) IRI <http://www.iri.centrepompidou.fr/>
       
     5 *
       
     6 * For the full copyright and license information, please view the LICENSE_MIDDLEWARE
       
     7 * file that was distributed with this source code.
       
     8 */
       
     9 
       
    10 /*
       
    11  * Projet : TraKERS
       
    12  * Module : MIDDLEWARE
       
    13  * Sous-Module : Search
       
    14  * Classe : Segmenter
       
    15  * 
       
    16  * Auteur : alexandre.bastien@iri.centrepompidou.fr
       
    17  * 
       
    18  * Fonctionnalités : Permet d'extraire à la volée les segments du tracé en cours.
       
    19  */
       
    20 
       
    21 using System;
       
    22 using System.Collections.Generic;
       
    23 using System.Linq;
       
    24 using System.Text;
       
    25 using System.Windows.Media.Media3D;
       
    26 
       
    27 namespace Trakers.Tracking.Search
       
    28 {
       
    29     public class Segmenter
       
    30     {
       
    31         //Accès à la classe de détection principale pour les paramètres.
       
    32         private KinectMain kinectMain;
       
    33         //Stocke les positions d'une main au cours du temps.
       
    34         private List<Point3D> handPointerHistory;
       
    35         //Point précédent.
       
    36         private Point3D prevPt;
       
    37         //Ratio : on prend 1/ratio points.
       
    38         private int ratio;
       
    39         //Indique le numéro du point actuellement enregistré (pour le ratio).
       
    40         private int currentPointNumber;
       
    41         //Extremums enregistrés parmi les 3 axes pour détecter les changements de sens.
       
    42         private double Xmax, Ymax, Zmax;
       
    43         private double Xmin, Ymin, Zmin;
       
    44         //On établit une distance en nombre de points entre le point actuel l'extremum 
       
    45         //local détecté dans les 3 axes (pour copier le segment : points de 0 à id de l'extremum).
       
    46         private int distToXmax, distToYmax, distToZmax;
       
    47         private int distToXmin, distToYmin, distToZmin;
       
    48         //Points critiques.
       
    49         private Point3D minPt, maxPt;
       
    50         //Tendance actuelle du tracé.
       
    51         private bool XtowardRight, YtowardUp, ZtowardFront;
       
    52         //Limites de différences à partir desquelles .
       
    53         private int directionChangeTresholdXY;
       
    54         private float directionChangeTresholdZ;
       
    55 
       
    56         /*
       
    57         *  Initialisation du segmenter.
       
    58         *  Coupe une courbe en deux dès qu'il repère un changement important de trajectoire.
       
    59         */
       
    60         public Segmenter(int _ratio, KinectMain _kinectMain)
       
    61         {
       
    62             kinectMain = _kinectMain;
       
    63             directionChangeTresholdXY = kinectMain.getDirectionChangeTresholdXY();
       
    64             directionChangeTresholdZ = kinectMain.getDirectionChangeTresholdZ();
       
    65             handPointerHistory = new List<Point3D>();
       
    66             ratio = _ratio;
       
    67             currentPointNumber = 1;
       
    68             prevPt = new Point3D(0, 0, 0);
       
    69 
       
    70             Xmax = Ymax = Zmax = Xmin = Ymin = Zmin = -1;
       
    71             distToXmax = distToYmax = distToZmax = distToXmin = distToYmin = distToZmin = -1;
       
    72         }
       
    73 
       
    74         /*
       
    75          * Getters et setters.
       
    76          */
       
    77         public void SetRatio(int _ratio)
       
    78         {
       
    79             ratio = _ratio;
       
    80         }
       
    81         public void SetDirectionChangeTresholdXY(int _directionChangeTresholdXY)
       
    82         {
       
    83             directionChangeTresholdXY = _directionChangeTresholdXY;
       
    84         }
       
    85         public void SetDirectionChangeTresholdZ(float _directionChangeTresholdZ)
       
    86         {
       
    87             directionChangeTresholdZ = _directionChangeTresholdZ;
       
    88         }
       
    89 
       
    90         public int GetRatio()
       
    91         {
       
    92             return ratio;
       
    93         }
       
    94         public int SetDirectionChangeTresholdXY()
       
    95         {
       
    96             return directionChangeTresholdXY;
       
    97         }
       
    98         public float SetDirectionChangeTresholdZ()
       
    99         {
       
   100             return directionChangeTresholdZ;
       
   101         }
       
   102 
       
   103         /*
       
   104          * On charge tous les paramètres d'un coup.
       
   105          */
       
   106         public void setParams(int _ratio, int _directionChangeTresholdXY, float _directionChangeTresholdZ)
       
   107         {
       
   108             ratio = _ratio;
       
   109             directionChangeTresholdXY = _directionChangeTresholdXY;
       
   110             directionChangeTresholdZ = _directionChangeTresholdZ;
       
   111         }
       
   112 
       
   113         /*
       
   114          * Enregistre le point passé en paramètre d'après le ratio.
       
   115          */
       
   116         public void RecordPoint(Point3D pt)
       
   117         {
       
   118             //Indique l'ID du point à couper.
       
   119             int whereToCut;
       
   120             //Si le ratio est excédé, on peut enregistrer.
       
   121             if (currentPointNumber > ratio)
       
   122                 currentPointNumber = 1;
       
   123             
       
   124             //Si le point précédent est à une position différente du point actuel.
       
   125             if(prevPt.X != pt.X || prevPt.Y != pt.Y || prevPt.Z != pt.Z)
       
   126             {
       
   127                 //Si le numéro est 1 (début ou ratio atteint), on enregistre.
       
   128                 if(currentPointNumber == 1)
       
   129                     handPointerHistory.Add(pt);
       
   130 
       
   131                 //Si le point précédent a été initialisé avec un vrai point.
       
   132                 if (prevPt.X > 0 && prevPt.Y > 0 && prevPt.Z > 0)
       
   133                 {
       
   134                     //Appel aux detecteurs d'extremums.
       
   135                     if ((whereToCut = DetectDirectionChangeAtXAxis(pt)) > 0)
       
   136                         Segment(whereToCut);
       
   137                     else if((whereToCut = DetectDirectionChangeAtYAxis(pt)) > 0)
       
   138                         Segment(whereToCut);
       
   139                     else if ((whereToCut = DetectDirectionChangeAtZAxis(pt)) > 0)
       
   140                         Segment(whereToCut);
       
   141                 }
       
   142                 //On met à jour le point précédent.
       
   143                 prevPt = pt;
       
   144                 //On passe au numéro suivant (jusqu'à atteindre le ration plus tard).
       
   145                 currentPointNumber++;
       
   146             }
       
   147         }
       
   148 
       
   149         /*
       
   150          * Détecte un changement de sens (extremum) dans l'axe X.
       
   151          */
       
   152         public int DetectDirectionChangeAtXAxis(Point3D pt)
       
   153         {
       
   154             //ID où couper en cas d'extremum.
       
   155             int whereToCut = -1;
       
   156 
       
   157             //Mise à jour des extremums.
       
   158             if (Xmax == -1 || Xmax < pt.X)
       
   159             {
       
   160                 //Si le point est plus grand en X que Xmax, alors il est remplacé et on réinitialise la
       
   161                 //distance au dernier maximum en X.
       
   162                 Xmax = pt.X;
       
   163                 maxPt = pt;
       
   164                 distToXmax = 0;
       
   165             }
       
   166             else
       
   167                 distToXmax++;
       
   168             if (Xmin == -1 || Xmin > pt.X)
       
   169             {
       
   170                 //Si le point est plus petit en X que Xmin, alors il est remplacé et on réinitialise la
       
   171                 //distance au dernier minimum en X.
       
   172                 Xmin = pt.X;
       
   173                 minPt = pt;
       
   174                 distToXmin = 0;
       
   175             }
       
   176             else
       
   177                 distToXmin++;
       
   178 
       
   179             //Si X max est plus grand que la position actuelle additionnée du seuil
       
   180             //et que l'extremum n'est pas le premier point sauvegardé.
       
   181             if (Xmax > pt.X + directionChangeTresholdXY && maxPt != handPointerHistory.First())
       
   182                 whereToCut = currentPointNumber - distToXmax;
       
   183             //Si X min est plus petit que la position actuelle à laquelle on a retiré le seuil
       
   184             //et que l'extremum n'est pas le premier point sauvegardé.
       
   185             if (Xmin < pt.X - directionChangeTresholdXY && minPt != handPointerHistory.First())
       
   186                 whereToCut = currentPointNumber - distToXmin;
       
   187 
       
   188             return whereToCut;
       
   189         }
       
   190 
       
   191         /*
       
   192          * Détecte un changement de sens (extremum) dans l'axe Y.
       
   193          */
       
   194         public int DetectDirectionChangeAtYAxis(Point3D pt)
       
   195         {
       
   196             //ID où couper en cas d'extremum.
       
   197             int whereToCut = -1;
       
   198 
       
   199             //Mise à jour des extremums.
       
   200             if (Ymax == -1 || Ymax < pt.Y)
       
   201             {
       
   202                 //Si le point est plus grand en Y que Ymax, alors il est remplacé et on réinitialise la
       
   203                 //distance au dernier maximum en Y.
       
   204                 Ymax = pt.Y;
       
   205                 maxPt = pt;
       
   206                 distToYmax = 0;
       
   207             }
       
   208             else
       
   209                 distToYmax++;
       
   210             if (Ymin == -1 || Ymin > pt.Y)
       
   211             {
       
   212                 //Si le point est plus petit en Y que Ymin, alors il est remplacé et on réinitialise la
       
   213                 //distance au dernier minimum en Y.
       
   214                 Ymin = pt.Y;
       
   215                 minPt = pt;
       
   216                 distToYmin = 0;
       
   217             }
       
   218             else
       
   219                 distToYmin++;
       
   220 
       
   221             //Si Y max est plus grand que la position actuelle additionnée du seuil
       
   222             //et que l'extremum n'est pas le premier point sauvegardé.
       
   223             if (Ymax > pt.Y + directionChangeTresholdXY && maxPt != handPointerHistory.First())
       
   224                 whereToCut = currentPointNumber - distToYmax;
       
   225             //Si Y min est plus petit que la position actuelle à laquelle on a retiré le seuil
       
   226             //et que l'extremum n'est pas le premier point sauvegardé.
       
   227             if (Ymin < pt.Y - directionChangeTresholdXY && minPt != handPointerHistory.First())
       
   228                 whereToCut = currentPointNumber - distToYmin;
       
   229 
       
   230             return whereToCut;
       
   231         }
       
   232 
       
   233         /*
       
   234          * Détecte un changement de sens (extremum) dans l'axe Z.
       
   235          */
       
   236         public int DetectDirectionChangeAtZAxis(Point3D pt)
       
   237         {
       
   238             //ID où couper en cas d'extremum.
       
   239             int whereToCut = -1;
       
   240 
       
   241             //Mise à jour des extremums.
       
   242             if (Zmax == -1 || Zmax < pt.Z)
       
   243             {
       
   244                 //Si le point est plus grand en Z que Ymax, alors il est remplacé et on réinitialise la
       
   245                 //distance au dernier maximum en Z.
       
   246                 Zmax = pt.Z;
       
   247                 maxPt = pt;
       
   248                 distToZmax = 0;
       
   249             }
       
   250             else
       
   251                 distToZmax++;
       
   252             if (Zmin == -1 || Zmin > pt.Z)
       
   253             {
       
   254                 //Si le point est plus petit en Z que Zmin, alors il est remplacé et on réinitialise la
       
   255                 //distance au dernier minimum en Z.
       
   256                 Zmin = pt.Z;
       
   257                 minPt = pt;
       
   258                 distToZmin = 0;
       
   259             }
       
   260             else
       
   261                 distToZmin++;
       
   262 
       
   263             //Si Z max est plus grand que la position actuelle additionnée du seuil
       
   264             //et que l'extremum n'est pas le premier point sauvegardé.
       
   265             if (Zmax > pt.Z + directionChangeTresholdXY && maxPt != handPointerHistory.First())
       
   266                 whereToCut = currentPointNumber - distToZmax;
       
   267             //Si Z min est plus petit que la position actuelle à laquelle on a retiré le seuil
       
   268             //et que l'extremum n'est pas le premier point sauvegardé.
       
   269             if (Zmin < pt.Z - directionChangeTresholdXY && minPt != handPointerHistory.First())
       
   270                 whereToCut = currentPointNumber - distToZmin;
       
   271 
       
   272             return whereToCut;
       
   273         }
       
   274 
       
   275         /*
       
   276          * Découpe le tracé en cours en segment allant du premier point au premier extremum trouvé.
       
   277          */
       
   278         public void Segment(int whereToCut)
       
   279         {
       
   280             handPointerHistory.RemoveRange(0, whereToCut);
       
   281             currentPointNumber -= whereToCut;
       
   282         }
       
   283     }
       
   284 }