A swift library that implements a parametric Lindenmayer system and related SwiftUI views for presentation of the results of your systems

Overview

Lindenmayer

Build Platforms Swift 5.5 License Twitter

The package provides a library you can expand upon to develop your own Lindenmayer systems, directly in the Swift programming language. While the package includes a number example L-systems, the primary intent is to allow you to create L-systems with rules and modules that you define. This implementation provides support for context sensitive, and parametric grammars when creating your L-system.

The library provides 2D and 3D representation rendering of a current L-system states, including some SwiftUI views that you can use to display either 2D or 3D results:

The repository has Discussions enabled if you have questions, as well as issues logged for planned improvements.

Contributions are welcome - as discussion, feedback, questions, or code.

Inspiration

A combination of influences led to this development, initial as an experiment and general exploration. One part was the lindenmayer swift playground by @henrinormak, which implements a great single-character representation which is perfect for exploring fractal systems. That, in turn, was built on the work of Aristid Lindenmayer in the book The Algorithmic Beauty of Plants. The research that Aristid Lindenmayer started continues to be expanded by Professor Przemyslaw Prusinkiewicz with generous publications of research papers on the site Algorithmic Botany.

A couple of the papers expand on the tooling to create and evaluate L-systems, and their advances allow for interesting new capabilities to be expressed in the L-systems:

The features that I was most interested in leveraging:

  • Parameters within an L-system's modules and exposing them to grammar evaluation and production choices (parametric L-systems).
  • The introduction of random values with those parameters (stochastic grammars).

While this project can be implemented using an interpreter, I wanted to see how far I could leverage the Swift language. This project attempts to follow in the conceptual footsteps of the L+C language to create a mechanism to create L-systems that compile down to machine code for efficiency of execution.

