private ISpatialIndexNode <TBounds, TItem> doSplit(ISpatialIndexNode <TBounds, TItem> node, DynamicRTreeBalanceHeuristic heuristic)
            {
                Boolean isLeaf = node.IsLeaf;

                IEnumerable <IBoundable <TBounds> > boundables =
                    isLeaf
                   ? Caster.Upcast <IBoundable <TBounds>, TItem>(node.Items)
                   : Caster.Upcast <IBoundable <TBounds>, ISpatialIndexNode <TBounds, TItem> >(node.SubNodes);

                Int32 boundablesCount = isLeaf ? node.ItemCount : node.SubNodeCount;

                List <IBoundable <TBounds> > entries = new List <IBoundable <TBounds> >(boundablesCount);

                entries.AddRange(boundables);

                IList <IBoundable <TBounds> > group1 = new List <IBoundable <TBounds> >();
                IList <IBoundable <TBounds> > group2 = new List <IBoundable <TBounds> >();

                pickSeeds(entries, group1, group2);

                Int32 group1Count = 1, group2Count = 1;

                distribute(entries, group1, group2, heuristic, ref group1Count, ref group2Count);

                if (entries.Count > 0)
                {
                    if (group1Count < heuristic.NodeItemMinimumCount)
                    {
                        fillShortGroup(entries, group1, ref group1Count);
                    }
                    else // group2Count < heuristic.NodeItemMinimumCount
                    {
                        fillShortGroup(entries, group2, ref group2Count);
                    }
                }

                node.Clear();


                ISpatialIndexNode <TBounds, TItem> sibling = NodeFactory.CreateNode(node.Level);

                IEnumerable <IBoundable <TBounds> > g1Sized = Enumerable.Take(group1, group1Count);
                IEnumerable <IBoundable <TBounds> > g2Sized = Enumerable.Take(group2, group2Count);

                if (isLeaf)
                {
                    //IEnumerable<TItem> g1Cast = Caster.Downcast<TItem, IBoundable<TBounds>>(g1Sized);
                    node.AddRange(g1Sized);


                    //IEnumerable<TItem> g2Cast = Caster.Downcast<TItem, IBoundable<IExtents>>(g2Sized);
                    sibling.AddRange(g2Sized);
                }
                else
                {
                    //IEnumerable<ISpatialIndexNode<IExtents, TItem>> g1Cast
                    //    = Caster.Downcast<ISpatialIndexNode<IExtents, TItem>, IBoundable<IExtents>>(g1Sized);
                    node.AddRange(g1Sized);

                    //IEnumerable<ISpatialIndexNode<IExtents, TItem>> g2Cast
                    //    = Caster.Downcast<ISpatialIndexNode<IExtents, TItem>, IBoundable<IExtents>>(g2Sized);
                    sibling.AddRange(g2Sized);
                }

                return(sibling);
            }