/// <summary> /// Create and apply edge path using calculated ER parameters stored in edge /// </summary> /// <param name="useCurrentCoords">Use current vertices coordinates or final coorfinates (for.ex if move animation is active final coords will be its destination)</param> /// <param name="externalRoutingPoints">Provided custom routing points will be used instead of stored ones.</param> /// <param name="updateLabel">Should edge label be updated in this pass</param> public virtual void PrepareEdgePath(bool useCurrentCoords = false, Measure.Point[] externalRoutingPoints = null, bool updateLabel = true) { //do not calculate invisible edges if ((Visibility != Visibility.Visible && !IsHiddenEdgesUpdated) && Source == null || Target == null || ManualDrawing || !IsTemplateLoaded) { return; } #region Get the inputs //get the size of the source var sourceSize = new Size { Width = Source.ActualWidth, Height = Source.ActualHeight }; if (CustomHelper.IsInDesignMode(this)) { sourceSize = new Size(80, 20); } //get the position center of the source var sourcePos = new Point { X = (useCurrentCoords ? GraphAreaBase.GetX(Source) : GraphAreaBase.GetFinalX(Source)) + sourceSize.Width * .5, Y = (useCurrentCoords ? GraphAreaBase.GetY(Source) : GraphAreaBase.GetFinalY(Source)) + sourceSize.Height * .5 }; //get the size of the target var targetSize = new Size { Width = Target.ActualWidth, Height = Target.ActualHeight }; if (CustomHelper.IsInDesignMode(this)) { targetSize = new Size(80, 20); } //get the position center of the target var targetPos = new Point { X = (useCurrentCoords ? GraphAreaBase.GetX(Target) : GraphAreaBase.GetFinalX(Target)) + targetSize.Width * .5, Y = (useCurrentCoords ? GraphAreaBase.GetY(Target) : GraphAreaBase.GetFinalY(Target)) + targetSize.Height * .5 }; var routedEdge = Edge as IRoutingInfo; if (routedEdge == null) { throw new GX_InvalidDataException("Edge must implement IRoutingInfo interface"); } //get the route informations var routeInformation = externalRoutingPoints ?? routedEdge.RoutingPoints; // Get the TopLeft position of the Source Vertex. var sourcePos1 = new Point { X = (useCurrentCoords ? GraphAreaBase.GetX(Source) : GraphAreaBase.GetFinalX(Source)), Y = (useCurrentCoords ? GraphAreaBase.GetY(Source) : GraphAreaBase.GetFinalY(Source)) }; // Get the TopLeft position of the Target Vertex. var targetPos1 = new Point { X = (useCurrentCoords ? GraphAreaBase.GetX(Target) : GraphAreaBase.GetFinalX(Target)), Y = (useCurrentCoords ? GraphAreaBase.GetY(Target) : GraphAreaBase.GetFinalY(Target)) }; var hasEpSource = EdgePointerForSource != null; var hasEpTarget = EdgePointerForTarget != null; #endregion //if self looped edge if (IsSelfLooped) { PrepareSelfLoopedEdge(sourcePos1); return; } //check if we have some edge route data var hasRouteInfo = routeInformation != null && routeInformation.Length > 1; //calculate source and target edge attach points if (RootArea != null && !hasRouteInfo && RootArea.EnableParallelEdges && ParallelEdgeOffset != 0) { sourcePos = GetParallelOffset(Source, Target, ParallelEdgeOffset); targetPos = GetParallelOffset(Target, Source, -ParallelEdgeOffset); } /* Rectangular shapes implementation by bleibold */ var gEdge = Edge as IGraphXCommonEdge; Point p1; Point p2; //calculate edge source (p1) and target (p2) endpoints based on different settings if (gEdge?.SourceConnectionPointId != null) { var sourceCp = Source.GetConnectionPointById(gEdge.SourceConnectionPointId.Value, true); if (sourceCp == null) { throw new GX_ObjectNotFoundException(string.Format("Can't find source vertex VCP by edge source connection point Id({1}) : {0}", Source, gEdge.SourceConnectionPointId)); } if (sourceCp.Shape == VertexShape.None) { p1 = sourceCp.RectangularSize.Center(); } else { var targetCpPos = gEdge.TargetConnectionPointId.HasValue ? Target.GetConnectionPointById(gEdge.TargetConnectionPointId.Value, true).RectangularSize.Center() : (hasRouteInfo ? routeInformation[1].ToWindows() : (targetPos)); p1 = GeometryHelper.GetEdgeEndpoint(sourceCp.RectangularSize.Center(), sourceCp.RectangularSize, targetCpPos, sourceCp.Shape); } } else { p1 = GeometryHelper.GetEdgeEndpoint(sourcePos, new SysRect(sourcePos1, sourceSize), (hasRouteInfo ? routeInformation[1].ToWindows() : (targetPos)), Source.VertexShape); } if (gEdge?.TargetConnectionPointId != null) { var targetCp = Target.GetConnectionPointById(gEdge.TargetConnectionPointId.Value, true); if (targetCp == null) { throw new GX_ObjectNotFoundException(string.Format("Can't find target vertex VCP by edge target connection point Id({1}) : {0}", Target, gEdge.TargetConnectionPointId)); } if (targetCp.Shape == VertexShape.None) { p2 = targetCp.RectangularSize.Center(); } else { var sourceCpPos = gEdge.SourceConnectionPointId.HasValue ? Source.GetConnectionPointById(gEdge.SourceConnectionPointId.Value, true).RectangularSize.Center() : hasRouteInfo ? routeInformation[routeInformation.Length - 2].ToWindows() : (sourcePos); p2 = GeometryHelper.GetEdgeEndpoint(targetCp.RectangularSize.Center(), targetCp.RectangularSize, sourceCpPos, targetCp.Shape); } } else { p2 = GeometryHelper.GetEdgeEndpoint(targetPos, new SysRect(targetPos1, targetSize), hasRouteInfo ? routeInformation[routeInformation.Length - 2].ToWindows() : (sourcePos), Target.VertexShape); } SourceConnectionPoint = p1; TargetConnectionPoint = p2; Linegeometry = new PathGeometry(); PathFigure lineFigure; //if we have route and route consist of 2 or more points if (RootArea != null && hasRouteInfo) { //replace start and end points with accurate ones var routePoints = routeInformation.ToWindows().ToList(); routePoints.Remove(routePoints.First()); routePoints.Remove(routePoints.Last()); routePoints.Insert(0, p1); routePoints.Add(p2); if (externalRoutingPoints == null && routedEdge.RoutingPoints != null) { routedEdge.RoutingPoints = routePoints.ToArray().ToGraphX(); } if (RootArea.EdgeCurvingEnabled) { var oPolyLineSegment = GeometryHelper.GetCurveThroughPoints(routePoints.ToArray(), 0.5, RootArea.EdgeCurvingTolerance); if (hasEpTarget) { UpdateTargetEpData(oPolyLineSegment.Points[oPolyLineSegment.Points.Count - 1], oPolyLineSegment.Points[oPolyLineSegment.Points.Count - 2]); oPolyLineSegment.Points.RemoveAt(oPolyLineSegment.Points.Count - 1); } if (hasEpSource) { UpdateSourceEpData(oPolyLineSegment.Points.First(), oPolyLineSegment.Points[1]); oPolyLineSegment.Points.RemoveAt(0); } lineFigure = GeometryHelper.GetPathFigureFromPathSegments(routePoints[0], true, true, oPolyLineSegment); #if WPF //freeze and create resulting geometry GeometryHelper.TryFreeze(oPolyLineSegment); #endif } else { if (hasEpSource) { routePoints[0] = routePoints[0].Subtract(UpdateSourceEpData(routePoints.First(), routePoints[1])); } if (hasEpTarget) { routePoints[routePoints.Count - 1] = routePoints[routePoints.Count - 1].Subtract(UpdateTargetEpData(p2, routePoints[routePoints.Count - 2])); } // Reverse the path if specified. if (gEdge.ReversePath) { routePoints.Reverse(); } var pcol = new PointCollection(); routePoints.ForEach(a => pcol.Add(a)); lineFigure = new PathFigure { StartPoint = p1, Segments = new PathSegmentCollection { new PolyLineSegment { Points = pcol } }, IsClosed = false }; } } else // no route defined { bool allowUpdateEpDataToUnsuppress = true; //check for hide only if prop is not 0 if (HideEdgePointerByEdgeLength != 0d) { if (MathHelper.GetDistanceBetweenPoints(p1, p2) <= HideEdgePointerByEdgeLength) { EdgePointerForSource?.Suppress(); EdgePointerForTarget?.Suppress(); allowUpdateEpDataToUnsuppress = false; } else { EdgePointerForSource?.UnSuppress(); EdgePointerForTarget?.UnSuppress(); } } if (hasEpSource) { p1 = p1.Subtract(UpdateSourceEpData(p1, p2, allowUpdateEpDataToUnsuppress)); } if (hasEpTarget) { p2 = p2.Subtract(UpdateTargetEpData(p2, p1, allowUpdateEpDataToUnsuppress)); } lineFigure = new PathFigure { StartPoint = gEdge.ReversePath ? p2 : p1, Segments = new PathSegmentCollection { new LineSegment() { Point = gEdge.ReversePath ? p1 : p2 } }, IsClosed = false }; } ((PathGeometry)Linegeometry).Figures.Add(lineFigure); #if WPF GeometryHelper.TryFreeze(lineFigure); GeometryHelper.TryFreeze(Linegeometry); #endif if (ShowLabel && EdgeLabelControl != null && _updateLabelPosition && updateLabel) { EdgeLabelControl.UpdatePosition(); } }
private Point UpdateTargetEpData(Point from, Point to, bool allowUnsuppress = true) { var dir = MathHelper.GetDirection(from, to); if (from == to) { if (HideEdgePointerOnVertexOverlap) { EdgePointerForTarget.Suppress(); } else { dir = new Vector(0, 0); } } else if (allowUnsuppress) { EdgePointerForTarget.UnSuppress(); } var result = EdgePointerForTarget.Update(from, dir, EdgePointerForTarget.NeedRotation ? (-MathHelper.GetAngleBetweenPoints(from, to).ToDegrees()) : 0); return(EdgePointerForTarget.Visibility == Visibility.Visible ? result : new Point()); }