Skip to content

Commit

Permalink
Added new warp functions and 2D checker generators
Browse files Browse the repository at this point in the history
  • Loading branch information
jphsd committed May 3, 2023
1 parent f1dacbc commit 5d7bce4
Show file tree
Hide file tree
Showing 4 changed files with 239 additions and 8 deletions.
104 changes: 104 additions & 0 deletions check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package texture

// Regular polygon tilings of the plane - triangle, square, hexagon.

type Triangles struct {
Name string
Scale float64
}

func NewTriangles(s float64) *Triangles {
return &Triangles{"Triangles", s}
}

func (t *Triangles) Eval2(x, y float64) float64 {
// Even triangles are 1, odd -1
_, rx := MapValueToLambda(x, t.Scale)
_, ry := MapValueToLambda(y, t.Scale)
if (rx + ry) < t.Scale {
return 1
}
return -1
}

type Squares struct {
Name string
Scale float64
}

func NewSquares(s float64) *Squares {
return &Squares{"Squares", s}
}

func (s *Squares) Eval2(x, y float64) float64 {
// Even squares are 1, odd -1
c, _ := MapValueToLambda(x, s.Scale)
if x < 0 {
c++
}
r, _ := MapValueToLambda(y, s.Scale)
if y < 0 {
r++
}
v := r + c
if v&0x1 == 1 {
return -1
}
return 1
}

type Hexagons struct {
Name string
Scale float64
}

func NewHexagons(s float64) *Hexagons {
return &Hexagons{"Hexagons", s}
}

func (h *Hexagons) Eval2(x, y float64) float64 {
// Even columnds are 1, 0, -1, odd columns are -1, 1, 0
c, rx := MapValueToLambda(x, h.Scale)
r, ry := MapValueToLambda(y, h.Scale)

r %= 3
if y < 0 {
r = 2 - r
}
c %= 3
if x < 0 {
c = 2 - c
}

if r == c {
// Diagonal requires special handling
switch r {
case 0:
if (rx + ry) < h.Scale {
return 0
} else {
return 1
}
case 1:
if (rx + ry) < h.Scale {
return 1
} else {
return -1
}
}
// case 2
if (rx + ry) < h.Scale {
return -1
}
return 0
}
v := r + c
switch v {
case 1:
return 1
case 2:
return 0
}
// case 3
return -1
}
2 changes: 1 addition & 1 deletion nonlinear.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type NonLinear struct {
}

func (nl *NonLinear) Eval(t float64) float64 {
// util.NonLinear is in range [0,1], mpa to [-1,1]
// util.NonLinear is in range [0,1], map to [-1,1]
return nl.NLF.Transform(t)*2 - 1
}

Expand Down
132 changes: 126 additions & 6 deletions warp.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import (
"math"
)

const (
twoPi = math.Pi * 2
)

type WarpFunc interface {
Eval(x, y float64) (float64, float64)
}
Expand Down Expand Up @@ -72,11 +76,127 @@ func NewRadialWF(c []float64, rs, cs float64) *RadialWF {
return &RadialWF{"RadialWF", c, rs, cs}
}

