private static void UpdateCoordinates(DependencyObject obj, double horizontalChange, double verticalChange) { if (double.IsNaN(GraphAreaBase.GetX(obj))) { GraphAreaBase.SetX(obj, 0, true); } if (double.IsNaN(GraphAreaBase.GetY(obj))) { GraphAreaBase.SetY(obj, 0, true); } //move the object var x = GraphAreaBase.GetX(obj) + horizontalChange; GraphAreaBase.SetX(obj, x, true); var y = GraphAreaBase.GetY(obj) + verticalChange; GraphAreaBase.SetY(obj, y, true); if (GetUpdateEdgesOnMove(obj)) { UpdateVertexEdges(obj as VertexControl); } }
/// <summary> /// Get control position on the GraphArea panel in attached coords X and Y /// </summary> /// <param name="final"></param> /// <param name="round"></param> public Point GetPosition(bool final = false, bool round = false) { return(round ? new Point(final ? (int)GraphAreaBase.GetFinalX(this) : (int)GraphAreaBase.GetX(this), final ? (int)GraphAreaBase.GetFinalY(this) : (int)GraphAreaBase.GetY(this)) : new Point(final ? GraphAreaBase.GetFinalX(this) : GraphAreaBase.GetX(this), final ? GraphAreaBase.GetFinalY(this) : GraphAreaBase.GetY(this))); }
/// <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 void PrepareEdgePath(bool useCurrentCoords = false, Point[] externalRoutingPoints = null, bool updateLabel = true) { //do not calculate invisible edges if ((Visibility != Visibility.Visible && !IsHiddenEdgesUpdated) && Source == null || Target == null || ManualDrawing) { return; } var template = Template; if (template != null) { #region Get the inputs //get the size of the source var sourceSize = new Size { Width = Source.ActualWidth, Height = Source.ActualHeight }; if (DesignerProperties.GetIsInDesignMode(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 (DesignerProperties.GetIsInDesignMode(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 }; //get the route informations var routeInformation = externalRoutingPoints == null ? (Edge as IRoutingInfo).RoutingPoints : externalRoutingPoints; #endregion // 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)) }; //if self looped edge if (IsSelfLooped) { if (!RootArea.EdgeShowSelfLooped) { return; } var pt = new Point(sourcePos1.X + RootArea.EdgeSelfLoopCircleOffset.X - RootArea.EdgeSelfLoopCircleRadius, sourcePos1.Y + RootArea.EdgeSelfLoopCircleOffset.X - RootArea.EdgeSelfLoopCircleRadius); var geo = new EllipseGeometry(pt, RootArea.EdgeSelfLoopCircleRadius, RootArea.EdgeSelfLoopCircleRadius); const double dArrowAngle = Math.PI / 2.0; _arrowgeometry = new PathGeometry(); var aPoint = sourcePos1; _arrowgeometry.Figures.Add(GeometryHelper.GenerateArrow(aPoint, new Point(), new Point(), dArrowAngle)); _linegeometry = geo; GeometryHelper.TryFreeze(_arrowgeometry); GeometryHelper.TryFreeze(_linegeometry); return; } var hasRouteInfo = routeInformation != null && routeInformation.Length > 1; //calculate source and target edge attach points if (RootArea != null && !hasRouteInfo && RootArea.EnableParallelEdges) { if (SourceOffset != 0) { sourcePos = GetParallelOffset(Source, Target, SourceOffset); } if (TargetOffset != 0) { targetPos = GetParallelOffset(Target, Source, TargetOffset); } } /* Rectangular shapes implementation by bleibold */ //Point p1 = GeometryHelper.GetEdgeEndpoint(sourcePos, new Rect(sourceSize), (hasRouteInfo ? routeInformation[1] : (targetPos)), Source.MathShape); //Point p2 = GeometryHelper.GetEdgeEndpoint(targetPos, new Rect(targetSize), hasRouteInfo ? routeInformation[routeInformation.Length - 2] : (sourcePos), Target.MathShape); var p1 = GeometryHelper.GetEdgeEndpoint(sourcePos, new Rect(sourcePos1, sourceSize), (hasRouteInfo ? routeInformation[1] : (targetPos)), Source.MathShape); var p2 = GeometryHelper.GetEdgeEndpoint(targetPos, new Rect(targetPos1, targetSize), hasRouteInfo ? routeInformation[routeInformation.Length - 2] : (sourcePos), Target.MathShape); _linegeometry = new PathGeometry(); PathFigure lineFigure; _arrowgeometry = new PathGeometry(); PathFigure arrowFigure; //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.ToList(); routePoints.Remove(routePoints.First()); routePoints.Remove(routePoints.Last()); routePoints.Insert(0, p1); routePoints.Add(p2); if (RootArea.EdgeCurvingEnabled) { var oPolyLineSegment = GeometryHelper.GetCurveThroughPoints(routePoints.ToArray(), 0.5, RootArea.EdgeCurvingTolerance); lineFigure = GeometryHelper.GetPathFigureFromPathSegments(routePoints[0], true, true, oPolyLineSegment); //get two last points of curved path to generate correct arrow var cLast = oPolyLineSegment.Points.Last(); var cPrev = oPolyLineSegment.Points[oPolyLineSegment.Points.Count - 2]; arrowFigure = GeometryHelper.GenerateOldArrow(cPrev, cLast); //freeze and create resulting geometry GeometryHelper.TryFreeze(oPolyLineSegment); } else { lineFigure = new PathFigure(p1, new PathSegment[] { new PolyLineSegment(routePoints, true) }, false); arrowFigure = GeometryHelper.GenerateOldArrow(routePoints[routePoints.Count - 2], p2); } } else // no route defined { //!!! Here is the line calculation to not overlap an arrowhead //Vector v = p1 - p2; v = v / v.Length * 5; // Vector n = new Vector(-v.Y, v.X) * 0.7; //segments[0] = new LineSegment(p2 + v, true); lineFigure = new PathFigure(p1, new PathSegment[] { new LineSegment(p2, true) }, false); arrowFigure = GeometryHelper.GenerateOldArrow(p1, p2); } GeometryHelper.TryFreeze(lineFigure); (_linegeometry as PathGeometry).Figures.Add(lineFigure); if (arrowFigure != null) { GeometryHelper.TryFreeze(arrowFigure); _arrowgeometry.Figures.Add(arrowFigure); } GeometryHelper.TryFreeze(_linegeometry); GeometryHelper.TryFreeze(_arrowgeometry); if (ShowLabel && _edgeLabelControl != null && _updateLabelPosition && updateLabel) { _edgeLabelControl.UpdatePosition(); } //PathGeometry = (PathGeometry)_linegeometry; } else { Debug.WriteLine("PrepareEdgePath() -> Edge template not found! Can't apply path to display edge!"); } }
/// <summary> /// Get control position on the GraphArea panel in attached coords X and Y /// </summary> /// <param name="offset">Return visual offset relative to parent host instead of coordinates</param> public Point GetPosition(bool offset = false, bool final = false, bool round = false) { if (offset) { var of = VisualTreeHelper.GetOffset(this); return(round ? new Point((int)of.X, (int)of.Y) : new Point(of.X, of.Y)); } else { if (round) { return(new Point(final ? (int)GraphAreaBase.GetFinalX(this) : (int)GraphAreaBase.GetX(this), final ? (int)GraphAreaBase.GetFinalY(this) : (int)GraphAreaBase.GetY(this))); } else { return(new Point(final ? GraphAreaBase.GetFinalX(this) : GraphAreaBase.GetX(this), final ? GraphAreaBase.GetFinalY(this) : GraphAreaBase.GetY(this))); } } }
/// <summary> /// Create and apply edge path using calculated ER parameters stored in edge /// </summary> /// <param name="useCurrentCoords">Use current vertices coordinates or final coordinates (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. public void PrepareEdgePath(bool useCurrentCoords = false, Point[] externalRoutingPoints = null) { //do not calculate invisible edges if (Visibility != System.Windows.Visibility.Visible || Source == null || Target == null || ManualDrawing) { return; } var template = Template; if (template != null) { #region Get the inputs //get the position of the source var sourcePos = new Point() { X = useCurrentCoords ? GraphAreaBase.GetX(Source) : GraphAreaBase.GetFinalX(Source), Y = useCurrentCoords ? GraphAreaBase.GetY(Source) : GraphAreaBase.GetFinalY(Source) }; //get the size of the source var sourceSize = new Size() { Width = Source.ActualWidth, Height = Source.ActualHeight }; //get the position of the target var targetPos = new Point() { X = useCurrentCoords ? GraphAreaBase.GetX(Target) : GraphAreaBase.GetFinalX(Target), Y = useCurrentCoords ? GraphAreaBase.GetY(Target) : GraphAreaBase.GetFinalY(Target) }; //get the size of the target var targetSize = new Size() { Width = Target.ActualWidth, Height = Target.ActualHeight }; //get the route informations var routeInformation = externalRoutingPoints == null ? (Edge as IRoutingInfo).RoutingPoints : externalRoutingPoints; #endregion //if self looped edge if (IsSelfLooped) { if (!RootArea.EdgeShowSelfLooped) { return; } var pt = new Point(sourcePos.X - sourceSize.Width / 2 + RootArea.EdgeSelfLoopCircleOffset.X - RootArea.EdgeSelfLoopCircleRadius, sourcePos.Y - sourceSize.Height / 2 + RootArea.EdgeSelfLoopCircleOffset.X - RootArea.EdgeSelfLoopCircleRadius); var geo = new EllipseGeometry(pt, RootArea.EdgeSelfLoopCircleRadius, RootArea.EdgeSelfLoopCircleRadius); var dArrowAngle = Math.PI / 2.0; _arrowgeometry = new PathGeometry(); _arrowgeometry.Figures.Add(GeometryHelper.GenerateArrow(new Point(sourcePos.X - sourceSize.Width / 2, sourcePos.Y - sourceSize.Height / 2), new Point(), new Point(), dArrowAngle)); _linegeometry = geo; return; } bool hasRouteInfo = routeInformation != null && routeInformation.Length > 1; //calculate source and target edge attach points if (!hasRouteInfo && RootArea.EnableParallelEdges) { if (SourceOffset != 0) { sourcePos = GetOffset(Source, Target, SourceOffset); } if (TargetOffset != 0) { targetPos = GetOffset(Target, Source, TargetOffset); } } Point p1 = GeometryHelper.GetEdgeEndpoint(sourcePos, new Rect(sourceSize), (hasRouteInfo ? routeInformation[1] : (targetPos)), Source.MathShape); Point p2 = GeometryHelper.GetEdgeEndpoint(targetPos, new Rect(targetSize), hasRouteInfo ? routeInformation[routeInformation.Length - 2] : (sourcePos), Target.MathShape); _linegeometry = new PathGeometry(); PathFigure lineFigure = null; _arrowgeometry = new PathGeometry(); PathFigure arrowFigure = null; //if we have route and route consist of 2 or more points if (hasRouteInfo) { //replace start and end points with accurate ones var routePoints = routeInformation.ToList(); routePoints.Remove(routePoints.First()); routePoints.Remove(routePoints.Last()); routePoints.Insert(0, p1); routePoints.Add(p2); if (RootArea.EdgeCurvingEnabled) { var oPolyLineSegment = GeometryHelper.GetCurveThroughPoints(routePoints.ToArray(), 0.5, RootArea.EdgeCurvingTolerance); lineFigure = GeometryHelper.GetPathFigureFromPathSegments(routePoints[0], true, true, oPolyLineSegment); //get two last points of curved path to generate correct arrow var c_last = oPolyLineSegment.Points.Last(); var c_prev = oPolyLineSegment.Points[oPolyLineSegment.Points.Count - 2]; arrowFigure = GeometryHelper.GenerateOldArrow(c_prev, c_last); //freeze and create resulting geometry GeometryHelper.TryFreeze(oPolyLineSegment); } else { lineFigure = new PathFigure(p1, new PathSegment[1] { new PolyLineSegment(routePoints, true) }, false); arrowFigure = GeometryHelper.GenerateOldArrow(routePoints[routePoints.Count - 2], p2); } } else // no route defined { //!!! Here is the line calculation to not overlap an arrowhead //Vector v = p1 - p2; v = v / v.Length * 5; // Vector n = new Vector(-v.Y, v.X) * 0.7; //segments[0] = new LineSegment(p2 + v, true); lineFigure = new PathFigure(p1, new PathSegment[1] { new LineSegment(p2, true) }, false); arrowFigure = GeometryHelper.GenerateOldArrow(p1, p2); } GeometryHelper.TryFreeze(lineFigure); (_linegeometry as PathGeometry).Figures.Add(lineFigure); if (arrowFigure != null) { GeometryHelper.TryFreeze(arrowFigure); _arrowgeometry.Figures.Add(arrowFigure); } GeometryHelper.TryFreeze(_linegeometry); GeometryHelper.TryFreeze(_arrowgeometry); } else { Debug.WriteLine("PrepareEdgePath() -> Edge template not found! Can't apply path to display edge!"); } }