void InkAnalyzer_ContextNodeCreated(object sender, ContextNodeCreatedEventArgs e) { // The GetRecognizedString returns null when the ContextNodeCreated event // is called, so we need to deal with it later. InkWordNode inkWordNode = e.NodeCreated as InkWordNode; if (inkWordNode != null) { uncheckedNewWordNodes.Add(inkWordNode); } }
private void M_analizer_ResultsUpdated(object sender, ResultsUpdatedEventArgs e) { if (e.Status.Successful) { ContextNodeCollection leaves = ((InkAnalyzer)sender).FindLeafNodes(); foreach (ContextNode leaf in leaves) { if (leaf is InkWordNode) { // Como palabra InkWordNode t = leaf as InkWordNode; Rect l = t.Location.GetBounds(); ReconocerEntrada(t.GetRecognizedString()); } } LimpiarCanvas(); } }
private void M_analyzer_ResultsUpdated(object sender, ResultsUpdatedEventArgs e) { if (e.Status.Successful) { ContextNodeCollection leaves = ((InkAnalyzer)sender).FindLeafNodes(); foreach (ContextNode leaf in leaves) { if (leaf is InkWordNode) { // Como palabra InkWordNode t = leaf as InkWordNode; Rect l = t.Location.GetBounds(); var result = recognizer.EvaluateString(t.GetRecognizedString()); if (textResult != "") { if (textResult[textResult.Length - 1] == '?') { textResult = textResult.Replace("?", result); } else { textResult += result; } } else { textResult += result; } textBox.Text = textResult; } else { recognizer.MssgFeedback = "No se ha reconocido su trazo"; } FeedbackText.Text = recognizer.MssgFeedback; } //textBox.ScrollToEnd(); ResetCanvas(); } }
public static List <Stroke> findLines(ContextNodeCollection contextNodeCollection) { List <Stroke> horizontalLines = new List <Stroke>(); //Find single line gestures foreach (ContextNode node in contextNodeCollection) { if (node.Strokes.Count == 1) { Stroke stroke = node.Strokes[0]; if (strokeIsHorizontalLine(stroke)) { horizontalLines.Add(stroke); } } } //Find single line in words foreach (ContextNode node in contextNodeCollection) { if (node.Strokes.Count == 0) { continue; } if (node is InkWordNode) { InkWordNode word = node as InkWordNode; Rect bounds = word.Strokes.GetBounds(); foreach (Stroke stroke in word.Strokes) { if (stroke.GetBounds().Width / bounds.Width >= Constants.LINE_WORD_OVERLAPSE_RATIO) { horizontalLines.Add(stroke); } } } } return(horizontalLines); }
public void SetSuggestions(InkWordNode _incorrectWord, List<String> suggestions, Dictionary<char, StylusToken> fontData) { SuggestionsStack.Children.Clear(); incorrectWord = _incorrectWord; int minX = int.MaxValue; int maxX = int.MinValue; int minY = int.MaxValue; int maxY = int.MinValue; foreach (Point point in incorrectWord.GetRotatedBoundingBox()) { minX = Math.Min(minX, (int)point.X); maxX = Math.Max(maxX, (int)point.X); minY = Math.Min(minY, (int)point.Y); maxY = Math.Max(maxY, (int)point.Y); } this.Width = 0; this.Height = 0; var midline = incorrectWord.GetMidline(); var baseline = incorrectWord.GetBaseline(); // Assume that the midline and baseline are horizontal lines // i.e. two points, same y coordinate. double wordSize = baseline[0].Y - midline[0].Y; // Keep the top 3 suggestions for now. int displayCount = Math.Min(3, suggestions.Count); for (int i = 0; i < displayCount; i++) { StrokeCollection strokeRepresentation = GetStrokesForString(suggestions[i], fontData); // In the font maker, the font size is currently 30.0 InkUtils.Scale(strokeRepresentation, wordSize / 30.0); InkUtils.MatchThickness(incorrectWord.Strokes, strokeRepresentation); InkCanvas suggestionCanvas = new InkCanvas(); suggestionCanvas.Strokes.Add(strokeRepresentation); suggestionCanvas.Height = InkUtils.StrokeYMax(strokeRepresentation) + 10; suggestionCanvas.Width = InkUtils.StrokeXRange(strokeRepresentation) + 10; suggestionCanvas.TouchDown += SuggestionCanvas_TouchDown; suggestionCanvas.StylusDown += SuggestionCanvas_StylusDown; suggestionCanvas.StylusEnter += SuggestionCanvas_StylusEnter; suggestionCanvas.StylusLeave += SuggestionCanvas_StylusLeave; this.Width = Math.Max(this.Width, suggestionCanvas.Width); this.Height += suggestionCanvas.Height; // We shouldn't be writing on this canvas, it's only for // display purposes. suggestionCanvas.EditingMode = InkCanvasEditingMode.None; SuggestionsStack.Children.Add(suggestionCanvas); } // Positioning. if (minY < this.Height) { // Show suggestions under incorrect word. Canvas.SetTop(this, maxY); } else { // Show suggestions above incorrect word. Canvas.SetTop(this, minY - this.Height); } Canvas.SetLeft(this, minX); }
private List <HeadingItem> findHeadings(List <Stroke> horizontalLines, ContextNodeCollection contextNodeCollection) { //Group lines together into "Heading Groups" List <HeadingItem> headings = new List <HeadingItem>(); foreach (Stroke node1 in horizontalLines) { List <HeadingItem> intersectHeadings = new List <HeadingItem>(); foreach (HeadingItem heading in headings) { bool intersectsAny = false; foreach (Stroke node2 in heading.lines) { Rect first = node1.GetBounds(); Rect second = node2.GetBounds(); if (Math.Abs(first.Y - second.Y) < Constants.HEADING_LINE_DISTANCE_MAX && Math.Abs(first.X - second.X) < Constants.HEADING_LINE_DISTANCE_MAX) { intersectsAny = true; break; } } if (intersectsAny) { intersectHeadings.Add(heading); } } HeadingItem resultHeading = new HeadingItem(); foreach (HeadingItem heading in intersectHeadings) { resultHeading.lines.AddRange(heading.lines); headings.Remove(heading); } resultHeading.lines.Add(node1); headings.Add(resultHeading); } //Find words that associate to Heading Groups foreach (ContextNode node in contextNodeCollection) { if (node.Strokes.Count == 0) { continue; } Rect underlineBounds = node.Strokes.GetBounds(); if (node is InkWordNode) { if ((node as InkWordNode).GetBaseline() != null && (node as InkWordNode).GetBaseline().Count > 0) { double baseline = (node as InkWordNode).GetBaseline()[0].Y; underlineBounds.Y = baseline; } InkWordNode word = node as InkWordNode; foreach (HeadingItem heading in headings) { if (heading.intersects(underlineBounds)) { heading.text.Add(word); break; } } } } //Remove bad headings List <HeadingItem> actualHeadings = new List <HeadingItem>(); foreach (HeadingItem heading in headings) { if (heading.text.Count > 0) { actualHeadings.Add(heading); } } return(actualHeadings); }
/// <summary> /// InkAnalysis results form a tree, this method is called recursively /// to render each node in the tree. /// </summary> private void DrawFeedback(DrawingContext drawingContext, ContextNode contextNode) { //see what type of ContextNode this is by casting it Rect nodeBounds = contextNode.Strokes.GetBounds(); InkWordNode inkWordNode = contextNode as InkWordNode; if (inkWordNode != null) { drawingContext.DrawRoundedRectangle(null, new Pen(Brushes.Blue, 1.0d), nodeBounds, 1d, 1d); drawingContext.DrawText(new FormattedText(inkWordNode.GetRecognizedString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Verdana"), 9.0d, Brushes.Black), nodeBounds.BottomLeft); goto recurse; } InkDrawingNode inkDrawingNode = contextNode as InkDrawingNode; if (inkDrawingNode != null) { drawingContext.DrawRoundedRectangle(null, new Pen(Brushes.Purple, 1.0d), nodeBounds, 1d, 1d); drawingContext.DrawText(new FormattedText("Drawing: " + inkDrawingNode.GetShapeName(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Verdana"), 9.0d, Brushes.Black), nodeBounds.BottomLeft); goto recurse; } InkBulletNode inkBulletNode = contextNode as InkBulletNode; if (inkBulletNode != null) { drawingContext.DrawRoundedRectangle(null, new Pen(Brushes.Green, 1.0d), nodeBounds, 1d, 1d); drawingContext.DrawText(new FormattedText(inkBulletNode.GetRecognizedString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Verdana"), 9.0d, Brushes.Black), nodeBounds.BottomLeft); goto recurse; } WritingRegionNode writingRegionNode = contextNode as WritingRegionNode; if (writingRegionNode != null) { nodeBounds.Inflate(3d, 3d); drawingContext.DrawRoundedRectangle(null, new Pen(Brushes.Black, 1.0d), nodeBounds, 1d, 1d); drawingContext.DrawText(new FormattedText("Writing Region", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Verdana"), 9.0d, Brushes.Black), nodeBounds.BottomLeft + new Vector(0, 3)); goto recurse; } ParagraphNode paragraphNode = contextNode as ParagraphNode; if (paragraphNode != null) { nodeBounds.Inflate(2d, 2d); //inflate so this will be visible outside the line node drawingContext.DrawRoundedRectangle(null, new Pen(Brushes.Red, 1.0d), nodeBounds, 1d, 1d); goto recurse; } LineNode lineNode = contextNode as LineNode; if (lineNode != null) { nodeBounds.Inflate(1d, 1d); //inflate so this will be visible outside the word node drawingContext.DrawRoundedRectangle(null, new Pen(Brushes.Orange, 1.0d), nodeBounds, 1d, 1d); goto recurse; } recurse: foreach (ContextNode subNode in contextNode.SubNodes) { DrawFeedback(drawingContext, subNode); } }
private void reflowParagraph(ParagraphNode node, InkAnalyzer inkAnalyzer, InkCanvas inkCanvas) { ContextNodeCollection lines = node.SubNodes; Rect bounds = node.Strokes.GetBounds(); List <InkWordNode> resultWords = new List <InkWordNode>(); double lineHeight = 0; double spacing = 30; //Collect all strokes foreach (ContextNode line in lines) { ContextNodeCollection words = line.SubNodes; foreach (ContextNode word in words) { lineHeight += word.Strokes.GetBounds().Height; InkWordNode wordNode = word as InkWordNode; resultWords.Add(wordNode); } } lineHeight /= resultWords.Count; List <List <InkWordNode> > resultLines = new List <List <InkWordNode> >(); List <double> lineMaxBaseline = new List <double>(); //Reflow strokes double x = 0; double maxX = inkCanvas.ActualWidth - bounds.X; resultLines.Add(new List <InkWordNode>()); lineMaxBaseline.Add(0); foreach (InkWordNode word in resultWords) { //Does word fit? Rect wordBound = word.Strokes.GetBounds(); if (x + wordBound.Width + spacing > maxX && multiline) { //Not fitting! Newline x = 0; resultLines.Add(new List <InkWordNode>()); lineMaxBaseline.Add(0); } x += spacing + wordBound.Width; PointCollection baseline = word.GetBaseline(); if (baseline != null && baseline.Count > 0) { double baselineFromTop = baseline[0].Y - wordBound.Y; resultLines[resultLines.Count - 1].Add(word); if (baselineFromTop > lineMaxBaseline[resultLines.Count - 1]) { lineMaxBaseline[resultLines.Count - 1] = baselineFromTop; } } } double y = 0; int lineNumber = 0; foreach (List <InkWordNode> line in resultLines) { double lineBaseline = lineMaxBaseline[lineNumber]; x = 0; foreach (InkWordNode word in line) { Rect wordBound = word.Strokes.GetBounds(); PointCollection baseline = word.GetBaseline(); double baselineFromTop = baseline[0].Y - wordBound.Y; double destX = (x + bounds.X); double dx = destX - (wordBound.X); //Match mid double dy = (y + lineBaseline + bounds.Y) - (wordBound.Y + baselineFromTop); InkUtils.transposeStrokes(inkAnalyzer, word.Strokes, dx, dy); x += spacing + wordBound.Width; } y += lineHeight + spacing; lineNumber++; } }
public void SetSuggestions(InkWordNode _incorrectWord, List <String> suggestions, Dictionary <char, StylusToken> fontData) { SuggestionsStack.Children.Clear(); incorrectWord = _incorrectWord; int minX = int.MaxValue; int maxX = int.MinValue; int minY = int.MaxValue; int maxY = int.MinValue; foreach (Point point in incorrectWord.GetRotatedBoundingBox()) { minX = Math.Min(minX, (int)point.X); maxX = Math.Max(maxX, (int)point.X); minY = Math.Min(minY, (int)point.Y); maxY = Math.Max(maxY, (int)point.Y); } this.Width = 0; this.Height = 0; var midline = incorrectWord.GetMidline(); var baseline = incorrectWord.GetBaseline(); // Assume that the midline and baseline are horizontal lines // i.e. two points, same y coordinate. double wordSize = baseline[0].Y - midline[0].Y; // Keep the top 3 suggestions for now. int displayCount = Math.Min(3, suggestions.Count); for (int i = 0; i < displayCount; i++) { StrokeCollection strokeRepresentation = GetStrokesForString(suggestions[i], fontData); // In the font maker, the font size is currently 30.0 InkUtils.Scale(strokeRepresentation, wordSize / 30.0); InkUtils.MatchThickness(incorrectWord.Strokes, strokeRepresentation); InkCanvas suggestionCanvas = new InkCanvas(); suggestionCanvas.Strokes.Add(strokeRepresentation); suggestionCanvas.Height = InkUtils.StrokeYMax(strokeRepresentation) + 10; suggestionCanvas.Width = InkUtils.StrokeXRange(strokeRepresentation) + 10; suggestionCanvas.TouchDown += SuggestionCanvas_TouchDown; suggestionCanvas.StylusDown += SuggestionCanvas_StylusDown; suggestionCanvas.StylusEnter += SuggestionCanvas_StylusEnter; suggestionCanvas.StylusLeave += SuggestionCanvas_StylusLeave; this.Width = Math.Max(this.Width, suggestionCanvas.Width); this.Height += suggestionCanvas.Height; // We shouldn't be writing on this canvas, it's only for // display purposes. suggestionCanvas.EditingMode = InkCanvasEditingMode.None; SuggestionsStack.Children.Add(suggestionCanvas); } // Positioning. if (minY < this.Height) { // Show suggestions under incorrect word. Canvas.SetTop(this, maxY); } else { // Show suggestions above incorrect word. Canvas.SetTop(this, minY - this.Height); } Canvas.SetLeft(this, minX); }