...
1 package geo
2
3 import (
4 "fmt"
5 "math"
6 )
7
8 type Intersectable interface {
9 Intersections(segment Segment) []*Point
10 }
11
12 type Segment struct {
13 Start *Point
14 End *Point
15 }
16
17 func NewSegment(from, to *Point) *Segment {
18 return &Segment{from, to}
19 }
20
21 func (s Segment) Overlaps(otherS Segment, isHorizontal bool, buffer float64) bool {
22 if isHorizontal {
23 if math.Min(s.Start.Y, s.End.Y)-math.Max(otherS.Start.Y, otherS.End.Y) >= buffer {
24 return false
25 }
26 if math.Min(otherS.Start.Y, otherS.End.Y)-math.Max(s.Start.Y, s.End.Y) >= buffer {
27 return false
28 }
29 return true
30 } else {
31 if math.Min(s.Start.X, s.End.X)-math.Max(otherS.Start.X, otherS.End.X) >= buffer {
32 return false
33 }
34 if math.Min(otherS.Start.X, otherS.End.X)-math.Max(s.Start.X, s.End.X) >= buffer {
35 return false
36 }
37 return true
38 }
39 }
40
41 func (segment Segment) Intersects(otherSegment Segment) bool {
42 return IntersectionPoint(segment.Start, segment.End, otherSegment.Start, otherSegment.End) != nil
43 }
44
45
46 func (s Segment) ToString() string {
47 return fmt.Sprintf("%v -> %v", s.Start.ToString(), s.End.ToString())
48 }
49
50 func (segment Segment) Intersections(otherSegment Segment) []*Point {
51 point := IntersectionPoint(segment.Start, segment.End, otherSegment.Start, otherSegment.End)
52 if point == nil {
53 return nil
54 }
55 return []*Point{point}
56 }
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 func (segment *Segment) GetBounds(segments []*Segment, buffer float64) (float64, float64) {
82 ceil := math.Inf(1)
83 floor := math.Inf(-1)
84 if segment.Start.X == segment.End.X && segment.Start.Y == segment.End.Y {
85
86 return floor, ceil
87 }
88 isHorizontal := segment.Start.X == segment.End.X
89 for _, otherSegment := range segments {
90 if isHorizontal {
91
92 if otherSegment.End.Y < segment.Start.Y-buffer {
93 continue
94 }
95 if otherSegment.Start.Y > segment.End.Y+buffer {
96 continue
97 }
98 if otherSegment.Start.X <= segment.Start.X {
99 floor = math.Max(floor, otherSegment.Start.X)
100 }
101 if otherSegment.Start.X > segment.Start.X {
102 ceil = math.Min(ceil, otherSegment.Start.X)
103 }
104 } else {
105 if otherSegment.End.X < segment.Start.X-buffer {
106 continue
107 }
108 if otherSegment.Start.X > segment.End.X+buffer {
109 continue
110 }
111 if otherSegment.Start.Y <= segment.Start.Y {
112 floor = math.Max(floor, otherSegment.Start.Y)
113 }
114 if otherSegment.Start.Y > segment.Start.Y {
115 ceil = math.Min(ceil, otherSegment.Start.Y)
116 }
117 }
118 }
119 return floor, ceil
120 }
121
122 func (segment Segment) Length() float64 {
123 return EuclideanDistance(segment.Start.X, segment.Start.Y, segment.End.X, segment.End.Y)
124 }
125
126 func (segment Segment) ToVector() Vector {
127 return NewVector(segment.End.X-segment.Start.X, segment.End.Y-segment.Start.Y)
128 }
129
View as plain text