Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question

2 Answers 2

up vote 3 down vote accepted

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.

share|improve this answer
    
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? –  skyork Apr 24 '13 at 2:59
1  
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... –  J. M. Apr 24 '13 at 3:02

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

share|improve this answer
    
This is neat. I can then get the transformed coordinates via GraphEmbedding[ SetProperty[g, VertexCoordinates -> 100 Rescale[GraphEmbedding[g]]]]. Thanks! –  skyork Apr 24 '13 at 4:02
1  
@skyork It is easier - the transformed coordinates are just: 100 Rescale[GraphEmbedding[g]] –  Vitaliy Kaurov Apr 24 '13 at 4:05
    
Great to know! Just starting to pick up Mathematica... Thanks for the help! –  skyork Apr 24 '13 at 4:15
    
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). –  skyork Apr 24 '13 at 17:20
    
@skyork GraphEmbedding[g] is just a set of points. Split them on separate X and Y coordinates, re-scale, and combine back. –  Vitaliy Kaurov Apr 24 '13 at 17:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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