2023-05-28 19:14:02 +03:00
|
|
|
package gx
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math"
|
|
|
|
)
|
|
|
|
|
2023-05-28 19:45:58 +03:00
|
|
|
// The type represents mathematical equation of line and line itself.
|
|
|
|
type Line struct {
|
2023-05-28 19:14:02 +03:00
|
|
|
K, C Float
|
|
|
|
}
|
|
|
|
|
2023-05-28 20:02:07 +03:00
|
|
|
type Liner interface {
|
|
|
|
Line() Line
|
|
|
|
}
|
|
|
|
|
2023-05-28 19:14:02 +03:00
|
|
|
// The type represents a line segment.
|
|
|
|
type LineSegment [2]Point
|
|
|
|
|
2023-06-03 11:25:19 +03:00
|
|
|
// The type represents multiple line segments.
|
|
|
|
type LineSegments []LineSegment
|
|
|
|
|
2023-05-28 20:02:07 +03:00
|
|
|
// Check whether the liner is parallel to the line.
|
|
|
|
func (l Line) Parallel(liner Liner) bool {
|
|
|
|
buf := liner.Line()
|
|
|
|
|
|
|
|
if buf.K == l.K {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-05-28 21:07:05 +03:00
|
|
|
func (l Line) Line() Line {
|
|
|
|
return l
|
|
|
|
}
|
|
|
|
|
2023-05-28 21:22:52 +03:00
|
|
|
func (l Line) ContainsPoint(p Point) bool {
|
|
|
|
buf := Line{0, p.Y}
|
|
|
|
pc, ok := l.crossesLine(buf)
|
|
|
|
if !ok {
|
|
|
|
return false
|
2023-05-28 21:07:05 +03:00
|
|
|
}
|
|
|
|
|
2023-05-28 21:22:52 +03:00
|
|
|
return pc == p
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l Line) Crosses(with Liner) (Point, bool) {
|
2023-05-28 21:07:05 +03:00
|
|
|
switch with.(type) {
|
|
|
|
case Line :
|
|
|
|
return l.crossesLine(with.(Line))
|
|
|
|
case LineSegment :
|
|
|
|
return with.(LineSegment).crossesLine(l)
|
|
|
|
default:
|
|
|
|
panic("unhandled type")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l1 Line) crossesLine(l2 Line) (Point, bool) {
|
2023-05-28 21:22:52 +03:00
|
|
|
if l1.Parallel(l2) {
|
|
|
|
return Point{}, false
|
|
|
|
}
|
|
|
|
|
2023-05-28 21:07:05 +03:00
|
|
|
x := (l1.C - l2.C) / (l2.K - l1.K)
|
|
|
|
y := l1.K*x + l1.C
|
|
|
|
return Point{x, y}, true
|
|
|
|
}
|
|
|
|
|
2023-05-30 13:12:11 +03:00
|
|
|
func (l LineSegment) ContainsPoint(p Point) bool {
|
|
|
|
line := l.Line()
|
|
|
|
if !line.ContainsPoint(p) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-05-28 19:14:02 +03:00
|
|
|
// Get square of length of line segment.
|
|
|
|
func (ls LineSegment) LenSqr() Float {
|
|
|
|
return Sqr(ls[0].X - ls[1].X) +
|
|
|
|
Sqr(ls[0].Y - ls[1].Y)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get length of the line segment.
|
|
|
|
func (ls LineSegment) Len() Float {
|
|
|
|
return math.Sqrt(ls.LenSqr())
|
|
|
|
}
|
|
|
|
|
2023-05-28 19:45:58 +03:00
|
|
|
// Returns corresponding to the segment line line.
|
|
|
|
func (l LineSegment) Line() Line {
|
2023-05-28 19:14:02 +03:00
|
|
|
p0 := l[0]
|
|
|
|
p1 := l[1]
|
|
|
|
|
|
|
|
k := (p0.Y - p1.Y) / (p0.X - p1.X)
|
|
|
|
c := p0.Y - p0.X*k
|
|
|
|
|
2023-05-28 19:45:58 +03:00
|
|
|
return Line{k, c}
|
2023-05-28 19:14:02 +03:00
|
|
|
}
|
|
|
|
|
2023-05-28 21:07:05 +03:00
|
|
|
func (l LineSegment) Crosses(with Liner) (Point, bool) {
|
2023-05-28 20:02:07 +03:00
|
|
|
switch with.(type) {
|
|
|
|
case Line :
|
|
|
|
return l.crossesLine(with.(Line))
|
|
|
|
case LineSegment :
|
|
|
|
return l.crossesLineSegment(with.(LineSegment))
|
|
|
|
default:
|
|
|
|
panic("The type that is not defined to be crossed")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-28 21:07:05 +03:00
|
|
|
func (l LineSegment) Contains(what any) bool {
|
|
|
|
switch what.(type) {
|
|
|
|
case Point :
|
|
|
|
return l.containsPoint(what.(Point))
|
|
|
|
default :
|
|
|
|
panic("Unexpected type")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l LineSegment) containsPoint(p Point) bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l LineSegment) crossesLineSegment(with LineSegment) (Point, bool) {
|
|
|
|
return Point{}, false
|
2023-05-28 20:02:07 +03:00
|
|
|
}
|
|
|
|
|
2023-05-28 21:07:05 +03:00
|
|
|
func (l LineSegment) crossesLine(with Line) (Point, bool) {
|
|
|
|
return Point{}, false
|
2023-05-28 20:02:07 +03:00
|
|
|
}
|
|
|
|
|