/// <summary>
        ///This function takes a to be deleted component and sees whether it could
        ///be a part of another component in the outer sentence. It could be a
        ///dot for example. If so, it will merged.
        /// </summary>
        /// <param name="InnerSentence"></param>
        /// <param name="OuterSentence"></param>
        public static void MergeRectangles(Sentence InnerSentence, Sentence OuterSentence)
        {
            int    MinDistance = 1000;
            int    Distance;
            double BestAngle = 90;
            double Angle;
            double AverageAngle;

            PageComponent InnerComponent;
            PageComponent MergeComponent = null;

            InnerComponent = InnerSentence.Components[0];

            if (InnerComponent.Type != ePageComponentType.eCharacter)
            {
                return;
            }

            AverageAngle = OuterSentence.AverageAngle();

            //we merge two rectangles if:
            //1. the distance between them is the minimum in comparing to other pairs in the sentence
            //2. if the angle between them is the best 90 degress angle in comparision to the average angle

            foreach (PageComponent OuterComponent in OuterSentence.Components)
            {
                Distance = PageComponent.DistanceBetweenComponents(OuterComponent, InnerComponent);

                if (Distance < MinDistance && OuterComponent.Type == ePageComponentType.eCharacter)
                {
                    Angle = PageComponent.AngleBetweenComponents(OuterComponent, InnerComponent);
                    Angle = (Angle % 180) - 90 + AverageAngle;

                    if (Math.Abs(Angle) <= 10)
                    {
                        if (Math.Abs(Angle) <= BestAngle)
                        {
                            //Check if the distance isn't to great, but if the angle is exact 90 degrees always
                            //do a merge.
                            if (Distance <= 3 * Math.Max(OuterComponent.Width, OuterComponent.Height) ||
                                Angle == 0)
                            {
                                BestAngle      = Math.Abs(Angle);
                                MergeComponent = OuterComponent;
                                MinDistance    = Distance;
                            }
                        }
                    }
                }
            }

            if (MergeComponent != null)
            {
                //we found a rectangle with which we can merge
                MergeComponent.Merge(InnerComponent);
            }
        }
        /// <summary>
        ///this function add spaces to sentences. Space are added between two
        ///characters when the space between the two is larger than
        ///60 percent of the average width of all the characters in the sentence
        /// </summary>
        /// <param name="Image"></param>

        public static void AddSpacesToSentences(PageImage Image)
        {
            int           Pointer;
            int           AverageWidthCharacters;
            int           WidthBetweenCharacters;
            int           nSpaces;
            PageComponent newSpace;
            Rectangle     newArea;
            Point         Component1, Component2;


            foreach (Sentence Sentence in Image.Sentences)
            {
                Pointer = Sentence.Count - 1;
                AverageWidthCharacters = (int)(Sentence.AverageWidth() * 0.60);

                if (Sentence.Components.Count > 1)
                {
                    while (Pointer > 0)
                    {
                        WidthBetweenCharacters = (int)PageComponent.DistanceBetweenComponents(Sentence.Components[Pointer], Sentence.Components[Pointer - 1]);
                        if (WidthBetweenCharacters >= AverageWidthCharacters && AverageWidthCharacters > 0)
                        {
                            nSpaces    = WidthBetweenCharacters / AverageWidthCharacters;
                            Component1 = Sentence.Components[Pointer - 1].CenterPoint;
                            Component2 = Sentence.Components[Pointer].CenterPoint;

                            for (int j = 0; j < nSpaces; j++)
                            {
                                //to do: the area part is mostly for visualising the space. Doesn't really needs to
                                //be there. This is an option to speed it up.
                                newSpace      = new PageComponent();
                                newSpace.Type = ePageComponentType.eSpace;


                                newArea = new Rectangle((Component2.X - Component1.X) / nSpaces + Component1.X,
                                                        (Component2.Y - Component1.Y) / nSpaces + Component1.Y,
                                                        2,
                                                        2);
                                newSpace.Area = newArea;

                                Sentence.Insert(Pointer, newSpace);
                            }
                        }
                        Pointer--;
                    }
                }
            }
        }
        /// <summary>
        ///This function searches the distance matrix for the closest component
        ///to the given rectangle. The closest component must comply to
        ///the following rules:
        /// * Different from the given component
        /// * Component must not be a part of another sentence
        /// * Must be on the left side of given rectangle (if bLeft is true)
        /// * Must be on the right side of given rectangle (if bLeft is false)
        /// * Angle between rectangle and given rectangle must be less than 5 degrees
        /// </summary>
        /// <param name="Sentence"></param>
        /// <param name="CurrentComponent"></param>
        /// <param name="m_Areas"></param>
        /// <param name="Angle"></param>
        /// <param name="Left"></param>
        /// <returns></returns>

        public static PageComponent FindNearestComponent(Sentence Sentence, PageComponent CurrentComponent, List <DetectionArea> m_Areas, float Angle, bool Left)
        {
            int MinDistance;
            int Distance;

            MinDistance = 2000;

            PageComponent BestCandidate = null;

            int           CurrentAreaIndex;
            DetectionArea Area;


            double AverageAngle       = Sentence.AverageAngle();
            int    MaxAllowedDistance = (int)(Sentence.AverageHeight() * 1.5);
            int    AreaIndex          = CurrentComponent.DetectionAreaIndex;

            for (int Index = 0; Index < 6; Index++)
            {
                //the Index is converted to an area number according to the
                //matrix below. The start point is the center area (lIndex = 2).
                //lIndex 3 is on the left when bleft = true or on the right when bleft = false

                //  *************
                //  * 1 * 0 * 1 *
                //  *************
                //  * 3 * 2 * 3 *
                //  *************
                //  * 5 * 4 * 5 *
                //  *************

                CurrentAreaIndex = AreaIndex;

                //translate the lIndex to the x axis of the areas
                if ((Index & 1) != 0)
                {
                    if (Left)
                    {
                        CurrentAreaIndex--;
                    }
                    else
                    {
                        CurrentAreaIndex++;
                    }
                }

                //translate the Index to the y axis of the areas
                CurrentAreaIndex += ((Index / 2) - 1) * NumberAreasX;

                //the current area number must ly within boundaries (0, number areas)
                //no throw here if it is outside the boundaries because when the area
                //lies on the edge of the image this algorithm will try to go further
                if (CurrentAreaIndex >= 0 && CurrentAreaIndex < m_Areas.Count)
                {
                    Area = m_Areas[CurrentAreaIndex];

                    //loop through all the rectangles in the area
                    foreach (PageComponent Candidate in Area.Components)
                    {
                        if (Candidate.Type == ePageComponentType.eCharacter)
                        {
                            //Candidate neighbour must be on left/right side
                            if ((Left && Candidate.Area.X < CurrentComponent.Area.X) ||
                                (!Left && Candidate.Area.X > CurrentComponent.Area.X))
                            {
                                Distance = PageComponent.DistanceBetweenComponents(CurrentComponent, Candidate);

                                //Distance must be between current minimum and Maximum allowed
                                if (MinDistance > Distance && MaxAllowedDistance > Distance)
                                {
                                    //Angle between rectangle and sentence must be less than 5 degrees
                                    if (PageComponent.AngleBetweenComponents(CurrentComponent, Candidate) < 5 ||
                                        (Sentence.Area.Bottom > Candidate.Area.Top && Sentence.Area.Top < Candidate.Area.Top) ||
                                        (Sentence.Area.Bottom > Candidate.Area.Bottom && Sentence.Area.Top > Candidate.Area.Bottom))
                                    {
                                        BestCandidate = Candidate;
                                        MinDistance   = Distance;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (BestCandidate != null)
            {
                m_Areas[BestCandidate.DetectionAreaIndex].Components.Remove(BestCandidate);
            }


            return(BestCandidate);
        }