static IControl WithoutShaft(RectangleEdge edge, Brush brush, Rectangle <IObservable <Points> > frame) { var stroke = Stroke.Create(1.0, brush | Theme.Active); var to = edge.NormalAxis() == Axis2D.Horizontal ? Point.Create(frame.GetEdge(edge), frame.Center().Y) : Point.Create(frame.Center().X, frame.GetEdge(edge)); var width = frame[edge.NormalAxis().Opposite()].Length.Mul(0.5); var bottom = Vector.Create(width, width); switch (edge) { case RectangleEdge.Bottom: bottom = bottom.RotateCCV(); break; case RectangleEdge.Right: bottom = bottom.RotateCCV().RotateCCV(); break; case RectangleEdge.Top: bottom = bottom.RotateCCV().RotateCCV().RotateCCV(); break; } var top = bottom.RotateCCV(); return(Layout.Layer( Shapes.Line(to, to + top, stroke), Shapes.Line(to, to + bottom, stroke))); }
public CalloutPositionedInfo(PartialRectangle rectangle, RectangleEdge targetEdge, RectangleEdge alignmentEdge, CalloutBeakPositionedInfo beakPosition) { ElementRectangle = rectangle; TargetEdge = targetEdge; AlignmentEdge = alignmentEdge; BeakPosition = beakPosition; }
private Rectangle AlignOppositeEdges(Rectangle rect, Rectangle target, RectangleEdge targetEdge, double gap = 0) { var oppositeEdge = (int)targetEdge * -1; var adjustedGap = GetRelativeEdgeValue((RectangleEdge)oppositeEdge, gap); return(MoveEdge(rect, (RectangleEdge)((int)targetEdge * -1), GetEdgeValue(target, targetEdge) + adjustedGap)); }
public CalloutBeakPositionedInfo(PartialRectangle elementRectangle, RectangleEdge targetEdge, RectangleEdge closestEdge) { ElementRectangle = elementRectangle; TargetEdge = targetEdge; AlignmentEdge = RectangleEdge.None; ClosestEdge = closestEdge; }
private Rectangle CenterEdgeToPoint(Rectangle rect, RectangleEdge edge, double point) { var positiveEdge = GetFlankingEdges(edge).positiveEdge; var elementMiddle = GetCenterValue(rect, edge); var distanceToMiddle = elementMiddle - GetEdgeValue(rect, positiveEdge); return(MoveEdge(rect, positiveEdge, point - distanceToMiddle)); }
public static IControl MakeResizable(this IControl self, RectangleEdge edge, string name) { var property = Property.Create(new Points(280)); //.Settings.GetPointsProperty(name + ".Width"); return(self .WithDimension(edge.NormalAxis(), property) .MakeResizable(edge, property)); }
private Rectangle MoveEdge(Rectangle rect, RectangleEdge edge, double newValue) { var difference = GetEdgeValue(rect, edge) - newValue; rect = SetEdgeValue(rect, edge, newValue); rect = SetEdgeValue(rect, (RectangleEdge)((int)edge * -1), GetEdgeValue(rect, (RectangleEdge)((int)edge * -1)) - difference); return(rect); }
GetSelfLoopEndpoint ( RectangleEdge farthestGraphRectangleEdge ) { AssertValid(); return(GetSelfLoopEndpointOnRectangle( GetBoundingSquare(m_dHalfWidth), farthestGraphRectangleEdge)); }
/// <summary> /// Cuts away a part of the control /// </summary> /// <param name="content">The content to cut from</param> /// <param name="edge">From which side of the content to cut from</param> /// <param name="points">How much to cut, measured as the dimension of the cut away area orthogonal to edge</param> /// <returns>A visually clipped control (desiring points less size)</returns> public static IControl Scissor(this IControl content, RectangleEdge edge, Points points) { edge = edge.FlipVerticallyOnMac(); return(content .WithFrame(f => f.WithEdge(edge, f.GetEdge(edge).Add(edge.IsMinimal() ? new Points(-points) : points))) .Clip() .WithDimension(edge.NormalAxis(), content.DesiredSize[edge.NormalAxis()].Sub(points)) ); }
private RectangleEdge FinalizeReturnEdge(Rectangle elementRectangle, RectangleEdge returnEdge, Rectangle bounds) { if (bounds != null && Math.Abs(GetRelativeEdgeDifference(elementRectangle, bounds, returnEdge)) > (Math.Abs(GetRelativeEdgeDifference(elementRectangle, bounds, (RectangleEdge)((int)returnEdge * -1))))) { return((RectangleEdge)((int)returnEdge * -1)); } return(returnEdge); }
GetSelfLoopEndpoint ( RectangleEdge farthestGraphRectangleEdge ) { AssertValid(); return(GetSelfLoopEndpointOnRectangle(this.Rectangle, farthestGraphRectangleEdge)); }
private double GetRelativeEdgeValue(RectangleEdge edge, double value) { if (edge > 0) { return(value); } else { return(value * -1); } }
public static IControl Horizontal(RectangleEdge edge, Brush fill) { return(Layout.StackFromTop( Control.Empty.WithHeight(3), Shapes.Rectangle(fill: fill).WithHeight(7).WithWidth(7).Dock(edge, Control.Empty.WithWidth(13 - 7)), Control.Empty.WithHeight(1), Shapes.Rectangle(fill: fill).WithHeight(3).WithWidth(13), Control.Empty.WithHeight(3)) .WithPadding(left: new Points(2), right: new Points(2)) .WithOverlay(Shapes.Rectangle(fill: fill).WithWidth(1).Dock(edge)) .WithPadding(new Thickness <Points>(1))); }
public static IControl MakeResizable(this IControl self, RectangleEdge edge, IProperty <Points> property, bool invert = false, Points minSize = default(Points)) { var restrictedSize = property.Convert(v => v, v => v.Max(minSize)); return(self .WithOverlay( Control.Empty .WithDimension(edge.NormalAxis(), _ => Observable.Return <Points>(5)) .WhileDraggingScrub(restrictedSize, invert ? edge.DirectionToOpposite() : edge.DirectionToEdge()) .SetCursor(edge.NormalAxis() == Axis2D.Horizontal ? Cursor.ResizeHorizontally : Cursor.ResizeVertically) .Dock(edge))); }
public static IControl DockIcon(RectangleEdge edge, Brush brush) { return(Shapes.Rectangle(stroke: Stroke.Create(1, brush)) .WithOverlay(Shapes.Rectangle(fill: brush) .WithHeight(2) .WithWidth(2) .WithPadding(new Thickness <Points>(2)) .Dock(edge)) .WithWidth(20) .WithHeight(16) .Center()); }
public static IControl Vertical(RectangleEdge edge, Brush fill) { return(Layout.StackFromLeft( Control.Empty.WithWidth(3), Shapes.Rectangle(fill: fill).WithWidth(7).WithHeight(7).Dock(edge, Control.Empty.WithHeight(13 - 7)), Control.Empty.WithWidth(1), Shapes.Rectangle(fill: fill).WithWidth(3).WithHeight(13), Control.Empty.WithWidth(3)) .WithPadding(top: new Points(2), bottom: new Points(2)) .WithOverlay(Shapes.Rectangle(fill: fill).WithHeight(1).Dock(edge)) .WithPadding(new Thickness <Points>(1))); }
protected override void OnExecute() { edgeSquare = EnumExtend.GetRandom <RectangleEdge>(edgeSquare); BoxCollider2D collider = collider2D.value; Vector2 newPosition = collider.GetPerimeterPoint(edgeSquare, Random.value); targetTransform.value.position = newPosition; EndAction(); }
public static RectangleEdge FlipVerticallyOnMac(this RectangleEdge edge) { if (edge == RectangleEdge.Top && ShouldFlip) { return(RectangleEdge.Bottom); } if (edge == RectangleEdge.Bottom && ShouldFlip) { return(RectangleEdge.Top); } return(edge); }
public static IControl MakeCollapsable( this IControl content, RectangleEdge edge, IObservable <bool> expanded, bool lazy = true, bool unrootWhenCollapsed = false, bool animate = true) { edge = edge.FlipVerticallyOnMac(); var expandedValueStep = expanded.Select(isExpanded => isExpanded ? 1.0 : 0.0); var expandedValue = animate ? expandedValueStep.LowPass() : expandedValueStep; var u = edge.NormalAxis(); var v = edge.NormalAxis().Opposite(); var lazyContent = lazy == false ? content : expanded .SkipWhile(e => e == false).Take(1) .Select(isExpanded => content) .StartWith(Control.Empty) .Switch() ; if (unrootWhenCollapsed) { lazyContent = lazyContent.HideWhen(expandedValue.Select(ev => ev < 0.01)); } return(Layout .Layer(self => new[] { lazyContent .Clip() .WithFrame(parentFrame => Rectangle .FromPositionSize( position: edge.GetOffsetPosition(lazyContent.DesiredSize[u], expandedValue), size: Size.Create( lazyContent.DesiredSize[u], parentFrame.Size[v], firstAxis: u)) .MoveTo(parentFrame.Position)) .Clip() }) .WithSize(desiredSize: Size.Create( lazyContent.DesiredSize[u].Mul(expandedValue), expanded.Switch(e => e ? lazyContent.DesiredSize[v] : ObservableMath.Zero), firstAxis: u))); }
private RectangleEdge GetClosestEdge(RectangleEdge targetEdge, Rectangle targetRect, Rectangle boundingRect) { var targetCenter = GetCenterValue(targetRect, targetEdge); var boundingCenter = GetCenterValue(boundingRect, targetEdge); var flankingEdges = GetFlankingEdges(targetEdge); if (targetCenter <= boundingCenter) { return(flankingEdges.positiveEdge); } else { return(flankingEdges.negativeEdge); } }
public static Point <IObservable <Points> > GetOffsetPosition(this RectangleEdge edge, IObservable <Points> width, IObservable <double> expandedValue) { if (edge.IsMinimal()) { return(ObservableMath.ZeroPoint); } var negativeWidth = width.Select(w => 0 - w); var collapsedValue = expandedValue.Select(v => 1 - v); return(Point.Create( negativeWidth.Mul(collapsedValue), ObservableMath.Zero, firstAxis: edge.NormalAxis())); }
TryDrawSelfLoop ( IVertex oVertex, DrawingContext oDrawingContext, GraphDrawingContext oGraphDrawingContext, Color oColor, Double dWidth, Boolean bDrawArrow ) { Debug.Assert(oVertex != null); Debug.Assert(oDrawingContext != null); Debug.Assert(oGraphDrawingContext != null); Debug.Assert(dWidth >= 0); AssertValid(); // Retrieve the information about how the vertex was drawn. VertexDrawingHistory oVertexDrawingHistory; if (!oGraphDrawingContext.VertexDrawingHistories.TryGetValue( oVertex.ID, out oVertexDrawingHistory)) { // The edge's vertex is hidden, so the edge should be hidden also. return(false); } // Determine the edge of the graph rectangle that is farthest from the // vertex. Point oVertexLocation = oVertexDrawingHistory.VertexLocation; RectangleEdge eFarthestGraphRectangleEdge = WpfGraphicsUtil.GetFarthestRectangleEdge(oVertexLocation, oGraphDrawingContext.GraphRectangle); // Get the point on the vertex at which to draw the self-loop. Point oSelfLoopEndpoint = oVertexDrawingHistory.GetSelfLoopEndpoint( eFarthestGraphRectangleEdge); DrawSelfLoopAt(oDrawingContext, oGraphDrawingContext, oColor, dWidth, oSelfLoopEndpoint, eFarthestGraphRectangleEdge, bDrawArrow); return(true); }
GetSelfLoopEndpoint ( RectangleEdge farthestGraphRectangleEdge ) { AssertValid(); // Return a point at one of the triangle's corners. Point oVertexLocation = this.VertexLocation; Double dVertexX = oVertexLocation.X; Double dVertexY = oVertexLocation.Y; Double dX = dVertexX; Double dY = dVertexY + m_dHalfWidth * WpfGraphicsUtil.Tangent30Degrees; switch (farthestGraphRectangleEdge) { case RectangleEdge.Top: dY = dVertexY - m_dHalfWidth / WpfGraphicsUtil.Cosine30Degrees; break; case RectangleEdge.Left: dX -= m_dHalfWidth; break; case RectangleEdge.Right: dX += m_dHalfWidth; break; case RectangleEdge.Bottom: break; default: Debug.Assert(false); break; } return(new Point(dX, dY)); }
GetSelfLoopEndpointOnRectangle ( Rect oVertexRectangle, RectangleEdge eFarthestGraphRectangleEdge ) { AssertValid(); Double dX = 0; Double dY = 0; switch (eFarthestGraphRectangleEdge) { case RectangleEdge.Top: dX = oVertexRectangle.Left + oVertexRectangle.Width / 2.0; dY = oVertexRectangle.Top; break; case RectangleEdge.Left: dX = oVertexRectangle.Left; dY = oVertexRectangle.Top + oVertexRectangle.Height / 2.0; break; case RectangleEdge.Right: dX = oVertexRectangle.Right; dY = oVertexRectangle.Top + oVertexRectangle.Height / 2.0; break; case RectangleEdge.Bottom: dX = oVertexRectangle.Left + oVertexRectangle.Width / 2.0; dY = oVertexRectangle.Bottom; break; default: Debug.Assert(false); break; } return(new Point(dX, dY)); }
public static IControl WithShaft(RectangleEdge edge, SymbolSize size = SymbolSize.Contain, Brush brush = default(Brush)) { var stroke = Stroke.Create(1.0, brush | Theme.Active); return(ResizeSymbol(edge, size, Control.BindNativeFrame(frame => WithoutShaft(edge, brush, frame) .WithOverlay( edge.NormalAxis() == Axis2D.Horizontal ? Shapes.Line( Point.Create(frame.Left(), frame.Center().Y), Point.Create(frame.Right(), frame.Center().Y), stroke) : Shapes.Line( Point.Create(frame.Center().X, frame.Top()), Point.Create(frame.Center().X, frame.Bottom()), stroke)))) .WithBackground(Color.Transparent)); // TODO: not sure why this is needed }
public static Direction2D DirectionToEdge(this RectangleEdge edge) { switch (edge) { case RectangleEdge.Right: return(Direction2D.LeftToRight); case RectangleEdge.Left: return(Direction2D.RightToLeft); case RectangleEdge.Bottom: return(Direction2D.TopToBottom); case RectangleEdge.Top: return(Direction2D.BottomToTop); } throw new ArgumentException(); }
public static RectangleEdges ToFlags(this RectangleEdge edge) { switch (edge) { case RectangleEdge.Right: return(RectangleEdges.Right); case RectangleEdge.Left: return(RectangleEdges.Left); case RectangleEdge.Bottom: return(RectangleEdges.Bottom); case RectangleEdge.Top: return(RectangleEdges.Top); } return(RectangleEdges.None); }
public static RectangleEdge Opposite(this RectangleEdge edge) { switch (edge) { case RectangleEdge.Left: return(RectangleEdge.Right); case RectangleEdge.Right: return(RectangleEdge.Left); case RectangleEdge.Top: return(RectangleEdge.Bottom); case RectangleEdge.Bottom: return(RectangleEdge.Top); } throw new ArgumentException(); }
/// <summary> /// Fines the edge interception. /// </summary> /// <param name="bounds">The bounds.</param> /// <param name="edge">The edge.</param> /// <param name="a">The first point.</param> /// <param name="b">The second point.</param> /// <returns>The interception.</returns> private static ScreenPoint LineIntercept(OxyRect bounds, RectangleEdge edge, ScreenPoint a, ScreenPoint b) { if (a.x == b.x && a.y == b.y) { return(a); } switch (edge) { case RectangleEdge.Bottom: if (b.Y == a.Y) { throw new ArgumentException("no intercept found"); } return(new ScreenPoint(a.X + (((b.X - a.X) * (bounds.Bottom - a.Y)) / (b.Y - a.Y)), bounds.Bottom)); case RectangleEdge.Left: if (b.X == a.X) { throw new ArgumentException("no intercept found"); } return(new ScreenPoint(bounds.Left, a.Y + (((b.Y - a.Y) * (bounds.Left - a.X)) / (b.X - a.X)))); case RectangleEdge.Right: if (b.X == a.X) { throw new ArgumentException("no intercept found"); } return(new ScreenPoint(bounds.Right, a.Y + (((b.Y - a.Y) * (bounds.Right - a.X)) / (b.X - a.X)))); case RectangleEdge.Top: if (b.Y == a.Y) { throw new ArgumentException("no intercept found"); } return(new ScreenPoint(a.X + (((b.X - a.X) * (bounds.Top - a.Y)) / (b.Y - a.Y)), bounds.Top)); } throw new ArgumentException("no intercept found"); }
/// <summary> /// Clips to one axis. /// </summary> /// <param name="bounds"> /// The bounds. /// </param> /// <param name="edge"> /// The edge. /// </param> /// <param name="v"> /// The points of the polygon. /// </param> /// <returns> /// The clipped points. /// </returns> private static List <ScreenPoint> ClipOneAxis(OxyRect bounds, RectangleEdge edge, IList <ScreenPoint> v) { if (v.Count == 0) { return(new List <ScreenPoint>()); } var polygon = new List <ScreenPoint>(v.Count); var s = v[v.Count - 1]; for (int i = 0; i < v.Count; ++i) { var p = v[i]; bool pin = IsInside(bounds, edge, p); bool sin = IsInside(bounds, edge, s); if (sin && pin) { // case 1: inside -> inside polygon.Add(p); } else if (sin) { // case 2: inside -> outside polygon.Add(LineIntercept(bounds, edge, s, p)); } else if (!pin) { // case 3: outside -> outside // emit nothing } else { // case 4: outside -> inside polygon.Add(LineIntercept(bounds, edge, s, p)); polygon.Add(p); } s = p; } return(polygon); }
/// <summary> /// Clips to one axis. /// </summary> /// <param name="bounds">The bounds.</param> /// <param name="edge">The edge.</param> /// <param name="v">The points of the polygon.</param> /// <returns>The clipped points.</returns> private static List<ScreenPoint> ClipOneAxis(OxyRect bounds, RectangleEdge edge, IList<ScreenPoint> v) { if (v.Count == 0) { return new List<ScreenPoint>(); } var polygon = new List<ScreenPoint>(v.Count); var s = v[v.Count - 1]; for (int i = 0; i < v.Count; ++i) { var p = v[i]; bool pin = IsInside(bounds, edge, p); bool sin = IsInside(bounds, edge, s); if (sin && pin) { // case 1: inside -> inside polygon.Add(p); } else if (sin) { // case 2: inside -> outside polygon.Add(LineIntercept(bounds, edge, s, p)); } else if (!pin) { // case 3: outside -> outside // emit nothing } else { // case 4: outside -> inside polygon.Add(LineIntercept(bounds, edge, s, p)); polygon.Add(p); } s = p; } return polygon; }
GetSelfLoopEndpointOnRectangle ( Rect oVertexRectangle, RectangleEdge eFarthestGraphRectangleEdge ) { AssertValid(); Double dX = 0; Double dY = 0; switch (eFarthestGraphRectangleEdge) { case RectangleEdge.Top: dX = oVertexRectangle.Left + oVertexRectangle.Width / 2.0; dY = oVertexRectangle.Top; break; case RectangleEdge.Left: dX = oVertexRectangle.Left; dY = oVertexRectangle.Top + oVertexRectangle.Height / 2.0; break; case RectangleEdge.Right: dX = oVertexRectangle.Right; dY = oVertexRectangle.Top + oVertexRectangle.Height / 2.0; break; case RectangleEdge.Bottom: dX = oVertexRectangle.Left + oVertexRectangle.Width / 2.0; dY = oVertexRectangle.Bottom; break; default: Debug.Assert(false); break; } return ( new Point(dX, dY) ); }
GetSelfLoopEndpoint ( RectangleEdge farthestGraphRectangleEdge );
//************************************************************************* // Method: GetSelfLoopEndpoint() // /// <summary> /// Gets the endpoint of an edge that is connected to <see /// cref="VertexDrawingHistory.Vertex" /> and is a self-loop. /// </summary> /// /// <param name="farthestGraphRectangleEdge"> /// The edge of the graph rectangle that is farthest from <see /// cref="VertexDrawingHistory.Vertex" />. /// </param> /// /// <returns> /// The self-loop endpoint. The endpoint is somewhere on <see /// cref="VertexDrawingHistory.Vertex" />. /// </returns> /// /// <remarks> /// A self-loop is an edge that connects a vertex to itself. This method /// determines the single endpoint of the self-loop, which gets drawn as a /// line looping back to its starting point. /// </remarks> //************************************************************************* public override Point GetSelfLoopEndpoint( RectangleEdge farthestGraphRectangleEdge ) { AssertValid(); return ( GetSelfLoopEndpointOnRectangle(this.Rectangle, farthestGraphRectangleEdge) ); }
GetSelfLoopEndpoint ( RectangleEdge farthestGraphRectangleEdge ) { AssertValid(); return ( GetSelfLoopEndpointOnRectangle(GetBoundingSquare(m_dRadius), farthestGraphRectangleEdge) ); }
/// <summary> /// Fines the edge interception. /// </summary> /// <param name="bounds">The bounds.</param> /// <param name="edge">The edge.</param> /// <param name="a">The first point.</param> /// <param name="b">The second point.</param> /// <returns>The interception.</returns> private static ScreenPoint LineIntercept(OxyRect bounds, RectangleEdge edge, ScreenPoint a, ScreenPoint b) { if (a.x == b.x && a.y == b.y) { return a; } switch (edge) { case RectangleEdge.Bottom: if (b.Y == a.Y) { throw new ArgumentException("no intercept found"); } return new ScreenPoint(a.X + (((b.X - a.X) * (bounds.Bottom - a.Y)) / (b.Y - a.Y)), bounds.Bottom); case RectangleEdge.Left: if (b.X == a.X) { throw new ArgumentException("no intercept found"); } return new ScreenPoint(bounds.Left, a.Y + (((b.Y - a.Y) * (bounds.Left - a.X)) / (b.X - a.X))); case RectangleEdge.Right: if (b.X == a.X) { throw new ArgumentException("no intercept found"); } return new ScreenPoint(bounds.Right, a.Y + (((b.Y - a.Y) * (bounds.Right - a.X)) / (b.X - a.X))); case RectangleEdge.Top: if (b.Y == a.Y) { throw new ArgumentException("no intercept found"); } return new ScreenPoint(a.X + (((b.X - a.X) * (bounds.Top - a.Y)) / (b.Y - a.Y)), bounds.Top); } throw new ArgumentException("no intercept found"); }
/// <summary> /// Determines whether the specified point is inside the edge/bounds. /// </summary> /// <param name="bounds">The bounds.</param> /// <param name="edge">The edge to test.</param> /// <param name="p">The point.</param> /// <returns> /// <c>true</c> if the specified point is inside; otherwise, <c>false</c>. /// </returns> private static bool IsInside(OxyRect bounds, RectangleEdge edge, ScreenPoint p) { switch (edge) { case RectangleEdge.Left: return !(p.X < bounds.Left); case RectangleEdge.Right: return !(p.X >= bounds.Right); case RectangleEdge.Top: return !(p.Y < bounds.Top); case RectangleEdge.Bottom: return !(p.Y >= bounds.Bottom); default: throw new ArgumentException("edge"); } }
DrawSelfLoopAt ( DrawingContext oDrawingContext, GraphDrawingContext oGraphDrawingContext, Color oColor, Double dWidth, Point oSelfLoopEndpoint, RectangleEdge eFarthestGraphRectangleEdge, Boolean bDrawArrow ) { Debug.Assert(oDrawingContext != null); Debug.Assert(oGraphDrawingContext != null); Debug.Assert(dWidth >= 0); AssertValid(); // The self-loop is drawn as a circle. Figure out the location of the // circle's center and the tip of the arrow, if there is an arrow. Double dCircleX, dCircleY, dArrowTipX, dArrowTipY, dArrowAngle; dCircleX = dArrowTipX = oSelfLoopEndpoint.X; dCircleY = dArrowTipY = oSelfLoopEndpoint.Y; Double dSelfLoopCircleDiameter = 2.0 * SelfLoopCircleRadius; dArrowAngle = 0; switch (eFarthestGraphRectangleEdge) { case RectangleEdge.Top: dCircleY -= SelfLoopCircleRadius; dArrowTipY -= dSelfLoopCircleDiameter; break; case RectangleEdge.Left: dCircleX -= SelfLoopCircleRadius; dArrowTipX -= dSelfLoopCircleDiameter; dArrowAngle = Math.PI / 2.0; // (90 degrees.) break; case RectangleEdge.Right: dCircleX += SelfLoopCircleRadius; dArrowTipX += dSelfLoopCircleDiameter; dArrowAngle = -Math.PI / 2.0; // (-90 degrees.) break; case RectangleEdge.Bottom: dCircleY += SelfLoopCircleRadius; dArrowTipY += dSelfLoopCircleDiameter; dArrowAngle = Math.PI; // (180 degrees.) break; default: Debug.Assert(false); break; } oDrawingContext.DrawEllipse(null, GetPen(oColor, dWidth), new Point(dCircleX, dCircleY), SelfLoopCircleRadius, SelfLoopCircleRadius); if (bDrawArrow) { // Rotate the arrow slightly to adjust to the circular shape of the // edge connected to it. dArrowAngle += Math.PI / 13.0; DrawArrow(oDrawingContext, new Point(dArrowTipX, dArrowTipY), dArrowAngle, oColor, dWidth); } }
//************************************************************************* // Method: GetSelfLoopEndpoint() // /// <summary> /// Gets the endpoint of an edge that is connected to <see /// cref="VertexDrawingHistory.Vertex" /> and is a self-loop. /// </summary> /// /// <param name="farthestGraphRectangleEdge"> /// The edge of the graph rectangle that is farthest from <see /// cref="VertexDrawingHistory.Vertex" />. /// </param> /// /// <returns> /// The self-loop endpoint. The endpoint is somewhere on <see /// cref="VertexDrawingHistory.Vertex" />. /// </returns> /// /// <remarks> /// A self-loop is an edge that connects a vertex to itself. This method /// determines the single endpoint of the self-loop, which gets drawn as a /// line looping back to its starting point. /// </remarks> //************************************************************************* public override Point GetSelfLoopEndpoint( RectangleEdge farthestGraphRectangleEdge ) { AssertValid(); // Return a point at one of the triangle's corners. Point oVertexLocation = this.VertexLocation; Double dVertexX = oVertexLocation.X; Double dVertexY = oVertexLocation.Y; Double dX = dVertexX; Double dY = dVertexY + m_dHalfWidth * WpfGraphicsUtil.Tangent30Degrees; switch (farthestGraphRectangleEdge) { case RectangleEdge.Top: dY = dVertexY - m_dHalfWidth / WpfGraphicsUtil.Cosine30Degrees; break; case RectangleEdge.Left: dX -= m_dHalfWidth; break; case RectangleEdge.Right: dX += m_dHalfWidth; break; case RectangleEdge.Bottom: break; default: Debug.Assert(false); break; } return ( new Point(dX, dY) ); }