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(); }
/// <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); }
public static C4b[] DefaultColor(V2i size) { var length = size.X * size.Y; var indexArray = new C4b[length].Set(C4b.White); return(indexArray); }
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); }
/// <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); }
/// <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); } } } }
/// <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); }
public static System.Drawing.Color ToColor(this C4b color) { return(System.Drawing.Color.FromArgb( color.A, color.R, color.G, color.B)); }
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)); } }
/// <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);