public static List <SketchStroke> Translate(List <SketchStroke> strokes, SketchPoint origin, SketchPoint centroid)
        {
            List <SketchStroke> newStrokes = new List <SketchStroke>();

            foreach (SketchStroke stroke in strokes)
            {
                List <SketchPoint> newPoints = new List <SketchPoint>();
                foreach (SketchPoint point in stroke.Points)
                {
                    newPoints.Add(new SketchPoint(point.X + origin.X - centroid.X, point.Y + origin.Y - centroid.Y));
                }
                SketchStroke newStroke = new SketchStroke(newPoints, stroke.TimeStamp);
                newStrokes.Add(newStroke);
            }

            return(newStrokes);
        }
Пример #2
0
        public BoundingBox(SketchStroke stroke)
        {
            MinX = double.MaxValue;
            MinY = double.MaxValue;
            MaxX = double.MinValue;
            MaxY = double.MinValue;

            foreach (SketchPoint point in stroke.Points)
            {
                MinX = MinX < point.X ? MinX : point.X;
                MinY = MinY < point.Y ? MinY : point.Y;
                MaxX = MaxX > point.X ? MaxX : point.X;
                MaxY = MaxY > point.Y ? MaxY : point.Y;
            }

            CenterX = (MinX + MaxX) / 2.0;
            CenterY = (MinY + MaxY) / 2.0;
        }
Пример #3
0
        public static string IntersectionRelationship(SketchStroke sketchStroke1, SketchStroke sketchStroke2)
        {
            SketchPoint closestPoint = Intersection(sketchStroke1, sketchStroke2);

            if (closestPoint == null)
            {
                return("none");
            }
            if (MathHelpers.EuclideanDistance(closestPoint, sketchStroke1.StartPoint) < 40)
            {
                return("touch head");
            }
            if (MathHelpers.EuclideanDistance(closestPoint, sketchStroke1.EndPoint) < 40)
            {
                return("touch tail");
            }
            return("cross");
        }
        public static List <SketchStroke> ScaleSquare(List <SketchStroke> strokes, double size)
        {
            double width  = SketchFeatureExtraction.Width(strokes);
            double height = SketchFeatureExtraction.Height(strokes);

            List <SketchStroke> newStrokes = new List <SketchStroke>();

            foreach (SketchStroke stroke in strokes)
            {
                List <SketchPoint> newPoints = new List <SketchPoint>();
                foreach (SketchPoint point in stroke.Points)
                {
                    newPoints.Add(new SketchPoint(point.X * size / width, point.Y * size / height));
                }
                SketchStroke newStroke = new SketchStroke(newPoints, stroke.TimeStamp);
                newStrokes.Add(newStroke);
            }

            return(newStrokes);
        }
        public static string[,] IntersectionMatrix(List <SketchStroke> strokes, int[] correspondance, HashSet <int> wrongDirectionStrokeIndices)
        {
            List <SketchStroke> restored = new List <SketchStroke>();

            for (int i = 0; i < correspondance.Length; i++)
            {
                int strokeIndex = Array.IndexOf(correspondance, i);

                if (wrongDirectionStrokeIndices.Contains(strokeIndex))
                {
                    restored.Add(SketchStroke.Reverse(strokes[strokeIndex]));
                }
                else
                {
                    restored.Add(strokes[strokeIndex]);
                }
            }

            return(IntersectionMatrix(restored));
        }
Пример #6
0
        public static double StartToEndSlope(SketchStroke stroke)
        {
            SketchPoint start = stroke.StartPoint;
            SketchPoint end   = stroke.EndPoint;

            if (start.X == end.X)
            {
                if (end.Y >= start.Y)
                {
                    return(double.PositiveInfinity);
                }
                else
                {
                    return(double.NegativeInfinity);
                }
            }
            else
            {
                return((end.Y - start.Y) / (end.X - start.X));
            }
        }
