Skip to content

plotter: Labels x/y-offsets are in vg.Length and it's inconvenient #710

@sbinet

Description

@sbinet

while working on the glyphboxes issue, I've noticed:

package plotter // import "gonum.org/v1/plot/plotter"

// Labels implements the Plotter interface,
// drawing a set of labels at specified points.
type Labels struct {
        XYs

        // Labels is the set of labels corresponding
        // to each point.
        Labels []string

        // TextStyle is the style of the label text. Each label
        // can have a different text style.
        TextStyle []text.Style

        // XOffset and YOffset are added directly to the final
        // label X and Y location respectively.
        XOffset, YOffset vg.Length
}

the {X,Y}Offset fields are in vg.Length (so, centimeters and what not).
it's convenient when drawing the labels:

// Plot implements the Plotter interface, drawing labels.
func (l *Labels) Plot(c draw.Canvas, p *plot.Plot) {
        trX, trY := p.Transforms(&c)
        for i, label := range l.Labels {
                pt := vg.Point{X: trX(l.XYs[i].X), Y: trY(l.XYs[i].Y)}
                if !c.Contains(pt) {
                        continue
                }
                pt.X += l.XOffset
                pt.Y += l.YOffset
                c.FillText(l.TextStyle[i], pt, label)
        }
}

but rather inconvenient when trying to compute the glyphbox around each label:

// GlyphBoxes returns a slice of GlyphBoxes,
// one for each of the labels, implementing the
// plot.GlyphBoxer interface.
func (l *Labels) GlyphBoxes(p *plot.Plot) []plot.GlyphBox {
        bs := make([]plot.GlyphBox, len(l.Labels))
        for i, label := range l.Labels {
                pt := l.XYs[i]
                pt.X += l.XOffset // error (cannot add float64 and vg.Length)
                pt.Y += l.YOffset // ditto
                bs[i].X = p.X.Norm(pt.X)
                bs[i].Y = p.Y.Norm(pt.Y)
                sty := l.TextStyle[i]
                bs[i].Rectangle = sty.Rectangle(label)
        }
        return bs
}

(the original code of Labels.GlyphBoxes(...) was missing the x/y-offsets)

there's no way (at least, I couldn't find one) to go from vg units back to "canvas/user" units.
(even less so when one has only a plot.Plot in hands, w/o the corresponding draw.Canvas as one has in Labels.Plot(c,p))

I see two avenues to solve this:

  • change {X,Y}Offset to data units (and document)
  • modify the GlyphBoxes signature (and the according plot.GlyphBoxer interface) to take an additional draw.Canvas argument, add a way (to plot.Plot?) to go from vg.Length units back to "data units".

option a) is probably less wide-ranging a change (only a couple of plotters in gonum/plot are using these fields)

(in any event, adding a method to go from vg.Length units back to "data units" may very well be quite convenient, though. I had the use for such a thing for go-hep/hplot here when trying to set labels in "normalized" coordinates.)

thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions