Skip to content

Commit

Permalink
Merge pull request #41 from li3zhen1/TypedView
Browse files Browse the repository at this point in the history
Patch: graph state management and api update.
  • Loading branch information
li3zhen1 authored Jan 7, 2024
2 parents a81c887 + a74fd93 commit 3b6ebe6
Show file tree
Hide file tree
Showing 46 changed files with 939 additions and 446 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ func buildSimulation() -> Simulation3D<My3DForce> {
forceField: My3DForce()
)

<<<<<<< HEAD
for _ in 0..<720 {
=======
for i in 0..<720 {
>>>>>>> main
sim.tick()
}
return sim
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
B70B52AF2AF822FF00A1E6CD /* Grape in Frameworks */ = {isa = PBXBuildFile; productRef = B70B52AE2AF822FF00A1E6CD /* Grape */; };
B71759592AFBFC4B000DF006 /* Miserables.swift in Sources */ = {isa = PBXBuildFile; fileRef = B71759582AFBFC4B000DF006 /* Miserables.swift */; };
B717595B2AFBFDBD000DF006 /* Lattice.swift in Sources */ = {isa = PBXBuildFile; fileRef = B717595A2AFBFDBD000DF006 /* Lattice.swift */; };
<<<<<<< HEAD
B762092F2B49FCD000476B93 /* MermaidVisualization.swift in Sources */ = {isa = PBXBuildFile; fileRef = B762092E2B49FCD000476B93 /* MermaidVisualization.swift */; };
=======
B719E4112AE5FBFC009D6C24 /* ForceDirectedLatticeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B719E4102AE5FBFC009D6C24 /* ForceDirectedLatticeView.swift */; };
>>>>>>> main
B780DD7A2AF84ECB001C605F /* MyRing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B780DD792AF84ECB001C605F /* MyRing.swift */; };
B7AFA55B2ADF4997009C7154 /* ForceDirectedGraphExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7AFA55A2ADF4997009C7154 /* ForceDirectedGraphExampleApp.swift */; };
B7AFA55D2ADF4997009C7154 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7AFA55C2ADF4997009C7154 /* ContentView.swift */; };
Expand All @@ -24,7 +28,11 @@
/* Begin PBXFileReference section */
B71759582AFBFC4B000DF006 /* Miserables.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Miserables.swift; sourceTree = "<group>"; };
B717595A2AFBFDBD000DF006 /* Lattice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Lattice.swift; sourceTree = "<group>"; };
<<<<<<< HEAD
B762092E2B49FCD000476B93 /* MermaidVisualization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MermaidVisualization.swift; sourceTree = "<group>"; };
=======
B719E4102AE5FBFC009D6C24 /* ForceDirectedLatticeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ForceDirectedLatticeView.swift; sourceTree = "<group>"; };
>>>>>>> main
B780DD792AF84ECB001C605F /* MyRing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyRing.swift; sourceTree = "<group>"; };
B7AFA5572ADF4997009C7154 /* ForceDirectedGraphExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ForceDirectedGraphExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
B7AFA55A2ADF4997009C7154 /* ForceDirectedGraphExampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForceDirectedGraphExampleApp.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -69,7 +77,10 @@
isa = PBXGroup;
children = (
B780DD792AF84ECB001C605F /* MyRing.swift */,
<<<<<<< HEAD
=======
B719E4102AE5FBFC009D6C24 /* ForceDirectedLatticeView.swift */,
>>>>>>> main
B7AFA55A2ADF4997009C7154 /* ForceDirectedGraphExampleApp.swift */,
B7AFA55C2ADF4997009C7154 /* ContentView.swift */,
B7AFA55E2ADF4999009C7154 /* Assets.xcassets */,
Expand All @@ -78,6 +89,10 @@
B7AFA56E2ADF49D6009C7154 /* Data.swift */,
B71759582AFBFC4B000DF006 /* Miserables.swift */,
B717595A2AFBFDBD000DF006 /* Lattice.swift */,
<<<<<<< HEAD
B762092E2B49FCD000476B93 /* MermaidVisualization.swift */,
=======
>>>>>>> main
);
path = ForceDirectedGraphExample;
sourceTree = "<group>";
Expand Down Expand Up @@ -173,6 +188,10 @@
B7AFA55D2ADF4997009C7154 /* ContentView.swift in Sources */,
B719E4112AE5FBFC009D6C24 /* ForceDirectedLatticeView.swift in Sources */,
B7AFA56F2ADF49D6009C7154 /* Data.swift in Sources */,
<<<<<<< HEAD
B762092F2B49FCD000476B93 /* MermaidVisualization.swift in Sources */,
=======
>>>>>>> main
B71759592AFBFC4B000DF006 /* Miserables.swift in Sources */,
B7AFA55B2ADF4997009C7154 /* ForceDirectedGraphExampleApp.swift in Sources */,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,14 @@ enum ExampleKind {
case ring
case classicMiserable
case lattice
<<<<<<< HEAD
case mermaid

static let list: [ExampleKind] = [.ring, .classicMiserable, .lattice, .mermaid]
=======

static let list: [ExampleKind] = [.ring, .classicMiserable, .lattice]
>>>>>>> main
}

