Skip to content

Commit db89ed1

Browse files
committed
Remove force result builder
1 parent af933ac commit db89ed1

File tree

6 files changed

+135
-21
lines changed

6 files changed

+135
-21
lines changed

Examples/ForceDirectedGraphExample/ForceDirectedGraphExample/Lattice.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ struct Lattice: View {
5050
}
5151

5252
} force: {
53-
LinkForce<Int>(
53+
.link(
5454
originalLength: .constant(0.8),
5555
stiffness: .weightedByDegree { _, _ in 1.0 }
5656
)
57-
ManyBodyForce<Int>(strength: -0.8)
57+
.manyBody(strength: -0.8)
5858
}
5959
.toolbar {
6060
GraphStateToggle(graphStates: graphStates)

Examples/ForceDirectedGraphExample/ForceDirectedGraphExample/MermaidVisualization.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ struct MermaidVisualization: View {
9999
.stroke(.black, StrokeStyle(lineWidth: 2.0, lineCap: .round, lineJoin: .round))
100100

101101
} force: {
102-
ManyBodyForce<String>()
103-
LinkForce<String>(originalLength: .constant(70))
104-
CenterForce<String>()
102+
.manyBody()
103+
.link(originalLength: .constant(70))
104+
.center()
105105
} emittingNewNodesWithStates: { id in
106106
KineticState(position: getInitialPosition(id: id, r: 100))
107107
}

Examples/ForceDirectedGraphExample/ForceDirectedGraphExample/Miserables.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ struct MiserableGraph: View {
6666
}
6767

6868
} force: {
69-
ManyBodyForce<String>(strength: -20)
70-
CenterForce<String>()
71-
LinkForce<String>(
69+
.manyBody(strength: -20)
70+
.center()
71+
.link(
7272
originalLength: .constant(35.0),
7373
stiffness: .weightedByDegree { _, _ in 1.0}
7474
)

Examples/ForceDirectedGraphExample/ForceDirectedGraphExample/MyRing.swift

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct MyRing: View {
1515
@State var graphStates = ForceDirectedGraphState()
1616

1717
var body: some View {
18-
18+
1919
ForceDirectedGraph(states: graphStates) {
2020
Series(0..<20) { i in
2121
NodeMark(id: 3 * i + 0)
@@ -32,26 +32,29 @@ struct MyRing: View {
3232
.symbolSize(radius:6.0)
3333
.foregroundStyle(.yellow)
3434
.stroke(.clear)
35-
35+
3636
LinkMark(from: 3 * i + 0, to: 3 * i + 1)
3737
LinkMark(from: 3 * i + 1, to: 3 * i + 2)
3838

3939
LinkMark(from: 3 * i + 0, to: 3 * ((i + 1) % 20) + 0)
4040
LinkMark(from: 3 * i + 1, to: 3 * ((i + 1) % 20) + 1)
4141
LinkMark(from: 3 * i + 2, to: 3 * ((i + 1) % 20) + 2)
42-
42+
4343

4444
}
45-
.stroke(.black, StrokeStyle(lineWidth: 1.5, lineCap: .round, lineJoin: .round))
45+
.stroke(
46+
.black,
47+
StrokeStyle(lineWidth: 1.5, lineCap: .round, lineJoin: .round)
48+
)
4649

4750
} force: {
48-
ManyBodyForce<Int>(strength: -15)
49-
LinkForce<Int>(
51+
.manyBody(strength: -15)
52+
.link(
5053
originalLength: .constant(20.0),
5154
stiffness: .weightedByDegree { _, _ in 3.0}
5255
)
53-
CenterForce<Int>()
54-
CollideForce<Int>()
56+
.center()
57+
.collide()
5558
}
5659
.graphOverlay { proxy in
5760
Rectangle().fill(.clear).contentShape(Rectangle())

Sources/Grape/Descriptors/ForceDescriptor.swift

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,119 @@ public struct SealedForceDescriptor<NodeID: Hashable>: _ForceDescriptor {
6868
}
6969
}
7070

71+
72+
@inlinable
73+
@discardableResult
74+
public static func center(x: Double = 0.0, y: Double = 0.0, strength: Double = 0.5) -> Self {
75+
SealedForceDescriptor([.center(CenterForce(x: x, y: y, strength: strength))])
76+
}
77+
78+
@inlinable
79+
@discardableResult
80+
public static func manyBody(strength: Double = -30.0, mass: ManyBodyForce<NodeID>.NodeMass = .constant(1.0), theta: Double = 0.9) -> Self {
81+
SealedForceDescriptor([.manyBody(ManyBodyForce(strength: strength, mass: mass, theta: theta))])
82+
}
83+
84+
@inlinable
85+
@discardableResult
86+
public static func link(
87+
originalLength: LinkForce<NodeID>.LinkLength = .constant(30.0),
88+
stiffness: LinkForce<NodeID>.Stiffness = .weightedByDegree { _, _ in 1.0 },
89+
iterationsPerTick: UInt = 1
90+
) -> Self {
91+
SealedForceDescriptor([.link(LinkForce(originalLength: originalLength, stiffness: stiffness, iterationsPerTick: iterationsPerTick))])
92+
}
93+
94+
@inlinable
95+
@discardableResult
96+
public static func collide(
97+
strength: Double = 0.5,
98+
radius: CollideForce<NodeID>.CollideRadius = .constant(3.0),
99+
iterationsPerTick: UInt = 1
100+
) -> Self {
101+
SealedForceDescriptor([.collide(CollideForce(strength: strength, radius: radius, iterationsPerTick: iterationsPerTick))])
102+
}
103+
104+
@inlinable
105+
@discardableResult
106+
public static func position(
107+
direction: Kinetics2D.DirectionOfPositionForce,
108+
targetOnDirection: PositionForce<NodeID>.TargetOnDirection,
109+
strength: PositionForce<NodeID>.PositionStrength = .constant(1.0)
110+
) -> Self {
111+
SealedForceDescriptor([.position(PositionForce(direction: direction, targetOnDirection: targetOnDirection, strength: strength))])
112+
}
113+
114+
@inlinable
115+
@discardableResult
116+
public static func radial(
117+
center: SIMD2<Double> = .zero,
118+
strength: RadialForce<NodeID>.RadialStrength = .constant(1.0),
119+
radius: RadialForce<NodeID>.Radius = .constant(3.0)
120+
) -> Self {
121+
SealedForceDescriptor([.radial(RadialForce(center: center, strength: strength, radius: radius))])
122+
}
123+
124+
125+
@inlinable
126+
@discardableResult
127+
public consuming func center(x: Double = 0.0, y: Double = 0.0, strength: Double = 0.5) -> Self {
128+
storage.append(.center(CenterForce(x: x, y: y, strength: strength)))
129+
return self
130+
}
131+
132+
@inlinable
133+
@discardableResult
134+
public consuming func manyBody(strength: Double = -30.0, mass: ManyBodyForce<NodeID>.NodeMass = .constant(1.0), theta: Double = 0.9) -> Self {
135+
storage.append(.manyBody(ManyBodyForce(strength: strength, mass: mass, theta: theta)))
136+
return self
137+
}
138+
139+
@inlinable
140+
@discardableResult
141+
public consuming func link(
142+
originalLength: LinkForce<NodeID>.LinkLength = .constant(30.0),
143+
stiffness: LinkForce<NodeID>.Stiffness = .weightedByDegree { _, _ in 1.0 },
144+
iterationsPerTick: UInt = 1
145+
) -> Self{
146+
storage.append(.link(LinkForce(originalLength: originalLength, stiffness: stiffness, iterationsPerTick: iterationsPerTick)))
147+
return self
148+
}
149+
150+
@inlinable
151+
@discardableResult
152+
public consuming func collide(
153+
strength: Double = 0.5,
154+
radius: CollideForce<NodeID>.CollideRadius = .constant(3.0),
155+
iterationsPerTick: UInt = 1
156+
) -> Self {
157+
storage.append(.collide(CollideForce(strength: strength, radius: radius, iterationsPerTick: iterationsPerTick)))
158+
return self
159+
}
160+
161+
@inlinable
162+
@discardableResult
163+
public consuming func position(
164+
direction: Kinetics2D.DirectionOfPositionForce,
165+
targetOnDirection: PositionForce<NodeID>.TargetOnDirection,
166+
strength: PositionForce<NodeID>.PositionStrength = .constant(1.0)
167+
) -> Self{
168+
storage.append(.position(PositionForce(direction: direction, targetOnDirection: targetOnDirection, strength: strength)))
169+
return self
170+
}
171+
172+
@inlinable
173+
@discardableResult
174+
public consuming func radial(
175+
center: SIMD2<Double> = .zero,
176+
strength: RadialForce<NodeID>.RadialStrength = .constant(1.0),
177+
radius: RadialForce<NodeID>.Radius = .constant(3.0)
178+
) -> Self{
179+
storage.append(.radial(RadialForce(center: center, strength: strength, radius: radius)))
180+
return self
181+
}
182+
183+
71184
@inlinable
72185
init(_ storage: [Entry] = []) {
73186
self.storage = storage

Sources/Grape/Views/ForceDirectedGraph.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,9 @@ where NodeID == Content.NodeID {
5454
/// The default force to be applied to the graph
5555
///
5656
/// - Returns: The default forces
57-
@SealedForceDescriptorBuilder<NodeID>
5857
@inlinable
5958
static public func defaultForce() -> SealedForceDescriptor<NodeID> {
60-
LinkForce<NodeID>()
61-
CenterForce<NodeID>()
59+
.link().center()
6260
}
6361

6462
/// Creates a force-directed graph view.
@@ -81,7 +79,7 @@ where NodeID == Content.NodeID {
8179
states: ForceDirectedGraphState = ForceDirectedGraphState(),
8280
ticksPerSecond: Double = 60.0,
8381
@GraphContentBuilder<NodeID> graph: () -> Content,
84-
@SealedForceDescriptorBuilder<NodeID> force: () -> SealedForceDescriptor<NodeID> = Self.defaultForce,
82+
force buildForce: () -> SealedForceDescriptor<NodeID> = defaultForce,
8583
emittingNewNodesWithStates: @escaping (NodeID) -> KineticState = defaultKineticStateProvider
8684
) {
8785

@@ -90,7 +88,7 @@ where NodeID == Content.NodeID {
9088

9189
self._graphRenderingContextShadow = gctx
9290

93-
self._forceDescriptors = force()
91+
self._forceDescriptors = buildForce()
9492

9593
self.model = .init(
9694
gctx,

0 commit comments

Comments
 (0)