private static object Get(
            double x,
            double y,
            double width,
            double height,
            MXCIFQuadTreeNode node)
        {
            if (node is MXCIFQuadTreeNodeLeaf) {
                var leaf = (MXCIFQuadTreeNodeLeaf) node;
                return GetFromData(x, y, width, height, leaf.Data);
            }

            var branch = (MXCIFQuadTreeNodeBranch) node;
            var q = node.Bb.GetQuadrantApplies(x, y, width, height);
            switch (q) {
                case QuadrantAppliesEnum.NW:
                    return Get(x, y, width, height, branch.Nw);

                case QuadrantAppliesEnum.NE:
                    return Get(x, y, width, height, branch.Ne);

                case QuadrantAppliesEnum.SW:
                    return Get(x, y, width, height, branch.Sw);

                case QuadrantAppliesEnum.SE:
                    return Get(x, y, width, height, branch.Se);

                case QuadrantAppliesEnum.SOME:
                    return GetFromData(x, y, width, height, branch.Data);
            }

            throw new IllegalStateException("Not applicable to any quadrant");
        }
        private static ICollection <object> Visit(
            MXCIFQuadTreeNode <object> node,
            double x, double y,
            double width, double height,
            ICollection <object> result)
        {
            var data = node.Data;

            if (data == null)
            {
                return(result);
            }
            if (data is XYWHRectangleMultiType point)
            {
                return(Visit(point, x, y, width, height, result));
            }

            var collection = (ICollection <XYWHRectangleMultiType>)data;

            foreach (XYWHRectangleMultiType rectangle in collection)
            {
                result = Visit(rectangle, x, y, width, height, result);
            }
            return(result);
        }
Esempio n. 3
0
        private static MXCIFQuadTreeNode <object> AddToNode(
            double x, double y,
            double width, double height,
            object value,
            MXCIFQuadTreeNode <object> node,
            MXCIFQuadTree <object> tree,
            bool unique,
            string indexName)
        {
            if (node is MXCIFQuadTreeNodeLeaf <object> )
            {
                var leaf = (MXCIFQuadTreeNodeLeaf <object>)node;

                if (leaf.Count < tree.LeafCapacity || node.Level >= tree.MaxTreeHeight)
                {
                    // can be multiple as value can be a collection
                    var numAdded = AddToData(leaf, x, y, width, height, value, unique, indexName);
                    leaf.IncCount(numAdded);

                    if (leaf.Count <= tree.LeafCapacity || node.Level >= tree.MaxTreeHeight)
                    {
                        return(leaf);
                    }
                }

                node = Subdivide(leaf, tree, unique, indexName);
            }

            var branch = (MXCIFQuadTreeNodeBranch <object>)node;

            AddToBranch(branch, x, y, width, height, value, tree, unique, indexName);
            return(node);
        }
        private static ICollection<object> Visit(
            MXCIFQuadTreeNode node,
            double x,
            double y,
            double width,
            double height,
            ICollection<object> result)
        {
            var data = node.Data;
            if (data == null) {
                return result;
            }

            if (data is XYWHRectangleMultiType point) {
                return Visit(point, x, y, width, height, result);
            } else if (data is IList<XYWHRectangleMultiType> listData) {
                var listDataCount = listData.Count;
                for (var ii = 0; ii < listDataCount; ii++) {
                    result = Visit(listData[ii], x, y, width, height, result);
                }
            } else if (data is IEnumerable<XYWHRectangleMultiType> enumData) {
                foreach (var rectangle in enumData) {
                    result = Visit(rectangle, x, y, width, height, result);
                }
            }
            else {
                throw new IllegalStateException("type-erasure failure");
            }

            return result;
        }
Esempio n. 5
0
        public static bool IsEmpty(MXCIFQuadTreeNode node)
        {
            if (node is MXCIFQuadTreeNodeLeaf leaf) {
                return leaf.Data == null;
            }

            return false;
        }