Пример #7
0
        private void StrokeInput_StrokesCollected(InkPresenter sender, InkStrokesCollectedEventArgs args)
        {
            if (this.IsSkritter == true)
            {
                var          strokes    = this.WritingInkCanvas.InkPresenter.StrokeContainer.GetStrokes();
                SketchStroke lastStroke = new SketchStroke(strokes[strokes.Count - 1], this.timeCollection[this.timeCollection.Count - 1]);

                if (SkritterHelpers.ValidateStroke(lastStroke, this.currentTemplateSketchStrokes[this.sketchStrokes.Count]) == true)
                {
                    this.sketchStrokes.Add(lastStroke);
                    InteractionTools.ShowStroke(this.AnimationCanvas, this.currentTemplateSketchStrokes[this.sketchStrokes.Count - 1]);
                }
                else
                {
                    this.timeCollection.RemoveAt(this.timeCollection.Count - 1);
                }

                strokes[strokes.Count - 1].Selected = true;
                this.WritingInkCanvas.InkPresenter.StrokeContainer.DeleteSelected();
            }
        }
        /// <summary>
        /// one sample stroke contains many template strokes
        /// </summary>
        /// <param name="sample"></param>
        /// <param name="template"></param>
        /// <returns>stroke index -> list of template indices it contains</returns>
        public static List <List <int> > StrokeToStrokeCorrespondenceConcatenating(List <SketchStroke> sample, List <SketchStroke> template)
        {
            List <List <int> > result = new List <List <int> >();

            List <KeyValuePair <SketchStroke, int> > templateStrokeToIndex = new List <KeyValuePair <SketchStroke, int> >();

            for (int i = 0; i < template.Count; i++)
            {
                templateStrokeToIndex.Add(new KeyValuePair <SketchStroke, int>(template[i], i));
            }

            foreach (SketchStroke sampleStroke in sample)
            {
                templateStrokeToIndex.Sort((t1, t2) => SketchTools.DirectedHausdorffDistance(t1.Key.Points, sampleStroke.Points).CompareTo(SketchTools.DirectedHausdorffDistance(t2.Key.Points, sampleStroke.Points)));

                double       currHausdorffFromSampleToTemplateList = double.MaxValue;
                SketchStroke currConcatenated = new SketchStroke();
                List <int>   currListIndices  = new List <int>();
                foreach (KeyValuePair <SketchStroke, int> pair in templateStrokeToIndex)
                {
                    SketchStroke newConcatenated = SketchStroke.ConcatenateStrokes(pair.Key, currConcatenated);
                    double       newDistance     = SketchTools.HausdorffDistance(sampleStroke, newConcatenated);
                    if (newDistance < currHausdorffFromSampleToTemplateList)
                    {
                        currHausdorffFromSampleToTemplateList = newDistance;
                        currConcatenated = newConcatenated;
                        currListIndices.Add(pair.Value);
                    }
                }

                result.Add(currListIndices);

                foreach (int currIndex in currListIndices)
                {
                    templateStrokeToIndex.Remove(new KeyValuePair <SketchStroke, int>(template[currIndex], currIndex));
                }
            }

            return(result);
        }
Пример #9
0
        public static async Task <Sketch> XMLToSketch(StorageFile file)
        {
            string text = await FileIO.ReadTextAsync(file);

            XDocument document = XDocument.Parse(text);

            int    minX  = Int32.Parse(document.Root.Attribute("frameMinX").Value);
            int    maxX  = Int32.Parse(document.Root.Attribute("frameMaxX").Value);
            int    minY  = Int32.Parse(document.Root.Attribute("frameMinY").Value);
            int    maxY  = Int32.Parse(document.Root.Attribute("frameMaxY").Value);
            string label = document.Root.Attribute("label").Value;
            List <SketchStroke> strokes = new List <SketchStroke>();

            // Itereates through each stroke element
            foreach (XElement element in document.Root.Elements())
            {
                // Initializes the stroke
                SketchStroke stroke = new SketchStroke();

                // Iterates through each point element
                double x, y;
                long   t;

                foreach (XElement pointElement in element.Elements())
                {
                    x = Double.Parse(pointElement.Attribute("x").Value);
                    y = Double.Parse(pointElement.Attribute("y").Value);
                    t = Int64.Parse(pointElement.Attribute("time").Value);

                    SketchPoint point = new SketchPoint(x, y);

                    stroke.AppendPoint(point);
                    stroke.AppendTime(t);
                }

                strokes.Add(stroke);
            }

            return(new Sketch(minX, maxX, minY, maxY, label, strokes));
        }
Пример #10
0
 public static List <SketchPoint> FindCorners(SketchStroke stroke)
 {
     return(ShortStraw.FindCorners(stroke));
 }
Пример #11
0
 public static double PathLength(SketchStroke stroke)
 {
     return(PathLength(stroke, 0, stroke.Points.Count - 1));
 }
 public static bool ValidateStroke(SketchStroke sampleStroke, SketchStroke templateStroke)
 {
     return(SketchTools.HausdorffDistance(sampleStroke, templateStroke) < SkritterHelpers.StrokeValidationDistanceThreshold);
 }
