public void HasBoundingBoxExact()
        {
            var storage = PointSetTests.CreateStorage();

            var ps = new[]
            {
                new V3d(0.1, 0.1, 0.1),
                new V3d(0.9, 0.1, 0.1),
                new V3d(0.9, 0.9, 0.1),
                new V3d(0.1, 0.9, 0.1),
                new V3d(0.1, 0.1, 0.9),
                new V3d(0.9, 0.1, 0.9),
                new V3d(0.9, 0.9, 0.9),
                new V3d(0.1, 0.9, 0.9),
            };

            var config = ImportConfig.Default.WithStorage(storage).WithRandomKey();
            var n      = PointCloud.Chunks(new Chunk(ps, null), config).Root.Value;

            Assert.IsTrue(n.HasBoundingBoxExactLocal);
            Assert.IsTrue(n.BoundingBoxExactLocal == new Box3f(new V3f(-0.4f), new V3f(0.4f)));

            Assert.IsTrue(n.HasBoundingBoxExactGlobal);
            Assert.IsTrue(n.BoundingBoxExactGlobal.Min.ApproxEqual(new V3d(0.1), 1e-6));
            Assert.IsTrue(n.BoundingBoxExactGlobal.Max.ApproxEqual(new V3d(0.9), 1e-6));
        }
Beispiel #2
0
        public void CanImportChunk_Reproject()
        {
            int n  = 10;
            var ps = new V3d[n];

            for (var i = 0; i < n; i++)
            {
                ps[i] = new V3d(i, 0, 0);
            }
            var bb = new Box3d(ps);

            var chunk = new Chunk(ps);

            Assert.IsTrue(chunk.Count == 10);
            Assert.IsTrue(chunk.BoundingBox == bb);

            var config = ImportConfig.Default
                         .WithStorage(PointCloud.CreateInMemoryStore())
                         .WithKey("test")
                         .WithOctreeSplitLimit(10)
                         .WithReproject(xs => xs.Select(x => x += V3d.OIO).ToArray())
            ;
            var pointcloud = PointCloud.Chunks(chunk, config);

            Assert.IsTrue(pointcloud.BoundingBox == bb + V3d.OIO);
        }
