Ejemplo n.º 1
0
    public bool MinimumTranslationVectorWithContainment(Vector2[] vertices1, Vector2[] vertices2, out MinimumTranslationVector?mtv)
    {
        double  overlap  = Double.PositiveInfinity;
        Vector2 smallest = default(Vector2);

        Vector2[] axes1 = GetAxes(vertices1);
        Vector2[] axes2 = GetAxes(vertices2);

        bool MTVWC(Vector2[] axes)
        {
            for (int i = 0; i < axes.Length; i++)
            {
                Vector2    axis = axes[i];
                Projection p1   = Project(vertices1, axis);
                Projection p2   = Project(vertices2, axis);
                if (!p1.Overlap(p2))
                {
                    return(false);
                }
                else
                {
                    double o = p1.GetOverlap(p2);
                    if (p1.Contains(p2) || p2.Contains(p1))
                    {
                        double mins = Math.Abs(p1.Min - p2.Min);
                        double maxs = Math.Abs(p1.Max - p2.Max);
                        o += mins < maxs ? mins : maxs;
                    }

                    if (o < overlap)
                    {
                        overlap  = o;
                        smallest = axis;
                    }
                }
            }
            return(true);
        }

        if (MTVWC(axes1) == false)
        {
            mtv = default(MinimumTranslationVector?);
            return(false);
        }

        if (MTVWC(axes2) == false)
        {
            mtv = default(MinimumTranslationVector?);
            return(false);
        }

        mtv = new MinimumTranslationVector(smallest, overlap);
        return(true);
    }
Ejemplo n.º 2
0
        private XYNode HorizontalCut(XYLeaf leaf, double minimumWidth,
                                     Func <IEnumerable <Letter>, double> dominantFontWidthFunc,
                                     Func <IEnumerable <Letter>, double> dominantFontHeightFunc, int level = 0)
        {
            // Order words bottom to top
            var words = leaf.Words.OrderBy(w => w.BoundingBox.Normalise().Bottom).ToArray();

            if (words.Length == 0)
            {
                return(new XYNode(null));
            }

            // Create new leaf with non-whitespace words.
            leaf = new XYLeaf(words);

            if (leaf.CountWords() <= 1)
            {
                // We stop cutting if
                // - only one word remains
                return(leaf);
            }

            // Determine dominant font height
            double dominantFontHeight = dominantFontHeightFunc(words.SelectMany(x => x.Letters));

            List <Projection> projectionProfile = new List <Projection>();

            var        firstWordBound    = words[0].BoundingBox.Normalise();
            Projection currentProjection = new Projection(firstWordBound.Bottom, firstWordBound.Top);
            int        wordsCount        = words.Length;

            for (int i = 1; i < wordsCount; i++)
            {
                var currentWordBound = words[i].BoundingBox.Normalise();

                if (currentProjection.Contains(currentWordBound.Bottom) || currentProjection.Contains(currentWordBound.Top))
                {
                    // It is overlapping
                    if (currentWordBound.Bottom >= currentProjection.LowerBound &&
                        currentWordBound.Bottom <= currentProjection.UpperBound &&
                        currentWordBound.Top > currentProjection.UpperBound)
                    {
                        currentProjection.UpperBound = currentWordBound.Top;
                    }
                }
                else
                {
                    // No overlap
                    if (currentWordBound.Bottom - currentProjection.UpperBound <= dominantFontHeight)
                    {
                        // If gap too small -> don't cut
                        // |____| |____|
                        currentProjection.UpperBound = currentWordBound.Top;
                    }
                    else
                    {
                        // If gap big enough -> cut!
                        // |____|   |   |____|
                        if (i != wordsCount - 1) // Will always add the last one after
                        {
                            projectionProfile.Add(currentProjection);
                            currentProjection = new Projection(currentWordBound.Bottom, currentWordBound.Top);
                        }
                    }
                }

                if (i == wordsCount - 1)
                {
                    projectionProfile.Add(currentProjection);
                }
            }

            if (projectionProfile.Count == 1)
            {
                if (level >= 1)
                {
                    return(leaf);
                }
                else
                {
                    level++;
                }
            }

            var newLeavesEnums = projectionProfile.Select(p => leaf.Words.Where(w =>
            {
                // Get words that are contained in each projection profiles
                var normalisedBB = w.BoundingBox.Normalise();
                return(normalisedBB.Bottom >= p.LowerBound && normalisedBB.Top <= p.UpperBound);
            }));

            var newLeaves = newLeavesEnums.Where(e => e.Any()).Select(e => new XYLeaf(e));
            var newNodes  = newLeaves.Select(l => VerticalCut(l, minimumWidth,
                                                              dominantFontWidthFunc, dominantFontHeightFunc, level)).ToList();

            var lost = leaf.Words.Except(newLeavesEnums.SelectMany(x => x)).Where(x => !string.IsNullOrWhiteSpace(x.Text)).ToList();

            if (lost.Count > 0)
            {
                newNodes.AddRange(lost.Select(w => new XYLeaf(w)));
            }
            return(new XYNode(newNodes));
        }
