// Double Exp Function
        MathUtil.Vector2 DoubleExpFilter(MathUtil.Vector2 InputPos)
        {
            // s0
            if (!IsTime0Past)
            {
                HistoryPointTime0 = InputPos;
                IsTime0Past       = true;
                return(InputPos);
            }

            // s1
            if (!IsTime1Past)
            {
                s           = InputPos;
                b           = InputPos - HistoryPointTime0;
                IsTime1Past = true;
                return(s + b);
            }

            MathUtil.Vector2 NextS, NextB;
            NextS = SmoothFactorAValue * InputPos + MathUtil.MathUtil.Clamp01(1 - SmoothFactorAValue) * (s - b);
            NextB = SmoothFactorBValue * (NextS - s) + MathUtil.MathUtil.Clamp01(1 - SmoothFactorBValue) * b;
            s     = NextS;
            b     = NextB;
            return(s + b);
        }
        private void GetGazePointTimer_Tick(object sender, EventArgs e)
        {
            // 抓眼動位置及儲存
            stream.GazePoint((x, y, ts) => CopyToGlobalVariable(x, y, ts));

            // Clipping 到螢幕中
            ClippingToScreenSize();

            // 代表資料不一樣
            // 要覆蓋 last 的值
            if (lastTimeStamp != timeStamp)
            {
                // 使用 Double Exp
                MathUtil.Vector2 tempVector2 = DoubleExpFilter(new MathUtil.Vector2(eyeX, eyeY));
                eyeX     = tempVector2.X;
                eyeY     = tempVector2.Y;
                lastEyeX = eyeX;
                lastEyeY = eyeY;

                lastTimeStamp = timeStamp;

                // 是否要被眼動儀 Control
                if (IsEnableControl)
                {
                    SetCursorPos((int)eyeX, (int)eyeY);

                    // 點擊判斷
                    if (MathUtil.Vector2.Distance(clickTempVector, tempVector2) > FreezeDistanceToClick)
                    {
                        clickTempVector = tempVector2;
                        clickTime       = 0;
                    }
                    else if ((float)(clickTime * GetGazePointTimer.Interval) / 1000 > FreezeTimeToClick)
                    {
                        if (IsSingleClickModel)
                        {
                            DoSingleClick();
                        }
                        else
                        {
                            DoDoubleClick();
                        }

                        clickTempVector = tempVector2;
                        clickTime       = 0;
                    }
                    else
                    {
                        clickTime++;
                    }
                }

                #region 記錄相關
                if (IsRecording)
                {
                    string line = eyeX.ToString() + "," + eyeY.ToString() + "," + timeStamp.ToString();
                    LineData.Add(line);

                    if (TryToUnRecording)
                    {
                        // 要暫停 Hook 不然會無法使用鍵盤打檔名
                        GetGazePointTimer.Enabled = false;
                        UnHook();

                        // 找到位置,並儲存
                        if (outputFileDialog.ShowDialog() == DialogResult.OK)
                        {
                            // 寫出檔案
                            string outputStr = "X, Y, TimeStamp\n";
                            for (int i = 0; i < LineData.Count; i++)
                            {
                                outputStr += LineData[i] + "\n";
                            }
                            System.IO.File.WriteAllText(outputFileDialog.FileName, outputStr);
                        }
                        LineData.Clear();

                        // 繼續抓
                        GetGazePointTimer.Enabled = true;
                        SetHook();

                        TryToUnRecording = false;
                        IsRecording      = false;
                    }
                }
                #endregion
            }
        }