Пример #13
0
 public static SketchStroke Substroke(SketchStroke stroke, int start, int end)
 {
     return new SketchStroke(stroke.Points.GetRange(start, end - start + 1), stroke.TimeStamp.GetRange(start, end - start + 1));
 }
        /// <summary>
        /// one to one, one to many, or many to one, result is from template to sample strokes
        /// </summary>
        /// <param name="sample"></param>
        /// <param name="template"></param>
        /// <returns></returns>
        public static List <List <int>[]> StrokeToStrokeCorrespondenceDifferentCountStartFromSample(List <SketchStroke> sample, List <SketchStroke> template)
        {
            List <List <int>[]> result              = new List <List <int>[]>();
            HashSet <int>       usedSampleIndices   = new HashSet <int>();
            HashSet <int>       usedTemplateIndices = new HashSet <int>();

            List <SketchStroke> sampleNormalized   = SketchPreprocessing.Normalize(sample, 128, 500, new SketchPoint(0.0, 0.0));
            List <SketchStroke> templateNormalized = SketchPreprocessing.Normalize(template, 128, 500, new SketchPoint(0.0, 0.0));

            int si = 0;

            while (si < sample.Count && usedTemplateIndices.Count < template.Count)
            {
                Debug.WriteLine("si = " + si);

                if (usedSampleIndices.Contains(si))
                {
                    si++;
                    continue;
                }

                double oneToOneDis = double.MaxValue;
                int    matchedIdx  = -1;
                for (int ti = 0; ti < template.Count; ti++)
                {
                    if (usedTemplateIndices.Contains(ti))
                    {
                        continue;
                    }

                    double dis = SketchTools.HausdorffDistance(sampleNormalized[si], templateNormalized[ti]);

                    if (dis < oneToOneDis)
                    {
                        oneToOneDis = dis;
                        matchedIdx  = ti;
                    }
                }

                usedSampleIndices.Add(si);
                usedTemplateIndices.Add(matchedIdx);

                List <int> oneToManyIndices = new List <int>();
                oneToManyIndices.Add(matchedIdx);
                List <int> manyToOneIndices = new List <int>();
                manyToOneIndices.Add(si);

                SketchStroke currSampleStroke = sampleNormalized[si];
                double       oneToManyDis     = oneToOneDis;

                int preSample  = si - 1;
                int postSample = si + 1;
                while (preSample >= 0)
                {
                    if (usedSampleIndices.Contains(preSample))
                    {
                        break;
                    }

                    SketchStroke concatenatedStroke = SketchStroke.ConcatenateStrokes(sampleNormalized[preSample], currSampleStroke);
                    double       dis = SketchTools.HausdorffDistance(concatenatedStroke, templateNormalized[matchedIdx]);

                    if (dis < oneToManyDis)
                    {
                        oneToManyDis = dis;
                        oneToManyIndices.Insert(0, preSample);
                        currSampleStroke = concatenatedStroke;
                    }
                    else
                    {
                        break;
                    }

                    preSample--;
                }
                while (postSample < sample.Count)
                {
                    if (usedSampleIndices.Contains(postSample))
                    {
                        break;
                    }

                    SketchStroke concatenatedStroke = SketchStroke.ConcatenateStrokes(currSampleStroke, sampleNormalized[postSample]);
                    double       dis = SketchTools.HausdorffDistance(concatenatedStroke, templateNormalized[matchedIdx]);

                    if (dis < oneToManyDis)
                    {
                        oneToManyDis = dis;
                        oneToManyIndices.Add(postSample);
                        currSampleStroke = concatenatedStroke;
                    }
                    else
                    {
                        break;
                    }

                    postSample++;
                }

                SketchStroke currTemplateStroke = templateNormalized[matchedIdx];
                double       manyToOneDis       = oneToOneDis;

                int preTemplate  = matchedIdx - 1;
                int postTemplate = matchedIdx + 1;
                while (preTemplate >= 0)
                {
                    if (usedTemplateIndices.Contains(preTemplate))
                    {
                        break;
                    }

                    SketchStroke concatenatedStroke = SketchStroke.ConcatenateStrokes(templateNormalized[preTemplate], currTemplateStroke);
                    double       dis = SketchTools.HausdorffDistance(concatenatedStroke, sampleNormalized[si]);

                    if (dis < manyToOneDis)
                    {
                        manyToOneDis = dis;
                        manyToOneIndices.Insert(0, preTemplate);
                        currTemplateStroke = concatenatedStroke;
                    }
                    else
                    {
                        break;
                    }

                    preTemplate--;
                }
                while (postTemplate < template.Count)
                {
                    if (usedTemplateIndices.Contains(postTemplate))
                    {
                        break;
                    }

                    SketchStroke concatenatedStroke = SketchStroke.ConcatenateStrokes(currTemplateStroke, templateNormalized[postTemplate]);
                    double       dis = SketchTools.HausdorffDistance(concatenatedStroke, sampleNormalized[si]);

                    if (dis < manyToOneDis)
                    {
                        manyToOneDis = dis;
                        manyToOneIndices.Add(postTemplate);
                        currTemplateStroke = concatenatedStroke;
                    }
                    else
                    {
                        break;
                    }

                    postTemplate++;
                }

                Debug.WriteLine("matched index = " + matchedIdx);

                int flag = -2; // -1 for oneToMany, 0 for oneToOne, 1 for manyToOne
                if (oneToManyDis < oneToOneDis && manyToOneDis < oneToOneDis)
                {
                    if (oneToManyDis < manyToOneDis)
                    {
                        flag = -1;
                    }
                    else
                    {
                        flag = 1;
                    }
                }
                else if (oneToManyDis < oneToOneDis)
                {
                    flag = -1;
                }
                else if (manyToOneDis < oneToOneDis)
                {
                    flag = 1;
                }
                else
                {
                    flag = 0;
                }

                if (flag == 0)
                {
                    List <int> oneTemplate = new List <int>();
                    List <int> oneSample   = new List <int>();
                    oneTemplate.Add(matchedIdx);
                    oneSample.Add(si);
                    result.Add(new List <int>[] { oneTemplate, oneSample });
                    usedTemplateIndices.Add(matchedIdx);
                    usedSampleIndices.Add(matchedIdx);
                    si++;
                }
                else if (flag == -1) // one to many
                {
                    List <int> one  = new List <int>();
                    List <int> many = new List <int>();
                    one.Add(matchedIdx);
                    usedTemplateIndices.Add(matchedIdx);
                    foreach (int index in oneToManyIndices)
                    {
                        usedSampleIndices.Add(index);
                        many.Add(index);
                    }
                    result.Add(new List <int>[] { one, many });
                    si = many[many.Count - 1] + 1;
                }
                else if (flag == 1) // many to one
                {
                    List <int> many = new List <int>();
                    List <int> one  = new List <int>();
                    foreach (int index in manyToOneIndices)
                    {
                        usedTemplateIndices.Add(index);
                        many.Add(index);
                    }
                    one.Add(si);
                    result.Add(new List <int>[] { many, one });
                    usedSampleIndices.Add(matchedIdx);
                    si++;
                }
            }

            return(result);
        }
        public static List <SketchStroke> Resample(List <SketchStroke> strokes, int n)
        {
            double totalLength = 0;

            foreach (SketchStroke stroke in strokes)
            {
                totalLength += SketchStrokeFeatureExtraction.PathLength(stroke);
            }

            double I = totalLength / (n - 1);
            double D = 0.0;

            List <SketchStroke> newStrokes = new List <SketchStroke>();

            // Iterates through each stroke points in a list of strokes
            int pointCount = 0;

            foreach (SketchStroke stroke in strokes)
            {
                //Resamples point locations
                List <SketchPoint> points    = stroke.Points;
                List <SketchPoint> newPoints = new List <SketchPoint>();

                newPoints.Add(new SketchPoint(points[0].X, points[0].Y));
                ++pointCount;

                bool isDone = false;

                for (int i = 1; i < points.Count; ++i)
                {
                    double d = MathHelpers.EuclideanDistance(points[i - 1], points[i]);

                    if (D + d >= I)
                    {
                        double qx = points[i - 1].X + ((I - D) / d) * (points[i].X - points[i - 1].X);
                        double qy = points[i - 1].Y + ((I - D) / d) * (points[i].Y - points[i - 1].Y);

                        if (pointCount < n - 1)
                        {
                            newPoints.Add(new SketchPoint(qx, qy));
                            ++pointCount;

                            points.Insert(i, new SketchPoint(qx, qy));
                            D = 0.0;
                        }
                        else
                        {
                            isDone = true;
                        }
                    }
                    else
                    {
                        D += d;
                    }

                    if (isDone)
                    {
                        break;
                    }
                }

                D = 0.0;

                // Resamples time stamps
                List <long> timeStamp    = stroke.TimeStamp;
                List <long> newTimeStamp = new List <long>();

                int oldCount = timeStamp.Count;
                int newCount = newPoints.Count;

                for (int j = 0; j < newCount; ++j)
                {
                    int index = (int)((double)j / newCount * oldCount);
                    newTimeStamp.Add(timeStamp[index]);
                }

                SketchStroke newStroke = new SketchStroke(newPoints, newTimeStamp);

                newStrokes.Add(newStroke);
            }

            return(newStrokes);
        }
Пример #16
0
 public static double HausdorffDistance(SketchStroke strokeA, SketchStroke strokeB)
 {
     return(SketchTools.HausdorffDistance(strokeA.Points, strokeB.Points));
 }
Пример #17
0
 private static bool IsLine(SketchStroke stroke)
 {
     return(IsLine(stroke, 0, stroke.Points.Count - 1));
 }