forked from go-spatial/geom
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathline.go
81 lines (64 loc) · 2.74 KB
/
line.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
package geom
import (
"log"
"math/big"
)
const (
// PrecisionLevelBigFloat is the precision of big floats, rounding if over
PrecisionLevelBigFloat = 20
)
// Line has exactly two points
type Line [2][2]float64
// IsVertical returns true if the `y` elements of the points that make up the line (l) are equal.
func (l Line) IsVertical() bool { return l[0][0] == l[1][0] }
// IsHorizontal returns true if the `x` elements of the points that make the line (l) are equal.
func (l Line) IsHorizontal() bool { return l[0][1] == l[1][1] }
// Point1 returns a new copy of the first point in the line.
func (l Line) Point1() *Point { return (*Point)(&l[0]) }
// Point2 returns a new copy of the second point in the line.
func (l Line) Point2() *Point { return (*Point)(&l[1]) }
func (l Line) Verticies() [][2]float64 { return l[:] }
// ContainsPoint checks to see if the given pont lines on the linesegment. (Incliding the end points.)
func (l Line) ContainsPoint(pt [2]float64) bool {
minx, maxx := l[0][0], l[1][0]
if minx > maxx {
minx, maxx = maxx, minx
}
miny, maxy := l[0][1], l[1][1]
if miny > maxy {
miny, maxy = maxy, miny
}
if debug {
log.Printf("pt.x %v is between %v and %v: %v && %v", pt[0], minx, maxx, minx <= pt[0], pt[0] <= maxx)
log.Printf("pt.y %v is between %v and %v: %v && %v", pt[1], miny, maxy, miny <= pt[1], pt[1] <= maxy)
}
return minx <= pt[0] && pt[0] <= maxx && miny <= pt[1] && pt[1] <= maxy
}
// ContainsPointBigFloat checks to see if the given point lies on the line segment. (Including the endpoints.)
func (l Line) ContainsPointBigFloat(pt [2]*big.Float) bool {
pminx, pmaxx := l[0][0], l[1][0]
if pminx > pmaxx {
pminx, pmaxx = pmaxx, pminx
}
pminy, pmaxy := l[0][1], l[1][1]
if pminy > pmaxy {
pminy, pmaxy = pmaxy, pminy
}
minx, maxx := big.NewFloat(pminx).SetPrec(PrecisionLevelBigFloat), big.NewFloat(pmaxx).SetPrec(PrecisionLevelBigFloat)
miny, maxy := big.NewFloat(pminy).SetPrec(PrecisionLevelBigFloat), big.NewFloat(pmaxy).SetPrec(PrecisionLevelBigFloat)
px, py := pt[0].SetPrec(PrecisionLevelBigFloat), pt[1].SetPrec(PrecisionLevelBigFloat)
cmpMinX, cmpMaxX := px.Cmp(minx), px.Cmp(maxx)
cmpMinY, cmpMaxY := py.Cmp(miny), py.Cmp(maxy)
goodX := (cmpMinX == 0 || cmpMinX == 1) && (cmpMaxX == 0 || cmpMaxX == -1)
goodY := (cmpMinY == 0 || cmpMinY == 1) && (cmpMaxY == 0 || cmpMaxY == -1)
if debug {
log.Printf("pt.x %v is between %v and %v: %v ,%v : %v", px, minx, maxx, cmpMinX, cmpMaxX, goodX)
log.Printf("pt.y %v is between %v and %v: %v ,%v : %v", py, miny, maxy, cmpMinY, cmpMaxY, goodY)
}
return goodX && goodY
}
// LengthSqured returns the length of the segment squared
func (l Line) LengthSquared() float64 {
deltax, deltay := l[1][0]-l[0][0], l[1][1]-l[0][1]
return (deltax * deltax) + (deltay * deltay)
}