refactor & feat: moved window visualization to
it's own file and created a video visulazer
This commit is contained in:
71
visualizer/video.go
Normal file
71
visualizer/video.go
Normal file
@ -0,0 +1,71 @@
|
||||
package visualizer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"maze-solver/io/writer"
|
||||
"maze-solver/maze"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
"github.com/mazznoer/colorgrad"
|
||||
)
|
||||
|
||||
type VideoVisualizer struct {
|
||||
Filename string
|
||||
Framerate float64
|
||||
ffmpeg_cmd string
|
||||
}
|
||||
|
||||
func (v *VideoVisualizer) Init(*maze.Maze) {
|
||||
path, err := exec.LookPath("ffmpeg")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
v.ffmpeg_cmd = path
|
||||
println(path)
|
||||
}
|
||||
func (v *VideoVisualizer) Run(lets_go chan<- bool) { lets_go <- true }
|
||||
|
||||
func (v *VideoVisualizer) Visualize(solved_chan <-chan *maze.SolvedMaze) {
|
||||
tmp_dir, err := os.MkdirTemp("", "maze-solver-go-")
|
||||
defer os.RemoveAll(tmp_dir)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
i := 0
|
||||
for solved := range solved_chan {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
img_writer := writer.ImageWriter{
|
||||
Filename: path.Join(tmp_dir, fmt.Sprintf("%07v.png", i)),
|
||||
Maze: solved,
|
||||
CellWidth: 2,
|
||||
CellHeight: 2,
|
||||
WallColor: color.Black,
|
||||
PathColor: color.White,
|
||||
SolutionGradient: colorgrad.Warm(),
|
||||
}
|
||||
img_writer.Write()
|
||||
wg.Done()
|
||||
}()
|
||||
i++
|
||||
}
|
||||
wg.Wait()
|
||||
cmd := exec.Command(
|
||||
v.ffmpeg_cmd,
|
||||
"-y",
|
||||
"-pattern_type", "glob",
|
||||
"-i", path.Join(tmp_dir, "*.png"),
|
||||
"-framerate", fmt.Sprint(v.Framerate),
|
||||
v.Filename,
|
||||
)
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
@ -1,58 +1,41 @@
|
||||
package visualizer
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"maze-solver/io/writer"
|
||||
"fmt"
|
||||
"maze-solver/maze"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/app"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"github.com/mazznoer/colorgrad"
|
||||
)
|
||||
|
||||
var (
|
||||
a fyne.App
|
||||
w fyne.Window
|
||||
img_writer writer.ImageWriter
|
||||
cimg *canvas.Image
|
||||
type Visualizer interface {
|
||||
Init(*maze.Maze)
|
||||
Visualize(<-chan *maze.SolvedMaze)
|
||||
Run(lets_go chan<- bool)
|
||||
}
|
||||
|
||||
type VisualizerFactory struct {
|
||||
Type *string
|
||||
Filename *string
|
||||
Framerate *float64
|
||||
}
|
||||
|
||||
const (
|
||||
_VIDEO = "video"
|
||||
_WINDOW = "window"
|
||||
)
|
||||
|
||||
func Init(m *maze.Maze) {
|
||||
a = app.New()
|
||||
w = a.NewWindow("maze-solver-go")
|
||||
img_writer = writer.ImageWriter{
|
||||
Filename: "",
|
||||
Maze: &maze.SolvedMaze{
|
||||
Maze: m,
|
||||
Solution: []*maze.Node{},
|
||||
},
|
||||
CellWidth: 2,
|
||||
CellHeight: 2,
|
||||
WallColor: color.Black,
|
||||
PathColor: color.White,
|
||||
SolutionGradient: colorgrad.Warm(),
|
||||
}
|
||||
println(m.Height)
|
||||
cimg = canvas.NewImageFromImage(img_writer.GenerateImage())
|
||||
w.SetContent(cimg)
|
||||
w.Resize(
|
||||
fyne.NewSize(
|
||||
float32(m.Width*img_writer.CellWidth),
|
||||
float32(m.Height*img_writer.CellHeight),
|
||||
),
|
||||
)
|
||||
w.Show()
|
||||
var VIZ_METHODS = []string{
|
||||
_VIDEO,
|
||||
_WINDOW,
|
||||
}
|
||||
|
||||
func Visualize(solved_chan <-chan *maze.SolvedMaze) {
|
||||
for solved := range solved_chan {
|
||||
img_writer.Maze = solved
|
||||
cimg.Image = img_writer.GenerateImage()
|
||||
cimg.Refresh()
|
||||
func (f *VisualizerFactory) Get() Visualizer {
|
||||
switch *f.Type {
|
||||
case _VIDEO:
|
||||
return &VideoVisualizer{
|
||||
Filename: *f.Filename,
|
||||
Framerate: *f.Framerate,
|
||||
}
|
||||
case _WINDOW:
|
||||
return &WindowVisualizer{}
|
||||
}
|
||||
}
|
||||
|
||||
func Run() {
|
||||
w.ShowAndRun()
|
||||
panic(fmt.Sprintf("Unrecognized visualizer type %q", *f.Type))
|
||||
}
|
||||
|
65
visualizer/window.go
Normal file
65
visualizer/window.go
Normal file
@ -0,0 +1,65 @@
|
||||
package visualizer
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"maze-solver/io/writer"
|
||||
"maze-solver/maze"
|
||||
|
||||
"fyne.io/fyne"
|
||||
"fyne.io/fyne/app"
|
||||
"fyne.io/fyne/canvas"
|
||||
"fyne.io/fyne/dialog"
|
||||
"github.com/mazznoer/colorgrad"
|
||||
)
|
||||
|
||||
type WindowVisualizer struct {
|
||||
app fyne.App
|
||||
window fyne.Window
|
||||
img_writer writer.ImageWriter
|
||||
cimg *canvas.Image
|
||||
}
|
||||
|
||||
func (v *WindowVisualizer) Init(m *maze.Maze) {
|
||||
v.app = app.New()
|
||||
v.window = v.app.NewWindow("maze-solver-go")
|
||||
v.img_writer = writer.ImageWriter{
|
||||
Filename: "",
|
||||
Maze: &maze.SolvedMaze{
|
||||
Maze: m,
|
||||
Solution: []*maze.Node{},
|
||||
},
|
||||
CellWidth: 2,
|
||||
CellHeight: 2,
|
||||
WallColor: color.Black,
|
||||
PathColor: color.White,
|
||||
SolutionGradient: colorgrad.Warm(),
|
||||
}
|
||||
v.cimg = canvas.NewImageFromImage(v.img_writer.GenerateImage())
|
||||
v.window.SetContent(v.cimg)
|
||||
v.window.Resize(
|
||||
fyne.NewSize(
|
||||
m.Width*v.img_writer.CellWidth,
|
||||
m.Height*v.img_writer.CellHeight,
|
||||
),
|
||||
)
|
||||
v.window.Show()
|
||||
}
|
||||
|
||||
func (v *WindowVisualizer) Visualize(solved_chan <-chan *maze.SolvedMaze) {
|
||||
for solved := range solved_chan {
|
||||
v.img_writer.Maze = solved
|
||||
v.cimg.Image = v.img_writer.GenerateImage()
|
||||
v.cimg.Refresh()
|
||||
}
|
||||
}
|
||||
|
||||
func (v *WindowVisualizer) Run(lets_go chan<- bool) {
|
||||
dial := dialog.NewConfirm("Start", "Let's go", func(ok bool) {
|
||||
lets_go <- ok
|
||||
if !ok {
|
||||
v.window.Close()
|
||||
}
|
||||
}, v.window)
|
||||
dial.Show()
|
||||
v.window.ShowAndRun()
|
||||
}
|
Reference in New Issue
Block a user