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:
- derivative, grad-x, grad-y - directional derivative of the field
- sum - sum of two fields
- multiply - multiplication of the fields
- composition - composition of the fields
- angles - angles of the field vectors
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:
- combine - create vector field randomly of from given parametrization.
- random-configuration - returns random configuration as a map
- randomize-configuration - change parametrization for given configuration.
Categories
- Create fields: field parametrization
- Derive scalar field from vector field: cross curl divergence dot heading jacobian magnitude
- Derive vector field from other vector field(s).: *skip-random-fields* angle-between combine composition derivative grad-x grad-y multiplication random-configuration randomize-configuration scalar->vector-field sum
Other vars: ->VoronCalcType ->VoronResType fields-list fields-list-not-random fields-list-random
*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.
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.
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)
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]