public void TestParseTwoInputsAndWire() { List <Sketch.Shape> modifiedShapes; // Add a wire Sketch.Substroke wireSub = AddNewStroke(new Tuple <double, double>(0.2, 0.2), new Tuple <double, double>(0.8, 0.8)); Sketch.Shape wire = sketch.MakeNewShapeFromSubstroke(out modifiedShapes, wireSub, Domain.LogicDomain.WIRE, 1); wire.Name = "wire_0"; // Add the left input and connect it to the wire Sketch.Substroke firstSub = AddNewStroke(new Tuple <double, double>(0.0, 0.0), new Tuple <double, double>(0.1, 0.1)); Sketch.Shape firstLabel = sketch.MakeNewShapeFromSubstroke(out modifiedShapes, firstSub, Domain.LogicDomain.TEXT, 1); firstLabel.Name = "A"; wire.Endpoints[0].ConnectedShape = firstLabel; sketch.connectShapes(firstLabel, wire); // Add the right input and connect it to the wire Sketch.Substroke secondSub = AddNewStroke(new Tuple <double, double>(0.9, 0.9), new Tuple <double, double>(1.0, 1.0)); Sketch.Shape secondLabel = sketch.MakeNewShapeFromSubstroke(out modifiedShapes, secondSub, Domain.LogicDomain.TEXT, 1); secondLabel.Name = "B"; wire.Endpoints[1].ConnectedShape = secondLabel; sketch.connectShapes(secondLabel, wire); Assert.IsTrue(parser.SuccessfullyParse(sketch), "parser should be able to parse sketch with a wire connecting two labels"); }
/// <summary> /// Break any shapes which are only partially in this selection /// </summary> private void BreakShapes() { foreach (Stroke stroke in resizedStrokes) { Sketch.Substroke substroke = inkSketch.GetSketchSubstrokeByInk(stroke); Sketch.Shape parent = substroke.ParentShape; if (parent != null && !oldShapesToNewShapes.ContainsKey(parent)) { bool breakShape = false; List <Sketch.Substroke> substrokes = new List <Sketch.Substroke>(); foreach (Sketch.Substroke sub in parent.Substrokes) { if (!resizedStrokes.Contains(inkSketch.GetInkStrokeBySubstroke(sub))) { breakShape = true; } else { substrokes.Add(sub); } } if (breakShape) { Sketch.Shape newShape = inkSketch.Sketch.BreakOffShape(parent, substrokes); oldShapesToNewShapes[newShape] = parent; } } } }
/// <summary> /// Constructor for StrokeInfoForm /// </summary> /// <param name="strokefeatures"></param> a FeatureStroke /// <param name="sketchFeatures"></param> a FeatureSketch /// <param name="inkStroke"></param> a System.Windows.Controls Stroke /// <param name="substroke"></param> a Sketch Substroke public StrokeInfoWindow(FeatureStroke strokefeatures, FeatureSketch sketchFeatures, Stroke inkStroke, Sketch.Substroke substroke) { InitializeComponent(); inkMovedX = 0; inkMovedY = 0; scale = 2.0f; mInkCanvas.Width = Width / 2 - 20; mInkCanvas.Height = Height - 20; mInkCanvas.StrokeCollected += new InkCanvasStrokeCollectedEventHandler(mInkCanvas_StrokeCollected); mSketchFeatures = sketchFeatures; mStrokeFeatures = strokefeatures; mInkStroke = inkStroke; mSubstroke = substroke; mInkCanvas.Strokes.Add(mInkStroke); Red = Color.FromArgb(255, 255, 0, 0); Green = Color.FromArgb(255, 0, 255, 0); Blue = Color.FromArgb(255, 0, 0, 255); Black = Color.FromArgb(255, 0, 0, 0); mInkCanvas.Strokes[0].DrawingAttributes.Color = Red; populateListView(); }
/// <summary> /// Constructor /// </summary> /// <param name="sketch">SketchPanel to add a label to</param> /// <param name="inkStrokes">InkOverlay strokes</param> /// <param name="inkStrokes">A StrokeCollection strokes</param> /// <param name="label">Label to apply</param> public ApplyLabelCmd(SketchPanel sketch, StrokeCollection inkStrokes, ShapeType labelType, bool userSpecifiedGroup = true, bool userSpecifiedLabel = true, int tagNumber = int.MinValue) { isUndoable = true; this.sketchPanel = sketch; this.inkStrokes = inkStrokes; this.userSpecifiedGroup = userSpecifiedGroup; this.userSpecifiedLabel = userSpecifiedLabel; this.tagNumber = tagNumber; this.labelType = labelType; // Save the original labels of the substrokes originalLabels = new Dictionary <Sketch.Shape, Tuple <ShapeType, StrokeCollection> >(); unlabeledStrokes = new StrokeCollection(); foreach (Stroke stroke in inkStrokes) { // If the stroke is classified, save its original shape. Sketch.Substroke sub = sketchPanel.InkSketch.GetSketchSubstrokeByInk(stroke); if (sub.ParentShape != null) { if (!originalLabels.ContainsKey(sub.ParentShape)) { originalLabels[sub.ParentShape] = new Tuple <ShapeType, StrokeCollection>(sub.ParentShape.Type, new StrokeCollection()); } originalLabels[sub.ParentShape].Item2.Add(stroke); } else // Record that it wasn't labeled. { unlabeledStrokes.Add(stroke); } } }
/// <summary> /// Constructor /// </summary> /// <param name="sketch">SketchPanel to add a label to</param> /// <param name="inkStrokes">InkOverlay strokes</param> /// <param name="inkStrokes">A StrokeCollection strokes</param> /// <param name="label">Label to apply</param> public ApplyLabelCmd(SketchPanel sketch, StrokeCollection inkStrokes, string label, bool userSpecifiedGroup = true, bool userSpecifiedLabel = true) { isUndoable = false; this.sketchPanel = sketch; this.label = label; this.inkStrokes = inkStrokes; this.userSpecifiedGroup = userSpecifiedGroup; this.userSpecifiedLabel = userSpecifiedLabel; labelColor = LogicDomain.getType(label).Color; // Save the original labels of the substrokes origLabels = new Dictionary <string, Data.Pair <ShapeType, StrokeCollection> >(); unlabeledStrokes = new StrokeCollection(); foreach (Stroke stroke in inkStrokes) { Sketch.Substroke sub = sketchPanel.InkSketch.GetSketchSubstrokeByInk(stroke); if (sub.ParentShape != null) { if (!origLabels.ContainsKey(sub.ParentShape.Name)) { origLabels[sub.ParentShape.Name] = new Data.Pair <ShapeType, StrokeCollection>(sub.ParentShape.Type, new StrokeCollection()); } origLabels[sub.ParentShape.Name].B.Add(stroke); } else { unlabeledStrokes.Add(stroke); } } }
/// <summary> /// Look at any out-of-context shapes in the sketch and refine them by /// removing a substroke. (We may want to try removing more strokes later). /// /// We assume that the substroke should be a wire, and we remove it /// from the shape. Then we regroup the shape without the substroke, /// re-recognize it, and check to see if it makes sense. If it does, /// keep it. If not, try again with a different substroke. /// </summary> public void StrokeShedRefine(Featurefy.FeatureSketch featureSketch) { foreach (Sketch.Shape shape in featureSketch.Sketch.Shapes) { bool valid = _domain.IsProperlyConnected(shape); // If the shape wansn't specified by the user, doesn't fit // its context, and is a gate if ((!shape.AlreadyGrouped) && (!valid || (shape.Probability < _thresholdProbability)) && (shape.Classification == LogicDomain.GATE_CLASS)) { float bestProb = 0F; Sketch.Substroke bestSubstroke = null; foreach (Sketch.Substroke substroke in shape.Substrokes) { // See how helpful it is to let the shape // shed this stroke float shedProb = strokeShedHelpfulness(shape, substroke, featureSketch); if (shedProb > bestProb) { bestProb = shedProb; bestSubstroke = substroke; } } // If hypotheticaly shedding one of the substrokes // enhanced the recognition of the shape, do it for real //if (bestProb > shape.Probability) // NOT SURE IF WE WANT TO KEEP THIS shedStroke(shape, bestSubstroke, featureSketch); } } }
/// <summary> /// Find all the substrokes that compose one subgroup /// within a given shape, starting with a given /// seed substroke, and store these substrokes in a /// given list. /// /// A subgroup is defined as a set of adjacent substrokes. /// This function uses a depth first search. /// /// NOTE: the shape must contain the given substroke /// </summary> /// <param name="seedSubstroke">A substroke in the desired subgroup</param> /// <param name="shape">The shape to investigate</param> /// <param name="adjacentSubstrokes">The list to store the desired substrokes</param> /// <param name="adjacency">The adjacency matrix for strokes</param> private void oneShapeSubgroup(Sketch.Substroke seedSubstroke, Sketch.Shape shape, List <Sketch.Substroke> adjacentSubstrokes, Dictionary <Guid, Dictionary <Guid, int> > adjacency) { Debug.Assert(shape.SubstrokesL.Contains(seedSubstroke), "Shape does not contain given substroke"); // Make a list of adjacent substrokes not yet accounted for List <Sketch.Substroke> additionalSubstrokes = new List <Sketch.Substroke>(); foreach (Sketch.Substroke substroke in shape.Substrokes) { if ((!adjacentSubstrokes.Contains(substroke)) && ((seedSubstroke.Id == substroke.Id) || (adjacency[seedSubstroke.Id][substroke.Id] > 0))) { additionalSubstrokes.Add(substroke); } } // Recurse on each of the found adjacent substrokes if (additionalSubstrokes.Count > 0) { foreach (Sketch.Substroke substroke in additionalSubstrokes) { adjacentSubstrokes.Add(substroke); } foreach (Sketch.Substroke substroke in additionalSubstrokes) { oneShapeSubgroup(substroke, shape, adjacentSubstrokes, adjacency); } } }
public void FeatureSketchCreationBehavior() { /* * Problem description: * When a sketch contains duplicated points, the creation of a FeatureSketch * may delete those points. */ Sketch.Sketch sketch = Sketches.newValidSketch(); // Duplicate a point in the sketch Sketch.Shape shape = sketch.Shapes[0]; List <Sketch.Point> points = new List <Sketch.Point>(shape.Substrokes[0].Points); points.Add(points[points.Count - 1]); Sketch.Substroke substroke = new Sketch.Substroke(points); sketch.AddStroke(new Sketch.Stroke(substroke)); shape.AddSubstroke(substroke); Sketch.Sketch clone = sketch.Clone(); Assert.IsTrue(sketch.Equals(clone), "Sketch is not equal to its clone"); Featurefy.FeatureSketch featureSketch = newValidFeatureSketch(new Sketch.Project(sketch)); Assert.IsTrue(sketch.Equals(clone), "FeatureSketch creation modified original sketch"); }
/// <summary> /// Main constructor of the subcircuit window. Takes in a project that it will wrap into an inkcanvas sketch /// in order to display. /// </summary> /// <param name="subSketch"></param> public MainWindow(ref Sketch.Project subSketch) { try { InitializeComponent(); } catch (Exception ex) { // Log error System.Console.WriteLine(ex.InnerException.Message); //System.Console.WriteLine(ex.ListTrace); } // Set up notes panel this.subSketch = subSketch; WrapperSketch = new InkToSketchWPF.InkCanvasSketch(new InkCanvas()); WrapperSketch.project = subSketch; this.WrapperSketch.ClearButNotSketch(); // Makes the ink to display WrapperSketch.CreateInkStrokesFromSketch(); //Set up the ink holder this.inkCanvas = WrapperSketch.InkCanvas; this.inkCanvas.Height = dockPanel.Height; this.inkCanvas.Width = dockPanel.Width; //The dockPanel is in a view box, which means that it will scale (and scale its children) //to fit the screen. TextBlock helpText = new TextBlock(); helpText.Text = "You can click a sub-circuit if one exists to view it"; helpText.FontSize = 16; dockPanel.Children.Clear(); dockPanel.Children.Add(this.inkCanvas); this.inkCanvas.Children.Add(helpText); //Actually color the strokes on the inkcanvas according to the recognition //This is valid because only simulatable circuits can be viewed here foreach (System.Windows.Ink.Stroke inkStroke in this.inkCanvas.Strokes) { Sketch.Substroke substroke = (Sketch.Substroke)WrapperSketch.GetSketchSubstrokeByInk(inkStroke); Domain.ShapeType label = substroke.Type; Color color = label.Color; inkStroke.DrawingAttributes.Color = color; } //Draws the inkcanvas with the new colors this.WrapperSketch.InkCanvas.InvalidateVisual(); this.inkCanvas.UpdateLayout(); // Set Editing Modes inkCanvas.EditingMode = InkCanvasEditingMode.None; inkCanvas.EditingModeInverted = InkCanvasEditingMode.None; inkCanvas.StylusDown += new StylusDownEventHandler(inkCanvas_StylusDown); }
private static void WriteSubstroke(Sketch.Substroke substroke, XmlTextWriter xmlDocument) { string[] substrokeAttributeNames = substroke.XmlAttrs.getAttributeNames(); object[] substrokeAttributeValues = substroke.XmlAttrs.getAttributeValues(); Sketch.Point[] points = substroke.Points; int length; int i; xmlDocument.WriteStartElement("shape"); // Write all the attributes length = substrokeAttributeNames.Length; for (i = 0; i < length; ++i) { if (substrokeAttributeValues[i] != null) { xmlDocument.WriteAttributeString(substrokeAttributeNames[i], substrokeAttributeValues[i].ToString()); } } // Write the point references length = points.Length; for (i = 0; i < length; ++i) { SaveToXML.WritePointReference(points[i], xmlDocument); } xmlDocument.WriteEndElement(); }
/// <summary> /// Applies a label to a group of substrokes. /// </summary> public override bool Execute() { // Add the new stroke to the sketch inkSketch.AddStroke(newStroke); // Update connections Sketch.Substroke newSubstroke = inkSketch.GetSketchSubstrokeByInk(newStroke); changedShape.AddSubstroke(newSubstroke); oldLocation.ConnectedShape = changedShape; newSubstroke.Endpoints[0].ConnectedShape = changedShape; newSubstroke.Endpoints[1].ConnectedShape = shapeAtNewLoc; // Add the new wire to the old wire's shape inkSketch.Sketch.connectShapes(changedShape, changedShape); // wires connected to themselves indicates an internal connection inkSketch.Sketch.connectShapes(changedShape, shapeAtNewLoc); changedShape.AlreadyLabeled = true; // Pre-emptive merging! Helps us undo. if (newIsWire) { inkSketch.Sketch.mergeShapes(changedShape, shapeAtNewLoc); } // Regroup everything so highlighting/labels are correctly updated Handle(changedShape); Regroup(new List <Sketch.Shape> { changedShape }); return(true); }
/// <summary> /// Take a substroke and add it to a given shape. /// </summary> /// <param name="shape">The shape that steals</param> /// <param name="substroke">The substroke to steal</param> private void stealStroke(Sketch.Shape strokeThief, Sketch.Substroke strokeToSteal, Featurefy.FeatureSketch featureSketch) { if (strokeToSteal != null) { // Move the substroke we're trying to steal Sketch.Shape strokeLoser = strokeToSteal.ParentShape; strokeLoser.RemoveSubstroke(strokeToSteal); strokeThief.AddSubstroke(strokeToSteal); // Update what these recombinant shapes and their // connected shapes are connected to List <Sketch.Shape> changedShapes = new List <Sketch.Shape>(); changedShapes.Add(strokeThief); changedShapes.Add(strokeLoser); _connector.recomputeConnectedShapes(changedShapes, featureSketch.Sketch); // Also update the substroke to match its new shape strokeToSteal.Classification = "Gate"; // See if the stroke thief is a valid shape _sketchRecognizer.recognize(strokeThief, featureSketch); // See if the stroke loser is a valid shape if (strokeLoser.SubstrokesL.Count > 0) { _sketchRecognizer.recognize(strokeLoser, featureSketch); } } }
/// <summary> /// Constructor /// </summary> /// <param name="order"></param> /// <param name="stroke"></param> public TimeToNext(SortedList <ulong, Sketch.Substroke> order, Sketch.Substroke stroke) : base("Time to Next Stroke", Scope.Multiple_Static) { m_Normalizer = Compute.StrokeTimeNormalizer; int index = order.IndexOfValue(stroke); if (index == order.Count - 1) { m_Value = 0.0; } else { ulong endCurrent = 0; ulong startNext = 0; foreach (KeyValuePair <ulong, Sketch.Substroke> pair in order) { if (pair.Value == stroke) { Sketch.Point[] points = pair.Value.Points; endCurrent = points[points.Length - 1].Time; } else if (order.IndexOfKey(pair.Key) == index + 1) { startNext = pair.Key; } } m_Value = (double)(startNext - endCurrent); } }
public void testWriteXML() { Sketch.Sketch sketch = new Sketch.Sketch(); sketch.XmlAttrs.Id = System.Guid.NewGuid(); Sketch.Shape shape = new Sketch.Shape(); shape.XmlAttrs.Id = System.Guid.NewGuid(); shape.XmlAttrs.Name = "shapeName"; shape.XmlAttrs.Type = "shape"; shape.XmlAttrs.Time = "111"; Sketch.Stroke stroke; Sketch.Substroke substroke; Sketch.Point point; ulong h; ulong i; ulong j; for (h = 0; h < 3; ++h) { stroke = new Sketch.Stroke(); stroke.XmlAttrs.Id = System.Guid.NewGuid(); stroke.XmlAttrs.Name = "strokeName"; stroke.XmlAttrs.Type = "stroke"; stroke.XmlAttrs.Time = h; for (i = 0; i < 5; ++i) { substroke = new Sketch.Substroke(); substroke.XmlAttrs.Id = System.Guid.NewGuid(); substroke.XmlAttrs.Name = "substrokeName"; substroke.XmlAttrs.Type = "substroke"; substroke.XmlAttrs.Time = i; for (j = 0; j < 10; ++j) { point = new Sketch.Point(); point.XmlAttrs.X = (float)random.NextDouble(); point.XmlAttrs.Y = (float)random.NextDouble(); point.XmlAttrs.Id = System.Guid.NewGuid(); point.XmlAttrs.Pressure = (ushort)(random.NextDouble() * 256); point.XmlAttrs.Name = "point" + j.ToString(); point.XmlAttrs.Time = j; substroke.AddPoint(point); } stroke.AddSubstroke(substroke); shape.AddSubstroke(substroke); } sketch.AddStroke(stroke); } sketch.AddShape(shape); sketch.Strokes[0].SplitStrokeAt(new int[] { 7, 14, 16, 21 }); ConverterXML.MakeXML xml = new ConverterXML.MakeXML(sketch); xml.WriteXML("test.xml"); }
/// <summary> /// Returns the stroke to it's original drawing attributes /// </summary> /// <param name="stroke"></param> private void unhighlightStroke(Stroke stroke) { if (sketchPanel.InkCanvas.Strokes.Contains(stroke)) { Sketch.Substroke substroke = sketchPanel.InkSketch.GetSketchSubstrokeByInk(stroke); stroke.DrawingAttributes.Color = substroke.Type.Color; } }
private static void WriteSubstrokeReference(Sketch.Substroke substroke, XmlTextWriter xmlDocument) { xmlDocument.WriteStartElement("arg"); xmlDocument.WriteAttributeString("type", "substroke"); xmlDocument.WriteString(substroke.XmlAttrs.Id.ToString()); xmlDocument.WriteEndElement(); }
/// <summary> /// When we remove the stylus, we make our selection /// </summary> /// <param name="sender">Ignored :(</param> /// <param name="e">MouseEventArgs, contains mouse location</param> public override void InkCanvas_StylusUp(object sender, System.Windows.Input.StylusEventArgs e) { if (!subscribed || e.Inverted || !makingSelection) { return; } // Update the rectangle one more time BoxSelect_StylusMove(sender, e); // Select the strokes under the box StrokeCollection boxSelection = sketchPanel.InkCanvas.Strokes.HitTest(currentRect, 70); // Look for a stroke directly below us System.Windows.Point point = e.GetPosition(sketchPanel.InkCanvas); Sketch.Substroke substrokeBelow = sketchPanel.InkSketch.Sketch.substrokeAtPoint(point.X, point.Y, SEARCH_RADIUS); if (boxSelection.Count > 0) { selection = boxSelection; } else if (substrokeBelow != null) { Stroke singleStroke = sketchPanel.InkSketch.GetInkStrokeBySubstroke(substrokeBelow); if (selection.Contains(singleStroke)) { if (debug) { System.Console.WriteLine("Stroke being removed"); } selection.Remove(singleStroke); } else { if (debug) { System.Console.WriteLine("Stroke being added"); } selection.Add(singleStroke); } } else if (substrokeBelow == null && boxSelection.Count == 0) { selection.Clear(); } Selection = selection; selectBox.Visibility = System.Windows.Visibility.Hidden; sketchPanel.InkCanvas.Children.Remove(selectBox); if (makingSelection) { selectionMade = selection.Count > 0; } makingSelection = false; }
public void AddStroke(Sketch.Substroke sub) { for (int i = 0; i < sub.PointsL.Count; i++) { _points.Add(new GenericPoint(sub.PointsL[i].X, sub.PointsL[i].Y, false)); } _points.Add(new GenericPoint(sub.PointsL[sub.PointsL.Count - 1].X, sub.PointsL[sub.PointsL.Count - 1].Y, true)); update(); }
/// <summary> /// Remove a substroke from a shape and turn it into a wire, and /// update the remains of the shape. If the shape ends up breaking /// into multiple shapes upon removing the substroke, the function /// returns a a list of these broken off shapes. If the shape /// originally had one substroke and therefore ends up with none, /// the empty shape gets removed from the sketch. /// /// ASSUMPTIONS: /// * The removed substroke should be a wire. /// * The shape has at least 1 substroke /// </summary> /// <param name="shape">The shape that sheds</param> /// <param name="substroke">The substroke to shed</param> /// <returns>A list of any shapes that were broken off of the /// original shape in the process.</returns> private List <Sketch.Shape> shedStroke(Sketch.Shape shape, Sketch.Substroke substroke, Featurefy.FeatureSketch featureSketch) { if (substroke == null) { return(null); } else { Debug.Assert(shape.SubstrokesL.Contains(substroke), "The substroke is not in the shape!"); // Change substroke classification to wire. substroke.Classification = "Wire"; // Remove substroke from the shape, and make it a new shape. List <Sketch.Substroke> strokesToShed = new List <Sketch.Substroke>(); strokesToShed.Add(substroke); Sketch.Shape newShape = featureSketch.Sketch.BreakOffShape(shape, strokesToShed); // Recognize the new shape. _sketchRecognizer.recognize(newShape, featureSketch); // Check if removing the substroke split the shape into smaller, unconnected shapes List <Sketch.Shape> brokenOffShapes = maybeBreakOffShapes(shape, featureSketch.Sketch); // Reconnect the shape(s) and the new, broken-off shape. List <Sketch.Shape> changedShapes = new List <Sketch.Shape>(); changedShapes.Add(shape); changedShapes.Add(newShape); foreach (Sketch.Shape subshape in brokenOffShapes) { changedShapes.Add(subshape); } _connector.recomputeConnectedShapes(changedShapes, featureSketch.Sketch); // If the shape no longer exists, remove it. if (shape.SubstrokesL.Count == 0) { featureSketch.Sketch.RemoveShape(shape); } // Otherwise, rerecognize the new version of the shape(s) else { _sketchRecognizer.recognize(shape, featureSketch); foreach (Sketch.Shape subshape in brokenOffShapes) { _sketchRecognizer.recognize(subshape, featureSketch); } } // Add shedded shape to the end of the list of broken off shapes brokenOffShapes.Add(newShape); return(brokenOffShapes); } }
private void menuStrokeInformation_Click(object sender, EventArgs e) { Sketch.Sketch sketch = sketchPanel.Sketch; FeatureSketch sketchFeatures = new FeatureSketch(ref sketch); Microsoft.Ink.Strokes selected = sketchPanel.InkSketch.Ink.Strokes; Microsoft.Ink.Stroke s = selected[selected.Count - 1]; Sketch.Substroke ss = sketchPanel.InkSketch.GetSketchSubstrokeByInkId(s.Id); StrokeInfoForm.strokeInfoForm sif = new StrokeInfoForm.strokeInfoForm(sketchFeatures.GetFeatureStrokeByStrokeGUID(ss.Id), sketchFeatures, s, ss); sif.Show(); }
public void TestParseSingleWire() { List <Sketch.Shape> modifiedShapes; // Make a single substroke into a wire Sketch.Substroke substroke = AddNewStroke(); Sketch.Shape wire = sketch.MakeNewShapeFromSubstroke(out modifiedShapes, substroke, Domain.LogicDomain.WIRE, 1); wire.Name = "wire_0"; Assert.IsFalse(parser.SuccessfullyParse(sketch), "parser should not be able to parse sketch with single wire"); }
/// <summary> /// Find the number of times substrokes 1 and 2 touch. /// </summary> /// <param name="stroke1">First substroke</param> /// <param name="stroke2">Second substroke</param> /// <returns>Number of times substrokes 1 and 2 touch.</returns> private static int Adjacent(Sketch.Substroke stroke1, Sketch.Substroke stroke2) { double totaldistance = 0; int count = 0; for (int i = 0; i < stroke1.PointsL.Count - 2; i++) { totaldistance += stroke1.Points[i].distance(stroke1.Points[i + 1]); count++; } for (int i = 0; i < stroke2.PointsL.Count - 2; i++) { totaldistance += stroke2.Points[i].distance(stroke2.Points[i + 1]); count++; } double avgDistance = totaldistance / count * 10; int numTouch = 0; foreach (Sketch.Point endpoint in stroke1.Endpoints) { foreach (Sketch.Point point in stroke2.Points) { if (endpoint.distance(point) < avgDistance) { numTouch++; break; } } } foreach (Sketch.Point endpoint in stroke2.Endpoints) { foreach (Sketch.Point point in stroke1.Points) { if (endpoint.distance(point) < avgDistance) { numTouch++; break; } } } foreach (Sketch.Point endpoint1 in stroke1.Endpoints) { foreach (Sketch.Point endpoint2 in stroke2.Endpoints) { if (endpoint1.distance(endpoint2) < avgDistance) { numTouch--; } } } return(numTouch); }
/// <summary> /// Applies a label to a group of substrokes. /// </summary> public override bool UnExecute() { List <Sketch.Shape> modifiedShapes; foreach (System.Windows.Ink.Stroke stroke in labeledStrokes) { stroke.DrawingAttributes.Color = labelColor; Sketch.Substroke sub = sketchPanel.InkSketch.GetSketchSubstrokeByInk(stroke); sketchPanel.InkSketch.Sketch.MakeNewShapeFromSubstroke(out modifiedShapes, sub, label); } return(true); }
/// <summary> /// Updates the cursor inside the selection box to display whether stylus down will move the strokes /// or remove a stroke /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void InkCanvas_StylusInAirMove(object sender, System.Windows.Input.StylusEventArgs e) { // If there are no strokes below us, use the automatic cursors. // Otherwise, use the pen cursor. System.Windows.Point point = e.GetPosition(sketchPanel.InkCanvas); Sketch.Substroke substrokeBelow = sketchPanel.InkSketch.Sketch.substrokeAtPoint(point.X, point.Y, SEARCH_RADIUS); if (substrokeBelow != null) { sketchPanel.UseCustomCursor = true; sketchPanel.Cursor = System.Windows.Input.Cursors.Pen; } }
/// <summary> /// Creates a Substroke from Microsoft point data /// </summary> /// <param name="stroke"></param> /// <returns></returns> static public Sketch.Substroke MakeSubstroke(Microsoft.Ink.Stroke stroke) { Sketch.Point[] SketchPoints = stripStroke(stroke); Sketch.XmlStructs.XmlShapeAttrs XmlAttrs = new Sketch.XmlStructs.XmlShapeAttrs(true); XmlAttrs.Time = SketchPoints[0].Time; XmlAttrs.Source = "InkOverlay"; XmlAttrs.PenHeight = stroke.DrawingAttributes.Height; XmlAttrs.PenTip = stroke.DrawingAttributes.PenTip.ToString(); XmlAttrs.PenWidth = stroke.DrawingAttributes.Width; XmlAttrs.Color = stroke.DrawingAttributes.Color.ToArgb(); Sketch.Substroke s = new Sketch.Substroke(SketchPoints, XmlAttrs); return(s); }
/// <summary> /// Removes a labeled shape from a Sketch. /// </summary> public override bool Execute() { bool success = false; foreach (Stroke stroke in labeledStrokes) { Sketch.Substroke sub = sketchPanel.InkSketch.GetSketchSubstrokeByInk(stroke); labeledShape = sub.RemoveLabel(label); if (this.labeledShape != null && this.labeledShape.Substrokes.Length == 0) { success = sketchPanel.InkSketch.Sketch.RemoveShape(this.labeledShape); } } return(success); }
private void Create2StrokeLR_new(Gate name, GatePart leftPart, GatePart rightPart) { if (m_InkOverlay.Ink.Strokes.Count != 2) { MessageBox.Show("Incorrect # of strokes present"); return; } Rectangle b0 = m_InkOverlay.Ink.Strokes[0].GetBoundingBox(); Rectangle b1 = m_InkOverlay.Ink.Strokes[1].GetBoundingBox(); Rectangle bLeft, bRight; Stroke msLeft, msRight; if (b0.Right < b1.Right) { msLeft = m_InkOverlay.Ink.Strokes[0]; msRight = m_InkOverlay.Ink.Strokes[1]; bLeft = b0; bRight = b1; } else { msLeft = m_InkOverlay.Ink.Strokes[1]; msRight = m_InkOverlay.Ink.Strokes[0]; bLeft = b1; bRight = b0; } Sketch.Substroke Left = m_Sketch.GetSketchSubstrokeByInkId(msLeft.Id); Sketch.Substroke Right = m_Sketch.GetSketchSubstrokeByInkId(msRight.Id); List <Sketch.Substroke> strokes = new List <Sketch.Substroke>(); Dictionary <Sketch.Substroke, GatePart> strokeInfo = new Dictionary <Sketch.Substroke, GatePart>(); strokes.Add(Left); strokeInfo.Add(Left, leftPart); strokes.Add(Right); strokeInfo.Add(Right, rightPart); Rectangle shapeBbox = m_InkOverlay.Ink.Strokes.GetBoundingBox(); SymbolInfo info = new SymbolInfo(new User("Tester"), name.ToString(), "Gate"); ImageTemplate complete = new ImageTemplate(strokes, strokeInfo, info); m_ImageTemplates.Add(complete); }
/// <summary> /// Converts a Sketch substroke into a Microsoft.Ink stroke. /// </summary> /// <param name="substroke">The Sketch substroke to convert</param> /// <param name="ink">A Microsoft.Ink Ink object</param> /// <returns>The desired ink stroke</returns> private Microsoft.Ink.Stroke convertToInk( Sketch.Substroke substroke, Microsoft.Ink.Ink ink) { int pointsCount = substroke.Points.Length; System.Drawing.Point[] inkPoints = new System.Drawing.Point[pointsCount]; // Convert the Sketch point format to Microsoft point format for (int i = 0; i < pointsCount; i++) { inkPoints[i] = new System.Drawing.Point( (int)(substroke.Points[i].X), (int)(substroke.Points[i].Y)); } return(ink.CreateStroke(inkPoints)); }
public void TestUpdateStrokeWithClassifiedStroke() { List <Sketch.Shape> modifiedShapes; // Add one stroke, classify it, and update it Stroke firstStroke = newStroke(); inkCanvasSketch.AddStroke(firstStroke); Sketch.Substroke oldSubstroke = inkCanvasSketch.GetSketchSubstrokeByInk(firstStroke); inkCanvasSketch.Sketch.MakeNewShapeFromSubstroke(out modifiedShapes, inkCanvasSketch.GetSketchSubstrokeByInk(firstStroke), Domain.LogicDomain.AND); inkCanvasSketch.UpdateInkStroke(firstStroke); Sketch.Substroke newSubstroke = inkCanvasSketch.GetSketchSubstrokeByInk(firstStroke); Assert.IsTrue(inkCanvasSketch.Sketch.CheckConsistency(), "sketch should be consistent after updating a stroke"); Assert.IsTrue(inkCanvasSketch.areDictionarySizesConsistent() == 1, "dictionary size should be 1 after updating the only stroke"); Assert.IsTrue(inkCanvasSketch.FeatureSketch.hasConsistentSubstrokes(), "after updating a stroke, data structures should be consistent"); Assert.IsTrue(inkCanvasSketch.InkCanvas.Strokes.Contains(firstStroke), "after updating a stroke, the inkcanvas should still contain it"); Assert.AreEqual(inkCanvasSketch.GetSketchSubstrokeByInk(firstStroke).ParentShape.Type, Domain.LogicDomain.AND, "updating should preserve shapes"); }
/// <summary> /// Applies a label to a group of substrokes. /// </summary> public override bool Execute() { // Add the new stroke to the sketch inkSketch.AddStroke(newStroke); // Update connections Sketch.Substroke newSubstroke = inkSketch.GetSketchSubstrokeByInk(newStroke); // If we're using on-the-fly recognition, the new substroke may already have a parent shape. Get rid of it! if (newSubstroke.ParentShape != null) { Sketch.Shape parent = newSubstroke.ParentShape; parent.RemoveSubstroke(newSubstroke); if (parent.SubstrokesL.Count == 0) { inkSketch.Sketch.RemoveShape(parent); } } changedShape.AddSubstroke(newSubstroke); oldLocation.ConnectedShape = changedShape; newSubstroke.Endpoints[0].ConnectedShape = changedShape; newSubstroke.Endpoints[1].ConnectedShape = shapeAtNewLoc; // Add the new wire to the old wire's shape inkSketch.Sketch.connectShapes(changedShape, changedShape); // wires connected to themselves indicates an internal connection inkSketch.Sketch.connectShapes(changedShape, shapeAtNewLoc); changedShape.AlreadyLabeled = true; // Pre-emptive merging! Helps us undo. if (newIsWire) { inkSketch.Sketch.mergeShapes(changedShape, shapeAtNewLoc); } // Regroup everything so highlighting/labels are correctly updated Handle(changedShape); Regroup(new List <Sketch.Shape> { changedShape }); return(true); }