This commit is contained in:
Andrey Parhomenko 2023-06-03 12:26:31 +03:00
parent 506e2772f7
commit e3ab4596e1
5 changed files with 92 additions and 77 deletions

View file

@ -32,7 +32,7 @@ func main() {
gx.Point{0, 1}, gx.Point{0, 1},
gx.Point{1, 0}, gx.Point{1, 0},
}.Line() }.Line()
fmt.Println(l1.Crosses(l2)) fmt.Println(gx.LinersCross(l1, l2))
fmt.Println(l1.ContainsPoint(gx.Point{1, 4})) fmt.Println(l1.ContainsPoint(gx.Point{1, 4}))
t := gx.Rectangle{ t := gx.Rectangle{

View file

@ -13,76 +13,48 @@ type Liner interface {
Line() Line Line() Line
} }
type LinerPointContainer interface {
Liner
PointContainer
}
// The type represents a line segment. // The type represents a line segment.
type LineSegment [2]Point type LineSegment [2]Point
// The type represents multiple line segments. // The type represents multiple line segments.
type LineSegments []LineSegment type LineSegments []LineSegment
// Check whether the liner is parallel to the line. type Edge = LineSegment
func (l Line) Parallel(liner Liner) bool { type Edges []Vertex
buf := liner.Line()
// Check if two LinerPointContainers do cross and return the
// crossing point.
func LinersCross(lp1, lp2 LinerPointContainer) (Point, bool) {
l1 := lp1.Line()
l2 := lp2.Line()
if buf.K == l.K { p, crosses := l1.crossesLine(l2)
return true if !crosses ||
} !lp1.ContainsPoint(p) ||
!lp2.ContainsPoint(p) {
return false
}
func (l Line) Line() Line {
return l
}
func (l Line) ContainsPoint(p Point) bool {
buf := Line{0, p.Y}
pc, ok := l.crossesLine(buf)
if !ok {
return false
}
return pc == p
}
func (l Line) Crosses(with Liner) (Point, bool) {
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) {
if l1.Parallel(l2) {
return Point{}, false return Point{}, false
} }
x := (l1.C - l2.C) / (l2.K - l1.K) return p, true
y := l1.K*x + l1.C
return Point{x, y}, true
} }
func (l LineSegment) ContainsPoint(p Point) bool { // Check whether the liner is parallel to the other liner.
line := l.Line() func LinersParallel(first, second Liner) bool {
if !line.ContainsPoint(p) { l1 := first.Line()
return false l2 := second.Line()
}
return false return l1.K == l2.K
} }
// Get square of length of line segment. // Returns the line itself. Made to implement the Liner interface.
func (ls LineSegment) LenSqr() Float { func (l Line) Line() Line {
return Sqr(ls[0].X - ls[1].X) + return l
Sqr(ls[0].Y - ls[1].Y)
}
// Get length of the line segment.
func (ls LineSegment) Len() Float {
return math.Sqrt(ls.LenSqr())
} }
// Returns corresponding to the segment line line. // Returns corresponding to the segment line line.
@ -96,35 +68,55 @@ func (l LineSegment) Line() Line {
return Line{k, c} return Line{k, c}
} }
func (l LineSegment) Crosses(with Liner) (Point, bool) { func (l Line) ContainsPoint(p Point) bool {
switch with.(type) { buf := Line{0, p.Y}
case Line : pc, ok := l.crossesLine(buf)
return l.crossesLine(with.(Line)) if !ok {
case LineSegment : return false
return l.crossesLineSegment(with.(LineSegment))
default:
panic("The type that is not defined to be crossed")
} }
return pc == p
} }
func (l LineSegment) Contains(what any) bool { func (l LineSegment) ContainsPoint(p Point) bool {
switch what.(type) { line := l.Line()
case Point : if !line.ContainsPoint(p) {
return l.containsPoint(what.(Point)) return false
default :
panic("Unexpected type")
} }
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)
if !(xMin < p.X && p.X < xMax) ||
!(yMin < p.Y && p.Y < yMax) {
return false
}
return true
} }
func (l LineSegment) containsPoint(p Point) bool { func (l1 Line) crossesLine(l2 Line) (Point, bool) {
return false if LinersParallel(l1, l2) {
return Point{}, false
}
x := (l1.C - l2.C) / (l2.K - l1.K)
y := l1.K*x + l1.C
return Point{x, y}, true
} }
func (l LineSegment) crossesLineSegment(with LineSegment) (Point, bool) {
return Point{}, false // 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)
} }
func (l LineSegment) crossesLine(with Line) (Point, bool) { // Get length of the line segment.
return Point{}, false func (ls LineSegment) Len() Float {
return math.Sqrt(ls.LenSqr())
} }

View file

@ -30,6 +30,22 @@ func Sgn(v Float) Float {
return 0 return 0
} }
func Max(v1, v2 Float) Float {
if v1 > v2 {
return v1
}
return v2
}
func Min(v1, v2 Float) Float {
if v1 < v2 {
return v1
}
return v2
}
func RadiansToDegrees(v Float) Float { func RadiansToDegrees(v Float) Float {
return v return v
} }

View file

@ -39,7 +39,13 @@ func (r Rectangle) Vertices() Points {
} }
func (r Rectangle) Edges() LineSegments { func (r Rectangle) Edges() LineSegments {
return LineSegments{} vs := r.Vertices()
return LineSegments{
LineSegment{vs[0], vs[1]},
LineSegment{vs[1], vs[2]},
LineSegment{vs[2], vs[3]},
LineSegment{vs[4], vs[0]},
}
} }
// Get 2 triangles that the rectangle consists of. // Get 2 triangles that the rectangle consists of.

View file

@ -9,6 +9,7 @@ type Vector struct {
X, Y Float X, Y Float
} }
type Point = Vector type Point = Vector
type Vertex = Vector
type Vectors []Vector type Vectors []Vector
type Points []Point type Points []Point