--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/GestureControl/GestureVector.cs Mon Oct 26 08:36:15 2009 +0100
@@ -0,0 +1,380 @@
+using System;
+using System.IO;
+using System.Xml;
+using System.Reflection;
+using System.Xml.Linq;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Input;
+using System.Windows;
+
+namespace GestureControl
+{
+ /// <summary>
+ /// Take a list of points and try to recognize a pattern
+ /// </summary>
+ public class SurfaceGesture : List<SurfaceGestureVector>
+ {
+
+ #region Prop
+ /// <summary>
+ /// Allow some variation without log a direction
+ /// </summary>
+ public int Precision { get; set; }
+ /// <summary>
+ /// List of pattern readed in the patterns.xml
+ /// </summary>
+ public List<SurfaceGesturePattern> Pattern = new List<SurfaceGesturePattern>();
+ #endregion
+ #region Constructor
+ /// <summary>
+ /// load know patterns and generate the vector list from a list of points with a default 20 precision factor
+ /// </summary>
+ /// <param name="list"></param>
+ public SurfaceGesture(List<SurfaceGesturePoint> list)
+ {
+ this.Precision = 20;
+ CommonPattern();
+ this.Generate(list);
+ }
+ /// <summary>
+ /// load know patterns and generate the vector list from a list of points with a precision factor
+ /// </summary>
+ /// <param name="list"></param>
+ /// <param name="precision"></param>
+ public SurfaceGesture(List<SurfaceGesturePoint> list, int precision)
+ {
+ this.Precision = precision;
+ CommonPattern();
+ this.Generate(list);
+ }
+ //public SurfaceGesture(System.Windows.Ink.Stroke stroke, int precision)
+ //{
+ // StylusPointCollection tmp = stroke.GetBezierStylusPoints();
+ // List<SurfaceGesturePoint> pointList = new List<SurfaceGesturePoint>();
+ // foreach (StylusPoint p in tmp)
+ // pointList.Add(new SurfaceGesturePoint { X = p.X, Y = p.Y });
+ // this.Precision = precision;
+ // this.Generate(pointList);
+ // CommonPattern();
+ //}
+ #endregion
+ #region GenerateVector
+ /// <summary>
+ /// Generate list of vector from courbe mouvements, filter with the pas value
+ /// </summary>
+ /// <param name="list"></param>
+ /// <param name="pas"></param>
+ /// <returns></returns>
+ private bool GenerateCourb(List<SurfaceGesturePoint> list, int pas)
+ {
+ List<SurfaceGesturePattern> tmp = new List<SurfaceGesturePattern>();
+ int sep = list.Count / pas;
+ double count = 0; ;
+ SurfaceGesturePoint past = new SurfaceGesturePoint() { X = 0, Y = 0 };
+ double y = 0;
+
+ for (int i = 0; i < list.Count - 1; i++)
+ {
+ if (i % pas != 0)
+ {
+ count += Math.Atan(list[i + 1].Y / list[i + 1].X) - Math.Atan(list[i].Y / list[i].X);
+ }
+ else
+ {
+ count /= pas;
+ if (count == 0 || this.GetDistancePoints(past, list[i + 1]) < 5)
+ {
+ y = list[i + 1].Y;
+ past.X = count;
+ continue;
+ }
+ if (y > list[i + 1].Y)
+ {
+ if (past.X > count)
+ this.AddDirection(SurfaceGestureVectorDirection.UPRIGHT);
+ else
+ this.AddDirection(SurfaceGestureVectorDirection.UPLEFT);
+ }
+ else
+ {
+ if (past.X > count)
+ this.AddDirection(SurfaceGestureVectorDirection.DOWNRIGHT);
+ else
+ this.AddDirection(SurfaceGestureVectorDirection.DOWNLEFT);
+ }
+ y = list[i + 1].Y;
+ past.X = count;
+ }
+ }
+ Console.Write(this);
+ if (this.GetPattern() != "None")
+ return true;
+ else
+ return false;
+ }
+ /// <summary>
+ /// Get distance between two points
+ /// </summary>
+ /// <param name="p1"></param>
+ /// <param name="p2"></param>
+ /// <returns></returns>
+ private int GetDistancePoints(SurfaceGesturePoint p1, SurfaceGesturePoint p2)
+ {
+ return (int)Math.Sqrt(Math.Pow((p2.X - p1.X), 2) + Math.Pow((p1.Y - p2.Y), 2));
+ }
+ /// <summary>
+ /// add a direction in the vector list if past who not the same
+ /// </summary>
+ /// <param name="type"></param>
+ private void AddDirection(SurfaceGestureVectorDirection type)
+ {
+ if (this.Count == 0)
+ {
+ this.Add(new SurfaceGestureVector{Direction = type, Lenght=42});
+ return ;
+ }
+ if (this[this.Count - 1].Direction != type)
+ this.Add(new SurfaceGestureVector { Direction = type, Lenght = 42 });
+ }
+ /// <summary>
+ /// generate list of vector
+ /// </summary>
+ /// <param name="list"></param>
+ private void Generate(List<SurfaceGesturePoint> list)
+ {
+ if (list.Count < 2)
+ return ;
+ SurfaceGestureVectorDirection lastDirection = SurfaceGestureVectorDirection.NONE;
+ int lastPoint = 0;
+ SurfaceGesturePoint LastChange = list[0];
+
+ /////// TEST///////////
+ if (this.GenerateCourb(list, 5) == true)
+ return;
+ this.Clear();
+ ///////////////////////
+
+ for (int i = 0; i < list.Count - 1; i++)
+ {
+ if (GetHorizontal(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.UP && lastDirection != SurfaceGestureVectorDirection.UP)
+ {
+ this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UP, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)) });
+ LastChange = list[i + 1];
+ lastDirection = SurfaceGestureVectorDirection.UP;
+ }
+ else if (GetHorizontal(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.DOWN && lastDirection != SurfaceGestureVectorDirection.DOWN)
+ {
+ this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWN, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)) });
+ LastChange = list[i + 1];
+ lastDirection = SurfaceGestureVectorDirection.DOWN;
+ }
+ else if (GetVertical(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.LEFT && lastDirection != SurfaceGestureVectorDirection.LEFT)
+ {
+ this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.LEFT, Lenght = (Math.Abs(LastChange.X - list[i + 1].X)) });
+ LastChange = list[i + 1];
+ lastDirection = SurfaceGestureVectorDirection.LEFT;
+ }
+ else if (GetVertical(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.RIGHT && lastDirection != SurfaceGestureVectorDirection.RIGHT)
+ {
+ this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.RIGHT, Lenght = (Math.Abs(LastChange.X - list[i + 1].X)) });
+ LastChange = list[i + 1];
+ lastDirection = SurfaceGestureVectorDirection.RIGHT;
+ }
+ ++lastPoint;
+ }
+ }
+ private SurfaceGestureVectorDirection GetHorizontal(SurfaceGesturePoint p1, SurfaceGesturePoint p2)
+ {
+ if (p1.Y < p2.Y)
+ {
+ // go up
+ if (Math.Abs(p2.Y - p1.Y) > this.Precision && Math.Abs(p2.X - p1.X) < Math.Abs(p2.Y - p1.Y))
+ return SurfaceGestureVectorDirection.DOWN;
+ }
+ else
+ {
+ // go down
+ if (Math.Abs(p1.Y - p2.Y) > this.Precision && Math.Abs(p1.X - p2.X) < Math.Abs(p1.Y - p2.Y))
+ return SurfaceGestureVectorDirection.UP;
+ }
+ return SurfaceGestureVectorDirection.NONE;
+ }
+ private SurfaceGestureVectorDirection GetVertical(SurfaceGesturePoint p1, SurfaceGesturePoint p2)
+ {
+ if (p1.X < p2.X)
+ {
+ // go left
+ if (Math.Abs(p2.X - p1.X) > this.Precision && Math.Abs(p2.Y - p1.Y) < Math.Abs(p2.X - p1.X))
+ return SurfaceGestureVectorDirection.RIGHT;
+ }
+ else
+ {
+ // go right
+ if (Math.Abs(p1.X - p2.X) > this.Precision && Math.Abs(p1.Y - p2.Y) < Math.Abs(p1.X - p2.X))
+ return SurfaceGestureVectorDirection.LEFT;
+ }
+ return SurfaceGestureVectorDirection.NONE;
+ }
+ #endregion
+ #region Override
+ public override String ToString()
+ {
+ String ret = "";
+
+ foreach (SurfaceGestureVector v in this)
+ {
+ ret += (v.Direction + ", lenght:" + v.Lenght + ", precision:" + this.Precision + "\n");
+ //Console.WriteLine(v.Direction + ", lenght:" + v.Lenght + ", precision:" + this.Precision);
+ }
+ return ret;
+ }
+ #endregion
+ #region Pattern
+ /// <summary>
+ /// return a String with the recognized pattern, "None" if no pattern
+ /// </summary>
+ /// <returns></returns>
+ public String GetPattern()
+ {
+ foreach (SurfaceGesturePattern p in this.Pattern)
+ {
+ if (p.Count == this.Count)
+ {
+ int i;
+ for (i = 0; i < p.Count; i++)
+ {
+ if (this[i].Direction != p[i].Direction)
+ break ;
+ }
+ if (i == p.Count)
+ return p.Name;
+ }
+ }
+ return "None";
+ }
+ /// <summary>
+ /// Load know patterns from the Resources/Patterns.xml file
+ /// </summary>
+ private void CommonPattern()
+ {
+ try
+ {
+ #region Load Patterns
+ System.IO.Stream file = Assembly.GetExecutingAssembly().GetManifestResourceStream("GestureControl.Resources.Patterns.xml");
+ XmlDocument xml = new XmlDocument();
+ xml.Load(file);
+ XmlElement root = xml.DocumentElement;
+ XmlNodeList nodes = root.SelectNodes("//Pattern");
+ SurfaceGesturePattern p;
+ int i = 0;
+ foreach (XmlNode node in nodes)
+ {
+ string name = node["Name"].InnerText;
+ XmlNodeList subNodes = node.SelectNodes("//Directions");
+ if (subNodes == null)
+ continue;
+ p = new SurfaceGesturePattern() { Name = name };
+ foreach (XmlNode subNode in subNodes[i++])
+ {
+ XmlNodeList dl = subNode.ChildNodes;
+ foreach (XmlNode d in dl)
+ {
+ switch (d.InnerText)
+ {
+ case "Up":
+ p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.UP });
+ break;
+ case "Down":
+ p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.DOWN });
+ break;
+ case "Left":
+ p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.LEFT });
+ break;
+ case "Right":
+ p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.RIGHT });
+ break;
+ case "DownRight":
+ p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.DOWNRIGHT });
+ break;
+ case "DownLeft":
+ p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.DOWNLEFT });
+ break;
+ case "UpRight":
+ p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.UPRIGHT });
+ break;
+ case "UpLeft":
+ p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.UPLEFT });
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ this.Pattern.Add(p);
+ }
+ #endregion
+ }
+ catch
+ {
+ throw new Exception("Error loading Patterns.xml");
+ }
+ }
+ #endregion
+ }
+ #region Tools
+ /// <summary>
+ /// Gesture event who return a object with a Gesture String value
+ /// </summary>
+ public class GestureRoutedEventArgs : RoutedEventArgs
+ {
+ public String Gesture { get; private set; }
+
+ public GestureRoutedEventArgs() : base() { }
+ public GestureRoutedEventArgs(String gesture) : base() { this.Gesture = gesture; }
+ public GestureRoutedEventArgs(RoutedEvent routedEvent) : base(routedEvent) { }
+ public GestureRoutedEventArgs(RoutedEvent routedEvent, String gesture) : base(routedEvent) { this.Gesture = gesture; }
+ public GestureRoutedEventArgs(RoutedEvent routedEvent, Object source) : base(routedEvent, source) { }
+ public GestureRoutedEventArgs(RoutedEvent routedEvent, Object source, String gesture) : base(routedEvent, source) { this.Gesture = gesture; }
+ }
+
+ public class SurfaceGesturePattern : List<SurfaceGestureVector>
+ {
+ public String Name { get; set; }
+
+ }
+ /// <summary>
+ /// Possible Gesture Vector
+ /// </summary>
+ public enum SurfaceGestureVectorDirection
+ {
+ UP,
+ DOWN,
+ LEFT,
+ RIGHT,
+ UPLEFT,
+ UPRIGHT,
+ DOWNLEFT,
+ DOWNRIGHT,
+ NONE,
+ }
+ /// <summary>
+ /// Describe a point in the grid
+ /// </summary>
+ public class SurfaceGesturePoint
+ {
+ public double X { get; set; }
+ public double Y { get; set; }
+ }
+
+ /// <summary>
+ /// Describe a vector to help the recognize pass
+ /// </summary>
+ public class SurfaceGestureVector
+ {
+ public SurfaceGestureVectorDirection Direction { get; set; }
+ public Double Lenght { get; set; }
+ }
+ #endregion
+}