Fix some off-by-one errors in Y axis calculations
Y axis label printing stopped before the top line Sometimes large data values would land on the border or beyond the box fix typo
This commit is contained in:
parent
e74935dded
commit
562ca47996
71
linechart.go
71
linechart.go
@ -7,9 +7,7 @@ package termui
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
// only 16 possible combinations, why bother
|
||||
@ -38,39 +36,9 @@ var braillePatterns = map[[2]int]rune{
|
||||
var lSingleBraille = [4]rune{'\u2840', '⠄', '⠂', '⠁'}
|
||||
var rSingleBraille = [4]rune{'\u2880', '⠠', '⠐', '⠈'}
|
||||
|
||||
// set this filename to have debug logging written here
|
||||
var DebugFilename string
|
||||
var debugFile *os.File
|
||||
|
||||
func debugLog(str string) {
|
||||
if DebugFilename == "" {
|
||||
return
|
||||
}
|
||||
var err error
|
||||
if debugFile == nil {
|
||||
debugFile, err = os.OpenFile(DebugFilename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
stamp := time.Now().Format(time.StampMilli)
|
||||
_, err = fmt.Fprintln(debugFile, stamp, str)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Debug(a ...interface{}) {
|
||||
debugLog(fmt.Sprint(a))
|
||||
}
|
||||
|
||||
func Debugf(format string, a ...interface{}) {
|
||||
debugLog(fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// LineChart has two modes: braille(default) and dot. Using braille gives 2x capicity as dot mode,
|
||||
// because one braille char can represent two data points.
|
||||
// LineChart has two modes: braille(default) and dot.
|
||||
// A single braille character is a 2x4 grid of dots, so Using braille
|
||||
// gives 2x X resolution and 4x Y resolution over dot mode.
|
||||
/*
|
||||
lc := termui.NewLineChart()
|
||||
lc.Border.Label = "braille-mode Line Chart"
|
||||
@ -95,8 +63,8 @@ type LineChart struct {
|
||||
drawingY int
|
||||
axisYHeight int
|
||||
axisXWidth int
|
||||
axisYLebelGap int
|
||||
axisXLebelGap int
|
||||
axisYLabelGap int
|
||||
axisXLabelGap int
|
||||
topValue float64
|
||||
bottomValue float64
|
||||
labelX [][]rune
|
||||
@ -118,8 +86,8 @@ func NewLineChart() *LineChart {
|
||||
lc.DotStyle = '•'
|
||||
lc.Data = make(map[string][]float64)
|
||||
lc.LineColor = make(map[string]Attribute)
|
||||
lc.axisXLebelGap = 2
|
||||
lc.axisYLebelGap = 1
|
||||
lc.axisXLabelGap = 2
|
||||
lc.axisYLabelGap = 1
|
||||
lc.bottomValue = math.Inf(1)
|
||||
lc.topValue = math.Inf(-1)
|
||||
lc.YPadding = 0.2
|
||||
@ -222,7 +190,6 @@ func (lc *LineChart) renderDot() Buffer {
|
||||
minCell := lc.innerArea.Min.X + lc.labelYSpace
|
||||
cellPos := lc.innerArea.Max.X - 1
|
||||
for dataPos := len(seriesData) - 1; dataPos >= 0 && cellPos > minCell; {
|
||||
Debug(seriesName, " ", dataPos, cellPos, seriesData[dataPos])
|
||||
c := Cell{
|
||||
Ch: lc.DotStyle,
|
||||
Fg: thisLineColor,
|
||||
@ -254,7 +221,7 @@ func (lc *LineChart) calcLabelX() {
|
||||
if l+w <= lc.axisXWidth {
|
||||
lc.labelX = append(lc.labelX, s)
|
||||
}
|
||||
l += w + lc.axisXLebelGap
|
||||
l += w + lc.axisXLabelGap
|
||||
} else { // braille
|
||||
if 2*l >= len(lc.DataLabels) {
|
||||
break
|
||||
@ -265,7 +232,7 @@ func (lc *LineChart) calcLabelX() {
|
||||
if l+w <= lc.axisXWidth {
|
||||
lc.labelX = append(lc.labelX, s)
|
||||
}
|
||||
l += w + lc.axisXLebelGap
|
||||
l += w + lc.axisXLabelGap
|
||||
|
||||
}
|
||||
}
|
||||
@ -285,9 +252,10 @@ func shortenFloatVal(x float64) string {
|
||||
|
||||
func (lc *LineChart) calcLabelY() {
|
||||
span := lc.topValue - lc.bottomValue
|
||||
lc.scale = span / float64(lc.axisYHeight)
|
||||
// where does -2 come from? Without it, we might draw on the top border or past the block
|
||||
lc.scale = span / float64(lc.axisYHeight-2)
|
||||
|
||||
n := (1 + lc.axisYHeight) / (lc.axisYLebelGap + 1)
|
||||
n := (1 + lc.axisYHeight) / (lc.axisYLabelGap + 1)
|
||||
lc.labelY = make([][]rune, n)
|
||||
maxLen := 0
|
||||
for i := 0; i < n; i++ {
|
||||
@ -354,7 +322,7 @@ func (lc *LineChart) calcLayout() {
|
||||
}
|
||||
}
|
||||
|
||||
lc.axisYHeight = lc.innerArea.Dy() - 2
|
||||
lc.axisYHeight = lc.innerArea.Dy() - 1
|
||||
lc.calcLabelY()
|
||||
|
||||
lc.axisXWidth = lc.innerArea.Dx() - 1 - lc.labelYSpace
|
||||
@ -362,8 +330,6 @@ func (lc *LineChart) calcLayout() {
|
||||
|
||||
lc.drawingX = lc.innerArea.Min.X + 1 + lc.labelYSpace
|
||||
lc.drawingY = lc.innerArea.Min.Y
|
||||
|
||||
Debugf("calcLayout bottom=%f top=%f min=%f max=%f axisYHeight=%d", lc.bottomValue, lc.topValue, lc.minY, lc.maxY, lc.axisYHeight)
|
||||
}
|
||||
|
||||
func (lc *LineChart) plotAxes() Buffer {
|
||||
@ -378,8 +344,8 @@ func (lc *LineChart) plotAxes() Buffer {
|
||||
buf.Set(x, origY, Cell{Ch: HDASH, Fg: lc.AxesColor, Bg: lc.Bg})
|
||||
}
|
||||
|
||||
for dy := 1; dy <= lc.axisYHeight; dy++ {
|
||||
buf.Set(origX, origY-dy, Cell{Ch: VDASH, Fg: lc.AxesColor, Bg: lc.Bg})
|
||||
for y := origY - 1; y > origY-lc.axisYHeight; y-- {
|
||||
buf.Set(origX, y, Cell{Ch: VDASH, Fg: lc.AxesColor, Bg: lc.Bg})
|
||||
}
|
||||
|
||||
// x label
|
||||
@ -398,7 +364,7 @@ func (lc *LineChart) plotAxes() Buffer {
|
||||
y := lc.innerArea.Min.Y + lc.innerArea.Dy() - 1
|
||||
buf.Set(x, y, c)
|
||||
}
|
||||
oft += len(rs) + lc.axisXLebelGap
|
||||
oft += len(rs) + lc.axisXLabelGap
|
||||
}
|
||||
|
||||
// y labels
|
||||
@ -406,7 +372,7 @@ func (lc *LineChart) plotAxes() Buffer {
|
||||
for j, r := range rs {
|
||||
buf.Set(
|
||||
lc.innerArea.Min.X+j,
|
||||
origY-i*(lc.axisYLebelGap+1),
|
||||
origY-i*(lc.axisYLabelGap+1),
|
||||
Cell{Ch: r, Fg: lc.AxesColor, Bg: lc.Bg})
|
||||
}
|
||||
}
|
||||
@ -425,17 +391,14 @@ func (lc *LineChart) Buffer() Buffer {
|
||||
}
|
||||
}
|
||||
if seriesCount == 0 {
|
||||
Debug("lc render no data")
|
||||
return buf
|
||||
}
|
||||
lc.calcLayout()
|
||||
buf.Merge(lc.plotAxes())
|
||||
|
||||
if lc.Mode == "dot" {
|
||||
Debug("lc render start dot")
|
||||
buf.Merge(lc.renderDot())
|
||||
} else {
|
||||
Debug("lc render start braille")
|
||||
buf.Merge(lc.renderBraille())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user