6 Commits

11 changed files with 589 additions and 54 deletions

View File

@ -1,30 +1,24 @@
last_step: 100
init_amount: 10
screen_size:
width: 1400
height: 1000
last_step: 500
init_amount: 20
steps:
- step: 10
amount: 1
- step: 100
amount: 20
neighbours: 5
- step: 200
amount: 20
neighbours: 10
- step: 300
amount: 5
neighbours: 1
- step: 20
amount: 100
- step: 400
amount: 5
neighbours: 1
- step: 30
amount: 1
- step: 500
amount: 6
neighbours: 1
- step: 40
amount: 10
neighbours: 2
- step: 50
Amount: 2
neighbours: 1
- step: 60
amount: 2
neighbours: 1
- step: 70
amount: 3
neighbours: 2
- step: 80
amount: 3
neighbours: 1
- step: 3000
amount: 3
- step: 600
amount: 7
neighbours: 1

172
examples/bpc_sliced.omp Normal file
View File

@ -0,0 +1,172 @@
(
setf *om-current-persistent*
(
om-load-patch1 "Patch 2"
(
quote
(
(
let
(
(
box
(
om-load-editor-box1 "BPC"
(
quote bpc
)
(
quote
(
(
om-load-inputfun
(
quote input-funbox
)
"object" "self" nil
)
(
om-load-inputfun
(
quote input-funbox
)
"X coordinates (list)" "x-points"
(
list 0 100
)
)
(
om-load-inputfun
(
quote input-funbox
)
"Y coordinates (list)" "y-points"
(
list 0 100
)
)
(
om-load-inputfun
(
quote input-funbox
)
"precision
(
integer
) [0 - 10]" "decimals" 0
)
)
)
(
om-make-point 151 96
)
(
om-make-point 40 60
)
(
let
(
(
newobj
(
when
(
find-class
(
quote bpc
)
nil
)
(
let
(
(
newbpf
(
simple-bpf-from-list
(
quote
(
-1 99 70
)
)
(
quote
(
0 100 65
)
)
(
quote bpc
)
0
)
)
)
(
setf
(
bpfcolor newbpf
)
(
om-make-color 0 0 0
)
)
(
set-name newbpf "BPC"
)
newbpf
)
)
)
)
(
when newobj
)
newobj
)
"x" nil
(
pairlis
(
quote
(
picture winpos winsize
)
)
(
list nil
(
om-make-point 0 0
)
(
om-make-point 1900 1006
)
)
)
nil nil nil nil
)
)
)
(
when
(
fboundp
(
quote set-active
)
)
(
set-active box nil
)
)
box
)
)
)
(
quote nil
)
nil 6.19
)
)

4
examples/empty_omp.omp Normal file
View File

@ -0,0 +1,4 @@
; OM File Header - Saved 2022/12/29 14:43:16
; (6.19 :patc (om-make-point 10 10) (om-make-point 50 50) (om-make-point 500 400) "" 183 0 "2022/12/29 14:43:16" "2022/12/29 14:43:16")
; End File Header
(in-package :om)(load-lib-for (quote nil))(setf *om-current-persistent* (om-load-patch1 "Patch" (quote nil) (quote nil) nil 6.19))

183
examples/simple_bpc.omp Normal file
View File

@ -0,0 +1,183 @@
(
in-package :om
)
(
load-lib-for
(
quote nil
)
)
(
setf *om-current-persistent*
(
om-load-patch1 "Patch 2"
(
quote
(
(
let
(
(
box
(
om-load-editor-box1 "BPC"
(
quote bpc
)
(
quote
(
(
om-load-inputfun
(
quote input-funbox
)
"object" "self" nil
)
(
om-load-inputfun
(
quote input-funbox
)
"X coordinates (list)" "x-points"
(
list 0 100
)
)
(
om-load-inputfun
(
quote input-funbox
)
"Y coordinates (list)" "y-points"
(
list 0 100
)
)
(
om-load-inputfun
(
quote input-funbox
)
"precision
(
integer
) [0 - 10]" "decimals" 0
)
)
)
(
om-make-point 151 96
)
(
om-make-point 40 60
)
(
let
(
(
newobj
(
when
(
find-class
(
quote bpc
)
nil
)
(
let
(
(
newbpf
(
simple-bpf-from-list
(
quote
(
-1 99 70
)
)
(
quote
(
0 100 65
)
)
(
quote bpc
)
0
)
)
)
(
setf
(
bpfcolor newbpf
)
(
om-make-color 0 0 0
)
)
(
set-name newbpf "BPC"
)
newbpf
)
)
)
)
(
when newobj
)
newobj
)
"x" nil
(
pairlis
(
quote
(
picture winpos winsize
)
)
(
list nil
(
om-make-point 0 0
)
(
om-make-point 1900 1006
)
)
)
nil nil nil nil
)
)
)
(
when
(
fboundp
(
quote set-active
)
)
(
set-active box nil
)
)
box
)
)
)
(
quote nil
)
nil 6.19
)
)