Beispiel #3
0
        public void CanImport_WithoutKey()
        {
            int n  = 10;
            var ps = new V3d[n];

            for (var i = 0; i < n; i++)
            {
                ps[i] = new V3d(i, 0, 0);
            }

            var chunk = new Chunk(ps);

            Assert.IsTrue(chunk.Count == 10);

            var config = ImportConfig.Default
                         .WithStorage(PointCloud.CreateInMemoryStore())
                         .WithKey(null)
                         .WithOctreeSplitLimit(10)
                         .WithCreateOctreeLod(false)
                         .WithDeduplicateChunks(false)
                         .WithMinDist(0.0)
                         .WithReproject(null)
                         .WithEstimateNormals(null)
            ;
            var pointcloud = PointCloud.Chunks(chunk, config);

            Assert.IsTrue(pointcloud.Id != null);
        }
        public void HasPointDistance()
        {
            var storage = PointSetTests.CreateStorage();

            var ps = new[]
            {
                new V3d(0.1, 0.1, 0.1),
                new V3d(0.9, 0.1, 0.1),
                new V3d(0.9, 0.9, 0.1),
                new V3d(0.1, 0.9, 0.1),
                new V3d(0.1, 0.1, 0.9),
                new V3d(0.9, 0.1, 0.9),
                new V3d(0.9, 0.9, 0.9),
                new V3d(0.1, 0.9, 0.9),
            };

            var config = ImportConfig.Default.WithStorage(storage).WithRandomKey();
            var n      = PointCloud.Chunks(new Chunk(ps, null), config).Root.Value;

            Assert.IsTrue(n.HasPointDistanceAverage);
            Assert.IsTrue(n.HasPointDistanceStandardDeviation);

            Assert.IsTrue(n.PointDistanceAverage.ApproximateEquals(0.8f, 1e-5f));
            Assert.IsTrue(n.PointDistanceStandardDeviation.ApproximateEquals(0.0f, 1e-5f));
        }
        public void NoLod()
        {
            var chunk = new Chunk(new[]
            {
                new V3d(0, 0, 0),
                new V3d(1, 0, 0),
                new V3d(1, 1, 0),
                new V3d(0, 1, 0)
            });

            var config = ImportConfig.Default
                         .WithInMemoryStore()
                         .WithRandomKey()
                         .WithCreateOctreeLod(false)
            ;
            var cloud = PointCloud.Chunks(chunk, config);

            Assert.IsTrue(cloud.HasNormals == false);
            Assert.IsTrue(cloud.HasLodNormals == false);

            config = config
                     .WithRandomKey()
                     .WithEstimateNormals(ps => Normals.EstimateNormals((V3d[])ps, 5))
            ;
            var cloud2 = cloud.GenerateNormals(config);

            Assert.IsTrue(cloud2.HasNormals == true);
            Assert.IsTrue(cloud2.Root.Value.Normals.Value.All(n => n == V3f.OOI));
            Assert.IsTrue(cloud2.HasLodNormals == false);
        }
        public void HasCentroid()
        {
            var storage = PointSetTests.CreateStorage();

            var ps = new[]
            {
                new V3d(0.1, 0.1, 0.1),
                new V3d(0.9, 0.1, 0.1),
                new V3d(0.9, 0.9, 0.1),
                new V3d(0.1, 0.9, 0.1),
                new V3d(0.1, 0.1, 0.9),
                new V3d(0.9, 0.1, 0.9),
                new V3d(0.9, 0.9, 0.9),
                new V3d(0.1, 0.9, 0.9),
            };

            var config = ImportConfig.Default.WithStorage(storage).WithRandomKey();
            var n      = PointCloud.Chunks(new Chunk(ps, null), config).Root.Value;

            Assert.IsTrue(n.HasCentroidLocal);
            Assert.IsTrue(n.HasCentroidLocalStdDev);

            Assert.IsTrue(n.CentroidLocal.ApproxEqual(V3f.Zero, 1e-5f));
            Assert.IsTrue(n.CentroidLocalStdDev.ApproximateEquals(0.0f, 1e-5f));
        }
        public void HasTreeDepth2()
        {
            var r       = new Random();
            var storage = PointSetTests.CreateStorage();

            var ps = new V3d[20000].SetByIndex(_ => new V3d(r.NextDouble(), r.NextDouble(), r.NextDouble()));

            var config = ImportConfig.Default.WithStorage(storage).WithRandomKey();
            var n      = PointCloud.Chunks(new Chunk(ps, null), config).Root.Value;

            Assert.IsTrue(n.HasMinTreeDepth);
            Assert.IsTrue(n.HasMaxTreeDepth);

            Assert.IsTrue(n.MinTreeDepth == 1);
            Assert.IsTrue(n.MaxTreeDepth == 1);
        }
Beispiel #8
0
        private static PointSet CreateRandomPointsInUnitCube(int n, int splitLimit)
        {
            var r  = new Random();
            var ps = new V3d[n];

            for (var i = 0; i < n; i++)
            {
                ps[i] = new V3d(r.NextDouble(), r.NextDouble(), r.NextDouble());
            }
            var config = ImportConfig.Default
                         .WithStorage(PointCloud.CreateInMemoryStore())
                         .WithKey("test")
                         .WithOctreeSplitLimit(splitLimit)
            ;

            return(PointCloud.Chunks(new Chunk(ps, null), config));
        }
