Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating documentation for Lindenmayer #31

Merged
merged 23 commits into from
Jan 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
dddc7d7
clean up from rebase
heckj Jan 22, 2022
36ab099
enabling a local copy of Angle when SwiftUI's version isn't available…
heckj Jan 23, 2022
05eb1ef
trying out Info.plist files inline
heckj Jan 23, 2022
a71605c
adding some basic tree example assets
heckj Jan 23, 2022
5cea3e0
getting CLI mechanisms downfor swift 5.5
heckj Jan 23, 2022
06f7879
updating overview, stubbing in initial creating article
heckj Jan 23, 2022
ccc1bf6
renaming LSystem protocol to Lindenmayer
heckj Jan 23, 2022
7bdad4b
renaming basic and RNG Lsystem types
heckj Jan 23, 2022
79b2f7e
renaming DefinesRNG type
heckj Jan 23, 2022
409e5c6
fixed rename references in docc links
heckj Jan 23, 2022
66807a3
cleaning up and collapsing examples
heckj Jan 23, 2022
a89d007
fixing public initializer
heckj Jan 23, 2022
daa45cf
assets for the 2D examples
heckj Jan 23, 2022
25ab70d
referencing images in DocC for 2D fractal examples
heckj Jan 23, 2022
19e21e6
moved transforms into static funcs on SceneKitRenderer
heckj Jan 23, 2022
16bf3d4
swiftformat cleanup work
heckj Jan 23, 2022
fb29e06
optional inclusion of Squirrell3 RNG, and finished first round of bas…
heckj Jan 24, 2022
a356d12
adding curation to ContextualLsystem
heckj Jan 24, 2022
0e03f2b
updating docs, curation of examples
heckj Jan 24, 2022
77f38d0
curation for random and parameter sets of LSystems, and consistency c…
heckj Jan 24, 2022
d0dc45e
curation of Modules and Render Command types
heckj Jan 24, 2022
a7cfae3
rule docs for basic contextual and random, including curation
heckj Jan 24, 2022
84955f0
wrapping up initial curation pass
heckj Jan 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Package.resolved
.build/
.swiftpm
.vscode

.docc-build/
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
Expand Down
62 changes: 62 additions & 0 deletions CLI_notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
To build and view the documentation locally:

```
mkdir -p .build/symbol-graphs

swift build --target Lindenmayer \
--target LindenmayerViews \
-Xswiftc -emit-symbol-graph \
-Xswiftc -emit-symbol-graph-dir -Xswiftc .build/symbol-graphs

xcrun docc preview \
--fallback-display-name Lindenmayer \
--fallback-bundle-identifier Lindenmayer-swift \
--fallback-bundle-version 0.1.0 \
--additional-symbol-graph-dir .build/symbol-graphs
```

Should show something like:

```
========================================
Starting Local Preview Server
Address: http://localhost:8000/documentation/squirrel3
http://localhost:8000/documentation/lindenmayer
http://localhost:8000/documentation/lindenmayerviews
http://localhost:8000/documentation/scenekitdebugtools
========================================
```


To generate the HTML:

```
mkdir -p html
xcrun docc convert \
--output-path html \
--fallback-display-name Lindenmayer \
--fallback-bundle-identifier Lindenmayer-swift \
--fallback-bundle-version 0.1.0 \
--additional-symbol-graph-dir .build/symbol-graphs \
```

To get documentation coverage details:

```
xcrun docc convert \
--fallback-display-name Lindenmayer \
--fallback-bundle-identifier Lindenmayer-swift \
--fallback-bundle-version 0.1.0 \
--additional-symbol-graph-dir .build/symbol-graphs \
--experimental-documentation-coverage \
--level brief
```


