fastmath.fields

Vector field functions.

Vector fields are functions R^2->R^2.

Names are taken from fractal flames world where such fields are call variations. Most implementations are taken from JWildfire software.

Creation

To create vector field call field multimethod with name of the field as keyword.

Some of the vector fields require additional configuration as a map of parameters as keywords and values. Call parametrization to create random one or to merge with provided.

Additionally you can provide amount parameter which is scaling factor for vector field (default: 1.0).

Derived fields

You can use several method to derive new vector field from the other one(s). Possible options are:

Scalar fields

You can derive scalar fields from given vector field(s):

  • jacobian - determinant of jacobian matrix
  • divergence - divergence of the field
  • cross - cross product of the fields (as a determinant of the 2x2 matrix of vectors)
  • dot - dot product
  • angle-between - angle between vectors from fields.

Combinations

The other option is to create vector field using some of the above possibilities. Combination is a tree of field operations with parametrizations. Functions:

*skip-random-fields*

dynamic

When random configuration for combine is used. Skip vector fields which are random.

angle-between

Angle between input vector and result of the vector field.

In case when two vector fields are given, cross product is taken from result of vector fields.

Resulting value is from range [-PI,PI].

Examples

Usage

(let [f (angle-between (field :swirl))] (f (v/vec2 1 1)))
;;=> 0.42920367320510344

Usage (two fields)

(let [f (angle-between (field :sinusoidal) (field :swirl))]
  (f (v/vec2 1 1)))
;;=> 0.42920367320510255

combine

(combine {:keys [type name amount config var step var1 var2]})(combine)

Create composite vector field function based on configuration

Call without argument to get random vector field.

Configuration is a tree structure where nodes are one of the following

  • {:type :variation :name NAME :amount AMOUNT :config CONFIG} where
    • NAME is variation name (keyword)
    • AMOUNT is scaling factor
    • CONFIG is variation parametrization
  • {:type :operation :name OPERATION :amount AMOUNT :var1 VAR1 :var2 VAR2} where
    • OPERATION is one of the operations (see below)
    • AMOUNT is scaling factor
    • VAR1 and VAR2 two variations to combine
  • {:type :operation :name :derivative :amount AMOUNT :var VAR :step STEP} where
    • AMOUNT is scaling factor
    • VAR variation, subject to calculate derivative
    • STEP dx and dy value

Possible OPERATIONs are:

  • :add - sum of two variations
  • :mult - multiplication
  • :comp - composition
  • :angles - vector field from angles

See random-configuration for example.

Examples

Create random combination

