From c9350c41c38750e2230357f655f6e72035995c34 Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Tue, 19 Apr 2022 05:25:30 +0300 Subject: . --- cirsim/component.go | 178 ++++++++++++++++++++++++++++++++ cirsim/models.go | 102 ++++++++++++++++++ cirsim/node.go | 96 +++++++++++++++++ cirsim/simulation.go | 286 +++++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 30 ++++++ go.sum | 113 ++++++++++++++++++++ main.go | 18 ++++ 7 files changed, 823 insertions(+) create mode 100644 cirsim/component.go create mode 100644 cirsim/models.go create mode 100644 cirsim/node.go create mode 100644 cirsim/simulation.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go diff --git a/cirsim/component.go b/cirsim/component.go new file mode 100644 index 0000000..5b03fd2 --- /dev/null +++ b/cirsim/component.go @@ -0,0 +1,178 @@ +package cirsim + +import ( + "fmt" + "io" + "log" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/widget" + "github.com/wcharczuk/go-chart/v2" + "github.com/wcharczuk/go-chart/v2/drawing" +) + +type Component struct { + widget.BaseWidget + Pos fyne.Position + Model Modeler + CurrentOverTime []float64 + ANode *Node + BNode *Node + CurrentRange chart.Range + Image *canvas.Image + labels []*widget.Label + entries []*widget.Entry +} + +func NewComponent(settings io.Reader, r chart.Range, nodes []*Node, update func()) *Component { + var c Component + var t string + var a int + var b int + _, err := fmt.Fscanf(settings, "%f %f %s %d %d\n", + &c.Pos.X, &c.Pos.Y, &t, &a, &b, + ) + if err != nil { + return nil + } + if a <= 0 || b <= 0 { + log.Fatal("unconnected components in the circuit") + } + c.ANode = nodes[a-1] + nodes[a-1].AComponents = append(nodes[a-1].AComponents, &c) + c.BNode = nodes[b-1] + nodes[b-1].BComponents = append(nodes[b-1].BComponents, &c) + switch t { + case "resistor": + c.Model = &Resistor{100.0} + case "capacitor": + c.Model = &Capacitor{0.000001} + case "inductor": + c.Model = &Inductor{0.000001} + case "diode": + c.Model = &Diode{} + case "power": + c.Model = &Power{Current: 1.0, Frequency: 1000.0} + } + c.entries = make([]*widget.Entry, 0) + c.labels = make([]*widget.Label, 0) + for k, v := range c.Model.Parameters() { + e := widget.NewEntry() + e.TextStyle.Monospace = true + e.SetPlaceHolder(k) + e.SetText(fmt.Sprintf("%f", v)) + e.OnSubmitted = func(s string) { + var v float64 + _, err := fmt.Sscanf(s+"\n", "%f\n", &v) + if err != nil { + e.SetText(fmt.Sprintf("%f", c.Model.Parameters()[k])) + } else { + c.Model.UpdateParameter(k, v) + update() + } + } + c.entries = append(c.entries, e) + l := widget.NewLabel(k) + l.TextStyle.Monospace = true + c.labels = append(c.labels, l) + } + c.CurrentRange = r + c.CurrentOverTime = make([]float64, 1000) + for i := range c.CurrentOverTime { + c.CurrentOverTime[i] = 0 + } + c.renderChart() + return &c +} + +func (c *Component) renderChart() { + graph := chart.Chart{ + Width: 140, + Height: 60, + ColorPalette: &componentColorPalette{}, + XAxis: chart.HideXAxis(), + YAxis: chart.YAxis{ + Style: chart.Hidden(), + Range: c.CurrentRange, + }, + Series: []chart.Series{ + chart.ContinuousSeries{ + XValues: chart.LinearRange(0, 999), + YValues: c.CurrentOverTime, + }, + }, + } + writer := &chart.ImageWriter{} + graph.Render(chart.PNG, writer) + img, _ := writer.Image() + c.Image = canvas.NewImageFromImage(img) +} + +type componentColorPalette struct{} + +func (*componentColorPalette) BackgroundColor() drawing.Color { + return drawing.ColorTransparent +} +func (*componentColorPalette) BackgroundStrokeColor() drawing.Color { + return drawing.ColorTransparent +} +func (*componentColorPalette) CanvasColor() drawing.Color { + return drawing.Color{R: 191, G: 254, B: 247, A: 128} +} +func (*componentColorPalette) CanvasStrokeColor() drawing.Color { + return drawing.ColorTransparent +} +func (*componentColorPalette) AxisStrokeColor() drawing.Color { + return drawing.ColorTransparent +} +func (*componentColorPalette) TextColor() drawing.Color { + return drawing.ColorTransparent +} +func (*componentColorPalette) GetSeriesColor(index int) drawing.Color { + return drawing.Color{R: 3, G: 247, B: 198, A: 255} +} + +func (c *Component) CreateRenderer() fyne.WidgetRenderer { return c } +func (c *Component) Layout(s fyne.Size) { + pos := fyne.NewPos(0, 0) + for i, e := range c.entries { + c.labels[i].Resize(fyne.NewSize(140, c.labels[i].MinSize().Height)) + c.labels[i].Move(pos) + pos.Y += c.labels[i].MinSize().Height + e.Resize(fyne.NewSize(140, e.MinSize().Height)) + e.Move(pos) + pos.Y += e.MinSize().Height + } + c.Image.Resize(fyne.NewSize(140, 60)) + c.Image.Move(pos) +} +func (c *Component) MinSize() fyne.Size { + res := fyne.NewSize(140, 60) + for _, e := range c.entries { + res.Height += e.MinSize().Height + } + for _, l := range c.labels { + res.Height += l.MinSize().Height + } + return res +} +func (c *Component) Refresh() { + c.renderChart() + for _, e := range c.entries { + e.Refresh() + } + for _, l := range c.labels { + l.Refresh() + } +} +func (c *Component) Destroy() {} +func (c *Component) Objects() []fyne.CanvasObject { + res := []fyne.CanvasObject{} + for i, e := range c.entries { + res = append(res, c.labels[i]) + res = append(res, e) + } + res = append(res, c.Image) + return res +} diff --git a/cirsim/models.go b/cirsim/models.go new file mode 100644 index 0000000..f4a73e9 --- /dev/null +++ b/cirsim/models.go @@ -0,0 +1,102 @@ +package cirsim + +import "math" + +type Modeler interface { + ModelConductance(time, delta, voltage, current float64) float64 + ModelCurrent(time, delta, voltage, current float64) float64 + Parameters() map[string]float64 + UpdateParameter(name string, value float64) +} + +type Capacitor struct { + Capacitance float64 +} + +func (m *Capacitor) ModelConductance(time, delta, voltage, current float64) float64 { + return 2.0 * m.Capacitance / delta +} +func (m *Capacitor) ModelCurrent(time, delta, voltage, current float64) float64 { + return -current - voltage*2*m.Capacitance/delta +} +func (m *Capacitor) Parameters() map[string]float64 { + return map[string]float64{"Capacitance": m.Capacitance} +} +func (m *Capacitor) UpdateParameter(name string, value float64) { + if name == "Capacitance" { + m.Capacitance = value + } +} + +type Resistor struct { + Resistance float64 +} + +func (m *Resistor) ModelConductance(time, delta, voltage, current float64) float64 { + return 1.0 / m.Resistance +} +func (m *Resistor) ModelCurrent(time, delta, voltage, current float64) float64 { + return 0 +} +func (m *Resistor) Parameters() map[string]float64 { + return map[string]float64{"Resistance": m.Resistance} +} +func (m *Resistor) UpdateParameter(name string, value float64) { + if name == "Resistance" { + m.Resistance = value + } +} + +type Inductor struct { + Inductance float64 +} + +func (m *Inductor) ModelConductance(time, delta, voltage, current float64) float64 { + return delta / (2.0 * m.Inductance) +} +func (m *Inductor) ModelCurrent(time, delta, voltage, current float64) float64 { + return current + voltage*delta/(2*m.Inductance) +} +func (m *Inductor) Parameters() map[string]float64 { + return map[string]float64{"Inductance": m.Inductance} +} +func (m *Inductor) UpdateParameter(name string, value float64) { + if name == "Inductance" { + m.Inductance = value + } +} + +type Diode struct{} + +func (m *Diode) ModelConductance(time, delta, voltage, current float64) float64 { + return 0 +} +func (m *Diode) ModelCurrent(time, delta, voltage, current float64) float64 { + return 0 +} +func (m *Diode) Parameters() map[string]float64 { + return map[string]float64{} +} +func (m *Diode) UpdateParameter(name string, value float64) {} + +type Power struct { + Current float64 + Frequency float64 +} + +func (m *Power) ModelConductance(time, delta, voltage, current float64) float64 { + return 0 +} +func (m *Power) ModelCurrent(time, delta, voltage, current float64) float64 { + return m.Current * math.Sin(time*m.Frequency*2*math.Pi) +} +func (m *Power) Parameters() map[string]float64 { + return map[string]float64{"Current": m.Current, "Frequency": m.Frequency} +} +func (m *Power) UpdateParameter(name string, value float64) { + if name == "Current" { + m.Current = value + } else if name == "Frequency" { + m.Frequency = value + } +} diff --git a/cirsim/node.go b/cirsim/node.go new file mode 100644 index 0000000..a9e8301 --- /dev/null +++ b/cirsim/node.go @@ -0,0 +1,96 @@ +package cirsim + +import ( + "fmt" + "io" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/widget" + "github.com/wcharczuk/go-chart/v2" + "github.com/wcharczuk/go-chart/v2/drawing" +) + +type Node struct { + widget.BaseWidget + Pos fyne.Position + VoltageOverTime []float64 + VoltageRange chart.Range + AComponents []*Component + BComponents []*Component + Image *canvas.Image +} + +func NewNode(settings io.Reader, r chart.Range) *Node { + var n Node + _, err := fmt.Fscanf(settings, "%f %f\n", &n.Pos.X, &n.Pos.Y) + if err != nil { + return nil + } + n.VoltageRange = r + n.VoltageOverTime = make([]float64, 1000) + for i := range n.VoltageOverTime { + n.VoltageOverTime[i] = 0 + } + n.renderChart() + return &n +} + +func (n *Node) renderChart() { + graph := chart.Chart{ + Width: 140, + Height: 60, + ColorPalette: &nodeColorPalette{}, + XAxis: chart.HideXAxis(), + YAxis: chart.YAxis{ + Style: chart.Hidden(), + Range: n.VoltageRange, + }, + Series: []chart.Series{ + chart.ContinuousSeries{ + XValues: chart.LinearRange(0, 999), + YValues: n.VoltageOverTime, + }, + }, + } + writer := &chart.ImageWriter{} + graph.Render(chart.PNG, writer) + img, _ := writer.Image() + n.Image = canvas.NewImageFromImage(img) +} + +type nodeColorPalette struct{} + +func (*nodeColorPalette) BackgroundColor() drawing.Color { + return drawing.ColorTransparent +} +func (*nodeColorPalette) BackgroundStrokeColor() drawing.Color { + return drawing.ColorTransparent +} +func (*nodeColorPalette) CanvasColor() drawing.Color { + return drawing.Color{R: 249, G: 254, B: 172, A: 128} +} +func (*nodeColorPalette) CanvasStrokeColor() drawing.Color { + return drawing.ColorTransparent +} +func (*nodeColorPalette) AxisStrokeColor() drawing.Color { + return drawing.ColorTransparent +} +func (*nodeColorPalette) TextColor() drawing.Color { + return drawing.ColorTransparent +} +func (*nodeColorPalette) GetSeriesColor(index int) drawing.Color { + return drawing.Color{R: 247, G: 239, B: 3, A: 255} +} + +func (n *Node) CreateRenderer() fyne.WidgetRenderer { return n } +func (n *Node) Layout(s fyne.Size) { + n.Image.Resize(s) + n.Image.Move(fyne.NewPos(0, 0)) +} +func (n *Node) MinSize() fyne.Size { return n.Image.MinSize() } +func (n *Node) Refresh() { n.renderChart() } +func (n *Node) Destroy() {} +func (n *Node) Objects() []fyne.CanvasObject { + return []fyne.CanvasObject{n.Image} +} diff --git a/cirsim/simulation.go b/cirsim/simulation.go new file mode 100644 index 0000000..ca0d841 --- /dev/null +++ b/cirsim/simulation.go @@ -0,0 +1,286 @@ +package cirsim + +import ( + "fmt" + "image/color" + "log" + "os" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/layout" + "fyne.io/fyne/v2/widget" + "github.com/wcharczuk/go-chart/v2" + "gonum.org/v1/gonum/mat" +) + +type Simulation struct { + Period float64 + Size fyne.Size + Nodes []*Node + Components []*Component + VoltageRange chart.ContinuousRange + CurrentRange chart.ContinuousRange + periodEntry *widget.Entry + voltageLabel *canvas.Text + currentLabel *canvas.Text +} + +func New() fyne.CanvasObject { + background := canvas.NewRectangle(color.White) + image := canvas.NewImageFromFile("circuit.svg") + file, err := os.Open("circuit") + if err != nil { + log.Fatal(err) + } + var sim Simulation + sim.Period = 0.01 + sim.VoltageRange = chart.ContinuousRange{Min: 0, Max: 0} + sim.CurrentRange = chart.ContinuousRange{Min: 0, Max: 0} + fmt.Fscanf(file, "%f %f\n\n", &sim.Size.Width, &sim.Size.Height) + sim.voltageLabel = canvas.NewText( + fmt.Sprintf(" %e < voltage < %e ", + sim.VoltageRange.Min, sim.VoltageRange.Max), + color.RGBA{R: 247, G: 239, B: 3, A: 255}, + ) + sim.voltageLabel.TextStyle.Monospace = true + sim.currentLabel = canvas.NewText( + fmt.Sprintf(" %e < current < %e ", + sim.CurrentRange.Min, sim.CurrentRange.Max), + color.RGBA{R: 3, G: 247, B: 198, A: 255}, + ) + sim.currentLabel.TextStyle.Monospace = true + periodLabel := widget.NewLabel("Period") + periodLabel.TextStyle.Monospace = true + sim.periodEntry = widget.NewEntry() + sim.periodEntry.TextStyle.Monospace = true + sim.periodEntry.SetPlaceHolder("default: 0.01s") + sim.periodEntry.OnSubmitted = sim.updatePeriod + c := container.New(&sim, + container.NewHBox( + sim.voltageLabel, + sim.currentLabel, + layout.NewSpacer(), + periodLabel, + container.New(&entryLayout{}, sim.periodEntry), + ), + background, + image, + ) + for n := NewNode(file, &sim.VoltageRange); n != nil; n = NewNode(file, &sim.VoltageRange) { + sim.Nodes = append(sim.Nodes, n) + c.Add(n) + } + for component := NewComponent(file, &sim.CurrentRange, sim.Nodes, sim.simulate); component != nil; component = NewComponent(file, &sim.CurrentRange, sim.Nodes, sim.simulate) { + sim.Components = append(sim.Components, component) + c.Add(component) + } + file.Close() + sim.simulate() + return c +} + +func (sim *Simulation) simulate() { + for _, n := range sim.Nodes { + for i := range n.VoltageOverTime { + n.VoltageOverTime[i] = 0 + } + } + for _, c := range sim.Components { + for i := range c.CurrentOverTime { + c.CurrentOverTime[i] = 0 + } + } + maxv := 0.0 + minv := 0.0 + maxc := 0.0 + minc := 0.0 + for i := 0; i != 1000; i++ { + N := len(sim.Nodes) + for refine := 0; refine != 10; refine++ { + m := mat.NewDense(N+1, N, nil) + v := mat.NewVecDense(N+1, nil) + for j, n := range sim.Nodes { + for _, c := range sim.Components { + if c.ANode == n { + v.SetVec(j, v.AtVec(j)-c.Model.ModelCurrent( + float64(i)*sim.Period/1000, sim.Period/1000, + c.BNode.VoltageOverTime[i]-n.VoltageOverTime[i], + c.CurrentOverTime[i])) + d := 0 + for k, v := range sim.Nodes { + if c.BNode == v { + d = k + break + } + } + m.Set(j, d, m.At(j, d)- + c.Model.ModelConductance( + float64(i)*sim.Period/1000, sim.Period/1000, + c.BNode.VoltageOverTime[i]-n.VoltageOverTime[i], + c.CurrentOverTime[i])) + m.Set(j, j, m.At(j, j)+ + c.Model.ModelConductance( + float64(i)*sim.Period/1000, sim.Period/1000, + c.BNode.VoltageOverTime[i]-n.VoltageOverTime[i], + c.CurrentOverTime[i])) + } else if c.BNode == n { + v.SetVec(j, v.AtVec(j)+c.Model.ModelCurrent( + float64(i)*sim.Period/1000, sim.Period/1000, + n.VoltageOverTime[i]-c.ANode.VoltageOverTime[i], + c.CurrentOverTime[i])) + d := 0 + for k, v := range sim.Nodes { + if c.ANode == v { + d = k + break + } + } + m.Set(j, d, m.At(j, d)- + c.Model.ModelConductance( + float64(i)*sim.Period/1000, sim.Period/1000, + n.VoltageOverTime[i]-c.ANode.VoltageOverTime[i], + c.CurrentOverTime[i])) + m.Set(j, j, m.At(j, j)+ + c.Model.ModelConductance( + float64(i)*sim.Period/1000, sim.Period/1000, + n.VoltageOverTime[i]-c.ANode.VoltageOverTime[i], + c.CurrentOverTime[i])) + } + } + } + r := make([]float64, N) + for j := 0; j != N-1; j++ { + r[j] = 0 + } + r[N-1] = 1 + m.SetRow(N, r) + v.SetVec(N, 0) + res := mat.NewVecDense(N, nil) + res.SolveVec(m, v) + for j, n := range sim.Nodes { + n.VoltageOverTime[i] = res.AtVec(j) + } + for _, c := range sim.Components { + c.CurrentOverTime[i] = (c.ANode.VoltageOverTime[i]-c.BNode.VoltageOverTime[i])* + c.Model.ModelConductance( + float64(i)*sim.Period/1000, sim.Period/1000, + c.BNode.VoltageOverTime[i]-c.ANode.VoltageOverTime[i], + c.CurrentOverTime[i]) + + c.Model.ModelCurrent( + float64(i)*sim.Period/1000, sim.Period/1000, + c.BNode.VoltageOverTime[i]-c.ANode.VoltageOverTime[i], + c.CurrentOverTime[i]) + } + } + if i == 999 { + break + } + for _, n := range sim.Nodes { + n.VoltageOverTime[i+1] = n.VoltageOverTime[i] + if n.VoltageOverTime[i] > maxv { + maxv = n.VoltageOverTime[i] + } else if n.VoltageOverTime[i] < minv { + minv = n.VoltageOverTime[i] + } + } + for _, c := range sim.Components { + c.CurrentOverTime[i+1] = c.CurrentOverTime[i] + if c.CurrentOverTime[i] > maxc { + maxc = c.CurrentOverTime[i] + } else if c.CurrentOverTime[i] < minc { + minc = c.CurrentOverTime[i] + } + } + } + sim.VoltageRange.Max = maxv + sim.VoltageRange.Min = minv + sim.CurrentRange.Max = maxc + sim.CurrentRange.Min = minc + sim.voltageLabel.Text = fmt.Sprintf(" %e < voltage < %e ", + sim.VoltageRange.Min, sim.VoltageRange.Max) + sim.currentLabel.Text = fmt.Sprintf(" %e < current < %e ", + sim.CurrentRange.Min, sim.CurrentRange.Max) + sim.voltageLabel.Refresh() + sim.currentLabel.Refresh() + for _, n := range sim.Nodes { + n.Refresh() + } + for _, c := range sim.Components { + c.Refresh() + } +} + +func (sim *Simulation) updatePeriod(period string) { + _, err := fmt.Sscanf(period+"\n", "%f\n", &sim.Period) + if err != nil { + sim.periodEntry.SetText(fmt.Sprintf("%f", sim.Period)) + } else { + sim.simulate() + } +} + +func (l *Simulation) MinSize(objects []fyne.CanvasObject) fyne.Size { + s := fyne.NewSize(0, 0) + for _, i := range objects { + switch o := i.(type) { + case *canvas.Image: + s = o.MinSize() + default: + } + } + return s +} + +func (l *Simulation) Layout(obs []fyne.CanvasObject, size fyne.Size) { + var p fyne.Position + var s fyne.Size + panel_height := obs[0].MinSize().Height + H := size.Height - panel_height + W := size.Width + h := l.Size.Height + w := l.Size.Width + var scale float32 + if H/W > h/w { + p = fyne.NewPos(0, (H-W*h/w)/2+panel_height) + s = fyne.NewSize(W, W*h/w) + scale = W / w + } else { + p = fyne.NewPos((W-H*w/h)/2, panel_height) + s = fyne.NewSize(H*w/h, H) + scale = H / h + } + obs[0].Resize(fyne.NewSize(W, panel_height)) + obs[0].Move(fyne.NewPos(0, 0)) + obs[1].Resize(size) + obs[1].Move(fyne.NewPos(0, panel_height)) + obs[2].Resize(s) + obs[2].Move(p) + for i, n := range l.Nodes { + obs[3+i].Resize(fyne.NewSize(140, 60)) + shift := fyne.NewPos(p.X+n.Pos.X*scale-70, p.Y+n.Pos.Y*scale-30) + obs[3+i].Move(shift) + } + for i, c := range l.Components { + ms := obs[3+len(l.Nodes)+i].MinSize() + obs[3+len(l.Nodes)+i].Resize(ms) + shift := fyne.NewPos(p.X+c.Pos.X*scale-70, p.Y+c.Pos.Y*scale-ms.Height+30) + obs[3+len(l.Nodes)+i].Move(shift) + } +} + +type entryLayout struct{} + +func (*entryLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { + return fyne.NewSize( + objects[0].MinSize().Width*4, + objects[0].MinSize().Height, + ) +} +func (*entryLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { + for _, o := range objects { + o.Resize(size) + o.Move(fyne.NewPos(0, 0)) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2249339 --- /dev/null +++ b/go.mod @@ -0,0 +1,30 @@ +module git.veresov.xyz/aversey/cirsim + +go 1.18 + +require ( + fyne.io/fyne/v2 v2.1.4 + github.com/wcharczuk/go-chart/v2 v2.1.0 + gonum.org/v1/gonum v0.11.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 // indirect + github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 // indirect + github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/goki/freetype v0.0.0-20220119013949-7a161fd3728c // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/srwiley/oksvg v0.0.0-20220128195007-1f435e4c2b44 // indirect + github.com/srwiley/rasterx v0.0.0-20220128185129-2efea2b9ea41 // indirect + github.com/stretchr/testify v1.7.1 // indirect + github.com/yuin/goldmark v1.4.11 // indirect + golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect + golang.org/x/net v0.0.0-20220412020605-290c469a71a5 // indirect + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect + golang.org/x/text v0.3.7 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..de78981 --- /dev/null +++ b/go.sum @@ -0,0 +1,113 @@ +fyne.io/fyne/v2 v2.1.4 h1:bt1+28++kAzRzPB0GM2EuSV4cnl8rXNX4cjfd8G06Rc= +fyne.io/fyne/v2 v2.1.4/go.mod h1:p+E/Dh+wPW8JwR2DVcsZ9iXgR9ZKde80+Y+40Is54AQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I= +github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 h1:FDqhDm7pcsLhhWl1QtD8vlzI4mm59llRvNzrFg6/LAA= +github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3/go.mod h1:CzM2G82Q9BDUvMTGHnXf/6OExw/Dz2ivDj48nVg7Lg8= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f/go.mod h1:wjpnOv6ONl2SuJSxqCPVaPZibGFdSci9HFocT9qtVYM= +github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 h1:zDw5v7qm4yH7N8C8uWd+8Ii9rROdgWxQuGoJ9WDXxfk= +github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211024062804-40e447a793be/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958 h1:TL70PMkdPCt9cRhKTqsm+giRpgrd0IGEj763nNr2VFY= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw= +github.com/goki/freetype v0.0.0-20220119013949-7a161fd3728c h1:JGCm/+tJ9gC6THUxooTldS+CUDsba0qvkvU3DHklqW8= +github.com/goki/freetype v0.0.0-20220119013949-7a161fd3728c/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc= +github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4= +github.com/srwiley/oksvg v0.0.0-20220128195007-1f435e4c2b44 h1:XPYXKIuH/n5zpUoEWk2jWV/SjEMNYmqDYmTgbjmhtaI= +github.com/srwiley/oksvg v0.0.0-20220128195007-1f435e4c2b44/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= +github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU= +github.com/srwiley/rasterx v0.0.0-20220128185129-2efea2b9ea41 h1:YR16ysw3I1bqwtEcYV9dpvhHEe7j55hIClkLoAqY31I= +github.com/srwiley/rasterx v0.0.0-20220128185129-2efea2b9ea41/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I= +github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.3.8/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.11 h1:i45YIzqLnUc2tGaTlJCyUxSG8TvgyGqhqOZOUKIjJ6w= +github.com/yuin/goldmark v1.4.11/go.mod h1:rmuwmfZ0+bvzB24eSC//bk1R1Zp3hM0OXYv/G2LIilg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3 h1:n9HxLrNxWWtEb1cA950nuEEj3QnKbtsCJ6KjcgisNUs= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 h1:LRtI4W37N+KFebI/qV0OFiLUv4GLOWeEW5hn/KEJvxE= +golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5 h1:bRb386wvrE+oBNdF1d/Xh9mQrfQ4ecYhW5qJ5GvTGT4= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..23474fa --- /dev/null +++ b/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/app" + "fyne.io/fyne/v2/theme" + "git.veresov.xyz/aversey/cirsim/cirsim" +) + +func main() { + a := app.New() + a.Settings().SetTheme(theme.LightTheme()) + w := a.NewWindow("Circuit Simulator") + w.Resize(fyne.NewSize(1280, 720)) + w.SetIcon(theme.SettingsIcon()) + w.SetContent(cirsim.New()) + w.ShowAndRun() +} -- cgit v1.2.3