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