github.com/cybriq/giocore@v0.0.7-0.20210703034601-cfb9cb5f3900/f32/f32.go (about) 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 if r.Empty() { 105 return Rectangle{} 106 } 107 return r 108 } 109 110 // Union returns the union of r and s. 111 func (r Rectangle) Union(s Rectangle) Rectangle { 112 if r.Empty() { 113 return s 114 } 115 if s.Empty() { 116 return r 117 } 118 if r.Min.X > s.Min.X { 119 r.Min.X = s.Min.X 120 } 121 if r.Min.Y > s.Min.Y { 122 r.Min.Y = s.Min.Y 123 } 124 if r.Max.X < s.Max.X { 125 r.Max.X = s.Max.X 126 } 127 if r.Max.Y < s.Max.Y { 128 r.Max.Y = s.Max.Y 129 } 130 return r 131 } 132 133 // Canon returns the canonical version of r, where Min is to 134 // the upper left of Max. 135 func (r Rectangle) Canon() Rectangle { 136 if r.Max.X < r.Min.X { 137 r.Min.X, r.Max.X = r.Max.X, r.Min.X 138 } 139 if r.Max.Y < r.Min.Y { 140 r.Min.Y, r.Max.Y = r.Max.Y, r.Min.Y 141 } 142 return r 143 } 144 145 // Empty reports whether r represents the empty area. 146 func (r Rectangle) Empty() bool { 147 return r.Min.X >= r.Max.X || r.Min.Y >= r.Max.Y 148 } 149 150 // Add offsets r with the vector p. 151 func (r Rectangle) Add(p Point) Rectangle { 152 return Rectangle{ 153 Point{r.Min.X + p.X, r.Min.Y + p.Y}, 154 Point{r.Max.X + p.X, r.Max.Y + p.Y}, 155 } 156 } 157 158 // Sub offsets r with the vector -p. 159 func (r Rectangle) Sub(p Point) Rectangle { 160 return Rectangle{ 161 Point{r.Min.X - p.X, r.Min.Y - p.Y}, 162 Point{r.Max.X - p.X, r.Max.Y - p.Y}, 163 } 164 }