< Summary - ReFlex - Library

Information
Class: PointCloud.Benchmark.Interactivity.MultiInteractionObserver
Assembly: ReFlex.PointCloud.Benchmark
File(s): D:\a\reflex\reflex\test\Library\Performance\PointCloud.Benchmark\Interactivity\MultiInteractionObserver.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 363
Coverable lines: 363
Total lines: 556
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 116
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

D:\a\reflex\reflex\test\Library\Performance\PointCloud.Benchmark\Interactivity\MultiInteractionObserver.cs

#LineLine coverage
 1using System.Diagnostics;
 2using ReFlex.Core.Common.Components;
 3using ReFlex.Core.Common.Util;
 4using ArrayUtils = PointCloud.Benchmark.Common.ArrayUtils;
 5using Math = System.Math;
 6
 7namespace PointCloud.Benchmark.Interactivity
 8{
 9    /// <summary>
 10    /// Finds multiple Interactions on a 2d vectorfield.
 11    /// </summary>
 12    public class MultiInteractionObserver : InteractionObserverBase
 13    {
 14        #region Fields
 15
 16        private PointCloud3 _pointCloud;
 17        private VectorField2 _vectorField;
 18        private int[][] _confidenceMat;
 19        private List<Interaction> _candidates;
 20
 021        private readonly Stopwatch _stopWatch = new();
 22
 23
 24        #endregion
 25
 26        #region Properties
 27
 28        /// <summary>
 29        /// Gets the type.
 30        /// </summary>
 31        /// <value>
 32        /// The type.
 33        /// </value>
 034        public override ObserverType Type => ObserverType.MultiTouch;
 35
 36        /// <summary>
 37        /// Gets or sets the point cloud.
 38        /// </summary>
 39        /// <value>
 40        /// The point cloud.
 41        /// </value>
 42        public override PointCloud3 PointCloud
 43        {
 044            get => _pointCloud;
 45            set
 046            {
 047                if (_pointCloud == value)
 048                    return;
 49
 050                _pointCloud = value;
 051                InitializeConfidenceMatrix();
 052            }
 53        }
 54
 55        /// <summary>
 56        /// Gets or sets the vector field.
 57        /// </summary>
 58        /// <value>
 59        /// The vector field.
 60        /// </value>
 61        public override VectorField2 VectorField
 62        {
 063            get => _vectorField;
 64            set
 065            {
 066                if (_vectorField == value)
 067                    return;
 68
 069                _vectorField = value;
 070                InitializeConfidenceMatrix();
 071            }
 72        }
 73
 74        #endregion
 75
 76        #region Events
 77        public override event EventHandler<IList<Interaction>> NewInteractions;
 78
 79        #endregion
 80
 81        /// <summary>
 82        /// Initializes a new instance of the <see cref="MultiInteractionObserver"/> class.
 83        /// </summary>
 084        public MultiInteractionObserver()
 085        {
 086            _candidates = new List<Interaction>();
 087        }
 88
 89        /// <summary>
 90        /// Updates this instance.
 91        /// </summary>
 92        public override Task<ProcessingResult> Update()
 093        {
 094            if (PointCloud == null ||
 095               VectorField == null ||
 096               _confidenceMat == null)
 097                return Task.FromResult(new ProcessingResult(ProcessServiceStatus.Error));
 98
 099            var processResult = new ProcessingResult(ProcessServiceStatus.Available);
 100
 0101            var perfItem = new ProcessPerformance();
 0102            if (MeasurePerformance)
 0103            {
 0104                _stopWatch.Start();
 0105            }
 106
 0107            UpdateVectorfield();
 108
 0109            _candidates.Clear();
 110
 0111            if (MeasurePerformance)
 0112            {
 0113                _stopWatch.Stop();
 0114                perfItem.Preparation = _stopWatch.Elapsed;
 0115                _stopWatch.Reset();
 0116            }
 117
 0118            if (MeasurePerformance)
 0119            {
 0120                _stopWatch.Start();
 0121            }
 122
 123
 124
 0125            if (MeasurePerformance)
 0126            {
 0127                _stopWatch.Stop();
 0128                perfItem.Update = _stopWatch.Elapsed;
 0129                _stopWatch.Reset();
 0130            }
 131
 0132            if (MeasurePerformance)
 0133            {
 0134                _stopWatch.Start();
 0135            }
 136
 0137            var interactions =  ConvertDepthValue(_candidates.ToList());
 138
 0139            if (MeasurePerformance)
 0140            {
 0141                _stopWatch.Stop();
 0142                perfItem.ConvertDepthValue = _stopWatch.Elapsed;
 0143                _stopWatch.Reset();
 0144            }
 145
 0146            if (MeasurePerformance)
 0147            {
 0148                _stopWatch.Start();
 0149            }
 150
 0151            var frame = ComputeSmoothingValue(interactions);
 152
 0153            if (MeasurePerformance)
 0154            {
 0155                _stopWatch.Stop();
 0156                perfItem.Smoothing = _stopWatch.Elapsed;
 0157                _stopWatch.Reset();
 0158            }
 159
 0160            var confidentInteractions = ApplyConfidenceFilter(frame.Interactions);
 161
 0162            if (MeasurePerformance)
 0163            {
 0164                _stopWatch.Start();
 0165            }
 166
 0167            var processedInteractions = ComputeExtremumType(confidentInteractions.ToList(), PointCloud.AsJaggedArray());
 168
 0169            if (MeasurePerformance)
 0170            {
 0171                _stopWatch.Stop();
 0172                perfItem.ComputeExtremumType = _stopWatch.Elapsed;
 0173                _stopWatch.Reset();
 0174            }
 175
 0176            UpdatePerformanceMetrics(perfItem);
 177
 178
 0179            OnNewInteractions(processedInteractions);
 180
 0181            return Task.FromResult(processResult);
 0182        }
 183
 184        /// <summary>
 185        /// Initializes the confidence matrix.
 186        /// </summary>
 187        private void InitializeConfidenceMatrix()
 0188        {
 0189            if (VectorField != null)
 0190                ArrayUtils.InitializeArray(out _confidenceMat, VectorField.SizeX, VectorField.SizeY);
 0191        }
 192
 193        public void UpdateVectorfield()
 0194        {
 0195            var stride = VectorField.Stride;
 0196            var pointCloud = PointCloud.AsJaggedArray();
 0197            var vectorField = VectorField.AsJaggedArray();
 198
 0199            for (var x = stride; x < VectorField.SizeX - stride; x++)
 200                // Parallel.ForEach(Iterate(stride, VectorField.SizeX - stride, stride), (x) =>
 0201            {
 0202                for (var y = stride; y < VectorField.SizeY - stride; y++)
 0203                {
 0204                    if (!vectorField[x][y].IsValid)
 0205                        continue;
 206
 0207                    var vectorX = vectorField[x][y].Add(vectorField[x + stride][y]);
 0208                    var vectorX2 = vectorField[x][y].Add(vectorField[x - stride][y]);
 0209                    var vectorY = vectorField[x][y].Add(vectorField[x][y + stride]);
 0210                    var vectorY2 = vectorField[x][y].Add(vectorField[x][y - stride]);
 211
 0212                    var angleX = vectorX.AngleBetween(vectorX2);
 0213                    var angleY = vectorY.AngleBetween(vectorY2);
 0214                    var angle = angleX + angleY / 2;
 215
 0216                    var confidence = _confidenceMat[x][y];
 0217                    if (float.IsNaN(angle) || angle > MinAngle)
 0218                    {
 0219                        if (confidence > 0)
 0220                            _confidenceMat[x][y]--;
 0221                    }
 222                    else
 0223                    {
 0224                        _candidates.Add(new Interaction(new Point3(x, y, pointCloud[x][y].Z), InteractionType.None,
 0225                            confidence));
 226
 0227                        if (confidence < MaxConfidence)
 0228                            _confidenceMat[x][y]++;
 0229                    }
 0230                }
 0231            }
 0232        }
 233
 234        public void UpdateVectorfieldParallel()
 0235        {
 0236            var stride = VectorField.Stride;
 0237            var pointCloud = PointCloud.AsJaggedArray();
 0238            var vectorField = VectorField.AsJaggedArray();
 239
 240            // for (var x = stride; x < VectorField.SizeX - stride; x+= stride)
 0241            Parallel.For(stride, VectorField.SizeX - stride, (x) =>
 0242            {
 0243                for (var y = stride; y < VectorField.SizeY - stride; y++)
 0244                {
 0245                    if (!vectorField[x][y].IsValid)
 0246                        continue;
 0247
 0248                    var vectorX = vectorField[x][y].Add(vectorField[x + stride][y]);
 0249                    var vectorX2 = vectorField[x][y].Add(vectorField[x - stride][y]);
 0250                    var vectorY = vectorField[x][y].Add(vectorField[x][y + stride]);
 0251                    var vectorY2 = vectorField[x][y].Add(vectorField[x][y - stride]);
 0252
 0253                    var angleX = vectorX.AngleBetween(vectorX2);
 0254                    var angleY = vectorY.AngleBetween(vectorY2);
 0255                    var angle = angleX + angleY / 2;
 0256
 0257                    var confidence = _confidenceMat[x][y];
 0258                    if (float.IsNaN(angle) || angle > MinAngle)
 0259                    {
 0260                        if (confidence > 0)
 0261                            _confidenceMat[x][y]--;
 0262                    }
 0263                    else
 0264                    {
 0265                        _candidates.Add(new Interaction(new Point3(x, y, pointCloud[x][y].Z), InteractionType.None,
 0266                            confidence));
 0267
 0268                        if (confidence < MaxConfidence)
 0269                            _confidenceMat[x][y]++;
 0270                    }
 0271                }
 0272            });
 0273        }
 274
 275        public void UpdateVectorfieldParallelStepped()
 0276        {
 0277            var stride = VectorField.Stride;
 0278            var pointCloud = PointCloud.AsJaggedArray();
 0279            var vectorField = VectorField.AsJaggedArray();
 280
 281            // for (var x = stride; x < VectorField.SizeX - stride; x+= stride)
 0282            Parallel.For(1, VectorField.SizeX - stride, (i) =>
 0283            {
 0284                var x = i * stride;
 0285
 0286                for (var y = stride; y < VectorField.SizeY - stride; y += stride)
 0287                {
 0288                    var vCenter = vectorField[x][y];
 0289
 0290                    if (!vCenter.IsValid)
 0291                        continue;
 0292
 0293                    var vectorX = vCenter.Add(vectorField[x + stride][y]);
 0294                    var vectorX2 = vCenter.Add(vectorField[x - stride][y]);
 0295                    var vectorY = vCenter.Add(vectorField[x][y + stride]);
 0296                    var vectorY2 = vCenter.Add(vectorField[x][y - stride]);
 0297
 0298                    var angleX = vectorX.AngleBetween(vectorX2);
 0299                    var angleY = vectorY.AngleBetween(vectorY2);
 0300                    var angle = angleX + angleY / 2f;
 0301
 0302                    var confidence = _confidenceMat[x][y];
 0303                    if (float.IsNaN(angle) || angle > MinAngle)
 0304                    {
 0305                        if (confidence > 0)
 0306                            _confidenceMat[x][y]--;
 0307                    }
 0308                    else
 0309                    {
 0310                        _candidates.Add(new Interaction(new Point3(x, y, pointCloud[x][y].Z), InteractionType.None,
 0311                            confidence));
 0312
 0313                        if (confidence < MaxConfidence)
 0314                            _confidenceMat[x][y]++;
 0315                    }
 0316                }
 0317            });
 0318        }
 319
 320        public void UpdateVectorfieldStepped1d()
 0321        {
 0322            var stride = VectorField.Stride;
 0323            var pointCloud = PointCloud.AsSpan();
 0324            var vectorField = VectorField.AsArray().AsMemory();
 325
 0326            var width = VectorField.SizeX;
 327
 0328            for (var x = stride; x < VectorField.SizeX - stride; x += stride)
 329                // Parallel.ForEach(SteppedIterator.SteppedIntegerList(stride, VectorField.SizeX - stride, stride), (x) 
 0330            {
 0331                for (var y = stride; y < VectorField.SizeY - stride; y += stride)
 0332                {
 0333                    var idx = y * width + x;
 334
 0335                    if (!vectorField.Span[idx].IsValid)
 0336                        continue;
 337
 338                    // idx = y * width + x + stride == idx + stride
 0339                    var vectorX = vectorField.Span[idx].Add(vectorField.Span[idx + stride]);
 340
 341                    // idx = y * width + x + stride == idx + stride
 0342                    var vectorX2 = vectorField.Span[idx].Add(vectorField.Span[idx - stride]);
 343
 0344                    var idx2 = (y + stride) * width + x;
 0345                    var vectorY = vectorField.Span[idx].Add(vectorField.Span[idx2]);
 346
 0347                    var idx3 = (y - stride) * width + x;
 0348                    var vectorY2 = vectorField.Span[idx].Add(vectorField.Span[idx3]);
 349
 0350                    var angleX = vectorX.AngleBetween(vectorX2);
 0351                    var angleY = vectorY.AngleBetween(vectorY2);
 0352                    var angle = angleX + angleY / 2;
 353
 0354                    var confidence = _confidenceMat[x][y];
 0355                    if (float.IsNaN(angle) || angle > MinAngle)
 0356                    {
 0357                        if (confidence > 0)
 0358                            _confidenceMat[x][y]--;
 0359                    }
 360                    else
 0361                    {
 0362                        _candidates.Add(new Interaction(new Point3(x, y, pointCloud[idx].Z), InteractionType.None,
 0363                            confidence));
 364
 0365                        if (confidence < MaxConfidence)
 0366                            _confidenceMat[x][y]++;
 0367                    }
 0368                }
 0369            }
 370            //);
 0371        }
 372
 373        public void UpdateVectorfieldSteppedParallel1d()
 0374        {
 0375            var stride = VectorField.Stride;
 0376            var pointCloud = PointCloud.AsMemory();
 0377            var vectorField = VectorField.AsArray().AsMemory();
 378
 0379            var width = VectorField.SizeX;
 380
 381            // for (var x = stride; x < VectorField.SizeX - stride; x+= stride)
 0382            Parallel.ForEach(SteppedIterator.SteppedIntegerList(stride, VectorField.SizeX - stride, stride), (x) =>
 0383            {
 0384                for (var y = stride; y < VectorField.SizeY - stride; y += stride)
 0385                {
 0386                    var idx = y * width + x;
 0387
 0388                    if (!vectorField.Span[idx].IsValid)
 0389                        continue;
 0390
 0391                    var vCenter = vectorField.Span[idx];
 0392
 0393                    // idx = y * width + x + stride == idx + stride
 0394                    var vectorX = vCenter.Add(vectorField.Span[idx + stride]);
 0395
 0396                    // idx = y * width + x + stride == idx + stride
 0397                    var vectorX2 = vCenter.Add(vectorField.Span[idx - stride]);
 0398
 0399                    var idx2 = (y + stride) * width + x;
 0400                    var vectorY = vCenter.Add(vectorField.Span[idx2]);
 0401
 0402                    var idx3 = (y - stride) * width + x;
 0403                    var vectorY2 = vCenter.Add(vectorField.Span[idx3]);
 0404
 0405                    var angleX = vectorX.AngleBetween(vectorX2);
 0406                    var angleY = vectorY.AngleBetween(vectorY2);
 0407                    var angle = angleX + angleY / 2f;
 0408
 0409                    var confidence = _confidenceMat[x][y];
 0410                    if (float.IsNaN(angle) || angle > MinAngle)
 0411                    {
 0412                        if (confidence > 0)
 0413                            _confidenceMat[x][y]--;
 0414                    }
 0415                    else
 0416                    {
 0417                        _candidates.Add(new Interaction(new Point3(x, y, pointCloud.Span[idx].Z), InteractionType.None,
 0418                            confidence));
 0419
 0420                        if (confidence < MaxConfidence)
 0421                            _confidenceMat[x][y]++;
 0422                    }
 0423                }
 0424            });
 425            //);
 0426        }
 427
 428        public IEnumerable<Interaction> ApplyConfidenceFilter1()
 0429        {
 0430            return _candidates.Where(item => item.Confidence > MinConfidence);
 0431        }
 432
 433        public IEnumerable<Interaction> ApplyConfidenceFilter2()
 0434        {
 0435            return _candidates.ToArray().Where(item => item.Confidence > MinConfidence);
 0436        }
 437
 438        public IEnumerable<Interaction> ApplyConfidenceFilter3()
 0439        {
 0440            return _candidates.AsReadOnly().Where(item => item.Confidence > MinConfidence);
 0441        }
 442
 443        public IEnumerable<Interaction> ApplyConfidenceFilter4()
 0444        {
 0445            var span = _candidates.ToArray().AsSpan();
 0446            var result = new List<Interaction>();
 0447            for (var i = 0; i < span.Length; i++)
 0448            {
 0449                var item = span[i];
 0450                if (item.Confidence > MinConfidence)
 0451                    result.Add(item);
 0452            }
 453
 0454            return result;
 0455        }
 456
 457        /// <summary>
 458        /// Called when [new interactions].
 459        /// </summary>
 460        /// <param name="args">The arguments.</param>
 0461        protected virtual void OnNewInteractions(List<Interaction> args) => NewInteractions?.Invoke(this, args);
 462
 463
 464        protected override IEnumerable<Interaction> ApplyConfidenceFilter(IEnumerable<Interaction> interactions)
 0465        {
 0466            return interactions.Where(item => item.Confidence > MinConfidence);
 0467        }
 468
 469
 470
 471        protected override List<Interaction> ComputeExtremumType(List<Interaction> interactions, Point3[][] pointsArray)
 0472        {
 0473            interactions.ForEach(interaction =>
 0474                interaction.ExtremumDescription = ComputeExtremumType(pointsArray, (int)interaction.Position.X, (int)int
 475
 0476            return interactions;
 0477        }
 478
 479        /// <summary>
 480        /// Calculates the average distance for the currently stored PointCloud.
 481        /// </summary>
 482        /// <returns></returns>
 483        public override float CalculateAverageDistance()
 0484        {
 0485            var sum = 0f;
 0486            var points = PointCloud?.AsArray();
 487
 0488            if (points == null)
 0489                return sum;
 490
 0491            var numValidSamples = 0;
 492
 0493            for (var i = 0; i < points.Length; ++i)
 0494            {
 0495                if (!points[i].IsValid || points[i].IsFiltered)
 0496                    continue;
 497
 0498                numValidSamples++;
 0499                sum += points[i].Z;
 0500            }
 501
 0502            return (float) decimal.Round((decimal) (sum / numValidSamples), 2);
 0503        }
 504
 505        private static Point3 GetSample(Point3[][] pointsArray, int xPos, int yPos, Tuple<int, int>[] samples, int i, in
 0506        {
 0507            var xIdx = xPos + samples[i].Item1;
 0508            xIdx = Math.Min(Math.Max(xIdx, 0), xMax);
 509
 0510            var yIdx = yPos + samples[i].Item2;
 0511            yIdx = Math.Min(Math.Max(yIdx, 0), yMax);
 0512            var sample = pointsArray[xIdx][yIdx];
 513
 0514            return sample;
 0515        }
 516
 517        private Tuple<int, int>[] GenerateSamples()
 0518        {
 0519            var result = new List<Tuple<int, int>>();
 520
 0521            var rnd = new Random();
 522
 0523            var min = (int)Math.Floor(0.5f * ExtremumTypeCheckRadius);
 0524            var max = ExtremumTypeCheckRadius;
 525
 0526            for (var i = 0; i < ExtremumTypeCheckNumSamples; i++)
 0527            {
 0528                var xStochastic = rnd.Next(min, max);
 0529                var yStochastic = rnd.Next(min, max);
 530
 0531                result.Add(new Tuple<int, int>(xStochastic, yStochastic));
 0532            }
 533
 0534            return result.ToArray();
 0535        }
 536
 537        private void UpdateSamples()
 0538        {
 0539            var samplesFixed = new List<Tuple<int, int>>();
 540
 0541            for (var i = 0; i < ExtremumTypeCheckNumSamples; i++)
 0542            {
 0543                var p = (float)i / ExtremumTypeCheckRadius;
 0544                var xFixed = (int) Math.Floor(ExtremumTypeCheckRadius * Math.Cos(p * 2 * Math.PI));
 0545                var yFixed = (int) Math.Floor(ExtremumTypeCheckRadius * Math.Sin(p * 2 * Math.PI));
 546
 0547                samplesFixed.Add(new Tuple<int, int>(xFixed, yFixed));
 0548            }
 0549            _fixedSamples = samplesFixed.ToArray();
 550
 0551            _stochasticSamples = GenerateSamples();
 0552        }
 553
 554    }
 555
 556}