/// <summary>
        /// Calculate the similarity in length of two Lines.
        /// </summary>
        /// <param name="line0">The first line.</param>
        /// <param name="line1">The second line.</param>
        /// <returns>How similar the lines are in length.</returns>
        private static double CalculateLengthSimilarity(InternalLine line0, InternalLine line1)
        {
            double len0 = line0.GetLength(); double len1 = line1.GetLength();
            var    dif = Math.Abs(len1 - len0);

            if (dif == 0)
            {
                return(1);
            }
            double shorter;

            if (len1 > len0)
            {
                shorter = len0;
            }
            else
            {
                shorter = len1;
            }
            if (dif >= shorter)
            {
                return(0);
            }
            return((shorter - dif) / shorter);
        }
Exemple #2
0
 /// <summary>
 /// Adds a point to the right canvas
 /// </summary>
 /// <param name="newPoint">The point</param>
 public void AddNewPointRight(Ellipse newPoint, InternalLine line)
 {
     newPoint.Height = 3; newPoint.Width = 3;
     newPoint.Fill   = Brushes.Black;
     RightCanvas.Children.Add(newPoint);
     newPoint.Margin = new Thickness(line.point.X - 1.5, line.point.Y - 1.5, 0, 0);
 }
 /// <summary>
 /// Finish the current Line, when the pressed Mouse is released.
 /// Overload that is used to pass a list of points to be used when one is available.
 /// </summary>
 /// <param name="p">The list of points</param>
 public void FinishCurrentLine(List <Point> p)
 {
     mouseDown = false;
     if (inDrawingMode && currentLine.Count > 0)
     {
         InternalLine newLine = new InternalLine(p, rightLineList.Count);
         rightLineList.Add(new Tuple <bool, InternalLine>(true, newLine));
         newLine.PopulateMatrixes(isFilledMatrix, linesMatrix);
         programPresenter.PassLastActionTaken(historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Draw, newLine.GetID())));
         programPresenter.UpdateRightLines(rightLineList);
         currentLine.Clear();
     }
     UpdateUI();
 }
        /// <summary>
        /// Calculate the average distance between the ends of two lines.
        /// </summary>
        /// <param name="line0">The first line.</param>
        /// <param name="line1">The second line.</param>
        /// <returns>The shortest average distance between the ends of the lines.</returns>
        private static double CalculateAverageDistance(InternalLine line0, InternalLine line1)
        {
            List <Point> points0        = line0.GetPoints();
            List <Point> points1        = line1.GetPoints();
            double       distfirstfirst = Math.Sqrt(Math.Pow((points0[0].X - points1[0].X), 2) + Math.Pow((points0[0].Y - points1[0].Y), 2));
            double       distlastlast   = Math.Sqrt(Math.Pow((points0.Last().X - points1.Last().X), 2) + Math.Pow((points0.Last().Y - points1.Last().Y), 2));
            double       distfirstlast  = Math.Sqrt(Math.Pow((points0[0].X - points1.Last().X), 2) + Math.Pow((points0[0].Y - points1.Last().Y), 2));
            double       distlastfirst  = Math.Sqrt(Math.Pow((points0.Last().X - points1[0].X), 2) + Math.Pow((points0.Last().Y - points1[0].Y), 2));

            if ((distfirstfirst + distlastlast) / 2 < (distfirstlast + distlastfirst) / 2)
            {
                return((distfirstfirst + distlastlast) / 2);
            }
            else
            {
                return((distfirstlast + distlastfirst) / 2);
            }
        }
        /// <summary>
        /// Calculate the approximate similarity of two lines.
        /// Using three weighted parameters to calculate a value between 0 and 1 to indicate the similarity of the lines.
        /// </summary>
        /// <param name="line0">The first line.</param>
        /// <param name="line1">The second line.</param>
        /// <returns>The similarity of the two lines.</returns>
        public static double CalculateSimilarity(InternalLine line0, InternalLine line1)
        {
            double CosSim  = Math.Abs(CalculateAverageCosineSimilarity(line0, line1));
            double LenSim  = CalculateLengthSimilarity(line0, line1);
            double AvDist  = CalculateAverageDistance(line0, line1);
            double DistSim = (50 - AvDist) / 50;

            if (DistSim < 0)
            {
                DistSim = 0;
            }
            if (CosSim < 0.5 || Double.IsNaN(CosSim))
            {
                CosSim = 0;
            }
            double output = (2 * CosSim + LenSim + DistSim) / 4;

            System.Diagnostics.Debug.WriteLine("Results: CosSim: {0}, LenSim: {1}, AvDist {2}, DistSim: {3}. Total: {4}",
                                               CosSim, LenSim, AvDist, DistSim, output);
            return(output);
        }
 /// <summary>
 /// Finish the current Line, when the pressed Mouse is released.
 /// </summary>
 /// <param name="valid">Whether the up event is valid or not</param>
 public void FinishCurrentLine(bool valid)
 {
     mouseDown = false;
     if (valid)
     {
         if (inDrawingMode && currentLine.Count > 0)
         {
             InternalLine newLine = new InternalLine(currentLine, rightLineList.Count);
             rightLineList.Add(new Tuple <bool, InternalLine>(true, newLine));
             newLine.PopulateMatrixes(isFilledMatrix, linesMatrix);
             programPresenter.PassLastActionTaken(historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Draw, newLine.GetID())));
             //TODO: For the person implementing overlay: Add check if overlay needs to be added
             programPresenter.UpdateRightLines(rightLineList);
             currentLine.Clear();
             programPresenter.UpdateCurrentLine(currentLine);
         }
     }
     else
     {
         currentLine.Clear();
     }
     UpdateUI();
 }
        /// <summary>
        /// An approximate calculation of the average cosine similarity
        /// of two lines, achieved by calculating the cosine similarity of subvectors.
        /// </summary>
        /// <param name="line0">The first line</param>
        /// <param name="line1">The second line</param>
        /// <returns>The approximate average cosine similarity of all subvectors</returns>
        public static double CalculateAverageCosineSimilarity(InternalLine line0, InternalLine line1)
        {
            //check if one of the lines is a point, or both lines are points
            if ((line0.isPoint && !line1.isPoint) || (line1.isPoint && !line0.isPoint))
            {
                return(0);
            }
            else if (line0.isPoint && line1.isPoint)
            {
                return(1);
            }

            List <Point> points0 = line0.GetPoints();
            List <Point> points1 = line1.GetPoints();

            if (points0.Count == points1.Count)
            {
                //If the two lists have an equal amount of subvectors,
                //compare the nth subvectors from each list and average the value.
                double       sum = 0; int i = 0;
                List <Point> shortL = points0; List <Point> longL = points1;
                for (; i < shortL.Count - 1; i++)
                {
                    if (i + 1 == shortL.Count || i + 1 == longL.Count)
                    {
                        break;
                    }
                    Vector v0 = new Vector(shortL[i + 1].X - shortL[i].X, shortL[i + 1].Y - shortL[i].Y);
                    Vector v1 = new Vector(longL[i + 1].X - longL[i].X, longL[i + 1].Y - longL[i].Y);
                    sum += CosineSimilarity(v0, v1);
                }
                return(sum / i);
            }
            else
            {
                //Determine if the longer list is of similar length or contains significatly more items
                List <Point> shortL = points0; List <Point> longL = points0;
                if (points0.Count < points1.Count)
                {
                    longL = points1;
                }
                if (points0.Count > points1.Count)
                {
                    shortL = points1;
                }
                double dif = (longL.Count - 1) / (shortL.Count - 1);
                if (dif > 1)
                {
                    //The longer list is significantly longer
                    //Each element in the shorter list is compared to multiple
                    // elements in the longer list to make up the difference
                    double sum = 0; int adds = 0;

                    for (int i = 0; i < shortL.Count - 1; i++)
                    {
                        if (i + 1 == shortL.Count)
                        {
                            break;
                        }
                        for (int j = 0; j <= dif; j++)
                        {
                            var k = i + j;
                            if (k + 1 == longL.Count)
                            {
                                break;
                            }
                            Vector v0 = new Vector(shortL[i + 1].X - shortL[i].X, shortL[i + 1].Y - shortL[i].Y);
                            Vector v1 = new Vector(longL[k + 1].X - longL[k].X, longL[k + 1].Y - longL[k].Y);
                            sum += CosineSimilarity(v0, v1); adds++;
                        }
                    }
                    return(sum / adds);
                }
                else
                {
                    //The longer list is almost the same length as the shorter list
                    //The remaining items are simply skipped
                    double sum = 0; int i = 0;
                    for (; i < shortL.Count - 1; i++)
                    {
                        if (i + 1 == shortL.Count || i + 1 == longL.Count)
                        {
                            break;
                        }
                        Vector v0 = new Vector(shortL[i + 1].X - shortL[i].X, shortL[i + 1].Y - shortL[i].Y);
                        Vector v1 = new Vector(longL[i + 1].X - longL[i].X, longL[i + 1].Y - longL[i].Y);
                        sum += CosineSimilarity(v0, v1);
                    }
                    return(sum / i);
                }
            }
        }