96
main.go
View File

@ -4,6 +4,7 @@ import (
"bytes"
"encoding/base64"
"fmt"
"html/template"
"image"
"image/color"
"image/png"
@ -19,7 +20,6 @@ import (
)
// parameters
var windowWidth, windowHeight = 1000, 700
var goidSize = 3
var goidColor = color.RGBA{200, 200, 100, 255} // gray, 50% transparency
var populationSize = 0
@ -28,11 +28,24 @@ var numNeighbours = 5
var separationFactor = float64(goidSize * 5)
var coherenceFactor = 8
const OM_TEMPLATE = `; OM File Header - Saved 2023/01/22 08:12:44
; (7.01 :patc (om-make-point 10 10) (om-make-point 915 795) (om-make-point 845 307) "" 183 0 "2023/01/22 08:11:39" "2023/01/22 08:12:44")
; End File Header
(in-package :om)(load-lib-for (quote nil))(setf *om-current-persistent* (om-load-patch1 "Patch" (quote ({{range $val := .BPC}}(let ((box (om-load-editor-box1 "BPC" (quote bpc) (quote ((om-load-inputfun (quote input-funbox) "object" "self" nil) (om-load-inputfun (quote input-funbox) "X coordinates (list)" "x-points" (list{{ range $x := .X }} {{ $x }}{{ end }})) (om-load-inputfun (quote input-funbox) "Y coordinates (list)" "y-points" (list{{ range $y:= .Y }} {{ $y }}{{ end }})) (om-load-inputfun (quote input-funbox) "precision (integer) [0 - 10]" "decimals" 0))) (om-make-point {{ .MakePoint.X }} {{ .MakePoint.Y }}) (om-make-point 50 50) (let ((newobj (when (find-class (quote bpc) nil) (let ((newbpf (simple-bpf-from-list (quote ({{ range $x := .X }} {{ $x }}{{ end }})) (quote ({{ range $y := .Y }} {{ $y }}{{ end }})) (quote bpc) 0))) (setf (bpfcolor newbpf) (om-make-color 0 0 0)) (set-name newbpf "BPC") newbpf)))) (when newobj) newobj) "&" nil (pairlis (quote (picture winpos winsize)) (list nil (om-make-point 20 20)(om-make-point 20 20))) nil nil nil nil))) (when (fboundp (quote set-active)) (set-active box nil)) box){{ end }}))(quote nil) nil 7.01))
`
type configuration struct {
Steps []steps `yaml:"steps"`
ScreenSize ScreenSize `yaml:"screen_size"`
LastStep int `yaml:"last_step"`
InitAmount int `yaml:"init_amount"`
}
type ScreenSize struct {
Width int `yaml:"width"`
Height int `yaml:"height"`
}
type steps struct {
Step int `yaml:"step"`
Amount int `yaml:"amount"`
@ -43,15 +56,24 @@ type Coor struct {
X int `yaml:"x"`
Y int `yaml:"y"`
}
type BPC struct {
BPC []Coords
}
type Coords struct {
X []int
Y []int
MakePoint Coor
}
type OutPut struct {
Goid int `yaml:"goid"`
Loop int `yaml:"loop"`
Data Coor `yaml:"data"`
}
func fixGoids(gs []*Goid, actual int, wished int) ([]*Goid, int) {
func fixGoids(gs []*Goid, actual int, wished int, field ScreenSize) ([]*Goid, int) {
if actual < wished {
g := createRandomGoid()
g := createRandomGoid(field)
gs = append(gs, &g)
return gs, actual + 1
} else if wished < actual {
@ -84,12 +106,13 @@ func main() {
hideCursor()
var goids []*Goid
for i := 0; i < populationSize; i++ {
g := createRandomGoid()
g := createRandomGoid(config.ScreenSize)
goids = append(goids, &g)
}
current_stage := 0
for i := 0; i < loops; i++ {
goids, populationSize = fixGoids(goids, populationSize, steps[current_stage].Amount)
goids, populationSize = fixGoids(goids, populationSize, steps[current_stage].Amount, config.ScreenSize)
fmt.Printf("%d - %d", i, populationSize)
if steps[current_stage].NumNeighbours >= populationSize {
numNeighbours = populationSize
} else {
@ -98,8 +121,8 @@ func main() {
if i == steps[current_stage+1].Step {
current_stage += 1
}
move(goids, fo, i)
frame := draw(goids)
move(goids, fo, i, config.ScreenSize)
frame := draw(goids, config.ScreenSize)
printImage(frame.SubImage(frame.Rect))
}
showCursor()
@ -121,29 +144,58 @@ func main() {
if err != nil {
panic(err)
}
bpc := BPC{}
mX := 0
mY := 0
for i := 0; i <= total; i++ {
mX += 70
if i%10 == 0 {
mX = 70
mY += 70
}
coords := Coords{}
makePoint := Coor{X: mX, Y: mY}
coords.MakePoint = makePoint
var x []string
var y []string
outfile.Write([]byte(fmt.Sprintf("GOID: %d\n", i)))
for z := 0; z <= loops; z++ {
cX := 0
cY := 0
check := false
for _, g := range output {
if g.Goid == i && g.Loop == z {
check = true
x = append(x, strconv.Itoa(g.Data.X))
y = append(y, strconv.Itoa(g.Data.Y))
coords.X = append(coords.X, g.Data.X)
coords.Y = append(coords.Y, g.Data.Y)
cX = g.Data.X
cY = g.Data.Y
break
}
}
if !check {
x = append(x, "-")
y = append(y, "-")
coords.X = append(coords.X, cX)
coords.Y = append(coords.Y, cY)
}
}
bpc.BPC = append(bpc.BPC, coords)
outfile.Write([]byte(fmt.Sprintf("%v\n", x)))
outfile.Write([]byte(fmt.Sprintf("%v\n", y)))
}
t, err := template.New("todos").Parse(OM_TEMPLATE)
if err != nil {
panic(err)
}
file, _ := os.Create("Patch.omp")
defer file.Close()
err = t.Execute(file, bpc)
if err != nil {
panic(err)
}
}
// Goid represents a drawn goid
@ -156,10 +208,10 @@ type Goid struct {
Color color.Color
}
func createRandomGoid() (g Goid) {
func createRandomGoid(field ScreenSize) (g Goid) {
g = Goid{
X: rand.Intn(windowWidth),
Y: rand.Intn(windowHeight),
X: rand.Intn(field.Width),
Y: rand.Intn(field.Height),
Vx: rand.Intn(goidSize),
Vy: rand.Intn(goidSize),
R: goidSize,
@ -189,7 +241,7 @@ func (g *Goid) distance(n Goid) float64 {
}
// move the goids with the 3 classic boid rules
func move(goids []*Goid, file *os.File, loop int) {
func move(goids []*Goid, file *os.File, loop int, field ScreenSize) {
for i, goid := range goids {
neighbours := goid.nearestNeighbours(goids)
separate(goid, neighbours)
@ -197,21 +249,21 @@ func move(goids []*Goid, file *os.File, loop int) {
cohere(goid, neighbours)
position := fmt.Sprintf("- goid: %d\n loop: %d\n data:\n x: %d\n y: %d\n", i, loop, goid.X, goid.Y)
file.Write([]byte(position))
stayInWindow(goid)
stayInWindow(goid, field)
}
}
// if goid goes out of the window frame it comes back on the other side
func stayInWindow(goid *Goid) {
func stayInWindow(goid *Goid, field ScreenSize) {
if goid.X < 0 {
goid.X = windowWidth - goid.X
} else if goid.X > windowWidth {
goid.X = windowWidth - goid.X
goid.X = field.Width - goid.X
} else if goid.X > field.Width {
goid.X = field.Width - goid.X
}
if goid.Y < 0 {
goid.Y = windowHeight - goid.Y
} else if goid.Y > windowHeight {
goid.Y = windowHeight - goid.Y
goid.Y = field.Height - goid.Y
} else if goid.Y > field.Height {
goid.Y = field.Height - goid.Y
}
}
@ -259,8 +311,8 @@ func cohere(g *Goid, neighbours []Goid) {
}
// draw the goids
func draw(goids []*Goid) *image.RGBA {
dest := image.NewRGBA(image.Rect(0, 0, windowWidth, windowHeight))
func draw(goids []*Goid, field ScreenSize) *image.RGBA {
dest := image.NewRGBA(image.Rect(0, 0, field.Width, field.Height))
gc := draw2dimg.NewGraphicContext(dest)
for _, goid := range goids {
gc.SetFillColor(goid.Color)

View File

@ -0,0 +1 @@
pacjage

11
pkg/types/omp/bpc.go Normal file
View File

@ -0,0 +1,11 @@
package omp
type BPC struct {
}
func (s BPC) Init() {
}
// InitPatch()

22
pkg/types/omp/header.go Normal file
View File

@ -0,0 +1,22 @@
package omp
type Header struct {
Data []byte
}
//TODO: It must be create dynamically for different kinds of entities (patch, maquette, etc)
func (h *Header) Init() {
h.Data = []byte(`; OM File Header - Saved 2022/12/29 14:43:16
; (6.19 :patc (om-make-point 10 10) (om-make-point 50 50) (om-make-point 500 400) "" 183 0 "2022/12/29 14:43:16" "2022/12/29 14:43:16")
; End File Header
`)
}
func (h *Header) GetData() []byte {
return h.Data
}
func (h *Header) DataToString() string {
return string(h.Data)
}

View File

@ -0,0 +1,21 @@
package omp_test
import (
"goids/pkg/types/omp"
"testing"
)
const headerExample = `; OM File Header - Saved 2022/12/29 14:43:16
; (6.19 :patc (om-make-point 10 10) (om-make-point 50 50) (om-make-point 500 400) "" 183 0 "2022/12/29 14:43:16" "2022/12/29 14:43:16")
; End File Header
`
func TestAbs(t *testing.T) {
header := &omp.Header{}
header.Init()
str := header.DataToString()
if str != headerExample {
t.Errorf("Header is wrong\nwant:\n%s \n\ngot \n%s", headerExample, str)
}
}

51
pkg/types/omp/omp.go Normal file
View File

@ -0,0 +1,51 @@
package omp
import (
"bytes"
"fmt"
)
type OMP struct {
Header Header
Data Data
}
func (s OMP) Build() []byte {
buff := bytes.NewBufferString("")
buff.Write(s.Header.GetData())
buff.Write(s.Data.GetIntro())
buff.Write(s.Data.GetLibFor())
buff.Write(s.Data.GetOMCurrentPersistent())
return buff.Bytes()
}
type Data struct {
Intro []byte
LibFor []byte
CurrentPersistent []byte
}
func (s *Data) GetIntro() []byte {
return s.Intro
}
func (s *Data) SetIntro() {
s.Intro = []byte("(in-package :om)")
}
func (s *Data) GetLibFor() []byte {
return s.LibFor
}
func (s *Data) SetLibFor() {
s.LibFor = []byte("(load-lib-for (quote nil))")
}
func (s *Data) SetOMCurrentPersistent(kind string, name string) {
s.CurrentPersistent = []byte(fmt.Sprintf("(setf *om-current-persistent* (%s \"%s\" () (quote nil) nil 6.19))", kind, name))
}
func (s *Data) GetOMCurrentPersistent() []byte {
return s.CurrentPersistent
}

24
pkg/types/omp/omp_test.go Normal file
View File

@ -0,0 +1,24 @@
package omp_test
import (
"goids/pkg/types/omp"
"testing"
)
const ompExample = `; OM File Header - Saved 2022/12/29 14:43:16
; (6.19 :patc (om-make-point 10 10) (om-make-point 50 50) (om-make-point 500 400) "" 183 0 "2022/12/29 14:43:16" "2022/12/29 14:43:16")
; End File Header
(in-package :om)(load-lib-for (quote nil))(setf *om-current-persistent* (om-load-patch1 "Test Patch" (quote nil) (quote nil) nil 6.19))`
func TestOmpBuilder(t *testing.T) {
header := &omp.OMP{}
header.Data.SetIntro()
header.Data.SetLibFor()
header.Data.SetOMCurrentPersistent("om-load-patch1", "Test Patch")
header.Header.Init()
str := string(header.Build())
if str != ompExample {
t.Errorf("Header is wrong\nwant:\n%s \n\ngot \n%s", ompExample, str)
}
}