示例#1
0
        private static IEnumerable <Points> ReadPoints(laszip_dll reader, int numberOfPointsPerChunk)
        {
            var n = reader.header.number_of_point_records;
            var numberOfChunks = n / numberOfPointsPerChunk;

            for (var j = 0; j < n; j += numberOfPointsPerChunk)
            {
                if (j + numberOfPointsPerChunk > n)
                {
                    numberOfPointsPerChunk = (int)(n - j);
                }
                //Console.WriteLine($"j: {j}, numberOfPointsPerChunk: {numberOfPointsPerChunk}, n: {n}");
                var p  = new double[3];
                var ps = new V3d[numberOfPointsPerChunk];
                var cs = new C4b[numberOfPointsPerChunk];
                var ts = new byte[numberOfPointsPerChunk];
                for (var i = 0; i < numberOfPointsPerChunk; i++)
                {
                    reader.laszip_read_point();

                    reader.laszip_get_coordinates(p);
                    ps[i] = new V3d(p);
                    cs[i] = new C4b(reader.point.rgb[0] >> 8, reader.point.rgb[1] >> 8, reader.point.rgb[2] >> 8);
                    ts[i] = reader.point.classification;
                }
                yield return(new Points(ps, cs, ts));
            }

            reader.laszip_close_reader();
        }
示例#2
0
        /// <summary>
        /// </summary>
        /// <param name="positions">Optional.</param>
        /// <param name="colors">Optional. Either null or same number of elements as positions.</param>
        /// <param name="normals">Optional. Either null or same number of elements as positions.</param>
        /// <param name="intensities">Optional. Either null or same number of elements as positions.</param>
        /// <param name="classifications">Optional. Either null or same number of elements as positions.</param>
        /// <param name="bbox">Optional. If null, then bbox will be constructed from positions.</param>
        public Chunk(
            IList <V3d> positions,
            IList <C4b> colors           = null,
            IList <V3f> normals          = null,
            IList <int> intensities      = null,
            IList <byte> classifications = null,
            Box3d?bbox = null
            )
        {
            //if (colors != null && colors.Count != positions?.Count) throw new ArgumentException(nameof(colors));
            if (normals != null && normals.Count != positions?.Count)
            {
                throw new ArgumentException(nameof(normals));
            }
            if (intensities != null && intensities.Count != positions?.Count)
            {
                throw new ArgumentException(nameof(intensities));
            }

            if (positions != null && colors != null && positions.Count != colors.Count)
            {
                colors = new C4b[positions.Count];
                Report.Warn("[Chunk-ctor] inconsistent length: pos.length = {0} vs cs.length = {1}", positions.Count, colors.Count);
            }

            Positions       = positions;
            Colors          = colors;
            Normals         = normals;
            Intensities     = intensities;
            Classifications = classifications;
            BoundingBox     = bbox ?? new Box3d(positions);
        }
示例#3
0
        public static C4b[] DefaultColor(V2i size)
        {
            var length     = size.X * size.Y;
            var indexArray = new C4b[length].Set(C4b.White);

            return(indexArray);
        }
示例#4
0
        public static C4b[] ComputeColorMap(V2i size)
        {
            var length     = size.X * size.Y;
            var indexArray = new C4b[length];

            var stepX = 255 / (double)size.X;
            var stepY = 255 / (double)size.Y;

            //var currColor = C4b.Black;
            for (int j = 0; j < size.Y; j++)
            {
                for (int i = 0; i < size.X; i++)
                {
                    int index = j * size.X + i;
                    var newR  = (byte)(stepX * i);
                    var newG  = (byte)(stepY * j);

                    indexArray[index]         = new C4b(newR, newG, (byte)128);
                    indexArray[index].Opacity = 255;
                }
            }

            indexArray[0]          = C4b.Red;
            indexArray[length - 1] = C4b.Blue;

            return(indexArray);
        }