Beispiel #9
0
        internal static void TestKNearest()
        {
            var sw   = new Stopwatch();
            var rand = new Random();

            Report.BeginTimed("generating point clouds");
            var cloud0 = CreateRandomPointsInUnitCube(1000000, 8192);
            var cloud1 = CreateRandomPointsInUnitCube(1000000, 8192);

            Report.EndTimed();

            var ps0 = cloud0.QueryAllPoints().SelectMany(chunk => chunk.Positions).ToArray();

            sw.Restart();
            for (var i = 0; i < ps0.Length; i++)
            {
                var p = cloud1.QueryPointsNearPoint(ps0[i], 0.1, 1);
                if (i % 100000 == 0)
                {
                    Console.WriteLine($"{i,20:N0}     {sw.Elapsed}");
                }
            }
            sw.Stop();
            Console.WriteLine($"{ps0.Length,20:N0}     {sw.Elapsed}");

            PointSet CreateRandomPointsInUnitCube(int n, int splitLimit)
            {
                var r  = new Random();
                var ps = new V3d[n];

                for (var i = 0; i < n; i++)
                {
                    ps[i] = new V3d(r.NextDouble(), r.NextDouble(), r.NextDouble());
                }
                var config = ImportConfig.Default
                             .WithStorage(PointCloud.CreateInMemoryStore(new LruDictionary <string, object>(1024 * 1024 * 1024)))
                             .WithKey("test")
                             .WithOctreeSplitLimit(splitLimit)
                ;

                return(PointCloud.Chunks(new Chunk(ps, null), config));
            }
        }
Beispiel #10
0
        public void CanImport_DuplicateKey()
        {
            int n  = 10;
            var ps = new V3d[n];

            for (var i = 0; i < n; i++)
            {
                ps[i] = new V3d(i, 0, 0);
            }

            var chunk = new Chunk(ps);

            Assert.IsTrue(chunk.Count == 10);

            var config = ImportConfig.Default
                         .WithStorage(PointCloud.CreateInMemoryStore())
                         .WithKey("test")
                         .WithOctreeSplitLimit(10)
                         .WithCreateOctreeLod(false)
                         .WithDeduplicateChunks(false)
                         .WithMinDist(0.0)
                         .WithReproject(null)
                         .WithEstimateNormals(null)
            ;


            var pointcloud = PointCloud.Chunks(new Chunk[] { }, config);

            Assert.IsTrue(pointcloud.Id != null);
            Assert.IsTrue(pointcloud.PointCount == 0);


            var pointcloud2 = PointCloud.Chunks(chunk, config);

            Assert.IsTrue(pointcloud2.Id != null);
            Assert.IsTrue(pointcloud2.PointCount == 10);


            var reloaded = config.Storage.GetPointSet("test", CancellationToken.None);

            Assert.IsTrue(reloaded.PointCount == 10);
        }
Beispiel #11
0
        public void CanParsePtsChunksThenImportThenLoadFromStore()
        {
            var filename = Path.Combine(Config.TestDataDir, "test.pts");

            if (!File.Exists(filename))
            {
                Assert.Ignore($"File not found: {filename}");
            }
            TestContext.WriteLine($"testfile is '{filename}'");
            var config = ImportConfig.Default
                         .WithStorage(PointCloud.CreateInMemoryStore())
                         .WithKey("test")
            ;
            var ptsChunks = Data.Points.Import.Pts.Chunks(filename, config);
            var pointset  = PointCloud.Chunks(ptsChunks, config);

            Assert.IsTrue(pointset.Id == "test");
            var pointset2 = config.Storage.GetPointSet("test", CancellationToken.None);

            Assert.IsTrue(pointset2 != null);
            Assert.IsTrue(pointset2.PointCount == 3);
        }
Beispiel #12
0
        public void CanImportChunk_EstimateNormals()
        {
            int n  = 10;
            var ps = new V3d[n];

            for (var i = 0; i < n; i++)
            {
                ps[i] = new V3d(i, 0, 0);
            }

            var chunk = new Chunk(ps);

            Assert.IsTrue(chunk.Count == 10);

            var config = ImportConfig.Default
                         .WithStorage(PointCloud.CreateInMemoryStore())
                         .WithKey("test")
                         .WithOctreeSplitLimit(10)
            ;
            var pointcloud = PointCloud.Chunks(chunk, config);
            var node       = pointcloud.Root.Value;

            Assert.IsTrue(node.IsLeaf);
            Assert.IsTrue(node.HasNormals == false);


            config = ImportConfig.Default
                     .WithStorage(PointCloud.CreateInMemoryStore())
                     .WithKey("test")
                     .WithOctreeSplitLimit(10)
                     .WithEstimateNormals(xs => xs.Select(x => V3f.OOI).ToArray())
            ;
            pointcloud = PointCloud.Chunks(chunk, config);
            node       = pointcloud.Root.Value;
            Assert.IsTrue(node.IsLeaf);
            Assert.IsTrue(node.HasNormals == true);
            Assert.IsTrue(node.Normals.Value.All(x => x == V3f.OOI));
        }
Beispiel #13
0
        internal static void PerfTestJuly2019()
        {
            var filename = @"T:\Vgm\Data\2017-10-20_09-44-27_1mm_shade_norm_5pp - Cloud.pts";
            //var filename = @"T:\Vgm\Data\JBs_Haus.pts";

            var config = ImportConfig.Default
                         .WithInMemoryStore()
                         .WithRandomKey()
                         .WithVerbose(true)
                         .WithMaxDegreeOfParallelism(0)
                         .WithMinDist(0.01)
                         .WithNormalizePointDensityGlobal(true)
            ;

            Report.BeginTimed("total");

            var chunks = Pts.Chunks(filename, config.ParseConfig);
            var pc     = PointCloud.Chunks(chunks, config);

            Report.EndTimed();

            Report.Line($"count -> {pc.PointCount}");
        }
Beispiel #14
0
        private static PointSet CreateRegularPointsInUnitCube(int n, int splitLimit)
        {
            var ps    = new List <V3d>();
            var step  = 1.0 / n;
            var start = step * 0.5;

            for (var x = start; x < 1.0; x += step)
            {
                for (var y = start; y < 1.0; y += step)
                {
                    for (var z = start; z < 1.0; z += step)
                    {
                        ps.Add(new V3d(x, y, z));
                    }
                }
            }
            var config = ImportConfig.Default
                         .WithStorage(PointCloud.CreateInMemoryStore())
                         .WithKey("test")
                         .WithOctreeSplitLimit(splitLimit)
            ;

            return(PointCloud.Chunks(new Chunk(ps, null), config));
        }
Beispiel #15
0
        public void CanImport_Empty()
        {
            var config = ImportConfig.Default
                         .WithStorage(PointCloud.CreateInMemoryStore())
                         .WithKey("test")
                         .WithOctreeSplitLimit(10)
                         .WithCreateOctreeLod(false)
                         .WithDeduplicateChunks(false)
                         .WithMinDist(0.0)
                         .WithReproject(null)
                         .WithEstimateNormals(null)
            ;


            var pointcloud = PointCloud.Chunks(new Chunk[] { }, config);

            Assert.IsTrue(pointcloud.Id == "test");
            Assert.IsTrue(pointcloud.PointCount == 0);

            var reloaded = config.Storage.GetPointSet("test", CancellationToken.None);

            Assert.IsTrue(reloaded.Id == "test");
            Assert.IsTrue(reloaded.PointCount == 0);
        }
Beispiel #16
0
        public void CanImportChunk_MinDist()
        {
            int n  = 100;
            var r  = new Random();
            var ps = new V3d[n];

            for (var i = 0; i < n; i++)
            {
                ps[i] = new V3d(r.NextDouble(), r.NextDouble(), r.NextDouble());
            }
            var chunk = new Chunk(ps);

            Assert.IsTrue(chunk.Count == 100);

            var config = ImportConfig.Default
                         .WithStorage(PointCloud.CreateInMemoryStore())
                         .WithKey("test")
                         .WithOctreeSplitLimit(10)
                         .WithMinDist(0.5)
            ;
            var pointcloud = PointCloud.Chunks(chunk, config);

            Assert.IsTrue(pointcloud.PointCount < 100);
        }
