All Projects → inconvergent → Weir

inconvergent / Weir

Licence: other
A system for making generative systems

Projects that are alternatives of or similar to Weir

Generative-Art
A selection of generative art scripts written in Python
Stars: ✭ 284 (-37.03%)
Mutual labels:  art, generative-art, generative
samila
Generative Art Generator
Stars: ✭ 750 (+66.3%)
Mutual labels:  art, generative-art, generative
corruption-loops
Digitally disintegrating music
Stars: ✭ 37 (-91.8%)
Mutual labels:  art, generative-art, generative
Allsketchs
Processing sketches, in which I have worked in the last years; images, videos, prototypes, experiments, tools, works, concepts... Everything is unfinished, some may not work, When I had no ideas, I would open one to see what it was...
Stars: ✭ 666 (+47.67%)
Mutual labels:  generative, image, art
glitch-image
🖼 Generate and save unique glitchy images
Stars: ✭ 46 (-89.8%)
Mutual labels:  art, generative-art, generative
Snek
See https://github.com/inconvergent/weir instead
Stars: ✭ 696 (+54.32%)
Mutual labels:  generative, generative-art, art
Pts
A library for visualization and creative-coding
Stars: ✭ 4,628 (+926.16%)
Mutual labels:  generative, generative-art, art
Sofloo Spot
Click Randomize
Stars: ✭ 37 (-91.8%)
Mutual labels:  generative, generative-art, art
book-mdpc
Il cinema tra le righe... di codice!
Stars: ✭ 59 (-86.92%)
Mutual labels:  art, generative-art, generative
microbium-app
Draw new worlds
Stars: ✭ 89 (-80.27%)
Mutual labels:  art, generative-art
generative
A digital playground for experimenting with creative coding and WebGL
Stars: ✭ 50 (-88.91%)
Mutual labels:  art, generative-art
pycontextfree
Pythonic generative art tool
Stars: ✭ 32 (-92.9%)
Mutual labels:  art, generative-art
GenerativeArtists
No description or website provided.
Stars: ✭ 22 (-95.12%)
Mutual labels:  generative-art, generative
SuperformulaSVG
2D superformula line-art generator built in Processing, with SVG export for use in digital fabrication workflows.
Stars: ✭ 40 (-91.13%)
Mutual labels:  art, generative
generative.fm
A platform for playing generative music in the browser.
Stars: ✭ 1,557 (+245.23%)
Mutual labels:  art, generative-art
glitch-art-bot-ts
Twitter bot that glitches photos on the fly
Stars: ✭ 66 (-85.37%)
Mutual labels:  art, generative-art
ZzSprite
Pixel Art Sprite Generator
Stars: ✭ 85 (-81.15%)
Mutual labels:  generative-art, generative
elm-generative
Making generative art in Elm
Stars: ✭ 23 (-94.9%)
Mutual labels:  art, generative
desert
A fast (?) random sampling drawing library
Stars: ✭ 61 (-86.47%)
Mutual labels:  generative-art, generative
Sand Spline
generative algorithm
Stars: ✭ 261 (-42.13%)
Mutual labels:  generative, generative-art

WEIR-A System for Making Generative Systems

About

This library is specifically written to be useful for a broad range of ways in which I create art using various generative algorithms. It is the next iteration of snek. I made a new version because I wanted to make some significant changes.

Main components:

  1. 2d and 3d vectors with corresponding operations:

    ; create a 2d vector
    (vec:vec 1d0 3d0)
    
    ; create a 3d vector
    (vec:3vec 1d0 2d0 3d0)
    

    vec supports common vector operations such as add, mult, div, sub, as well as cross products cross, dot products, dot.

    Note: Functions that operate on 3d vectors are prefixed with 3.

    Furthermore there are corresponding functions for scalars, lists of vectors, and broadcasting. They are indicated by prefix l and s:

    ; add scalar s to a, return result
    (vec:sadd va s)
    
    ; add vectors in two lists, returns list of new vectors
    (vec:ladd aa bb)
    
    ; add b to elements of aa, return list of new vectors
    (vec:ladd* aa vb)
    

    Most of these functions also have a corresponding function postfixed with !, which performs the same operation, but assigns the result to the first argument. This is faster since there is no need to create a new vec struct.

    Note: This can cause strange behaviour since you can inadvertently change the internal state of a struct. Use with caution.

    Example:

    ; add b to a, store result in a; also returns a
    (vec:add! va vb)
    

    There are also some common geometric operations, such as line interpolation, line-line intersection, angles, and line-plane intersection.

    ; find the position s between a and b. s should be between 0 and 1
    (vec:on-line s va vb)
    ; find intersection of two lines, returns
    a bool, and interpolation value along line 1, line 2
    (vec:segx line1 line2)
    

    See the code in the package for more details.

  2. Random numbers, some examples:

    ; random double 0d0 and a (default: 1d0)
    (rnd:rnd a)
    
    ; ditto, between -a and a
    (rnd:rnd* a)
    
    ; between a and b
    (rnd:rndrng a b)
    
    ; random fixnum
    (rnd:rndi 10)
    
    ; return n random numbers between a and b
    (rnd:rndspace n a b)
    
    ; random number from normal distribution
    (rnd:norm :mu 0d0 :sigma 1d0)
    
    ; uniform in circle of radius a at centered at p
    (rnd:in-circ a :xy p)
    
    ; uniform numbers in a rectangle
    (rnd:in-rect w h :xy p)
    
    ; pick a random point between points va and vb
    (rnd:on-line va vb)
    
    ; execute a form with a certain probability
    ; second form is optional
    (rnd:prob 0.1d0 (print "10% hi") (print "90% oh no"))
    
    ; perform either form 1 or 2
    (rnd:either (print "form 1") (print "form 2"))
    
    ; repeat the form at most n-1 times
    (rnd:rep n (print 1))
    

    There are also some utils for random 3d vector numbers, see src/rnd/3rnd.lisp.

  3. A simple graph data structure, weir, for working with vertices and edges. The structure is combined with a programming pattern for applying changes to the structure. The pattern relies on alterations, see below. You can also manipulate the structure directly.

    Below is a small example:

    (let ((wer (weir:make))) ; use :dim 3 for 3d
      ; add three edges
      (loop repeat 3
            do (weir:add-edge! wer
                 (weir:add-vert! wer (rnd:in-circ 200d0))
                 (weir:add-vert! wer (rnd:in-circ 200d0
                                 :xy (vec:rep 500d0)))))
      ; iterate verts
      (weir:itr-verts (wer v) (print (weir:get-vert wer v)))
    
      ; move a vert relativ to current position:
      (weir:move-vert! wer 0 (vec:vec 1d0 2d0))
      ; move a vert to an absolute position
      (weir:move-vert! wer 1 (vec:vec 1d0 2d0) :rel nil)
    
      ; iterate edges
      (weir:itr-edges (wer vv) (print (weir:get-verts wer vv)))
    
      ; edges are represented as lists of verts, and they are always
      ; sorted with the smallest vert index first, so both
      (weir:edge-exists wer '(0 1)) ; and
      (weir:edge-exists wer '(1 0)) ; returns t
    
      ; get edges incident to vert 0
      (weir:get-incident-edges wer 0))
    

    See the examples folder for more.

  4. A series of other useful data structures and tools. E.g. a package for handling colors (pigment), splines (bzspl), and various vector and path functionality. Eg. math, lin-path and simplify-path.

    (let* ((points (rnd:nin-circ 5 400d0))
           (bz (bzspl:make points))
           (lp (lin-path:make points)))
      ; sample a point on the spline
      (bzspl:pos bz (rnd:rnd))
      ; sample a point on path
      (lin-path:pos lp (rnd:rnd))
    
      ; represent the spline with a limited number of points
      (bzspl:adaptive-pos bz :lim 1d0))
    
    ; return n numbers evenly spaced between a and b, inclusive
    (math:linspace n a b :end t)
    
    ; all fixnums from a to b-1
    (math:range a b)
    
    ; repeat the form n times
    (math:nrep n (rnd:rnd))
    
  5. Orthogonal projection ortho:

    (let ((proj (ortho:make :s 1d0
                            :xy (vec:rep 500d0)
                            :cam (vec:3vec 1000d0 1000d0 0d0)
                            :look (vec:3zero))))
      (multiple-value-bind (v d)
        (ortho:project proj (rnd:3in-sphere :rad 300d0))
        ; point in 2d
        (print v)
        ; distance from 3d point to camera plane
        (print d))
    
      ; update cam position and look at something else
      (ortho:update proj :cam (vec:3vec 3d0 4d0 1d0)
                         :look (vec:3rep 79d0)))
    
  6. A tool for drawing svg files: draw-svg. Mainly files that are good for plotting.

    (let ((psvg (draw-svg:make :stroke "black"))
          (pts (list (vec:vec 10d0 20d0) (vec:vec 20d0 30d0)
                     (vec:vec 10d0 50d0))))
      ; sw is the stroke width
      (draw-svg:path psvg pts :sw 3d0)
      (draw-svg:bzspl psvg pts :sw 3d0 :so 0.5d0)
      (draw-svg:circ psvg (vec:rep 30d0) 10d0 :sw 3d0 :stroke "red")
      (draw-svg:save psvg "filename"))
    
  7. A tool for drawing pngs called sandpaint. This package uses random sampling to draw. This creates a fairly distinct and gritty look in many cases. Also supports direct pixel manipulations and a few filters.

Weir Graphs and Alterations

An alteration is a change that will be applied to the structure at the end of a given context. In many ways this is similar to map/reduce.

Here is and example of manipulating a weir instance called wer using alterations. Alteration constructors are postfixed with ?.

; context start
(let (wer (weir:make))

  ; add some data to wer here ...

  ; (% ...) is used to accumulate alterations
  ; alterations are applied at the end of (weir:with ...)
  (weir:with (wer %)
    ; iterate vertices
    (weir:itr-verts (wer v)
      ; move alteration
      (% (weir:move-vert? v (rnd:in-circ 1d0)))
      ; w will be an arbitrary
      ; vertex in wer
      (weir:with-rnd-vert (wer w)
        ; join v and w if they are closer than d
        (when (< (weir:edge-length wer v w) d)
              ; add edge
              (% (weir:add-edge? v w)))))))

It is possible to reference alterations inside a (weir:with ...) context. A simple example looks like this:

(weir:with (wer %)
  ; add vert, named :a
  (% (weir:add-vert? pt) :a)
  ; add vert, named :b
  (% (weir:add-vert? pt) :b)
  ; use :a and :b to add new edge, if both are added
  (% (weir:add-edge? :a :b) (:a :b)))

You can also define your own arbitrary alterations. There is an example of custom alterations and references in examples/custom-alt.lisp.

All alterations must follow a specific format. There can be at most three forms inside (% ...). The first must be a form that evaluates to a lambda (or a lambda, this is experimental). This function should accept a single argument. When the alteration is applied it is called with the current weir instance as the only argument.

The second and third arguments are both optional, and the order does not matter. Use a :keyword if you want to give the alteration result a name; and a list of keywords, to indicate that you are using references to other named alteration results in this alteration.

Shadowing

All arguments to an alteration that are atoms, or forms that do not contain a reference to another alteration result, will be shadowed before the alteration is collected. This is the behaviour you will usually want in an example such as the one above. However, it might cause unexpected issues if you write something like.


(% (some-alteration? local-var (first local-var-1) :a
                     (list :b (first local-var-2))) (:a :b))

The variables/forms that will be shadowed here are: local-var, (first local-var-1), and (first local-var-2).

You can use (weir:with ... :bd t) to see how an alteration is expanded. This might make it easier to find issues with shadowed/non-shadowed variables. Also, you can usually solve problems with shadowing using (labels ()) locally to create a custom alteration.

Furthermore, placing an alteration inside a loop (of any kind) can result in unexpected behaviour. Most notably you shouldn't reference the result of an alteration in a loop from another alteration: It does not stack up all results, and it will not wait until the loop is finished to resolve any dependent alterations.

NOTE: Before it was possible to reference other alteration results, (% ...) was a function. This eradicated the need for (most of) these complex shadowing rules. I might try to change the behaviour once I have a better understanding of what behaviour I actually find convenient. However, I'm not currently sure how avoid these rules when some arguments do not exist at the time the alteration is collected.

Use

I use weir for most of the work that I post online (https://inconvergent.net/, https://img.inconvergent.net/, https://twitter.com/inconvergent). Both for raster images, as well as vector images for plotter drawings.

Here are some plotted examples:

Writing

I have written about things related to this code (when it was called snek) at:

And recently at:

On Use and Contributions

This code is written for my personal use, and parts of it is rather experimental. Also, it is likely to change at my whim. For this reason I don't recommend depending on this library for anything.

I release it publicly in case people find it useful or interesting. It is not, however, intended as a collaboration/Open Source project. As such I am unlikely to accept PRs, reply to issues, or take requests.

Installation and Dependencies

This code requires Quicklisp to install dependencies (which are listed in weir.asd). To install and load Weir, do:

(ql:quickload :weir)

If this does not work, Weir may not be in a place Quicklisp or ASDF can see them. To fix this, either

(load "weir.asd")

or, for a long term solution, push the directory in which Weir sits to the variable quicklisp:*local-project-directories*:

; in your .sbclrc, for example:
#+quicklisp
(push "/path/to/dir/containing/weir" ql:*local-project-directories*)

The fn package (for generating file names) depends on the fn command from https://github.com/inconvergent/fn, but this is not necessary to use any of the other packages.

The code has only been tested in Ubuntu 18.04 LTS with SBCL 2.0.1. I've been told that examples work with SBCL in macOS.

Tests

Run:

(asdf:test-system :weir)

In Case of QL Version Issues

See http://blog.quicklisp.org/2011/08/going-back-in-dist-time.html

Summary:

(use-package :ql-dist)
; see versions
(available-versions (dist "quicklisp"))
; select a dist version
(install-dist
  "http://beta.quicklisp.org/dist/quicklisp/2019-03-07/distinfo.txt"
  :replace t)

Thanks

I would like to thank:

Who have provided me with useful hints and code feedback.

The ASDF config and test setup was kindly suggested and implemented by Robert Smith (https://twitter.com/stylewarning). The remaining weirdness in the test system is my fault. Hope to fix it properly later.

Also, many thanks to https://twitter.com/xach for making Quicklisp.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].