# Draw network graph and get the coordinates of each node

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?

-

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]


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.

-
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
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... –  Guess who it is. Apr 24 '13 at 3:02

Build a graph and see what are the current coordinates:

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


Get coordinates via GraphEmbedding, then Rescale and verify:

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


-
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
@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