Пример #1
0
        GetEdgeEndpointOnCircle
        (
            Point oVertexALocation,
            Double dVertexARadius,
            Point oVertexBLocation,
            out Point oEdgeEndpoint
        )
        {
            Debug.Assert(dVertexARadius >= 0);
            AssertValid();

            Double dEdgeAngle = WpfGraphicsUtil.GetAngleBetweenPoints(
                oVertexALocation, oVertexBLocation);

            oEdgeEndpoint = new Point(
                oVertexALocation.X + (dVertexARadius * Math.Cos(dEdgeAngle)),
                oVertexALocation.Y - (dVertexARadius * Math.Sin(dEdgeAngle))
                );
        }
Пример #2
0
        GetEdgeEndpointOnRectangle
        (
            Point oVertexALocation,
            Rect oVertexARectangle,
            Point oVertexBLocation,
            out Point oEdgeEndpoint
        )
        {
            AssertValid();

            if (oVertexALocation == oVertexBLocation)
            {
                oEdgeEndpoint = oVertexALocation;

                return;
            }

            Double dVertexAX = oVertexALocation.X;
            Double dVertexAY = oVertexALocation.Y;

            Double dVertexBX = oVertexBLocation.X;
            Double dVertexBY = oVertexBLocation.Y;

            Double dHalfVertexARectangleWidth  = oVertexARectangle.Width / 2.0;
            Double dHalfVertexARectangleHeight = oVertexARectangle.Height / 2.0;

            // Get the angle between vertex A and vertex B.

            Double dEdgeAngle = WpfGraphicsUtil.GetAngleBetweenPoints(
                oVertexALocation, oVertexBLocation);

            // Get the angle that defines the aspect ratio of vertex A's rectangle.

            Double dAspectAngle = Math.Atan2(
                dHalfVertexARectangleHeight, dHalfVertexARectangleWidth);

            if (dEdgeAngle >= -dAspectAngle && dEdgeAngle < dAspectAngle)
            {
                // For a square, this is -45 degrees to 45 degrees.

                Debug.Assert(dVertexBX != dVertexAX);

                oEdgeEndpoint = new Point(

                    dVertexAX + dHalfVertexARectangleWidth,

                    dVertexAY + dHalfVertexARectangleWidth *
                    ((dVertexBY - dVertexAY) / (dVertexBX - dVertexAX))
                    );

                return;
            }

            if (dEdgeAngle >= dAspectAngle && dEdgeAngle < Math.PI - dAspectAngle)
            {
                // For a square, this is 45 degrees to 135 degrees.

                Debug.Assert(dVertexBY != dVertexAY);

                oEdgeEndpoint = new Point(

                    dVertexAX + dHalfVertexARectangleHeight *
                    ((dVertexBX - dVertexAX) / (dVertexAY - dVertexBY)),

                    dVertexAY - dHalfVertexARectangleHeight
                    );

                return;
            }

            if (dEdgeAngle < -dAspectAngle && dEdgeAngle >= -Math.PI + dAspectAngle)
            {
                // For a square, this is -45 degrees to -135 degrees.

                Debug.Assert(dVertexBY != dVertexAY);

                oEdgeEndpoint = new Point(

                    dVertexAX + dHalfVertexARectangleHeight *
                    ((dVertexBX - dVertexAX) / (dVertexBY - dVertexAY)),

                    dVertexAY + dHalfVertexARectangleHeight
                    );

                return;
            }

            // For a square, this is 135 degrees to 180 degrees and -135 degrees to
            // -180 degrees.

            Debug.Assert(dVertexAX != dVertexBX);

            oEdgeEndpoint = new Point(

                dVertexAX - dHalfVertexARectangleWidth,

                dVertexAY + dHalfVertexARectangleWidth *
                ((dVertexBY - dVertexAY) / (dVertexAX - dVertexBX))
                );
        }
Пример #3
0
        TryDrawEdge
        (
            IEdge edge,
            GraphDrawingContext graphDrawingContext,
            out EdgeDrawingHistory edgeDrawingHistory
        )
        {
            Debug.Assert(edge != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            edgeDrawingHistory = null;

            // If the edge is hidden, do nothing.

            VisibilityKeyValue eVisibility = GetVisibility(edge);

            if (eVisibility == VisibilityKeyValue.Hidden)
            {
                return(false);
            }

            Boolean   bDrawAsSelected = GetDrawAsSelected(edge);
            Color     oColor          = GetColor(edge, eVisibility, bDrawAsSelected);
            Double    dWidth          = GetWidth(edge, bDrawAsSelected);
            DashStyle oDashStyle      = GetDashStyle(edge, dWidth, bDrawAsSelected);
            Boolean   bDrawArrow      = (m_bDrawArrowOnDirectedEdge && edge.IsDirected);

            IVertex [] aoVertices = edge.Vertices;

            DrawingVisual oDrawingVisual = new DrawingVisual();

            using (DrawingContext oDrawingContext = oDrawingVisual.RenderOpen())
            {
                if (edge.IsSelfLoop)
                {
                    if (!TryDrawSelfLoop(aoVertices[0], oDrawingContext,
                                         graphDrawingContext, oColor, dWidth, bDrawArrow))
                    {
                        // The edge's vertex is hidden, so the edge should be
                        // hidden also.

                        return(false);
                    }
                }
                else
                {
                    Point oEdgeEndpoint1, oEdgeEndpoint2;

                    if (!TryGetEdgeEndpoints(aoVertices[0], aoVertices[1],
                                             graphDrawingContext, out oEdgeEndpoint1,
                                             out oEdgeEndpoint2))
                    {
                        // One of the edge's vertices is hidden, so the edge should
                        // be hidden also.

                        return(false);
                    }

                    if (bDrawArrow)
                    {
                        // Draw the arrow and set the second endpoint to the center
                        // of the flat end of the arrow.

                        Double dArrowAngle = WpfGraphicsUtil.GetAngleBetweenPoints(
                            oEdgeEndpoint1, oEdgeEndpoint2);

                        oEdgeEndpoint2 = DrawArrow(oDrawingContext, oEdgeEndpoint2,
                                                   dArrowAngle, oColor, dWidth);
                    }

                    // Draw the edge.

                    oDrawingContext.DrawLine(GetPen(oColor, dWidth, oDashStyle),
                                             oEdgeEndpoint1, oEdgeEndpoint2);

                    // Draw the edge's label, if there is one.

                    Object oLabelAsObject;

                    if (edge.TryGetValue(ReservedMetadataKeys.PerEdgeLabel,
                                         typeof(String), out oLabelAsObject) &&
                        oLabelAsObject != null)
                    {
                        DrawLabel(oDrawingContext, graphDrawingContext,
                                  oEdgeEndpoint1, oEdgeEndpoint2,
                                  (String)oLabelAsObject, oColor);
                    }
                }

                // Retain information about the edge that was drawn.

                edgeDrawingHistory = new EdgeDrawingHistory(
                    edge, oDrawingVisual, bDrawAsSelected);

                return(true);
            }
        }
Пример #4
0
        GetEdgeEndpoint
        (
            VertexDrawingHistory otherVertexDrawingHistory,
            out Point edgeEndpoint
        )
        {
            AssertValid();

            Point oVertexLocation      = this.VertexLocation;
            Point oOtherVertexLocation = otherVertexDrawingHistory.VertexLocation;

            // Instead of doing geometry calculations similar to what is done in
            // VertexDrawingHistory.GetEdgePointOnRectangle(), make use of that
            // method by making the triangle look like a rectangle.  First, figure
            // out how to rotate the triangle about the vertex location so that the
            // side containing the endpoint is vertical and to the right of the
            // vertex location.

            Double dEdgeAngle = WpfGraphicsUtil.GetAngleBetweenPoints(
                oVertexLocation, oOtherVertexLocation);

            Double dEdgeAngleDegrees = MathUtil.RadiansToDegrees(dEdgeAngle);

            Double dAngleToRotateDegrees;

            if (dEdgeAngleDegrees >= -30.0 && dEdgeAngleDegrees < 90.0)
            {
                dAngleToRotateDegrees = 30.0;
            }
            else if (dEdgeAngleDegrees >= -150.0 && dEdgeAngleDegrees < -30.0)
            {
                dAngleToRotateDegrees = 270.0;
            }
            else
            {
                dAngleToRotateDegrees = 150.0;
            }

            // Now create a rotated rectangle that is centered on the vertex
            // location and that has the vertical, endpoint-containing triangle
            // side as the rectangle's right edge.

            Double dWidth = 2.0 * m_dHalfWidth;

            Rect oRotatedRectangle = new Rect(
                oVertexLocation.X,
                oVertexLocation.Y - m_dHalfWidth,
                dWidth * WpfGraphicsUtil.Tangent30Degrees,
                dWidth
                );

            Matrix oMatrix = WpfGraphicsUtil.GetRotatedMatrix(oVertexLocation,
                                                              dAngleToRotateDegrees);

            // Rotate the other vertex location.

            Point oRotatedOtherVertexLocation =
                oMatrix.Transform(oOtherVertexLocation);

            // GetEdgeEndpointOnRectangle will compute an endpoint on the
            // rectangle's right edge.

            Point oRotatedEdgeEndpoint;

            GetEdgeEndpointOnRectangle(oVertexLocation, oRotatedRectangle,
                                       oRotatedOtherVertexLocation, out oRotatedEdgeEndpoint);

            // Now rotate the edge endpoint in the other direction.

            oMatrix = WpfGraphicsUtil.GetRotatedMatrix(oVertexLocation,
                                                       -dAngleToRotateDegrees);

            edgeEndpoint = oMatrix.Transform(oRotatedEdgeEndpoint);
        }
Пример #5
0
        DrawLabel
        (
            DrawingContext oDrawingContext,
            GraphDrawingContext oGraphDrawingContext,
            Point oEdgeEndpoint1,
            Point oEdgeEndpoint2,
            String sLabel,
            Color oColor
        )
        {
            Debug.Assert(oDrawingContext != null);
            Debug.Assert(oGraphDrawingContext != null);
            Debug.Assert(sLabel != null);
            AssertValid();

            if (sLabel.Length == 0)
            {
                return;
            }

            sLabel = TruncateLabel(sLabel);

            if (oEdgeEndpoint2.X < oEdgeEndpoint1.X)
            {
                // Don't let text be drawn upside-down.

                Point oTemp = oEdgeEndpoint2;
                oEdgeEndpoint2 = oEdgeEndpoint1;
                oEdgeEndpoint1 = oTemp;
            }

            Double dEdgeAngleDegrees = MathUtil.RadiansToDegrees(
                WpfGraphicsUtil.GetAngleBetweenPoints(
                    oEdgeEndpoint1, oEdgeEndpoint2));

            Double dEdgeLength = WpfGraphicsUtil.GetDistanceBetweenPoints(
                oEdgeEndpoint1, oEdgeEndpoint2);

            // To avoid trigonometric calculations, use a RotateTransform to make
            // the edge look as if it is horizontal, with oEdgeEndpoint2 to the
            // right of oEdgeEndpoint1.

            RotateTransform oRotateTransform = new RotateTransform(
                dEdgeAngleDegrees, oEdgeEndpoint1.X, oEdgeEndpoint1.Y);

            oEdgeEndpoint2         = oRotateTransform.Transform(oEdgeEndpoint2);
            oRotateTransform.Angle = -dEdgeAngleDegrees;
            oDrawingContext.PushTransform(oRotateTransform);

            FormattedText oFormattedText = CreateFormattedText(sLabel, oColor);

            oFormattedText.Trimming = TextTrimming.CharacterEllipsis;

            if (sLabel.IndexOf('\n') == -1)
            {
                // Unless the label includes line breaks, don't allow the
                // FormattedText class to break the text into multiple lines.

                oFormattedText.MaxLineCount = 1;
            }

            Double dTextWidth = oFormattedText.Width;

            // The ends of the label text are between one and two "buffer units"
            // from the ends of the edge.  The buffer unit is the width of an
            // arbitrary character.

            Double dBufferUnit             = CreateFormattedText("i", oColor).Width;
            Double dEdgeLengthMinusBuffers = dEdgeLength - 2 * dBufferUnit;

            if (dEdgeLengthMinusBuffers <= 0)
            {
                return;
            }

            // Determine where to draw the label text, and where to draw a
            // translucent rectangle behind the text.  The translucent rectangle
            // serves to obscure, but not completely hide, the underlying edge.

            Point oLabelOrigin = oEdgeEndpoint1;
            Rect  oTranslucentRectangle;

            if (dTextWidth > dEdgeLengthMinusBuffers)
            {
                // The label text should start one buffer unit from the first
                // endpoint, and terminate with ellipses approximately one buffer
                // length from the second endpoint.

                oLabelOrigin.Offset(dBufferUnit, 0);
                oFormattedText.MaxTextWidth = dEdgeLengthMinusBuffers;

                // The translucent rectangle should be the same width as the text.

                oTranslucentRectangle = new Rect(oLabelOrigin,
                                                 new Size(dEdgeLengthMinusBuffers, oFormattedText.Height));
            }
            else
            {
                // The label should be centered along the edge's length.

                oLabelOrigin.Offset(dEdgeLength / 2.0, 0);
                oFormattedText.TextAlignment = TextAlignment.Center;

                // The translucent rectangle should extend between zero and one
                // buffer units beyond the ends of the text.  This provides a
                // margin between the text and the unobscured edge, if there is
                // enough space.

                oTranslucentRectangle = new Rect(oLabelOrigin,

                                                 new Size(
                                                     Math.Min(dTextWidth + 2 * dBufferUnit,
                                                              dEdgeLengthMinusBuffers),

                                                     oFormattedText.Height)
                                                 );

                oTranslucentRectangle.Offset(
                    -oTranslucentRectangle.Width / 2.0, 0);
            }

            // The text and rectangle should be vertically centered on the edge.

            oDrawingContext.PushTransform(
                new TranslateTransform(0, -oFormattedText.Height / 2.0));

            // Draw the translucent rectangle, then the text.
            //
            // Note: Don't make the rectangle any more opaque than the edge, which
            // might be translucent itself.

            oDrawingContext.DrawRectangle(GetBrush(
                                              WpfGraphicsUtil.SetWpfColorAlpha(oGraphDrawingContext.BackColor,
                                                                               Math.Min(LabelBackgroundAlpha, oColor.A))
                                              ),
                                          null, oTranslucentRectangle);

            oDrawingContext.DrawText(oFormattedText, oLabelOrigin);

            oDrawingContext.Pop();
            oDrawingContext.Pop();
        }