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--; } } } } }
//If the result is true this method also sets the currently active edit point. public bool EditPointsHitTest(Point pt) { if (this.EditPoints.Count > 0) { foreach (EditPoint editPoint in this.EditPoints) { if (DesignerGeometryHelper.DistanceBetweenPoints(pt, editPoint.Location) <= EditPointHitTestRadius) { this.activeEditPoint = editPoint; return(true); } } } return(false); }
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { Visibility connectorLabelVisibility = Visibility.Collapsed; string labelText = values[0] as string; PointCollection connectorPoints = values[1] as PointCollection; if (!String.IsNullOrEmpty(labelText) && connectorPoints != null) { int maxSegmentStartPoint; if (DesignerGeometryHelper.LongestSegmentLength(connectorPoints, out maxSegmentStartPoint) > Connector.MinConnectorSegmentLengthForLabel) { connectorLabelVisibility = Visibility.Visible; } } return(connectorLabelVisibility); }
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)); } } }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { PathSegmentCollection retVal = new PathSegmentCollection(); PointCollection pointCollection = value as PointCollection; if (RoundRadius > 0) { if (pointCollection != null && pointCollection.Count > 0) { retVal.Add(new LineSegment(pointCollection[0], true)); double curSegmentArcUsed = 0; for (int i = 1; i < pointCollection.Count - 1; i++) { double dist1 = DesignerGeometryHelper.DistanceBetweenPoints(pointCollection[i - 1], pointCollection[i]); double dist2 = DesignerGeometryHelper.DistanceBetweenPoints(pointCollection[i], pointCollection[i + 1]); if (dist1 - curSegmentArcUsed > RoundRadius && dist2 > RoundRadius) { //build rounded arc at line join. curSegmentArcUsed = RoundRadius; Vector firstSegmentPointingVector = new Vector(pointCollection[i].X - pointCollection[i - 1].X, pointCollection[i].Y - pointCollection[i - 1].Y); Vector secondSegmentPointingVector = new Vector(pointCollection[i + 1].X - pointCollection[i].X, pointCollection[i + 1].Y - pointCollection[i].Y); firstSegmentPointingVector.Normalize(); secondSegmentPointingVector.Normalize(); Point turningPoint1 = Point.Add(pointCollection[i - 1], Vector.Multiply(dist1 - RoundRadius, firstSegmentPointingVector)); Point turningPoint2 = Point.Add(pointCollection[i], Vector.Multiply(RoundRadius, secondSegmentPointingVector)); double crossProductZ = firstSegmentPointingVector.X * secondSegmentPointingVector.Y - firstSegmentPointingVector.Y * secondSegmentPointingVector.X; retVal.Add(new LineSegment(turningPoint1, true)); retVal.Add(new ArcSegment(turningPoint2, new Size(RoundRadius, RoundRadius), 0, false, crossProductZ > 0 ? SweepDirection.Clockwise : SweepDirection.Counterclockwise, true)); } else { curSegmentArcUsed = 0; retVal.Add(new LineSegment(pointCollection[i], true)); } } retVal.Add(new LineSegment(pointCollection[pointCollection.Count - 1], true)); } } return(retVal); }
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { Thickness margin = new Thickness(0); PointCollection connectorPoints = values[0] as PointCollection; double labelBorderWidth = (double)values[1]; double labelBorderHeight = (double)values[2]; if (connectorPoints != null) { int longestSegmentIndex; DesignerGeometryHelper.LongestSegmentLength(connectorPoints, out longestSegmentIndex); if (longestSegmentIndex >= 0) { Point labelLocation = DesignerGeometryHelper.MidPointOfLineSegment(connectorPoints[longestSegmentIndex], connectorPoints[longestSegmentIndex + 1]); labelLocation.X = (int)(labelLocation.X - labelBorderWidth / 2 + EPS); labelLocation.Y = (int)(labelLocation.Y - labelBorderHeight / 2 + EPS); margin.Top = labelLocation.Y; margin.Left = labelLocation.X; } } return(margin); }
public static bool IsEqualTo(this Point point1, Point point2) { return(DesignerGeometryHelper.DistanceBetweenPoints(point1, point2) < DesignerGeometryHelper.EPS); }
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."); }
private void MeasureChildren(out double height, out double width) { height = 0; width = 0; Point pt = new Point(0, 0); bool isOutmostPanel = this.IsOutmostPanel(); foreach (UIElement child in Children) { Connector connectorChild = child as Connector; if (connectorChild != null && isOutmostPanel) { pt = new Point(0, 0); if (measureConnectors) { Point srcPoint = FreeFormPanel.GetLocationRelativeToOutmostPanel(FreeFormPanel.GetSourceConnectionPoint(connectorChild)); Point destPoint = FreeFormPanel.GetLocationRelativeToOutmostPanel(FreeFormPanel.GetDestinationConnectionPoint(connectorChild)); if (connectorChild.Points.Count == 0 || (DesignerGeometryHelper.DistanceBetweenPoints(connectorChild.Points[0], srcPoint) > 1) || (DesignerGeometryHelper.DistanceBetweenPoints(connectorChild.Points[connectorChild.Points.Count - 1], destPoint) > 1)) { connectorChild.Points = new PointCollection(); RoutePolyLine(connectorChild); } connectorChild.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); } else { continue; } } else //Measure non-connector elements. { child.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); if (!child.DesiredSize.Equals(((Size)FreeFormPanel.GetChildSize(child)))) { FreeFormPanel.SetChildSize(child, child.DesiredSize); } pt = FreeFormPanel.GetLocation(child); if (pt.X == 0 && pt.Y == 0) { pt = new Point(LeftStackingMargin, lastYPosition); OnLocationChanged(child, new LocationChangedEventArgs(pt)); FreeFormPanel.SetLocation(child, pt); lastYPosition += child.DesiredSize.Height + VerticalStackingDistance; } } if (height < child.DesiredSize.Height + pt.Y) { height = child.DesiredSize.Height + pt.Y; } if (width < child.DesiredSize.Width + pt.X) { width = child.DesiredSize.Width + pt.X; } } width = (width < this.MinWidth) ? this.MinWidth : width; height = (height < this.MinHeight) ? this.MinHeight : height; }