// Eval converts from Euclidean to radial coords.
func (rw *RadialWF) Eval(x, y float64) (float64, float64) {
lx, ly := x-rw.Center[0], y-rw.Center[1]
rr := math.Hypot(lx, ly) * rw.RScale
rx := rr*math.Atan2(ly, lx)*rw.CScale + rw.Center[0]
ry := rr + rw.Center[1]
// Eval implements the WarpFunc interface
func (wf *RadialWF) Eval(x, y float64) (float64, float64) {
lx, ly := x-wf.Center[0], y-wf.Center[1]
rr := math.Hypot(lx, ly) * wf.RScale
rx := rr*math.Atan2(ly, lx)*wf.CScale + wf.Center[0]
ry := rr + wf.Center[1]
return rx, ry
}

// SwirlWF performs a swirl warp around Center in x for use in the above warp types.
// The cordinates are converted to polar (r, th) and th advanced by scale * r.
type SwirlWF struct {
Name string
Center []float64 // Center of warp
Scale float64 // Scale factor
}

func NewSwirlWF(c []float64, s float64) *SwirlWF {
return &SwirlWF{"SwirlWF", c, s / twoPi}
}

// Eval implements the WarpFunc interface
func (wf *SwirlWF) Eval(x, y float64) (float64, float64) {
dx, dy := x-wf.Center[0], y-wf.Center[1]
r, th := toPolar(dx, dy)
th += r * wf.Scale
dx, dy = toEuclidean(r, th)
return wf.Center[0] + dx, wf.Center[1] + dy
}

// DrainWF performs a drain warp around Center in x for use in the above warp types.
// The x value is scaled about the central x value by |dy|^alpha*scale
type DrainWF struct {
Name string
Center []float64 // Center of warp
Scale float64 // Scale factor
Effct float64 // Effect radius
}

func NewDrainWF(c []float64, s, e float64) *DrainWF {
return &DrainWF{"DrainWF", c, s, e}
}

// Eval implements the WarpFunc interface
func (wf *DrainWF) Eval(x, y float64) (float64, float64) {
dx, dy := x-wf.Center[0], y-wf.Center[1]
r, th := toPolar(dx, dy)
if r > wf.Effct {
return x, y
}
th += (1 - r/wf.Effct) * wf.Scale
dx, dy = toEuclidean(r, th)
return wf.Center[0] + dx, wf.Center[1] + dy
}

// RadialNLWF performs a radius warp around Center based on an NL
type RadialNLWF struct {
Name string
Center []float64 // Center of warp
NL *NonLinear // [0,1] => [0,1]
Effct float64 // Effect radius
}

func NewRadialNLWF(c []float64, nl *NonLinear, e float64) *RadialNLWF {
return &RadialNLWF{"RadialNLWF", c, nl, e}
}

// Eval implements the WarpFunc interface
func (wf *RadialNLWF) Eval(x, y float64) (float64, float64) {
dx, dy := x-wf.Center[0], y-wf.Center[1]
r, th := toPolar(dx, dy)
if r > wf.Effct {
return x, y
}
t := r / wf.Effct
tp := (wf.NL.Eval(t) + 1) / 2 // NL returns results in [-1,1]
r = tp * wf.Effct
dx, dy = toEuclidean(r, th)
return wf.Center[0] + dx, wf.Center[1] + dy
}

// PinchXWF performs a pinched warp around Center in x for use in the above warp types.
// The x value is scaled about the central x value by |dy|^alpha*scale
type PinchXWF struct {
Name string
Center []float64 // Center of warp
Init float64 // Initial scale
Scale float64 // Scale factor
Alpha float64 // Power factor
}

func NewPinchXWF(c []float64, i, s, a float64) *PinchXWF {
return &PinchXWF{"PinchXWF", c, i, s, a}
}

// Eval implements the WarpFunc interface
func (wf *PinchXWF) Eval(x, y float64) (float64, float64) {
dx, dy := x-wf.Center[0], y-wf.Center[1]
dy *= wf.Scale
if dy < 0 {
dy = -dy
}
if !within(wf.Alpha, 1, 0.00001) {
dy = math.Pow(dy, wf.Alpha)
}
dx *= 1 / (dy + wf.Init)
return wf.Center[0] + dx, y
}

func toPolar(dx, dy float64) (float64, float64) {
return math.Hypot(dx, dy), math.Atan2(dy, dx)
}

func toEuclidean(r, th float64) (float64, float64) {
return r * math.Cos(th), r * math.Sin(th)
}

func within(a, b, eps float64) bool {
d := a - b
if d < 0 {
d = -d
}
return d < eps
}
9 changes: 8 additions & 1 deletion wave.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,14 @@ func (g *NLWave) Eval(v float64) float64 {
}

// Calculate t
t := v1 / g.Lambdas[i]
var t float64
if i > nl-1 {
// Rolled off end due to rounding errors
t = 1
i--
} else {
t = v1 / g.Lambdas[i]
}

// If mirrored, find direction
if g.Mirrored {
Expand Down

0 comments on commit 5d7bce4

Please sign in to comment.