Skip to content

Commit 24f80ee

Browse files
committed
Init Polygon and RegularPolygon
1 parent 2e9abaa commit 24f80ee

File tree

3 files changed

+135
-12
lines changed

3 files changed

+135
-12
lines changed

polygon.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package geom
2+
3+
// Polygon is a 2D polygon with 3+ transform.
4+
type Polygon[T Number] struct {
5+
Vertices []Point[T]
6+
}
7+
8+
// Center returns the polygon centroid computed as the average of its transform.
9+
func (p Polygon[T]) Center() Point[T] {
10+
var x, y T
11+
l := T(len(p.Vertices))
12+
for _, v := range p.Vertices {
13+
x, y = x+v.X, y+v.Y
14+
}
15+
16+
return Point[T]{x / l, y / l}
17+
}
18+
19+
// Translate creates a new Polygon translated by the given vector (applied to all transform).
20+
func (p Polygon[T]) Translate(vector Vector[T]) Polygon[T] {
21+
return Polygon[T]{transform(p.Vertices, func(e Point[T]) Point[T] {
22+
return e.Add(vector)
23+
})}
24+
}
25+
26+
// MoveTo creates a new Polygon whose centroid is moved to point, preserving shape.
27+
func (p Polygon[T]) MoveTo(point Point[T]) Polygon[T] {
28+
return p.Translate(point.Subtract(p.Center()))
29+
}
30+
31+
// Scale creates a new Polygon uniformly scaled about its centroid by the factor.
32+
func (p Polygon[T]) Scale(scale float64) Polygon[T] {
33+
center := p.Center()
34+
return Polygon[T]{transform(p.Vertices, func(point Point[T]) Point[T] {
35+
return center.Add(point.Subtract(center).Multiply(scale))
36+
})}
37+
}
38+
39+
// ScaleXY creates a new Polygon scaled about its centroid by the factors.
40+
func (p Polygon[T]) ScaleXY(scaleX, scaleY float64) Polygon[T] {
41+
center := p.Center()
42+
return Polygon[T]{transform(p.Vertices, func(point Point[T]) Point[T] {
43+
return center.Add(point.Subtract(center).MultiplyXY(scaleX, scaleY))
44+
})}
45+
}
46+
47+
func transform[S ~[]E, E any, T any](input S, fn func(E) T) []T {
48+
output := make([]T, len(input))
49+
for i, v := range input {
50+
output[i] = fn(v)
51+
}
52+
53+
return output
54+
}

polygon_regular.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package geom
2+
3+
import (
4+
"math"
5+
)
6+
7+
// RegularPolygon is a polygon with equally spaced transform around a center.
8+
type RegularPolygon[T Number] struct {
9+
Center Point[T]
10+
Size Size[T]
11+
N int
12+
}
13+
14+
// RP is shorthand for RegularPolygon{center, size, n}.
15+
func RP[T Number](center Point[T], size Size[T], n int) RegularPolygon[T] {
16+
return RegularPolygon[T]{center, size, n}
17+
}
18+
19+
// Triangle creates a RegularPolygon with 3 transform.
20+
func Triangle[T Number](center Point[T], size Size[T]) RegularPolygon[T] {
21+
return RegularPolygon[T]{center, size, 3}
22+
}
23+
24+
// Square creates a RegularPolygon with 4 transform.
25+
func Square[T Number](center Point[T], size Size[T]) RegularPolygon[T] {
26+
return RegularPolygon[T]{center, size, 4}
27+
}
28+
29+
// Hexagon creates a RegularPolygon with 6 transform.
30+
func Hexagon[T Number](center Point[T], size Size[T]) RegularPolygon[T] {
31+
return RegularPolygon[T]{center, size, 6}
32+
}
33+
34+
// Translate creates a new RegularPolygon translated by the given vector.
35+
func (rp RegularPolygon[T]) Translate(change Vector[T]) RegularPolygon[T] {
36+
return RegularPolygon[T]{rp.Center.Add(change), rp.Size, rp.N}
37+
}
38+
39+
// MoveTo creates a new RegularPolygon with the same size and sides centered at point.
40+
func (rp RegularPolygon[T]) MoveTo(point Point[T]) RegularPolygon[T] {
41+
return RegularPolygon[T]{point, rp.Size, rp.N}
42+
}
43+
44+
// Multiple creates a new RegularPolygon with size scaled by the given factor.
45+
func (rp RegularPolygon[T]) Scale(scale float64) RegularPolygon[T] {
46+
return RegularPolygon[T]{rp.Center, rp.Size.Scale(scale), rp.N}
47+
}
48+
49+
// Multiple creates a new RegularPolygon with size scaled by the given factors.
50+
func (rp RegularPolygon[T]) ScaleXY(scaleX, scaleY float64) RegularPolygon[T] {
51+
return RegularPolygon[T]{rp.Center, rp.Size.ScaleXY(scaleX, scaleY), rp.N}
52+
}
53+
54+
// Vertices returns the polygon transform in order starting from angle 0, counter-clockwise.
55+
func (rp RegularPolygon[T]) Vertices() []Point[T] {
56+
initAngle := 0.0
57+
angleStep := 2 * math.Pi / float64(rp.N)
58+
59+
vertices := make([]Point[T], rp.N)
60+
for i := 0; i < rp.N; i++ {
61+
vertices[i] = rp.Center.Add(VecFromAngle[T](initAngle+float64(i)*angleStep, 1).MultiplyXY(float64(rp.Size.Width), float64(rp.Size.Height)))
62+
}
63+
64+
return vertices
65+
}
66+
67+
// ToPolygon converts the regular polygon into a generic Polygon with computed vertices.
68+
func (rp RegularPolygon[T]) ToPolygon() Polygon[T] {
69+
return Polygon[T]{rp.Vertices()}
70+
}

