comparison pkg/octree/polygon.go @ 2490:c9164ff98871 octree-diff

Started with point in polygon check.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sun, 03 Mar 2019 21:10:07 +0100
parents 4f292ff74d9e
children 10681749371d
comparison
equal deleted inserted replaced
2489:4f292ff74d9e 2490:c9164ff98871
20 "math" 20 "math"
21 21
22 "gemma.intevation.de/gemma/pkg/wkb" 22 "gemma.intevation.de/gemma/pkg/wkb"
23 ) 23 )
24 24
25 type ring []float64
26
25 type Polygon struct { 27 type Polygon struct {
26 // TODO: Implement me! 28 // TODO: Implement me!
27 rings [][]float64 29 rings []ring
28 } 30 }
29 31
30 type IntersectionType byte 32 type IntersectionType byte
31 33
32 const ( 34 const (
41 } 43 }
42 44
43 func (p *Polygon) IntersectionWithTriangle(t *Triangle) IntersectionType { 45 func (p *Polygon) IntersectionWithTriangle(t *Triangle) IntersectionType {
44 // TODO: Implement me 46 // TODO: Implement me
45 return IntersectionOutSide 47 return IntersectionOutSide
48 }
49
50 func (rng ring) isClosed() bool { return (len(rng) / 2) >= 3 }
51
52 func (rng ring) contains(point []float64) bool {
53 if !rng.isClosed() {
54 return false
55 }
56
57 contains := intersectsWithRaycast(point, rng[:2], rng[len(rng)-2:len(rng)])
58
59 for i := 2; i < len(rng); i += 2 {
60 if intersectsWithRaycast(point, rng[i-2:i], rng[i:i+2]) {
61 contains = !contains
62 }
63 }
64
65 return contains
66 }
67
68 // Using the raycast algorithm, this returns whether or not the passed in point
69 // Intersects with the edge drawn by the passed in start and end points.
70 // Original implementation: http://rosettacode.org/wiki/Ray-casting_algorithm#Go
71 func intersectsWithRaycast(point, start, end []float64) bool {
72
73 // Always ensure that the the first point
74 // has a y coordinate that is less than the second point
75 if start[1] > end[1] {
76 // Switch the points if otherwise.
77 start, end = end, start
78 }
79
80 // Move the point's y coordinate
81 // outside of the bounds of the testing region
82 // so we can start drawing a ray
83 for point[1] == start[1] || point[1] == end[1] {
84 y := math.Nextafter(point[1], math.Inf(1))
85 point = []float64{point[0], y}
86 }
87
88 // If we are outside of the polygon, indicate so.
89 if point[1] < start[1] || point[1] > end[1] {
90 return false
91 }
92
93 if start[0] > end[0] {
94 if point[0] > start[0] {
95 return false
96 }
97 if point[0] < end[0] {
98 return true
99 }
100 } else {
101 if point[0] > end[0] {
102 return false
103 }
104 if point[0] < start[0] {
105 return true
106 }
107 }
108
109 raySlope := (point[1] - start[1]) / (point[0] - start[0])
110 diagSlope := (end[1] - start[1]) / (end[0] - start[0])
111
112 return raySlope >= diagSlope
46 } 113 }
47 114
48 func (p *Polygon) FromWKB(data []byte) error { 115 func (p *Polygon) FromWKB(data []byte) error {
49 116
50 r := bytes.NewReader(data) 117 r := bytes.NewReader(data)
77 var numRings uint32 144 var numRings uint32
78 if err = binary.Read(r, order, &numRings); err != nil { 145 if err = binary.Read(r, order, &numRings); err != nil {
79 return err 146 return err
80 } 147 }
81 148
82 rings := make([][]float64, numRings) 149 rngs := make([]ring, numRings)
83 150
84 for ring := uint32(0); ring < numRings; ring++ { 151 for rng := uint32(0); rng < numRings; rng++ {
85 var numVertices uint32 152 var numVertices uint32
86 if err = binary.Read(r, order, &numVertices); err != nil { 153 if err = binary.Read(r, order, &numVertices); err != nil {
87 return err 154 return err
88 } 155 }
89 156
90 vertices := make([]float64, 2*numVertices) 157 numVertices *= 2
158 vertices := make([]float64, numVertices)
91 159
92 for v := uint32(0); v < numVertices; v++ { 160 for v := uint32(0); v < numVertices; v += 2 {
93 var lat, lon uint64 161 var lat, lon uint64
94 if err = binary.Read(r, order, &lat); err != nil { 162 if err = binary.Read(r, order, &lat); err != nil {
95 return err 163 return err
96 } 164 }
97 if err = binary.Read(r, order, &lon); err != nil { 165 if err = binary.Read(r, order, &lon); err != nil {
98 return err 166 return err
99 } 167 }
100 vertices[v*2] = math.Float64frombits(lat) 168 vertices[v] = math.Float64frombits(lat)
101 vertices[v*2+1] = math.Float64frombits(lon) 169 vertices[v+1] = math.Float64frombits(lon)
102 } 170 }
103 171
104 rings[ring] = vertices 172 rngs[rng] = vertices
105 } 173 }
106 174
107 p.rings = rings 175 p.rings = rngs
108 176
109 return nil 177 return nil
110 } 178 }