< Summary - ReFlex - Library

Information
Class: ReFlex.Core.Interactivity.Components.SingleInteractionObserver
Assembly: ReFlex.Core.Interactivity
File(s): D:\a\reflex\reflex\library\src\Core\Interactivity\Components\SingleInteractionObserver.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 129
Coverable lines: 129
Total lines: 234
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 52
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%
get_VectorField()100%210%
Update()0%1806420%
FindGlobalExtreme(...)0%110100%

File(s)

D:\a\reflex\reflex\library\src\Core\Interactivity\Components\SingleInteractionObserver.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;
 8using ReFlex.Core.Interactivity.Interfaces;
 9using Math = System.Math;
 10
 11namespace ReFlex.Core.Interactivity.Components
 12{
 13    /// <summary>
 14    /// Observes a depthimage and reports single touch interactions.
 15    /// </summary>
 16    /// <seealso cref="IInteractionObserver" />
 17    /// <inheritdoc />
 18    /// <seealso cref="T:ReFlex.Core.Interactivity.Interfaces.IInteractionObserver" />
 19    public class SingleInteractionObserver : InteractionObserverBase
 20    {
 021        private readonly Stopwatch _stopWatch = new();
 22
 23        #region Properties
 24
 25        /// <summary>
 26        /// Gets the type.
 27        /// </summary>
 28        /// <value>
 29        /// The type.
 30        /// </value>
 031        public override ObserverType Type => ObserverType.SingleTouch;
 32
 33        /// <summary>
 34        /// Gets or sets the source.
 35        /// </summary>
 36        /// <value>
 37        /// The source.
 38        /// </value>
 039        public override PointCloud3 PointCloud { get; set; }
 40
 41        /// <inheritdoc />
 42        /// <summary>
 43        /// Gets or sets the vector field.
 44        /// </summary>
 45        /// <value>
 46        /// The vector field.
 47        /// </value>
 048        public override VectorField2 VectorField { get; set; }
 49
 50        #endregion
 51
 52        #region Events
 53
 54        public override event EventHandler<IList<Interaction>> NewInteractions;
 55
 56        #endregion
 57
 58        public override Task<ProcessingResult> Update()
 059        {
 060            if (PointCloud == null)
 061                return Task.FromResult(new ProcessingResult(ProcessServiceStatus.Error));
 62
 063            var processResult = new ProcessingResult(ProcessServiceStatus.Available);
 064            var perfItem = new ProcessPerformance();
 065            var start = DateTime.Now.Ticks;
 66
 067            if (MeasurePerformance)
 068            {
 069                _stopWatch.Start();
 070            }
 071            var extreme = FindGlobalExtreme(PointCloud, Distance);
 072            if (MeasurePerformance)
 073            {
 074                _stopWatch.Stop();
 075                perfItem.Update = _stopWatch.Elapsed;
 076                _stopWatch.Reset();
 077            }
 78
 79            float depth;
 80            InteractionType type;
 81
 82
 083            if (MeasurePerformance)
 084            {
 085                _stopWatch.Start();
 086            }
 87
 088            var extremumType = ComputeExtremumType(PointCloud.AsJaggedArray(), (int) extreme.X, (int) extreme.Y);
 89
 090            if (MeasurePerformance)
 091            {
 092                _stopWatch.Stop();
 093                perfItem.ComputeExtremumType = _stopWatch.Elapsed;
 094                _stopWatch.Reset();
 095            }
 96
 097            if (MeasurePerformance)
 098            {
 099                _stopWatch.Start();
 0100            }
 101
 0102            if (extreme.Z < Distance + MinDistance && extreme.Z > Distance - MinDistance)
 0103            {
 0104                type = InteractionType.None;
 0105                depth = 0;
 0106            }
 0107            else if (extreme.Z < Distance)
 0108            {
 0109                type = InteractionType.Push;
 0110                depth = (Distance - extreme.Z - MinDistance) / (MinDistance - MaxDistance);
 111
 0112                if (depth > 0)
 0113                    depth = 0;
 114
 0115                if (depth < -1)
 0116                    depth = -1;
 0117            }
 118            else
 0119            {
 0120                type = InteractionType.Pull;
 0121                depth = (extreme.Z - MinDistance - Distance) / (MaxDistance - MinDistance);
 122
 0123                if (depth < 0)
 0124                    depth = 0;
 125
 0126                if (depth > 1)
 0127                    depth = 1;
 0128            }
 129
 0130            extreme.Z = depth;
 131
 0132            if (MeasurePerformance)
 0133            {
 0134                _stopWatch.Stop();
 0135                perfItem.ConvertDepthValue = _stopWatch.Elapsed;
 0136                _stopWatch.Reset();
 0137            }
 138
 0139            if (MeasurePerformance)
 0140            {
 0141                _stopWatch.Start();
 0142            }
 143
 0144            var TOLERANCE = 0.001;
 145
 0146            var result = new List<Interaction>();
 147
 0148            if (Math.Abs(depth) > TOLERANCE)
 0149            {
 0150                var interaction = new Interaction(extreme, type, 1);
 0151                interaction.ExtremumDescription = extremumType;
 152
 0153                var frame = ComputeSmoothingValue(interaction.AsList());
 154
 0155                var smoothed = frame.Interactions;
 156
 0157                if (smoothed.Count > 0)
 0158                {
 0159                    result = smoothed.Take(1).ToList();
 160
 0161                    var lastTime = smoothed.Max(item => item.Time);
 0162                    var id = smoothed.Max(item => item.TouchId);
 0163                    var last = smoothed.FirstOrDefault(
 0164                        it => Equals(it.Time, lastTime) && Equals(it.TouchId, id));
 165
 0166                    if (last != null)
 0167                    {
 0168                        var smoothedItem = new Interaction(last)
 0169                        {
 0170                            TouchId = id
 0171                        };
 172
 0173                        result = new List<Interaction> { smoothedItem };
 0174                    }
 0175                }
 176                else
 0177                {
 0178                    result = smoothed;
 0179                }
 0180            }
 181
 0182            if (MeasurePerformance)
 0183            {
 0184                _stopWatch.Stop();
 0185                perfItem.Smoothing = _stopWatch.Elapsed;
 0186                _stopWatch.Reset();
 0187            }
 188
 0189            UpdatePerformanceMetrics(perfItem, start);
 190
 0191            NewInteractions?.Invoke(this, result);
 192
 0193            return Task.FromResult(processResult);
 0194        }
 195
 196        /// <summary>
 197        /// Finds the global extreme.
 198        /// </summary>
 199        /// <param name="source">The source.</param>
 200        /// <param name="averageDepth">The average depth.</param>
 201        /// <returns></returns>
 202        public static Point3 FindGlobalExtreme(PointCloud3 source, float averageDepth)
 0203        {
 0204            var candidate = new Point3(0, 0, averageDepth);
 205
 0206            if (source == null)
 0207                return candidate;
 208
 0209            var candidates = source.AsJaggedArray();
 210
 0211            for (var x = 0; x < source.SizeX; ++x)
 0212            {
 0213                for (var y = 0; y < source.SizeY; ++y)
 0214                {
 0215                    var curr = candidates[x][y];
 216
 0217                    if (!curr.IsValid)
 0218                        continue;
 219
 0220                    if (!(Math.Abs(curr.Z - averageDepth)
 0221                          >= Math.Abs(candidate.Z - averageDepth)))
 0222                        continue;
 223
 0224                    candidate.X = x;
 0225                    candidate.Y = y;
 0226                    candidate.Z = candidates[x][y].Z;
 0227                }
 0228            }
 229
 0230            return candidate;
 0231        }
 232    }
 233
 234}