| | | 1 | | using System; |
| | | 2 | | using System.Collections.Generic; |
| | | 3 | | using System.Diagnostics; |
| | | 4 | | using System.Linq; |
| | | 5 | | using System.Threading.Tasks; |
| | | 6 | | using ReFlex.Core.Common.Components; |
| | | 7 | | using ReFlex.Core.Common.Util; |
| | | 8 | | using ReFlex.Core.Interactivity.Interfaces; |
| | | 9 | | using Math = System.Math; |
| | | 10 | | |
| | | 11 | | namespace 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 | | { |
| | 6 | 21 | | 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> |
| | 0 | 31 | | public override ObserverType Type => ObserverType.SingleTouch; |
| | | 32 | | |
| | | 33 | | /// <summary> |
| | | 34 | | /// Gets or sets the source. |
| | | 35 | | /// </summary> |
| | | 36 | | /// <value> |
| | | 37 | | /// The source. |
| | | 38 | | /// </value> |
| | 24 | 39 | | 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> |
| | 0 | 48 | | public override VectorField2 VectorField { get; set; } |
| | | 49 | | |
| | | 50 | | #endregion |
| | | 51 | | |
| | | 52 | | protected override IEnumerable<Interaction> SelectSmoothedInteractions(IEnumerable<Interaction> interactions) |
| | 10 | 53 | | => interactions.OrderByDescending(item => item.Time) |
| | 6 | 54 | | .ThenByDescending(item => item.TouchId) |
| | 4 | 55 | | .Take(1); |
| | | 56 | | |
| | | 57 | | protected override Task<ProcessingResult> CheckInitialState() |
| | 6 | 58 | | { |
| | 6 | 59 | | return Task.FromResult(PointCloud == null |
| | 6 | 60 | | ? new ProcessingResult(ProcessServiceStatus.Error) |
| | 6 | 61 | | : new ProcessingResult(ProcessServiceStatus.Available) |
| | 6 | 62 | | ); |
| | 6 | 63 | | } |
| | | 64 | | |
| | | 65 | | |
| | | 66 | | protected override Task<Tuple<IEnumerable<Interaction>, ProcessPerformance>> Analyze( |
| | | 67 | | ProcessPerformance performance) |
| | 4 | 68 | | { |
| | 4 | 69 | | var extreme = FindGlobalExtreme(PointCloud, Distance); |
| | 4 | 70 | | var result = new List<Interaction>() { new Interaction(extreme, InteractionType.None, 1) }; |
| | 4 | 71 | | var perfItem = new ProcessPerformance(); |
| | 4 | 72 | | perfItem.Preparation = TimeSpan.Zero; |
| | | 73 | | |
| | 4 | 74 | | return Task.FromResult(new Tuple<IEnumerable<Interaction>, ProcessPerformance>(result, perfItem)); |
| | 4 | 75 | | } |
| | | 76 | | |
| | | 77 | | /// <summary> |
| | | 78 | | /// Finds the global extreme. |
| | | 79 | | /// </summary> |
| | | 80 | | /// <param name="source">The source.</param> |
| | | 81 | | /// <param name="averageDepth">The average depth.</param> |
| | | 82 | | /// <returns></returns> |
| | | 83 | | public static Point3 FindGlobalExtreme(PointCloud3 source, float averageDepth) |
| | 4 | 84 | | { |
| | 4 | 85 | | var candidate = new Point3(0, 0, averageDepth); |
| | | 86 | | |
| | 4 | 87 | | if (source == null) |
| | 0 | 88 | | return candidate; |
| | | 89 | | |
| | 4 | 90 | | var candidates = source.AsJaggedArray(); |
| | | 91 | | |
| | 408 | 92 | | for (var x = 0; x < source.SizeX; ++x) |
| | 200 | 93 | | { |
| | 12400 | 94 | | for (var y = 0; y < source.SizeY; ++y) |
| | 6000 | 95 | | { |
| | 6000 | 96 | | var curr = candidates[x][y]; |
| | | 97 | | |
| | 6000 | 98 | | if (!curr.IsValid) |
| | 0 | 99 | | continue; |
| | | 100 | | |
| | 6000 | 101 | | if (!(Math.Abs(curr.Z - averageDepth) |
| | 6000 | 102 | | >= Math.Abs(candidate.Z - averageDepth))) |
| | 3256 | 103 | | continue; |
| | | 104 | | |
| | 2744 | 105 | | candidate.X = x; |
| | 2744 | 106 | | candidate.Y = y; |
| | 2744 | 107 | | candidate.Z = candidates[x][y].Z; |
| | 2744 | 108 | | } |
| | 200 | 109 | | } |
| | | 110 | | |
| | 4 | 111 | | return candidate; |
| | 4 | 112 | | } |
| | | 113 | | } |
| | | 114 | | |
| | | 115 | | } |