• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlange-42 / ark-pixel / 13728789674

07 Mar 2025 08:31PM CUT coverage: 89.367% (+61.3%) from 28.089%
13728789674

push

github

web-flow
Re-activate unit tests (#9)

1454 of 1627 relevant lines covered (89.37%)

222405.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.49
/plot/contour.go
1
package plot
2

3
import (
4
        "fmt"
5
        "image/color"
6

7
        pixel "github.com/gopxl/pixel/v2"
8
        "github.com/gopxl/pixel/v2/backends/opengl"
9
        "github.com/mlange-42/ark-tools/observer"
10
        "github.com/mlange-42/ark/ecs"
11
        "gonum.org/v1/plot"
12
        "gonum.org/v1/plot/palette"
13
        "gonum.org/v1/plot/plotter"
14
        "gonum.org/v1/plot/vg"
15
        "gonum.org/v1/plot/vg/draw"
16
        "gonum.org/v1/plot/vg/vgimg"
17
)
18

19
// Contour plot drawer.
20
//
21
// Plots a grid as a contours.
22
// For large grids, this is relatively slow.
23
// Consider using [Image] instead.
24
type Contour struct {
25
        Observer   observer.Grid   // Observers providing a Grid for contours.
26
        Levels     []float64       // Levels for iso lines. Optional.
27
        Palette    palette.Palette // Color palette. Optional.
28
        Labels     Labels          // Labels for plot and axes. Optional.
29
        HideLegend bool            // Hides the legend.
30

31
        data  plotGrid
32
        scale float64
33
}
34

35
// Initialize the drawer.
36
func (c *Contour) Initialize(w *ecs.World, win *opengl.Window) {
2✔
37
        c.Observer.Initialize(w)
2✔
38
        c.data = plotGrid{
2✔
39
                Grid: c.Observer,
2✔
40
        }
2✔
41
        c.scale = calcScaleCorrection()
2✔
42
}
2✔
43

44
// Update the drawer.
45
func (c *Contour) Update(w *ecs.World) {
200✔
46
        c.Observer.Update(w)
200✔
47
}
200✔
48

49
// UpdateInputs handles input events of the previous frame update.
50
func (c *Contour) UpdateInputs(w *ecs.World, win *opengl.Window) {}
200✔
51

52
// Draw the drawer.
53
func (c *Contour) Draw(w *ecs.World, win *opengl.Window) {
200✔
54
        width := win.Canvas().Bounds().W()
200✔
55
        height := win.Canvas().Bounds().H()
200✔
56

200✔
57
        c.updateData(w)
200✔
58

200✔
59
        canvas := vgimg.New(vg.Points(width*c.scale)-10, vg.Points(height*c.scale)-10)
200✔
60

200✔
61
        p := plot.New()
200✔
62
        setLabels(p, c.Labels)
200✔
63

200✔
64
        p.X.Tick.Marker = removeLastTicks{}
200✔
65

200✔
66
        cols := c.Palette.Colors()
200✔
67
        min := 0.0
200✔
68
        max := 1.0
200✔
69
        if len(c.Levels) > 0 {
399✔
70
                min = c.Levels[0]
199✔
71
                max = c.Levels[len(c.Levels)-1]
199✔
72
        } else {
200✔
73
                c.Levels = []float64{0.01, 0.05, 0.25, 0.5, 0.75, 0.95, 0.99}
1✔
74
        }
1✔
75

76
        contours := plotter.Contour{
200✔
77
                GridXYZ:    &c.data,
200✔
78
                Levels:     c.Levels,
200✔
79
                LineStyles: []draw.LineStyle{plotter.DefaultLineStyle},
200✔
80
                Palette:    c.Palette,
200✔
81
                Underflow:  cols[0],
200✔
82
                Overflow:   cols[len(cols)-1],
200✔
83
                Min:        min,
200✔
84
                Max:        max,
200✔
85
        }
200✔
86

200✔
87
        if !c.HideLegend {
400✔
88
                p.Legend = plot.NewLegend()
200✔
89
                p.Legend.TextStyle.Font.Variant = "Mono"
200✔
90
                c.populateLegend(&p.Legend, &contours)
200✔
91
        }
200✔
92

93
        p.Add(&contours)
200✔
94

200✔
95
        win.Clear(color.White)
200✔
96
        p.Draw(draw.New(canvas))
200✔
97

200✔
98
        img := canvas.Image()
200✔
99
        picture := pixel.PictureDataFromImage(img)
200✔
100

200✔
101
        sprite := pixel.NewSprite(picture, picture.Bounds())
200✔
102
        sprite.Draw(win, pixel.IM.Moved(pixel.V(picture.Rect.W()/2.0+5, picture.Rect.H()/2.0+5)))
200✔
103
}
104

105
func (c *Contour) updateData(w *ecs.World) {
200✔
106
        c.data.Values = c.Observer.Values(w)
200✔
107
}
200✔
108

109
func (c *Contour) populateLegend(legend *plot.Legend, contours *plotter.Contour) {
200✔
110
        var pal []color.Color
200✔
111
        if c.Palette != nil {
400✔
112
                pal = c.Palette.Colors()
200✔
113
        }
200✔
114
        ps := float64(len(pal)-1) / (c.Levels[len(c.Levels)-1] - c.Levels[0])
200✔
115
        if len(c.Levels) == 1 {
200✔
116
                ps = 0
×
117
        }
×
118
        for i := len(c.Levels) - 1; i >= 0; i-- {
1,800✔
119
                z := c.Levels[i]
1,600✔
120
                var col color.Color
1,600✔
121
                switch {
1,600✔
122
                case z < contours.Min:
×
123
                        col = contours.Underflow
×
124
                case z > contours.Max:
×
125
                        col = contours.Overflow
×
126
                case len(pal) == 0:
×
127
                        col = contours.Underflow
×
128
                default:
1,600✔
129
                        col = pal[int((z-c.Levels[0])*ps+0.5)] // Apply palette scaling.
1,600✔
130
                }
131
                legend.Add(fmt.Sprintf("%f", z), colorThumbnailer{col})
1,600✔
132
        }
133
}
134

135
// colorThumbnailer implements the Thumbnailer interface.
136
type colorThumbnailer struct {
137
        color color.Color
138
}
139

140
// Thumbnail satisfies the plot.Thumbnailer interface.
141
func (t colorThumbnailer) Thumbnail(c *draw.Canvas) {
1,600✔
142
        pts := []vg.Point{
1,600✔
143
                {X: c.Min.X, Y: c.Min.Y},
1,600✔
144
                {X: c.Min.X, Y: c.Max.Y},
1,600✔
145
                {X: c.Max.X, Y: c.Max.Y},
1,600✔
146
                {X: c.Max.X, Y: c.Min.Y},
1,600✔
147
        }
1,600✔
148
        poly := c.ClipPolygonY(pts)
1,600✔
149
        c.FillPolygon(t.color, poly)
1,600✔
150
}
1,600✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc