f32.go raw

   1  // SPDX-License-Identifier: Unlicense OR MIT
   2  
   3  /*
   4  Package f32 is a float32 implementation of package image's
   5  Point and Rectangle.
   6  
   7  The coordinate space has the origin in the top left
   8  corner with the axes extending right and down.
   9  */
  10  package f32
  11  
  12  import "strconv"
  13  
  14  // A Point is a two dimensional point.
  15  type Point struct {
  16  	X, Y float32
  17  }
  18  
  19  // String return a string representation of p.
  20  func (p Point) String() string {
  21  	return "(" + strconv.FormatFloat(float64(p.X), 'f', -1, 32) +
  22  		"," + strconv.FormatFloat(float64(p.Y), 'f', -1, 32) + ")"
  23  }
  24  
  25  // A Rectangle contains the points (X, Y) where Min.X <= X < Max.X,
  26  // Min.Y <= Y < Max.Y.
  27  type Rectangle struct {
  28  	Min, Max Point
  29  }
  30  
  31  // String return a string representation of r.
  32  func (r Rectangle) String() string {
  33  	return r.Min.String() + "-" + r.Max.String()
  34  }
  35  
  36  // Rect is a shorthand for Rectangle{Point{x0, y0}, Point{x1, y1}}.
  37  // The returned Rectangle has x0 and y0 swapped if necessary so that
  38  // it's correctly formed.
  39  func Rect(x0, y0, x1, y1 float32) Rectangle {
  40  	if x0 > x1 {
  41  		x0, x1 = x1, x0
  42  	}
  43  	if y0 > y1 {
  44  		y0, y1 = y1, y0
  45  	}
  46  	return Rectangle{Point{x0, y0}, Point{x1, y1}}
  47  }
  48  
  49  // Pt is shorthand for Point{X: x, Y: y}.
  50  func Pt(x, y float32) Point {
  51  	return Point{X: x, Y: y}
  52  }
  53  
  54  // Add return the point p+p2.
  55  func (p Point) Add(p2 Point) Point {
  56  	return Point{X: p.X + p2.X, Y: p.Y + p2.Y}
  57  }
  58  
  59  // Sub returns the vector p-p2.
  60  func (p Point) Sub(p2 Point) Point {
  61  	return Point{X: p.X - p2.X, Y: p.Y - p2.Y}
  62  }
  63  
  64  // Mul returns p scaled by s.
  65  func (p Point) Mul(s float32) Point {
  66  	return Point{X: p.X * s, Y: p.Y * s}
  67  }
  68  
  69  // In reports whether p is in r.
  70  func (p Point) In(r Rectangle) bool {
  71  	return r.Min.X <= p.X && p.X < r.Max.X &&
  72  		r.Min.Y <= p.Y && p.Y < r.Max.Y
  73  }
  74  
  75  // Size returns r's width and height.
  76  func (r Rectangle) Size() Point {
  77  	return Point{X: r.Dx(), Y: r.Dy()}
  78  }
  79  
  80  // Dx returns r's width.
  81  func (r Rectangle) Dx() float32 {
  82  	return r.Max.X - r.Min.X
  83  }
  84  
  85  // Dy returns r's Height.
  86  func (r Rectangle) Dy() float32 {
  87  	return r.Max.Y - r.Min.Y
  88  }
  89  
  90  // Intersect returns the intersection of r and s.
  91  func (r Rectangle) Intersect(s Rectangle) Rectangle {
  92  	if r.Min.X < s.Min.X {
  93  		r.Min.X = s.Min.X
  94  	}
  95  	if r.Min.Y < s.Min.Y {
  96  		r.Min.Y = s.Min.Y
  97  	}
  98  	if r.Max.X > s.Max.X {
  99  		r.Max.X = s.Max.X
 100  	}
 101  	if r.Max.Y > s.Max.Y {
 102  		r.Max.Y = s.Max.Y
 103  	}
 104  	return r
 105  }
 106  
 107  // Union returns the union of r and s.
 108  func (r Rectangle) Union(s Rectangle) Rectangle {
 109  	if r.Min.X > s.Min.X {
 110  		r.Min.X = s.Min.X
 111  	}
 112  	if r.Min.Y > s.Min.Y {
 113  		r.Min.Y = s.Min.Y
 114  	}
 115  	if r.Max.X < s.Max.X {
 116  		r.Max.X = s.Max.X
 117  	}
 118  	if r.Max.Y < s.Max.Y {
 119  		r.Max.Y = s.Max.Y
 120  	}
 121  	return r
 122  }
 123  
 124  // Canon returns the canonical version of r, where Min is to
 125  // the upper left of Max.
 126  func (r Rectangle) Canon() Rectangle {
 127  	if r.Max.X < r.Min.X {
 128  		r.Min.X, r.Max.X = r.Max.X, r.Min.X
 129  	}
 130  	if r.Max.Y < r.Min.Y {
 131  		r.Min.Y, r.Max.Y = r.Max.Y, r.Min.Y
 132  	}
 133  	return r
 134  }
 135  
 136  // Empty reports whether r represents the empty area.
 137  func (r Rectangle) Empty() bool {
 138  	return r.Min.X >= r.Max.X || r.Min.Y >= r.Max.Y
 139  }
 140  
 141  // Add offsets r with the vector p.
 142  func (r Rectangle) Add(p Point) Rectangle {
 143  	return Rectangle{
 144  		Point{r.Min.X + p.X, r.Min.Y + p.Y},
 145  		Point{r.Max.X + p.X, r.Max.Y + p.Y},
 146  	}
 147  }
 148  
 149  // Sub offsets r with the vector -p.
 150  func (r Rectangle) Sub(p Point) Rectangle {
 151  	return Rectangle{
 152  		Point{r.Min.X - p.X, r.Min.Y - p.Y},
 153  		Point{r.Max.X - p.X, r.Max.Y - p.Y},
 154  	}
 155  }
 156