go-hep.org/x/hep@v0.38.1/hplot/line.go (about)

     1  // Copyright ©2019 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  	"image/color"
     9  	"math"
    10  
    11  	"gonum.org/v1/plot"
    12  	"gonum.org/v1/plot/plotter"
    13  	"gonum.org/v1/plot/vg"
    14  	"gonum.org/v1/plot/vg/draw"
    15  )
    16  
    17  // VertLine draws a vertical line at X and colors the
    18  // left and right portions of the plot with the provided
    19  // colors.
    20  type VertLine struct {
    21  	X     float64
    22  	Line  draw.LineStyle
    23  	Left  color.Color
    24  	Right color.Color
    25  }
    26  
    27  // VLine creates a vertical line at x with the default line style.
    28  func VLine(x float64, left, right color.Color) *VertLine {
    29  	return &VertLine{
    30  		X:     x,
    31  		Line:  plotter.DefaultLineStyle,
    32  		Left:  left,
    33  		Right: right,
    34  	}
    35  }
    36  
    37  func (vline *VertLine) Plot(c draw.Canvas, plt *plot.Plot) {
    38  	var (
    39  		trX, _ = plt.Transforms(&c)
    40  		x      = trX(vline.X)
    41  		xmin   = c.Min.X
    42  		xmax   = c.Max.X
    43  		ymin   = c.Min.Y
    44  		ymax   = c.Max.Y
    45  	)
    46  
    47  	if vline.Left != nil && x > xmin {
    48  		c.SetColor(vline.Left)
    49  		rect := vg.Rectangle{
    50  			Min: vg.Point{X: xmin, Y: ymin},
    51  			Max: vg.Point{X: x, Y: ymax},
    52  		}
    53  		c.Fill(rect.Path())
    54  	}
    55  	if vline.Right != nil && x < xmax {
    56  		c.SetColor(vline.Right)
    57  		rect := vg.Rectangle{
    58  			Min: vg.Point{X: x, Y: ymin},
    59  			Max: vg.Point{X: xmax, Y: ymax},
    60  		}
    61  		c.Fill(rect.Path())
    62  	}
    63  
    64  	if vline.Line.Width != 0 && xmin <= x && x <= xmax {
    65  		c.StrokeLine2(vline.Line, x, ymin, x, ymax)
    66  	}
    67  }
    68  
    69  // Thumbnail returns the thumbnail for the VertLine,
    70  // implementing the plot.Thumbnailer interface.
    71  func (vline *VertLine) Thumbnail(c *draw.Canvas) {
    72  	if vline.Left != nil {
    73  		minX := c.Min.X
    74  		maxX := c.Center().X
    75  		minY := c.Min.Y
    76  		maxY := c.Max.Y
    77  		points := []vg.Point{
    78  			{X: minX, Y: minY},
    79  			{X: minX, Y: maxY},
    80  			{X: maxX, Y: maxY},
    81  			{X: maxX, Y: minY},
    82  		}
    83  		poly := c.ClipPolygonY(points)
    84  		c.FillPolygon(vline.Left, poly)
    85  	}
    86  
    87  	if vline.Right != nil {
    88  		minX := c.Center().X
    89  		maxX := c.Max.X
    90  		minY := c.Min.Y
    91  		maxY := c.Max.Y
    92  		points := []vg.Point{
    93  			{X: minX, Y: minY},
    94  			{X: minX, Y: maxY},
    95  			{X: maxX, Y: maxY},
    96  			{X: maxX, Y: minY},
    97  		}
    98  		poly := c.ClipPolygonY(points)
    99  		c.FillPolygon(vline.Right, poly)
   100  	}
   101  
   102  	if vline.Line.Width != 0 {
   103  		x := c.Center().X
   104  		c.StrokeLine2(vline.Line, x, c.Min.Y, x, c.Max.Y)
   105  	}
   106  }
   107  
   108  // DataRange returns the range of X and Y values.
   109  func (vline *VertLine) DataRange() (xmin, xmax, ymin, ymax float64) {
   110  	xmin = vline.X
   111  	xmax = vline.X
   112  	ymin = math.Inf(+1)
   113  	ymax = math.Inf(-1)
   114  	return
   115  }
   116  
   117  // HorizLine draws a horizontal line at Y and colors the
   118  // top and bottom portions of the plot with the provided
   119  // colors.
   120  type HorizLine struct {
   121  	Y      float64
   122  	Line   draw.LineStyle
   123  	Top    color.Color
   124  	Bottom color.Color
   125  }
   126  
   127  // HLine creates a horizontal line at y with the default line style.
   128  func HLine(y float64, top, bottom color.Color) *HorizLine {
   129  	return &HorizLine{
   130  		Y:      y,
   131  		Line:   plotter.DefaultLineStyle,
   132  		Top:    top,
   133  		Bottom: bottom,
   134  	}
   135  }
   136  
   137  func (hline *HorizLine) Plot(c draw.Canvas, plt *plot.Plot) {
   138  	var (
   139  		_, trY = plt.Transforms(&c)
   140  		y      = trY(hline.Y)
   141  		xmin   = c.Min.X
   142  		xmax   = c.Max.X
   143  		ymin   = c.Min.Y
   144  		ymax   = c.Max.Y
   145  	)
   146  
   147  	if hline.Top != nil && y < ymax {
   148  		c.SetColor(hline.Top)
   149  		rect := vg.Rectangle{
   150  			Min: vg.Point{X: xmin, Y: y},
   151  			Max: vg.Point{X: xmax, Y: ymax},
   152  		}
   153  		c.Fill(rect.Path())
   154  	}
   155  	if hline.Bottom != nil && y > ymin {
   156  		c.SetColor(hline.Bottom)
   157  		rect := vg.Rectangle{
   158  			Min: vg.Point{X: xmin, Y: ymin},
   159  			Max: vg.Point{X: xmax, Y: y},
   160  		}
   161  		c.Fill(rect.Path())
   162  	}
   163  
   164  	if hline.Line.Width != 0 && ymin <= y && y <= ymax {
   165  		c.StrokeLine2(hline.Line, xmin, y, xmax, y)
   166  	}
   167  }
   168  
   169  // Thumbnail returns the thumbnail for the VertLine,
   170  // implementing the plot.Thumbnailer interface.
   171  func (hline *HorizLine) Thumbnail(c *draw.Canvas) {
   172  	if hline.Top != nil {
   173  		minX := c.Min.X
   174  		maxX := c.Max.X
   175  		minY := c.Center().Y
   176  		maxY := c.Max.Y
   177  		points := []vg.Point{
   178  			{X: minX, Y: minY},
   179  			{X: minX, Y: maxY},
   180  			{X: maxX, Y: maxY},
   181  			{X: maxX, Y: minY},
   182  		}
   183  		poly := c.ClipPolygonY(points)
   184  		c.FillPolygon(hline.Top, poly)
   185  	}
   186  
   187  	if hline.Bottom != nil {
   188  		minX := c.Min.X
   189  		maxX := c.Max.X
   190  		minY := c.Min.Y
   191  		maxY := c.Center().Y
   192  		points := []vg.Point{
   193  			{X: minX, Y: minY},
   194  			{X: minX, Y: maxY},
   195  			{X: maxX, Y: maxY},
   196  			{X: maxX, Y: minY},
   197  		}
   198  		poly := c.ClipPolygonY(points)
   199  		c.FillPolygon(hline.Bottom, poly)
   200  	}
   201  
   202  	if hline.Line.Width != 0 {
   203  		y := c.Center().Y
   204  		c.StrokeLine2(hline.Line, c.Min.X, y, c.Max.X, y)
   205  	}
   206  }
   207  
   208  // DataRange returns the range of X and Y values.
   209  func (hline *HorizLine) DataRange() (xmin, xmax, ymin, ymax float64) {
   210  	xmin = math.Inf(+1)
   211  	xmax = math.Inf(-1)
   212  	ymin = hline.Y
   213  	ymax = hline.Y
   214  	return
   215  }
   216  
   217  var (
   218  	_ plot.Plotter = (*VertLine)(nil)
   219  	_ plot.Plotter = (*HorizLine)(nil)
   220  
   221  	_ plot.DataRanger = (*VertLine)(nil)
   222  	_ plot.DataRanger = (*HorizLine)(nil)
   223  
   224  	_ plot.Thumbnailer = (*VertLine)(nil)
   225  	_ plot.Thumbnailer = (*HorizLine)(nil)
   226  )