(let [f (combine)] (f (v/vec2 -0.5 0.5)))
;;=> [##NaN ##NaN]

Create combination for given configuration

(let [conf {:type :operation,
            :name :comp,
            :var1 {:type :variation,
                   :name :blocky,
                   :amount 1.0,
                   :config {:x -1.4, :y 0.9, :mp 2.6}},
            :var2
            {:type :variation, :name :secant, :amount 1.0, :config {}},
            :amount 1.0}
      f (combine conf)]
  (f (v/vec2 -0.5 0.5)))
;;=> [0.18532823300678739 0.437177284257253]

composition

(composition f1 f2 amount)(composition f1 f2)

Compose two vector fields.

Examples

Usage

(let [field-1 (field :sinusoidal)
      field-2 (field :swirl)
      field-comp (composition field-1 field-2)]
  (field-comp (v/vec2 0.5 0.3)))
;;=> [-0.11582232201566794 0.5408299143217236]

cross

2d cross product (det of the 2x2 matrix) of the input vector and result of the vector field.

In case when two vector fields are given, cross product is taken from results of vector fields.

Examples

Usage

(let [f (cross (field :swirl))] (f (v/vec2 1 1)))
;;=> 0.8322936730942845

Usage (two fields)

(let [f (cross (field :sinusoidal) (field :swirl))] (f (v/vec2 1 1)))
;;=> -0.7003509767480289

curl

(curl f)(curl f h)

Curl (2d version) of the field.

See: https://youtu.be/rB83DpBJQsE?t=855

Examples

Usage

(let [f (curl (field :swirl) 1.0E-8)] (f (v/vec2 0.0 0.0)))
;;=> -2.0

derivative

(derivative f amount h)(derivative f h)(derivative f)

Calculate directional derivative of fn. Derivative is calculated along [1,1] vector with h as a step (default 1.0e-6).

Examples

Usage

(let [f (derivative (field :sinusoidal) 1.0E-8)] (f (v/vec2 0.0 0.0)))
;;=> [1.0 1.0]

divergence

(divergence f)(divergence f h)

Divergence of the field.

See: https://youtu.be/rB83DpBJQsE?t=855

Examples

Usage

(let [f (divergence (field :sinusoidal) 1.0E-8)] (f (v/vec2 0.0 0.0)))
;;=> 2.0

dot

Dot product of the input vector and result of the vector field.

In case when two vector fields are given, cross product is taken from result of vector fields.

Examples

Usage

(let [f (dot (field :swirl))] (f (v/vec2 1 1)))
;;=> 1.8185948536513636

Usage (two fields)

(let [f (dot (field :sinusoidal) (field :swirl))] (f (v/vec2 1 1)))
;;=> 1.5302948024685854

field

multimethod

Return vector field for given name and options: amount (scaling factor) and parametrization.

Default scaling factor is 1.0, default parametrization is random.

Resulting function operates on Vec2 type.

Examples

Get vector field by name

(field :sinusoidal)
;;=> fastmath.fields$make_sinusoidal$fn__20321@b287b20
((field :sinusoidal) (v/vec2 m/HALF_PI m/HALF_PI))
;;=> [1.0 1.0]

Get vector field by name and scale

(field :sinusoidal 0.5)
;;=> fastmath.fields$make_sinusoidal$fn__20321@12d2a133
((field :sinusoidal 0.5) (v/vec2 m/HALF_PI m/HALF_PI))
;;=> [0.5 0.5]

Apply parametrization

(let [params (parametrization :cpow3)
      f (field :cpow3 1.0 params)]
  {:parametrization params, :value (f (v/vec2 -1.0 1.0))})
;;=> {:parametrization {:a -0.2904914699966432,
;;=>                    :discrete-spread 0.4001257594501395,
;;=>                    :divisor -1.2935168845931895,
;;=>                    :offset2 -0.9694677615700984,
;;=>                    :r -0.7319235658855412,
;;=>                    :spread 1.0958844977903195,
;;=>                    :spread2 -1.4735625606460951},
;;=>  :value [1.2944046801072704 -0.15204009342754204]}

fields-list

Examples

List of all vector field names.

(sort fields-list)
;;=> (:arch
;;=>  :asteria :atan
;;=>  :auger :barycentroid
;;=>  :bcollide :bent
;;=>  :bent2 :beta
;;=>  :bipolar :blade
;;=>  :blade2 :blob
;;=>  :blocky :blur
;;=>  :blurcircle :blurpixelize
;;=>  :blurzoom :bmod
;;=>  :boarders :boarders2
;;=>  :bsplit :bswirl
;;=>  :btransform :bubble
;;=>  :butterfly :bwraps7
;;=>  :cayley :cell
;;=>  :checks :chunk
;;=>  :circleblur :circlelinear
;;=>  :circlerand :clifford
;;=>  :conic :cosine
;;=>  :cot :cpow
;;=>  :cpow3 :cross
;;=>  :csin :curl
;;=>  :curve :cylinder
;;=>  :default :diamond
;;=>  :disc :disc2
;;=>  :edisc :elliptic
;;=>  :emod :ennepers
;;=>  :erf :escher
;;=>  :ex :exp
;;=>  :exponential :eyefish
;;=>  :fan :fan2
;;=>  :fisheye :flower
;;=>  :foci :foucaut
;;=>  :gamma :gaussianblur
;;=>  :gdoffs :handkerchief
;;=>  :heart :hemisphere
;;=>  :hole2 :horseshoe
;;=>  :hyperbolic :hypershift
;;=>  :invtree :julia
;;=>  :julia2 :juliac
;;=>  :julian :juliaq
;;=>  :juliascope :lazysusan
;;=>  :log :logapo
;;=>  :loonie :miller
;;=>  :millerrev :modulus
;;=>  :ngon :noise
;;=>  :panorama1 :panorama2
;;=>  :parabola :pdj
;;=>  :perlin :perlin2
;;=>  :perspective :petal
;;=>  :phoenix-julia :pie
;;=>  :polar :polar2
;;=>  :popcorn2 :powblock
;;=>  :power :pressure-wave
;;=>  :r-circleblur :radialblur
;;=>  :rational3 :rays
;;=>  :rays1 :rays2
;;=>  :rays3 :rectangles
;;=>  :rhodonea :rings
;;=>  :rings2 :ripple
;;=>  :rippled :roundspher
;;=>  :scry :secant
;;=>  :secant2 :sech
;;=>  :shreadrad :sinusoidal
;;=>  :spherical :spiral
;;=>  :split :splits
;;=>  :square :squirrel
;;=>  :stwin :supershape
;;=>  :swirl :tangent
;;=>  :taurus :trade
;;=>  :twintrian :vibration
;;=>  :vibration2 :voron
;;=>  :waves :wedge)

fields-list-not-random

Examples

List of all vector fields which are not random.

(sort fields-list-not-random)
;;=> (:atan
;;=>  :auger
;;=>  :barycentroid :bcollide
;;=>  :bent :bent2
;;=>  :beta :bipolar
;;=>  :blob :blocky
;;=>  :bmod :bsplit
;;=>  :bswirl :bubble
;;=>  :butterfly :bwraps7
;;=>  :cayley :cell
;;=>  :chunk :circlelinear
;;=>  :clifford :cosine
;;=>  :cot :cross
;;=>  :csin :curl
;;=>  :curve :cylinder
;;=>  :default :diamond
;;=>  :disc :disc2
;;=>  :edisc :emod
;;=>  :ennepers :erf
;;=>  :escher :ex
;;=>  :exp :exponential
;;=>  :eyefish :fan
;;=>  :fan2 :fisheye
;;=>  :foci :foucaut
;;=>  :gamma :gdoffs
;;=>  :handkerchief :heart
;;=>  :hemisphere :hole2
;;=>  :horseshoe :hyperbolic
;;=>  :hypershift :lazysusan
;;=>  :log :logapo
;;=>  :loonie :miller
;;=>  :millerrev :modulus
;;=>  :ngon :panorama1
;;=>  :panorama2 :pdj
;;=>  :perlin :perlin2
;;=>  :perspective :petal
;;=>  :polar :polar2
;;=>  :popcorn2 :power
;;=>  :pressure-wave :rational3
;;=>  :rays1 :rays2
;;=>  :rays3 :rectangles
;;=>  :rings :rings2
;;=>  :ripple :rippled
;;=>  :roundspher :scry
;;=>  :secant :secant2
;;=>  :sech :shreadrad
;;=>  :sinusoidal :spherical
;;=>  :spiral :split
;;=>  :splits :squirrel
;;=>  :stwin :swirl
;;=>  :tangent :taurus
;;=>  :trade :vibration
;;=>  :vibration2 :voron
;;=>  :waves :wedge)

fields-list-random

Examples

List of all vector fields which give random results.

(sort fields-list-random)
;;=> (:arch
;;=>  :asteria :blade
;;=>  :blade2 :blur
;;=>  :blurcircle :blurpixelize
;;=>  :blurzoom :boarders
;;=>  :boarders2 :btransform
;;=>  :checks :circleblur
;;=>  :circlerand :conic
;;=>  :cpow :cpow3
;;=>  :elliptic :flower
;;=>  :gaussianblur :invtree
;;=>  :julia :julia2
;;=>  :juliac :julian
;;=>  :juliaq :juliascope
;;=>  :noise :parabola
;;=>  :phoenix-julia :pie
;;=>  :powblock :r-circleblur
;;=>  :radialblur :rays
;;=>  :rhodonea :square
;;=>  :supershape :twintrian)

grad-x

(grad-x f amount h)(grad-x f h)(grad-x f)

Calculate gradient along x axis.

Examples

Usage

(let [f (grad-x (field :sinusoidal) 1.0E-8)] (f (v/vec2 0.0 0.0)))
;;=> [1.0 0.0]

grad-y

(grad-y f amount h)(grad-y f h)(grad-y f)

Calculate gradient along y axis.

Examples

Usage

(let [f (grad-y (field :sinusoidal) 1.0E-8)] (f (v/vec2 0.0 0.0)))
;;=> [0.0 1.0]

heading

(heading f)

Angle of the vectors from field.

Examples

Usage

(let [f (heading (field :sinusoidal))]
  (m/degrees (f (v/vec2 m/HALF_PI m/HALF_PI))))
;;=> 45.0

jacobian

(jacobian f)(jacobian f h)

Det of Jacobian of the field

Examples

Usage

(let [f (jacobian (field :sinusoidal) 1.0E-8)] (f (v/vec2 0.0 0.0)))
;;=> 1.0

magnitude

(magnitude f)

Magnitude of the vectors from field.

Examples

Usage

(let [f (magnitude (field :sinusoidal))]
  (f (v/vec2 m/HALF_PI m/HALF_PI)))
;;=> 1.4142135623730951

multiplication

(multiplication f1 f2 amount)(multiplication f1 f2)

Multiply two vector fields (as a element-wise multiplication of results).

Examples

Usage

(let [field-1 (field :sinusoidal)
      field-2 (field :swirl)
      field-multiplication (multiplication field-1 field-2)]
  (field-multiplication (v/vec2 0.5 0.3)))
;;=> [-0.05565308460418609 0.1688671791104423]

parametrization

multimethod

Return random parametrization map for given field.

Optinally you can pass part of the parametrization. In this case function will add remaining keys with randomly generated values.

If field doesn’t have parametrization, empty map will be returned.

See field.

Examples

Get random parametrization for given field

(parametrization :auger)
;;=> {:freq -0.8959311275428661,
;;=>  :scale 1.3796451513802848,
;;=>  :sym 1.2301673306301368,
;;=>  :weight -0.561403253438304}

Add lacking fields

(parametrization :auger {:scale 1.0, :freq 1.0})
;;=> {:freq 1.0,
;;=>  :scale 1.0,
;;=>  :sym 0.7756824937529592,
;;=>  :weight -0.7987864630503383}

Returns empty map when field doesn’t have parametrization

(parametrization :sinusoidal)
;;=> {}

random-configuration

(random-configuration)(random-configuration depth)(random-configuration depth f)

Create random configuration for combine function. Optionally with depth (0 = only root is created).

See combine for structure.

Bind *skip-random-fields* to true to exclude fields which are random.

Examples

Generate random configuration

(random-configuration)
;;=> {:amount 1.0,
;;=>  :name :comp,
;;=>  :type :operation,
;;=>  :var1 {:amount 1.0,
;;=>         :name :comp,
;;=>         :type :operation,
;;=>         :var1 {:amount 1.0, :config {}, :name :power, :type :variation},
;;=>         :var2 {:amount 1.0, :config {}, :name :blur, :type :variation}},
;;=>  :var2 {:amount 1.0,
;;=>         :config {:x-freq -1.143498132300067,
;;=>                  :y-freq -0.26592900179904966},
;;=>         :name :pressure-wave,
;;=>         :type :variation}}

One node configuration

(random-configuration 0)
;;=> {:amount 1.0,
;;=>  :config {:rotation 1.061204838634575,
;;=>           :slices -5.17615611680218,
;;=>           :thickness 0.4634968729929825},
;;=>  :name :pie,
;;=>  :type :variation}

Configuration with depth 2

(random-configuration 2)
;;=> {:amount 1.0,
;;=>  :name :deriv,
;;=>  :step 0.061192227269183844,
;;=>  :type :operation,
;;=>  :var {:amount 1.0,
;;=>        :name :comp,
;;=>        :type :operation,
;;=>        :var1 {:amount 1.0, :config {}, :name :scry, :type :variation},
;;=>        :var2 {:amount 1.0,
;;=>               :config {:a 2.6643913543689752,
;;=>                        :b -2.97804733081722,
;;=>                        :c 0.8728341524614294,
;;=>                        :d 0.8025435272855646},
;;=>               :name :pdj,
;;=>               :type :variation}}}

randomize-configuration

(randomize-configuration f)

Randomize values for given configuration. Keeps structure untouched.

Examples

Usage

(let [conf {:type :variation,
            :name :blocky,
            :amount 1.0,
            :config {:x -1.4, :y 0.9, :mp 2.6}}]
  [(randomize-configuration conf) (randomize-configuration conf)])
;;=> [{:amount 1.0,
;;=>   :config {:mp 1.4120029829331664,
;;=>            :x -1.2754534142137968,
;;=>            :y 1.3574640263249287},
;;=>   :name :blocky,
;;=>   :type :variation}
;;=>  {:amount 1.0,
;;=>   :config {:mp 3.6965670527603702,
;;=>            :x -0.7111922170687248,
;;=>            :y -1.1492079176911658},
;;=>   :name :blocky,
;;=>   :type :variation}]

scalar->vector-field

(scalar->vector-field scalar f)(scalar->vector-field scalar f1 f2)

Returns vector field build from scalar fields of the input vector and result of the vector field.

Examples

Usage

(let [f (scalar->vector-field v/heading (field :sinusoidal))]
  (v/applyf (f (v/vec2 m/HALF_PI m/HALF_PI)) m/degrees))
;;=> [45.0 45.0]

Usage (two fields)

(let [f (scalar->vector-field v/heading
                              (field :sinusoidal)
                              (field :julia))]
  (v/applyf (f (v/vec2 m/HALF_PI m/HALF_PI)) m/degrees))
;;=> [45.0 -157.50000000000003]

sum

(sum f1 f2 amount)(sum f1 f2)

Add two vector fields.

Examples

Usage

(let [field-1 (field :sinusoidal)
      field-2 (field :swirl)
      field-sum (sum field-1 field-2)]
  (field-sum (v/vec2 0.5 0.3)))
;;=> [0.3633426850161062 0.866943667067757]