Initial version of the geom package
- Includes PointF, RectangleF and PolygonF. Additional it includes the 32 bit floating point PointF32 and wrappers to image.Point and image.Rectangle.
This commit is contained in:
commit
26bac636bc
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Sander Schobers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# geom package
|
||||
|
||||
The geom packages exposes some basic geometries using floating point numbers. The package is licensed under [MIT](LICENSE). Currently this package is still under development and thus the API may break.
|
13
point.go
Normal file
13
point.go
Normal file
@ -0,0 +1,13 @@
|
||||
package geom
|
||||
|
||||
import (
|
||||
_image "image"
|
||||
)
|
||||
|
||||
// Point is exposing the standard library image.Point in the geom package.
|
||||
type Point _image.Point
|
||||
|
||||
// Pt is a shorthand function to create a point.
|
||||
func Pt(x, y int) Point {
|
||||
return Point{x, y}
|
||||
}
|
81
pointf.go
Normal file
81
pointf.go
Normal file
@ -0,0 +1,81 @@
|
||||
package geom
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// PointF is an X, Y coordinate pair (floating point).
|
||||
type PointF struct {
|
||||
X, Y float64
|
||||
}
|
||||
|
||||
// PtF is a shorthand function to create a point.
|
||||
func PtF(x, y float64) PointF {
|
||||
return PointF{X: x, Y: y}
|
||||
}
|
||||
|
||||
// String formats the point p as a string.
|
||||
func (p Point) String() string {
|
||||
return "(" + strconv.Itoa(p.X) + "," + strconv.Itoa(p.Y) + ")"
|
||||
}
|
||||
|
||||
// To32 transforms the point p into a PointF32.
|
||||
func (p PointF) To32() PointF32 {
|
||||
return PointF32{float32(p.X), float32(p.Y)}
|
||||
}
|
||||
|
||||
// Add adds q as a vector to p
|
||||
func (p PointF) Add(q PointF) PointF {
|
||||
return PointF{p.X + q.X, p.Y + q.Y}
|
||||
}
|
||||
|
||||
// AngleTo calculates the angle [0..2*Pi) from point p to point q.
|
||||
func (p PointF) AngleTo(q PointF) float64 {
|
||||
a := math.Atan((p.Y - q.Y) / (p.X - q.X))
|
||||
if q.X < p.X {
|
||||
return a + math.Pi
|
||||
}
|
||||
if a < 0 {
|
||||
a += 2 * math.Pi
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// Distance calculates the distance between points p and q.
|
||||
func (p PointF) Distance(q PointF) float64 {
|
||||
return math.Sqrt(p.Distance2(q))
|
||||
}
|
||||
|
||||
// Distance2 calculates the squared distance between points p and q.
|
||||
func (p PointF) Distance2(q PointF) float64 {
|
||||
dx := q.X - p.X
|
||||
dy := q.Y - p.Y
|
||||
return dx*dx + dy*dy
|
||||
}
|
||||
|
||||
// In tests if the point p is inside the rectangle r.
|
||||
func (p PointF) In(r RectangleF) bool {
|
||||
if p.X < r.Min.X || p.X >= r.Max.X || p.Y < r.Min.Y || p.Y >= r.Max.Y {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// InPolygon tests is the point p is inside the polygon q.
|
||||
func (p PointF) InPolygon(q PolygonF) bool {
|
||||
var n = len(q.Points)
|
||||
var c = false
|
||||
|
||||
var i = 0
|
||||
var j = n - 1
|
||||
for i < n {
|
||||
if ((q.Points[i].Y >= p.Y) != (q.Points[j].Y >= p.Y)) &&
|
||||
(p.X <= (q.Points[j].X-q.Points[i].X)*(p.Y-q.Points[i].Y)/(q.Points[j].Y-q.Points[i].Y)+q.Points[i].X) {
|
||||
c = !c
|
||||
}
|
||||
j = i
|
||||
i++
|
||||
}
|
||||
return c
|
||||
}
|
6
pointf32.go
Normal file
6
pointf32.go
Normal file
@ -0,0 +1,6 @@
|
||||
package geom
|
||||
|
||||
// PointF32 is an X, Y coordinate pair (floating point, 32 bits).
|
||||
type PointF32 struct {
|
||||
X, Y float32
|
||||
}
|
31
pointf_test.go
Normal file
31
pointf_test.go
Normal file
@ -0,0 +1,31 @@
|
||||
package geom
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPointFAngleTo(t *testing.T) {
|
||||
for a := .0; a <= 2*math.Pi; a += math.Pi * 0.25 {
|
||||
assert.InDelta(t, a, PtF(0, 0).AngleTo(PtF(100*math.Cos(a), 100*math.Sin(a))), 0.000001)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointInPolygon(t *testing.T) {
|
||||
pol := PolygonF{[]PointF{PtF(0, 0), PtF(0, 3), PtF(1, 3), PtF(2, 1), PtF(3, 3), PtF(5, 3), PtF(5, 2), PtF(3, 1), PtF(5, 0)}}
|
||||
assert.True(t, PtF(1, 2).InPolygon(pol))
|
||||
assert.True(t, PtF(3, 2).InPolygon(pol))
|
||||
assert.True(t, PtF(4, 2).InPolygon(pol))
|
||||
// assert.True(t, PtF(0, 0).InPolygon(pol)) // Corner = out
|
||||
// assert.True(t, PtF(0, 3).InPolygon(pol)) // Corner = out
|
||||
// assert.True(t, PtF(5, 3).InPolygon(pol)) // Corner = in
|
||||
// assert.True(t, PtF(5, 0).InPolygon(pol)) // Corner = out
|
||||
assert.False(t, PtF(0, -1).InPolygon(pol))
|
||||
assert.False(t, PtF(-1, 0).InPolygon(pol))
|
||||
assert.False(t, PtF(2, 2).InPolygon(pol))
|
||||
assert.False(t, PtF(2, 3).InPolygon(pol))
|
||||
assert.False(t, PtF(4, 1).InPolygon(pol))
|
||||
assert.False(t, PtF(5, 1).InPolygon(pol))
|
||||
}
|
14
polygonf.go
Normal file
14
polygonf.go
Normal file
@ -0,0 +1,14 @@
|
||||
package geom
|
||||
|
||||
// PolygonF is defined by a set of points (floating point).
|
||||
type PolygonF struct {
|
||||
Points []PointF
|
||||
}
|
||||
|
||||
// Add creates a new polyqon based on p with one or more extra points q.
|
||||
func (p PolygonF) Add(q ...PointF) PolygonF {
|
||||
var t = PolygonF{make([]PointF, len(p.Points)+len(q))}
|
||||
copy(t.Points, p.Points)
|
||||
copy(t.Points[len(p.Points):], q)
|
||||
return t
|
||||
}
|
13
rectangle.go
Normal file
13
rectangle.go
Normal file
@ -0,0 +1,13 @@
|
||||
package geom
|
||||
|
||||
import (
|
||||
_image "image"
|
||||
)
|
||||
|
||||
// Rectangle is exposing the standard library image.Rectangle in the geom package.
|
||||
type Rectangle _image.Rectangle
|
||||
|
||||
// Rect is a shorthand function to create a rectangle.
|
||||
func Rect(x0, y0, x1, y1 int) Rectangle {
|
||||
return Rectangle(_image.Rect(x0, y0, x1, y1))
|
||||
}
|
22
rectanglef.go
Normal file
22
rectanglef.go
Normal file
@ -0,0 +1,22 @@
|
||||
package geom
|
||||
|
||||
// RectangleF is defined by two points, the minimum and maximum (floating point).
|
||||
type RectangleF struct {
|
||||
Min, Max PointF
|
||||
}
|
||||
|
||||
// RectF is a shorthand function to create a rectangle.
|
||||
func RectF(x0, y0, x1, y1 float64) RectangleF {
|
||||
if x0 > x1 {
|
||||
x0, x1 = x1, x0
|
||||
}
|
||||
if y0 > y1 {
|
||||
y0, y1 = y1, y0
|
||||
}
|
||||
return RectangleF{PtF(x0, y0), PtF(x1, y1)}
|
||||
}
|
||||
|
||||
// Size returns the size of the rectangle.
|
||||
func (r RectangleF) Size() PointF {
|
||||
return PtF(r.Max.X-r.Min.X, r.Max.Y-r.Min.Y)
|
||||
}
|
Loading…
Reference in New Issue
Block a user