Esempio n. 6
0
 internal MXCIFQuadTree(
     int leafCapacity,
     int maxTreeHeight,
     MXCIFQuadTreeNode root)
 {
     LeafCapacity = leafCapacity;
     MaxTreeHeight = maxTreeHeight;
     Root = root;
 }
Esempio n. 7
0
        public static bool IsEmpty(MXCIFQuadTreeNode <object> node)
        {
            if (node is MXCIFQuadTreeNodeLeaf <object> leaf)
            {
                return(leaf.Data == null);
            }

            return(false);
        }
Esempio n. 8
0
        private static int Count(MXCIFQuadTreeNode node)
        {
            if (node is MXCIFQuadTreeNodeLeaf) {
                var leaf = (MXCIFQuadTreeNodeLeaf) node;
                return CountData(leaf.Data);
            }

            var branch = (MXCIFQuadTreeNodeBranch) node;
            return Count(branch.Nw) + Count(branch.Ne) + Count(branch.Sw) + Count(branch.Se) + CountData(branch.Data);
        }
Esempio n. 9
0
 public static void Set(
     double x,
     double y,
     double width,
     double height,
     object value,
     MXCIFQuadTree tree)
 {
     MXCIFQuadTreeNode root = tree.Root;
     MXCIFQuadTreeFilterIndexCheckBB.CheckBB(root.Bb, x, y, width, height);
     tree.Root = SetOnNode(x, y, width, height, value, root, tree);
 }
Esempio n. 10
0
        private static int SetOnNodeWithRect(
            MXCIFQuadTreeNode node,
            double x,
            double y,
            double width,
            double height,
            XYWHRectangleWValue value)
        {
            if (!value.CoordinateEquals(x, y, width, height)) {
                throw new IllegalStateException();
            }

            return SetOnNode(node, x, y, width, height, value.Value);
        }
Esempio n. 11
0
        private static int Count <TL>(MXCIFQuadTreeNode <TL> node)
        {
            if (node is MXCIFQuadTreeNodeLeaf <TL> leaf)
            {
                return(CountData <TL>(leaf.Data));
            }

            var branch = (MXCIFQuadTreeNodeBranch <TL>)node;

            return(Count(branch.Nw) +
                   Count(branch.Ne) +
                   Count(branch.Sw) +
                   Count(branch.Se) +
                   CountData <TL>(branch.Data));
        }
        private static void CollectNode(
            MXCIFQuadTreeNode <object> node,
            double x, double y,
            double width, double height,
            EventBean eventBean, TT target,
            QuadTreeCollector <TL, TT> collector)
        {
            var rectangles = node.Data;

            if (rectangles == null)
            {
                return;
            }

            if (rectangles is XYWHRectangleWValue <TL> rectangleX)
            {
                if (BoundingBox.IntersectsBoxIncludingEnd(
                        x,
                        y,
                        x + width,
                        y + height,
                        rectangleX.X,
                        rectangleX.Y,
                        rectangleX.W,
                        rectangleX.H))
                {
                    collector.CollectInto(eventBean, rectangleX.Value, target);
                }

                return;
            }

            var collection = (ICollection <XYWHRectangleWValue <TL> >)rectangles;

            foreach (XYWHRectangleWValue <TL> rectangle in collection)
            {
                if (BoundingBox.IntersectsBoxIncludingEnd(
                        x, y, x + width, y + height,
                        rectangle.X,
                        rectangle.Y,
                        rectangle.W,
                        rectangle.H))
                {
                    collector.CollectInto(eventBean, rectangle.Value, target);
                }
            }
        }
