/**
         * Get all the instances withing the given radius of the provided location.
         *
         * @param subdivision
         *          If we should get the instance count for subdivisions (grass) or for big cells.
         */
        public int GetInstanceCountLocation(Vector3 position, float radius, bool subdivision)
        {
            int count = 0;

            Vector3 min = position - new Vector3(radius, radius, radius);
            Vector3 max = position + new Vector3(radius, radius, radius);

            float distanceDelta = radius * radius;
            float x, y, z;

            // Iterate divisions
            FoliageCell.IterateMinMax(min, max, false, (int hash) =>
            {
                FoliageCellData cell;

                if (m_FoliageData.TryGetValue(hash, out cell) == false)
                {
                    return;
                }

                if (subdivision == false)
                {
                    // Count all the tree foliage that overlaps the sphere
                    foreach (var data in cell.m_TypeHashLocationsEditor.Values)
                    {
                        foreach (var instances in data.Values)
                        {
                            for (int i = 0; i < instances.Count; i++)
                            {
                                x = instances[i].m_Position.x - position.x;
                                y = instances[i].m_Position.y - position.y;
                                z = instances[i].m_Position.z - position.z;

                                if ((x * x + y * y + z * z) < distanceDelta)
                                {
                                    count++;
                                }
                            }
                        }
                    }
                }
                else
                {
                    // Iterate subdivisions
                    Vector3 minLocal = GetLocalInCell(min, cell);
                    Vector3 maxLocal = GetLocalInCell(max, cell);

                    FoliageCell.IterateMinMax(minLocal, maxLocal, true, (int hashLocal) =>
                    {
                        FoliageCellSubdividedData cellSubdivided;

                        if (cell.m_FoliageDataSubdivided.TryGetValue(hashLocal, out cellSubdivided) == false)
                        {
                            return;
                        }

                        // Count all the grass foliage that overlaps the sphere
                        foreach (var data in cellSubdivided.m_TypeHashLocationsEditor.Values)
                        {
                            foreach (var instances in data.Values)
                            {
                                for (int i = 0; i < instances.Count; i++)
                                {
                                    x = instances[i].m_Position.x - position.x;
                                    y = instances[i].m_Position.y - position.y;
                                    z = instances[i].m_Position.z - position.z;

                                    if ((x * x + y * y + z * z) < distanceDelta)
                                    {
                                        count++;
                                    }
                                }
                            }
                        }
                    });
                }
            });

            return(count);
        }
        /**
         * Removes foliage instances.
         *
         * @return True if we removed anything
         */
        public bool RemoveInstances(int typeHash, Vector3 position, float radius = 0.3f /*30cm default position delta */)
        {
            Vector3 min = position - new Vector3(radius, radius, radius);
            Vector3 max = position + new Vector3(radius, radius, radius);

            bool anyRemoved      = false;
            bool anyGrassRemoved = false;

            float x, y, z;
            float distanceDelta = radius * radius;

            // Remove all the foliage that overlaps the sphere
            FoliageCell.IterateMinMax(min, max, false, (int hash) =>
            {
                if (m_FoliageData.ContainsKey(hash) == false)
                {
                    return;
                }

                FoliageCellData cell = m_FoliageData[hash];

                // Remove the types from the cell
                if (cell.m_TypeHashLocationsEditor.ContainsKey(typeHash))
                {
                    var labeledData = cell.m_TypeHashLocationsEditor[typeHash];

                    foreach (var instances in labeledData.Values)
                    {
                        for (int i = instances.Count - 1; i >= 0; i--)
                        {
                            x = instances[i].m_Position.x - position.x;
                            y = instances[i].m_Position.y - position.y;
                            z = instances[i].m_Position.z - position.z;

                            // If we are at a distance smaller than the threshold then remove the instance
                            if ((x * x + y * y + z * z) < distanceDelta)
                            {
                                instances.RemoveAt(i);

                                // We removed from the cell, we have to recalculate the extended bounds
                                anyRemoved = true;
                            }
                        }
                    }
                }

                // Remove the types from the subdivided cells

                // Iterate subdivisions
                Vector3 minLocal = GetLocalInCell(min, cell);
                Vector3 maxLocal = GetLocalInCell(max, cell);

                FoliageCell.IterateMinMax(minLocal, maxLocal, true, (int hashLocal) =>
                {
                    FoliageCellSubdividedData cellSubdivided;

                    if (cell.m_FoliageDataSubdivided.TryGetValue(hashLocal, out cellSubdivided) == false)
                    {
                        return;
                    }

                    // Count all the grass foliage that overlaps the sphere
                    if (cellSubdivided.m_TypeHashLocationsEditor.ContainsKey(typeHash))
                    {
                        var data = cellSubdivided.m_TypeHashLocationsEditor[typeHash];

                        foreach (var instances in data.Values)
                        {
                            for (int i = instances.Count - 1; i >= 0; i--)
                            {
                                x = instances[i].m_Position.x - position.x;
                                y = instances[i].m_Position.y - position.y;
                                z = instances[i].m_Position.z - position.z;

                                // If we are at a distance smaller than the threshold then remove the instance
                                if ((x * x + y * y + z * z) < distanceDelta)
                                {
                                    instances.RemoveAt(i);

                                    // Just for grass removal...
                                    anyGrassRemoved = true;
                                }
                            }
                        }
                    }

                    RemoveEmptyTypeDataCellSubdivided(cellSubdivided);
                    if (IsSubCellEmpty(cellSubdivided))
                    {
                        cell.m_FoliageDataSubdivided.Remove(hashLocal);
                    }
                });

                // If we removed everything from a cell then clear it from the list completely
                RemoveEmptyTypeDataCell(cell);
                if (IsCellEmpty(cell))
                {
                    m_FoliageData.Remove(hash);
                }
            });

            if (anyRemoved)
            {
                RecalculateBoundsAfterRemove();
            }

            return(anyRemoved || anyGrassRemoved);
        }