void RemoveEditPointSegmentsWithinTolerance(List <EditPoint> pointsToRetain) { for (int i = 1; i < this.editPoints.Count - 1; i++) { EditPoint previous = this.editPoints[i - 1]; EditPoint current = this.editPoints[i]; EditPoint next = this.editPoints[i + 1]; if (pointsToRetain == null || !pointsToRetain.Contains(current)) { double distance = DesignerGeometryHelper.DistanceOfLineSegments(new Point[] { previous.Location, current.Location }); if (distance < ConnectorEditor.EditPointRadius && next.Type == EditPoint.EditPointTypes.MultiSegmentEditPoint) { double slope = DesignerGeometryHelper.SlopeOfLineSegment(current.Location, next.Location); next.Location = (slope < 1) ? new Point(next.Location.X, previous.Location.Y) : new Point(previous.Location.X, next.Location.Y); this.editPoints.Remove(current); i -= 1; } else { distance = DesignerGeometryHelper.DistanceOfLineSegments(new Point[] { current.Location, next.Location }); if (distance < ConnectorEditor.EditPointRadius && previous.Type == EditPoint.EditPointTypes.MultiSegmentEditPoint) { double slope = DesignerGeometryHelper.SlopeOfLineSegment(previous.Location, current.Location); previous.Location = (slope < 1) ? new Point(previous.Location.X, next.Location.Y) : new Point(next.Location.X, previous.Location.Y); this.editPoints.Remove(current); i--; } } } } }
void RemoveCoincidingEditPoints(List <EditPoint> pointsToRetain) { for (int i = 1; i < this.EditPoints.Count - 1; i++) { EditPoint current = this.EditPoints[i]; if (pointsToRetain == null || !pointsToRetain.Contains(current)) { EditPoint previous = this.EditPoints[i - 1]; EditPoint next = this.EditPoints[i + 1]; double slope1 = DesignerGeometryHelper.SlopeOfLineSegment(previous.Location, current.Location); double slope2 = DesignerGeometryHelper.SlopeOfLineSegment(current.Location, next.Location); if (Math.Abs(slope1) == Math.Abs(slope2)) { this.EditPoints.Remove(current); i -= 1; } } } }
//Remove points with the same slope void RemoveCoincidingEditPoints() { if (this.editPoints.Count < 2 || this.editPoints[0].Type != EditPoint.EditPointTypes.ConnectionEditPoint || this.editPoints[this.editPoints.Count - 1].Type != EditPoint.EditPointTypes.ConnectionEditPoint || (this.activeEditPoint != null && this.activeEditPoint.Type == EditPoint.EditPointTypes.ConnectionEditPoint)) { return; } //Create list of points to retain List <EditPoint> editPointsToRetain = new List <EditPoint>(this.editPoints.Count); for (int i = 0; i < this.editPoints.Count; i++) { if (this.editPoints[i].Type != EditPoint.EditPointTypes.MultiSegmentEditPoint || this.editPoints[i] == this.activeEditPoint) { editPointsToRetain.Add(this.editPoints[i]); } } //Step1: Get rid of all the line segments which are within tolerance range RemoveEditPointSegmentsWithinTolerance(editPointsToRetain); //Step2: We should make sure that the active edit point is always retained but those points which are coincidental are always removed RemoveCoincidingEditPoints(editPointsToRetain); //Step3: Go through each segment and ensure that all the segments are either vertical or horizontal for (int i = 0; i < this.editPoints.Count - 1; i++) { EditPoint current = this.editPoints[i]; EditPoint next = this.editPoints[i + 1]; double slope = DesignerGeometryHelper.SlopeOfLineSegment(current.Location, next.Location); if (slope != 0 && slope != double.MaxValue) { Point location = (slope < 1) ? new Point(next.Location.X, current.Location.Y) : new Point(current.Location.X, next.Location.Y); this.editPoints.Insert(i + 1, new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, location)); } } }
void UpdateEditPoints(Point newPoint) { if (this.editPoints.Count < 2 || this.editPoints[0].Type != EditPoint.EditPointTypes.ConnectionEditPoint || this.editPoints[this.editPoints.Count - 1].Type != EditPoint.EditPointTypes.ConnectionEditPoint) { Debug.Assert(false, "EditPoints are invalid"); return; } if (this.activeEditPoint != null) { int activeEditPointIndex = this.editPoints.IndexOf(this.activeEditPoint); EditPoint previous = (activeEditPointIndex > 0) ? this.editPoints[activeEditPointIndex - 1] : null; EditPoint next = (activeEditPointIndex < this.editPoints.Count - 1) ? this.editPoints[activeEditPointIndex + 1] : null; //Note that extra edit points are only added if we are connected to connection point if (previous != null && previous.Type == EditPoint.EditPointTypes.ConnectionEditPoint) { double slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(previous.Location, this.activeEditPoint.Location); Orientation orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; int editPointOffset = Convert.ToInt32(DesignerGeometryHelper.DistanceBetweenPoints(previous.Location, (next != null) ? next.Location : this.activeEditPoint.Location)) / 4; if (orientation == Orientation.Horizontal) { editPointOffset *= (previous.Location.X < this.activeEditPoint.Location.X) ? 1 : -1; } else { editPointOffset *= (previous.Location.Y < this.activeEditPoint.Location.Y) ? 1 : -1; } activeEditPointIndex = this.editPoints.IndexOf(this.activeEditPoint); Point editPointLocation = (orientation == Orientation.Horizontal) ? new Point(previous.Location.X + editPointOffset, previous.Location.Y) : new Point(previous.Location.X, previous.Location.Y + editPointOffset); previous = new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation); this.editPoints.InsertRange(activeEditPointIndex, new EditPoint[] { new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation), previous }); } if (next != null && next.Type == EditPoint.EditPointTypes.ConnectionEditPoint) { double slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(this.activeEditPoint.Location, next.Location); Orientation orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; int editPointOffset = Convert.ToInt32(DesignerGeometryHelper.DistanceBetweenPoints((previous != null) ? previous.Location : this.activeEditPoint.Location, next.Location)) / 4; if (orientation == Orientation.Horizontal) { editPointOffset *= (this.activeEditPoint.Location.X < next.Location.X) ? -1 : 1; } else { editPointOffset *= (this.activeEditPoint.Location.Y < next.Location.Y) ? -1 : 1; } activeEditPointIndex = this.editPoints.IndexOf(this.activeEditPoint); Point editPointLocation = (orientation == Orientation.Horizontal) ? new Point(next.Location.X + editPointOffset, next.Location.Y) : new Point(next.Location.X, next.Location.Y + editPointOffset); next = new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation); this.editPoints.InsertRange(activeEditPointIndex + 1, new EditPoint[] { next, new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation) }); } if (this.activeEditPoint.Type == EditPoint.EditPointTypes.ConnectionEditPoint) { Debug.Assert(this.editPoints[0].Type == EditPoint.EditPointTypes.ConnectionEditPoint, "EditPoint type is wrong."); Debug.Assert(this.editPoints[editPoints.Count - 1].Type == EditPoint.EditPointTypes.ConnectionEditPoint, "EditPoint type is wrong."); this.activeEditPoint.Location = newPoint; Point begin, end; Debug.Assert(this.editPoints.Count > 0, "Some edit point should exist"); begin = this.editPoints[0].Location; end = this.editPoints[this.editPoints.Count - 1].Location; //When we start editing the end point we need to clear the slate and start over List <EditPoint> newEditPoints = new List <EditPoint>(); Point[] points = ConnectorRouter.Route(parentPanel, begin, end); if (points != null && points.Length > 1) { RemoveEditPoints(EditPoint.EditPointTypes.MultiSegmentEditPoint); for (int i = 1; i < points.Length - 1; ++i) { newEditPoints.Add(new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, points[i])); } this.editPoints.InsertRange(1, newEditPoints.ToArray()); } } else if (this.activeEditPoint.Type == EditPoint.EditPointTypes.MultiSegmentEditPoint) { if (previous != null && previous.Type != EditPoint.EditPointTypes.ConnectionEditPoint && next != null && next.Type != EditPoint.EditPointTypes.ConnectionEditPoint) { //Update the previous point double slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(previous.Location, this.activeEditPoint.Location); Orientation orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; previous.Location = (orientation == Orientation.Horizontal) ? new Point(previous.Location.X, newPoint.Y) : new Point(newPoint.X, previous.Location.Y); //Update the next point slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(this.activeEditPoint.Location, next.Location); orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; next.Location = (orientation == Orientation.Horizontal) ? new Point(next.Location.X, newPoint.Y) : new Point(newPoint.X, next.Location.Y); //Update the current point this.activeEditPoint.Location = newPoint; } else { Debug.Assert(false, "Should not be here. UpdateEditPoints failed."); } } } // Remove all the redundant edit points RemoveCoincidingEditPoints(); bool validEditPoints = ValidateEditPoints(); Debug.Assert(validEditPoints, "Validating EditPoints failed."); }