// determines the angle, in radians, between two points. the angle is defined // by the circle centered on the start point with a radius to the end point, // where 0 radians is straight right from start (+x-axis) and PI/2 radians is // straight down (+y-axis). public static double AngleInRadians(PointR start, PointR end, bool positiveOnly) { double radians = 0.0; if (start.X != end.X) { radians = Math.Atan2(end.Y - start.Y, end.X - start.X); } else // pure vertical movement { if (end.Y < start.Y) { radians = -Math.PI / 2.0; // -90 degrees is straight up } else if (end.Y > start.Y) { radians = Math.PI / 2.0; // 90 degrees is straight down } } if (positiveOnly && radians < 0.0) { radians += Math.PI * 2.0; } return(radians); }
public static double Distance(PointR p1, PointR p2) { double dx = p2.X - p1.X; double dy = p2.Y - p1.Y; return(Math.Sqrt(dx * dx + dy * dy)); }
// rotate the points by the given radians about their centroid public static ArrayList RotateByRadians(ArrayList points, double radians) { ArrayList newPoints = new ArrayList(points.Count); PointR c = Centroid(points); double cos = Math.Cos(radians); double sin = Math.Sin(radians); double cx = c.X; double cy = c.Y; for (int i = 0; i < points.Count; i++) { PointR p = (PointR)points[i]; double dx = p.X - cx; double dy = p.Y - cy; PointR q = PointR.Empty; q.X = dx * cos - dy * sin + cx; q.Y = dx * sin + dy * cos + cy; newPoints.Add(q); } return(newPoints); }
// Rotate a point 'p' around a point 'c' by the given radians. // Rotation (around the origin) amounts to a 2x2 matrix of the form: // // [ cos A -sin A ] [ p.x ] // [ sin A cos A ] [ p.y ] // // Note that the C# Math coordinate system has +x-axis stright right and // +y-axis straight down. Rotation is clockwise such that from +x-axis to // +y-axis is +90 degrees, from +x-axis to -x-axis is +180 degrees, and // from +x-axis to -y-axis is -90 degrees. public static PointR RotatePoint(PointR p, PointR c, double radians) { PointR q = PointR.Empty; q.X = (p.X - c.X) * Math.Cos(radians) - (p.Y - c.Y) * Math.Sin(radians) + c.X; q.Y = (p.X - c.X) * Math.Sin(radians) + (p.Y - c.Y) * Math.Cos(radians) + c.Y; return(q); }
public override bool Equals(object obj) { if (obj is PointR) { PointR p = (PointR)obj; return(X == p.X && Y == p.Y); } return(false); }
// copy constructor public PointR(PointR p) { //_x = p.X; //_y = p.Y; //_t = p.T; X = p.X; Y = p.Y; T = p.T; }
// translates the points by the given delta amounts public static ArrayList TranslateBy(ArrayList points, SizeR sz) { ArrayList newPoints = new ArrayList(points.Count); for (int i = 0; i < points.Count; i++) { PointR p = (PointR)points[i]; p.X += sz.Width; p.Y += sz.Height; newPoints.Add(p); } return(newPoints); }
// scales the points so that the length of their shorter side // matches the length of the shorter side of the given box. // thus, both dimensions are warped proportionally, rather than // independently, like in the function ScaleTo. public static ArrayList ScaleToMin(ArrayList points, RectangleR box) { ArrayList newPoints = new ArrayList(points.Count); RectangleR r = FindBox(points); for (int i = 0; i < points.Count; i++) { PointR p = (PointR)points[i]; p.X *= (box.MinSide / r.MinSide); p.Y *= (box.MinSide / r.MinSide); newPoints.Add(p); } return(newPoints); }
// scales by the percentages contained in the 'sz' parameter. values of 1.0 would result in the // identity scale (that is, no change). public static ArrayList ScaleBy(ArrayList points, SizeR sz) { ArrayList newPoints = new ArrayList(points.Count); RectangleR r = FindBox(points); for (int i = 0; i < points.Count; i++) { PointR p = (PointR)points[i]; p.X *= sz.Width; p.Y *= sz.Height; newPoints.Add(p); } return(newPoints); }
// translates the points so that their centroid lies at 'toPt' public static ArrayList TranslateCentroidTo(ArrayList points, PointR toPt) { ArrayList newPoints = new ArrayList(points.Count); PointR centroid = Centroid(points); for (int i = 0; i < points.Count; i++) { PointR p = (PointR)points[i]; p.X += (toPt.X - centroid.X); p.Y += (toPt.Y - centroid.Y); newPoints.Add(p); } return(newPoints); }
// translates the points so that the upper-left corner of their bounding box lies at 'toPt' public static ArrayList TranslateBBoxTo(ArrayList points, PointR toPt) { ArrayList newPoints = new ArrayList(points.Count); RectangleR r = Utils.FindBox(points); for (int i = 0; i < points.Count; i++) { PointR p = (PointR)points[i]; p.X += (toPt.X - r.X); p.Y += (toPt.Y - r.Y); newPoints.Add(p); } return(newPoints); }
// scales the points so that they form the size given. does not restore the // origin of the box. public static ArrayList ScaleTo(ArrayList points, SizeR sz) { ArrayList newPoints = new ArrayList(points.Count); RectangleR r = FindBox(points); for (int i = 0; i < points.Count; i++) { PointR p = (PointR)points[i]; if (r.Width != 0d) { p.X *= (sz.Width / r.Width); } if (r.Height != 0d) { p.Y *= (sz.Height / r.Height); } newPoints.Add(p); } return(newPoints); }
// assumes the reader has been just moved to the head of the content. private Gesture ReadGesture(XmlTextReader reader) { Debug.Assert(reader.LocalName == "Gesture"); string name = reader.GetAttribute("Name"); ArrayList points = new ArrayList(XmlConvert.ToInt32(reader.GetAttribute("NumPts"))); reader.Read(); // advance to the first Point Debug.Assert(reader.LocalName == "Point"); while (reader.NodeType != XmlNodeType.EndElement) { PointR p = PointR.Empty; p.X = XmlConvert.ToDouble(reader.GetAttribute("X")); p.Y = XmlConvert.ToDouble(reader.GetAttribute("Y")); p.T = XmlConvert.ToInt32(reader.GetAttribute("T")); points.Add(p); reader.ReadStartElement("Point"); } return(new Gesture(name, points)); }
public bool SaveGesture(string filename, ArrayList points) { // add the new prototype with the name extracted from the filename. string name = Gesture.ParseName(filename); if (_gestures.ContainsKey(name)) { _gestures.Remove(name); } //Gesture newPrototype = new Gesture(name, points); //_gestures.Add(name, newPrototype); // figure out the duration of the gesture PointR p0 = (PointR)points[0]; PointR pn = (PointR)points[points.Count - 1]; // do the xml writing bool success = true; XmlTextWriter writer = null; try { // save the prototype as an Xml file writer = new XmlTextWriter(filename, Encoding.UTF8); writer.Formatting = Formatting.Indented; writer.WriteStartDocument(true); writer.WriteStartElement("Gesture"); writer.WriteAttributeString("Name", name); writer.WriteAttributeString("NumPts", XmlConvert.ToString(points.Count)); writer.WriteAttributeString("MillSeconds", XmlConvert.ToString(pn.T - p0.T)); writer.WriteAttributeString("AppName", Assembly.GetExecutingAssembly().GetName().Name); writer.WriteAttributeString("AppVer", Assembly.GetExecutingAssembly().GetName().Version.ToString()); writer.WriteAttributeString("Date", DateTime.Now.ToLongDateString()); writer.WriteAttributeString("TimeOfDay", DateTime.Now.ToLongTimeString()); // write out the raw individual points foreach (PointR p in points) { writer.WriteStartElement("Point"); writer.WriteAttributeString("X", XmlConvert.ToString(p.X)); writer.WriteAttributeString("Y", XmlConvert.ToString(p.Y)); writer.WriteAttributeString("T", XmlConvert.ToString(p.T)); writer.WriteEndElement(); // <Point /> } writer.WriteEndDocument(); // </Gesture> } catch (XmlException xex) { Console.Write(xex.Message); success = false; } catch (Exception ex) { Console.Write(ex.Message); success = false; } finally { if (writer != null) { writer.Close(); } } return(success); // Xml file successfully written (or not) }
// determines the angle, in degrees, between two points. the angle is defined // by the circle centered on the start point with a radius to the end point, // where 0 degrees is straight right from start (+x-axis) and 90 degrees is // straight down (+y-axis). public static double AngleInDegrees(PointR start, PointR end, bool positiveOnly) { double radians = AngleInRadians(start, end, positiveOnly); return(Rad2Deg(radians)); }
private void MainForm_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (_isDown) { if (_points.Count >= 2) { PointR p = (PointR)_points[_points.Count - 1]; //_directionalCodewords = "" + getDirectionalCodewords(e.X, e.Y, p.X, p.Y); _directionalCodewordsQueue.Enqueue(getDirectionalCodewords(e.X, e.Y, p.X, p.Y)); if (_directionalCodewordsQueue.Count > _maxCount) { _directionalCodewordsQueue.Dequeue(); } } _points.Add(new PointR(e.X, e.Y, Environment.TickCount)); //info = info + "a"; if (_hmmc != null && _directionalCodewordsQueue.Count > 1 && !_recording) // not recording, so testing { Queue <int> directionalCodewordsQueueTemp = _directionalCodewordsQueue; while (directionalCodewordsQueueTemp.Count > 40) { //lblResult.Text = "Recognizing..."; _info = null; _info = _info + _rec.encode(_directionalCodewordsQueue.ToArray()) + "\n"; //int[] observations = _rec.decode(_directionalCodewords); int[] observations = directionalCodewordsQueueTemp.ToArray(); _info = _info + _hmmc.Compute(observations) + "\n"; string gestureName = (string)_hmms[0].Tag; double probTemp = 0; _hmmc[0].Decode(observations, out probTemp); //double probTemp = hmms[0].Evaluate(observations); foreach (HiddenMarkovModel hmm in _hmms) { //double prob = hmm.Evaluate(observations); double prob = 0; int[] viterbipath = hmm.Decode(observations, out prob); if (prob > probTemp) { gestureName = (string)hmm.Tag; probTemp = prob; } //info = info + hmm.Tag + "\t" + hmm.Evaluate(observations) + "\t"; _info = _info + hmm.Tag + "\t" + prob + "\t"; // = hmm.Decode(observations); foreach (int state in viterbipath) { _info = _info + state + " "; } _info = _info + "\n"; } double probTM = 0; int[] viterbipathTM = _hmmc.Threshold.Decode(observations, out probTM); _info = _info + "ThresholdModel\t" + probTM + "\t"; //hmmc.Threshold.Decode(observations); foreach (int state in viterbipathTM) { _info = _info + state + " "; } _info = _info + "\n"; if (probTM > probTemp) { gestureName = "Threshold"; _info = _info + "\n\n" + gestureName; } else { _info = _info + "\n\n" + gestureName; _directionalCodewordsQueue.Clear(); break; } for (int loop = 0; loop < 10; loop++) { directionalCodewordsQueueTemp.Dequeue(); } } } Invalidate(); } } //Invalidate(new Rectangle(e.X - 2, e.Y - 2, 4, 4)); }