gg/mx/liner.go

82 lines
1.5 KiB
Go
Raw Permalink Normal View History

2024-05-28 11:24:12 +03:00
package mx
type Liner interface {
PointContainer
GetLineExpr() LineExpr
}
type Liners []Liner
// The type represents the cross of 2 Liners.
type LinersCrossing struct {
Pair [2]LineExpr
Point Vector
}
// Checks all possible combinations
// of Liners to cross and returns
// the crossings if are present.
func GetLinersCrossings(
what, with Liners,
) []LinersCrossing {
ret := make([]LinersCrossing, 0, len(with))
for i := range what {
for j := range with {
cross, doCross := DoLinersCross(
what[i],
with[j],
)
if doCross {
ret = append(ret, cross)
}
}
}
return ret
}
// Check if two LinerPointContainers do cross and return the
// crossing point.
func DoLinersCross(
lp1, lp2 Liner,
) (LinersCrossing, bool) {
l1 := lp1.GetLineExpr()
l2 := lp2.GetLineExpr()
crossPt, doCross := l1.Crosses(l2)
if !lp1.ContainsPoint(crossPt) ||
!lp2.ContainsPoint(crossPt) {
return LinersCrossing{}, false
}
return LinersCrossing{
Pair: [2]LineExpr{l1, l2},
Point: crossPt,
}, doCross
}
// Check whether the liner is parallel to the other liner.
func AreLinersParallel(
first, second Liner,
) bool {
l1 := first.GetLineExpr()
l2 := second.GetLineExpr()
return l1.Vertical && l2.Vertical ||
l1.K == l2.K
}
// Returns angle between liners in radians.
// The value fits the -Pi < Value < Pi condition.
func GetAngleBetweenLiners(
first, second Liner,
) Float {
l1 := first.GetLineExpr()
l2 := second.GetLineExpr()
if l1.K == l2.K {
return 0
}
return Atan(l1.K/l2.K)
}