public MockGridData(GridRange range) { ColumnHeader = new DefaultHeaderData(range.Columns, DefaultHeaderData.Mode.Column); RowHeader = new DefaultHeaderData(range.Rows, DefaultHeaderData.Mode.Row); Grid = new Grid <string>(range, (r, c) => Invariant($"{r}:{c}")); }
protected PointCloudVerticalHistogram GenerateHistogramDefault(DefaultHeaderData headerData, PointCloudBounds bounds) { var fileName = Path.GetFileName(FilePath); long currentOffset = headerData.DataOffset; long processed = 0; var result = new PointCloudVerticalHistogram(bounds); using (var file = MemoryMappedFile.CreateFromFile(FilePath ?? throw new Exception("Input file not found."), FileMode.Open)) { var batchIndex = 0; var maxArraySize = TreeUtility.CalculateMaxArraySize(headerData.DataStride); var totalBatchCount = Mathf.CeilToInt((float)headerData.DataCount / maxArraySize); while (processed < headerData.DataCount) { var batchCount = Math.Min(maxArraySize, headerData.DataCount - processed); var batchSize = batchCount * headerData.DataStride; using (var view = file.CreateViewAccessor(currentOffset, batchSize, MemoryMappedFileAccess.Read)) { unsafe { batchIndex++; var progressBarTitle = $"Calculating bounds ({fileName}, batch {batchIndex.ToString()}/{totalBatchCount.ToString()})"; var batchHistogram = PointImportJobs.GenerateHistogram(view, batchCount, headerData.DataStride, headerData.Elements, bounds, progressBarTitle); result.AddData(batchHistogram.regions); } } processed += batchCount; currentOffset += batchSize; } } return(result); }
/// <summary> /// Default <see cref="ConvertPoints"/> implementation for formats using <see cref="DefaultHeaderData"/>. /// </summary> /// <param name="headerData">Data extracted from file header.</param> /// <param name="target">Target processor dispatcher to which transformed points should be passed.</param> /// <param name="transformationData">Data used for transformation of the points.</param> /// <returns>True if conversion finished successfully, false otherwise.</returns> protected bool ConvertPointsDefault(DefaultHeaderData headerData, NodeProcessorDispatcher target, TransformationData transformationData) { var fileName = Path.GetFileName(FilePath); long currentOffset = headerData.DataOffset; long processed = 0; using (var file = MemoryMappedFile.CreateFromFile(FilePath, FileMode.Open)) { var batchIndex = 0; var maxArraySize = TreeUtility.CalculateMaxArraySize(headerData.DataStride); var totalBatchCount = Mathf.CeilToInt((float)headerData.DataCount / maxArraySize); while (processed < headerData.DataCount) { var batchCount = Math.Min(maxArraySize, headerData.DataCount - processed); var batchSize = batchCount * headerData.DataStride; using (var view = file.CreateViewAccessor(currentOffset, batchSize, MemoryMappedFileAccess.Read)) { batchIndex++; var progressBarTitle = $"Converting ({fileName}, batch {batchIndex.ToString()}/{totalBatchCount.ToString()})"; var targetBuffer = target.PublicMaxSizeBuffer; PointImportJobs.ConvertData(view, targetBuffer, headerData.Elements, transformationData, headerData.DataStride, batchCount, progressBarTitle); target.AddChunk(targetBuffer, (int)batchCount); } processed += batchCount; currentOffset += batchSize; } } return(true); }
/// <summary> /// Default <see cref="CalculateBounds"/> implementation for formats using <see cref="DefaultHeaderData"/>. /// </summary> /// <param name="headerData">Data extracted from file header.</param> /// <returns>Bounds of points in given file.</returns> protected PointCloudBounds CalculateBoundsDefault(DefaultHeaderData headerData) { var fileName = Path.GetFileName(FilePath); long currentOffset = headerData.DataOffset; long processed = 0; var result = PointCloudBounds.Empty; using (var file = MemoryMappedFile.CreateFromFile(FilePath, FileMode.Open)) { var batchIndex = 0; var totalBatchCount = Mathf.CeilToInt((float)headerData.DataCount / TreeUtility.MaxPointCountPerArray); while (processed < headerData.DataCount) { var batchCount = Math.Min(TreeUtility.MaxPointCountPerArray, headerData.DataCount - processed); var batchSize = batchCount * headerData.DataStride; using (var view = file.CreateViewAccessor(currentOffset, batchSize, MemoryMappedFileAccess.Read)) { batchIndex++; var progressBarTitle = $"Calculating bounds ({fileName}, batch {batchIndex.ToString()}/{totalBatchCount.ToString()})"; var batchBounds = PointImportJobs.CalculateBounds(view, batchCount, headerData.DataStride, headerData.Elements, progressBarTitle); result.Encapsulate(batchBounds); } processed += batchCount; currentOffset += batchSize; } } return(result); }
/// <summary> /// Reads header of associated file and stores results under <see cref="header"/>. /// </summary> /// <returns></returns> /// <exception cref="Exception"></exception> private DefaultHeaderData ReadHeader() { var result = new DefaultHeaderData(); using (var file = MemoryMappedFile.CreateFromFile(FilePath, FileMode.Open)) { string[] fields = null; string[] sizes = null; string[] types = null; using (var view = file.CreateViewStream(0, 4096, MemoryMappedFileAccess.Read)) { var buffer = new byte[4096]; int length = view.Read(buffer, 0, buffer.Length); using (var stream = new MemoryStream(buffer, 0, length, false)) { var byteLine = new byte[128]; while (true) { int byteCount = stream.Read(byteLine, 0, byteLine.Length); int index = -1; for (int i = 0; i < byteCount; i++) { if (byteLine[i] == '\n' || byteLine[i] == '\r') { index = i; break; } } if (index == -1) { throw new Exception("Bad PCD file format"); } byte next = byteLine[index + 1]; stream.Position -= byteLine.Length - (index + (next == '\r' || next == '\n' ? 2 : 1)); var line = Encoding.ASCII.GetString(byteLine, 0, index); line = new Regex("#.*$").Replace(line, "").Trim(); if (line.Length == 0) { continue; } if (line.StartsWith("VERSION")) { var version = line.Split(new[] { ' ' }, 2); if (version[1] != "0.7") { throw new Exception($"Unsupported PCD version: {version[1]}"); } } else if (line.StartsWith("FIELDS")) { fields = line.Split(' ').Skip(1).ToArray(); } else if (line.StartsWith("SIZE")) { sizes = line.Split(' ').Skip(1).ToArray(); } else if (line.StartsWith("TYPE")) { types = line.Split(' ').Skip(1).ToArray(); } else if (line.StartsWith("COUNT")) { var counts = line.Split(' '); if (counts.Skip(1).Any(c => c != "1")) { throw new Exception($"Unsupported PCD counts, expected '1' for all fields"); } } else if (line.StartsWith("HEIGHT")) { var height = line.Split(new[] { ' ' }, 2); if (height[1] != "1") { throw new Exception($"Unsupported PCD height: {height[1]}"); } } else if (line.StartsWith("POINTS")) { var points = line.Split(new[] { ' ' }, 2); result.DataCount = long.Parse(points[1]); } else if (line.StartsWith("DATA")) { var data = line.Split(new[] { ' ' }, 2); if (data[1] != "binary") { throw new Exception($"Unsupported PCD data format: {data[1]}"); } break; } } result.DataOffset = stream.Position; } } if (fields == null) { throw new Exception("PCD file is missing FIELDS"); } if (sizes == null) { throw new Exception("PCD file is missing SIZE"); } if (types == null) { throw new Exception("PCD file is missing TYPE"); } if (fields.Length != sizes.Length || fields.Length != types.Length) { throw new Exception("PCD file has incorrect type specs"); } int elementOffset = 0; for (int i = 0; i < fields.Length; i++) { PointElementType?type = null; PointElementName?name = null; int elementSize = int.Parse(sizes[i]); if (fields[i] == "x") { name = PointElementName.X; } if (fields[i] == "y") { name = PointElementName.Y; } if (fields[i] == "z") { name = PointElementName.Z; } if (fields[i] == "intensity") { name = PointElementName.I; } if (fields[i] == "scalar_intensity") { name = PointElementName.I; } if (types[i] == "U" && elementSize == 1) { type = PointElementType.Byte; } if (types[i] == "F" && elementSize == 4) { type = PointElementType.Float; } if (types[i] == "D" && elementSize == 8) { type = PointElementType.Double; } if (type.HasValue && name.HasValue) { result.Elements.Add(new PointElement() { Type = type.Value, Name = name.Value, Offset = elementOffset }); } elementOffset += elementSize; } result.DataStride = elementOffset; } return(result); }
public PcdPointProcessor(string filePath) : base(filePath) { header = ReadHeader(); }
private DefaultHeaderData ReadHeader() { var result = new DefaultHeaderData(); using (var file = MemoryMappedFile.CreateFromFile(FilePath, FileMode.Open)) { int elementOffset = 0; using (var view = file.CreateViewStream(0, 4096, MemoryMappedFileAccess.Read)) { var buffer = new byte[4096]; int length = view.Read(buffer, 0, buffer.Length); using (var stream = new MemoryStream(buffer, 0, length, false)) { var byteLine = new byte[128]; bool first = true; while (true) { int byteCount = stream.Read(byteLine, 0, byteLine.Length); int index = -1; for (int i = 0; i < byteCount; i++) { if (byteLine[i] == '\n' || byteLine[i] == '\r') { index = i; break; } } if (index == -1) { throw new Exception("Bad PLY file"); } var line = Encoding.ASCII.GetString(byteLine, 0, index); byte next = byteLine[index + 1]; stream.Position -= byteLine.Length - (index + (next == '\r' || next == '\n' ? 2 : 1)); if (first && line != "ply") { throw new Exception("Bad PLY file format"); } first = false; if (line.StartsWith("format")) { var format = line.Split(new[] { ' ' }); if (format[1] != "binary_little_endian" || format[2] != "1.0") { throw new Exception($"Unsupported PLY format: {line}"); } } else if (line.StartsWith("property")) { var props = line.Split(new[] { ' ' }, 3); if (props[1] != "list") { PointElementType?type = null; PointElementName?name = null; if (props[1] == "uint8") { type = PointElementType.Byte; } if (props[1] == "float32") { type = PointElementType.Float; } if (props[1] == "float64") { type = PointElementType.Double; } if (props[1] == "uchar") { type = PointElementType.Byte; } if (props[1] == "float") { type = PointElementType.Float; } if (props[1] == "double") { type = PointElementType.Double; } if (props[2] == "x") { name = PointElementName.X; } if (props[2] == "y") { name = PointElementName.Y; } if (props[2] == "z") { name = PointElementName.Z; } if (props[2] == "red") { name = PointElementName.R; } if (props[2] == "green") { name = PointElementName.G; } if (props[2] == "blue") { name = PointElementName.B; } if (props[2] == "intensity") { name = PointElementName.I; } if (props[2] == "scalar_intensity") { name = PointElementName.I; } if (!type.HasValue) { throw new Exception($"PLY file has unsupported property type {props[1]}"); } if (name.HasValue) { result.Elements.Add(new PointElement() { Type = type.Value, Name = name.Value, Offset = elementOffset }); } elementOffset += PointElement.GetSize(type.Value); } } else if (line.StartsWith("element vertex")) { var vertex = line.Split(new[] { ' ' }, 3); result.DataCount = long.Parse(vertex[2]); } else if (line.StartsWith("end_header")) { break; } } result.DataOffset = stream.Position; } } result.DataStride = elementOffset; } return(result); }