Esempio n. 13
0
        public static void Traverse(
            MXCIFQuadTreeNode node,
            Consumer<object> consumer)
        {
            if (node is MXCIFQuadTreeNodeLeaf) {
                MXCIFQuadTreeNodeLeaf leaf = (MXCIFQuadTreeNodeLeaf) node;
                TraverseData(leaf.Data, consumer);
                return;
            }

            MXCIFQuadTreeNodeBranch branch = (MXCIFQuadTreeNodeBranch) node;
            TraverseData(branch.Data, consumer);
            Traverse(branch.Nw, consumer);
            Traverse(branch.Ne, consumer);
            Traverse(branch.Sw, consumer);
            Traverse(branch.Se, consumer);
        }
        private static int SetOnNode(
            MXCIFQuadTreeNode <object> node,
            double x,
            double y,
            double width,
            double height,
            TL value)
        {
            var currentValue = node.Data;

            if (currentValue == null)
            {
                node.Data = new XYWHRectangleWValue <TL>(x, y, width, height, value);
                return(1);
            }

            if (currentValue is XYWHRectangleWValue <TL> otherXY)
            {
                if (otherXY.CoordinateEquals(x, y, width, height))
                {
                    otherXY.Value = value;
                    return(0);
                }

                var collectionX = new List <XYWHRectangleWValue <TL> >();
                collectionX.Add(otherXY);
                collectionX.Add(new XYWHRectangleWValue <TL>(x, y, width, height, value));
                node.Data = collectionX;
                return(1);
            }

            var collection = (ICollection <XYWHRectangleWValue <TL> >)currentValue;

            foreach (var other in collection)
            {
                if (other.CoordinateEquals(x, y, width, height))
                {
                    other.Value = value;
                    return(0);
                }
            }

            collection.Add(new XYWHRectangleWValue <TL>(x, y, width, height, value));
            return(1);
        }
        private static ICollection <object> QueryNode(
            MXCIFQuadTreeNode <object> node,
            double x, double y,
            double width, double height,
            ICollection <object> result)
        {
            if (node is MXCIFQuadTreeNodeLeaf <object> leaf)
            {
                return(Visit(leaf, x, y, width, height, result));
            }

            var branch = (MXCIFQuadTreeNodeBranch <object>)node;

            result = Visit(branch, x, y, width, height, result);
            result = QueryNode(branch.Nw, x, y, width, height, result);
            result = QueryNode(branch.Ne, x, y, width, height, result);
            result = QueryNode(branch.Sw, x, y, width, height, result);
            result = QueryNode(branch.Se, x, y, width, height, result);
            return(result);
        }
        private static void CollectRange(
            MXCIFQuadTreeNode <object> node,
            double x, double y,
            double width, double height,
            EventBean eventBean, TT target,
            QuadTreeCollector <TL, TT> collector)
        {
            if (node is MXCIFQuadTreeNodeLeaf <object> leaf)
            {
                CollectNode(leaf, x, y, width, height, eventBean, target, collector);
                return;
            }

            var branch = (MXCIFQuadTreeNodeBranch <object>)node;

            CollectNode(branch, x, y, width, height, eventBean, target, collector);
            CollectRange(branch.Nw, x, y, width, height, eventBean, target, collector);
            CollectRange(branch.Ne, x, y, width, height, eventBean, target, collector);
            CollectRange(branch.Sw, x, y, width, height, eventBean, target, collector);
            CollectRange(branch.Se, x, y, width, height, eventBean, target, collector);
        }
Esempio n. 17
0
        private static void CollectRange(
            MXCIFQuadTreeNode node,
            double x,
            double y,
            double width,
            double height,
            EventBean eventBean,
            TT target,
            QuadTreeCollector<TT> collector,
            ExprEvaluatorContext ctx)
        {
            if (node is MXCIFQuadTreeNodeLeaf leaf)
            {
                CollectNode(leaf, x, y, width, height, eventBean, target, collector, ctx);
                return;
            }

            MXCIFQuadTreeNodeBranch branch = (MXCIFQuadTreeNodeBranch) node;
            CollectNode(branch, x, y, width, height, eventBean, target, collector, ctx);
            CollectRange(branch.Nw, x, y, width, height, eventBean, target, collector, ctx);
            CollectRange(branch.Ne, x, y, width, height, eventBean, target, collector, ctx);
            CollectRange(branch.Sw, x, y, width, height, eventBean, target, collector, ctx);
            CollectRange(branch.Se, x, y, width, height, eventBean, target, collector, ctx);
        }
Esempio n. 18
0
        private static MXCIFQuadTreeNode SetOnNode(
            double x,
            double y,
            double width,
            double height,
            object value,
            MXCIFQuadTreeNode node,
            MXCIFQuadTree tree)
        {
            if (node is MXCIFQuadTreeNodeLeaf leaf) {
                var count = SetOnNode(leaf, x, y, width, height, value);
                leaf.IncCount(count);

                if (leaf.Count <= tree.LeafCapacity || node.Level >= tree.MaxTreeHeight) {
                    return leaf;
                }

                node = Subdivide(leaf, tree);
            }

            var branch = (MXCIFQuadTreeNodeBranch) node;
            AddToBranch(branch, x, y, width, height, value, tree);
            return node;
        }
Esempio n. 19
0
        private static void CollectNode(
            MXCIFQuadTreeNode node,
            double x,
            double y,
            double width,
            double height,
            EventBean eventBean,
            TT target,
            QuadTreeCollector<TT> collector,
            ExprEvaluatorContext ctx)
        {
            object rectangles = node.Data;
            if (rectangles == null) {
                return;
            }

            if (rectangles is XYWHRectangleWValue rectangleWValue) {
                if (BoundingBox.IntersectsBoxIncludingEnd(
                    x,
                    y,
                    x + width,
                    y + height,
                    rectangleWValue.X,
                    rectangleWValue.Y,
                    rectangleWValue.W,
                    rectangleWValue.H)) {
                    collector.CollectInto(eventBean, rectangleWValue.Value, target, ctx);
                }
            }
            else if (rectangles is List<XYWHRectangleWValue> listWithType) {
                // Using the enumerable structure has some overhead when called a lot.  So, when
                // we know the value is a list (which it should be), then we attempt to use a
                // traditional loop to avoid the overhead.  Need to measure this against the time
                // cost for List.ForEach()

                var listWithTypeCount = listWithType.Count;
                for (var ii = 0; ii < listWithTypeCount; ii++) {
                    var rectangle = listWithType[ii];
                    if (BoundingBox.IntersectsBoxIncludingEnd(
                        x,
                        y,
                        x + width,
                        y + height,
                        rectangle.X,
                        rectangle.Y,
                        rectangle.W,
                        rectangle.H)) {
                        collector.CollectInto(eventBean, rectangle.Value, target, ctx);
                    }
                }
            }
            else if (rectangles is IEnumerable<XYWHRectangleWValue> enumerableWithType) {
                foreach (var rectangle in enumerableWithType) {
                    if (BoundingBox.IntersectsBoxIncludingEnd(
                        x,
                        y,
                        x + width,
                        y + height,
                        rectangle.X,
                        rectangle.Y,
                        rectangle.W,
                        rectangle.H)) {
                        collector.CollectInto(eventBean, rectangle.Value, target, ctx);
                    }
                }
            }
            else {
                throw new IllegalStateException("unknown type for rectangles");
            }
            }
Esempio n. 20
0
 internal MXCIFQuadTree(int leafCapacity, int maxTreeHeight, MXCIFQuadTreeNode <TL> root)
 {
     _leafCapacity  = leafCapacity;
     _maxTreeHeight = maxTreeHeight;
     _root          = root;
 }
