Example #1
0
        TransformGroupRectangles
        (
            IGraph graph,
            LayoutContext originalLayoutContext,
            LayoutContext newLayoutContext
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(originalLayoutContext != null);
            Debug.Assert(newLayoutContext != null);

            GroupLayoutDrawingInfo oGroupLayoutDrawingInfo;

            if (TryGetGroupLayoutDrawingInfo(graph, out oGroupLayoutDrawingInfo))
            {
                // Replace the metadata value's group rectangles with a transformed
                // set of group rectangles.

                Matrix oTransformationMatrix =
                    LayoutUtil.GetRectangleTransformation(
                        originalLayoutContext.GraphRectangle,
                        newLayoutContext.GraphRectangle
                        );

                foreach (GroupInfo oGroupInfo in
                         oGroupLayoutDrawingInfo.GroupsToDraw)
                {
                    oGroupInfo.Rectangle = LayoutUtil.TransformRectangle(
                        oGroupInfo.Rectangle, oTransformationMatrix);
                }
            }
        }
Example #2
0
        TransformLayoutCore
        (
            IGraph graph,
            LayoutContext originalLayoutContext,
            LayoutContext newLayoutContext
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(originalLayoutContext != null);
            Debug.Assert(newLayoutContext != null);
            AssertValid();

            Matrix oTransformationMatrix = LayoutUtil.GetRectangleTransformation(
                originalLayoutContext.GraphRectangle,
                newLayoutContext.GraphRectangle
                );

            LayoutUtil.TransformVertexLocations(graph, oTransformationMatrix);
        }
Example #3
0
        SaveGraphCore
        (
            IGraph graph,
            Stream stream
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(stream != null);
            AssertValid();

            // The Pajek format requires coordinates to be between 0 and 1.0.  Get
            // a Matrix that will transform the vertex locations to this range.

            RectangleF oCurrentBoundingRectangle =
                LayoutUtil.GetGraphBoundingRectangle(graph);

            RectangleF oNewBoundingRectangle =
                new RectangleF(PointF.Empty, new SizeF(1.0F, 1.0F));

            Matrix oRectangleTransformation =
                LayoutUtil.GetRectangleTransformation(
                    oCurrentBoundingRectangle, oNewBoundingRectangle
                    );

            // Create a dictionary to keep track of vertices.  The keys are vertex
            // IDs and the values are the one-based vertex numbers used by the
            // Pajek format.

            Dictionary <Int32, Int32> oVertexIDToNumber =
                new Dictionary <Int32, Int32>();

            IVertexCollection oVertices = graph.Vertices;

            StreamWriter oStreamWriter = new StreamWriter(stream, StreamEncoding);

            // Add the *vertices section.

            oStreamWriter.WriteLine(

                "*vertices {0}"
                ,
                oVertices.Count
                );

            Int32 iVertexNumber = 1;

            foreach (IVertex oVertex in oVertices)
            {
                // Format:
                //
                // 1 "vertex 1 name" x y z

                // Transform the vertex location.

                PointF oTransformedLocation = LayoutUtil.TransformPointF(
                    oVertex.Location, oRectangleTransformation);

                // Limit the range in case of rounding errors.

                Single fX = Math.Max(0F, oTransformedLocation.X);
                fX = Math.Min(1F, fX);

                Single fY = Math.Max(0F, oTransformedLocation.Y);
                fY = Math.Min(1F, fY);

                oStreamWriter.WriteLine(

                    "{0} \"{1}\" {2:N6} {3:N6} 0"
                    ,
                    iVertexNumber,
                    oVertex.Name,
                    fX,
                    fY
                    );

                oVertexIDToNumber.Add(oVertex.ID, iVertexNumber);

                iVertexNumber++;
            }

            IEdgeCollection oEdges = graph.Edges;

            GraphDirectedness eDirectedness = graph.Directedness;

            Boolean bSectionNameWritten = false;

            if (eDirectedness != GraphDirectedness.Directed)
            {
                // If appropriate, add the *edges section, which specifies
                // undirected edges.

                foreach (IEdge oEdge in oEdges)
                {
                    // The graph could be mixed.

                    if (oEdge.IsDirected)
                    {
                        continue;
                    }

                    if (!bSectionNameWritten)
                    {
                        oStreamWriter.WriteLine("*edges");

                        bSectionNameWritten = true;
                    }

                    WriteEdge(oEdge, oVertexIDToNumber, oStreamWriter);
                }
            }

            bSectionNameWritten = false;

            if (eDirectedness != GraphDirectedness.Undirected)
            {
                // If appropriate, add the *arcs section, which specifies
                // directed edges.

                foreach (IEdge oEdge in oEdges)
                {
                    // The graph could be mixed.

                    if (!oEdge.IsDirected)
                    {
                        continue;
                    }

                    if (!bSectionNameWritten)
                    {
                        oStreamWriter.WriteLine("*arcs");

                        bSectionNameWritten = true;
                    }

                    WriteEdge(oEdge, oVertexIDToNumber, oStreamWriter);
                }
            }

            oStreamWriter.Flush();
        }
        SetUnboundedLocations
        (
            ICollection <IVertex> verticesToLayOut,
            LayoutContext layoutContext,
            Single fTemperature,
            Boolean bAlsoSetVertexLocations
        )
        {
            Debug.Assert(verticesToLayOut != null);
            Debug.Assert(layoutContext != null);
            Debug.Assert(fTemperature > 0);
            AssertValid();

            // The following variables define the unbounded rectangle.

            TMathType tMinLocationX = Single.MaxValue;
            TMathType tMaxLocationX = Single.MinValue;

            TMathType tMinLocationY = Single.MaxValue;
            TMathType tMaxLocationY = Single.MinValue;

            foreach (IVertex oVertex in verticesToLayOut)
            {
                // Retrieve the object that stores calculated values for the
                // vertex.  We need the vertex's current unbounded location and
                // the displacement created by the repulsive and attractive forces
                // on the vertex.

                FruchtermanReingoldVertexInfo oVertexInfo =
                    (FruchtermanReingoldVertexInfo)oVertex.Tag;

                TMathType tUnboundedLocationX =
                    (TMathType)oVertexInfo.UnboundedLocationX;

                TMathType tUnboundedLocationY =
                    (TMathType)oVertexInfo.UnboundedLocationY;

                TMathType tDisplacementX = (TMathType)oVertexInfo.DisplacementX;
                TMathType tDisplacementY = (TMathType)oVertexInfo.DisplacementY;

                TMathType tDisplacement = (TMathType)Math.Sqrt(
                    (tDisplacementX * tDisplacementX) +
                    (tDisplacementY * tDisplacementY)
                    );

                if (tDisplacement != 0)
                {
                    // Calculate a new unbounded location, limited by the current
                    // temperature.

                    tUnboundedLocationX += (tDisplacementX / tDisplacement) *
                                           Math.Min(tDisplacement, (TMathType)fTemperature);

                    tUnboundedLocationY += (tDisplacementY / tDisplacement) *
                                           Math.Min(tDisplacement, (TMathType)fTemperature);
                }

                // Update the vertex's unbounded location.

                oVertexInfo.UnboundedLocationX = (Single)tUnboundedLocationX;
                oVertexInfo.UnboundedLocationY = (Single)tUnboundedLocationY;

                // Expand the unbounded rectangle if necessary.

                tMinLocationX = Math.Min(tUnboundedLocationX, tMinLocationX);
                tMaxLocationX = Math.Max(tUnboundedLocationX, tMaxLocationX);

                tMinLocationY = Math.Min(tUnboundedLocationY, tMinLocationY);
                tMaxLocationY = Math.Max(tUnboundedLocationY, tMaxLocationY);
            }

            if (!bAlsoSetVertexLocations)
            {
                return;
            }

            Debug.Assert(verticesToLayOut.Count != 0);

            Debug.Assert(tMinLocationX != Single.MaxValue);
            Debug.Assert(tMaxLocationX != Single.MinValue);
            Debug.Assert(tMinLocationY != Single.MaxValue);
            Debug.Assert(tMaxLocationY != Single.MinValue);

            // Get a Matrix that will transform vertex locations from coordinates
            // in the unbounded rectangle to cooordinates in the bounded graph
            // rectangle.

            Matrix oTransformationMatrix = LayoutUtil.GetRectangleTransformation(

                RectangleF.FromLTRB(
                    (Single)tMinLocationX,
                    (Single)tMinLocationY,
                    (Single)tMaxLocationX,
                    (Single)tMaxLocationY
                    ),

                layoutContext.GraphRectangle
                );

            // Transform the vertex locations.

            foreach (IVertex oVertex in verticesToLayOut)
            {
                FruchtermanReingoldVertexInfo oVertexInfo =
                    (FruchtermanReingoldVertexInfo)oVertex.Tag;

                PointF [] aoLocation = new PointF [] {
                    new PointF(
                        oVertexInfo.UnboundedLocationX,
                        oVertexInfo.UnboundedLocationY
                        )
                };

                oTransformationMatrix.TransformPoints(aoLocation);

                if (!VertexIsLocked(oVertex))
                {
                    oVertex.Location = aoLocation[0];
                }
            }
        }
