/// <summary> /// Calculates the similarity between this point and either 1 or 2 previous points representing a line segment /// This function decides how appropriately this point would fit into a path joining 'point' /// Comparison factors include: thickness of this valley compared to the last, valley colour, relative directions of the valleys /// </summary> /// <param name="point">Point to compare with</param> /// <param name="previousPoint">Point prior to 'point', if applicable</param> /// <returns>A floating-point similarity value between 0 and 1 where 1 is virtually identical</returns> public SimilarityPack CalculateSimilarity(EdgePoint point, EdgePoint previousPoint = null) { SimilarityPack similarity = new SimilarityPack() { Colour = ImageMath.PixelDifference(ColourUnderPoint, point.ColourUnderPoint), Direction = 1.0f, Length = 1.0f, Width = 1.0f, Distance = 1.0f, }; if (previousPoint != null) { Vector2 previousVector = new Vector2(point.X - previousPoint.X, point.Y - previousPoint.Y); Vector2 currentVector = new Vector2(X - point.X, Y - point.Y); if (previousVector.LengthSquared() > 0 && currentVector.LengthSquared() > 0) { // Direction similarity: Use the dot product of the normalised segment vectors similarity.Direction = Vector2.Dot(previousVector / previousVector.Length(), currentVector / currentVector.Length()); // Length similarity: Use the smaller length divided by the bigger length.....? similarity.Length = previousVector.Length() / currentVector.Length(); if (similarity.Length > 1.0f) { similarity.Length = 1.0f / similarity.Length; // swap the division operands lazily } } } if (point.LastPoint != null && LastPoint != null) { // Width similarity: Use the smaller width divided by the bigger width? similarity.Width = Vector2.Distance(new Vector2(X, Y), new Vector2(LastPoint.X, LastPoint.Y)) / Vector2.Distance(new Vector2(point.X, point.Y), new Vector2(point.LastPoint.X, point.LastPoint.Y)); if (similarity.Width > 1.0f) { similarity.Width = 1.0f / similarity.Width; } } if (previousPoint == null) { float distanceToPoint = Vector2.Distance(new Vector2(X, Y), new Vector2(point.X, point.Y)); similarity.Distance = distanceToPoint > 0 ? 1.0f / distanceToPoint : 1.0f; } return(similarity); }
private void ConnectEdgePoints(IEnumerable <EdgePoint>[] gridLines, List <Highlighter> highlighters) { // We want to join lines of similar edge lengths together. If we're coming from the tips of the fingers, we're fine increasing the width over time // If we're coming from the opposite, we're fine decreasing the width // Basically, we want to track whether the width increases or decreases as we go along List <EdgePoint> finalEdgeList = new List <EdgePoint>(); for (int i = Input.LastClickPosition.X / gridInterval; i < gridLines.Count(); ++i) { EdgePoint mostSimilarPoint = null; SimilarityPack highestSimilarity = new SimilarityPack(); foreach (EdgePoint p in gridLines[i]) { SimilarityPack similarity; if (finalEdgeList.Count == 0) { similarity = new SimilarityPack(); similarity.Distance = 1.0f / ((p.X - Input.LastClickPosition.X) * (p.X - Input.LastClickPosition.X) + (p.Y - Input.LastClickPosition.Y) * (p.Y - Input.LastClickPosition.Y)); } else if (finalEdgeList.Count == 1) { similarity = p.CalculateSimilarity(finalEdgeList[0], null); } else { similarity = p.CalculateSimilarity(finalEdgeList[finalEdgeList.Count - 1], finalEdgeList[finalEdgeList.Count - 2]); } if (similarity.OverallSimilarity >= highestSimilarity.OverallSimilarity) { mostSimilarPoint = p; highestSimilarity = similarity; } } finalEdgeList.Add(mostSimilarPoint); DebugInfo += highestSimilarity.Info + "\r\n"; } for (int i = 1; i < finalEdgeList.Count; ++i) { highlighters.Add(new EdgeHighlighter(new Point(finalEdgeList[i - 1].X, finalEdgeList[i - 1].Y), new Point(finalEdgeList[i].X, finalEdgeList[i].Y)) { Pen = new Pen(Color.Green, 1.0f) }); } }