Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support alignment translation of axis #30

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ type Range struct {
InvNorm func(float64) float64 // Inverse of Norm()
Data2Screen func(float64) int // Function to map data value to screen position
Screen2Data func(int) float64 // Inverse of Data2Screen

AlignTrans bool // alignment translation of the axis: false: axis location left/bottom, true: axis location right/top
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AlignTrans is not a clear name. I would prefer something like SwitchSide or AlternateSide or something else but it is not just a translation, and not really an alignment.

For the comment: Start with a capital letter.

Maybe

SwitchSide bool // Switch location of axis to top / right if true.

}

// Fixed is a helper (just reduces typing) functions which turns of autoscaling
Expand Down Expand Up @@ -674,8 +676,12 @@ type LayoutData struct {
NumXtics, NumYtics int // suggested numer of tics for both axis
}

// Layout graph data area on screen and place key.
func layout(g Graphics, title, xlabel, ylabel string, hidextics, hideytics bool, key *Key) (ld LayoutData) {
return layoutWithAlign(g, title, xlabel, ylabel, hidextics, hideytics, key, false, false)
}

// Layout graph data area on screen and place key.
func layoutWithAlign(g Graphics, title, xlabel, ylabel string, hidextics, hideytics bool, key *Key, xalign bool, yalign bool) (ld LayoutData) {
fw, fh, _ := g.FontMetrics(Font{})
w, h := g.Dimensions()

Expand All @@ -684,6 +690,9 @@ func layout(g Graphics, title, xlabel, ylabel string, hidextics, hideytics bool,
}

width, leftm, height, topm := w-int(6*fw), int(2*fw), h-2*fh, fh
if yalign {
leftm = int(4 * fw)
}
xlabsep, ylabsep := fh, int(3*fw)
if title != "" {
topm += (5 * fh) / 2
Expand All @@ -697,11 +706,15 @@ func layout(g Graphics, title, xlabel, ylabel string, hidextics, hideytics bool,
xlabsep += (3 * fh) / 2
}
if ylabel != "" {
leftm += 2 * fh
if !yalign {
leftm += 2 * fh
}
width -= 2 * fh
}
if !hideytics {
leftm += int(6 * fw)
if !yalign {
leftm += int(6 * fw)
}
width -= int(6 * fw)
ylabsep += int(6 * fw)
}
Expand Down
Binary file modified example/bestof.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions example/samplecharts.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ func scatterChart() {
pl.XRange.TicSetting.Grid = 1
pl.XRange.Label = "X-Range"
pl.YRange.Label = "Y-Range"
pl.YRange.AlignTrans = true
pl.Key.Cols = 2
pl.Key.Pos = "orb"

Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGw
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/llgcode/draw2d v0.0.0-20180825133448-f52c8a71aff0 h1:2vp6ESimuT8pCuZHThVyV0hlfa9oPL06HnGCL9pbUgc=
github.com/llgcode/draw2d v0.0.0-20180825133448-f52c8a71aff0/go.mod h1:mVa0dA29Db2S4LVqDYLlsePDzRJLDfdhVZiI15uY0FA=
github.com/llgcode/ps v0.0.0-20150911083025-f1443b32eedb h1:61ndUreYSlWFeCY44JxDDkngVoI7/1MVhEl98Nm0KOk=
github.com/llgcode/ps v0.0.0-20150911083025-f1443b32eedb/go.mod h1:1l8ky+Ew27CMX29uG+a2hNOKpeNYEQjjtiALiBlFQbY=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20181030002151-69cc3646b96e h1:LpHV5J9Rec5OYn+RZFfNenrW109yUVSoKjGOgmKKhxE=
Expand Down
62 changes: 49 additions & 13 deletions graphics.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,37 +278,63 @@ func drawYTics(bg BasicGraphics, rng Range, x, xm, ticLen int, options PlotOptio
y := rng.Data2Screen(tic.Pos)
ly := rng.Data2Screen(tic.LabelPos)

ox := x
oxm := xm
if rng.AlignTrans {
ox = xm // origin to right
oxm = x // mirror to right
}
// Tics
switch rng.TicSetting.Tics {
case 0:
bg.Line(x-ticLen, y, x+ticLen, y, ticstyle)
bg.Line(ox-ticLen, y, ox+ticLen, y, ticstyle)
case 1:
bg.Line(x, y, x+ticLen, y, ticstyle)
if rng.AlignTrans {
bg.Line(ox, y, ox-ticLen, y, ticstyle)
} else {
bg.Line(ox, y, ox+ticLen, y, ticstyle)
}
case 2:
bg.Line(x-ticLen, y, x, y, ticstyle)
if rng.AlignTrans {
bg.Line(ox+ticLen, y, ox, y, ticstyle)
} else {
bg.Line(ox-ticLen, y, ox, y, ticstyle)
}
default:
}

// Mirrored tics
if rng.TicSetting.Mirror >= 2 {
switch rng.TicSetting.Tics {
case 0:
bg.Line(xm-ticLen, y, xm+ticLen, y, ticstyle)
bg.Line(oxm-ticLen, y, oxm+ticLen, y, ticstyle)
case 1:
bg.Line(xm-ticLen, y, xm, y, ticstyle)
if rng.AlignTrans {
bg.Line(oxm+ticLen, y, oxm, y, ticstyle)
} else {
bg.Line(oxm-ticLen, y, oxm, y, ticstyle)
}
case 2:
bg.Line(xm, y, xm+ticLen, y, ticstyle)
if rng.AlignTrans {
bg.Line(oxm, y, oxm-ticLen, y, ticstyle)
} else {
bg.Line(oxm, y, oxm+ticLen, y, ticstyle)
}
default:
}
}

if !rng.TicSetting.HideLabels {
// Label
if rng.Time && tic.Align == 0 { // centered tic
bg.Line(x-2*ticLen, y, x+ticLen, y, ticstyle)
bg.Text(x-ticLen, ly, tic.Label, "cr", 0, ticfont)
bg.Line(ox-2*ticLen, y, ox+ticLen, y, ticstyle)
bg.Text(ox-ticLen, ly, tic.Label, "cr", 0, ticfont)
} else {
bg.Text(x-2*ticLen, ly, tic.Label, "cr", 0, ticfont)
if rng.AlignTrans {
bg.Text(ox+2*ticLen, ly, tic.Label, "cl", 0, ticfont)
} else {
bg.Text(ox-2*ticLen, ly, tic.Label, "cr", 0, ticfont)
}
}
}
}
Expand All @@ -319,7 +345,7 @@ func drawYTics(bg BasicGraphics, rng Range, x, xm, ticLen int, options PlotOptio
// The y.axis and the mirrord y-axis are drawn at x and ym respectively.
func GenericYAxis(bg BasicGraphics, rng Range, x, xm int, options PlotOptions) {
font := elementStyle(options, MajorAxisElement).Font
_, fontheight, _ := bg.FontMetrics(font)
fw, fontheight, _ := bg.FontMetrics(font)
var ticLen int = 0
if !rng.TicSetting.Hide {
ticLen = imin(10, imax(4, fontheight/2))
Expand All @@ -342,17 +368,27 @@ func GenericYAxis(bg BasicGraphics, rng Range, x, xm int, options PlotOptions) {
}
if rng.Label != "" {
y := (ya + ye) / 2
bg.Text(alx, y, rng.Label, "bc", 90, font)
if rng.AlignTrans {
bg.Text(xm+alx+int(6*fw), y, rng.Label, "bc", 90, font)
} else {
bg.Text(alx, y, rng.Label, "bc", 90, font)
}
}

if !rng.TicSetting.Hide {
drawYTics(bg, rng, x, xm, ticLen, options)
}

// Axis itself, mirrord axis and zero
bg.Line(x, ya, x, ye, elementStyle(options, MajorAxisElement))
ox := x
oxm := xm
if rng.AlignTrans {
ox = xm
oxm = x
}
bg.Line(ox, ya, ox, ye, elementStyle(options, MajorAxisElement))
if rng.TicSetting.Mirror >= 1 {
bg.Line(xm, ya, xm, ye, elementStyle(options, MinorAxisElement))
bg.Line(oxm, ya, oxm, ye, elementStyle(options, MinorAxisElement))
}
if rng.ShowZero && rng.Min < 0 && rng.Max > 0 {
z := rng.Data2Screen(0)
Expand Down
4 changes: 2 additions & 2 deletions scatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ func (c *ScatterChart) Reset() {

// Plot outputs the scatter chart to the graphic output g.
func (c *ScatterChart) Plot(g Graphics) {
layout := layout(g, c.Title, c.XRange.Label, c.YRange.Label,
layout := layoutWithAlign(g, c.Title, c.XRange.Label, c.YRange.Label,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is scatterplot the only one which calls layoutWithAlign?

c.XRange.TicSetting.Hide || c.XRange.TicSetting.HideLabels,
c.YRange.TicSetting.Hide || c.YRange.TicSetting.HideLabels,
&c.Key)
&c.Key, c.XRange.AlignTrans, c.YRange.AlignTrans)

width, height := layout.Width, layout.Height
topm, leftm := layout.Top, layout.Left
Expand Down