Beispiel #17
0
        public void ProgressCallbackWorks()
        {
            var CHUNKSIZE  = 10000;
            var CHUNKCOUNT = 10;

            var countProgressCallbacks = 0L;

            var config = ImportConfig.Default
                         .WithStorage(PointCloud.CreateInMemoryStore())
                         .WithKey("test")
                         .WithProgressCallback(x => Interlocked.Increment(ref countProgressCallbacks));

            ;

            var pointcloud = PointCloud.Chunks(GenerateChunks(CHUNKSIZE).Take(CHUNKCOUNT), config);

            Assert.IsTrue(pointcloud.PointCount == CHUNKSIZE * CHUNKCOUNT);

            Assert.IsTrue(countProgressCallbacks > 10);


            IEnumerable <Chunk> GenerateChunks(int numberOfPointsPerChunk)
            {
                var r = new Random();

                while (true)
                {
                    var _ps = new V3d[numberOfPointsPerChunk];
                    for (var i = 0; i < numberOfPointsPerChunk; i++)
                    {
                        _ps[i] = new V3d(r.NextDouble(), r.NextDouble(), r.NextDouble());
                    }
                    yield return(new Chunk(_ps));
                }
            }
        }
Beispiel #18
0
        internal static void TestE57()
        {
            var sw = new Stopwatch();

            CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
            var filename        = @"T:\Vgm\Data\E57\Innenscan_FARO.e57";
            var fileSizeInBytes = new FileInfo(filename).Length;

            var info = E57.E57Info(filename, ParseConfig.Default);

            Report.Line($"total bounds: {info.Bounds}");
            Report.Line($"total count : {info.PointCount:N0}");

            var config = ImportConfig.Default
                         .WithInMemoryStore()
                         .WithRandomKey()
                         .WithVerbose(true)
                         .WithMaxDegreeOfParallelism(0)
                         .WithMinDist(0.01)
            ;

            Report.BeginTimed("total");

            var chunks = E57
                         .Chunks(filename, config.ParseConfig)
                         //.Take(10)
                         //.AsParallel()
                         //.Select(x => x.ImmutableFilterMinDistByCell(new Cell(x.BoundingBox), config))
                         //.Select(x => x.ImmutableFilterSequentialMinDistL1(0.01))
                         //.ToArray()
            ;
            var pc = PointCloud.Chunks(chunks, config);

            Report.EndTimed();

            //var memstore = new SimpleMemoryStore().ToPointCloudStore();

            // classic
            //var foo = chunks.AsParallel().Select(x => InMemoryPointSet.Build(x, 8192).ToPointSetCell(memstore));
            //var r = foo.MapReduceParallel((first, second, ct2) =>
            //{
            //    var merged = first.Merge(second, 8192, null, default);
            //    memstore.Add(Guid.NewGuid().ToString(), merged, default);
            //    Report.Line($"{first.PointCountTree,12:N0} + {second.PointCountTree,12:N0} -> {merged.PointCountTree,12:N0}");
            //    return merged;
            //}, 0);

            //// test 1
            //Report.BeginTimed("merging all chunks");
            //var chunk = Chunk.Empty;
            //foreach (var x in chunks) chunk = Chunk.ImmutableMerge(chunk, x);
            //Report.Line($"points     : {chunk.Count:N0}");
            //Report.EndTimed();

            //Report.BeginTimed("filter mindist");
            //chunk = chunk.ImmutableFilterMinDistByCell(0.01, new Cell(chunk.BoundingBox));
            //Report.Line($"points     : {chunk.Count:N0}");
            //Report.EndTimed();

            //Report.BeginTimed("slots");
            //var slots = chunk.Positions.GroupBy(p => (V3i)p).ToArray();
            //Report.Line($"[slots] {slots.Length}");
            //var slotsCountAvg = slots.Sum(x => x.Count() / (double)slots.Length);
            //var slotsCountMin = slots.Min(x => x.Count());
            //var slotsCountMax = slots.Max(x => x.Count());
            //var slotsCountSd = (slots.Sum(x => (x.Count() - slotsCountAvg).Square()) / slots.Length).Sqrt();
            //Report.Line($"[slots] count avg = {slotsCountAvg}");
            //Report.Line($"[slots] count min = {slotsCountMin}");
            //Report.Line($"[slots] count max = {slotsCountMax}");
            //Report.Line($"[slots] count sd  = {slotsCountSd}");
            //Report.EndTimed();


            //Report.BeginTimed("build octree");
            //var octree = InMemoryPointSet.Build(chunk, 8192);
            //Report.EndTimed();

            //Report.BeginTimed("toPointSetCell");
            //var psc = octree.ToPointSetCell(memstore);
            //var ps = new PointSet(memstore, "foo", psc.Id, 8192);
            //Report.EndTimed();

            //Report.BeginTimed("generate lod");
            //var psWithNormals = ps.GenerateLod(config);
            //Report.EndTimed();



            //Report.Line($"chunks: {foo.Count}");



            //return;

            //var lastProgress = 0.0;
            //config = ImportConfig.Default
            //    .WithInMemoryStore()
            //    .WithRandomKey()
            //    .WithVerbose(false)
            //    .WithMaxDegreeOfParallelism(0)
            //    .WithMinDist(0.01)
            //    .WithProgressCallback(x =>
            //    {
            //        if (x < lastProgress) Console.WriteLine("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH"); else lastProgress = x;
            //        Console.WriteLine($"[PROGRESS]; {x,8:0.00000}; {sw.Elapsed.TotalSeconds:0.00}");
            //    })
            //    ;

            //chunks = E57.Chunks(filename, config.ParseConfig);
            //var pointcloud = PointCloud.Chunks(chunks, config);
            //Console.WriteLine($"pointcloud.PointCount  : {pointcloud.PointCount}");
            //Console.WriteLine($"pointcloud.Bounds      : {pointcloud.Bounds}");
            //Console.WriteLine($"pointcloud.BoundingBox : {pointcloud.BoundingBox}");

            //var chunks = E57.Chunks(filename, config);
            //var pointcloud = PointCloud.Chunks(chunks, config);
            //Console.WriteLine($"pointcloud.PointCount  : {pointcloud.PointCount}");
            //Console.WriteLine($"pointcloud.Bounds      : {pointcloud.Bounds}");
            //Console.WriteLine($"pointcloud.BoundingBox : {pointcloud.BoundingBox}");


            //var leafLodPointCount = 0L;
            //pointcloud.Root.Value.ForEachNode(true, n => { if (n.IsLeaf) leafLodPointCount += n.LodPositionsAbsolute.Length; });
            //Console.WriteLine($"leaf lod point count :{leafLodPointCount}");

            //foreach (var chunk in chunks)
            //{
            //    for (var i = 0; i < chunk.Count; i++)
            //    {
            //        Console.WriteLine($"{chunk.Positions[i]:0.000} {chunk.Colors?[i]}");
            //    }
            //}

            //Console.WriteLine($"chunks point count: {chunks.Sum(x => x.Positions.Count)}");
            //Console.WriteLine($"chunks bounds     : {new Box3d(chunks.SelectMany(x => x.Positions))}");

            //using (var w = File.CreateText("test.txt"))
            //{
            //    foreach (var chunk in chunks)
            //    {
            //        for (var i = 0; i < chunk.Count; i++)
            //        {
            //            var p = chunk.Positions[i];
            //            var c = chunk.Colors[i];
            //            w.WriteLine($"{p.X} {p.Y} {p.Z} {c.R} {c.G} {c.B}");
            //        }
            //    }
            //}
            //return;

            /*
             * var stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
             * ASTM_E57.VerifyChecksums(stream, fileSizeInBytes);
             * var header = ASTM_E57.E57FileHeader.Parse(stream);
             *
             * //Report.BeginTimed("parsing E57 file");
             * //var take = int.MaxValue;
             * //var data = header.E57Root.Data3D.SelectMany(x => x.StreamCartesianCoordinates(false)).Take(take).Chunk(1000000).ToList();
             * //Report.EndTimed();
             * //Report.Line($"#points: {data.Sum(xs => xs.Length)}");
             *
             * foreach (var p in header.E57Root.Data3D.SelectMany(x => x.StreamPoints(false))) Console.WriteLine(p.Item1);
             *
             * //var ps = PointCloud.Parse(filename, ImportConfig.Default)
             * //    .SelectMany(x => x.Positions)
             * //    .ToArray()
             * //    ;
             */
        }
