-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgeom2d.go
72 lines (64 loc) · 2.48 KB
/
geom2d.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// Copyright (c) 2023, The Goki Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mat32
import (
"image"
)
// Geom2DInt defines a geometry in 2D dots units (int) -- this is just a more
// convenient format than image.Rectangle for cases where the size and
// position are independently updated (e.g., Viewport)
type Geom2DInt struct {
Pos image.Point
Size image.Point
}
// Bounds converts geom to equivalent image.Rectangle
func (gm *Geom2DInt) Bounds() image.Rectangle {
return image.Rect(gm.Pos.X, gm.Pos.Y, gm.Pos.X+gm.Size.X, gm.Pos.Y+gm.Size.Y)
}
// SizeRect converts geom to rect version of size at 0 pos
func (gm *Geom2DInt) SizeRect() image.Rectangle {
return image.Rect(0, 0, gm.Size.X, gm.Size.Y)
}
// SetRect sets values from image.Rectangle
func (gm *Geom2DInt) SetRect(r image.Rectangle) {
gm.Pos = r.Min
gm.Size = r.Size()
}
// FitGeomInWindow returns a position and size for a region (sub-window)
// within a larger window geom (pos and size) that fits entirely
// within that window to the extent possible,
// given an initial starting position and size.
// The position is first adjusted to try to fit the size, and then the size
// is adjusted to make it fit if it is still too big.
func FitGeomInWindow(stPos, stSz, winPos, winSz int) (pos, sz int) {
pos = stPos
sz = stSz
// we go through two iterations: one to fix our position and one to fix
// our size. this ensures that we adjust position and not size if we can,
// but we still always end up with valid dimensions by using size as a fallback.
if pos < winPos {
pos = winPos
}
if pos+sz > winPos+winSz { // our max > window max
pos = winPos + winSz - sz // window max - our size
}
if pos < winPos {
pos = winPos
}
if pos+sz > winPos+winSz { // our max > window max
sz = winSz + winPos - pos // window max - our min
}
return
}
// FitInWindow returns a position and size for a region (sub-window)
// within a larger window geom that fits entirely within that window to the
// extent possible, for the initial "ideal" starting position and size.
// The position is first adjusted to try to fit the size, and then the size
// is adjusted to make it fit if it is still too big.
func (gm *Geom2DInt) FitInWindow(win Geom2DInt) Geom2DInt {
var fit Geom2DInt
fit.Pos.X, fit.Size.X = FitGeomInWindow(gm.Pos.X, gm.Size.X, win.Pos.X, win.Size.X)
fit.Pos.Y, fit.Size.Y = FitGeomInWindow(gm.Pos.Y, gm.Size.Y, win.Pos.Y, win.Size.Y)
return fit
}