forked from ThomWorm/Pandemics_Graph_Viz
-
Notifications
You must be signed in to change notification settings - Fork 0
/
addEdge.py
85 lines (69 loc) · 3.04 KB
/
addEdge.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May 15 11:45:07 2020
@author: aransil
"""
import math
# Start and end are lists defining start and end points
# Edge x and y are lists used to construct the graph
# arrowAngle and arrowLength define properties of the arrowhead
# arrowPos is None, 'middle' or 'end' based on where on the edge you want the arrow to appear
# arrowLength is the length of the arrowhead
# arrowAngle is the angle in degrees that the arrowhead makes with the edge
# dotSize is the plotly scatter dot size you are using (used to even out line spacing when you have a mix of edge lengths)
def addEdge(start, end, edge_x, edge_y, lengthFrac=1, arrowPos = None, arrowLength=0.025, arrowAngle = 30, dotSize=40):
# Get start and end cartesian coordinates
x0, y0 = start
x1, y1 = end
# Incorporate the fraction of this segment covered by a dot into total reduction
length = math.sqrt( (x1-x0)**2 + (y1-y0)**2 )
dotSizeConversion = .0565/20 # length units per dot size
convertedDotDiameter = dotSize * dotSizeConversion
lengthFracReduction = convertedDotDiameter / length
lengthFrac = lengthFrac - lengthFracReduction
# If the line segment should not cover the entire distance, get actual start and end coords
skipX = (x1-x0)*(1-lengthFrac)
skipY = (y1-y0)*(1-lengthFrac)
x0 = x0 + skipX/2
x1 = x1 - skipX/2
y0 = y0 + skipY/2
y1 = y1 - skipY/2
# Append line corresponding to the edge
edge_x.append(x0)
edge_x.append(x1)
edge_x.append(None) # Prevents a line being drawn from end of this edge to start of next edge
edge_y.append(y0)
edge_y.append(y1)
edge_y.append(None)
# Draw arrow
if not arrowPos == None:
# Find the point of the arrow; assume is at end unless told middle
pointx = x1
pointy = y1
eta = math.degrees(math.atan((x1-x0)/(y1-y0+ 0.0000001)))
if arrowPos == 'middle' or arrowPos == 'mid':
pointx = x0 + (x1-x0)/2
pointy = y0 + (y1-y0)/2
# Find the directions the arrows are pointing
signx = (x1-x0)/abs(x1- (x0 + 0.0000001) )
signy = (y1-y0)/abs(y1-y0 + 0.0000001)
# Append first arrowhead
dx = arrowLength * math.sin(math.radians(eta + arrowAngle))
dy = arrowLength * math.cos(math.radians(eta + arrowAngle))
edge_x.append(pointx)
edge_x.append(pointx - signx**2 * signy * dx)
edge_x.append(None)
edge_y.append(pointy)
edge_y.append(pointy - signx**2 * signy * dy)
edge_y.append(None)
# And second arrowhead
dx = arrowLength * math.sin(math.radians(eta - arrowAngle))
dy = arrowLength * math.cos(math.radians(eta - arrowAngle))
edge_x.append(pointx)
edge_x.append(pointx - signx**2 * signy * dx)
edge_x.append(None)
edge_y.append(pointy)
edge_y.append(pointy - signx**2 * signy * dy)
edge_y.append(None)
return edge_x, edge_y