Ejemplo n.º 3
0
        public void Run(TestConfig config)
        {
            int i;
            IDatabase db = config.GetDatabase();
            config.Result = new TestResult();
            Root root = new Root();
            var arr = db.CreateArray<FromRec>(45);
            root.arr = arr;
            db.Root = root;
            db.Commit();
            int projectedEls = 45;
            for (i = 0; i < projectedEls; i++)
            {
                arr.Add(new FromRec(db, i));
            }
            arr[0].toEl = null;

            db.Commit();
            var p1 = new Projection<FromRec, ToRec>("list");
            Tests.Assert(p1.Count == 0);
            Tests.Assert(p1.Length == 0);
            Tests.Assert(!p1.IsReadOnly);
            Tests.Assert(!p1.IsSynchronized);
            Tests.Assert(null == p1.SyncRoot);
            p1.Project(arr);
            Tests.Assert(p1.Count == projectedEls * 5);
            var arrTmp = p1.ToArray();
            Tests.Assert(arrTmp.Length == p1.Length);
            p1.Reset();

            p1.Project(arr[0]);
            Tests.Assert(p1.Length == 5);
            p1.Reset();

            var arr3 = arr.ToArray();
            p1.Project(arr3);
            Tests.Assert(p1.Length == projectedEls * 5);
            p1.Clear();

            IEnumerator<FromRec> e1 = arr.GetEnumerator();
            p1.Project(e1);
            Tests.Assert(p1.Length == projectedEls * 5);

            var p2 = new Projection<FromRec, ToRec>("list2");
            p2.Project(arr);
            Tests.Assert(p2.Length == projectedEls * 5);

            var p3 = new Projection<FromRec, ToRec>("toEl");
            p3.Project(arr);
            Tests.Assert(p2.Length == projectedEls * 5);

            p1.Join<FromRec>(p2);

            Tests.Assert(p1.GetEnumerator() != null);
            IEnumerator eTmp = ((IEnumerable)p1).GetEnumerator();
            Tests.Assert(eTmp != null);

            ToRec[] res = new ToRec[p3.Count];
            p3.CopyTo(res, 0);
            foreach (var tmp in res)
            {
                Tests.Assert(p3.Contains(tmp));
                p3.Remove(tmp);
                Tests.Assert(!p3.Contains(tmp));
            }
            Tests.Assert(0 == p3.Length);
            db.Commit();
            db.Close();
        }
Ejemplo n.º 4
0
        private XYNode VerticalCut(XYLeaf leaf, double minimumWidth,
                                   Func <IEnumerable <Letter>, double> dominantFontWidthFunc,
                                   Func <IEnumerable <Letter>, double> dominantFontHeightFunc, int level = 0)
        {
            // Order words left to right
            var words = leaf.Words.OrderBy(w => w.BoundingBox.Normalise().Left).ToArray();

            if (words.Length == 0)
            {
                return(new XYNode(null));
            }

            // Create new leaf with non-whitespace words.
            leaf = new XYLeaf(words);

            if (leaf.CountWords() <= 1 || leaf.BoundingBox.Width <= minimumWidth)
            {
                // We stop cutting if
                // - only one word remains
                // - width is too small
                return(leaf);
            }

            // Determine dominant font width
            double dominantFontWidth = dominantFontWidthFunc(words.SelectMany(x => x.Letters));

            List <Projection> projectionProfile = new List <Projection>();

            var        firstWordBound    = words[0].BoundingBox.Normalise();
            Projection currentProjection = new Projection(firstWordBound.Left, firstWordBound.Right);
            int        wordsCount        = words.Length;

            for (int i = 1; i < wordsCount; i++)
            {
                var currentWordBound = words[i].BoundingBox.Normalise();

                if (currentProjection.Contains(currentWordBound.Left) || currentProjection.Contains(currentWordBound.Right))
                {
                    // It is overlapping
                    if (currentWordBound.Left >= currentProjection.LowerBound &&
                        currentWordBound.Left <= currentProjection.UpperBound &&
                        currentWordBound.Right > currentProjection.UpperBound)
                    {
                        // |____|
                        //    |____|
                        // |_______|    <- updated
                        currentProjection.UpperBound = currentWordBound.Right;
                    }

                    // We ignore the following cases:
                    //    |____|
                    // |____|          (not possible because of OrderBy)
                    //
                    //    |____|
                    //|___________|    (not possible because of OrderBy)
                    //
                    //  |____|
                    //   |_|
                }
                else
                {
                    // No overlap
                    if (currentWordBound.Left - currentProjection.UpperBound <= dominantFontWidth)
                    {
                        // If gap too small -> don't cut
                        // |____| |____|
                        currentProjection.UpperBound = currentWordBound.Right;
                    }
                    else if (currentProjection.UpperBound - currentProjection.LowerBound < minimumWidth)
                    {
                        // Still too small
                        currentProjection.UpperBound = currentWordBound.Right;
                    }
                    else
                    {
                        // If gap big enough -> cut!
                        // |____|   |   |____|
                        if (i != wordsCount - 1) // Will always add the last one after
                        {
                            projectionProfile.Add(currentProjection);
                            currentProjection = new Projection(currentWordBound.Left, currentWordBound.Right);
                        }
                    }
                }

                if (i == wordsCount - 1)
                {
                    projectionProfile.Add(currentProjection);
                }
            }

            var newLeavesEnums = projectionProfile.Select(p => leaf.Words.Where(w =>
            {
                // Get words that are contained in each projection profiles
                var normalisedBB = w.BoundingBox.Normalise();
                return(normalisedBB.Left >= p.LowerBound && normalisedBB.Right <= p.UpperBound);
            }));

            var newLeaves = newLeavesEnums.Where(e => e.Any()).Select(e => new XYLeaf(e));
            var newNodes  = newLeaves.Select(l => HorizontalCut(l, minimumWidth,
                                                                dominantFontWidthFunc, dominantFontHeightFunc, level)).ToList();

            var lost = leaf.Words.Except(newLeavesEnums.SelectMany(x => x)).Where(x => !string.IsNullOrWhiteSpace(x.Text)).ToList();

            if (lost.Count > 0)
            {
                newNodes.AddRange(lost.Select(w => new XYLeaf(w)));
            }

            return(new XYNode(newNodes));
        }