123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- 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<GesturePointOffset> gesturePointOffsetList = new List<GesturePointOffset>();
- 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<Dictionary<string, string>>(json);
- this.sampleRate = int.Parse(data["sample_rate"]);
- gesturePointOffsetList.Clear();
- GesturePointOffset[] pointOffsets = JsonConvert.DeserializeObject<GesturePointOffset[]>(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;
- }
- }
|