Exemplo n.º 1
0
        /// <summary>
        /// <para>Checks if a sector is mergeable with other assuming that the other is positioned in at positive direction ( right, bottom or both ).</para>
        /// <para>Therefore, if a sector if mergeable with other, according to this method the same sectors inverted will not be mergeables.</para>
        /// </summary>
        /// <typeparam name="T">Type of the quadtree matrix values.</typeparam>
        /// <param name="original">Original sector.</param>
        /// <param name="other">Other sector.</param>
        /// <param name="get">Getter of the quadtree matrix values.</param>
        /// <param name="equals">Comparator of quadtree matrix elements. Must return true if a value is compared with himself.</param>
        /// <returns>If the original sector is mergeable with other assuming that the other is positioned in at positive direction ( right, bottom or both ).</returns>
        public static bool AreMergeableNotInvertible <T>(QuadTreeSector original, QuadTreeSector other, Func <int, int, T> get, Func <T, T, bool> equals)
        {
            bool notContained     = original.Initial != other.Initial && original.Final != other.Final && original.Initial != other.Final && original.Final != other.Initial;
            bool horitzontalMatch = original.Final.x == other.Initial.x - 1 && original.Final.y == other.Final.y && original.Initial.y == other.Initial.y;
            bool verticalMatch    = original.Final.y == other.Final.y - 1 && original.Final.x == other.Final.x && original.Initial.x == other.Initial.x;
            bool equalsValues     = equals(get(other.Initial.x, other.Initial.y), get(original.Initial.x, original.Initial.y));

            return(notContained && (horitzontalMatch || verticalMatch) && equalsValues);
        }
Exemplo n.º 2
0
    /// <summary>
    /// Checks a quadtree sector. Test if the sector is equal and calls MathFunctions.QuadTree if it isn't.
    /// </summary>
    /// <typeparam name="T">Type of the matrix values.</typeparam>
    /// <param name="sector">Sector to check.</param>
    /// <param name="get">Getter of the matrix values.</param>
    /// <param name="equals">Comparator of matrix elements. Must return true if a value is compared with himself.</param>
    /// <param name="mergeSectors">If the sectors will be merged. Used to pass it to MathFunctions.QuadTree if is called.</param>
    /// <returns>List of the obtained sectors.</returns>
    private static List <QuadTreeSector> QuadTreeSectorCheck <T>(QuadTreeSector sector, Func <int, int, T> get, Func <T, T, bool> equals, bool mergeSectors)
    {
        List <QuadTreeSector> result = new List <QuadTreeSector>();

        if (IsEqualQuadTreeSector(sector, get, equals))
        {
            result.Add(sector);
        }
        else
        {
            result.AddRange(SplitAndMerge(get, equals, sector, mergeSectors));
        }

        return(result);
    }
Exemplo n.º 3
0
    /// <summary>
    /// Check if a quadtree sector is completly equal. For that the first position is compared with all the other positions.
    /// </summary>
    /// <typeparam name="T">Type of the matrix values.</typeparam>
    /// <param name="sector">Sector to check.</param>
    /// <param name="get">Getter of the matrix values.</param>
    /// <param name="equals">Comparator of matrix elements. Must return true if a value is compared with himself.</param>
    /// <returns>If the sector is completely equal.</returns>
    private static bool IsEqualQuadTreeSector <T>(QuadTreeSector sector, Func <int, int, T> get, Func <T, T, bool> equals)
    {
        bool equalGroup = true;

        T lastElement = get(sector.Initial.x, sector.Initial.y);
        T currentElement;

        for (int col = sector.Initial.x; col <= sector.Final.x && equalGroup; col++)
        {
            for (int row = sector.Initial.y; row <= sector.Final.y && equalGroup; row++)
            {
                currentElement = get(col, row);
                equalGroup    &= equals(lastElement, currentElement);
            }
        }

        return(equalGroup);
    }
Exemplo n.º 4
0
        /// <summary>
        /// Tries a merge between the current sector and other. If the merge is not possible, throws a Exception.
        /// </summary>
        /// <typeparam name="T">Type of the quadtree matrix values.</typeparam>
        /// <param name="other">Other sector.</param>
        /// <param name="get">Getter of the quadtree matrix values.</param>
        /// <param name="equals">Comparator of quadtree matrix elements. Must return true if a value is compared with himself.</param>
        /// <returns>The merged sector if is possible. Else, throws a exception.</returns>
        public QuadTreeSector TryMerge <T>(QuadTreeSector other, Func <int, int, T> get, Func <T, T, bool> equals)
        {
            QuadTreeSector result;

            if (AreMergeableNotInvertible(this, other, get, equals))
            {
                result = new QuadTreeSector(this.Initial, other.Final);
            }
            else if (AreMergeableNotInvertible(other, this, get, equals))
            {
                result = new QuadTreeSector(other.Initial, this.Final);
            }
            else
            {
                throw new Exception($"Impossible merge sector {this} with {other}");
            }

            return(result);
        }
