Пример #1
0
        /// <summary>
        /// Create the fragmentation points in the FragmentPanel
        /// </summary>
        public override void Execute()
        {
            foreach (KeyValuePair <Sketch.Stroke, List <int> > entry in ptsToAdd)
            {
                Sketch.Stroke stroke     = entry.Key;
                List <int>    newIndices = entry.Value;

                // Associate the split point we've found with our FeatureStroke
                if (!this.strokeToCorners.ContainsKey(stroke))
                {
                    this.strokeToCorners.Add(stroke, newIndices.GetRange(0, newIndices.Count));

                    DisplayFragmentPoints(stroke, newIndices);
                }
                else
                {
                    List <int> oldIndices = this.strokeToCorners[stroke];

                    foreach (int index in newIndices)
                    {
                        if (!oldIndices.Contains(index))
                        {
                            oldIndices.Add(index);
                            DisplayFragmentPoints(stroke, index);
                        }

                        // This Command currently only works with a UNIQUE set of pts in ptsToAdd
                        else
                        {
                            break;
                        }
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Undoes the current fragmentation within the FragmentPanel
        /// </summary>
        public override void UnExecute()
        {
            // Remove all of the fragment point references from the Hashtable
            foreach (KeyValuePair <Sketch.Stroke, List <int> > entry in this.ptsToAdd)
            {
                Sketch.Stroke stroke       = entry.Key;
                List <int>    addedIndices = entry.Value;
                List <int>    indices      = this.strokeToCorners[stroke];

                foreach (int index in addedIndices)
                {
                    indices.Remove(index);
                }
            }

            // Remove all the drawn strokes from the InkOverlay
            foreach (System.Drawing.Point coordinates in this.fragmentPtsDrawn)
            {
                foreach (Microsoft.Ink.Stroke fragPt in this.overlayInk.Ink.Strokes)
                {
                    if (fragPt.BezierPoints[0] == coordinates)
                    {
                        this.overlayInk.Ink.DeleteStroke(fragPt);
                        break;
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// When the user manually triggers recognition, label everything
        /// in the sketch as a wire.
        /// </summary>
        void Recognizer.recognize(Sketch.Sketch sketch, Sketch.Stroke[] selectedStrokes, bool userTriggered)
        {
            // Only operate on user triggered recognition events
            if (!userTriggered)
            {
                return;
            }

            lastLabeledSketchArgs = new RecognizerEventArgs();

            foreach (Sketch.Stroke selectedStroke in selectedStrokes)
            {
                if (selectedStroke == null)
                {
                    // The recognition triggerer left empty elements in
                    // the selected strokes array.  Here we just ignore
                    // the lack of a stroke.
                    continue;
                }


                // Get the corresponding stroke in the sketch to make sure we label
                // the right substrokes
                Sketch.Stroke sketchStroke = sketch.GetStroke((System.Guid)selectedStroke.XmlAttrs.Id);

                if (sketchStroke == null)
                {
                    // The selected stroke is not in the sketch.
                    // In some scenarios, we might want to throw an exception,
                    // but in this case we just skip the stroke
                    continue;
                }

                // Now label the substrokes
                Sketch.Substroke[] selectedSubstrokes = sketchStroke.Substrokes;
                foreach (Sketch.Substroke selectedSubstroke in selectedSubstrokes)
                {
                    if (selectedSubstroke.GetLabels().Length > 0)
                    {
                        continue;
                    }

                    // Apply wire label or error label using simulated error rate
                    if (randobj.NextDouble() < UIConstants.ErrorLabelErrorRate)
                    {
                        sketch.AddLabel(selectedSubstroke, UIConstants.ErrorLabel, 1.0);
                    }
                    else
                    {
                        sketch.AddLabel(selectedSubstroke, UIConstants.WireLabel, 1.0);
                    }
                }
            }

            lastLabeledSketchArgs.recognitionResults[0] = sketch;
            lastLabeledSketchArgs.eventTime             = DateTime.Now;
            lastLabeledSketchArgs.userTriggered         = true;

            RecognitionEvent(this, lastLabeledSketchArgs);
        }
Пример #4
0
 /// <summary>
 /// Adds an Ink Stroke and updates the Sketch.  NOTE: Does NOT check
 /// to ensure that the given Ink stroke is contained within the
 /// Ink object associated with this InkSketch.
 /// </summary>
 /// <param name="iStroke">The Ink Stroke to add</param>
 public void AddInkStroke(Microsoft.Ink.Stroke iStroke)
 {
     Sketch.Stroke sStroke = mReadJnt.InkStroke2SketchStroke(iStroke);
     ink2sketchStr.Add(iStroke.Id, sStroke.Substrokes[0].XmlAttrs.Id); // Converted stroke will always have
                                                                       // exactly one substroke.
     sketchStr2ink.Add(sStroke.Substrokes[0].XmlAttrs.Id, iStroke.Id);
     substrokeIdMap.Add(sStroke.Substrokes[0].XmlAttrs.Id, sStroke.Substrokes[0]);
     Sketch.AddStroke(sStroke);
     if (StrokeAdded != null)
     {
         StrokeAdded(sStroke);
     }
 }
Пример #5
0
        /// <summary>
        /// Transforms (e.g. moves or resizes) an Ink Stroke in the Sketch.
        /// Converts the given Ink Stroke into a Sketch stroke and then
        /// updates the Sketch to point to the new Ink Stroke instead of the old one.
        /// </summary>
        /// <param name="iStroke">The Ink Stroke to modify</param>
        public void TransformInkStroke(Microsoft.Ink.Stroke iStroke)
        {
            if (!ink2sketchStr.ContainsKey(iStroke.Id))
            {
                return;
            }

            if (!substrokeIdMap.ContainsKey(ink2sketchStr[iStroke.Id]))
            {
                return;
            }

            Sketch.Stroke newSStroke = mReadJnt.InkStroke2SketchStroke(iStroke);
            Substroke     oldSStroke = substrokeIdMap[ink2sketchStr[iStroke.Id]];

            // FIXME need to masquerade Substroke Ids.  Here
            // we abitrarily synchronize the Ids of the first
            // substroke in each stroke.  We do this because
            // ReadJnt will always return a stroke with one
            // substroke.  In some use cases (e.g. fragmenting),
            // matching Ids like this might cause problems.
            //
            // Eric Peterson: June 30, 2009: When loading an old
            // xml sketch, we need to preserve the time data for
            // each point.
            newSStroke.Substrokes[0].XmlAttrs.Id = oldSStroke.XmlAttrs.Id;
            for (int i = 0; i < oldSStroke.Points.Length; i++)
            {
                newSStroke.Substrokes[0].Points[i].Time = oldSStroke.Points[i].Time;
            }

            // Update mapping between strokes
            ink2sketchStr.Remove(iStroke.Id);
            ink2sketchStr.Add(iStroke.Id, newSStroke.Substrokes[0].XmlAttrs.Id);
            sketchStr2ink.Remove(oldSStroke.XmlAttrs.Id);
            sketchStr2ink.Add(newSStroke.Substrokes[0].XmlAttrs.Id, iStroke.Id);
            substrokeIdMap.Remove(newSStroke.Substrokes[0].XmlAttrs.Id);
            substrokeIdMap.Add(newSStroke.Substrokes[0].XmlAttrs.Id, newSStroke.Substrokes[0]);

            // Update pointers in Sketch
            Sketch.Substroke newSSubstroke = newSStroke.Substrokes[0];
            foreach (Sketch.Shape shape in oldSStroke.ParentShapes)
            {
                shape.AddSubstroke(newSSubstroke);
            }

            Sketch.RemoveSubstroke(oldSStroke);
            Sketch.AddStroke(newSStroke);
        }
Пример #6
0
        private void DisplayFragmentPoints(Sketch.Stroke stroke, int index)
        {
            Sketch.Point[] points = stroke.Points;

            System.Drawing.Point coordinates = new System.Drawing.Point((int)points[index].X,
                                                                        (int)points[index].Y);

            // Set the fragment point with drawing attributes
            Microsoft.Ink.Stroke fragPt = overlayInk.Ink.CreateStroke(new System.Drawing.Point[1] {
                coordinates
            });
            fragPt.DrawingAttributes = this.fragmentPtAttributes;

            this.fragmentPtsDrawn.Add(coordinates);
        }
Пример #7
0
        private void DisplayFragmentPoints(Sketch.Stroke stroke, List <int> indices)
        {
            Sketch.Point[] points = stroke.Points;

            foreach (int index in indices)
            {
                System.Drawing.Point pt = new System.Drawing.Point((int)points[index].X,
                                                                   (int)points[index].Y);

                // Set the fragment point with drawing attributes
                Microsoft.Ink.Stroke fragPt = this.overlayInk.Ink.CreateStroke(new System.Drawing.Point[1] {
                    pt
                });
                fragPt.DrawingAttributes = this.fragmentPtAttributes;
            }
        }
Пример #8
0
        /// <summary>
        /// Returns the time it took to draw the stroke
        /// </summary>
        /// <param name="stroke">The stroke</param>
        /// <returns>the total time it took to draw the stroke</returns>
        public ulong findStrokeTime(Sketch.Stroke stroke)
        {
            double minTime = Double.PositiveInfinity;
            double maxTime = Double.NegativeInfinity;

            Point[] points = stroke.Points;
            for (int i = 0; i < points.Length; i++)
            {
                if ((Double)(points[i].Time) < minTime)
                {
                    minTime = points[i].Time;
                }
                if ((Double)(points[i].Time) > maxTime)
                {
                    maxTime = (Double)(points[i].Time);
                }
            }
            return((ulong)(maxTime - minTime));
        }
Пример #9
0
        /// <summary>
        /// Adds a Stroke to our internal data structures - the Sketch and FeatureSketch
        /// </summary>
        /// Precondition: The InkStroke is not in the InkCanvas's collection of strokes.
        /// Postcondition: The InkStroke has been added to the InkCanvas, Sketch's list of
        /// Strokes, Substrokes, and FeatureSketch.
        /// <param name="inkStroke"></param>
        public void AddStroke(System.Windows.Ink.Stroke inkStroke)
        {
            if (mInkCanvas.Strokes.Contains(inkStroke))
            {
                throw new Exception("adding a stroke to the InkCanvasSketch, but it was already there!");
            }
            // Format the stroke
            inkStroke.AddPropertyData(dtGuid, (ulong)DateTime.Now.ToFileTime());
            string strokeId = Guid.NewGuid().ToString();

            inkStroke.AddPropertyData(idGuid, strokeId);

            // Update the dictionaries
            Sketch.Stroke sketchStroke = new Sketch.Stroke(inkStroke, dtGuid, SAMPLE_RATE);
            ink2sketchStr.Add(strokeId, sketchStroke.Substrokes[0].XmlAttrs.Id);
            sketchStr2ink.Add(sketchStroke.Substrokes[0].Id, strokeId);
            substrokeIdMap.Add(sketchStroke.Substrokes[0].Id, sketchStroke.Substrokes[0]);

            // Add it to the relevant data structures (InkCanvas last.)
            mFeatureSketch.AddStroke(sketchStroke);
            mInkCanvas.Strokes.Add(inkStroke);
        }
Пример #10
0
        /// <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.Contains(Microsoft.Ink.StrokeProperty.TimeID) &&
                (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;
                //theTime = ((ulong)System.DateTime.Now.Ticks - 116444736000000000) / 10000;
                theTime = ((ulong)DateTime.Now.ToFileTime() - 116444736000000000) / 10000;
            }

            // 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();
            float penWidth  = drawingAttributes.Width;
            float penHeight = drawingAttributes.Height;

            // 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
            // Not all pressure data is in the range of 0 - 255. Some tablets
            // register pressure in the range 0 - 1023, while others are 0 - 32768
            int[] pressureData;
            if (ReadJnt.IsPropertyIncluded(inkStroke, Microsoft.Ink.PacketProperty.NormalPressure))
            {
                pressureData = inkStroke.GetPacketValuesByProperty(Microsoft.Ink.PacketProperty.NormalPressure);
                int max = 0;
                foreach (int p in pressureData)
                {
                    max = Math.Max(max, p);
                }

                if (max > 1024) // Tablet reading in range 0 - 32767
                {
                    double     conversion = 255.0 / 32767.0;
                    List <int> temp       = new List <int>(pressureData.Length);
                    foreach (int p in pressureData)
                    {
                        temp.Add((int)(p * conversion));
                    }

                    pressureData = temp.ToArray();
                }
                else if (max > 255) // Tablet reading in range 0 - 1023
                {
                    double     conversion = 255.0 / 1023.0;
                    List <int> temp       = new List <int>(pressureData.Length);
                    foreach (int p in pressureData)
                    {
                        temp.Add((int)(p * conversion));
                    }

                    pressureData = temp.ToArray();
                }
            }
            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 (ReadJnt.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.Name   = "stroke";
            converterStroke.Time   = (ulong)theTime;
            converterStroke.Source = "Converter";


            // Add all of the points to the stroke

            length = inkStroke.PacketCount;
            List <Point> pointsToAdd = new List <Point>();

            for (i = 0; i < length; i++)
            {
                float currX = Convert.ToSingle(xData[i]);
                float currY = Convert.ToSingle(yData[i]);

                XmlStructs.XmlPointAttrs attrs = new XmlStructs.XmlPointAttrs(
                    currX, currY,
                    Convert.ToUInt16(pressureData[i]),
                    Convert.ToUInt64(adjustedTime[i]),
                    "point", idData[i]);

                Sketch.Point toAdd = new Sketch.Point(attrs);
            }


            //NOTE: X, Y, WIDTH, HEIGHT done later... boundingbox seems to be off
            Sketch.Substroke substroke = new Sketch.Substroke(pointsToAdd);
            substroke.Name      = "substroke";
            substroke.Color     = color;
            substroke.PenTip    = penTip;
            substroke.PenWidth  = penWidth;
            substroke.PenHeight = penHeight;
            substroke.Raster    = raster;
            substroke.Source    = "ConverterJnt";
            substroke.Start     = idData[0];
            substroke.End       = idData[idData.Length - 1];

            converterStroke.AddSubstroke(substroke);
            return(converterStroke);
        }
Пример #11
0
        /// <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>
        private 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
            long theTime;

            if (this.IsPropertyIncluded(inkStroke, Microsoft.Ink.StrokeProperty.TimeID))
            {
                byte[] timeBits = inkStroke.ExtendedProperties[Microsoft.Ink.StrokeProperty.TimeID].Data as byte[];
                long   fileTime = BitConverter.ToInt64(timeBits, 0);               //filetime format
                theTime = (fileTime - 116444736000000000) / 10000;                 //MIT time format
                // string time = theTime.ToString();
            }
            else
            {
                theTime = 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 (this.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
            long[] adjustedTime = new long[xData.Length];
            int[]  timerTick;
            if (this.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.
                    adjustedTime[i] = theTime + (long)timerTick[i] * 10000;                   //add the time of the stroke to each offset
                }
            }
            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 - (long)((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   = (ulong)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 = "Converter";
            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);
        }
Пример #12
0
        public void UpdateFragmentCorners(Dictionary <Sketch.Stroke, List <int> > fragStrokeToCorners)
        {
            // Clear the current InkOverlay
            overlayInk.Ink.DeleteStrokes();

            // Split the Stroke at the new fragment points
            foreach (KeyValuePair <Sketch.Stroke, List <int> > entry in fragStrokeToCorners)
            {
                Sketch.Stroke stroke  = entry.Key;
                List <int>    corners = entry.Value;

                bool       notEqualOrNull = false;
                List <int> sCorn;
                bool       haveCorners = this.lTool.StrokeToCorners.TryGetValue(stroke, out sCorn);
                if (haveCorners)
                {
                    notEqualOrNull = true;
                }
                else if (!haveCorners && corners != null && corners.Count > 0)
                {
                    notEqualOrNull = true;
                }
                else if (haveCorners && corners != null &&
                         corners.ToArray() != sCorn.ToArray())
                {
                    notEqualOrNull = true;
                }

                if (notEqualOrNull)
                {
                    if ((corners == null || corners.Count == 0) &&
                        sCorn.Count > 0)
                    {
                        this.lTool.StrokeToCorners.Remove(stroke);
                    }
                    else
                    {
                        this.lTool.StrokeToCorners[stroke] = corners;
                    }

                    //// Remove all of the substrokes within our InkPicture and hashtables
                    //foreach (Sketch.Substroke substroke in stroke.Substrokes)
                    //{
                    //    this.lTool.MIdToSubstroke.Remove(this.lTool.SubstrokeIdToMStroke[substroke.XmlAttrs.Id.Value].Id);
                    //    this.inkPic.Ink.DeleteStroke(this.lTool.SubstrokeIdToMStroke[substroke.XmlAttrs.Id.Value]);
                    //    this.lTool.SubstrokeIdToMStroke.Remove(substroke.XmlAttrs.Id.Value);
                    //}

                    // Merge the substrokes together
                    bool labelSame = stroke.MergeSubstrokes();
                    if (!labelSame)
                    {
                        System.Windows.Forms.DialogResult ok = System.Windows.Forms.MessageBox.Show(
                            "Labels removed from Stroke " + stroke.XmlAttrs.Id.ToString() +
                            "\ndue to fragmenting a non-uniformly labeled stroke",
                            "Important",
                            System.Windows.Forms.MessageBoxButtons.OK,
                            System.Windows.Forms.MessageBoxIcon.Exclamation);
                    }

                    // Fragment the substroke at the specified indices
                    if (corners != null && corners.Count > 0)
                    {
                        stroke.SplitStrokeAt(corners.ToArray());
                    }

                    // Draw the substrokes in the InkPicture
                    foreach (Sketch.Substroke substroke in stroke.Substrokes)
                    {
                        Sketch.Point[]         substrokePts = substroke.Points;
                        System.Drawing.Point[] pts          = new System.Drawing.Point[substrokePts.Length];

                        int len2 = pts.Length;
                        for (int i = 0; i < len2; ++i)
                        {
                            pts[i] = new System.Drawing.Point((int)(substrokePts[i].X),
                                                              (int)(substrokePts[i].Y));
                        }

                        this.inkPic.Ink.CreateStroke(pts);

                        // Allows us to look up a Sketch.Stroke from its Microsoft counterpart
                        int mId = this.inkPic.Ink.Strokes[this.inkPic.Ink.Strokes.Count - 1].Id;
                    }

                    // Update the colors associated with the substrokes
                    UpdateColors(new List <Substroke>(stroke.Substrokes));
                }
            }

            // Add the InkOverlay points we'll be drawing
            List <System.Drawing.Point> ptsToDraw = new List <System.Drawing.Point>();

            Sketch.Stroke[] strokes = this.Sketch.Strokes;
            foreach (Sketch.Stroke stroke in strokes)
            {
                List <int> corners;
                if (this.lTool.StrokeToCorners.TryGetValue(stroke, out corners))
                {
                    Sketch.Point[] points = stroke.Points;

                    foreach (int index in corners)
                    {
                        ptsToDraw.Add(new System.Drawing.Point((int)points[index].X, (int)points[index].Y));
                    }
                }
            }

            System.Drawing.Point[] fragPts = ptsToDraw.ToArray();

            // Create strokes consisting of one point each.
            // This way we can draw the points in our InkPicture and correctly scale the points
            // accordingly.
            foreach (System.Drawing.Point pt in fragPts)
            {
                System.Drawing.Point[] p = new System.Drawing.Point[1];
                p[0] = pt;

                overlayInk.Ink.CreateStroke(p);
            }

            // Render each point
            foreach (Microsoft.Ink.Stroke s in overlayInk.Ink.Strokes)
            {
                s.DrawingAttributes = this.fragmentPtAttributes;
            }

            // Update the Hashtable
            foreach (KeyValuePair <Sketch.Stroke, List <int> > entry in fragStrokeToCorners)
            {
                Sketch.Stroke key = entry.Key;
                List <int>    val = entry.Value;

                if (val == null || val.Count == 0)
                {
                    this.lTool.StrokeToCorners.Remove(key);
                }
                else
                {
                    this.lTool.StrokeToCorners[key] = new List <int>(val);
                }
            }

            this.inkPic.Invalidate();
            this.inkPic.Refresh();
        }
Пример #13
0
        /// <summary>
        /// Fragment the loaded Stroke at the intersections created by the drawn
        /// Microsoft.Ink.Stroke.
        /// </summary>
        /// <param name="sender">Reference to the object that raised the event</param>
        /// <param name="e">Passes an object specific to the event that is being handled</param>
        private void sketchInk_Stroke(object sender, InkCollectorStrokeEventArgs e)
        {
            // Find the float intersection points
            float[] intersections             = e.Stroke.FindIntersections(sketchInk.Ink.Strokes);
            System.Drawing.Point[] pointInter = new System.Drawing.Point[intersections.Length];

            // Find the actual points of intersection
            for (int i = 0; i < pointInter.Length; ++i)
            {
                pointInter[i] = LocatePoint(e.Stroke, intersections[i]);
            }

            // Remove our drawing stroke from the Ink
            this.sketchInk.Ink.DeleteStroke(e.Stroke);

            // Threshold for how far away we can draw from the actual stroke
            const double DISTTHRESHOLD = 40.0;

            // Hashtable mapping new points to FeatureStrokes
            Dictionary <Sketch.Stroke, List <int> > ptsToAdd = new Dictionary <Sketch.Stroke, List <int> >();

            // For each point in our intersections we'll find the closest point in
            // the corresponding FeatureStroke points
            foreach (System.Drawing.Point currPt in pointInter)
            {
                int           bestPointIndex = 0;
                double        bestDist       = Double.PositiveInfinity;
                Sketch.Stroke bestStroke     = null;

                // Check all of the FeatureStrokes to see if the Point is close enough
                foreach (Sketch.Stroke stroke in this.strokes)
                {
                    Sketch.Point[] pts = stroke.Points;

                    // Find the closest point for this FeatureStroke
                    for (int i = 0; i < pts.Length; i++)
                    {
                        double currDist = Euclidean(currPt.X, currPt.Y, pts[i].X, pts[i].Y);

                        if (currDist < bestDist)
                        {
                            bestDist       = currDist;
                            bestPointIndex = i;
                            bestStroke     = stroke;
                        }
                    }
                }

                // If it's close enough, add it to our temporary Hashtable to keep track of
                // which point corresponds to which FeatureStroke
                if (bestDist < DISTTHRESHOLD)
                {
                    bool alreadyExists = false;
                    if (this.strokeToCorners.ContainsKey(bestStroke))
                    {
                        List <int> existingPts = this.strokeToCorners[bestStroke];

                        if (existingPts.Contains(bestPointIndex))
                        {
                            alreadyExists = true;
                        }
                    }

                    if (!alreadyExists)
                    {
                        if (!ptsToAdd.ContainsKey(bestStroke))
                        {
                            List <int> newPts = new List <int>();
                            newPts.Add(bestPointIndex);
                            ptsToAdd.Add(bestStroke, newPts);
                        }
                        else
                        {
                            List <int> existingPts = ptsToAdd[bestStroke];

                            if (!existingPts.Contains(bestPointIndex))
                            {
                                existingPts.Add(bestPointIndex);
                            }
                        }
                    }
                }
            }

            if (ptsToAdd.Count > 0)
            {
                // Hand-fragment the stroke
                CM.ExecuteCommand(new CommandList.HandFragmentCornersCmd(ptsToAdd,
                                                                         this.strokeToCorners, this.overlayInk, this.fragmentPtAttributes));
            }

            sketchInk.Refresh();
        }
Пример #14
0
        /// <summary>
        /// Creates a copy of the stroke
        /// </summary>
        /// <returns></returns>
        public Stroke Clone()
        {
            Stroke clone = new Stroke(this.CloneSubstrokes(), this.XmlAttrs.Clone());

            return(clone);
        }