```
--- Experimental coverage output enabled. ---
| Abstract | Curated | Code Listing
Types | 95% (112/118) | 60% (71/118) | 0.0% (0/118)
Members | 3.6% (350/9750) | 95% (9218/9750) | 0.0% (0/9750)
Globals | 41% (9/22) | 91% (20/22) | 0.0% (0/22)
```
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ let package = Package(
targets: [
.target(
name: "Lindenmayer",
dependencies: ["Squirrel3"]
dependencies: ["Squirrel3", "SceneKitDebugTools"]
),
.target(
name: "LindenmayerViews",
dependencies: ["Lindenmayer", "SceneKitDebugTools"]
),
.testTarget(
name: "LindenmayerTests",
dependencies: ["Lindenmayer", "Squirrel3"]
dependencies: ["Lindenmayer", "Squirrel3", "SceneKitDebugTools"]
),
]
)
68 changes: 68 additions & 0 deletions Sources/Lindenmayer/Angle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//
// Angel.swift
//
//
// Created by Joseph Heck on 1/22/22.
//

import Foundation
#if canImport(SwiftUI)
import SwiftUI
/// A geometric angle whose value you access in either radians or degrees.
public typealias Angle = SwiftUI.Angle
#else
/// A geometric angle whose value you access in either radians or degrees.
public typealias Angle = SimpleAngle
#endif

/// A geometric angle whose value you access in either radians or degrees.
///
/// ## Topics
///
/// ### Creating an Angle
///
/// - ``degrees(_:)``
/// - ``radians(_:)``
/// - ``init(degrees:)``
/// - ``init(radians:)``
/// - ``init()``
///
/// ### Inspecting the value of an Angle
///
/// - ``degrees``
/// - ``radians``
///
@frozen public struct SimpleAngle {
/// The value of the angle in radians.
public var radians: Double

/// The value of the angle in degrees.
@inlinable public var degrees: Double {
return radians * 180.0 / .pi
}

/// Creates a new Angle of zero radians.
@inlinable public init() {
radians = 0
}

/// Creates a new Angle with the value of radians you provide.
@inlinable public init(radians: Double) {
self.radians = radians
}

/// Creates a new Angle with the value of degrees you provide.
@inlinable public init(degrees: Double) {
radians = degrees * .pi / 180
}

/// Creates a new Angle with the value of radians you provide.
@inlinable public static func radians(_ radians: Double) -> Angle {
return Angle(radians: radians)
}

/// Creates a new Angle with the value of degrees you provide.
@inlinable public static func degrees(_ degrees: Double) -> Angle {
return Angle(degrees: degrees)
}
}
28 changes: 18 additions & 10 deletions Sources/Lindenmayer/BuiltinModules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,29 @@
//

import Foundation
import SwiftUI // for the 'Angle' type

/// A namespace for a collection of built-in modules for use in L-systems.
///
///
/// ## Topics
///
/// ### Built-in Modules
///
/// - ``Modules/Move``
/// - ``Modules/Draw``
/// - ``Modules/Branch``
/// - ``Modules/EndBranch``
/// - ``Modules/TurnLeft``
/// - ``Modules/TurnRight``
/// - ``Modules/PitchUp``
/// - ``Modules/PitchDown``
/// - ``Modules/RollLeft``
/// - ``Modules/RollRight``
/// - ``Modules/RollUpToVertical``
///
public enum Modules {}

