go-hep.org/x/hep@v0.38.1/hplot/figure.go (about) 1 // Copyright ©2020 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package hplot 6 7 import ( 8 "go-hep.org/x/hep/hplot/htex" 9 "gonum.org/v1/plot" 10 "gonum.org/v1/plot/vg" 11 "gonum.org/v1/plot/vg/draw" 12 "gonum.org/v1/plot/vg/vgimg" 13 ) 14 15 // Figure creates a new figure from a plot and options. 16 // Figure returns a value implementing the Drawer interface. 17 func Figure(p Drawer, opts ...FigOption) *Fig { 18 fig := &Fig{ 19 Plot: p, 20 Latex: htex.NoopHandler{}, 21 DPI: float64(vgimg.DefaultDPI), 22 } 23 for _, opt := range opts { 24 opt(fig) 25 } 26 return fig 27 } 28 29 // FigOption allows to customize the creation of figures. 30 type FigOption func(fig *Fig) 31 32 // Border specifies the borders' sizes, the space between the 33 // end of the plot image (PDF, PNG, ...) and the actual plot. 34 type Border struct { 35 Left vg.Length 36 Right vg.Length 37 Bottom vg.Length 38 Top vg.Length 39 } 40 41 // WithBorder allows to specify the borders' sizes, the space between the 42 // end of the plot image (PDF, PNG, ...) and the actual plot. 43 func WithBorder(b Border) FigOption { 44 return func(fig *Fig) { 45 fig.Border = b 46 } 47 } 48 49 // WithLatexHandler allows to enable the automatic generation of PDFs from .tex files. 50 // To enable the automatic generation of PDFs, use DefaultHandler: 51 // 52 // WithLatexHandler(htex.DefaultHandler) 53 func WithLatexHandler(h htex.Handler) FigOption { 54 return func(fig *Fig) { 55 fig.Latex = h 56 } 57 } 58 59 // WithDPI allows to modify the default DPI of a plot. 60 func WithDPI(dpi float64) FigOption { 61 return func(fig *Fig) { 62 fig.DPI = dpi 63 } 64 } 65 66 // WithLegend enables the display of a legend on the righthand-side of a plot. 67 func WithLegend(l Legend) FigOption { 68 return func(fig *Fig) { 69 leg := l 70 fig.Legend = &leg 71 } 72 } 73 74 // Fig is a figure, holding a plot and figure-level customizations. 75 type Fig struct { 76 // Plot is a gonum/plot.Plot like value. 77 Plot Drawer 78 79 // Legend displays a legend on the righthand-side of the plot. 80 Legend *Legend 81 82 // Border specifies the borders' sizes, the space between the 83 // end of the plot image (PDF, PNG, ...) and the actual plot. 84 Border Border 85 86 // Latex handles the generation of PDFs from .tex files. 87 // The default is to use htex.NoopHandler (a no-op). 88 // To enable the automatic generation of PDFs, use DefaultHandler: 89 // p := hplot.Wrap(plt) 90 // p.Latex = htex.DefaultHandler 91 Latex htex.Handler 92 93 // DPI is the dot-per-inch for PNG,JPEG,... plots. 94 DPI float64 95 } 96 97 func (fig *Fig) Draw(dc draw.Canvas) { 98 vgtexBorder(dc) 99 100 dc = draw.Crop(dc, 101 fig.Border.Left, -fig.Border.Right, 102 fig.Border.Bottom, -fig.Border.Top, 103 ) 104 105 if fig.Legend != nil { 106 var ( 107 r = fig.Legend.Rectangle(dc) 108 width = r.Max.X - r.Min.X 109 height vg.Length 110 ) 111 // adjust the legend down a little. 112 switch p := fig.Plot.(type) { 113 case *plot.Plot: 114 height = p.Title.TextStyle.FontExtents().Height 115 case *Plot: 116 height = p.Title.TextStyle.FontExtents().Height 117 } 118 fig.Legend.YOffs = -height 119 120 fig.Legend.Draw(dc) 121 122 // carve up space for the legend. 123 dc = draw.Crop(dc, 0, -width-vg.Millimeter, 0, 0) 124 } 125 126 fig.Plot.Draw(dc) 127 } 128 129 var ( 130 _ Drawer = (*Fig)(nil) 131 )