Esempio n. 21
0
        private static MXCIFQuadTreeNode<object> DeleteFromNode(
            double x, double y, 
            double width, double height,
            MXCIFQuadTreeNode<object> node, 
            MXCIFQuadTree<object> tree)
        {
            if (node is MXCIFQuadTreeNodeLeaf<object> leaf)
            {
                var removed = DeleteFromData(x, y, width, height, leaf.Data);
                if (removed)
                {
                    leaf.DecCount();
                    if (leaf.Count == 0) leaf.Data = null;
                }

                return leaf;
            }

            var branch = (MXCIFQuadTreeNodeBranch<object>) node;
            var quadrant = node.Bb.GetQuadrantApplies(x, y, width, height);
            if (quadrant == QuadrantAppliesEnum.NW)
            {
                branch.Nw = DeleteFromNode(x, y, width, height, branch.Nw, tree);
            }
            else if (quadrant == QuadrantAppliesEnum.NE)
            {
                branch.Ne = DeleteFromNode(x, y, width, height, branch.Ne, tree);
            }
            else if (quadrant == QuadrantAppliesEnum.SW)
            {
                branch.Sw = DeleteFromNode(x, y, width, height, branch.Sw, tree);
            }
            else if (quadrant == QuadrantAppliesEnum.SE)
            {
                branch.Se = DeleteFromNode(x, y, width, height, branch.Se, tree);
            }
            else if (quadrant == QuadrantAppliesEnum.SOME)
            {
                var removed = DeleteFromData(x, y, width, height, branch.Data);
                if (removed)
                {
                    branch.DecCount();
                    if (branch.Count == 0) branch.Data = null;
                }
            }

            if (!(branch.Nw is MXCIFQuadTreeNodeLeaf<object> nwLeaf) ||
                !(branch.Ne is MXCIFQuadTreeNodeLeaf<object> neLeaf) ||
                !(branch.Sw is MXCIFQuadTreeNodeLeaf<object> swLeaf) ||
                !(branch.Se is MXCIFQuadTreeNodeLeaf<object> seLeaf))
                return branch;

            var total = nwLeaf.Count + neLeaf.Count + swLeaf.Count + seLeaf.Count + branch.Count;
            if (total >= tree.LeafCapacity) return branch;

            var collection = new LinkedList<XYWHRectangleWValue<TL>>();
            var count = MergeChildNodes(collection, branch.Data);
            count += MergeChildNodes(collection, nwLeaf.Data);
            count += MergeChildNodes(collection, neLeaf.Data);
            count += MergeChildNodes(collection, swLeaf.Data);
            count += MergeChildNodes(collection, seLeaf.Data);
            return new MXCIFQuadTreeNodeLeaf<object>(branch.Bb, branch.Level, collection, count);
        }
