Get nodes positions in a randomly generated graph
Check nx.spring_layout
docs here, look for the scale
and k
parameters:
scale (number (default: 1)) – Scale factor for positions. Not used unless fixed is None.
k (float (default=None)) – Optimal distance between nodes. If None the distance is set to 1/sqrt(n) where n is the number of nodes. Increase this value to move nodes farther apart.
As to getting integer coordinates, you can easily do this with int
.
positions = { node: (int(pos[0]),int(pos[1])) for node,pos in node_positions.items() }
[Edit]k
is the parameter for Fruchterman-Reingold layout algorithm, it is kind of strength of repulsion between nodes.
I'd better show what it does (the same graph layed out with different k's):
k=0.001
k=0.1
What is the best way compare two nodes coordinates?
If I understand your question correctly, you want to check the closeness between two points (positions) which may or may not be far apart from each other.
Check out this function first:
int get_distance(std::pair<int, int> const pos_a, std::pair<int, int> const pos_b)
{
auto const distance_x = pos_a.first >= pos_b.first ? pos_a.first - pos_b.first : pos_b.first - pos_a.first;
auto const distance_y = pos_a.second >= pos_b.second ? pos_a.second - pos_b.second : pos_b.second - pos_a.second;
if (distance_x != 0 && distance_y != 0)
return int(round(sqrt(distance_x * distance_x + distance_y * distance_y)));
if (distance_x == 0)
return distance_y;
return distance_x;
}
Here, it calculates the distance between two points by subtracting it with the greatest number (Hence the two beginning statements) and the operator used is a Ternary Operator. (Click on the link if you don't know what that is)
The third line is an if statement evaluating whether both the acquired distances are non-zero because if they are, then they are on the same line vertically or horizontally...
If both are non-zero numbers, then square root sum of squares of both distance x and y is rounded off to the nearest integer and then cast itself to an integer (Since the return type is int)
On the other hand, if any one of them is a zero number (Hence, on the same line), then the distance X or Y will be returned respectively based on the axis of the line (Vertical or Horizontal, hence distance_x == 0
and distance_y == 0
)
Now, for your other problem, viz. Closeness, which was mentioned above, one way is to declare an enumerator that stores the value for this kind of thing...
Example:
enum Distance
{
DISTANCE_VERY_CLOSE = 1,
DISTANCE_CLOSE,
DISTANCE_RELATIVELY_CLOSE,
DISTANCE_RELATIVELY_FAR,
DISTANCE_FAR,
DISTANCE_VERY_FAR,
DISTANCE_EXTREMELY_FAR
};
Then this enumerator will keep track of the distance for you, so you just need to use this macro to convert an integer to
Distance
(The enumerator)...
#define TO_DISTANCE(distance) ((distance) > 7 ? Distance(7) : Distance(distance))
This is a simple macro that just simply casts an integer to the enumerator and casts the digit 7 if the distance is more than 7 (Hence,
DISTANCE_EXTREMELY_FAR
). However, you can go ahead and add more inside the enumerator if you want. (Just remember to change 7 to the value the lastenum
member has)
Example use of the above method:
int main()
{
auto const dist = TO_DISTANCE(get_distance(std::make_pair(20, 20), std::make_pair(30, 30)));
accuracy *= dist; // Multiplying accuracy to distance (Hence, increases)
// Note: The accuracy needs to be at least 1 or more for this to work...
// You can check the "closeness" like this...
if (dist == DISTANCE_FAR)
std::cout << "They are far away from each other" << std::endl;
// Some other code goes here ...
return 0;
}
Kind regards,
Ruks.
How to change node positions in networkx graph?
You can pass the position dictionary (keys are nodes, values are 2-d coordinates) to the more general draw_networkx
function using the pos
argument:
nx.draw_networkx(G,pos= positions,with_labels=True,node_color=node_color,node_size=500)
Note that the nx.draw_shell
will layout your network according to a shell layout algorithm.
Drawing nodes of multigraph in fixed position
You can set the attributes before you convert the graph to a Pydot object:
import networkx as nx
graph= nx.MultiGraph()
#add 4 nodes in the vertexs of a square. X and Y are the coordinates
graph.add_node(1,x=100,y=100)
graph.add_node(2,x=100,y=200)
graph.add_node(3,x=200,y=100)
graph.add_node(4,x=200,y=200)
graph.add_edge(1,2)
graph.add_edge(2,3)
graph.add_edge(3,4)
graph.add_edge(4,1)
# assign positions
for n in graph:
graph.node[n]['pos'] = '"%d,%d"'%(graph.node[n]['x'], graph.node[n]['y'])
p = nx.to_pydot(graph)
print p.to_string()
p.write('foo.dot')
# run neato -n2 -Tpng foo.dot >foo.png
The output is:
graph G {
1 [y=100, x=100, pos="100,100"];
2 [y=200, x=100, pos="100,200"];
3 [y=100, x=200, pos="200,100"];
4 [y=200, x=200, pos="200,200"];
1 -- 2 [key=0];
1 -- 4 [key=0];
2 -- 3 [key=0];
3 -- 4 [key=0];
}
Run neato -n2 -Tpng foo.dot >foo.png
(the -n2 keeps your node positions)
Related Topics
How to Convert a Unix Timestamp to Datetime and Vice Versa
Parsing CSV Files in C#, With Header
Webbrowser Control in a New Thread
Split List into Sublists With Linq
How to Add User-Supplied Input to an SQL Statement
Mvvm: Tutorial from Start to Finish
Windows Service Not Shown in Add Remove Programs Under Control Panel
Why Saving Changes to a Database Fails
C# Difference Between == and Equals()
The Calling Thread Cannot Access This Object Because a Different Thread Owns It
How to Auto-Generate a C# Class File from a Json String
How to Make a Textbox That Only Accepts Numbers
How to Dynamically Compile and Execute C# Code Fragments
The Entity Cannot Be Constructed in a Linq to Entities Query