/// <summary> Remove until object count is less than count</summary>
        public void RemoveUntil(int count)
        {
            List <GLObjectsWithLabels> toremove = new List <GLObjectsWithLabels>();

            int n = 0;      // index of removal

            while (n < BlockList.Count && Objects > count)
            {
                var blocklist = BlockList[n];

                foreach (var b in blocklist)
                {
                    b.owl.Remove(b.blockindex);     // in owl, remove block
                    if (b.owl.Emptied)              // if block has gone emptied, add to remove list
                    {
                        toremove.Add(b.owl);
                    }
                    Objects -= b.count;
                }

                System.Diagnostics.Debug.Assert(TagsToBlocks.ContainsKey(blocklist[0].tag));

                UserData.Remove(blocklist[0].tag);      // remove the user data associated with the tag
                TagsToBlocks.Remove(blocklist[0].tag);  // remove the tag associated with the blocklist
                n++;
            }

            if (n > 0)      // if removed something
            {
                System.Diagnostics.Debug.WriteLine($"Blocklist {BlockList.Count} remove {n} objects {Objects}");
                BlockList.RemoveRange(0, n);            // and empty block list

                foreach (var removeit in toremove)
                {
                    robjects.Remove(removeit.ObjectRenderer); // remove renders
                    robjects.Remove(removeit.TextRenderer);
                    removeit.Dispose();                       // then dispose
                    set.Remove(removeit);
                }
            }
        }
        /// <summary> Remove the oldest N blocks</summary>
        public void RemoveOldest(int n)
        {
            List <GLObjectsWithLabels> toremove = new List <GLObjectsWithLabels>();

            n = Math.Min(BlockList.Count, n);       // limit

            for (int i = 0; i < n; i++)             // for all block list entries
            {
                var blocklist = BlockList[i];

                foreach (var b in blocklist)
                {
                    b.owl.Remove(b.blockindex);     // in owl, remove block
                    if (b.owl.Emptied)              // if block has gone emptied, add to remove list
                    {
                        toremove.Add(b.owl);
                    }
                    Objects -= b.count;
                }

                System.Diagnostics.Debug.Assert(TagsToBlocks.ContainsKey(blocklist[0].tag));

                UserData.Remove(blocklist[0].tag);      // remove the user data associated with the tag
                TagsToBlocks.Remove(blocklist[0].tag);  // remove the tag associated with the blocklist
            }

            //System.Diagnostics.Debug.WriteLine($"Blocklist {BlockList.Count} remove {n} objects {Objects}");
            BlockList.RemoveRange(0, n);            // and empty block list

            foreach (var removeit in toremove)
            {
                robjects.Remove(removeit.ObjectRenderer); // remove renders
                robjects.Remove(removeit.TextRenderer);
                removeit.Dispose();                       // then dispose
                set.Remove(removeit);
            }
        }