Skip to content

Commit

Permalink
Merge pull request #40 from li3zhen1/dev
Browse files Browse the repository at this point in the history
Update SwiftUI View implementations
  • Loading branch information
li3zhen1 authored Jan 3, 2024
2 parents 0d37f24 + acccb51 commit bf540e7
Show file tree
Hide file tree
Showing 71 changed files with 3,606 additions and 1,119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ extension ExampleKind {

struct ContentView: View {

@State var selection: ExampleKind = .ring
@State var selection: ExampleKind = .classicMiserable

var body: some View {
NavigationSplitView {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,21 @@ struct Lattice: View {

@inlinable
var body: some View {
ForceDirectedGraph(isRunning: $isRunning) {
for i in 0..<(width*width) {
ForceDirectedGraph($isRunning) {
ForEach(Array(0..<(width*width)), id:\.self) { i in

let _i = Double(i / width) / Double(width)
let _j = Double(i % width) / Double(width)


NodeMark(id: i, fill: .init(red: 1, green: _i, blue: _j), radius: 3.0, strokeColor: .white, strokeWidth: 0.5)
NodeMark(id: i, radius: 3.0)
.foregroundStyle(Color(red: 1, green: _i, blue: _j))
.stroke()
}
for l in edge {

LinkMark(from: l.0, to: l.1)
}
} forceField: {
} force: {
LinkForce(
originalLength: .constant(0.8),
stiffness: .weightedByDegree(k: { _, _ in 1})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Foundation
import Grape
import SwiftUI
import ForceSimulation
import Charts


//struct MyForceField: ForceField {
Expand All @@ -33,10 +34,8 @@ struct MiserableGraph: View {
let graphData = getData(miserables)

var body: some View {
ForceDirectedGraph(isRunning: $isRunning) {
for i in graphData.nodes.indices {
NodeMark(id: i, fill: colors[graphData.nodes[i].group % colors.count], radius: 3.0)
}
ForceDirectedGraph($isRunning) {

for l in graphData.links {
let fromID = graphData.nodes.firstIndex { mn in
mn.id == l.source
Expand All @@ -46,14 +45,34 @@ struct MiserableGraph: View {
}!
LinkMark(from: fromID, to: toID)
}
} forceField: {
ForEach(graphData.nodes.indices, id: \.self) { i in
NodeMark(id: i)
.symbol(.asterisk)
.symbolSize(radius: 12.0)
.foregroundStyle(
colors[graphData.nodes[i].group % colors.count]
.shadow(.inner(color:colors[graphData.nodes[i].group % colors.count].opacity(0.3), radius: 3, x:0, y: 1.5))
.shadow(.drop(color:colors[graphData.nodes[i].group % colors.count].opacity(0.12), radius: 12, x:0, y: 8))
)
.stroke()
.label(offset: CGVector(dx: 0.0, dy: 12.0)) {
// if i.isMultiple(of: 5) {
Text(graphData.nodes[i].id)
.font(.title3)
// }
}
}
} force: {
ManyBodyForce(strength: -20)
LinkForce(
originalLength: .constant(35.0),
stiffness: .weightedByDegree(k: { _, _ in 1.0})
)
CenterForce()
CollideForce()
// CollideForce()
}
.onNodeTapped {
print($0)
}
.toolbar {
Button {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,20 @@ struct MyRing: View {
var body: some View {


ForceDirectedGraph(isRunning: $isRunning) {
for i in 0..<20 {
NodeMark(id: 3 * i + 0, fill: .green)
NodeMark(id: 3 * i + 1, fill: .blue, radius: 5.0)
NodeMark(id: 3 * i + 2, fill: .yellow)
ForceDirectedGraph($isRunning) {
ForEach(Array(0..<20), id: \.self) { i in
NodeMark(id: 3 * i + 0)
.symbol(.circle)
.symbolSize(radius:4.0)
.foregroundStyle(.green)
NodeMark(id: 3 * i + 1)
.symbol(.pentagon)
.symbolSize(radius:5.0)
.foregroundStyle(.blue)
NodeMark(id: 3 * i + 2)
.symbol(.circle)
.symbolSize(radius:6.0)
.foregroundStyle(.yellow)

LinkMark(from: 3 * i + 0, to: 3 * i + 1)
LinkMark(from: 3 * i + 1, to: 3 * i + 2)
Expand All @@ -47,7 +56,7 @@ struct MyRing: View {
LinkMark(from: 3 * i + j, to: 3 * ((i + 1) % 20) + j)
}
}
} forceField: {
} force: {
ManyBodyForce(strength: -15)
LinkForce(
originalLength: .constant(20.0),
Expand Down
18 changes: 9 additions & 9 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ let package = Package(
],

dependencies: [
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"),
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0")
],

targets: [

.target(
name: "ForceSimulation",
path: "Sources/ForceSimulation"
Expand All @@ -41,8 +41,8 @@ let package = Package(
name: "Grape",
dependencies: ["ForceSimulation"],
path: "Sources/Grape"
// link ForceSimulation in release mode
// swiftSettings: [.unsafeFlags(["-Xfrontend", "-disable-availability-checking"])]
// link ForceSimulation in release mode
// swiftSettings: [.unsafeFlags(["-Xfrontend", "-disable-availability-checking"])]
),

.testTarget(
Expand All @@ -54,10 +54,10 @@ let package = Package(
name: "ForceSimulationTests",
dependencies: ["ForceSimulation"]
),
// .testTarget(
// name: "GrapeTests",
// dependencies: ["Grape"]
// ),

.testTarget(
name: "GrapeTests",
dependencies: ["Grape"]
),
]
)
18 changes: 14 additions & 4 deletions Sources/ForceSimulation/ForceProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ public protocol ForceProtocol<Vector> {

/// Takes a simulation state and modifies its node positions and velocities.
/// This is executed in each tick of the simulation.
@inlinable func apply()
// @inlinable func apply()


/// Takes a simulation state and modifies its node positions and velocities.
/// This is executed in each tick of the simulation.
@inlinable func apply(to kinetics: inout Kinetics<Vector>)

/// Bind to a kinetic system that describes the state of all nodes in your simulation.
/// This has to be called before `apply` is called.
Expand Down Expand Up @@ -41,7 +46,7 @@ extension Kinetics3D.RadialForce: Force3D {}
extension Kinetics3D.EmptyForce: Force3D {}
extension CompositedForce: Force3D where Vector == SIMD3<Float> {}

public protocol ForceDescriptor {
public protocol ForceDescriptor: Equatable {
associatedtype ConcreteForce: ForceProtocol
func createForce() -> ConcreteForce
}
Expand All @@ -58,9 +63,14 @@ where Vector: SimulatableVector & L2NormCalculatable {
}

extension ForceField {
// @inlinable
// public func apply() {
// self.force.apply()
// }

@inlinable
public func apply() {
self.force.apply()
public func apply(to kinetics: inout Kinetics<Vector>) {
self.force.apply(to: &kinetics)
}

@inlinable
Expand Down
14 changes: 9 additions & 5 deletions Sources/ForceSimulation/Forces/CenterForce.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@ extension Kinetics {
/// See [Collide Force - D3](https://d3js.org/d3-force/collide).
public struct CenterForce: ForceProtocol {

@usableFromInline var kinetics: Kinetics! = nil
// @usableFromInline var kinetics: Kinetics! = nil

@inlinable
public func apply() {
assert(self.kinetics != nil, "Kinetics not bound to force")
fatalError()
}

@inlinable
public func apply(to kinetics: inout Kinetics) {
var meanPosition = Vector.zero
let positionBufferPointer = kinetics.position.mutablePointer
for i in kinetics.range {
for i in 0..<kinetics.validCount {
meanPosition += positionBufferPointer[i] //.position
}
let delta = meanPosition * (self.strength / Vector.Scalar(kinetics.validCount))
Expand All @@ -22,9 +26,10 @@ extension Kinetics {
positionBufferPointer[i] -= delta
}
}

@inlinable
public mutating func bindKinetics(_ kinetics: Kinetics) {
self.kinetics = kinetics
// self.kinetics = kinetics
}

public var center: Vector
Expand All @@ -38,7 +43,6 @@ extension Kinetics {
self.strength = strength
}


@inlinable
public func dispose() {}

Expand Down
Loading

0 comments on commit bf540e7

Please sign in to comment.