using Newtonsoft.Json; using NUnit.Framework; using System.Collections.Generic; using System.Net.Sockets; using UnityEngine; /* 本文件用于控制手势的采集和比对 * 也包含导出和导入手势的功能 */ public class GestureController { // Start is called once before the first execution of Update after the MonoBehaviour is created private List gesturePointOffsetList = new List(); public int sampleRate { private set; get; } = 10; // 采样率 private Vector2 prePointLoc = new Vector2(0, 0); // 第一个点 private Vector2 curPointLoc = new Vector2(0, 0); // 第二个点 public string ExportToJson() { string json = string.Empty; if (gesturePointOffsetList.Count / 2 <= sampleRate) { return json; } json = JsonConvert.SerializeObject(this); return json; } public void ImportFromJson(string json) { var data = JsonConvert.DeserializeObject>(json); this.sampleRate = int.Parse(data["sample_rate"]); gesturePointOffsetList.Clear(); GesturePointOffset[] pointOffsets = JsonConvert.DeserializeObject(data["points"]); foreach (var point in pointOffsets) { gesturePointOffsetList.Add(point); } } // 添加一个运动轨迹 public void AddGesturePoint(Vector2 pointLoc) { if (gesturePointOffsetList.Count == 0) { prePointLoc = pointLoc; curPointLoc = pointLoc; GesturePointOffset gesturePointMovement = new GesturePointOffset(0, 0); gesturePointOffsetList.Add(gesturePointMovement); return; } else { curPointLoc = pointLoc; float distance = Vector2.Distance(prePointLoc, curPointLoc); float angle = Vector2.Angle(prePointLoc, curPointLoc); GesturePointOffset gesturePointMovement = new GesturePointOffset(distance, angle); gesturePointOffsetList.Add(gesturePointMovement); prePointLoc = curPointLoc; } } public float CompareGesture(GestureController anotherGesture) { float score = 0f; if (this.sampleRate != anotherGesture.sampleRate) { Debug.Log("Sample rate not match"); return -1f; } int maxGesturePoints = Mathf.Max(this.gesturePointOffsetList.Count, anotherGesture.gesturePointOffsetList.Count); int minGesturePoints = Mathf.Min(this.gesturePointOffsetList.Count, anotherGesture.gesturePointOffsetList.Count); for (int i = 0; i < minGesturePoints; i++) { float ditanceMin = Mathf.Min(this.gesturePointOffsetList[i].distance - anotherGesture.gesturePointOffsetList[i].distance); float ditanceMax = Mathf.Max(this.gesturePointOffsetList[i].distance - anotherGesture.gesturePointOffsetList[i].distance); float distanceScore = ditanceMin / ditanceMax; float angleMin = Mathf.Min(this.gesturePointOffsetList[i].angle - anotherGesture.gesturePointOffsetList[i].angle); float angleMax = Mathf.Max(this.gesturePointOffsetList[i].angle - anotherGesture.gesturePointOffsetList[i].angle); float angleDitance1 = angleMax - angleMin; float angleDitance2 = 360 - angleDitance1; float angleScore = 1 - (Mathf.Min(angleDitance1, angleDitance2) / 180); score = score * (i / (i + 1)) + (distanceScore + angleScore) / 2 * (1f / (i + 1)); } // 如果长度超过20%,就要考虑调整score if ((maxGesturePoints / minGesturePoints) > 1.2f) { int deltaGesturePoints = Mathf.RoundToInt(maxGesturePoints - minGesturePoints * 1.2f); score = score * (minGesturePoints / (minGesturePoints + deltaGesturePoints)); } return score; } }