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); }
internal static Point CalculateDropLocation(Point mousePosition, Point originalDropLocation, Size droppedSize, Point srcLocation, Point destLocation, Size srcSize, Size destSize, HashSet <Point> shapeLocations) { Point dropLocation = originalDropLocation; double distToSrc = DesignerGeometryHelper.ManhattanDistanceBetweenPoints(mousePosition, new Point(srcLocation.X + (srcSize.Width / 2), srcLocation.Y + (srcSize.Height / 2))); double distToDest = DesignerGeometryHelper.ManhattanDistanceBetweenPoints(mousePosition, new Point(destLocation.X + (destSize.Width / 2), destLocation.Y + (destSize.Height / 2))); AutoSplitAlignment srcAlignment = GetAlignment(mousePosition, srcLocation, srcSize); AutoSplitAlignment destAlignment = GetAlignment(mousePosition, destLocation, destSize); if ((distToSrc <= distToDest || destAlignment == AutoSplitAlignment.None) && srcAlignment == AutoSplitAlignment.Vertical) { dropLocation = CalculateDropLocationToAlignVertically(dropLocation, droppedSize, srcLocation, srcSize); } else if ((distToSrc <= distToDest || destAlignment == AutoSplitAlignment.None) && srcAlignment == AutoSplitAlignment.Horizontal) { dropLocation = CalculateDropLocationToAlignHorizontally(dropLocation, droppedSize, srcLocation, srcSize); } else if ((distToSrc >= distToDest || srcAlignment == AutoSplitAlignment.None) && destAlignment == AutoSplitAlignment.Vertical) { dropLocation = CalculateDropLocationToAlignVertically(dropLocation, droppedSize, destLocation, destSize); } else if ((distToSrc >= distToDest || srcAlignment == AutoSplitAlignment.None) && destAlignment == AutoSplitAlignment.Horizontal) { dropLocation = CalculateDropLocationToAlignHorizontally(dropLocation, droppedSize, destLocation, destSize); } dropLocation.X = dropLocation.X < 0 ? 0 : dropLocation.X; dropLocation.Y = dropLocation.Y < 0 ? 0 : dropLocation.Y; // To avoid overlaps with existing shapes if (shapeLocations != null) { while (shapeLocations.Contains(dropLocation)) { dropLocation.Offset(FreeFormPanel.GridSize, FreeFormPanel.GridSize); } } return(dropLocation); }
public static ConnectionPoint GetClosestConnectionPoint(List <ConnectionPoint> connectionPoints, Point refPoint, out double minDist) { minDist = double.PositiveInfinity; if (connectionPoints == null || connectionPoints.Count == 0) { return(null); } double dist = 0; ConnectionPoint closestPoint = null; foreach (ConnectionPoint point in connectionPoints) { dist = DesignerGeometryHelper.DistanceBetweenPoints(refPoint, point.Location); if (dist < minDist) { minDist = dist; closestPoint = point; } } return(closestPoint); }
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { Thickness margin = new Thickness(0); PointCollection connectorPoints = values[0] as PointCollection; // 8 and 4 is calcuated from the margin / padding settings related to the label in xaml double labelBorderWidth = (double)values[1] + 8; double labelBorderHeight = (double)values[2] + 4; 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); }
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 || !this.Disabled && ((DesignerGeometryHelper.ManhattanDistanceBetweenPoints(connectorChild.Points[0], srcPoint) > ConnectorRouter.EndPointTolerance) || (DesignerGeometryHelper.ManhattanDistanceBetweenPoints(connectorChild.Points[connectorChild.Points.Count - 1], destPoint) > ConnectorRouter.EndPointTolerance))) { 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 (!IsLocationValid(pt)) { 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; }
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) { Fx.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) { Fx.Assert(this.editPoints[0].Type == EditPoint.EditPointTypes.ConnectionEditPoint, "EditPoint type is wrong."); Fx.Assert(this.editPoints[editPoints.Count - 1].Type == EditPoint.EditPointTypes.ConnectionEditPoint, "EditPoint type is wrong."); this.activeEditPoint.Location = newPoint; Fx.Assert(this.editPoints.Count > 0, "Some edit point should exist"); ConnectionPoint targetConnPt = null; Point[] points = null; Point begin = this.editPoints[0].Location; Point end = this.editPoints[this.editPoints.Count - 1].Location; if (typeof(ConnectionPointsAdorner).IsAssignableFrom(Mouse.DirectlyOver.GetType())) { ConnectionPointsAdorner connPtsAdorner = Mouse.DirectlyOver as ConnectionPointsAdorner; targetConnPt = FreeFormPanel.ConnectionPointHitTest(newPoint, connPtsAdorner); } if (activeEditPointIndex == 0) { // We are dragging the source point of a connector. ConnectionPoint destConnPt = FreeFormPanel.GetDestinationConnectionPoint(this.editedConnector); if (targetConnPt != null) { points = ConnectorRouter.Route(parentPanel, targetConnPt, destConnPt); this.activeEditPoint.Location = targetConnPt.Location; } else { points = ConnectorRouter.Route(parentPanel, begin, destConnPt); } } else { // We are dragging the destination point of a connector. ConnectionPoint srcConnPt = FreeFormPanel.GetSourceConnectionPoint(this.editedConnector); if (targetConnPt != null) { points = ConnectorRouter.Route(parentPanel, srcConnPt, targetConnPt); this.activeEditPoint.Location = targetConnPt.Location; } else { points = ConnectorRouter.Route(parentPanel, srcConnPt, end); } } //When we start editing the end point we need to clear the slate and start over List <EditPoint> newEditPoints = new List <EditPoint>(); 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 { Fx.Assert(false, "Should not be here. UpdateEditPoints failed."); } } } // Remove all the redundant edit points RemoveCoincidingEditPoints(); bool validEditPoints = ValidateEditPoints(); Fx.Assert(validEditPoints, "Validating EditPoints failed."); }