diff -r e408e158c1a2 -r e99fe78cd168 src/GestureControl/GestureVector.cs --- /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 +{ + /// + /// Take a list of points and try to recognize a pattern + /// + public class SurfaceGesture : List + { + + #region Prop + /// + /// Allow some variation without log a direction + /// + public int Precision { get; set; } + /// + /// List of pattern readed in the patterns.xml + /// + public List Pattern = new List(); + #endregion + #region Constructor + /// + /// load know patterns and generate the vector list from a list of points with a default 20 precision factor + /// + /// + public SurfaceGesture(List list) + { + this.Precision = 20; + CommonPattern(); + this.Generate(list); + } + /// + /// load know patterns and generate the vector list from a list of points with a precision factor + /// + /// + /// + public SurfaceGesture(List list, int precision) + { + this.Precision = precision; + CommonPattern(); + this.Generate(list); + } + //public SurfaceGesture(System.Windows.Ink.Stroke stroke, int precision) + //{ + // StylusPointCollection tmp = stroke.GetBezierStylusPoints(); + // List pointList = new List(); + // 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 + /// + /// Generate list of vector from courbe mouvements, filter with the pas value + /// + /// + /// + /// + private bool GenerateCourb(List list, int pas) + { + List tmp = new List(); + 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; + } + /// + /// Get distance between two points + /// + /// + /// + /// + 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)); + } + /// + /// add a direction in the vector list if past who not the same + /// + /// + 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 }); + } + /// + /// generate list of vector + /// + /// + private void Generate(List 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 + /// + /// return a String with the recognized pattern, "None" if no pattern + /// + /// + 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"; + } + /// + /// Load know patterns from the Resources/Patterns.xml file + /// + 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 + /// + /// Gesture event who return a object with a Gesture String value + /// + 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 + { + public String Name { get; set; } + + } + /// + /// Possible Gesture Vector + /// + public enum SurfaceGestureVectorDirection + { + UP, + DOWN, + LEFT, + RIGHT, + UPLEFT, + UPRIGHT, + DOWNLEFT, + DOWNRIGHT, + NONE, + } + /// + /// Describe a point in the grid + /// + public class SurfaceGesturePoint + { + public double X { get; set; } + public double Y { get; set; } + } + + /// + /// Describe a vector to help the recognize pass + /// + public class SurfaceGestureVector + { + public SurfaceGestureVectorDirection Direction { get; set; } + public Double Lenght { get; set; } + } + #endregion +}