示例#5
0
            /// <summary>byte[] -> C4b[]</summary>
            public static C4b[] BufferToC4bArray(byte[] buffer)
            {
                if (buffer == null)
                {
                    return(null);
                }
                var data = new C4b[buffer.Length / 4];

                for (int i = 0, j = 0; i < data.Length; i++)
                {
                    data[i] = new C4b(buffer[j++], buffer[j++], buffer[j++], buffer[j++]);
                }
                return(data);
            }
示例#6
0
        /// <summary>
        /// Returns lod points for given octree depth/front, where level 0 is the root node.
        /// Front will include leafs higher up than given level.
        /// </summary>
        public static IEnumerable <Chunk> QueryPointsInOctreeLevel(
            this IPointCloudNode node, int level
            )
        {
            if (level < 0)
            {
                yield break;
            }

            if (level == 0 || node.IsLeaf())
            {
                var ps = node.PositionsAbsolute;
                var cs = node?.TryGetColors4b()?.Value;
                if (ps != null && cs != null && ps.Length != cs.Length)
                {
                    cs = new C4b[ps.Length];
                    Report.Warn("[Chunk] inconsistent length: pos.length = {0} vs cs.length = {1}", ps.Length, cs.Length);
                }
                var ns    = node?.TryGetNormals3f()?.Value;
                var js    = node?.TryGetIntensities()?.Value;
                var ks    = node?.TryGetClassifications()?.Value;
                var chunk = new Chunk(ps, cs, ns, js, ks);
                yield return(chunk);
            }
            else
            {
                if (node.Subnodes == null)
                {
                    yield break;
                }

                for (var i = 0; i < 8; i++)
                {
                    var n = node.Subnodes[i];
                    if (n == null)
                    {
                        continue;
                    }
                    foreach (var x in QueryPointsInOctreeLevel(n.Value, level - 1))
                    {
                        yield return(x);
                    }
                }
            }
        }
示例#7
0
        /// <summary></summary>
        public static C4b[] GetC4bArray(this Storage storage, string key, CancellationToken ct)
        {
            var data = (C4b[])storage.f_tryGetFromCache(key, ct);

            if (data != null)
            {
                return(data);
            }

            var buffer = storage.f_get(key, ct);

            if (buffer == null)
            {
                return(null);
            }
            data = new C4b[buffer.Length / 4];
            for (int i = 0, j = 0; i < data.Length; i++)
            {
                data[i] = new C4b(buffer[j++], buffer[j++], buffer[j++], buffer[j++]);
            }
            storage.f_add(key, data, null, ct);
            return(data);
        }
示例#8
0
 public static System.Drawing.Color ToColor(this C4b color)
 {
     return(System.Drawing.Color.FromArgb(
                color.A, color.R, color.G, color.B));
 }
