< 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: 128
Coverable lines: 128
Total lines: 233
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();
 65
 066            if (MeasurePerformance)
 067            {
 068                _stopWatch.Start();
 069            }
 070            var extreme = FindGlobalExtreme(PointCloud, Distance);
 071            if (MeasurePerformance)
 072            {
 073                _stopWatch.Stop();
 074                perfItem.Update = _stopWatch.Elapsed;
 075                _stopWatch.Reset();
 076            }
 77
 78            float depth;
 79            InteractionType type;
 80
 81
 082            if (MeasurePerformance)
 083            {
 084                _stopWatch.Start();
 085            }
 86
 087            var extremumType = ComputeExtremumType(PointCloud.AsJaggedArray(), (int) extreme.X, (int) extreme.Y);
 88
 089            if (MeasurePerformance)
 090            {
 091                _stopWatch.Stop();
 092                perfItem.ComputeExtremumType = _stopWatch.Elapsed;
 093                _stopWatch.Reset();
 094            }
 95
 096            if (MeasurePerformance)
 097            {
 098                _stopWatch.Start();
 099            }
 100
 0101            if (extreme.Z < Distance + MinDistance && extreme.Z > Distance - MinDistance)
 0102            {
 0103                type = InteractionType.None;
 0104                depth = 0;
 0105            }
 0106            else if (extreme.Z < Distance)
 0107            {
 0108                type = InteractionType.Push;
 0109                depth = (Distance - extreme.Z - MinDistance) / (MinDistance - MaxDistance);
 110
 0111                if (depth > 0)
 0112                    depth = 0;
 113
 0114                if (depth < -1)
 0115                    depth = -1;
 0116            }
 117            else
 0118            {
 0119                type = InteractionType.Pull;
 0120                depth = (extreme.Z - MinDistance - Distance) / (MaxDistance - MinDistance);
 121
 0122                if (depth < 0)
 0123                    depth = 0;
 124
 0125                if (depth > 1)
 0126                    depth = 1;
 0127            }
 128
 0129            extreme.Z = depth;
 130
 0131            if (MeasurePerformance)
 0132            {
 0133                _stopWatch.Stop();
 0134                perfItem.ConvertDepthValue = _stopWatch.Elapsed;
 0135                _stopWatch.Reset();
 0136            }
 137
 0138            if (MeasurePerformance)
 0139            {
 0140                _stopWatch.Start();
 0141            }
 142
 0143            var TOLERANCE = 0.001;
 144
 0145            var result = new List<Interaction>();
 146
 0147            if (Math.Abs(depth) > TOLERANCE)
 0148            {
 0149                var interaction = new Interaction(extreme, type, 1);
 0150                interaction.ExtremumDescription = extremumType;
 151
 0152                var frame = ComputeSmoothingValue(interaction.AsList());
 153
 0154                var smoothed = frame.Interactions;
 155
 0156                if (smoothed.Count > 0)
 0157                {
 0158                    result = smoothed.Take(1).ToList();
 159
 0160                    var lastTime = smoothed.Max(item => item.Time);
 0161                    var id = smoothed.Max(item => item.TouchId);
 0162                    var last = smoothed.FirstOrDefault(
 0163                        it => Equals(it.Time, lastTime) && Equals(it.TouchId, id));
 164
 0165                    if (last != null)
 0166                    {
 0167                        var smoothedItem = new Interaction(last)
 0168                        {
 0169                            TouchId = id
 0170                        };
 171
 0172                        result = new List<Interaction> { smoothedItem };
 0173                    }
 0174                }
 175                else
 0176                {
 0177                    result = smoothed;
 0178                }
 0179            }
 180
 0181            if (MeasurePerformance)
 0182            {
 0183                _stopWatch.Stop();
 0184                perfItem.Smoothing = _stopWatch.Elapsed;
 0185                _stopWatch.Reset();
 0186            }
 187
 0188            UpdatePerformanceMetrics(perfItem);
 189
 0190            NewInteractions?.Invoke(this, result);
 191
 0192            return Task.FromResult(processResult);
 0193        }
 194
 195        /// <summary>
 196        /// Finds the global extreme.
 197        /// </summary>
 198        /// <param name="source">The source.</param>
 199        /// <param name="averageDepth">The average depth.</param>
 200        /// <returns></returns>
 201        public static Point3 FindGlobalExtreme(PointCloud3 source, float averageDepth)
 0202        {
 0203            var candidate = new Point3(0, 0, averageDepth);
 204
 0205            if (source == null)
 0206                return candidate;
 207
 0208            var candidates = source.AsJaggedArray();
 209
 0210            for (var x = 0; x < source.SizeX; ++x)
 0211            {
 0212                for (var y = 0; y < source.SizeY; ++y)
 0213                {
 0214                    var curr = candidates[x][y];
 215
 0216                    if (!curr.IsValid)
 0217                        continue;
 218
 0219                    if (!(Math.Abs(curr.Z - averageDepth)
 0220                          >= Math.Abs(candidate.Z - averageDepth)))
 0221                        continue;
 222
 0223                    candidate.X = x;
 0224                    candidate.Y = y;
 0225                    candidate.Z = candidates[x][y].Z;
 0226                }
 0227            }
 228
 0229            return candidate;
 0230        }
 231    }
 232
 233}