public extension Modules {
// MARK: - An Example module -

struct Internode: Module {
// This is the kind of thing that I want external developers using the library to be able to create to represent elements within their L-system.
public var name = "I"
public var render2D: [TwoDRenderCmd] = [RenderCommand.Draw(length: 10)] // draws a line 10 units long
public init() {}
}

// MARK: - Built-in Modules that are effectively wrappers around specific rendering commands

/// A module that informs a renderer to turn left while rendering the L-system.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// LSystemBasic.swift
// ContextualLSystem.swift
//
//
// Created by Joseph Heck on 1/1/22.
Expand All @@ -10,15 +10,59 @@ import Foundation
/// A basic Lindenmayer system.
///
/// The basic Lindenmayer system doesn't use external parameters or a seed-able random number generator within its rules.
/// If you want to create an L-system that uses a seed-able random number generator, use ``LSystemRNG``.
/// If you want to create an L-system that uses a set of external parameters and a seed-able random number generator, use ``LSystemDefinesRNG``.
/// If you want to create an L-system that uses a seed-able random number generator, use ``RandomContextualLSystem``.
/// If you want to create an L-system that uses a set of external parameters and a seed-able random number generator, use ``ParameterizedRandomContextualLSystem``.
///
/// For more information on the background of Lindenmayer systems, see [Wikipedia's L-System](https://en.wikipedia.org/wiki/L-system).

public struct LSystemBasic: LSystem {
///
/// ## Topics
///
/// ### Creating and Updating L-systems
///
/// - ``ContextualLSystem/init(_:state:newStateIndicators:rules:)``
/// - ``ContextualLSystem/updatedLSystem(with:newItemIndicators:)``
///
/// ### Inspecting L-systems
///
/// - ``ContextualLSystem/state``
/// - ``ContextualLSystem/state(at:)``
/// - ``ContextualLSystem/newStateIndicators``
///
/// ### Adding Rules to an L-system
///
/// - ``ContextualLSystem/rewrite(_:produces:)``
/// - ``ContextualLSystem/rewrite(_:where:produces:)``
/// - ``ContextualLSystem/rules``
///
/// ### Adding Contextual Rules to an L-system
///
/// - ``ContextualLSystem/rewrite(leftContext:directContext:produces:)``
/// - ``ContextualLSystem/rewrite(directContext:rightContext:produces:)``
/// - ``ContextualLSystem/rewrite(leftContext:directContext:rightContext:produces:)``
///
/// ### Adding Contextual Rules with an evaluation closure to an L-system
///
/// - ``ContextualLSystem/rewrite(leftContext:directContext:where:produces:)``
/// - ``ContextualLSystem/rewrite(directContext:rightContext:where:produces:)``
/// - ``ContextualLSystem/rewrite(leftContext:directContext:rightContext:where:produces:)``
///
/// ### Evolving the L-system
///
/// - ``ContextualLSystem/evolve()``
/// - ``ContextualLSystem/evolved(iterations:)``
///
/// ### Resetting L-systems to their initial state
///
/// - ``ContextualLSystem/reset()``
public struct ContextualLSystem: LindenmayerSystem {
let axiom: [Module]

/// The sequence of modules that represents the current state of the L-system.
public let state: [Module]

/// An array of Boolean values that indicate if the state in the L-system was newly created in the evolution.
///
/// This array is primarily used for debugging purposes
public var newStateIndicators: [Bool]

/// The sequence of rules that the L-system uses to process and evolve its state.
Expand All @@ -30,6 +74,16 @@ public struct LSystemBasic: LSystem {
/// - parameters: A set of parameters accessible to rules for evaluation and production.
/// - prng: A psuedo-random number generator to use for stochastic rule productions.
/// - rules: A collection of rules that the Lindenmayer system applies when you call the evolve function.
///
/// Convenient initializers for creating contextual L-systems uses ``LSystem``, calling ``LSystem/create(_:)-632a3``, or ``LSystem/create(_:)-12ubu``.
/// For example:
/// ```
/// struct A: Module {
/// public var name = "A"
/// }
///
/// let algae = Lsystem.create(A())
/// ```
public init(_ axiom: [Module],
state: [Module]?,
newStateIndicators: [Bool]?,
Expand All @@ -56,18 +110,20 @@ public struct LSystemBasic: LSystem {
/// - Parameter state: The sequence of modules that represent the new state.
/// - Returns: A new L-system with the updated state that has the same rules.
///
/// This function is called from the common LSystem protocol's default implementation to generate an updated
/// This function is called from the common ``LindenmayerSystem`` protocol's default implementation to generate an updated
/// L-system with a set of new modules.
public func updatedLSystem(with state: [Module], newItemIndicators: [Bool]) -> Self {
return LSystemBasic(axiom, state: state, newStateIndicators: newItemIndicators, rules: rules)
return ContextualLSystem(axiom, state: state, newStateIndicators: newItemIndicators, rules: rules)
}


/// Resets the L-system to it's initial state, wiping out an existing state while keeping the rules.
/// - Returns: A new L-system with it's state reset to the initial state you set when you created the L-system.
public func reset() -> Self {
return LSystemBasic(axiom, state: nil, newStateIndicators: newStateIndicators, rules: rules)
return ContextualLSystem(axiom, state: nil, newStateIndicators: newStateIndicators, rules: rules)
}
}

public extension LSystemBasic {
public extension ContextualLSystem {
/// Adds a rewriting rule to the L-System.
/// - Parameters:
/// - direct: The type of module that the rule matches
Expand All @@ -81,7 +137,7 @@ public extension LSystemBasic {
let newRule = RewriteRuleDirect(direct: direct, where: evalClosure, produce: produceClosure)
var newRuleSet: [Rule] = rules
newRuleSet.append(contentsOf: [newRule])
return LSystemBasic(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
return ContextualLSystem(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
}

/// Adds a rewriting rule to the L-System.
Expand All @@ -95,7 +151,7 @@ public extension LSystemBasic {
let newRule = RewriteRuleDirect(direct: direct, where: nil, produce: produceClosure)
var newRuleSet: [Rule] = rules
newRuleSet.append(contentsOf: [newRule])
return LSystemBasic(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
return ContextualLSystem(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
}

/// Adds a rewriting rule to the L-System.
Expand All @@ -111,7 +167,7 @@ public extension LSystemBasic {
let newRule = RewriteRuleLeftDirect(leftType: leftContext, directType: directContext, where: evalClosure, produces: produceClosure)
var newRuleSet: [Rule] = rules
newRuleSet.append(contentsOf: [newRule])
return LSystemBasic(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
return ContextualLSystem(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
}

/// Adds a rewriting rule to the L-System.
Expand All @@ -125,7 +181,7 @@ public extension LSystemBasic {
let newRule = RewriteRuleLeftDirect(leftType: leftContext, directType: directContext, where: nil, produces: produceClosure)
var newRuleSet: [Rule] = rules
newRuleSet.append(contentsOf: [newRule])
return LSystemBasic(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
return ContextualLSystem(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
}

/// Adds a rewriting rule to the L-System.
Expand All @@ -141,7 +197,7 @@ public extension LSystemBasic {
let newRule = RewriteRuleDirectRight(directType: directContext, rightType: rightContext, where: evalClosure, produces: produceClosure)
var newRuleSet: [Rule] = rules
newRuleSet.append(contentsOf: [newRule])
return LSystemBasic(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
return ContextualLSystem(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
}

/// Adds a rewriting rule to the L-System.
Expand All @@ -155,7 +211,7 @@ public extension LSystemBasic {
let newRule = RewriteRuleDirectRight(directType: directContext, rightType: rightContext, where: nil, produces: produceClosure)
var newRuleSet: [Rule] = rules
newRuleSet.append(contentsOf: [newRule])
return LSystemBasic(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
return ContextualLSystem(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
}

/// Adds a rewriting rule to the L-System.
Expand All @@ -171,7 +227,7 @@ public extension LSystemBasic {
let newRule = RewriteRuleLeftDirectRight(leftType: leftContext, directType: directContext, rightType: rightContext, where: evalClosure, produces: produceClosure)
var newRuleSet: [Rule] = rules
newRuleSet.append(contentsOf: [newRule])
return LSystemBasic(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
return ContextualLSystem(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
}

/// Adds a rewriting rule to the L-System.
Expand All @@ -185,6 +241,6 @@ public extension LSystemBasic {
let newRule = RewriteRuleLeftDirectRight(leftType: leftContext, directType: directContext, rightType: rightContext, where: nil, produces: produceClosure)
var newRuleSet: [Rule] = rules
newRuleSet.append(contentsOf: [newRule])
return LSystemBasic(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
return ContextualLSystem(axiom, state: state, newStateIndicators: newStateIndicators, rules: newRuleSet)
}
}
Loading