Esempio n. 22
0
 public static void Delete(double x, double y, double width, double height, MXCIFQuadTree<object> tree)
 {
     MXCIFQuadTreeNode<object> root = tree.Root;
     MXCIFQuadTreeFilterIndexCheckBB.CheckBB(root.Bb, x, y, width, height);
     tree.Root = DeleteFromNode(x, y, width, height, root, tree);
 }
        private static MXCIFQuadTreeNode RemoveFromNode(
            double x,
            double y,
            double width,
            double height,
            object value,
            MXCIFQuadTreeNode node,
            MXCIFQuadTree tree)
        {
            if (node is MXCIFQuadTreeNodeLeaf leaf) {
                var removed = RemoveFromPoints(x, y, width, height, value, leaf.Data);
                if (removed) {
                    leaf.DecCount();
                    if (leaf.Count == 0) {
                        leaf.Data = null;
                    }
                }

                return leaf;
            }

            var branch = (MXCIFQuadTreeNodeBranch) node;
            var quadrant = node.Bb.GetQuadrantApplies(x, y, width, height);
            switch (quadrant) {
                case QuadrantAppliesEnum.NW:
                    branch.Nw = RemoveFromNode(x, y, width, height, value, branch.Nw, tree);
                    break;

                case QuadrantAppliesEnum.NE:
                    branch.Ne = RemoveFromNode(x, y, width, height, value, branch.Ne, tree);
                    break;

                case QuadrantAppliesEnum.SW:
                    branch.Sw = RemoveFromNode(x, y, width, height, value, branch.Sw, tree);
                    break;

                case QuadrantAppliesEnum.SE:
                    branch.Se = RemoveFromNode(x, y, width, height, value, branch.Se, tree);
                    break;

                case QuadrantAppliesEnum.SOME:
                    var removed = RemoveFromPoints(x, y, width, height, value, branch.Data);
                    if (removed) {
                        branch.DecCount();
                        if (branch.Count == 0) {
                            branch.Data = null;
                        }
                    }

                    break;
            }

            if (!(branch.Nw is MXCIFQuadTreeNodeLeaf) ||
                !(branch.Ne is MXCIFQuadTreeNodeLeaf) ||
                !(branch.Sw is MXCIFQuadTreeNodeLeaf) ||
                !(branch.Se is MXCIFQuadTreeNodeLeaf)) {
                return branch;
            }

            var nwLeaf = (MXCIFQuadTreeNodeLeaf) branch.Nw;
            var neLeaf = (MXCIFQuadTreeNodeLeaf) branch.Ne;
            var swLeaf = (MXCIFQuadTreeNodeLeaf) branch.Sw;
            var seLeaf = (MXCIFQuadTreeNodeLeaf) branch.Se;
            var total = branch.Count + nwLeaf.Count + neLeaf.Count + swLeaf.Count + seLeaf.Count;
            if (total >= tree.LeafCapacity) {
                return branch;
            }

            var collection = new List<XYWHRectangleMultiType>();
            var count = MergeChildNodes(collection, branch.Data);
            count += MergeChildNodes(collection, nwLeaf.Data);
            count += MergeChildNodes(collection, neLeaf.Data);
            count += MergeChildNodes(collection, swLeaf.Data);
            count += MergeChildNodes(collection, seLeaf.Data);
            return new MXCIFQuadTreeNodeLeaf(branch.Bb, branch.Level, collection, count);
        }
Esempio n. 24
0
        public static int AddToData(
            MXCIFQuadTreeNode <object> node,
            double x, double y,
            double width, double height,
            object value,
            bool unique,
            string indexName)
        {
            var currentValue = node.Data;

            // value can be multitype itself since we may subdivide-add and don't want to allocate a new object
            if (value is XYWHRectangleMultiType rectangle)
            {
                if (!rectangle.CoordinateEquals(x, y, width, height))
                {
                    throw new IllegalStateException();
                }

                if (currentValue == null)
                {
                    node.Data = rectangle;
                    return(rectangle.Count());
                }

                if (currentValue is XYWHRectangleMultiType otherXYWHR)
                {
                    if (otherXYWHR.CoordinateEquals(x, y, width, height))
                    {
                        if (unique)
                        {
                            throw HandleUniqueViolation(indexName, otherXYWHR);
                        }

                        otherXYWHR.AddMultiType(rectangle);
                        return(rectangle.Count());
                    }

                    var collectionInner = new LinkedList <XYWHRectangleMultiType>();
                    collectionInner.AddLast(otherXYWHR);
                    collectionInner.AddLast(rectangle);
                    node.Data = collectionInner;
                    return(rectangle.Count());
                }

                var collectionXYWH = (ICollection <XYWHRectangleMultiType>)currentValue;
                foreach (var other in collectionXYWH)
                {
                    if (other.CoordinateEquals(x, y, width, height))
                    {
                        if (unique)
                        {
                            throw HandleUniqueViolation(indexName, other);
                        }

                        other.AddMultiType(rectangle);
                        return(rectangle.Count());
                    }
                }

                collectionXYWH.Add(rectangle);
                return(rectangle.Count());
            }

            if (currentValue == null)
            {
                var point = new XYWHRectangleMultiType(x, y, width, height, value);
                node.Data = point;
                return(1);
            }

            if (currentValue is XYWHRectangleMultiType otherInnerX)
            {
                if (otherInnerX.CoordinateEquals(x, y, width, height))
                {
                    if (unique)
                    {
                        throw HandleUniqueViolation(indexName, otherInnerX);
                    }

                    otherInnerX.AddSingleValue(value);
                    return(1);
                }

                var collectionXY = new LinkedList <XYWHRectangleMultiType>();
                collectionXY.AddLast(otherInnerX);
                collectionXY.AddLast(new XYWHRectangleMultiType(x, y, width, height, value));
                node.Data = collectionXY;
                return(1);
            }

            var collection = (ICollection <XYWHRectangleMultiType>)currentValue;

            foreach (XYWHRectangleMultiType other in collection)
            {
                if (other.CoordinateEquals(x, y, width, height))
                {
                    if (unique)
                    {
                        throw HandleUniqueViolation(indexName, other);
                    }

                    other.AddSingleValue(value);
                    return(1);
                }
            }

            collection.Add(new XYWHRectangleMultiType(x, y, width, height, value));
            return(1);
        }
