Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small changes for lines #3

Merged
merged 3 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: main
on: [ push ]
jobs:
build:
tests:
name: Tests
runs-on: ubuntu-latest

Expand Down
3 changes: 3 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
comment:
layout: "condensed_header, condensed_files, condensed_footer"
hide_project_coverage: true
130 changes: 43 additions & 87 deletions geometry_line.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,46 @@ func (ln Line) Length() float64 {
return ln.From.Distance(ln.To)
}

// Vector returns the vector of the Line.
// https://en.wikipedia.org/wiki/Euclidean_vector
func (ln Line) Vector() Point {
return ln.To.Sub(ln.From)
}

// Slope returns the slope value of the Line.
// https://en.wikipedia.org/wiki/Slope
func (ln Line) Slope() float64 {
return (ln.To.Y - ln.From.Y) / (ln.To.X - ln.From.X)
}

// CrossProduct returns the cross product of the Line.
// https://en.wikipedia.org/wiki/Cross_product
func (ln Line) CrossProduct() float64 {
return ln.From.X*ln.To.Y - ln.From.Y*ln.To.X
}

// IsHorizontal tests if the Line is horizontal.
func (ln Line) IsHorizontal() bool {
return ln.From.Y == ln.To.Y
}

// IsVertical tests if the Line is vertical.
func (ln Line) IsVertical() bool {
return ln.From.X == ln.To.X
}

// IsMoving tests if the Line has magnitude.
func (ln Line) IsMoving() bool {
return !ln.From.IsSame(ln.To)
}

// Segment returns the Line segment with the given length.
func (ln Line) Segment(length float64) Line {
if length == 0 {
return Line{ln.From, ln.From}
}

v := ln.Direction()
v := ln.Vector()
vl := ln.Length()
ux := v.X / vl
uy := v.Y / vl
Expand All @@ -40,31 +73,6 @@ func (ln Line) Segment(length float64) Line {
}
}

// IsMoving tests if the Line represents a moving object.
func (ln Line) IsMoving() bool {
return !ln.From.IsSame(ln.To)
}

// Direction returns the direction of the Line.
func (ln Line) Direction() Point {
return ln.To.Sub(ln.From)
}

// IsHorizontal tests if the Line is horizontal.
func (ln Line) IsHorizontal() bool {
return ln.From.Y == ln.To.Y
}

// IsVertical tests if the Line is vertical.
func (ln Line) IsVertical() bool {
return ln.From.X == ln.To.X
}

// Slope returns the slope value of the Line.
func (ln Line) Slope() float64 {
return (ln.To.Y - ln.From.Y) / (ln.To.X - ln.From.X)
}

// IsPointOnLine tests if the Point is on the Line.
func (ln Line) IsPointOnLine(p Point) bool {
if ln.IsHorizontal() {
Expand Down Expand Up @@ -92,75 +100,24 @@ func (ln Line) IsPointOnSegment(p Point) bool {

// LinesIntersection returns the crossing Point of two Lines.
func (ln Line) LinesIntersection(tl Line) (Point, bool) {
// parallel
if (ln.IsHorizontal() && tl.IsHorizontal()) || (ln.IsVertical() && tl.IsVertical()) {
return Point{}, false
}

// vertical / horizontal
if ln.IsVertical() && tl.IsHorizontal() {
return tl.LinesIntersection(ln)
}
if ln.IsHorizontal() && tl.IsVertical() {
return NewPoint(tl.From.X, ln.From.Y), true
}

// diagonal and vertical
if tl.IsVertical() {
return tl.LinesIntersection(ln)
}
if ln.IsVertical() {
x := ln.From.X
y := tl.Slope()*x + tl.From.Y
return NewPoint(x, y), true
}

// diagonal
slope1 := ln.Slope()
slope2 := tl.Slope()
// parallel
if slope1 == slope2 {
return Point{}, false
}

yIntercept1 := ln.From.Y - slope1*ln.From.X
yIntercept2 := tl.From.Y - slope2*tl.From.X

x := (yIntercept2 - yIntercept1) / (slope1 - slope2)
y := slope1*x + yIntercept1

return NewPoint(x, y), true
return linesIntersection(ln, tl, false, false)
}

// SegmentsIntersection returns the crossing Point of two Line segments.
func (ln Line) SegmentsIntersection(tl Line) (Point, bool) {
p, ok := ln.LinesIntersection(tl)
if !ok {
return Point{}, false
}
if !ln.Rect().IsContainsPoint(p) || !tl.Rect().IsContainsPoint(p) {
return Point{}, false
}
return p, true
return linesIntersection(ln, tl, true, true)
}

// LineSegmentIntersection returns the crossing Point of the Line and the Line segment.
func (ln Line) LineSegmentIntersection(tl Line) (Point, bool) {
p, ok := ln.LinesIntersection(tl)
if !ok {
return Point{}, false
}
if !tl.Rect().IsContainsPoint(p) {
return Point{}, false
}
return p, true
return linesIntersection(ln, tl, false, true)
}

// Rotate returns the Line rotated by the given angle.
func (ln Line) Rotate(angle float64) Line {
radians := angle * math.Pi / 180

v := ln.Direction()
v := ln.Vector()
rx := v.X*math.Cos(radians) + v.Y*math.Sin(radians)
ry := v.X*-math.Sin(radians) + v.Y*math.Cos(radians)

Expand All @@ -169,18 +126,17 @@ func (ln Line) Rotate(angle float64) Line {

// IsCollision tests whether a moving object collides with another moving object within a given radius.
func (ln Line) IsCollision(tl Line, radius float64) bool {
tv := tl.Direction()
lv := ln.Direction()
tv := tl.Vector()
lv := ln.Vector()
dx := tl.From.Sub(ln.From)
vx2 := tv.X - lv.X
vy2 := tv.Y - lv.Y
vx := tv.Sub(lv)

a := vx2*vx2 + vy2*vy2
a := vx.X*vx.X + vx.Y*vx.Y
if a <= 0 {
return false
}

b := 2 * (dx.X*vx2 + dx.Y*vy2)
b := 2 * (dx.X*vx.X + dx.Y*vx.Y)
c := dx.X*dx.X + dx.Y*dx.Y - radius*radius
d := b*b - 4*a*c
if d < 0 {
Expand Down
Loading