private static void WritePointReference(Sketch.Point point, XmlTextWriter xmlDocument) { xmlDocument.WriteStartElement("arg"); xmlDocument.WriteAttributeString("type", "point"); xmlDocument.WriteString(point.Id.ToString()); xmlDocument.WriteEndElement(); }
/// <summary> /// Computes the weighted center of the substrokes /// </summary> private void computeWeightedCenter() { int i, len = m_substrokes.Count; Featurefy.Spatial spatial; Sketch.Point wAvg; float length; //Find weighted average point of many substrokes ulong XL = 0, YL = 0; float L = 0.0f; for (i = 0; i < len; ++i) { spatial = new Featurefy.Spatial(m_substrokes[i].Points); wAvg = spatial.WeightedAveragePoint; length = spatial.Length; //If there is only 1 point if (length == 0.0f) { length = float.Epsilon; } XL += (ulong)(wAvg.X * length); YL += (ulong)(wAvg.Y * length); L += length; } m_weightedCenter = new Sketch.Point(); m_weightedCenter.XmlAttrs.X = XL / L; m_weightedCenter.XmlAttrs.Y = YL / L; }
public void testWriteXML() { Sketch.Sketch sketch = new Sketch.Sketch(); sketch.XmlAttrs.Id = System.Guid.NewGuid(); Sketch.Shape shape = new Sketch.Shape(); shape.XmlAttrs.Id = System.Guid.NewGuid(); shape.XmlAttrs.Name = "shapeName"; shape.XmlAttrs.Type = "shape"; shape.XmlAttrs.Time = "111"; Sketch.Stroke stroke; Sketch.Substroke substroke; Sketch.Point point; ulong h; ulong i; ulong j; for (h = 0; h < 3; ++h) { stroke = new Sketch.Stroke(); stroke.XmlAttrs.Id = System.Guid.NewGuid(); stroke.XmlAttrs.Name = "strokeName"; stroke.XmlAttrs.Type = "stroke"; stroke.XmlAttrs.Time = h; for (i = 0; i < 5; ++i) { substroke = new Sketch.Substroke(); substroke.XmlAttrs.Id = System.Guid.NewGuid(); substroke.XmlAttrs.Name = "substrokeName"; substroke.XmlAttrs.Type = "substroke"; substroke.XmlAttrs.Time = i; for (j = 0; j < 10; ++j) { point = new Sketch.Point(); point.XmlAttrs.X = (float)random.NextDouble(); point.XmlAttrs.Y = (float)random.NextDouble(); point.XmlAttrs.Id = System.Guid.NewGuid(); point.XmlAttrs.Pressure = (ushort)(random.NextDouble() * 256); point.XmlAttrs.Name = "point" + j.ToString(); point.XmlAttrs.Time = j; substroke.AddPoint(point); } stroke.AddSubstroke(substroke); shape.AddSubstroke(substroke); } sketch.AddStroke(stroke); } sketch.AddShape(shape); sketch.Strokes[0].SplitStrokeAt(new int[] { 7, 14, 16, 21 }); ConverterXML.MakeXML xml = new ConverterXML.MakeXML(sketch); xml.WriteXML("test.xml"); }
/// <summary> /// finds the midpoint of a shape /// </summary> /// <param name="sh"></param> /// <returns></returns> public Sketch.Point shapeMidPoint(Sketch.Shape sh) { Sketch.Point p = new Sketch.Point(); p.XmlAttrs.X = (double)sh.XmlAttrs.X + (double)sh.XmlAttrs.Width / 2; p.XmlAttrs.Y = (double)sh.XmlAttrs.Y + (double)sh.XmlAttrs.Height / 2; return(p); }
/// <summary> /// Compute the bounding box center of these substrokes /// </summary> private void computeCenter() { float xCenter = (MaxX + MinX) / 2; float yCenter = (MaxY + MinY) / 2; m_center = new Sketch.Point(); m_center.XmlAttrs.X = xCenter; m_center.XmlAttrs.Y = yCenter; }
/// <summary> /// Resets all cached values to null /// </summary> private void setNull() { m_weightedCenter = null; m_center = null; m_maxWeightedCenter = null; m_maxCenter = null; m_minX = null; m_minY = null; m_maxX = null; m_maxY = null; }
/// <summary> /// Rotate the substrokes around their weighted center /// </summary> /// <param name="theta">The angle to rotate by (in radians)</param> public void rotate(double theta) { float x = WeightedCenter.X; float y = WeightedCenter.Y; int len = m_substrokes.Count; for (int i = 0; i < len; ++i) { m_substrokes[i].rotate(theta, x, y); } //Set null, but the center stays the same :) Sketch.Point tempCenter = m_weightedCenter; setNull(); m_weightedCenter = tempCenter; }
private static void WritePoint(Sketch.Point point, XmlTextWriter xmlDocument) { string[] pointAttributeNames = point.XmlAttrs.getAttributeNames(); object[] pointAttributeValues = point.XmlAttrs.getAttributeValues(); int length; int i; xmlDocument.WriteStartElement("point"); // Write all the attributes length = pointAttributeNames.Length; for (i = 0; i < length; ++i) { if (pointAttributeValues[i] != null) { xmlDocument.WriteAttributeString(pointAttributeNames[i], pointAttributeValues[i].ToString()); } } xmlDocument.WriteEndElement(); }
/// <summary> /// Checks whether there is an intersection between points a,b and c,d /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="c"></param> /// <param name="d"></param> /// <returns></returns> private bool intersects(Sketch.Point a, Sketch.Point b, Sketch.Point c, Sketch.Point d) { double m1 = (double)(b.Y - a.Y) / (double)(b.X - a.X); double b1 = (double)a.Y - (m1 * (double)a.X); double m2 = (double)(d.Y - c.Y) / (double)(d.X - c.X); double b2 = (double)c.Y - (m2 * (double)c.X); double x = (b2 - b1) / (m1 - m2); double y = m1 * x + b1; if (((a.X < x && b.X > x) || (a.X > x && b.X < x)) && ((c.X < x && d.X > x) || (c.X > x && d.X < x)) && ((a.Y < y && b.Y > y) || (a.Y > y && b.Y < y)) && ((c.Y < y && d.Y > y) || (c.Y > y && d.Y < y))) { return(true); } else { return(false); } }
/// <summary> /// Grabs the (x, y, time) data from the inkStroke /// </summary> /// <param name="inkStroke"></param> /// <returns></returns> static public Sketch.Point[] stripStroke(Microsoft.Ink.Stroke inkStroke) { ulong theTime; int strokeLength = inkStroke.PacketCount; ulong[] time = new ulong[strokeLength]; if (inkStroke.ExtendedProperties.DoesPropertyExist(Utilities.General.theTimeGuid)) { time = (ulong[])inkStroke.ExtendedProperties[Utilities.General.theTimeGuid].Data; if (time.Length > 0) { theTime = time[0]; } else { theTime = ((ulong)DateTime.Now.ToFileTime() - 116444736000000000) / 10000; for (int i = 0; i < strokeLength; i++) { // The multiplication by 1,000 is to convert from // seconds to milliseconds. // // Our time is in the form of milliseconds since Jan 1, 1970 // // NOTE: The timestamp for the stroke is made WHEN THE PEN IS LIFTED time[i] = theTime - (ulong)((1 / Utilities.General.SAMPLE_RATE * 1000) * (strokeLength - i)); } } } else { theTime = ((ulong)DateTime.Now.ToFileTime() - 116444736000000000) / 10000; for (int i = 0; i < strokeLength; i++) { // The multiplication by 1,000 is to convert from // seconds to milliseconds. // // Our time is in the form of milliseconds since Jan 1, 1970 // // NOTE: The timestamp for the stroke is made WHEN THE PEN IS LIFTED time[i] = theTime - (ulong)((1 / Utilities.General.SAMPLE_RATE * 1000) * (strokeLength - i)); } } bool includePressure = false; List <Guid> packetProperties = new List <Guid>(inkStroke.PacketDescription); if (packetProperties.Contains(Microsoft.Ink.PacketProperty.NormalPressure)) { includePressure = true; } int[] x = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.X); int[] y = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.Y); int[] pressure = new int[x.Length]; if (includePressure) { pressure = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.NormalPressure); } Sketch.Point[] points = new Sketch.Point[x.Length]; for (int i = 0; i < x.Length; i++) { if (includePressure) { points[i] = new Sketch.Point((float)x[i], (float)y[i], (float)pressure[i]); } else { points[i] = new Sketch.Point((float)x[i], (float)y[i]); } points[i].Time = time[i]; } return(points); }
/// <summary> /// Find the maximum distance between a point and the bounding box of these substrokes /// </summary> /// <param name="p">The point to compare</param> /// <returns>The max distance</returns> private float maxToPoint(Sketch.Point p) { return(Math.Max(Math.Max(p.X - MinX, MaxX - p.X), Math.Max(p.Y - MinY, MaxY - p.Y))); }
/// <summary> /// Takes an Ink.Stroke and outputs an internal representation that can /// then be output to an XML file /// </summary> /// <param name="inkStroke">Ink.Stroke which will have extracted from it the information necessary to store a Stroke in MIT XML.</param> /// <param name="transf">Transformation matrix to shift the stroke by</param> /// <param name="shift">Boolean for if we should shift by the transformation matrix</param> /// <returns>PointsAndShape object that stores the extracted information.</returns> public static Sketch.Stroke StripStrokeData(Microsoft.Ink.Stroke inkStroke, Matrix transf, bool shift) { int i; int length; // Get the timestamp for the function using an undocumented GUID (Microsoft.Ink.StrokeProperty.TimeID) to // get the time as a byte array, which we then convert to a long ulong theTime; if (inkStroke.ExtendedProperties[Microsoft.Ink.StrokeProperty.TimeID] != null) { byte[] timeBits = inkStroke.ExtendedProperties[Microsoft.Ink.StrokeProperty.TimeID].Data as byte[]; // Filetime format ulong fileTime = BitConverter.ToUInt64(timeBits, 0); // MIT time format theTime = (fileTime - 116444736000000000) / 10000; //string time = theTime.ToString(); } else { theTime = (ulong)System.DateTime.Now.Ticks; } // Grab X and Y int[] xData = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.X); int[] yData = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.Y); if (shift) { // Shift X and Y according to transformation matrix System.Drawing.Point[] pointData = new System.Drawing.Point[xData.Length]; length = xData.Length; for (i = 0; i < length; i++) { pointData[i] = new System.Drawing.Point(xData[i], yData[i]); } transf.TransformPoints(pointData); //Console.WriteLine("x: " + (pointData[0].X - xData[0]) + " y: " + (pointData[0].Y - yData[0])); for (i = 0; i < length; i++) { xData[i] = pointData[i].X; yData[i] = pointData[i].Y; } } Microsoft.Ink.DrawingAttributes drawingAttributes = inkStroke.DrawingAttributes; System.Drawing.Rectangle boundingBox = inkStroke.GetBoundingBox(); // Grab the color int color = drawingAttributes.Color.ToArgb(); // THIS IS DRAWING POINT (PENTIP) HEIGHT AND WIDTH... WE DONT HAVE ANYWHERE TO PUT IT... //string height = inkStroke.DrawingAttributes.Height.ToString(); //string width = inkStroke.DrawingAttributes.Width.ToString(); // Grab height and width of total stroke float height = boundingBox.Height; float width = boundingBox.Width; // Grab penTip string penTip = drawingAttributes.PenTip.ToString(); // Grab raster string raster = drawingAttributes.RasterOperation.ToString(); float x = Convert.ToSingle(boundingBox.X); float y = Convert.ToSingle(boundingBox.Y); //float leftx = Convert.ToSingle(boundingBox.Left); //float topy = Convert.ToSingle(boundingBox.Top); // If the pressure data is included take it, otherwise set to 255/2's int[] pressureData; if (IsPropertyIncluded(inkStroke, Microsoft.Ink.PacketProperty.NormalPressure)) { pressureData = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.NormalPressure); } else { pressureData = new int[xData.Length]; length = pressureData.Length; for (i = 0; i < length; ++i) { pressureData[i] = (255 - 0) / 2; } } // If the time data is included take it, otherwise set to the timestamp plus and increment ulong[] adjustedTime = new ulong[xData.Length]; int[] timerTick; if (IsPropertyIncluded(inkStroke, Microsoft.Ink.PacketProperty.TimerTick)) { timerTick = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.TimerTick); length = timerTick.Length; for (i = 0; i < length; i++) { // This may be incorrect, we never encountered this because Microsoft Journal doesn't save TimerTick data. // We know that the timestamp of a stroke is made when the pen is lifted. // Add the time of the stroke to each offset adjustedTime[i] = theTime + (ulong)timerTick[i] * 10000; } } else { timerTick = new int[xData.Length]; length = timerTick.Length; for (i = 0; i < length; i++) { // We believe this to be the standard sample rate. The multiplication by 1,000 is to convert from // seconds to milliseconds. // // Our time is in the form of milliseconds since Jan 1, 1970 // // NOTE: The timestamp for the stroke is made WHEN THE PEN IS LIFTED adjustedTime[i] = theTime - (ulong)((1 / SAMPLE_RATE * 1000) * (length - i)); } } // Create the array of ID's as new Guid's Guid[] idData = new Guid[xData.Length]; length = idData.Length; for (i = 0; i < length; i++) { idData[i] = Guid.NewGuid(); } // Create the internal representation Sketch.Stroke converterStroke = new Sketch.Stroke(); converterStroke.XmlAttrs.Id = System.Guid.NewGuid(); converterStroke.XmlAttrs.Name = "stroke"; converterStroke.XmlAttrs.Time = (ulong)theTime; converterStroke.XmlAttrs.Type = "stroke"; converterStroke.XmlAttrs.Source = "Converter"; Sketch.Substroke substroke = new Sketch.Substroke(); substroke.XmlAttrs.Id = System.Guid.NewGuid(); substroke.XmlAttrs.Name = "substroke"; substroke.XmlAttrs.Time = theTime; substroke.XmlAttrs.Type = "substroke"; substroke.XmlAttrs.Color = color; substroke.XmlAttrs.Height = height; substroke.XmlAttrs.Width = width; substroke.XmlAttrs.PenTip = penTip; substroke.XmlAttrs.Raster = raster; substroke.XmlAttrs.X = x; substroke.XmlAttrs.Y = y; //substroke.XmlAttrs.LeftX = leftx; //substroke.XmlAttrs.TopY = topy; substroke.XmlAttrs.Source = "ConverterJnt"; substroke.XmlAttrs.Start = idData[0]; substroke.XmlAttrs.End = idData[idData.Length - 1]; // Add all of the points to the stroke length = inkStroke.PacketCount; for (i = 0; i < length; i++) { Sketch.Point toAdd = new Sketch.Point(); toAdd.XmlAttrs.Name = "point"; toAdd.XmlAttrs.X = Convert.ToSingle(xData[i]); toAdd.XmlAttrs.Y = Convert.ToSingle(yData[i]); toAdd.XmlAttrs.Pressure = Convert.ToUInt16(pressureData[i]); toAdd.XmlAttrs.Time = Convert.ToUInt64(adjustedTime[i]); toAdd.XmlAttrs.Id = idData[i]; substroke.AddPoint(toAdd); } converterStroke.AddSubstroke(substroke); return(converterStroke); }