-
-
Notifications
You must be signed in to change notification settings - Fork 112
Description
One issue that has been preventing me from using Sketchy (my generative art framework) more often is frequent panics in the path intersection part of the code. This issue isn't about that specifically, but I'm guessing it might be related.
Even when there are no panics, I get unexpected behavior sometimes. Here is a simple example. This program animates a Lissajous figure, using ebitengine for the animation and canvas for drawing the curve. You can see from the animation that with some different phases of the curve, the empty areas between parts of the curve become filled. I would not expect this since I set the fill to transparent and only call Stroke().
The code is also below. Is this expected and if not is it related to path intersections?
Screencast_20251004_195642.webm
package main
import (
"log"
"github.com/aldernero/gaul"
"github.com/hajimehoshi/ebiten/v2"
"github.com/tdewolff/canvas"
"github.com/tdewolff/canvas/renderers/rasterizer"
)
const (
screenWidth = 600
screenHeight = 600
radiansPerTick = 0.01
curveResolution = 1000
strokeWidth = 1
mmPerPx = 0.26458333
)
type Game struct {
lissa gaul.Lissajous
center gaul.Point
scale float64
cnvs *canvas.Canvas
}
func (g *Game) Update() error {
g.lissa.Px += radiansPerTick
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
g.cnvs.Reset()
ctx := canvas.NewContext(g.cnvs)
// Draw background
ctx.SetFillColor(canvas.Black)
gaul.Rect{W: float64(screenWidth) * mmPerPx, H: float64(screenHeight) * mmPerPx}.Draw(ctx) // Background
// Draw Lissajous curve
ctx.SetStrokeWidth(strokeWidth)
ctx.SetStrokeColor(canvas.White)
ctx.SetFillColor(canvas.Transparent)
curve := gaul.GenLissajous(g.lissa, curveResolution, g.center, g.scale)
curve.Draw(ctx)
ctx.Stroke()
// Draw to ebiten screen
img := rasterizer.Draw(g.cnvs, canvas.DefaultResolution, canvas.DefaultColorSpace)
op := &ebiten.DrawImageOptions{}
screen.DrawImage(ebiten.NewImageFromImage(img), op)
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
}
func main() {
game := Game{
lissa: gaul.Lissajous{
Nx: 3,
Ny: 2,
Px: 0,
Py: 0,
},
center: gaul.Point{
X: mmPerPx * screenWidth / 2,
Y: mmPerPx * screenHeight / 2,
},
scale: float64(screenWidth) * mmPerPx * 0.4,
cnvs: canvas.New(screenWidth*mmPerPx, screenHeight*mmPerPx),
}
ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetWindowTitle("Animated Lissajous Figure")
if err := ebiten.RunGame(&game); err != nil {
log.Fatal(err)
}
}