extension ExampleKind {
Expand All @@ -84,6 +90,11 @@ extension ExampleKind {
return "Miserables"
case .lattice:
return "Lattice"
<<<<<<< HEAD
case .mermaid:
return "Mermaid visualization"
=======
>>>>>>> main
}
}
}
Expand All @@ -105,6 +116,11 @@ struct ContentView: View {
MiserableGraph()
case .lattice:
Lattice()
<<<<<<< HEAD
case .mermaid:
MermaidVisualization()
=======
>>>>>>> main
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,44 @@ struct Lattice: View {
@inlinable
var body: some View {
ForceDirectedGraph($isRunning) {
<<<<<<< HEAD

Repeated(0..<(width*width)) { i in
let _i = Double(i / width) / Double(width)
let _j = Double(i % width) / Double(width)
=======
ForEach(Array(0..<(width*width)), id:\.self) { i in

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

>>>>>>> main
NodeMark(id: i, radius: 3.0)
.foregroundStyle(Color(red: 1, green: _i, blue: _j))
.stroke()
}
<<<<<<< HEAD

Repeated(edge) {
LinkMark(from: $0.0, to: $0.1)
}

=======
for l in edge {

LinkMark(from: l.0, to: l.1)
}
>>>>>>> main
} force: {
LinkForce(
originalLength: .constant(0.8),
stiffness: .weightedByDegree(k: { _, _ in 1})
)
ManyBodyForce(strength: -0.8)
<<<<<<< HEAD
=======

>>>>>>> main
}
.toolbar {
Button {
Expand All @@ -62,5 +80,9 @@ struct Lattice: View {
Text(isRunning ? "Pause" : "Start")
}
}
<<<<<<< HEAD

=======
>>>>>>> main
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
//
// MermaidVisualization.swift
// ForceDirectedGraphExample
//
// Created by li3zhen1 on 1/6/24.
//

import SwiftUI
import RegexBuilder
import Grape
import simd

let multipleNodeRegex = Regex {
"{"
ZeroOrMore(.whitespace)
ZeroOrMore {
Capture (OneOrMore(.word))
ZeroOrMore(.whitespace)
","
ZeroOrMore(.whitespace)
}
Capture (OneOrMore(.word))
ZeroOrMore(.whitespace)
"}"
}

let singleNodeRegex = Regex {
Capture( OneOrMore(.word) )
}

let mermaidLinkRegex = Regex {
singleNodeRegex
// ChoiceOf {
// singleNodeRegex
// multipleNodeRegex
// }
OneOrMore(.whitespace)
ChoiceOf {
"-->"
"<--"
"—>"
"<—"
"->"
"<-"
}

OneOrMore(.whitespace)
singleNodeRegex
}

func parseMermaid(
_ text: String
) -> ([String], [(String, String)]) {
let links = text.split(separator: "\n")
.compactMap {
if let results = $0.matches(of: mermaidLinkRegex).first {
return (String(results.output.1), String(results.output.2))
}
return nil
}
let nodes = Array(Set(links.flatMap { [$0.0, $0.1] }))
return (nodes, links)
}

func getInitialPosition(id: String, r: Double) -> SIMD2<Double> {
if let firstLetter = id.first?.unicodeScalars.first {
let deg = Double(firstLetter.value % 26) / 26 * 2 * .pi
return [cos(deg) * r, sin(deg) * r]
}
return .zero
}

struct MermaidVisualization: View {

@State private var text: String = """
Alice --> Bob
Bob --> Cindy
Alice --> Dan
Alice --> Cindy
Tom --> Bob
Tom --> Kate
Kate --> Cindy
"""

var parsedGraph: ([String], [(String, String)]) {
parseMermaid(text)
}

var body: some View {
ForceDirectedGraph {
Repeated(parsedGraph.0) { node in
NodeMark(id: node)
.symbol(RoundedRectangle(cornerSize: CGSize(width: 3, height: 3)))
.symbolSize(radius: 6)
.label(alignment: .bottom, offset: [0, 4]) {
Text(node)
}
}
Repeated(parsedGraph.1) { link in
LinkMark(from: link.0, to: link.1)
}
} force: {
ManyBodyForce()
LinkForce(originalLength: .constant(70))
CenterForce()
} emittingNewNodesWithStates: { id in
KineticState(position: getInitialPosition(id: id, r: 100))
}
.inspector(isPresented: .constant(true)) {
VStack {
Text("Edit the mermaid syntaxes to update the graph")
.font(.title)
TextEditor(text: $text)
.fontDesign(.monospaced)

}.padding(.top)
}


}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
//
<<<<<<< HEAD
// Miserables.swift
=======
// ForceDirectedGraphSwiftUIExample.swift
>>>>>>> main
// ForceDirectedGraphExample
//
// Created by li3zhen1 on 11/5/23.
Expand All @@ -8,6 +12,49 @@
import Foundation
import Grape
import SwiftUI
<<<<<<< HEAD
import Charts


struct MiserableGraph: View {

private let graphData = getData(miserables)

@State private var isRunning = false
@State private var opacity: Double = 0
@State private var inspectorPresented = false

var body: some View {

ForceDirectedGraph($isRunning) {

Repeated(graphData.nodes) { node in
NodeMark(id: node.id)
.symbol(.asterisk)
.symbolSize(radius: 9.0)
.stroke()
.foregroundStyle(
colors[node.group % colors.count]
.shadow(
.inner(
color: colors[node.group % colors.count].opacity(0.3),
radius: 3,
x: 0,
y: 1.5
)
)
)
.label(offset: [0.0, 12.0]) {
Text(node.id)
.font(.caption2)
}
}

Repeated(graphData.links) { l in
LinkMark(from: l.source, to: l.target)
}
//
=======
import ForceSimulation
import Charts

Expand Down Expand Up @@ -62,13 +109,32 @@ struct MiserableGraph: View {
// }
}
}
>>>>>>> main
} force: {
ManyBodyForce(strength: -20)
LinkForce(
originalLength: .constant(35.0),
stiffness: .weightedByDegree(k: { _, _ in 1.0})
)
CenterForce()
<<<<<<< HEAD
}
.onNodeTapped { node in
inspectorPresented = true
}
.opacity(opacity)
.animation(.easeInOut, value: opacity)
.inspector(isPresented: $inspectorPresented) {
Text("Hello")
}

.toolbar {
Button {
isRunning.toggle()
if opacity < 1 {
opacity = 1
}
=======
// CollideForce()
}
.onNodeTapped {
Expand All @@ -77,6 +143,7 @@ struct MiserableGraph: View {
.toolbar {
Button {
isRunning = !isRunning
>>>>>>> main
} label: {
Image(systemName: isRunning ? "pause.fill" : "play.fill")
Text(isRunning ? "Pause" : "Start")
Expand Down
Loading

0 comments on commit 3b6ebe6

Please sign in to comment.