float StrokeCost(int strokeIndex, out StrokeMatch bestMatch) { StrokeTemplate template = Template[strokeIndex]; List <StrokeMatch> candidateMatches = InputMatches[strokeIndex]; float bestCost = float.PositiveInfinity; bestMatch = null; foreach (StrokeMatch match in candidateMatches) { if (match.Parts.Count != template.Parts.Count) { continue; } float cost = 0; for (int partIndex = 0; partIndex < match.Parts.Count; partIndex++) { StrokePartMatch partMatch = match.Parts[partIndex]; StrokePartTemplate partTemplate = template.Parts[partIndex]; cost += partTemplate.MatchCost(partMatch); } cost += match.Cost * 30; if (cost < bestCost) { bestCost = cost; bestMatch = match; } } return(bestCost); }
StrokePartMatch MatchLine(int start, int end) { StrokePart line = new StrokePart(Input[start], Input[end]); float multi = line.Length * 0.5f; float a = 0, b = 0, c = 0; //Parabel coefficients for (int i = start; i <= end; i++) { Vector2f point = Input[i]; float weight = Weight[i]; float scaledX = line.GetParallelPositionScaled(point); float unscaledY = line.GetOrthoPositionUnscaled(point); float unscaledOutside = (Math.Abs(scaledX) - 1) * multi; if (unscaledOutside > 0) { c += weight * (unscaledOutside * unscaledOutside + unscaledY * unscaledY); } else { float param = (1 - scaledX * scaledX) * multi; a += weight * param * param; b += weight * (-2) * param * unscaledY; c += weight * unscaledY * unscaledY; } } float optimalCurve = -b / (2 * a); var result = new StrokePartMatch(line.StartPoint, line.EndPoint, optimalCurve); result.DeltaCurveCost = a; result.MinCost = c - b * b / (4 * a); return(result); }
public float MatchCost(StrokePartMatch match) { float lenDelta = match.Delta.Length - Length; float lenDeltaSquared = lenDelta * lenDelta; float angleDelta = (match.Delta.AngleTo() - Angle) / (2 * (float)Math.PI); angleDelta = 2 * (angleDelta - (float)Math.Floor(angleDelta + 0.5f)); float angleDeltaSquared = angleDelta * angleDelta; float curveDelta = match.Curve - Curve; float curveDeltaSquared = curveDelta * curveDelta; float startDeltaSquared = (match.StartPoint - StartPoint).LengthSquared; float endDeltaSquared = (match.StartPoint - StartPoint).LengthSquared; float cost = 3*lenDeltaSquared + 4*(startDeltaSquared + endDeltaSquared) +6* curveDeltaSquared + 20*Length*angleDeltaSquared; return cost; }
public float MatchCost(StrokePartMatch match) { float lenDelta = match.Delta.Length - Length; float lenDeltaSquared = lenDelta * lenDelta; float angleDelta = (match.Delta.AngleTo() - Angle) / (2 * (float)Math.PI); angleDelta = 2 * (angleDelta - (float)Math.Floor(angleDelta + 0.5f)); float angleDeltaSquared = angleDelta * angleDelta; float curveDelta = match.Curve - Curve; float curveDeltaSquared = curveDelta * curveDelta; float startDeltaSquared = (match.StartPoint - StartPoint).LengthSquared; float endDeltaSquared = (match.StartPoint - StartPoint).LengthSquared; float cost = 3 * lenDeltaSquared + 4 * (startDeltaSquared + endDeltaSquared) + 6 * curveDeltaSquared + 20 * Length * angleDeltaSquared; return(cost); }
private IEnumerable <StrokeMatch> Match() { if (Input.Count < 2) { yield break; } var singleMatch = new List <StrokePartMatch>(); singleMatch.Add(MatchLine(0, Input.Count - 1)); yield return(new StrokeMatch(singleMatch)); foreach (int i in InterestingPoints) { StrokePartMatch match1 = MatchLine(0, i); StrokePartMatch match2 = MatchLine(i, Input.Count - 1); var match = new List <StrokePartMatch>(); match.Add(match1); match.Add(match2); StrokeMatch fullMatch = new StrokeMatch(match); yield return(fullMatch); } foreach (int i in InterestingPoints) { foreach (int j in InterestingPoints) { if (i >= j) { continue; } StrokePartMatch match1 = MatchLine(0, i); StrokePartMatch match2 = MatchLine(i, j); StrokePartMatch match3 = MatchLine(j, Input.Count - 1); var match = new List <StrokePartMatch>(); match.Add(match1); match.Add(match2); match.Add(match3); StrokeMatch fullMatch = new StrokeMatch(match); yield return(fullMatch); } } }
StrokePartMatch MatchLine(int start, int end) { StrokePart line = new StrokePart(Input[start], Input[end]); float multi = line.Length* 0.5f; float a = 0, b = 0, c = 0;//Parabel coefficients for (int i = start; i <= end; i++) { Vector2f point = Input[i]; float weight = Weight[i]; float scaledX = line.GetParallelPositionScaled(point); float unscaledY = line.GetOrthoPositionUnscaled(point); float unscaledOutside = (Math.Abs(scaledX) - 1) * multi; if (unscaledOutside > 0) { c += weight * (unscaledOutside * unscaledOutside + unscaledY *unscaledY ); } else { float param = (1 - scaledX * scaledX) * multi; a += weight * param * param; b += weight * (-2) * param * unscaledY; c += weight * unscaledY * unscaledY; } } float optimalCurve = -b / (2 * a); var result = new StrokePartMatch(line.StartPoint, line.EndPoint, optimalCurve); result.DeltaCurveCost = a; result.MinCost = c - b * b / (4 * a); return result; }