npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

l-system-tools

v0.0.1

Published

This is a JavaScript-based implementation of [Lindenmayer systems](https://en.wikipedia.org/wiki/l-system).

Downloads

4

Readme

L System Tools

This is a JavaScript-based implementation of Lindenmayer systems.

It consists of two key pieces:

  • A parse function that takes an axiom and a set of production rules, and returns a generated command string.
  • A number of different renderers that take a command string and output graphics. The renderers use a class-based system that allows them to be extended with custom graphics rules. Renderers are provided for canvas and SVG (though the base renderer could be extended for other uses.)

Installation

npm i l-system-tools

Parse Function

The core concept of L systems is that you can take a starting string (an axiom) and iteratively replace characters in that string following a set of production rules. This outputs a longer, generated string composed of repeating patterns that mimic natural, organic structures.

Here's an example of using the parser:

import { parse } from "l-system-tools";

const commandString = parse({
  // Starting string
  axiom: "F",
  // Object containing production rules
  production_rules: {
    // The character to replace
    F: {
      // What to replace the character with
      replacement: "F[-F][+F]",
      // Optionally include a decimal chance of the rule applying
      chance: "1",
    },
  },
  // How many times to iterate over the string
  iterations: 2,
});

This would output the following command string:

F[-F][+F][-F[-F][+F]][+F[-F][+F]]

Renderers

The renderer takes a command string and outputs graphics. There are currently three main renderers:

  • Renderer — A base renderer. Does not actually output graphics. (Contains core functionality that can be extended for various graphic outputs.)
  • SvgRenderer — Renders a command string's output to an existing SVG element
  • CanvasRenderer — Renders a command string's output to an existing canvas element.

Using the SVG Renderer

Here's an example of using the SVG renderer:

import { parse, SvgRenderer } from 'l-system-tools';

// The renderer expects to be passed an SVG element when initialized
const renderer = new SvgRenderer(document.querySelector("svg"));

renderer.render({
  commandString: parse({
    axiom: "F",
    productions: {
      F: {
        replacement: "F[-F][+F]"
      }
    },
    iterations: 2,
  });
  // Optionally define a starting rotation (determines starting direction)
  // Defaults to 90 (degrees)
  startRotation: 90,
  // Optionally define a rotation for how far to turn when a turn command is encountered
  // Defaults to 30 (degrees)
  turnRotation: 30,
  // Optionally define a distance to move when a forward command is encountered
  // Defaults to 10
  distance: 10,
  // Optionally define a starting poition
  // Defaults to { x: 50, y: 50 }
  startPosition: { x: 50, y: 50 },
});

Using the Canvas Renderer

The canvas renderer has the same syntax, but takes a canvas element instead of an SVG.

import { parse, CanvasRenderer } from "l-system-tools";

// The renderer expects to be passed an SVG element when initialized
const renderer = new CanvasRenderer(document.querySelector("canvas"));

renderer.render({
  // The Canvas Renderer takes the same options as the SVG Renderer above
});

Extending Renderers

Any of the renderers can be extended to add additional functionality or styles. Here's an example of extending the SVG renderer to add a special rendering rule for the letter 'C':

import { SvgRenderer } from "../renderer.js";

export class ExperimentalSvgRenderer extends SvgRenderer {
  customCommand = (command) => {
    if (command === "C") {
      // The SVG renderer builds a `markup` string containing the SVG markup
      this.markup += `
        <circle
          cx="${this.position.x}" 
          cy="${this.position.y}" 
          r="${this.distance / 5}"
        />`;
    }
  };
}

Here's a similar example for the canvas Renderer:

import { canvasRenderer } from "../renderer.js";

export class ExperimentalCanvasRenderer extends canvasRenderer {
  customCommand = (command) => {
    if (command === "C") {
      // Canvas renderers expose a canvas 2d context property.
      this.context.arc(
        this.position.x,
        this.position.y,
        this.distance / 5,
        0,
        2 * Math.PI,
        false
      );
    }
  };
}

For further information about extending renderers I recommend you review the source code and see how the SVG Renderer and Canvas Renderer are coded.