Esempio n. 25
0
 public void Clear()
 {
     Root = new MXCIFQuadTreeNodeLeaf(Root.Bb, Root.Level, null, 0);
 }
Esempio n. 26
0
        public static int AddToData(
            MXCIFQuadTreeNode node,
            double x,
            double y,
            double width,
            double height,
            object value,
            bool unique,
            string indexName)
        {
            var currentValue = node.Data;

            // value can be multitype itself since we may subdivide-add and don't want to allocate a new object
            if (value is XYWHRectangleMultiType) {
                var rectangle = (XYWHRectangleMultiType) value;
                if (!rectangle.CoordinateEquals(x, y, width, height)) {
                    throw new IllegalStateException();
                }

                if (currentValue == null) {
                    node.Data = rectangle;
                    return rectangle.Count();
                }

                if (currentValue is XYWHRectangleMultiType) {
                    var other = (XYWHRectangleMultiType) currentValue;
                    if (other.CoordinateEquals(x, y, width, height)) {
                        if (unique) {
                            throw HandleUniqueViolation(indexName, other);
                        }

                        other.AddMultiType(rectangle);
                        return rectangle.Count();
                    }

                    ICollection<XYWHRectangleMultiType> collectionX = new List<XYWHRectangleMultiType>();
                    collectionX.Add(other);
                    collectionX.Add(rectangle);
                    node.Data = collectionX;
                    return rectangle.Count();
                }

                var collectionY = (ICollection<XYWHRectangleMultiType>) currentValue;
                foreach (var other in collectionY) {
                    if (other.CoordinateEquals(x, y, width, height)) {
                        if (unique) {
                            throw HandleUniqueViolation(indexName, other);
                        }

                        other.AddMultiType(rectangle);
                        return rectangle.Count();
                    }
                }

                collectionY.Add(rectangle);
                return rectangle.Count();
            }

            if (currentValue == null) {
                node.Data = new XYWHRectangleMultiType(x, y, width, height, value);
                return 1;
            }

            if (currentValue is XYWHRectangleMultiType) {
                var other = (XYWHRectangleMultiType) currentValue;
                if (other.CoordinateEquals(x, y, width, height)) {
                    if (unique) {
                        throw HandleUniqueViolation(indexName, other);
                    }

                    other.AddSingleValue(value);
                    return 1;
                }

                ICollection<XYWHRectangleMultiType> collectionZ = new List<XYWHRectangleMultiType>();
                collectionZ.Add(other);
                collectionZ.Add(new XYWHRectangleMultiType(x, y, width, height, value));
                node.Data = collectionZ;
                return 1;
            }

            var collection = (ICollection<XYWHRectangleMultiType>) currentValue;
            foreach (var other in collection) {
                if (other.CoordinateEquals(x, y, width, height)) {
                    if (unique) {
                        throw HandleUniqueViolation(indexName, other);
                    }

                    other.AddSingleValue(value);
                    return 1;
                }
            }

            collection.Add(new XYWHRectangleMultiType(x, y, width, height, value));
            return 1;
        }