Exemple #1
0
        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));
        }