src/FingersDance.GestureControl/GestureVector.cs
changeset 174 45c9e55fcf23
child 176 0896f36b9d57
equal deleted inserted replaced
173:e99fe78cd168 174:45c9e55fcf23
       
     1 using System;
       
     2 using System.IO;
       
     3 using System.Xml;
       
     4 using System.Reflection;
       
     5 using System.Xml.Linq;
       
     6 using System.Collections.Generic;
       
     7 using System.Linq;
       
     8 using System.Text;
       
     9 using System.Windows.Input;
       
    10 using System.Windows;
       
    11 
       
    12 namespace GestureControl
       
    13 {
       
    14     /// <summary>
       
    15     /// Take a list of points and try to recognize a pattern
       
    16     /// </summary>
       
    17     public class SurfaceGesture : List<SurfaceGestureVector>
       
    18     {
       
    19 
       
    20         #region Prop
       
    21         /// <summary>
       
    22         /// Allow some variation without log a direction
       
    23         /// </summary>
       
    24         public int Precision { get; set; }
       
    25         /// <summary>
       
    26         /// List of pattern readed in the patterns.xml
       
    27         /// </summary>
       
    28         public List<SurfaceGesturePattern> Pattern = new List<SurfaceGesturePattern>();
       
    29         #endregion
       
    30         #region Constructor
       
    31         /// <summary>
       
    32         /// load know patterns and generate the vector list from a list of points with a default 20 precision factor
       
    33         /// </summary>
       
    34         /// <param name="list"></param>
       
    35         public SurfaceGesture(List<SurfaceGesturePoint> list)
       
    36         {
       
    37             this.Precision = 20;
       
    38             CommonPattern();
       
    39             this.Generate(list);
       
    40         }
       
    41         /// <summary>
       
    42         /// load know patterns and generate the vector list from a list of points with a precision factor
       
    43         /// </summary>
       
    44         /// <param name="list"></param>
       
    45         /// <param name="precision"></param>
       
    46         public SurfaceGesture(List<SurfaceGesturePoint> list, int precision)
       
    47         {
       
    48             this.Precision = precision;
       
    49             CommonPattern();
       
    50             this.Generate(list);
       
    51         }
       
    52         //public SurfaceGesture(System.Windows.Ink.Stroke stroke, int precision)
       
    53         //{
       
    54         //    StylusPointCollection tmp = stroke.GetBezierStylusPoints();
       
    55         //    List<SurfaceGesturePoint> pointList = new List<SurfaceGesturePoint>();
       
    56         //    foreach (StylusPoint p in tmp)
       
    57         //        pointList.Add(new SurfaceGesturePoint { X = p.X, Y = p.Y });
       
    58         //    this.Precision = precision;
       
    59         //    this.Generate(pointList);
       
    60         //    CommonPattern();
       
    61         //}
       
    62         #endregion
       
    63         #region GenerateVector
       
    64         /// <summary>
       
    65         /// Generate list of vector from courbe mouvements, filter with the pas value
       
    66         /// </summary>
       
    67         /// <param name="list"></param>
       
    68         /// <param name="pas"></param>
       
    69         /// <returns></returns>
       
    70         private bool GenerateCourb(List<SurfaceGesturePoint> list, int pas)
       
    71         {
       
    72             List<SurfaceGesturePattern> tmp = new List<SurfaceGesturePattern>();
       
    73             int sep = list.Count / pas;
       
    74             double count = 0; ;
       
    75             SurfaceGesturePoint past = new SurfaceGesturePoint() { X = 0, Y = 0 };
       
    76             double y = 0;
       
    77 
       
    78             for (int i = 0; i < list.Count - 1; i++)
       
    79             {
       
    80                 if (i % pas != 0)
       
    81                 {
       
    82                     count += Math.Atan(list[i + 1].Y / list[i + 1].X) - Math.Atan(list[i].Y / list[i].X);
       
    83                 }
       
    84                 else
       
    85                 {
       
    86                     count /= pas;
       
    87                     if (count == 0 || this.GetDistancePoints(past, list[i + 1]) < 5)
       
    88                     {
       
    89                         y = list[i + 1].Y;
       
    90                         past.X = count;
       
    91                         continue;
       
    92                     }
       
    93                     if (y > list[i + 1].Y)
       
    94                     {
       
    95                         if (past.X > count)
       
    96                             this.AddDirection(SurfaceGestureVectorDirection.UPRIGHT);
       
    97                         else
       
    98                             this.AddDirection(SurfaceGestureVectorDirection.UPLEFT);
       
    99                     }
       
   100                     else
       
   101                     {
       
   102                         if (past.X > count)
       
   103                             this.AddDirection(SurfaceGestureVectorDirection.DOWNRIGHT);
       
   104                         else
       
   105                             this.AddDirection(SurfaceGestureVectorDirection.DOWNLEFT);
       
   106                     }
       
   107                     y = list[i + 1].Y;
       
   108                     past.X = count;
       
   109                 }
       
   110             }
       
   111             Console.Write(this);
       
   112             if (this.GetPattern() != "None")
       
   113                 return true;
       
   114             else
       
   115                 return false;
       
   116         }
       
   117         /// <summary>
       
   118         /// Get distance between two points
       
   119         /// </summary>
       
   120         /// <param name="p1"></param>
       
   121         /// <param name="p2"></param>
       
   122         /// <returns></returns>
       
   123         private int GetDistancePoints(SurfaceGesturePoint p1, SurfaceGesturePoint p2)
       
   124         {
       
   125             return (int)Math.Sqrt(Math.Pow((p2.X - p1.X), 2) + Math.Pow((p1.Y - p2.Y), 2));
       
   126         }
       
   127         /// <summary>
       
   128         /// add a direction in the vector list if past who not the same
       
   129         /// </summary>
       
   130         /// <param name="type"></param>
       
   131         private void AddDirection(SurfaceGestureVectorDirection type)
       
   132         {
       
   133             if (this.Count == 0)
       
   134             {
       
   135                 this.Add(new SurfaceGestureVector{Direction = type, Lenght=42});
       
   136                 return ;
       
   137             }
       
   138             if (this[this.Count - 1].Direction != type)
       
   139                 this.Add(new SurfaceGestureVector { Direction = type, Lenght = 42 });
       
   140         }
       
   141         /// <summary>
       
   142         /// generate list of vector
       
   143         /// </summary>
       
   144         /// <param name="list"></param>
       
   145         private void Generate(List<SurfaceGesturePoint> list)
       
   146         {
       
   147             if (list.Count < 2)
       
   148                 return ;
       
   149             SurfaceGestureVectorDirection lastDirection = SurfaceGestureVectorDirection.NONE;
       
   150             int lastPoint = 0;
       
   151             SurfaceGesturePoint LastChange = list[0];
       
   152 
       
   153             /////// TEST///////////
       
   154             if (this.GenerateCourb(list, 5) == true)
       
   155                 return;
       
   156             this.Clear();
       
   157             ///////////////////////
       
   158 
       
   159             for (int i = 0; i < list.Count - 1; i++)
       
   160             {
       
   161                 if (GetHorizontal(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.UP && lastDirection != SurfaceGestureVectorDirection.UP)
       
   162                 {
       
   163                     this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UP, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)) });
       
   164                     LastChange = list[i + 1];
       
   165                     lastDirection = SurfaceGestureVectorDirection.UP;
       
   166                 }
       
   167                 else if (GetHorizontal(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.DOWN && lastDirection != SurfaceGestureVectorDirection.DOWN)
       
   168                 {
       
   169                     this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWN, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)) });
       
   170                     LastChange = list[i + 1];
       
   171                     lastDirection = SurfaceGestureVectorDirection.DOWN;
       
   172                 }
       
   173                 else if (GetVertical(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.LEFT && lastDirection != SurfaceGestureVectorDirection.LEFT)
       
   174                 {
       
   175                     this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.LEFT, Lenght = (Math.Abs(LastChange.X - list[i + 1].X)) });
       
   176                     LastChange = list[i + 1];
       
   177                     lastDirection = SurfaceGestureVectorDirection.LEFT;
       
   178                 }
       
   179                 else if (GetVertical(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.RIGHT && lastDirection != SurfaceGestureVectorDirection.RIGHT)
       
   180                 {
       
   181                     this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.RIGHT, Lenght = (Math.Abs(LastChange.X - list[i + 1].X)) });
       
   182                     LastChange = list[i + 1];
       
   183                     lastDirection = SurfaceGestureVectorDirection.RIGHT;
       
   184                 }
       
   185                 ++lastPoint;
       
   186             }
       
   187         }
       
   188         private SurfaceGestureVectorDirection GetHorizontal(SurfaceGesturePoint p1, SurfaceGesturePoint p2)
       
   189         {
       
   190             if (p1.Y < p2.Y)
       
   191             {
       
   192                 // go up
       
   193                 if (Math.Abs(p2.Y - p1.Y) > this.Precision && Math.Abs(p2.X - p1.X) < Math.Abs(p2.Y - p1.Y))
       
   194                     return SurfaceGestureVectorDirection.DOWN;
       
   195             }
       
   196             else
       
   197             {
       
   198                 // go down
       
   199                 if (Math.Abs(p1.Y - p2.Y) > this.Precision && Math.Abs(p1.X - p2.X) < Math.Abs(p1.Y - p2.Y))
       
   200                     return SurfaceGestureVectorDirection.UP;
       
   201             }
       
   202             return SurfaceGestureVectorDirection.NONE;
       
   203         }
       
   204         private SurfaceGestureVectorDirection GetVertical(SurfaceGesturePoint p1, SurfaceGesturePoint p2)
       
   205         {
       
   206             if (p1.X < p2.X)
       
   207             {
       
   208                 // go left
       
   209                 if (Math.Abs(p2.X - p1.X) > this.Precision && Math.Abs(p2.Y - p1.Y) < Math.Abs(p2.X - p1.X))
       
   210                     return SurfaceGestureVectorDirection.RIGHT;
       
   211             }
       
   212             else
       
   213             {
       
   214                 // go right
       
   215                 if (Math.Abs(p1.X - p2.X) > this.Precision && Math.Abs(p1.Y - p2.Y) < Math.Abs(p1.X - p2.X))
       
   216                     return SurfaceGestureVectorDirection.LEFT;
       
   217             }
       
   218             return SurfaceGestureVectorDirection.NONE;
       
   219         }
       
   220         #endregion
       
   221         #region Override
       
   222         public override String ToString()
       
   223         {
       
   224             String ret = "";
       
   225 
       
   226             foreach (SurfaceGestureVector v in this)
       
   227             {
       
   228                 ret += (v.Direction + ", lenght:" + v.Lenght + ", precision:" + this.Precision + "\n");
       
   229                 //Console.WriteLine(v.Direction + ", lenght:" + v.Lenght + ", precision:" + this.Precision);
       
   230             }
       
   231             return ret;
       
   232         }
       
   233         #endregion
       
   234         #region Pattern
       
   235         /// <summary>
       
   236         /// return a String with the recognized pattern, "None" if no pattern
       
   237         /// </summary>
       
   238         /// <returns></returns>
       
   239         public String GetPattern()
       
   240         {
       
   241             foreach (SurfaceGesturePattern p in this.Pattern)
       
   242             {
       
   243                 if (p.Count == this.Count)
       
   244                 {
       
   245                     int i;
       
   246                     for (i = 0; i < p.Count; i++)
       
   247                     {
       
   248                         if (this[i].Direction != p[i].Direction)
       
   249                             break ;
       
   250                     }
       
   251                     if (i == p.Count)
       
   252                         return p.Name;
       
   253                 }
       
   254             }
       
   255             return "None";
       
   256         }
       
   257         /// <summary>
       
   258         /// Load know patterns from the Resources/Patterns.xml file
       
   259         /// </summary>
       
   260         private void CommonPattern()
       
   261         {
       
   262             try
       
   263             {
       
   264                 #region Load Patterns
       
   265                 System.IO.Stream file = Assembly.GetExecutingAssembly().GetManifestResourceStream("GestureControl.Resources.Patterns.xml");
       
   266                 XmlDocument xml = new XmlDocument();
       
   267                 xml.Load(file);
       
   268                 XmlElement root = xml.DocumentElement;
       
   269                 XmlNodeList nodes = root.SelectNodes("//Pattern");
       
   270                 SurfaceGesturePattern p;
       
   271                 int i = 0;
       
   272                 foreach (XmlNode node in nodes)
       
   273                 {
       
   274                     string name = node["Name"].InnerText;
       
   275                     XmlNodeList subNodes = node.SelectNodes("//Directions");
       
   276                     if (subNodes == null)
       
   277                         continue;
       
   278                     p = new SurfaceGesturePattern() { Name = name };
       
   279                     foreach (XmlNode subNode in subNodes[i++])
       
   280                     {
       
   281                         XmlNodeList dl = subNode.ChildNodes;
       
   282                         foreach (XmlNode d in dl)
       
   283                         {
       
   284                             switch (d.InnerText)
       
   285                             {
       
   286                                 case "Up":
       
   287                                     p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.UP });
       
   288                                     break;
       
   289                                 case "Down":
       
   290                                     p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.DOWN });
       
   291                                     break;
       
   292                                 case "Left":
       
   293                                     p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.LEFT });
       
   294                                     break;
       
   295                                 case "Right":
       
   296                                     p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.RIGHT });
       
   297                                     break;
       
   298                                 case "DownRight":
       
   299                                     p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.DOWNRIGHT });
       
   300                                     break;
       
   301                                 case "DownLeft":
       
   302                                     p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.DOWNLEFT });
       
   303                                     break;
       
   304                                 case "UpRight":
       
   305                                     p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.UPRIGHT });
       
   306                                     break;
       
   307                                 case "UpLeft":
       
   308                                     p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.UPLEFT });
       
   309                                     break;
       
   310                                 default:
       
   311                                     break;
       
   312                             }
       
   313                         }
       
   314                     }
       
   315                     this.Pattern.Add(p);
       
   316                 }
       
   317                 #endregion
       
   318             }
       
   319             catch
       
   320             {
       
   321                 throw new Exception("Error loading Patterns.xml");
       
   322             }
       
   323         }
       
   324         #endregion
       
   325     }
       
   326     #region Tools
       
   327     /// <summary>
       
   328     /// Gesture event who return a object with a Gesture String value
       
   329     /// </summary>
       
   330     public class GestureRoutedEventArgs : RoutedEventArgs
       
   331     {
       
   332         public String Gesture { get; private set; }
       
   333             
       
   334         public GestureRoutedEventArgs() : base() { }
       
   335         public GestureRoutedEventArgs(String gesture) : base() { this.Gesture = gesture; }
       
   336         public GestureRoutedEventArgs(RoutedEvent routedEvent) : base(routedEvent) { }
       
   337         public GestureRoutedEventArgs(RoutedEvent routedEvent, String gesture) : base(routedEvent) { this.Gesture = gesture; }
       
   338         public GestureRoutedEventArgs(RoutedEvent routedEvent, Object source) : base(routedEvent, source) { }
       
   339         public GestureRoutedEventArgs(RoutedEvent routedEvent, Object source, String gesture) : base(routedEvent, source) { this.Gesture = gesture; }
       
   340     }
       
   341 
       
   342     public class SurfaceGesturePattern : List<SurfaceGestureVector>
       
   343     {
       
   344         public String Name { get; set; }
       
   345 
       
   346     }
       
   347     /// <summary>
       
   348     /// Possible Gesture Vector
       
   349     /// </summary>
       
   350     public enum SurfaceGestureVectorDirection
       
   351     {
       
   352         UP,
       
   353         DOWN,
       
   354         LEFT,
       
   355         RIGHT,
       
   356         UPLEFT,
       
   357         UPRIGHT,
       
   358         DOWNLEFT,
       
   359         DOWNRIGHT,
       
   360         NONE,
       
   361     }
       
   362     /// <summary>
       
   363     /// Describe a point in the grid
       
   364     /// </summary>
       
   365     public class SurfaceGesturePoint
       
   366     {
       
   367         public double X { get; set; }
       
   368         public double Y { get; set; }
       
   369     }
       
   370 
       
   371     /// <summary>
       
   372     /// Describe a vector to help the recognize pass
       
   373     /// </summary>
       
   374     public class SurfaceGestureVector
       
   375     {
       
   376         public SurfaceGestureVectorDirection Direction { get; set; }
       
   377         public Double Lenght { get; set; }
       
   378     }
       
   379     #endregion
       
   380 }