示例#9
0
        public static void Run()
        {
            using (var app = /*new VulkanApplication() */ new OpenGlApplication())
            {
                var win = app.CreateSimpleRenderWindow(samples: 8);

                // create CPU side array
                var indices = new int[] { 0, 1, 2, 0, 2, 3 };
                // wrap it into cpu buffer. ArrayBuffer is a CPU buffer (which will be uploaded on demand),
                // In contrast, BackendBuffer would be a buffer prepared for a specific backend.
                // both implement the IBuffer interface.
                var indexBuffer = (IBuffer) new ArrayBuffer(indices);

                // same applies for vertex data. Here we do not explicitly create an ArrayBuffer since
                // we use convinience functions which internally create the ArrayBuffer for us
                var vertices = new V3f[] {
                    new V3f(-1, -1, 0), new V3f(1, -1, 0), new V3f(1, 1, 0), new V3f(-1, 1, 0)
                };
                var colors = new C4b[] {
                    C4b.Green, C4b.Red, C4b.Blue, C4b.White
                };

                // In this low level API, we manually construct a drawCallInfo which essentially map
                // to the arguments of glDrawElements etc.
                var drawCallInfo = new DrawCallInfo()
                {
                    FaceVertexCount = 6,
                    InstanceCount   = 1, // DrawCallInfo is a struct and is initialized with zeros. make sure to set instanceCount to 1
                    FirstIndex      = 0,
                };

                // next we create a scene graph node which describes a simple scene which, when rendered
                // uses the supplied drawCallInfo to render geometry of type TriangleList (in constrast to points, linestrip etc)
                var drawNode = new Sg.RenderNode(drawCallInfo, IndexedGeometryMode.TriangleList);
                // the main principle is to use scene graph nodes as small building blocks to build together the
                // complete scene description - a bit like lego ;)
                // the same applies for applying geometry data. just like any other attribute (e.g. model trafos),
                // vertex data can be inherited along the edges in the scene graph. thus the scene graph would look like this
                //             VertexIndexApplicator   (applies index buffer to sub graph)
                //                 ^
                //                 |
                //              drawNode               (performs draw call using attributes inherited along scene graph edges)
                var sceneWithIndexBuffer =
                    new Sg.VertexIndexApplicator(
                        new BufferView(AValModule.constant(indexBuffer), typeof(int)),
                        drawNode
                        );

                // of course constructing scene graph nodes manually is tedious. therefore we use
                // convinience extension functions which can be chaned together, each
                // wrapping a node around the previously constructed scene graph
                var scene =
                    sceneWithIndexBuffer
                    .WithVertexAttribute("Positions", vertices)
                    // there are a lot such extension functions defined to conviniently work with scene graphs
                    .VertexAttribute(DefaultSemantic.Colors, colors)
                    // next, we apply the shaders (this way, the shader becomes the root node -> all children now use
                    // this so called effect (a pipeline shader which combines all shader stages into one object)
                    .WithEffects(new[] { Aardvark.Rendering.Effects.VertexColor.Effect });

                // next we use the aardvark scene graph compiler to construct a so called render task,
                // an optimized representation of the scene graph.
                var renderTask = app.Runtime.CompileRender(win.FramebufferSignature, scene);

                // next, we assign the rendertask to our render window.
                win.RenderTask = renderTask;

                win.Run();
            }
        }
            public PointSetNode ToPointSetCell(Storage storage, bool isTemporaryImportNode)
            {
                var center = new V3d(_centerX, _centerY, _centerZ);

                V3f[]  ps = null;
                C4b[]  cs = null;
                V3f[]  ns = null;
                int[]  js = null;
                byte[] ks = null;

                if (_ia != null)
                {
                    var allPs = _octree.m_ps;
                    var count = _ia.Count;

                    ps = new V3f[count];
                    for (var i = 0; i < count; i++)
                    {
                        ps[i] = (V3f)(allPs[_ia[i]] - center);
                    }

                    if (_octree.m_cs != null)
                    {
                        var allCs = _octree.m_cs;
                        cs = new C4b[count];
                        for (var i = 0; i < count; i++)
                        {
                            cs[i] = allCs[_ia[i]];
                        }
                    }

                    if (_octree.m_ns != null)
                    {
                        var allNs = _octree.m_ns;
                        ns = new V3f[count];
                        for (var i = 0; i < count; i++)
                        {
                            ns[i] = allNs[_ia[i]];
                        }
                    }

                    if (_octree.m_is != null)
                    {
                        var allIs = _octree.m_is;
                        js = new int[count];
                        for (var i = 0; i < count; i++)
                        {
                            js[i] = allIs[_ia[i]];
                        }
                    }

                    if (_octree.m_ks != null)
                    {
                        var allKs = _octree.m_ks;
                        ks = new byte[count];
                        for (var i = 0; i < count; i++)
                        {
                            ks[i] = allKs[_ia[i]];
                        }
                    }
                }

                Guid?psId = ps != null ? (Guid?)Guid.NewGuid() : null;
                Guid?csId = cs != null ? (Guid?)Guid.NewGuid() : null;
                Guid?nsId = ns != null ? (Guid?)Guid.NewGuid() : null;
                Guid?isId = js != null ? (Guid?)Guid.NewGuid() : null;
                Guid?ksId = ks != null ? (Guid?)Guid.NewGuid() : null;

                var subcells   = _subnodes?.Map(x => x?.ToPointSetCell(storage, isTemporaryImportNode));
                var subcellIds = subcells?.Map(x => x?.Id);
                var isLeaf     = _subnodes == null;

#if DEBUG
                if (_subnodes != null)
                {
                    if (ps != null)
                    {
                        throw new InvalidOperationException("Invariant d98ea55b-760c-4564-8076-ce9cf7d293a0.");
                    }

                    for (var i = 0; i < 8; i++)
                    {
                        var sn = _subnodes[i]; if (sn == null)
                        {
                            continue;
                        }
                        if (sn._cell.Exponent != this._cell.Exponent - 1)
                        {
                            throw new InvalidOperationException("Invariant 2c33afb4-683b-4f71-9e1f-36ec4a79fba1.");
                        }
                    }
                }
#endif
                var pointCountTreeLeafs = subcells != null
                    ? subcells.Sum(n => n != null?n.PointCountTree : 0)
                                          : ps.Length
                ;

                var data = ImmutableDictionary <Durable.Def, object> .Empty
                           .Add(Durable.Octree.NodeId, Guid.NewGuid())
                           .Add(Durable.Octree.Cell, _cell)
                           .Add(Durable.Octree.PointCountTreeLeafs, pointCountTreeLeafs)
                ;

                if (isTemporaryImportNode)
                {
                    data = data.Add(PointSetNode.TemporaryImportNode, 0);
                }

                if (psId != null)
                {
                    storage.Add(psId.ToString(), ps);
                    var bbExactLocal = new Box3f(ps);

                    data = data
                           .Add(Durable.Octree.PointCountCell, ps.Length)
                           .Add(Durable.Octree.PositionsLocal3fReference, psId.Value)
                           .Add(Durable.Octree.BoundingBoxExactLocal, bbExactLocal)
                    ;

                    if (isLeaf)
                    {
                        var bbExactGlobal = (Box3d)bbExactLocal + center;
                        data = data
                               .Add(Durable.Octree.BoundingBoxExactGlobal, bbExactGlobal)
                        ;
                    }
                }
                else
                {
                    data = data
                           .Add(Durable.Octree.PointCountCell, 0)
                    ;
                }

                if (csId != null)
                {
                    storage.Add(csId.ToString(), cs); data = data.Add(Durable.Octree.Colors4bReference, csId.Value);
                }
                if (nsId != null)
                {
                    storage.Add(nsId.ToString(), ns); data = data.Add(Durable.Octree.Normals3fReference, nsId.Value);
                }
                if (isId != null)
                {
                    storage.Add(isId.ToString(), js); data = data.Add(Durable.Octree.Intensities1iReference, isId.Value);
                }
                if (ksId != null)
                {
                    storage.Add(ksId.ToString(), ks); data = data.Add(Durable.Octree.Classifications1bReference, ksId.Value);
                }

                if (isLeaf) // leaf
                {
                    var result = new PointSetNode(data, storage, writeToStore: true);
                    if (storage.GetPointCloudNode(result.Id) == null)
                    {
                        throw new InvalidOperationException("Invariant d1022027-2dbf-4b11-9b40-4829436f5789.");
                    }
                    return(result);
                }
                else
                {
                    for (var i = 0; i < 8; i++)
                    {
                        var x = subcellIds[i];
                        if (x.HasValue)
                        {
                            var id = x.Value;
                            if (storage.GetPointCloudNode(id) == null)
                            {
                                throw new InvalidOperationException("Invariant 01830b8b-3c0e-4a8b-a1bd-bfd1b1be1844.");
                            }
                        }
                    }
                    var bbExactGlobal = new Box3d(subcells.Where(x => x != null).Select(x => x.BoundingBoxExactGlobal));
                    data = data
                           .Add(Durable.Octree.BoundingBoxExactGlobal, bbExactGlobal)
                           .Add(Durable.Octree.SubnodesGuids, subcellIds.Map(x => x ?? Guid.Empty))
                    ;
                    var result = new PointSetNode(data, storage, writeToStore: true);
                    if (storage.GetPointCloudNode(result.Id) == null)
                    {
                        throw new InvalidOperationException("Invariant 7b09eccb-b6a0-4b99-be7a-eeff53b6a98b.");
                    }
                    return(result);
                }
            }
 public void Write(C4b c)
 {
     Write(c.R); Write(c.G); Write(c.B); Write(c.A);
 }
            public PointSetNode ToPointSetCell(Storage storage, CancellationToken ct, double kdTreeEps = 1e-6)
            {
                var center = new V3d(_centerX, _centerY, _centerZ);

                V3f[] ps = null;
                C4b[] cs = null;
                V3f[] ns = null;
                int[] js = null;
                PointRkdTreeD <V3f[], V3f> kdTree = null;

                if (_ia != null)
                {
                    var allPs = _octree.m_ps;
                    var count = _ia.Count;

                    ps = new V3f[count];
                    for (var i = 0; i < count; i++)
                    {
                        ps[i] = (V3f)(allPs[_ia[i]] - center);
                    }

                    if (_octree.m_cs != null)
                    {
                        var allCs = _octree.m_cs;
                        cs = new C4b[count];
                        for (var i = 0; i < count; i++)
                        {
                            cs[i] = allCs[_ia[i]];
                        }
                    }

                    if (_octree.m_ns != null)
                    {
                        var allNs = _octree.m_ns;
                        ns = new V3f[count];
                        for (var i = 0; i < count; i++)
                        {
                            ns[i] = allNs[_ia[i]];
                        }
                    }

                    if (_octree.m_is != null)
                    {
                        var allIs = _octree.m_is;
                        js = new int[count];
                        for (var i = 0; i < count; i++)
                        {
                            js[i] = allIs[_ia[i]];
                        }
                    }

                    kdTree = new PointRkdTreeD <V3f[], V3f>(
                        3, ps.Length, ps,
                        (xs, i) => xs[(int)i], (v, i) => (float)v[i],
                        (a, b) => V3f.Distance(a, b), (i, a, b) => b - a,
                        (a, b, c) => VecFun.DistanceToLine(a, b, c), VecFun.Lerp, kdTreeEps
                        );
                }

                Guid?psId = ps != null ? (Guid?)Guid.NewGuid() : null;
                Guid?csId = cs != null ? (Guid?)Guid.NewGuid() : null;
                Guid?nsId = ns != null ? (Guid?)Guid.NewGuid() : null;
                Guid?isId = js != null ? (Guid?)Guid.NewGuid() : null;
                Guid?kdId = kdTree != null ? (Guid?)Guid.NewGuid() : null;

                var subcells   = _subnodes?.Map(x => x?.ToPointSetCell(storage, ct, kdTreeEps));
                var subcellIds = subcells?.Map(x => x?.Id);

#if DEBUG
                if (ps != null && _subnodes != null)
                {
                    throw new InvalidOperationException();
                }
#endif
                var pointCountTree = ps != null
                    ? ps.Length
                    : subcells.Sum(n => n != null ? n.PointCountTree : 0)
                ;

                if (psId != null)
                {
                    storage.Add(psId.ToString(), ps, ct);
                }
                if (csId != null)
                {
                    storage.Add(csId.ToString(), cs, ct);
                }
                if (nsId != null)
                {
                    storage.Add(nsId.ToString(), ns, ct);
                }
                if (isId != null)
                {
                    storage.Add(isId.ToString(), js, ct);
                }
                if (kdId != null)
                {
                    storage.Add(kdId.ToString(), kdTree.Data, ct);
                }

                if (subcellIds == null) // leaf
                {
                    return(new PointSetNode(_cell, pointCountTree, psId, csId, kdId, nsId, isId, storage));
                }
                else
                {
                    return(new PointSetNode(_cell, pointCountTree, subcellIds, storage));
                }
            }
示例#13
0
 /// <summary>Computes MD5 hash of given data.</summary>
 public static Guid ComputeMd5Hash(this C4b x)
 => ComputeMd5Hash(bw => { bw.Write(x.R); bw.Write(x.G); bw.Write(x.B); bw.Write(x.A); });
 /// <summary>
 /// C4b to System.Drawing.Color.
 /// </summary>
 public static Color ToColor(this C4b color)
 => Color.FromArgb(color.A, color.R, color.G, color.B);