src/GestureControl/GestureVector.cs
changeset 173 e99fe78cd168
--- /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
+}