Beispiel #19
0
        internal static void TestE57()
        {
            CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
            var filename        = @"test.e57";
            var fileSizeInBytes = new FileInfo(filename).Length;

            var config = ImportConfig.Default
                         .WithInMemoryStore()
                         .WithRandomKey()
                         .WithVerbose(true)
                         .WithMaxDegreeOfParallelism(0)
                         .WithMinDist(0.005)
            ;

            var chunks     = E57.Chunks(filename, config).ToList();
            var pointcloud = PointCloud.Chunks(chunks, config);

            Console.WriteLine($"pointcloud.PointCount  : {pointcloud.PointCount}");
            Console.WriteLine($"pointcloud.Bounds      :{pointcloud.Bounds}");
            Console.WriteLine($"pointcloud.BoundingBox :{pointcloud.BoundingBox}");

            var leafLodPointCount = 0L;

            pointcloud.Root.Value.ForEachNode(true, n => { if (n.IsLeaf)
                                                           {
                                                               leafLodPointCount += n.LodPositionsAbsolute.Length;
                                                           }
                                              });
            Console.WriteLine($"leaf lod point count :{leafLodPointCount}");

            //foreach (var chunk in chunks)
            //{
            //    for (var i = 0; i < chunk.Count; i++)
            //    {
            //        Console.WriteLine($"{chunk.Positions[i]:0.000} {chunk.Colors?[i]}");
            //    }
            //}

            Console.WriteLine($"chunks point count: {chunks.Sum(x => x.Positions.Count)}");
            Console.WriteLine($"chunks bounds     : {new Box3d(chunks.SelectMany(x => x.Positions))}");

            //using (var w = File.CreateText("test.txt"))
            //{
            //    foreach (var chunk in chunks)
            //    {
            //        for (var i = 0; i < chunk.Count; i++)
            //        {
            //            var p = chunk.Positions[i];
            //            var c = chunk.Colors[i];
            //            w.WriteLine($"{p.X} {p.Y} {p.Z} {c.R} {c.G} {c.B}");
            //        }
            //    }
            //}
            //return;

            /*
             * var stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
             * ASTM_E57.VerifyChecksums(stream, fileSizeInBytes);
             * var header = ASTM_E57.E57FileHeader.Parse(stream);
             *
             * //Report.BeginTimed("parsing E57 file");
             * //var take = int.MaxValue;
             * //var data = header.E57Root.Data3D.SelectMany(x => x.StreamCartesianCoordinates(false)).Take(take).Chunk(1000000).ToList();
             * //Report.EndTimed();
             * //Report.Line($"#points: {data.Sum(xs => xs.Length)}");
             *
             * foreach (var p in header.E57Root.Data3D.SelectMany(x => x.StreamPoints(false))) Console.WriteLine(p.Item1);
             *
             * //var ps = PointCloud.Parse(filename, ImportConfig.Default)
             * //    .SelectMany(x => x.Positions)
             * //    .ToArray()
             * //    ;
             */
        }