Comments
  • `@V` state element (aka `$` in ABOP) isn't rendering out correctly

    `@V` state element (aka `$` in ABOP) isn't rendering out correctly

    Fundamentally, the example trees rendered with the L-systems taken directly from The Algorithmic Beauty of Plants aren't resulting the same visualizations as described in the book. They're close, but there's complication - I think - around a specific symbol and what it's doing: @V in the implementation research paper, and $ in the book itself.

    As an example, compare the results for the following sympodial and monopodial trees: lindenmayer2 original2 lindenmayer1 original1

    I suspect part of the core of this issue is that what I'm doing to create the rotations for the $ symbol is resulting in a rotation that is far too vertically oriented.

    I thought perhaps I had confused basic transforms and headings, but in reviewing the relevant code (https://github.com/heckj/Lindenmayer/blob/main/Sources/Lindenmayer/SceneKitRenderer.swift#L181-L214), I seem to have accounted for the corrected heading.

    Since I've been mentally confusing directions, I suspect that I need to add a debugging view (#26), as well as potentially tests, to generate the relevant objects and then interrogate them to verify rotations, translations, etc.

    bug 
    opened by heckj 5
  • 3D rendering debug view

    3D rendering debug view

    3D view for debugging the output of an L-system rendered into a 3D object using SceneKitRenderer.

    • enable control that shows, and allows for, stepping through the entire state sequence to add in the nodes into 3D under user control, rather than all at once.
      • as a baseline, maybe a stepper, but the L-system state size gets pretty darn huge (1000's -> 1,000,000's pretty quick) - so something where you can drag an interactive slider - or use held-down-key controls to indicate rapid movement as well as fine grained control would be useful.
    • enable some coloring or highlighting options that can show the generation of a given state element (what iteration revolution is was created upon)
    • allow the visualization, and then selection, of the state sequence and which that corresponds to within the tree.
    • given a static element that doesn't change with further generations, allow a means of showing the difference of the "new growth" segment that can appear right after with a sort of highly localized "diff state" view between two evolutions.
    • consider creating, and embedding, a unique ID with each state element so that the 3D object can be queried and manipulated after generation for highlighting based on the index of the original state array.
    • enable a 3D component that shows the current "state" direction and heading
    • look into how hard it would be to show rotation operations as animated updates to the current state 3D indicator, so you can see what rotation is actually happening
    • enable the evolution to be controlled in this view so that you can selectively move forward (and backward) in iterations.
    • enable parameter value application prior to evolution, and resetting or controlling the RND seed element from the master debug view.
    enhancement 
    opened by heckj 3
  • Error message 'The target type,

    Error message 'The target type, "ClangTarget" is not supported.' when using within Swift Playgrounds iOS

    I tried to include the library into a Swift Playgrounds iOS (v4) app as a swift package - and it immediately displayed this error on loading:

    The target type, "ClangTarget" is not supported.

    Unfortunately, this is a limitation of Swift Playgrounds iOS that means that it can't compile one of the dependencies for the Lindenmayer package. It has a dependency on Squirrel3, which is a C-based seedable pseudo-random generator. The C-based project makes it a "ClangTarget" which is what's represented here.

    A only-written-in-swift port of that library would allow this all to be used in Swift Playgrounds iOS though, at the cost of some performance for the generation of random numbers.

    bug enhancement 
    opened by heckj 1
  • Updating documentation for Lindenmayer

    Updating documentation for Lindenmayer

    • converting to using SwiftUI's Angle type instead of Double in renderers and rendering commands for consistency and usability clarity
    • adding docs to a variety of methods
    • renamed PWrapper to ParameterWrapper
    • normalized rendering commands and removed unimplemented ones

    resolves #7

    opened by heckj 1
  • enable '@V' rolling to horizontal 3D rendering command/module

    enable '@V' rolling to horizontal 3D rendering command/module

    In Honda's example model (pg 68 of PARAMETRIC L-SYSTEMS AND THEIR APPLICATION TO THE MODELLING AND VISUALIZATION OF PLANTS), uses the L+C module @V, which is described as maintaining the current axis of "growth", but rolling on that axis so that branching to the left or right results in a horizontal (from the world perspective) divergence.

    I haven't sorted out the relevant math to enable that within the 3D visualizations currently, but I'd like to be able to showcase that model as an example.

    enhancement 
    opened by heckj 1
  • Reduce unneeded boxing for modules that represent just rendering commands

    Reduce unneeded boxing for modules that represent just rendering commands

    During the initial implementation, I set up RenderingCommands and Modules are two different things - using enumerations for RenderingCommands (both 2D and 3D). In the current API, a module returns a sequence of 2D commands, or a single 3D command.

    After implementing a few L-systems, it's clear that sometimes the modules are simply wrapping a single rendering command, so it might be a lot simpler if Modules and RenderingCommands were effectively the same thing, so that I didn't need to have both modules to represent the rendering commands, as well as modules for whatever the system is supposed to enable.

    If the sequence of drawing commands for 2D is really needed (sequence was an experiment), then enabling context-free decomposition into rendering modules (called 'interpretation' in the scientific literature).

    Additionally, I think it would make significantly more sense to switch the rendering commands from enums to static structs so that a developer could potentially expand and utilize their own representation engine if they wanted to do so.

    enhancement 
    opened by heckj 1
  • removing Squirrel3 dependency

    removing Squirrel3 dependency

    • removes CLANG target dependency (C code) in favor of an embedded default pseudo-random number generator using the Xoshiro algorithm in pure swift. It's not as fast, but effective - and allows for using this package within Swift Playgrounds, which doesn't support CLANG target dependencies.

    resolves #33

    opened by heckj 0
  • Roll to vertical

    Roll to vertical

    resolves #7

    • reset the process flow and extracted the code and equations
    • switched the process to forward project into the rotated space for vector evaluation
    • explicitly projected the vector instead evaluating the angle between +Y and the rotated UP vector
    • added simple tests to verify the rotation is as expected for no translation and tilting 45° in each coordinate direction
    opened by heckj 0
  • module cleanup, normalizing rendering commands

    module cleanup, normalizing rendering commands

    resolves #3

    • now that all rules are typed, the need for dynamic member lookups for modules is pretty much gone - removing that capability from the Module protocol.
    opened by heckj 0
  • Evaluation of rules to include optional closure that can work against internal parameters of modules

    Evaluation of rules to include optional closure that can work against internal parameters of modules

    resolves #8 resolves #19

    • stub in optional evaluation closure to protocol and types
    • converted rule evaluation to use ModuleSet
    • simplified ModuleSet's initializers, and updated in testing
    • added evalClosure to initializers for all rules, updated tests to pass in nil for full initialization
    • switched out all the rules to specific typed rules, using generics - and layering over types in the LSystems
    • recreated the combinatorial explosion of rewrite() methods
    • fixed up the tests, although test coverage has dropped precipitously with the explosion of types
    • no more "casting" of types needed in the produce closures, and they no longer accept throwing closures
    • evaluation closures for parametric evaluation of rules now don't require casting either - all typed based on Rules
    opened by heckj 0
  • Stochastics within L-systems and rules

    Stochastics within L-systems and rules

    resolves #5 resolves #18

    • establish protocol for a seeded PRNG to use within the systems
    • establish default PRNG for both types of L-system
    • establish default PRNG for both types of rules
    • expanded types for basic, w/RNG, w/Defines, and w/Both
    • migrated Chaos wrapper down to just the rules themselves
    • added Lindenmayer top-level struct with factory methods on it for different types of LSystems (Basic, +Rng, +Defines&RNG)
    • added rewrite rules on specific types of LSystems to provide factory for the various rule types, and exposing the relevant closures for less extra _ need
    opened by heckj 0
  • expand tests to cover all the typed rule cases now that its fully generic

    expand tests to cover all the typed rule cases now that its fully generic

    Rules were previously existential, and writing closures that used the modules required casting. With update #21, that's notable changed - all the modules are shifted into fully typed expressions, and the rules are all generic across a couple different Axis, resulting in a combinatorial explosion of types:

    Context matching:

    • direct
    • left, direct
    • direct, right
    • left, direct, right

    matrixed against:

    • basicLSystem (no parameters, no RNG)
    • RNGLSystem (no parameters, RNG)
    • DefinesLSystem (parameters, no RNG)
    • DefinesRNGLSystem (parameters and RNG)

    Some of the code is verified, but it should all be basically "worked" to verify that I didn't miss anything while making "the maze of twisty passages, all alike" in order to have typed closures for writing LSystems.

    (Coverage of Lindenmayer in general dropped to 36%)

    enhancement 
    opened by heckj 0
  • Supporting server-side swift use of Lindenmayer

    Supporting server-side swift use of Lindenmayer

    I don't know if it makes sense or not, but it could be quite possible to use Lindenmayer with Server-side swift (or more generally, swift running on Linux or other platforms). Primarily, it would mean conditionally compiling the existing pieces that require Apple platform specific libraries (CoreGraphics, SwiftUI, and SceneKit) and enabling a secondary 2D (if not 3D) renderer.

    One option for the 2D renderer is to borrow from what swift-collections-benchmark has done and enable a simple SVG output renderer as a default 2D renderer if the others aren't available. See that project's DefaultRenderer.swift implementation for the gist of the pattern.

    If you'd like this capability, please let me know in this issue - or feel free to jump in and help contribute to enable it.

    enhancement good first issue 
    opened by heckj 0
  • enable tropism - vector effects for turns, bends, and rolls

    enable tropism - vector effects for turns, bends, and rolls

    It would be nice to add the ability to easily compute adjustments to final vectors resulting from the 3D modeling commands of yaw, pitch, and roll so that effects such as Tropism (either from wind or sun) could be included in calculating the resulting growth direction of L-systems.

    I'm not sure how easily that could be accommodated, and where would be most appropriate - but I'm guessing as an additional component to the production results when there's an explicit growth or bend.

    enhancement 
    opened by heckj 1
  • enable a pruning '%' module

    enable a pruning '%' module

    One of the interesting advanced functions of current L-systems is supporting a '%' symbol as a mechanism to prune a branch, and all associated sub-elements, from an existing tree. I suspect that's best done in a follow-on phase after the rule evaluations for each state of the sequence that makes up the tree is complete, at least to allow everything to operate in a parallel mode.

    enhancement 
    opened by heckj 0
  • Enable rendering pre-set or provided bicubic patches for leaves and/or petals

    Enable rendering pre-set or provided bicubic patches for leaves and/or petals

    Some previous tooling (L+C modeling tools) use bicubic patches for rendering the interesting shapes of leaves and/or petals rather than explicitly "growing" them with their own L-system. It would be tremendous to allow/enable that same capability when rendering the results of L-systems in 3D.

    enhancement 
    opened by heckj 0
  • concurrent rule evaluation and async/await API for the library

    concurrent rule evaluation and async/await API for the library

    The initial API for Lindenmayer is blocking and serialized. WIth Swift 5.5 supporting async/await, it would be great to consider exposing some of the API of this library as async and concurrent.

    My initial thought is that LSystem.evolve() is the primary target to consider for exposing an async API

    enhancement 
    opened by heckj 0
Releases(0.7.3)
  • 0.7.3(Aug 6, 2022)

    What's Changed

    • removing Squirrel3 dependency by @heckj in https://github.com/heckj/Lindenmayer/pull/36, which allows for Lindenmayer to be used within Swift Playgrounds as it's now all pure-swift code (no C-based dependencies)

    Full Changelog: https://github.com/heckj/Lindenmayer/compare/0.7.2...0.7.3

    Source code(tar.gz)
    Source code(zip)
  • 0.7.2(Jan 31, 2022)

    What's Changed

    • updating 3D rendering by @heckj in https://github.com/heckj/Lindenmayer/pull/30
    • Roll to vertical by @heckj in https://github.com/heckj/Lindenmayer/pull/32
    • Updating documentation for Lindenmayer by @heckj in https://github.com/heckj/Lindenmayer/pull/31
    • final tweaks to resource locations by @heckj in https://github.com/heckj/Lindenmayer/pull/34
    • fixes for updates in dependency modules that are pre-release

    Full Changelog: https://github.com/heckj/Lindenmayer/compare/0.7.1...0.7.2

    Source code(tar.gz)
    Source code(zip)
  • 0.7.1(Jan 14, 2022)

    What's Changed

    • module cleanup, normalizing rendering commands by @heckj in https://github.com/heckj/Lindenmayer/pull/23
    • Faster iteration by @heckj in https://github.com/heckj/Lindenmayer/pull/24
    • Debug view by @heckj in https://github.com/heckj/Lindenmayer/pull/28

    Full Changelog: https://github.com/heckj/Lindenmayer/compare/0.7.0...0.7.1

    Source code(tar.gz)
    Source code(zip)
  • 0.7.0(Jan 2, 2022)

    BREAKING CHANGES

    Writing rules ergonomic updates:

    The process of writing LSystems has been improved by including factory/wrapper methods on the various types of LSystems (basic, RNG, Parameters, RNG+Parameters), and now all the rules are explicitly typed. This in turn allows for the closures that produce the rewriting for the relevant modules to be explicitly typed, so there's no longer a need to down-cast from the existential Module type into the specific kind of module in order to use the types parameters when computing what replaces it.

    The rules all now also have additional evaluation criteria enabled through an optional (typed) closure so that you can choose if rules are activated not only by the types they match, but in addition with a closure that you provide that can interrogate the modules that were matched.

    Source code(tar.gz)
    Source code(zip)
  • 0.5.0(Dec 23, 2021)

    (2021-12-23)

    The initial release of Lindenmayer.

    The library supports creating context-free and contextual parametric L-systems. Built-in modules support 2D and basic 3D visualizations, and some reference implementations of previously described L-systems.

    The API is by no means finished, complete, or in a final form. There are several places where I'm considering how to make creating L-systems written in the Swift language more ergonomic, and additional features that I want to add for broader support (such as stochastic production rules).

    This edition is suitable for experimentation, and I certainly welcome feedback in the discussion section of the Github repository.

    Full Changelog: https://github.com/heckj/Lindenmayer/commits/0.5.0

    Source code(tar.gz)
    Source code(zip)
Owner
Joseph Heck
Joseph Heck
A macOS auxiliary app to choose results from cloud input methods

CloudInputAssist Introduction 介绍 一个 macOS 辅助应用程序,用于使用云输入法(例如谷歌云输入法)API 提供辅助的候选词结果。 Motivation 动机 使用不联网的本地输入法时,长句的候选词往往不太理想,尤其是使用双拼输入时。这种情况下,借助一些输入法的云计

JJAYCHEN 1 Jan 3, 2023
Presentation for Podlodka iOS Crew #9 - Modern iOS Coding

Struct oriented programming vs Protocol oriented programming How do we use protocols How to do it without protocols How to transform any protocol to a

Evgenii Sukhanov 6 Dec 27, 2022
SwiftPokedex is a simple Pokedex app in Swift that implements the PokeAPI

Pokedex SwiftPokedex is a simple Pokedex app in Swift that implements the PokeAPI. For full documentation and implementation of PokeAPI have a look at

Tuba Nur Yıldız 0 Jan 14, 2022
Simple SwiftUI ViewModifier to easily align your views!

Align Align gives you an easy way to align views in SwiftUI. Simply import Align in whichever SwiftUI view you like and you're good to go. Align suppl

Jacob's Apps 26 Mar 15, 2022
A Figma component preview for your SwiftUI views

FigmaPreviewSwiftUI A Figma component preview for your SwiftUI views. You can use Figma components instead of real views within your app until you imp

Danis Tazetdinov 50 Dec 23, 2022
Orbit-swiftui - Orbit design system implemented in SwiftUI for iOS

Orbit is a SwiftUI component library which provides developers the easiest possi

Kiwi.com 37 Jan 3, 2023
A collection of Swift functions, extensions, and SwiftUI and UIKit Views.

J's Helper A collection of Swift functions, extensions, and SwiftUI and UIKit Views. Legend: ?? UIKit ?? SwiftUI ?? Shared Installation In XCode 12 go

Jem Alvarez 3 Oct 1, 2022
A SwiftUI system components and interactions demo app

SwiftUI Kit A SwiftUI system components and interactions demo app based on iOS 14, macOS Big Sur, watchOS 7, and tvOS 14. Use the SwiftUI Kit app to s

Jordan Singer 2k Jan 6, 2023
Animated shine effect for your views

Shine-View-SwiftUI Animated shine effect for your views @State var animateTrigger = false var body: some View { Button(action: { animate

Алексей 9 Sep 14, 2022
A SwiftUI wrapper around the `Add to Siri` button used to donate INIntents to the system.

AddToSiri A SwiftUI wrapper around the Add to Siri button used to donate INIntents to the system. Originally created by Reddit user u/dippnerd (Github

Florian Schweizer 5 Nov 23, 2022
A SwiftUI App that displays information about the planets in our solar system.

MySpaceApp Created by Noman Ahmad Current Version : 1.0 Description: MySpaceApp is a simple ios app designed for space enthusiasts. With this app, you

Noman Ahmad 1 Nov 2, 2021
A realistic reflective shimmer to SwiftUI Views that uses device orientation. Position any View relative to device orientation to appear as if through a window or reflected by the screen.

A 3d rotation effect that uses Core Motion to allow SwiftUI views to appear projected in a specific direction and distance relative to the device in r

Ryan Lintott 235 Dec 30, 2022
A lightweight and efficient bus tracker app for the Miami-Dade Transit System

A lightweight bus tracker app for the Miami-Dade Transit System Built in Swift, this app features a favorites page, real-time bus location and ETA, us

Jacob Schuster 1 Dec 10, 2021
COVID Safe Paths (based on Private Kit) is an open and privacy preserving system to use personal information to battle COVID

COVID Safe Paths is a mobile app for digital contract tracing (DCT) sponsored by Path Check a nonprofit and developed by a growing global community of engineers, designers, and contributors. Safe Paths is based on research originally conducted at the MIT Media Lab.

PathCheck Foundation 470 Nov 6, 2022
A macOS app to simulate the system update

Goaf-Happy-Fishing A macOS app to simulate the system update. Turn on the app, t

Logeast 1 Dec 23, 2021
Visualize your dividend growth. DivRise tracks dividend prices of your stocks, gives you in-depth information about dividend paying stocks like the next dividend date and allows you to log your monthly dividend income.

DivRise DivRise is an iOS app written in Pure SwiftUI that tracks dividend prices of your stocks, gives you in-depth information about dividend paying

Kevin Li 78 Oct 17, 2022
A SwiftUI dynamic property wrapper for fetching media from your photo library. (iOS, tvOS, macOS)

Media Also available as a part of my SwiftUI+ Collection – just add it to Xcode 13+ A package for simplifying the user of the camera and the user's ph

SwiftUI+ 20 Nov 16, 2022
SwiftUI Backports - Introducing a collection of SwiftUI backports to make your iOS development easier

SwiftUI Backports Introducing a collection of SwiftUI backports to make your iOS development easier. Many backports support iOS 13+ but where UIKIt fe

Shaps 530 Dec 28, 2022
iOS Trakt Client - Keep track of your favorite TV shows and movies on your iPhone. (Under development)

CouchTracker Keep track of your favorite movies and tv shows on your iPhone Setup for development You will need Xcode 11.2.1 Swift 5.1.2 Run the follo

Pietro Caselani 42 Apr 19, 2022