/// <summary> /// Compares two handdatas and tells whether they match. /// </summary> /// <param name="position">The position that should be matched.</param> /// <param name="current">The current data.</param> /// <param name="tollerance">How much each joint is allowed to deviate.</param> /// <returns>Whether the data matches.</returns> public bool AreSimilar(PositionRecord position, HandData current, double tollerance = 0) { tollerance = Math.Pow(tollerance > 0 ? tollerance : TOLLERANCE, 2); // Number of joints. int max = (int)HandData.Joint.MAX; // The total deviation. double total = 0, frac; // The number of non-ignored joints. int nr = 0; for (int i = 0; i < max; i++) { if (position.Ignored[i]) { continue; } // Add square deviation of this joint to the total. frac = position[i].Degrees - current[i].Degrees; total += frac * frac; nr++; } // Check whether this one matches. if (total / nr < tollerance) { return(true); } else { return(false); } }
/// <summary> /// Creates a record from the file input. /// </summary> /// <param name="name">The name of the record.</param> /// <param name="csv">The CSV string of values.</param> /// <returns></returns> private PositionRecord makeRecord(string name, string csv) { // Parse the name line bool standalone = !name.EndsWith("-"); name = name.TrimEnd(new char[] { '-' }); PositionRecord rv = new PositionRecord(name); rv.Standalone = standalone; // Parse the CSV line string[] values = csv.Split(SEPARATOR); if (values.Length != values.Length) { throw new ArgumentException("The CSV needs to contain exactly 22 values.", "csv"); } for (int i = 0; i < values.Length; i++) { string v = values[i].Trim(); if (v == "*") { rv.Ignored[i] = true; } else { rv[i].Value = Double.Parse(values[i].Trim()); } } return(rv); }
/// <summary> /// Parses the contents of the given file. Recognized positions will be saved in /// Hand.positions. /// </summary> public void Parse() { // If the file does not exist, we create it (for writing). Its contents // will of course be empty, so we can just exit immediately. if (!File.Exists(Path)) { File.Create(Path); return; } // name and csv strings, for file input. string name, csv; StreamReader reader = new StreamReader(Path); try { while (reader.Peek() != -1) { // Read two lines. First line is always a name, possibly with the Dependency modifier.... name = reader.ReadLine(); // ... followed by the array of values csv = reader.ReadLine(); PositionRecord record = makeRecord(name, csv); AddPosition(record); } } catch (Exception e) { throw e; } finally { reader.Close(); reader.Dispose(); } }
/// <summary> /// Compares two handdatas and tells whether they match. /// </summary> /// <param name="position">The position that should be matched.</param> /// <param name="current">The current data.</param> /// <returns>Whether the data matches.</returns> public bool AreSimilar(PositionRecord position, HandData current, double tollerance = 0) { tollerance = tollerance > 0 ? tollerance : TOLLERANCE; int max = (int)HandData.Joint.MAX; for (int i = 0; i < max; i++) { if (position.Ignored[i]) continue; else if (!position[i].IsSimilar(current[i], tollerance)) return false; } return true; }
/// <summary> /// Returns a list of matches with the given HandData object, with the precision altered by the given argument. /// </summary> /// <param name="needle">The HandData object that we have to search a match for.</param> /// <param name="precision">The normal precision will be multiplied by this number. /// Low number increases precision, high number decreases precision.</param> /// <returns>A List of matches. Will be empty if none were found.</returns> public static List <PositionRecord> GetAllMatches(PositionRecord needle, double precision) { List <PositionRecord> rv = new List <PositionRecord>(); foreach (PositionRecord pr in positions.Values) { if (pr.IsSimilar(needle, precision)) { rv.Add(pr); } } return(rv); }
/// <summary> /// Tells whether a hand's current position is similar to this one, with /// the precision altered by the given argument. /// Not to confused with IsSimilar(HandData, double) which is a less /// specific implementation. /// </summary> /// <param name="other">The other handposition.</param> /// <param name="tollerance">The factor by which the default precision should be multiplied.</param> /// <returns>Whether the other hand is similar to this one.</returns> public bool IsSimilar(PositionRecord other, double tollerance) { int max = NR_FINGERS * NR_JOINTS + 2; for (int i = 0; i < max; i++) { if (Ignored[i] || other.Ignored[i]) { continue; } else if (!this[i].IsSimilar(other[i], tollerance)) { return(false); } } return(true); }
/// <summary> /// Saves a record to the text file. /// </summary> /// <param name="record">The record that should be saved.</param> public void Save(PositionRecord record) { StreamWriter writer = null; try { writer = new StreamWriter(Path, true); writer.WriteLine(record.Name + (record.Standalone ? "" : "-")); writer.WriteLine(record.CSV); AddPosition(record); } finally { if (writer != null) { writer.Close(); writer.Dispose(); } } }
/// <summary> /// Adds a record to the list of known records. /// </summary> /// <param name="pr">The PositionRecord that needs to be added.</param> public static void AddPosition(PositionRecord pr) { positions.Add(pr.Name, pr); }