Shape RecognizeBoxOrLines(DragState state, out bool potentialSelection) { // Okay so this is a rectangular recognizer that only sees things at // 45-degree angles. List <Section> sections1 = BreakIntoSections(state); List <Section> sections2 = new List <Section>(sections1); // Figure out if a box or a line string is a better interpretation EliminateTinySections(sections1, 10); LineOrArrow line = InterpretAsPolyline(state, sections1); Shape shape = line; // Conditions to detect a box: // 0. If both endpoints are anchored, a box cannot be formed. // continued below... EliminateTinySections(sections2, 10 + (int)(sections1.Sum(s => s.LengthPx) * 0.05)); if (line.ToAnchor == null || line.FromAnchor == null || line.FromAnchor.Equals(line.ToAnchor)) { shape = (Shape)TryInterpretAsBox(sections2, (line.FromAnchor ?? line.ToAnchor) != null, out potentialSelection) ?? line; } else { potentialSelection = false; } return(shape); }
private LineOrArrow InterpretAsPolyline(DragState state, List <Section> sections) { var shape = new LineOrArrow { Style = Control.LineStyle }; shape.FromAnchor = state.StartAnchor; LineSegmentT prevLine = new LineSegmentT(), curLine; for (int i = 0; i < sections.Count; i++) { int angleMod8 = sections[i].AngleMod8; var startSS = sections[i].StartSS; var endSS = sections[i].EndSS; Vector <float> vector = Mod8Vectors[angleMod8]; Vector <float> perpVector = vector.Rot90(); bool isStartLine = i == 0; bool isEndLine = i == sections.Count - 1; if (isStartLine) { if (shape.FromAnchor != null) { startSS = shape.FromAnchor.Point; } } if (isEndLine) { if ((shape.ToAnchor = Control.GetBestAnchor(endSS, angleMod8 + 4)) != null) { endSS = shape.ToAnchor.Point; } // Also consider forming a closed shape else if (shape.Points.Count > 1 && shape.Points[0].Sub(endSS).Length() <= DiagramControl.AnchorSnapDistance && Math.Abs(vector.Cross(shape.Points[1].Sub(shape.Points[0]))) > 0.001f) { endSS = shape.Points[0]; } } if (isStartLine) { curLine = startSS.To(startSS.Add(vector)); } else { curLine = endSS.Sub(vector).To(endSS); PointT?itsc = prevLine.ComputeIntersection(curLine, LineType.Infinite); if (itsc.HasValue) { startSS = itsc.Value; } } shape.Points.Add(startSS); if (isEndLine) { if (isStartLine) { Debug.Assert(shape.Points.Count == 1); var adjustedStart = startSS.ProjectOntoInfiniteLine(endSS.Sub(vector).To(endSS)); var adjustedEnd = endSS.ProjectOntoInfiniteLine(curLine); if (shape.FromAnchor != null) { if (shape.ToAnchor != null) { // Both ends anchored => do nothing, allow unusual angle } else { // Adjust endpoint to maintain angle endSS = adjustedEnd; } } else { if (shape.ToAnchor != null) { // End anchored only => alter start point shape.Points[0] = adjustedStart; } else { // Neither end anchored => use average line shape.Points[0] = startSS.To(adjustedStart).Midpoint(); endSS = endSS.To(adjustedEnd).Midpoint(); } } } shape.Points.Add(endSS); } prevLine = curLine; } shape.FromArrow = Control.FromArrow; shape.ToArrow = Control.ToArrow; return(shape); }
private LineOrArrow InterpretAsPolyline(DragState state, List<Section> sections) { var shape = new LineOrArrow { Style = Control.LineStyle }; shape.FromAnchor = state.StartAnchor; LineSegmentT prevLine = new LineSegmentT(), curLine; for (int i = 0; i < sections.Count; i++) { int angleMod8 = sections[i].AngleMod8; var startSS = sections[i].StartSS; var endSS = sections[i].EndSS; Vector<float> vector = Mod8Vectors[angleMod8]; Vector<float> perpVector = vector.Rot90(); bool isStartLine = i == 0; bool isEndLine = i == sections.Count - 1; if (isStartLine) { if (shape.FromAnchor != null) startSS = shape.FromAnchor.Point; } if (isEndLine) { if ((shape.ToAnchor = Control.GetBestAnchor(endSS, angleMod8 + 4)) != null) endSS = shape.ToAnchor.Point; // Also consider forming a closed shape else if (shape.Points.Count > 1 && shape.Points[0].Sub(endSS).Length() <= DiagramControl.AnchorSnapDistance && Math.Abs(vector.Cross(shape.Points[1].Sub(shape.Points[0]))) > 0.001f) endSS = shape.Points[0]; } if (isStartLine) curLine = startSS.To(startSS.Add(vector)); else { curLine = endSS.Sub(vector).To(endSS); PointT? itsc = prevLine.ComputeIntersection(curLine, LineType.Infinite); if (itsc.HasValue) startSS = itsc.Value; } shape.Points.Add(startSS); if (isEndLine) { if (isStartLine) { Debug.Assert(shape.Points.Count == 1); var adjustedStart = startSS.ProjectOntoInfiniteLine(endSS.Sub(vector).To(endSS)); var adjustedEnd = endSS.ProjectOntoInfiniteLine(curLine); if (shape.FromAnchor != null) { if (shape.ToAnchor != null) { // Both ends anchored => do nothing, allow unusual angle } else { // Adjust endpoint to maintain angle endSS = adjustedEnd; } } else { if (shape.ToAnchor != null) // End anchored only => alter start point shape.Points[0] = adjustedStart; else { // Neither end anchored => use average line shape.Points[0] = startSS.To(adjustedStart).Midpoint(); endSS = endSS.To(adjustedEnd).Midpoint(); } } } shape.Points.Add(endSS); } prevLine = curLine; } shape.FromArrow = Control.FromArrow; shape.ToArrow = Control.ToArrow; return shape; }