public static QuadTree FromOctree(Octree octree, Vec2 zRange) { var sliceMin = new Vec3(octree.Min.xy, zRange.X); var sliceMax = new Vec3(octree.Max.xy, zRange.Y); var heightThreshold = (zRange.Y - zRange.X) / 2 * 0.99f; octree = octree.Transform((path, transformChildren) => path.Intersects(sliceMin, sliceMax) ? transformChildren() : Octree.Node.Empty); if (!octree.RootPath.FullLeaves.Any()) { return(new QuadTree(octree.Min.xy, octree.Max.xy, Node.Empty, octree.Isosurface)); } octree = octree.MakeFullDepthUniform(); var maxDepth = octree.RootPath.FullLeaves.First().Depth; Node Build(Vec2 min, Vec2 max, int depth) { if (depth < maxDepth) { var halfSize = (max - min) / 2; var center = min + halfSize; var children = Quadrants.Select(x => { var corner = center - halfSize * x; return(Build(corner, corner + halfSize, depth + 1)); }).ToArray(); return(children.All(x => x == Node.Empty) ? Node.Empty : children.All(x => x == Node.Full) ? Node.Full : new Node { Children = children }); } var vcenter = (max - min) / 2 + min; var height = octree.FindLeaves(path => path.Contains(vcenter)).Where(path => path.IsFull) .Select(x => x.Max.Z - x.Min.Z).DefaultIfEmpty(0).Sum(); return(height >= heightThreshold ? Node.Full : Node.Empty); } return(new QuadTree(octree.Min.xy, octree.Max.xy, Build(octree.Min.xy, octree.Max.xy, 0), octree.Isosurface)); }