diff --git a/cmd/math/main.go b/cmd/math/main.go new file mode 100644 index 0000000..19625fc --- /dev/null +++ b/cmd/math/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "vultras.su/core/gg" + "fmt" + "encoding/json" +) +type Float = gg.Float + +func EdgesFromVals(vals ...Float) gg.Edges { + ret := gg.Edges{} + for i:=0 ; i 0 || doCross } func GetCollisions(c Collider, cs []Collider) []Collision { diff --git a/edge.go b/edge.go index fcc58ee..253a15e 100644 --- a/edge.go +++ b/edge.go @@ -2,7 +2,7 @@ package gg type Edges []Edge // Get crosses of edges. -func (what Edges) LineCrossWith(with Edges) ([]LineCross, bool) { +func (what Edges) CrossWithEdges(with Edges) ([]LineCross, bool) { ret := []LineCross{} for i := range what { for j := range with { @@ -13,11 +13,7 @@ func (what Edges) LineCrossWith(with Edges) ([]LineCross, bool) { } } - if len(ret) == 0 { - return nil, false - } - - return ret, true + return ret, len(ret) > 0 } // The type represents a line segment. The name is for short. @@ -25,13 +21,22 @@ type Edge [2]Vector // Returns corresponding to the segment Line. func (l Edge) Line() Line { + var ( + x Float + vertical bool + ) + p0 := l[0] p1 := l[1] k := (p0.Y - p1.Y) / (p0.X - p1.X) c := p0.Y - p0.X*k - - return Line{k, c} + if p0.X == p1.X { + vertical = true + x = p0.X + } + + return Line{k, c, x, vertical} } func (l Edge) ContainedPoints(pts Points) (Points) { @@ -51,11 +56,11 @@ func (l Edge) ContainsPoint(p Point) bool { return false } - xMax := Max(l[0].X, l[1].X) - xMin := Min(l[0].X, l[1].X) + xMax := Max(l[0].X, l[1].X) + xMin := Min(l[0].X, l[1].X) - yMax := Max(l[0].Y, l[1].Y) - yMin := Min(l[0].Y, l[1].Y) + yMax := Max(l[0].Y, l[1].Y) + yMin := Min(l[0].Y, l[1].Y) if !(xMin < p.X && p.X < xMax) || !(yMin < p.Y && p.Y < yMax) { diff --git a/fmt.go b/fmt.go new file mode 100644 index 0000000..bdd5b07 --- /dev/null +++ b/fmt.go @@ -0,0 +1,13 @@ +package gg + +import ( + "fmt" +) + +func Println(v ...any) { + fmt.Println(v...) +} + +func Printf(format string, v ...any) { + fmt.Printf(format, v...) +} diff --git a/line.go b/line.go index e89664b..b2a08ce 100644 --- a/line.go +++ b/line.go @@ -1,8 +1,11 @@ package gg +//import "fmt" + // The type represents mathematical equation of line and line itself. type Line struct { - K, C Float + K, C, X Float + Vertical bool } // Returns the line itself. Made to implement the Liner interface. @@ -11,22 +14,32 @@ func (l Line) Line() Line { } func (l Line) ContainsPoint(p Point) bool { - buf := Line{0, p.Y} + buf := Line{0, p.Y, 0, false} pc, ok := l.crossesLine(buf) if !ok { return false } - return pc == p + return Neq(pc.X, p.X) && Neq(pc.Y, p.Y) } func (l1 Line) crossesLine(l2 Line) (Point, bool) { + var x, y Float if LinersParallel(l1, l2) { return Point{}, false } - - x := (l1.C - l2.C) / (l2.K - l1.K) - y := l1.K*x + l1.C + + if l1.Vertical { + x = l1.X + y = l2.K*x + l2.C + } else if l2.Vertical { + x = l2.X + y = l1.K*x + l1.C + } else { + x = (l1.C - l2.C) / (l2.K - l1.K) + y = l1.K*x + l1.C + } + return Point{x, y}, true } diff --git a/liner.go b/liner.go index 965511e..7892002 100644 --- a/liner.go +++ b/liner.go @@ -22,16 +22,15 @@ func LinersCross(lp1, lp2 LinerPointContainer) (LineCross, bool) { l2 := lp2.Line() crossPt, doCross := l1.crossesLine(l2) - if !doCross || - len(lp1.ContainedPoints([]Point{crossPt}))==0 || + if len(lp1.ContainedPoints([]Point{crossPt}))==0 || len(lp2.ContainedPoints([]Point{crossPt}))==0 { - return LineCross{}, false + doCross = false } return LineCross{ Pair: [2]Line{l1, l2}, Point: crossPt, - }, true + }, doCross } // Check whether the liner is parallel to the other liner. @@ -39,7 +38,7 @@ func LinersParallel(first, second Liner) bool { l1 := first.Line() l2 := second.Line() - return l1.K == l2.K + return l1.K == l2.K || l1.Vertical && l2.Vertical } // Returns angle between liners in radians. diff --git a/math.go b/math.go index 98a67bf..1f3e124 100644 --- a/math.go +++ b/math.go @@ -13,8 +13,17 @@ const ( Pi = math.Pi RadDegrees = 57.2958 //PiRad = Pi * Rad + EqualityThreshold = 1e-9 ) +func IsNan(v Float) bool { + return math.IsNaN(v) +} + +func IsInf(f Float, sign int) bool { + return math.IsInf(f, sign) +} + func Degree(f Float) Float { return (f/(2*Pi))*360 } @@ -64,6 +73,13 @@ func Min(v1, v2 Float) Float { return v2 } +func Abs(v Float) Float { + if v >= 0 { + return v + } + return -v +} + func RadiansToDegrees(v Float) Float { return v/Pi * 180 } @@ -72,4 +88,8 @@ func DeegresToRadians(v Float) Float { return v } +// Returns whether the two floats are nearly equal. +func Neq(a, b Float) bool { + return Abs(a-b) <= EqualityThreshold +} diff --git a/polygon.go b/polygon.go index 0f31c4a..6424aaa 100644 --- a/polygon.go +++ b/polygon.go @@ -28,6 +28,13 @@ func (p Polygon) MakeTriangles() Triangles { return ret } +func (p Polygon) Vertices() Vertices { + return p.MakeTriangles().Vertices() +} +func (p Polygon) Edges() Edges { + return p.MakeTriangles().Edges() +} + // Polygon that can be drawn. type DrawablePolygon struct { Polygon diff --git a/size.go b/size.go index 02877ab..c06b113 100644 --- a/size.go +++ b/size.go @@ -6,7 +6,13 @@ type Size struct { // The upper left corner position point. Position Point // Absolute width and height. + // Both must be positive values. Width, Height Float } +func (size Size) ContainsPoint(pt Point) bool { + return (size.Position.X < pt.X && (size.Position.X + size.Width) > pt.X ) && + (size.Position.Y < pt.Y && (size.Position.Y + size.Height) > pt.Y ) +} + //type (s Size) ContainsPoint diff --git a/taskfile.yml b/taskfile.yml index 1043de8..8ceccca 100644 --- a/taskfile.yml +++ b/taskfile.yml @@ -3,3 +3,6 @@ tasks: btest: cmds: - go build ./cmd/test/ + bmath: + cmds: + - go build ./cmd/math/ diff --git a/transform.go b/transform.go index 790845d..8b25878 100644 --- a/transform.go +++ b/transform.go @@ -43,6 +43,7 @@ func T() Transform { scale: Vector{1, 1}, // Rotate around the center. around: V(.5, .5), + rotation: EqualityThreshold, } return ret } diff --git a/triangle.go b/triangle.go index 4106f66..ea9983d 100644 --- a/triangle.go +++ b/triangle.go @@ -86,6 +86,14 @@ func (t Triangle) Sgn() Float { (t[1].X - t[2].X) * (t[0].Y - t[2].Y) } +func (t Triangle) Edges() Edges { + return Edges{ + Edge{t[0], t[1]}, + Edge{t[1], t[2]}, + Edge{t[2], t[0]}, + } +} + func (t Triangle) Vertices() Vertices { return Vertices{ t[0], t[1], t[2], @@ -103,6 +111,22 @@ func (ts Triangles) ContainedPoints(pts Points) (Points) { return ret } +func (ts Triangles) Vertices() Vertices { + ret := make(Vertices, 0, len(ts)*3) + for _, t := range ts { + ret = append(ret, t.Vertices()...) + } + return ret +} + +func (ts Triangles) Edges() Edges { + ret := make(Edges, 0, len(ts)*3) + for _, t := range ts { + ret = append(ret, t.Edges()...) + } + return ret +} + func (r *DrawableTriangles) MakeEVertices(c *Context) []EVertex { m := c.Camera.RealMatrix() vs := make([]ebiten.Vertex, len(r.Triangles) * 3) @@ -117,3 +141,4 @@ func (r *DrawableTriangles) MakeEVertices(c *Context) []EVertex { return vs } +