4
$\begingroup$

I would like to draw an undirected graph by specifying the nodes and the edges among them. This is currently done by, for example:

GraphPlot[{1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6, 6 -> 7, 7 -> 8, 8 -> 1}]

In addition, I would like to lay out the graph within a specified region of x-y coordinate system. Imagine this specified region as the 'canvas' in which the above circle is drawn. For instance, such a canvas can be specified by four points such as (0, 0), (100, 0), (100, 100), (0, 100).

Lastly, I would like to get the coordinates for each of the nodes of the graph drawn within the specified 'canvas'.

What is the right workflow in Mathematica to accomplish each of the steps above?

$\endgroup$

2 Answers 2

3
$\begingroup$

I guess something like this:

net = {1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6, 6 -> 7, 7 -> 8, 8 -> 1}; gp = GraphPlot[net];
pts = First[Cases[gp, GraphicsComplex[pts_, others___] :> pts, ∞]];

{xb, yb} = Composition[Through, {Min, Max}] /@ Transpose[pts];
Show[gp /. 
     GraphicsComplex[pts_, others___] :> 
     GraphicsComplex[MapThread[Rescale, {#, {xb, yb}, {{0, 100}, {0, 100}}}] & /@ pts,
                     others],
     Frame -> True, FrameTicks -> True]

rescaled graph

Alternatively, one could have done

GraphPlot[net, Frame -> True, FrameTicks -> True, 
          VertexCoordinateRules -> MapIndexed[First[#2] -> #1 &, 
            MapThread[Rescale, {#, {xb, yb}, {{0, 100}, {0, 100}}}] & /@ pts]]

The key is in extracting the coordinates from the handy structure provided by GraphicsComplex[], and then applying the function Rescale[] appropriately.

$\endgroup$
2
  • $\begingroup$ Thanks a lot! A related question, is it possible to tweak the layout of the graph within the specified region? For example, how do I rotate the graph by some degree clockwise or anti-clockwise? $\endgroup$
    – skyork
    Apr 24, 2013 at 2:59
  • 1
    $\begingroup$ Sure, you could do something like Composition[RotationTransform[π/4], MapThread[Rescale, {#, {xb, yb}, {{0, 100}, {0, 100}}}] &] /@ pts to rotate by 45 degrees anticlockwise, for instance... $\endgroup$ Apr 24, 2013 at 3:02
4
$\begingroup$

Build a graph and see what are the current coordinates:

g = CycleGraph[8, Axes -> True, GraphStyle -> "SmallNetwork"]

enter image description here

Get coordinates via GraphEmbedding, then Rescale and verify:

SetProperty[g, VertexCoordinates -> 100 Rescale[GraphEmbedding[g]]]

enter image description here

$\endgroup$
7
  • $\begingroup$ This is neat. I can then get the transformed coordinates via GraphEmbedding[ SetProperty[g, VertexCoordinates -> 100 Rescale[GraphEmbedding[g]]]]. Thanks! $\endgroup$
    – skyork
    Apr 24, 2013 at 4:02
  • 1
    $\begingroup$ @skyork It is easier - the transformed coordinates are just: 100 Rescale[GraphEmbedding[g]] $\endgroup$ Apr 24, 2013 at 4:05
  • $\begingroup$ Great to know! Just starting to pick up Mathematica... Thanks for the help! $\endgroup$
    – skyork
    Apr 24, 2013 at 4:15
  • $\begingroup$ a quick follow-up question, what is the neatest way to generalize your approach to re-scale the graph to any given region? e.g. re-position the above circle at the center of the region defined by points (0, 0), (0, 100), (150, 100), (0, 150). $\endgroup$
    – skyork
    Apr 24, 2013 at 17:20
  • $\begingroup$ @skyork GraphEmbedding[g] is just a set of points. Split them on separate X and Y coordinates, re-scale, and combine back. $\endgroup$ Apr 24, 2013 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.