/// <summary>
 /// Removes duplicate points from the line object
 /// </summary>
 private void CleanPoints()
 {
     if (linePoints.Any())
     {
         //check if its a point
         var localIsPoint = linePoints.All(o => o.X == linePoints.First().X&& o.Y == linePoints.First().Y);
         if (!localIsPoint)
         {
             List <Point> newList  = new List <Point>();
             List <Point> tempList = new List <Point>();
             //Since Point is non-nullable, we must ensure the nullPoints,
             //which we remove can not possibly be points of the original given line.
             int nullValue = (int)linePoints[0].X + 1;
             //Fill the gaps between points
             for (int i = 0; i < linePoints.Count - 1; i++)
             {
                 nullValue += (int)linePoints[i + 1].X;
                 List <Point> partialList = GeometryCalculator.BresenhamLineAlgorithm(linePoints[i], linePoints[i + 1]);
                 tempList.AddRange(partialList);
             }
             Point nullPoint = new Point(nullValue, 0);
             //Set duplicate points to the null point
             for (int i = 1; i < tempList.Count; i++)
             {
                 if ((tempList[i].X == tempList[i - 1].X) && (tempList[i].Y == tempList[i - 1].Y))
                 {
                     tempList[i - 1] = nullPoint;
                 }
             }
             //remove the null points
             foreach (Point tempPoint in tempList)
             {
                 if (tempPoint.X != nullValue)
                 {
                     newList.Add(tempPoint);
                 }
             }
             linePoints = new List <Point>(newList);
         }
         else
         {
             isPoint = true;
             point   = linePoints.First();
             linePoints.Clear();
             linePoints.Add(point);
         }
     }
 }
        /// <summary>
        /// Method to be called every tick. Updates the current Line, or checks for Lines to delete, depending on the drawing mode.
        /// </summary>
        public void Tick()
        {
            if (cursorPositions.Count > 0)
            {
                previousCursorPosition = cursorPositions.Dequeue();
            }
            else
            {
                previousCursorPosition = currentCursorPosition;
            }

            if (optitrackAvailable)
            {
                SetCurrentFingerPosition(new Point(optiTrackX, optiTrackY));
            }


            if (optiTrackInUse && inDrawingMode && !OptiMovingBack) // optitrack is being used
            {
                //outside of drawing zone
                if (!CheckInsideDrawingZone(optiTrackZ))
                {
                    //Check if trackable was in drawing zone last tick & program is in drawing mode-> finish line
                    if (optiTrackInsideDrawingZone && inDrawingMode)
                    {
                        optiTrackInsideDrawingZone = false;
                        FinishCurrentLine(true);
                    }
                }
                else //Draw with optitrack, when in drawing zone
                {
                    //Optitrack wasn't in the drawing zone last tick -> start a new line
                    if (!optiTrackInsideDrawingZone)
                    {
                        optiTrackInsideDrawingZone = true;
                        StartNewLine();
                    }
                    else
                    {
                        currentLine.Add(currentOptiCursorPosition);
                    }
                    programPresenter.UpdateCurrentLine(currentLine);
                    if (optiTrackZ > WARNING_ZONE_BOUNDARY)
                    {
                        wristband.PushForward();
                    }
                    else if (optiTrackZ < -1 * WARNING_ZONE_BOUNDARY)
                    {
                        wristband.PushBackward();
                    }
                }
            }
            else if (!optiTrackInUse && inDrawingMode)
            {
                //drawing without optitrack
                cursorPositions.Enqueue(currentCursorPosition);
                if (inDrawingMode && programPresenter.IsMousePressed())
                {
                    currentLine.Add(currentCursorPosition);
                    //programPresenter.UpdateCurrentLine(currentLine);
                }
            }

            //Deletion mode for optitrack and regular use
            if (!inDrawingMode)
            {
                List <Point> uncheckedPoints = new List <Point>();
                if (programPresenter.IsMousePressed() && !optiTrackInUse) //without optitrack
                {
                    uncheckedPoints = GeometryCalculator.BresenhamLineAlgorithm(previousCursorPosition, currentCursorPosition);
                }
                if (optiTrackInUse && CheckInsideDrawingZone(optiTrackZ) && !OptiMovingBack) //with optitrack
                {
                    uncheckedPoints = GeometryCalculator.BresenhamLineAlgorithm(previousOptiCursorPosition, currentOptiCursorPosition);
                }

                foreach (Point currPoint in uncheckedPoints)
                {
                    HashSet <int> linesToDelete = CheckDeletionMatrixesAroundPoint(currPoint, deletionRadius);
                    if (linesToDelete.Count > 0)
                    {
                        programPresenter.PassLastActionTaken(historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Delete, linesToDelete)));
                        foreach (int lineID in linesToDelete)
                        {
                            rightLineList[lineID] = new Tuple <bool, InternalLine>(false, rightLineList[lineID].Item2);
                        }
                        RepopulateDeletionMatrixes();
                        programPresenter.UpdateRightLines(rightLineList);
                    }
                }
            }
        }