Skip to content

Commit a981ef8

Browse files
committed
Add a central force and ignore repulsion force if two points are too far from each other
1 parent a05e608 commit a981ef8

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

Sources/Layouts/ForceDirectedLayoutEngine.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ struct ForceDirectedLayoutEngine: LayoutEngine {
99
var springLength: CGFloat = 70
1010
var stiffness: CGFloat = 0.09
1111
var charge: CGFloat = 50
12+
var gravitationalConstant = CGFloat(20)
13+
var shieldDistanceSquared = CGFloat(250000)
1214

1315
func layout(from currentLayout: Layout,
1416
canvas: CGRect,
@@ -22,6 +24,7 @@ struct ForceDirectedLayoutEngine: LayoutEngine {
2224
for (index, position) in positions.enumerated() {
2325
forces[index] += repulsionForce(at: position, from: positions, skipIndex: index)
2426
forces[index] += springForce(at: position, from: edges[index])
27+
forces[index] += centralForce(at: position, from: canvas.center)
2528

2629
let nv = velocities[index] + forces[index]
2730
let d = nv.length
@@ -57,9 +60,19 @@ struct ForceDirectedLayoutEngine: LayoutEngine {
5760
guard index != skippedIndex else { continue }
5861

5962
let diff = point - other
60-
force += diff / (diff.lengthSquared + 0.00000001) * charge
63+
let diffSquared = diff.lengthSquared
64+
guard diffSquared < shieldDistanceSquared else {
65+
continue
66+
}
67+
force += diff / (diffSquared + 0.00000001) * charge
6168
}
6269

6370
return force
6471
}
72+
73+
private func centralForce(at point: CGPoint, from center: CGPoint) -> CGPoint {
74+
let diff = center - point
75+
let dist = diff.lengthSquared
76+
return dist > shieldDistanceSquared ? diff / dist * gravitationalConstant : .zero
77+
}
6578
}

0 commit comments

Comments
 (0)