/// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="gesture">The Gesture to recognize.</param>
 /// <param name="skeleton">The skeleton that had the gesture in it</param>
 public GestureRecognizer(Gesture gesture, Skeleton skeleton)
 {
     Gesture = gesture;
     CurrentPoseIndex = -1;
     InvalidFrameCount = 0;
     InitialAnchorPosition = skeleton.Joints[gesture.AnchorJoint].Position;
     UpdateArmLength(skeleton);
 }
        void recognizer_Recognized(object sender, PoseEventArgs e)
        {
            string[] poses = e.Poses;

            HashSet<GestureRecognizer> toAdd = new HashSet<GestureRecognizer>();

            // Find gestures that start with this pose
            foreach (Gesture g in Gestures)
            {
                if (poses.Contains(g.PoseList[0]))
                {
                    GestureRecognizer existing = ActiveGestures.Find((GestureRecognizer gr) => { return gr.Gesture == g && gr.CurrentPoseIndex <= 0; });
                    if (existing != null)
                    {
                        existing.UpdatedTime = DateTime.Now.Ticks;
                    }
                    else
                    {
                        GestureRecognizer gr = new GestureRecognizer(g, e.Skeleton);
                        toAdd.Add(gr);
                    }
                }
            }

            HashSet<GestureRecognizer> toRemove = new HashSet<GestureRecognizer>();

            // Evaluate Active Gestures
            foreach (GestureRecognizer gr in ActiveGestures)
            {
                // If a gesture was recognized
                if (gr.EvaluatePose(poses, e.Skeleton))
                {
                    if (gr.Gesture.IsMirror(LastGesture))
                    {
                        toRemove.Add(gr);
                        long now = DateTime.Now.Ticks;

                        if (gr.UpdatedTime - LastGestureTime <= MIRROR_DETECT_DELAY)
                        {
                            continue;
                        }
                    }

                    // Clear all active gestures
                    ActiveGestures.Clear();

                    // Calculate gesture speed
                    double distance = CalculateDistance(gr.FinalAnchorPosition, gr.InitialAnchorPosition);

                    long age = DateTime.Now.Ticks - gr.CreatedTime;

                    //double speed = Math.Sqrt(distance / (age/15000000.0))*2.0;

                    //Console.WriteLine("Age:\t{0}\nSpeed:\t{1}\nRatio:\t{2}\n\n", age, speed, distance/gr.SkeletonHeight);

                    double speed = 3.0 * (distance / gr.SkeletonHeight);

                    // Trigger event
                    LastGesture = gr.Gesture;
                    LastGestureTime = DateTime.Now.Ticks;
                    OnGestureDetected(gr.Gesture, speed);
                    break;
                }
                else if (gr.Expired)
                {
                    toRemove.Add(gr);
                }
                else if (gr.InvalidFrameCount >= MAX_INVALID_FRAMES)
                {
                    toRemove.Add(gr);
                    if (gr.Gesture == LastGesture || gr.Gesture.IsMirror(LastGesture))
                    {
                        LastGesture = null;
                    }
                }
            }

            ActiveGestures.RemoveAll((GestureRecognizer gr) => { return toRemove.Contains(gr); });
            ActiveGestures.AddRange(toAdd);
        }
        /// <summary>
        /// Detects if a gesture has the exact opposite pose list as this one
        /// </summary>
        /// <param name="g">Gesture to check</param>
        /// <returns>True if the gesture is an exact mirror of this one</returns>
        public bool IsMirror(Gesture g)
        {
            if (g == null || g.PoseList.Length != this.PoseList.Length)
            {
                return false;
            }

            int length = g.PoseList.Length;

            for (int ii = 0; ii < (length + 1) / 2; ++ii)
            {
                if (g.PoseList[ii] != this.PoseList[length - ii - 1])
                {
                    return false;
                }
            }

            return true;
        }
 /// <summary>
 /// When a Gesture is recognized, fire the GestureDetected event.
 /// </summary>
 /// <param name="g">The recognized Gesture.</param>
 private void OnGestureDetected(Gesture g, double executionSpeedRatio)
 {
     if (GestureDetected != null)
     {
         GestureDetected(this, new GestureEventArgs(g.Name, executionSpeedRatio));
     }
 }