// Increase age of tracked glyph and remove old ones
        private void IncreaseHistoryAge( )
        {
            List <int> keys = new List <int>(trackedGlyphs.Keys);

            for (int i = 0; i < keys.Count; i++)
            {
                int          id           = keys[i];
                TrackedGlyph trackedGlyph = trackedGlyphs[id];

                trackedGlyph.Age++;

                if (((trackedGlyph.Age > MaxGlyphAge) && (trackedGlyph.AverageRecentMotion >= StalledAverageMotionLimit)) ||
                    (trackedGlyph.Age > MaxStalledGlyphAge))
                {
                    trackedGlyphs.Remove(id);

                    if (prevRotation.ContainsKey(id))
                    {
                        prevRotation.Remove(id);
                    }
                }
            }
        }
        // Get ID of the specified glyph
        // Note (todo?): glyph tracking needs to be improved since current implementation
        // is not reliable enough for the case when several glyphs of the same type are
        // found and those do not move smoothely.
        private int GetGlyphID(ExtractedGlyphData glyph)
        {
            int glyphID = -1;

            // get CoG of the provided glyph
            Point glyphCog = PointsCloud.GetCenterOfGravity(glyph.Quadrilateral);
            // distance to the closest simlar glyph kept in history
            float minDistance = float.MaxValue;

            // name of the passed specifed glyph
            string glyphName = (glyph.RecognizedGlyph != null) ?
                               glyph.RecognizedGlyph.Name : string.Empty;

            // check all currently tracked glyphs
            foreach (TrackedGlyph trackedGlyph in trackedGlyphs.Values)
            {
                if (trackedGlyph.Age == 0)
                {
                    // skip glyph whichs were already taken or just added
                    continue;
                }

                if (
                    // recognized case - compare names
                    ((trackedGlyph.Glyph.RecognizedGlyph != null) &&
                     (trackedGlyph.Glyph.RecognizedGlyph.Name == glyphName)) ||
                    // unrecognized case - compare raw data
                    (Glyph.CheckForMatching(glyph.RawData, trackedGlyph.Glyph.RawData) != -1))
                {
                    float distance = glyphCog.DistanceTo(trackedGlyph.Position);

                    if (distance < minDistance)
                    {
                        // get ID of the closest glyph with the same name
                        minDistance = distance;
                        glyphID     = trackedGlyph.ID;
                    }
                }
            }

            // if the glyph is further away than the maximum specified limit,
            // then it is no way can be treated as smooth motion, so reset ID
            // (TODO: should probably depend on glyph size ...)
            if ((glyphID != -1) && (minDistance > MaxAllowedDistance))
            {
                glyphID = -1;
            }

            // if glyph was not found within tracked glyphs, then add new
            // glyph to tracker
            if (glyphID == -1)
            {
                glyphID = counter++;
                trackedGlyphs.Add(glyphID, new TrackedGlyph(glyphID,
                                                            (ExtractedGlyphData)glyph.Clone( ), glyphCog));
            }
            else
            {
                TrackedGlyph trackedGlyph = trackedGlyphs[glyphID];

                if ((glyph.RecognizedGlyph != null) &&
                    (!IsCoordinatesDifferenceSignificant(glyph.RecognizedQuadrilateral,
                                                         trackedGlyphs[glyphID].Glyph.RecognizedQuadrilateral)))
                {
                    // correct coordinates of recognized glyphs to eliminate small noisy shaking
                    glyph.RecognizedQuadrilateral = trackedGlyph.Glyph.RecognizedQuadrilateral;
                    glyphCog = trackedGlyph.Position;
                }
                else
                {
                    // update glyph with the latest CoG and recognized info
                    trackedGlyph.Position = glyphCog;
                    trackedGlyph.Glyph    = (ExtractedGlyphData)glyph.Clone( );
                }

                // reset age of the tracked glyph
                trackedGlyph.Age = 0;

                // add glyph's position to history
                trackedGlyph.AddMotionHistory(glyphCog);
            }

            return(glyphID);
        }