81 lines
2.4 KiB
Python
81 lines
2.4 KiB
Python
import math
|
|
|
|
import numpy as np
|
|
|
|
from src import plot
|
|
|
|
def convex_hull(G):
|
|
# gift wrapping algorithm
|
|
pos = G.vp["pos"]
|
|
x = []
|
|
y = []
|
|
for v in G.vertices():
|
|
# print(pos[v])
|
|
ver = pos[v]
|
|
x.append(ver[0])
|
|
y.append(ver[1])
|
|
|
|
min_x = min(x)
|
|
min_y = min(y)
|
|
max_x = max(x)
|
|
max_y = max(y)
|
|
pos = np.stack((np.array(x), np.array(y)), axis=-1)
|
|
|
|
convex_hull = []
|
|
hull_point = np.array([min_x,pos[np.argmin(x)][1]])
|
|
convex_hull.append(hull_point)
|
|
endpoint = None
|
|
i = 0
|
|
while not plot.Vector.eql(endpoint, convex_hull[0]):
|
|
endpoint = pos[0]
|
|
for point in pos:
|
|
if plot.Vector.eql(endpoint, hull_point) or plot.Vector.cross_z(plot.Vector.vec(convex_hull[i], endpoint), plot.Vector.vec(convex_hull[i], point)) < 0:
|
|
endpoint = point
|
|
i += 1
|
|
hull_point = endpoint
|
|
convex_hull.append(hull_point)
|
|
return convex_hull
|
|
|
|
def correct(G, centrality, m_opt, c0_opt, b_opt):
|
|
"""
|
|
Correct a given centrality through the calculated model.
|
|
@param pos [Array-2d] Positions of points (i.e. `g.vp["pos"].get_2d_array()`)
|
|
@param centrality [VertexPropertyMap] Result of a centrality calculation of `graph-tool` on graph G
|
|
@param m_opt [Float] Model m value (slope of linear function)
|
|
@param c0_opt [Float] Model c0 value (offset of linear function)
|
|
@param b_opt [Float] Model b value (intersection point)
|
|
@return [VertexPropertyMap] Corrected centrality values based on @param centrality
|
|
"""
|
|
corrected_metric = centrality
|
|
pos = G.vp["pos"]
|
|
x = []
|
|
y = []
|
|
for v in G.vertices():
|
|
# print(pos[v])
|
|
ver = pos[v]
|
|
x.append(ver[0])
|
|
y.append(ver[1])
|
|
|
|
keys = iter(centrality.a)
|
|
hull = convex_hull(G)
|
|
|
|
points = np.stack((np.array(x), np.array(y)), axis=-1)
|
|
for point in pos:
|
|
min_distance = math.inf
|
|
key = next(keys)
|
|
for edge in hull:
|
|
vector = plot.Vector.vec(point, edge)
|
|
distance = plot.Vector.vec_len(vector)
|
|
if distance < min_distance:
|
|
min_distance = distance
|
|
if min_distance <= b_opt:
|
|
# requires correction
|
|
value = centrality[key]
|
|
delta = (m_opt * b_opt) - (m_opt * min_distance)
|
|
corrected_metric[key] = value + delta
|
|
else:
|
|
# unaffected by boundary
|
|
corrected_metric[key] = centrality[key]
|
|
|
|
return corrected_metric
|