/* Determines whether the following stroke could be interpreted as * an edge (or edges) and if so, returns all the consecutive nodes that the * stroke has gone through in order. */ public static Nodes ifEdgeGetNodes(Stroke s, Graph g) { Point[] sPoints = s.GetPoints(); Nodes strokeHitNodes = new Nodes(); Node prev = null; for (int i = 0; i < sPoints.Length; i++) { for (int j = 0; j < g.Nodes.Length(); j++) { Node n = g.Nodes[j]; Rectangle r = n.Stroke.GetBoundingBox(); if (s.HitTest(n.CenterPoint, Math.Max(r.Width / 2, r.Height / 2)) && r.Contains(sPoints[i]) && !n.Equals(prev)) { strokeHitNodes.Add(n); prev = n; break; } } } //If stroke hit one or less nodes, it is clearly not an edge. if (strokeHitNodes.Length() < 2) { return(null); } return(strokeHitNodes); }
private void inkOverlay_SelectionResized(object sender, InkOverlaySelectionResizedEventArgs e) { if (this.InvokeRequired) { return; } Nodes selectedNodes = graph.Nodes.getNodes(inkOverlay.Selection); for (int i = 0; i < selectedNodes.Length(); i++) { Rectangle r = selectedNodes[i].Stroke.GetBoundingBox(); selectedNodes[i].CenterPoint = new Point(r.X + r.Width / 2, r.Y + r.Height / 2); } Invalidate(); }
//Renders each edge and node and also marks the home and destination nodes public void Render(InkOverlay i, Graphics g) { for (int j = 0; j < edges.Length(); j++) { edges[j].Render(i, g); } for (int j = 0; j < nodes.Length(); j++) { nodes[j].Render(i, g); if (nodes[j].Equals(home)) { g.DrawString("*", new Font("Arial", 30), new SolidBrush(Color.Green), StrokeManager.InkSpaceToPixelRect(i, g, nodes[j].Stroke.GetBoundingBox())); } else if (nodes[j].Equals(destination)) { g.DrawString("X", new Font("Arial", 14, FontStyle.Bold), new SolidBrush(Color.Red), StrokeManager.InkSpaceToPixelRect(i, g, nodes[j].Stroke.GetBoundingBox())); } } }
private void inkOverlay_Stroke(object sender, InkCollectorStrokeEventArgs e) { if (this.InvokeRequired) { return; } //in effect, this is reseting the timer to start from the beginning. edgeTimer.Stop(); edgeTimer.Start(); //Check if the stroke was a tap, and if it was, get the node it tapped. Node n = StrokeManager.TappedNode(e.Stroke, graph); if (n != null) { //If its eraser mode, delete it. if (inkOverlay.EditingMode == InkOverlayEditingMode.Delete) { graph.Remove(n); } else { //Any other mode, select it and change to selection mode int[] ids = { n.Stroke.Id }; selectionButton(sender, e); inkOverlay.Selection = e.Stroke.Ink.CreateStrokes(ids); } e.Stroke.Ink.DeleteStroke(e.Stroke); Invalidate(); return; } //The following code is for pen mode only strokes if (inkOverlay.EditingMode != InkOverlayEditingMode.Ink) { return; } //If a stroke is inside a node, store it in n n = StrokeManager.HitNodeTest(e.Stroke, graph); //If the stroke is closed and it's a start, assign a home or destination if (StrokeManager.isClosed(e.Stroke) && n != null && StrokeManager.isStar(e.Stroke)) { graph.AssignNode(n); RecognizeWeight(); //Attempt at recognizing weight is made after every stroke. } //If the stroke is closed and it is not enclosed in a node and is a circle, make a circular node else if (StrokeManager.isClosed(e.Stroke) && n == null && e.Stroke.PacketCount > StrokeManager.SMALLEST_N_SIZE && StrokeManager.FitsCircleProperties(e.Stroke)) { Stroke circle = StrokeManager.makeCircle(inkOverlay, e.Stroke); Node circleNode = new Node(circle); graph.Add(circleNode); RecognizeWeight(); } //If the stroke is close and it is not enclosed in a node and is a rectangle, make a rectangular node else if (StrokeManager.isClosed(e.Stroke) && n == null && e.Stroke.PacketCount > StrokeManager.SMALLEST_N_SIZE && StrokeManager.FitsRectProperties(e.Stroke)) { Stroke rect = StrokeManager.makeRect(inkOverlay, e.Stroke); Node rectNode = new Node(rect); graph.Add(rectNode); RecognizeWeight(); } //if the stroke isn't closed, then it is an edge. else if (!StrokeManager.isClosed(e.Stroke)) { //Get all the nodes hit by this stroke and create edges for them Nodes edgeNodes = StrokeManager.ifEdgeGetNodes(e.Stroke, graph); if (edgeNodes != null && !StrokeManager.isScratchOut(e.Stroke)) { for (int i = 0; i < edgeNodes.Length() - 1; i++) { if (!Edge.hasEdge(edgeNodes[i], edgeNodes[i + 1])) { Edge edge = new Edge(edgeNodes[i], edgeNodes[i + 1], inkOverlay); graph.Add(edge); } } } else if (StrokeManager.isScratchOut(e.Stroke)) { ArrayList objs = StrokeManager.HitObjects(e.Stroke, graph); for (int i = 0; i < objs.Count; i++) { graph.Remove(objs[i]); } } RecognizeWeight(); } else { //if all of the above fails, then the stroke is considered for edge weights Edge hitEdge = StrokeManager.HitEdgeTest(e.Stroke, graph); if (hitEdge != null) { /* if the edge hit is the same as the previous one, * accumulate strokes for it before recognizing, * if it's a different edge, then recognize and add this * stroke to the new edge. */ if (prevEdgeHit == null) { prevEdgeHit = hitEdge; } if (hitEdge.Equals(prevEdgeHit)) { myRecognizer.Strokes.Add(StrokeManager.CopyStroke(e.Stroke)); } else { RecognizeWeight(); prevEdgeHit = hitEdge; myRecognizer.Strokes.Add(StrokeManager.CopyStroke(e.Stroke)); } } } e.Stroke.Ink.DeleteStroke(e.Stroke); Invalidate(); }
/* Determines whether the following stroke could be interpreted as * an edge (or edges) and if so, returns all the consecutive nodes that the * stroke has gone through in order. */ public static Nodes ifEdgeGetNodes(Stroke s, Graph g) { Point[] sPoints = s.GetPoints(); Nodes strokeHitNodes = new Nodes(); Node prev = null; for(int i=0; i<sPoints.Length; i++) { for(int j=0; j<g.Nodes.Length(); j++) { Node n = g.Nodes[j]; Rectangle r = n.Stroke.GetBoundingBox(); if(s.HitTest(n.CenterPoint,Math.Max(r.Width/2, r.Height/2)) && r.Contains(sPoints[i]) && !n.Equals(prev)) { strokeHitNodes.Add(n); prev = n; break; } } } //If stroke hit one or less nodes, it is clearly not an edge. if(strokeHitNodes.Length() < 2) { return null; } return strokeHitNodes; }