vdobler / chart

Provide basic charts in go
BSD 3-Clause "New" or "Revised" License
771 stars 104 forks source link

BarChart wrong formatted bars #20

Open nekrondev opened 8 years ago

nekrondev commented 8 years ago

The following snippet will generate the attached wrong formatted bar chart. If more bars are used the formatting looks okay, so somehow the bar width and pos calculation for one or two datapoints is wrong. chart_issue

func IssueChart() error {
    wuc := chart.BarChart{Title: "Weekly Data Usage"}
    wuc.XRange.Category = []string{"W1", "W2"}
    wuc.XRange.Label, wuc.YRange.Label = "Calendar Week", "Data Transfer (MB)"
    wuc.Key.Pos, wuc.Key.Cols, wuc.Key.Border = "otc", 2, -1
    wuc.YRange.ShowZero = true
    wuc.ShowVal = 0
    pos := []float64{0, 1}
    rx := []float64{100.0, 150.0}
    tx := []float64{50.0, 200.0}
    wuc.AddDataPair("RX (Download)", pos, rx,
        chart.Style{Symbol: 'o', LineColor: color.NRGBA{69, 117, 179, 0xff}, LineWidth: 2, FillColor: color.NRGBA{79, 127, 189, 0xff}})
    wuc.AddDataPair("TX (Upload)", pos, tx,
        chart.Style{Symbol: 'o', LineColor: color.NRGBA{182, 70, 67, 0xff}, LineWidth: 2, FillColor: color.NRGBA{192, 80, 77, 0xff}})
    // Save image
    igr := imgg.New(1024, 640, color.RGBA{0xff, 0xff, 0xff, 0xff}, nil, nil)
    wuc.Plot(igr)
    fh, err := os.Create("chart_issue.jpg")
    if err != nil {
        return err
    }
    err = jpeg.Encode(fh, igr.Image, nil)
    return err
}
vdobler commented 8 years ago

This is unfortunate. It is the result of default autoscaling a categorical axis with bar charts. As a workaround you may fix the Min and Max of the x-axis manually like this:

wuc.XRange.Fixed(-0.5, 1.5, 1)

Of course you could fix it to the actual range covered by pos +- 0.5

Probably there is no sensible way to fix this automatically because:

Any automatic solution would have to be an ugly special case, probably with a heuristic when to trigger. Like: "For bar charts autoexpand range to cover full bar modulo Fixed and Constrained autoscaling and ignore Expansion in the RangeMode." This would work, I'll try it out but I'm afraid this new heuristic might break other existing code.