Example #5
0
    TransformLayoutCore
    (
        IGraph graph,
        LayoutContext originalLayoutContext,
        LayoutContext newLayoutContext
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(originalLayoutContext != null);
        Debug.Assert(newLayoutContext != null);
        AssertValid();

        // Transform the graph's vertex locations.

        Matrix oTransformationMatrix = LayoutUtil.GetRectangleTransformation(
            originalLayoutContext.GraphRectangle,
            newLayoutContext.GraphRectangle
            );

        base.TransformLayoutCore(graph, originalLayoutContext,
            newLayoutContext);

        // Tranform the geometry metadata added by LayOutGraphCore().

        Object oValue;

        if ( graph.TryGetValue(
            ReservedMetadataKeys.SugiyamaComputedRadius, typeof(Single),
            out oValue) )
        {
            // Transforming the radius in the x-direction only isn't ideal, but
            // doing the transform properly would involve drawing the vertex as
            // an ellipse.

            PointF oTransformedRadius = LayoutUtil.TransformPointF(
                new PointF( (Single)oValue, 0 ), oTransformationMatrix
                );

            graph.SetValue(
                ReservedMetadataKeys.SugiyamaComputedRadius,
                oTransformedRadius.X
                );
        }

        foreach (IEdge oEdge in graph.Edges)
        {
            if ( !oEdge.TryGetValue(
                ReservedMetadataKeys.SugiyamaCurvePoints, typeof( PointF [] ),
                    out oValue
                ) )
            {
                continue;
            }

            PointF [] aoCurvePoints = ( PointF [] )oValue;

            oTransformationMatrix.TransformPoints(aoCurvePoints);

            oEdge.SetValue(ReservedMetadataKeys.SugiyamaCurvePoints,
                aoCurvePoints);

            PointF oEndpoint = (PointF)oEdge.GetRequiredValue(
                ReservedMetadataKeys.SugiyamaEndpoint, typeof(PointF)
                );

            oEdge.SetValue(
                ReservedMetadataKeys.SugiyamaEndpoint,
                LayoutUtil.TransformPointF(oEndpoint, oTransformationMatrix)
                );
        }
    }