rectangle.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,14 @@ func R[T Number](center Point[T], size Size[T]) Rectangle[T] {
1313
return Rectangle[T]{center, size}
1414
}
1515

16-
// RectMin creates a Rectangle from min point and size.
17-
func RectMin[T Number](min Point[T], size Size[T]) Rectangle[T] {
16+
// RectangleFromMin creates a Rectangle from min point and size.
17+
func RectangleFromMin[T Number](min Point[T], size Size[T]) Rectangle[T] {
1818
return Rectangle[T]{min.AddXY(size.Scale(0.5).XY()), size}
1919
}
2020

21-
// RectMinMax creates a Rectangle from min and max points.
22-
func RectMinMax[T Number](min, max Point[T]) Rectangle[T] {
23-
return RectMin(min, S(max.Subtract(min).XY()))
24-
}
25-
26-
// RectFromSize creates a Rectangle centered at (0,0) with the given size.
27-
func RectFromSize[T Number](size Size[T]) Rectangle[T] {
28-
return Rectangle[T]{Point[T]{0, 0}, size}
21+
// RectangleFromMinMax creates a Rectangle from min and max points.
22+
func RectangleFromMinMax[T Number](min, max Point[T]) Rectangle[T] {
23+
return RectangleFromMin(min, S(max.Subtract(min).XY()))
2924
}
3025

3126
// Translate creates a new Rectangle translated by the given vector.
@@ -122,7 +117,7 @@ func (r Rectangle[T]) Edges() []Line[T] {
122117
return []Line[T]{}
123118
}
124119

125-
// Vertices returns the four corner points in clockwise order starting from Min (bottom-left).
120+
// Vertices returns the polygon vertices in order starting Min point, counter-clockwise.
126121
func (r Rectangle[T]) Vertices() []Point[T] {
127122
return []Point[T]{
128123
r.BottomLeft(),
@@ -159,8 +154,12 @@ func (r Rectangle[T]) Contains(point Point[T]) bool {
159154
return minPoint.X <= point.X && point.X <= maxPoint.X && minPoint.Y <= point.Y && point.Y <= maxPoint.Y
160155
}
161156

157+
// ToPolygon converts the rectangle into a generic Polygon with computed vertices.
158+
func (r Rectangle[T]) ToPolygon() Polygon[T] {
159+
return Polygon[T]{r.Vertices()}
160+
}
161+
162162
// String returns a string representation of the Rectangle using min and max.
163163
func (r Rectangle[T]) String() string {
164164
return fmt.Sprintf("%s-%s", r.Min().String(), r.Max().String())
165-
166165
}

0 commit comments

Comments
 (0)