< Summary - ReFlex - Library

Information
Class: ReFlex.Core.Interactivity.Components.MultiInteractionObserver
Assembly: ReFlex.Core.Interactivity
File(s): D:\a\reflex\reflex\library\src\Core\Interactivity\Components\MultiInteractionObserver.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 143
Coverable lines: 143
Total lines: 260
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 50
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%210%
get_Type()100%210%
get_PointCloud()100%210%
set_PointCloud(...)0%620%
get_VectorField()100%210%
set_VectorField(...)0%620%
Update()0%812280%
InitializeConfidenceMatrix()0%2040%
FindExtremaInVectorfield()0%156120%
OnNewInteractions(...)0%620%

File(s)

D:\a\reflex\reflex\library\src\Core\Interactivity\Components\MultiInteractionObserver.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Diagnostics;
 4using System.Linq;
 5using System.Threading.Tasks;
 6using ReFlex.Core.Common.Components;
 7using ReFlex.Core.Common.Util;
 8
 9namespace ReFlex.Core.Interactivity.Components
 10{
 11    /// <summary>
 12    /// Finds multiple Interactions on a 2d vectorfield.
 13    /// </summary>
 14    public class MultiInteractionObserver : InteractionObserverBase
 15    {
 16        #region Fields
 17
 18        private PointCloud3 _pointCloud;
 19        private VectorField2 _vectorField;
 20        private int[][] _confidenceMat;
 21
 022        private bool _isProcessing = false;
 23
 024        private readonly Stopwatch _stopWatch = new();
 25
 26
 27        #endregion
 28
 29        #region Properties
 30
 31        /// <summary>
 32        /// Gets the type.
 33        /// </summary>
 34        /// <value>
 35        /// The type.
 36        /// </value>
 037        public override ObserverType Type => ObserverType.MultiTouch;
 38
 39        /// <summary>
 40        /// Gets or sets the point cloud.
 41        /// </summary>
 42        /// <value>
 43        /// The point cloud.
 44        /// </value>
 45        public override PointCloud3 PointCloud
 46        {
 047            get => _pointCloud;
 48            set
 049            {
 050                if (_pointCloud == value)
 051                    return;
 52
 053                _pointCloud = value;
 054                InitializeConfidenceMatrix();
 055            }
 56        }
 57
 58        /// <summary>
 59        /// Gets or sets the vector field.
 60        /// </summary>
 61        /// <value>
 62        /// The vector field.
 63        /// </value>
 64        public override VectorField2 VectorField
 65        {
 066            get => _vectorField;
 67            set
 068            {
 069                if (_vectorField == value)
 070                    return;
 71
 072                _vectorField = value;
 073                InitializeConfidenceMatrix();
 074            }
 75        }
 76
 77        #endregion
 78
 79        #region Events
 80        public override event EventHandler<IList<Interaction>> NewInteractions;
 81
 82        #endregion
 83
 84        /// <summary>
 85        /// Initializes a new instance of the <see cref="MultiInteractionObserver"/> class.
 86        /// </summary>
 087        public MultiInteractionObserver()
 088        {
 089        }
 90
 91        /// <summary>
 92        /// Updates this instance.
 93        /// </summary>
 94        public override Task<ProcessingResult> Update()
 095        {
 096            if (PointCloud == null ||
 097               VectorField == null ||
 098               _confidenceMat == null)
 099                return Task.FromResult(new ProcessingResult(ProcessServiceStatus.Error));
 100
 0101            var processResult = new ProcessingResult(ProcessServiceStatus.Available);
 102
 0103            if (_isProcessing)
 0104                return Task.FromResult(new ProcessingResult(ProcessServiceStatus.Skipped));
 105
 0106            var processingDateTime = DateTime.Now.Ticks;
 0107            var perfItem = new ProcessPerformance();
 0108            if (MeasurePerformance)
 0109            {
 0110                _stopWatch.Start();
 0111            }
 112
 0113            if (MeasurePerformance)
 0114            {
 0115                _stopWatch.Stop();
 0116                perfItem.Preparation = _stopWatch.Elapsed;
 0117                _stopWatch.Reset();
 0118            }
 119
 0120            if (MeasurePerformance)
 0121            {
 0122                _stopWatch.Start();
 0123            }
 124
 0125            var candidates = FindExtremaInVectorfield();
 126
 0127            if (MeasurePerformance)
 0128            {
 0129                _stopWatch.Stop();
 0130                perfItem.Update = _stopWatch.Elapsed;
 0131                _stopWatch.Reset();
 0132            }
 133
 0134            if (MeasurePerformance)
 0135            {
 0136                _stopWatch.Start();
 0137            }
 138
 0139            var interactions =  ConvertDepthValue(candidates.ToList());
 140
 0141            if (MeasurePerformance)
 0142            {
 0143                _stopWatch.Stop();
 0144                perfItem.ConvertDepthValue = _stopWatch.Elapsed;
 0145                _stopWatch.Reset();
 0146            }
 147
 0148            if (MeasurePerformance)
 0149            {
 0150              _stopWatch.Start();
 0151            }
 152
 0153            var processedInteractions = ComputeExtremumType(interactions, PointCloud.AsJaggedArray());
 154
 0155            var cleanedUpInteractions = RemoveExtremumsBetweenTouches(processedInteractions);
 156
 0157            if (MeasurePerformance)
 0158            {
 0159              _stopWatch.Stop();
 0160              perfItem.ComputeExtremumType = _stopWatch.Elapsed;
 0161              _stopWatch.Reset();
 0162            }
 163
 164
 0165            if (MeasurePerformance)
 0166            {
 0167                _stopWatch.Start();
 0168            }
 169
 0170            var frame = ComputeSmoothingValue(cleanedUpInteractions);
 171
 0172            if (MeasurePerformance)
 0173            {
 0174                _stopWatch.Stop();
 0175                perfItem.Smoothing = _stopWatch.Elapsed;
 0176                _stopWatch.Reset();
 0177            }
 178
 0179            var confidentInteractions = ApplyConfidenceFilter(frame.Interactions);
 180
 0181            UpdatePerformanceMetrics(perfItem, processingDateTime);
 182
 0183            OnNewInteractions(confidentInteractions.ToList());
 184
 0185            return Task.FromResult(processResult);
 0186        }
 187
 188        /// <summary>
 189        /// Initializes the confidence matrix.
 190        /// </summary>
 191        private void InitializeConfidenceMatrix()
 0192        {
 0193            if (VectorField != null && !_isProcessing)
 0194                ArrayUtils.InitializeArray(out _confidenceMat, VectorField.SizeX, VectorField.SizeY);
 0195        }
 196
 197        private IEnumerable<Interaction> FindExtremaInVectorfield()
 0198        {
 0199            var stride = VectorField.Stride;
 0200            var pointCloud = PointCloud.AsJaggedArray();
 0201            var vectorField = VectorField.AsJaggedArray();
 202
 0203            var result = new List<Interaction>();
 204
 0205            _isProcessing = true;
 206
 0207            Parallel.For(1, (VectorField.SizeX - 1) / stride, (i) =>
 0208            {
 0209                var x = i * stride;
 0210
 0211                for (var y = stride; y < VectorField.SizeY - stride; y += stride)
 0212                {
 0213                    var vCenter = vectorField[x][y];
 0214
 0215                    if (!vCenter.IsValid)
 0216                        continue;
 0217
 0218                    var vectorX = vCenter.Add(vectorField[x + stride][y]);
 0219                    var vectorX2 = vCenter.Add(vectorField[x - stride][y]);
 0220                    var vectorY = vCenter.Add(vectorField[x][y + stride]);
 0221                    var vectorY2 = vCenter.Add(vectorField[x][y - stride]);
 0222
 0223                    var angleX = vectorX.AngleBetween(vectorX2);
 0224                    var angleY = vectorY.AngleBetween(vectorY2);
 0225                    var angle = angleX + angleY / 2f;
 0226
 0227                    var confidence = _confidenceMat[x][y];
 0228                    if (float.IsNaN(angle) || angle > MinAngle)
 0229                    {
 0230                        if (confidence > 0)
 0231                            _confidenceMat[x][y]--;
 0232                    }
 0233                    else
 0234                    {
 0235                        lock (result)
 0236                        {
 0237                            result.Add(new Interaction(new Point3(x, y, pointCloud[x][y].Z), InteractionType.None,
 0238                                confidence));
 0239                        }
 0240
 0241                        if (confidence < MaxConfidence)
 0242                            _confidenceMat[x][y]++;
 0243                    }
 0244                }
 0245            });
 246
 0247            _isProcessing = false;
 248
 0249            return result.ToArray();
 0250        }
 251
 252        /// <summary>
 253        /// Called when [new interactions].
 254        /// </summary>
 255        /// <param name="args">The arguments.</param>
 0256        protected virtual void OnNewInteractions(List<Interaction> args) => NewInteractions?.Invoke(this, args);
 257
 258    }
 259
 260}