< 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: 142
Coverable lines: 142
Total lines: 259
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 perfItem = new ProcessPerformance();
 0107            if (MeasurePerformance)
 0108            {
 0109                _stopWatch.Start();
 0110            }
 111
 0112            if (MeasurePerformance)
 0113            {
 0114                _stopWatch.Stop();
 0115                perfItem.Preparation = _stopWatch.Elapsed;
 0116                _stopWatch.Reset();
 0117            }
 118
 0119            if (MeasurePerformance)
 0120            {
 0121                _stopWatch.Start();
 0122            }
 123
 0124            var candidates = FindExtremaInVectorfield();
 125
 0126            if (MeasurePerformance)
 0127            {
 0128                _stopWatch.Stop();
 0129                perfItem.Update = _stopWatch.Elapsed;
 0130                _stopWatch.Reset();
 0131            }
 132
 0133            if (MeasurePerformance)
 0134            {
 0135                _stopWatch.Start();
 0136            }
 137
 0138            var interactions =  ConvertDepthValue(candidates.ToList());
 139
 0140            if (MeasurePerformance)
 0141            {
 0142                _stopWatch.Stop();
 0143                perfItem.ConvertDepthValue = _stopWatch.Elapsed;
 0144                _stopWatch.Reset();
 0145            }
 146
 0147            if (MeasurePerformance)
 0148            {
 0149              _stopWatch.Start();
 0150            }
 151
 0152            var processedInteractions = ComputeExtremumType(interactions, PointCloud.AsJaggedArray());
 153
 0154            var cleanedUpInteractions = RemoveExtremumsBetweenTouches(processedInteractions);
 155
 0156            if (MeasurePerformance)
 0157            {
 0158              _stopWatch.Stop();
 0159              perfItem.ComputeExtremumType = _stopWatch.Elapsed;
 0160              _stopWatch.Reset();
 0161            }
 162
 163
 0164            if (MeasurePerformance)
 0165            {
 0166                _stopWatch.Start();
 0167            }
 168
 0169            var frame = ComputeSmoothingValue(cleanedUpInteractions);
 170
 0171            if (MeasurePerformance)
 0172            {
 0173                _stopWatch.Stop();
 0174                perfItem.Smoothing = _stopWatch.Elapsed;
 0175                _stopWatch.Reset();
 0176            }
 177
 0178            var confidentInteractions = ApplyConfidenceFilter(frame.Interactions);
 179
 0180            UpdatePerformanceMetrics(perfItem);
 181
 0182            OnNewInteractions(confidentInteractions.ToList());
 183
 0184            return Task.FromResult(processResult);
 0185        }
 186
 187        /// <summary>
 188        /// Initializes the confidence matrix.
 189        /// </summary>
 190        private void InitializeConfidenceMatrix()
 0191        {
 0192            if (VectorField != null && !_isProcessing)
 0193                ArrayUtils.InitializeArray(out _confidenceMat, VectorField.SizeX, VectorField.SizeY);
 0194        }
 195
 196        private IEnumerable<Interaction> FindExtremaInVectorfield()
 0197        {
 0198            var stride = VectorField.Stride;
 0199            var pointCloud = PointCloud.AsJaggedArray();
 0200            var vectorField = VectorField.AsJaggedArray();
 201
 0202            var result = new List<Interaction>();
 203
 0204            _isProcessing = true;
 205
 0206            Parallel.For(1, (VectorField.SizeX - 1) / stride, (i) =>
 0207            {
 0208                var x = i * stride;
 0209
 0210                for (var y = stride; y < VectorField.SizeY - stride; y += stride)
 0211                {
 0212                    var vCenter = vectorField[x][y];
 0213
 0214                    if (!vCenter.IsValid)
 0215                        continue;
 0216
 0217                    var vectorX = vCenter.Add(vectorField[x + stride][y]);
 0218                    var vectorX2 = vCenter.Add(vectorField[x - stride][y]);
 0219                    var vectorY = vCenter.Add(vectorField[x][y + stride]);
 0220                    var vectorY2 = vCenter.Add(vectorField[x][y - stride]);
 0221
 0222                    var angleX = vectorX.AngleBetween(vectorX2);
 0223                    var angleY = vectorY.AngleBetween(vectorY2);
 0224                    var angle = angleX + angleY / 2f;
 0225
 0226                    var confidence = _confidenceMat[x][y];
 0227                    if (float.IsNaN(angle) || angle > MinAngle)
 0228                    {
 0229                        if (confidence > 0)
 0230                            _confidenceMat[x][y]--;
 0231                    }
 0232                    else
 0233                    {
 0234                        lock (result)
 0235                        {
 0236                            result.Add(new Interaction(new Point3(x, y, pointCloud[x][y].Z), InteractionType.None,
 0237                                confidence));
 0238                        }
 0239
 0240                        if (confidence < MaxConfidence)
 0241                            _confidenceMat[x][y]++;
 0242                    }
 0243                }
 0244            });
 245
 0246            _isProcessing = false;
 247
 0248            return result.ToArray();
 0249        }
 250
 251        /// <summary>
 252        /// Called when [new interactions].
 253        /// </summary>
 254        /// <param name="args">The arguments.</param>
 0255        protected virtual void OnNewInteractions(List<Interaction> args) => NewInteractions?.Invoke(this, args);
 256
 257    }
 258
 259}