public Timeline getContent(Timeline tl, BoundingBox wnd, double scale)
        {
            // assert: tl intersects wnd and is visible
            // => tl is part of content
            // => tl is loaded
            // => return tl with ChildTimelines

            var content = tl.clone();
            content.isBuffered = true;

            foreach (var child in tl.ChildTimelines)
            {
                if (child.intersects(wnd) && child.isVisible(scale))
                    content.ChildTimelines.Add(getContent(child, wnd, scale));
                else
                    content.ChildTimelines.Add(child.clone());
            }

            return content;
        }
        public Timeline getPath(Timeline tl, BoundingBox wnd, ref Timeline lca)
        {
            // assert: tl contains wnd
            // => tl is part of path

            var path = tl.clone();
            path.Exhibits = new List<Exhibit>();
            lca = tl;

            foreach (var child in tl.ChildTimelines)
            {
                if (child.contains(wnd))
                {
                    path.ChildTimelines.Add(getPath(child, wnd, ref lca));
                    break;
                }
            }

            return path;
        }