Exemplo n.º 5
0
    /// <summary>
    /// Merge a list of quadtree sectors with other list of sectors of a positive position ( more to the right or down ).
    /// </summary>
    /// <typeparam name="T">Type of the matrix values.</typeparam>
    /// <param name="baseSectors">Original list of sectors. Will be modified adding new sectors ( merged or not ).</param>
    /// <param name="greatersSectors">Sectors to try to merge or, instead, add to baseSectors.</param>
    /// <param name="get">Getter of the matrix values.</param>
    /// <param name="equals">Comparator of matrix elements. Must return true if a value is compared with himself.</param>
    private static void MergeQuadTreeSectorsPositive <T>(List <QuadTreeSector> baseSectors, List <QuadTreeSector> greatersSectors, Func <int, int, T> get, Func <T, T, bool> equals)
    {
        QuadTreeSector baseSector;
        bool           isMerged;

        foreach (QuadTreeSector greaterSector in greatersSectors)
        {
            isMerged = false;
            for (int j = 0; j < baseSectors.Count && !isMerged; j++)
            {
                baseSector = baseSectors[j];

                if (QuadTreeSector.AreMergeableNotInvertible(baseSector, greaterSector, get, equals))
                {
                    baseSectors[j] = new QuadTreeSector(baseSector.Initial, greaterSector.Final);
                    isMerged       = true;
                }
            }
            if (!isMerged)
            {
                baseSectors.Add(greaterSector);
            }
        }
    }
Exemplo n.º 6
0
    /// <summary>
    /// <para>Calculates the quadtree sectors of a square matrix sector with a power of two dimensions ( columns and rows ).</para>
    /// <para>Is recursive.</para>
    /// </summary>
    /// <typeparam name="T">Type of the matrix values.</typeparam>
    /// <param name="get">Getter of the matrix values.</param>
    /// <param name="equals">Comparator of matrix elements. Must return true if a value is compared with himself.</param>
    /// <param name="sector">Sector to apply the quadtree algorithm.</param>
    /// <param name="mergeSectors">If is true : some of the mergeable sectors ( equals and have a common size ) will be merged. Implies an additional cost but fewer sectors will be generated.</param>
    /// <returns>List of the obtained sectors.</returns>
    public static List <QuadTreeSector> SplitAndMerge <T>(Func <int, int, T> get, Func <T, T, bool> equals, QuadTreeSector sector, bool mergeSectors)
    {
        List <QuadTreeSector> result         = new List <QuadTreeSector>();
        List <QuadTreeSector> currentSectors = new List <QuadTreeSector>();
        int        firstCol   = sector.Initial.x;
        int        firstRow   = sector.Initial.y;
        Vector2Int sectorSize = sector.Size;

        // If not square sector
        if (sectorSize.x != sectorSize.y)
        {
            throw new Exception($"ERROR QuadTree : Sector [ {sector} ] isn't a square");
        }
        else if (!IsPowerOfTwo(sectorSize.x))
        {
            throw new Exception($"ERROR QuadTree : Sector size [ {sectorSize.x} ] isn't power of two");
        }
        // If only one tile
        else if (sectorSize.x == 1)
        {
            result.Add(sector);
        }
        // Else, check the four sectors
        else
        {
            int midSectorColumns = (sectorSize.x - 1) / 2;
            int midSectorRows    = (sectorSize.y - 1) / 2;
            int midCol           = firstCol + midSectorColumns;
            int midRow           = firstRow + midSectorRows;
            int finalCol         = sector.Final.x;
            int finalRow         = sector.Final.y;

            // Top-left
            result.AddRange(QuadTreeSectorCheck(new QuadTreeSector(firstCol, firstRow, midCol, midRow), get, equals, mergeSectors));

            // Top-right
            currentSectors = QuadTreeSectorCheck(new QuadTreeSector(midCol + 1, firstRow, finalCol, midRow), get, equals, mergeSectors);
            if (mergeSectors)
            {
                MergeQuadTreeSectorsPositive(result, currentSectors, get, equals);
            }
            else
            {
                result.AddRange(currentSectors);
            }

            // Bottom-left
            currentSectors = QuadTreeSectorCheck(new QuadTreeSector(firstCol, midRow + 1, midCol, finalRow), get, equals, mergeSectors);
            if (mergeSectors)
            {
                MergeQuadTreeSectorsPositive(result, currentSectors, get, equals);
            }
            else
            {
                result.AddRange(currentSectors);
            }

            // Bottom-right ( not mergeable with Top-left )
            currentSectors = QuadTreeSectorCheck(new QuadTreeSector(midCol + 1, midRow + 1, finalCol, finalRow), get, equals, mergeSectors);
            if (mergeSectors)
            {
                MergeQuadTreeSectorsPositive(result, currentSectors, get, equals);
            }
            else
            {
                result.AddRange(currentSectors);
            }
        }

        return(result);
    }