< Summary - ReFlex - Library

Information
Class: ReFlex.Core.Networking.Util.EmulatedPointCloud
Assembly: ReFlex.Core.Networking
File(s): D:\a\reflex\reflex\library\src\Core\Networking\Util\EmulatedPointCloud.cs
Line coverage
94%
Covered lines: 141
Uncovered lines: 8
Coverable lines: 149
Total lines: 249
Line coverage: 94.6%
Branch coverage
87%
Covered branches: 47
Total branches: 54
Branch coverage: 87%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%210%
get_MaxDepthImageValue()100%11100%
get_Points()100%11100%
get_GenerateDepthImage()100%11100%
.ctor(...)100%11100%
InitializePointCloud(...)83.33%6689.28%
Reset()100%44100%
UpdateFromInteractions(...)100%1818100%
UpdateFromGreyScaleImage(...)90%101092.1%
ComputeIndex(...)50%9880%
GetUpdatedDepthImage()50%22100%
GetImageDefaultValue()100%11100%
SetDepthImageValueFromDepth(...)100%22100%
SetDepthImageValue(...)100%44100%
Combine(...)100%11100%

File(s)

D:\a\reflex\reflex\library\src\Core\Networking\Util\EmulatedPointCloud.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using NLog;
 4using ReFlex.Core.Common.Components;
 5using ReFlex.Core.Common.Util;
 6using Math = System.Math;
 7
 8namespace ReFlex.Core.Networking.Util
 9{
 10    public class EmulatedPointCloud
 11    {
 012        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
 13
 14        private StreamParameter _currentParams;
 15        private readonly EmulatorParameters _emulatorParameters;
 16        private readonly float _pushRange;
 17        private readonly float _pullRange;
 18
 19        private byte[] _image;
 20
 21        private uint _numChannels;
 22        private uint _bytesPerChannel;
 3145623        public uint MaxDepthImageValue { get => (1u << (int)(8 * _bytesPerChannel)) - 1; }
 24
 14093425        public Point3[] Points { get; private set; }
 26
 7045027        public bool GenerateDepthImage {get; set; } = true;
 28
 4229        public EmulatedPointCloud(EmulatorParameters param)
 4230        {
 4231            _emulatorParameters = param;
 4232            _pushRange = _emulatorParameters.PlaneDistanceInMeter - _emulatorParameters.MinDepthInMeter;
 4233            _pullRange = _emulatorParameters.MaxDepthInMeter - _emulatorParameters.PlaneDistanceInMeter;
 4234        }
 35
 36        public void InitializePointCloud(StreamParameter param)
 4237        {
 4238            if (param == null)
 039            {
 040                Logger.Error("Invalid parameter for intializatoin of point cloud.");
 041                return;
 42            }
 43
 4244            _bytesPerChannel = DepthImageFormatTools.BytesPerChannel(param.Format);
 4245            _numChannels = DepthImageFormatTools.NumChannels(param.Format);
 4246            var defaultValue = GetImageDefaultValue();
 47
 4248            _currentParams = param;
 49
 4250            var result = new Point3[param.Width * param.Height].AsSpan<Point3>();
 4251            _image = new byte[param.Width * param.Height * _bytesPerChannel * _numChannels];
 52
 4253            var xOffset = _emulatorParameters.WidthInMeters / param.Width;
 4254            var yOffset = _emulatorParameters.HeightInMeters / param.Height;
 55
 4256            var xMin = 0 -_emulatorParameters.WidthInMeters * 0.5f;
 4257            var yMin = 0 -_emulatorParameters.HeightInMeters * 0.5f;
 58
 520859            for (var x = 0; x < param.Width; ++x)
 256260            {
 256261                var xPos = xMin + (xOffset * x);
 62
 25088863                for (var y = 0; y < param.Height; ++y)
 12288264                {
 12288265                    var yPos = yMin + (yOffset * y);
 66
 12288267                    var idx = ComputeIndex(x, y);
 68
 12288269                    result[idx] = new Point3(xPos, yPos, _emulatorParameters.PlaneDistanceInMeter);
 70
 12288271                    SetDepthImageValue(defaultValue, idx);
 12288272                }
 256273            }
 74
 4275            Points = result.ToArray();
 4276        }
 77
 78        public void Reset()
 2879        {
 2880            var defaultValue = GetImageDefaultValue();
 81
 12295282            for (int i = 0; i < Points.Length; ++i)
 6144883            {
 6144884                Points[i].Z = _emulatorParameters.PlaneDistanceInMeter;
 85
 6144886                if (GenerateDepthImage)
 6144887                    SetDepthImageValue(defaultValue, i);
 6144888            }
 2889        }
 90
 91        public void UpdateFromInteractions(List<Interaction> interactions)
 2092        {
 2093            var squaredRadius = _emulatorParameters.Radius * _emulatorParameters.Radius;
 94
 8095            for (var i = 0; i < interactions.Count; ++i)
 2096            {
 2097                var interaction = interactions[i];
 98
 2099                var centerX = (int)interaction.Position.X;
 20100                var centerY = (int)interaction.Position.Y;
 101
 20102                var offset = interaction.Position.Z < 0 ? interaction.Position.Z * _pushRange : interaction.Position.Z *
 103
 20104                var radius = (int) Math.Abs(Math.Round(_emulatorParameters.Radius * offset));
 105
 744106                for (var x = -radius; x < radius; ++x)
 352107                {
 18624108                    for (var y = -radius; y < radius; ++y)
 8960109                    {
 8960110                       var idx = ComputeIndex(centerX + x, centerY + y);
 111
 8960112                        if (x == 0 && y == 0)
 20113                        {
 20114                            Points[idx].Z = _emulatorParameters.PlaneDistanceInMeter + offset;
 115
 20116                            if (GenerateDepthImage)
 20117                                SetDepthImageValueFromDepth(Points[idx].Z, idx);
 20118                            continue;
 119                        }
 120
 8940121                        var dist = Math.Sqrt( x * x + y * y);
 122
 8940123                        var maxDist = Math.Sqrt(2f * radius * radius);
 124
 8940125                        var smooth = (float) Math.Sqrt(dist/maxDist);
 126
 8940127                        if (dist < squaredRadius)
 8940128                        {
 8940129                            var factor = 1.0f - smooth;
 130
 8940131                            var centerZ = _emulatorParameters.PlaneDistanceInMeter + (offset * factor);
 132
 8940133                            Points[idx].Z = centerZ;
 134
 8940135                            if (GenerateDepthImage)
 8940136                                SetDepthImageValueFromDepth(centerZ, idx);
 8940137                        }
 8940138                    }
 352139                }
 20140            }
 20141        }
 142
 143        public void UpdateFromGreyScaleImage(ImageByteArray imageData)
 28144        {
 28145            if (imageData.ImageData.Length < imageData.Width * imageData.Height * imageData.BytesPerChannel * _numChanne
 0146            {
 0147                Logger.Log(LogLevel.Error, $"Incorrect Size for image data: Size of Byte Array: {imageData.ImageData.Len
 0148                return;
 149            }
 150
 28151            var defaultDepth = GetImageDefaultValue();
 152
 153            // compute global offset - center of the plane is in the origin
 28154            var xMin = -_emulatorParameters.WidthInMeters * 0.5f;
 28155            var yMin = -_emulatorParameters.HeightInMeters * 0.5f;
 156
 157            // compute offset per pixel
 28158            var pxOffsetX = _emulatorParameters.WidthInMeters / _currentParams.Width;
 28159            var pxOffsetY = _emulatorParameters.HeightInMeters / _currentParams.Height;
 160
 28161            var iterationStep = _numChannels * _bytesPerChannel;
 162
 122952163            for (uint i = 0; i < imageData.ImageData.Length; i+=iterationStep)
 61448164            {
 61448165                var zIdx = i + ((_numChannels - 1) * _bytesPerChannel);
 166
 61448167                var dist = (int) imageData.ImageData[zIdx];
 168
 61448169                if (_bytesPerChannel == 2)
 24584170                {
 24584171                    dist = Combine(imageData.ImageData[zIdx], imageData.ImageData[zIdx + 1]);
 24584172                }
 173
 174                // The midpoint encodes the undeformed plane.
 61448175                if (dist == defaultDepth)
 52500176                    continue;
 177
 178                // 3 channels --> divide
 8948179                var pos = i / (iterationStep);
 180
 181                // compute pixel index
 8948182                var xPx = pos % _currentParams.Width;
 8948183                var yPx = pos / _currentParams.Width;
 184
 8948185                var x = xMin + (xPx * pxOffsetX);
 8948186                var y = yMin + (yPx * pxOffsetY);
 187
 8948188                var pushValueRange = (float)defaultDepth;
 8948189                var pullValueRange = (float)(MaxDepthImageValue - defaultDepth);
 190
 8948191                var z = dist < defaultDepth
 8948192
 8948193                    // push: normalized depth * push range + min depth
 8948194                    ? (dist / pushValueRange) * _pushRange + _emulatorParameters.MinDepthInMeter
 8948195
 8948196                    // pull: subtract push range, normalize depth behind plane * pull range + plane distance
 8948197                    : ((dist - defaultDepth) / pullValueRange) * _pullRange + _emulatorParameters.PlaneDistanceInMeter;
 198
 199
 8948200                Points[pos] = new Point3(x, y, z);
 8948201            }
 28202        }
 203
 204        public int ComputeIndex(int x, int y)
 131842205        {
 131842206            if (x < 0 || x >= _currentParams.Width || y < 0 || y >= _currentParams.Height)
 0207                return 0;
 208
 131842209            return y * _currentParams.Width + x;
 131842210        }
 211
 212        public ImageByteArray GetUpdatedDepthImage()
 20213        {
 20214            return _image == null
 20215                ? new ImageByteArray(new byte[1],1,1, 1, 1, DepthImageFormat.Greyscale8bpp)
 20216                : new ImageByteArray(_image, _currentParams.Width, _currentParams.Height, _bytesPerChannel, _numChannels
 20217        }
 218
 219        private uint GetImageDefaultValue()
 9058220        {
 221            // divide by 2: shifting bytes to the right
 9058222            return MaxDepthImageValue >> 1;
 9058223        }
 224
 225        private void SetDepthImageValueFromDepth(float depth, int index)
 8960226        {
 8960227            var midpoint = GetImageDefaultValue();
 8960228            var offset = depth - _emulatorParameters.PlaneDistanceInMeter;
 8960229            var value = offset < 0
 8960230                ? midpoint + offset / _pushRange * midpoint
 8960231                : midpoint + offset / _pullRange * (MaxDepthImageValue - midpoint);
 232
 8960233            SetDepthImageValue((uint)Math.Round(Math.Clamp(value, 0, MaxDepthImageValue)), index);
 8960234        }
 235
 236        private void SetDepthImageValue(uint value, int index)
 193290237        {
 1397840238            for (var channel = 0; channel < _numChannels; channel++)
 2491060239                for (var b = 0; b < _bytesPerChannel; b++)
 739900240                    _image[(index * _numChannels + channel) * _bytesPerChannel + b] = (byte)(value >> (8 * b));
 193290241        }
 242
 243        private static int Combine(byte b1, byte b2)
 24584244        {
 245            // return b1 << 8 | b2;
 24584246            return b1 | (b2 << 8);
 24584247        }
 248    }
 249}