1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package s2
16
17 import (
18 "sort"
19
20 "github.com/golang/geo/r2"
21 )
22
23
24
25
26
27
28
29
30
31 type CrossingEdgeQuery struct {
32 index *ShapeIndex
33
34
35 a, b r2.Point
36 iter *ShapeIndexIterator
37
38
39 cells []*ShapeIndexCell
40 }
41
42
43 func NewCrossingEdgeQuery(index *ShapeIndex) *CrossingEdgeQuery {
44 c := &CrossingEdgeQuery{
45 index: index,
46 iter: index.Iterator(),
47 }
48 return c
49 }
50
51
52
53
54
55 func (c *CrossingEdgeQuery) Crossings(a, b Point, shape Shape, crossType CrossingType) []int {
56 edges := c.candidates(a, b, shape)
57 if len(edges) == 0 {
58 return nil
59 }
60
61 crosser := NewEdgeCrosser(a, b)
62 out := 0
63 n := len(edges)
64
65 for in := 0; in < n; in++ {
66 b := shape.Edge(edges[in])
67 sign := crosser.CrossingSign(b.V0, b.V1)
68 if crossType == CrossingTypeAll && (sign == MaybeCross || sign == Cross) || crossType != CrossingTypeAll && sign == Cross {
69 edges[out] = edges[in]
70 out++
71 }
72 }
73
74 if out < n {
75 edges = edges[0:out]
76 }
77 return edges
78 }
79
80
81 type EdgeMap map[Shape][]int
82
83
84
85
86
87
88
89
90 func (c *CrossingEdgeQuery) CrossingsEdgeMap(a, b Point, crossType CrossingType) EdgeMap {
91 edgeMap := c.candidatesEdgeMap(a, b)
92 if len(edgeMap) == 0 {
93 return nil
94 }
95
96 crosser := NewEdgeCrosser(a, b)
97 for shape, edges := range edgeMap {
98 out := 0
99 n := len(edges)
100 for in := 0; in < n; in++ {
101 edge := shape.Edge(edges[in])
102 sign := crosser.CrossingSign(edge.V0, edge.V1)
103 if (crossType == CrossingTypeAll && (sign == MaybeCross || sign == Cross)) || (crossType != CrossingTypeAll && sign == Cross) {
104 edgeMap[shape][out] = edges[in]
105 out++
106 }
107 }
108
109 if out == 0 {
110 delete(edgeMap, shape)
111 } else {
112 if out < n {
113 edgeMap[shape] = edgeMap[shape][0:out]
114 }
115 }
116 }
117 return edgeMap
118 }
119
120
121
122 func (c *CrossingEdgeQuery) candidates(a, b Point, shape Shape) []int {
123 var edges []int
124
125
126
127 const maxBruteForceEdges = 27
128 maxEdges := shape.NumEdges()
129 if maxEdges <= maxBruteForceEdges {
130 edges = make([]int, maxEdges)
131 for i := 0; i < maxEdges; i++ {
132 edges[i] = i
133 }
134 return edges
135 }
136
137
138 c.getCellsForEdge(a, b)
139 if len(c.cells) == 0 {
140 return nil
141 }
142
143
144
145
146 var shapeID int32
147 for k, v := range c.index.shapes {
148 if v == shape {
149 shapeID = k
150 }
151 }
152
153 for _, cell := range c.cells {
154 if cell == nil {
155 continue
156 }
157 clipped := cell.findByShapeID(shapeID)
158 if clipped == nil {
159 continue
160 }
161 edges = append(edges, clipped.edges...)
162 }
163
164 if len(c.cells) > 1 {
165 edges = uniqueInts(edges)
166 }
167
168 return edges
169 }
170
171
172 func uniqueInts(in []int) []int {
173 var edges []int
174 m := make(map[int]bool)
175 for _, i := range in {
176 if m[i] {
177 continue
178 }
179 m[i] = true
180 edges = append(edges, i)
181 }
182 sort.Ints(edges)
183 return edges
184 }
185
186
187
188
189
190
191 func (c *CrossingEdgeQuery) candidatesEdgeMap(a, b Point) EdgeMap {
192 edgeMap := make(EdgeMap)
193
194
195
196 if len(c.index.shapes) == 1 {
197
198
199
200 shape := c.index.Shape(0)
201
202
203
204 edgeMap[shape] = c.candidates(a, b, shape)
205 return edgeMap
206 }
207
208
209 c.getCellsForEdge(a, b)
210 if len(c.cells) == 0 {
211 return edgeMap
212 }
213
214
215 for _, cell := range c.cells {
216 for _, clipped := range cell.shapes {
217 s := c.index.Shape(clipped.shapeID)
218 for j := 0; j < clipped.numEdges(); j++ {
219 edgeMap[s] = append(edgeMap[s], clipped.edges[j])
220 }
221 }
222 }
223
224 if len(c.cells) > 1 {
225 for s, edges := range edgeMap {
226 edgeMap[s] = uniqueInts(edges)
227 }
228 }
229
230 return edgeMap
231 }
232
233
234
235 func (c *CrossingEdgeQuery) getCells(a, b Point, root *PaddedCell) []*ShapeIndexCell {
236 aUV, bUV, ok := ClipToFace(a, b, root.id.Face())
237 if ok {
238 c.a = aUV
239 c.b = bUV
240 edgeBound := r2.RectFromPoints(c.a, c.b)
241 if root.Bound().Intersects(edgeBound) {
242 c.computeCellsIntersected(root, edgeBound)
243 }
244 }
245
246 if len(c.cells) == 0 {
247 return nil
248 }
249
250 return c.cells
251 }
252
253
254 func (c *CrossingEdgeQuery) getCellsForEdge(a, b Point) {
255 c.cells = nil
256
257 segments := FaceSegments(a, b)
258 for _, segment := range segments {
259 c.a = segment.a
260 c.b = segment.b
261
262
263
264
265
266 edgeBound := r2.RectFromPoints(c.a, c.b)
267 pcell := PaddedCellFromCellID(CellIDFromFace(segment.face), 0)
268 edgeRoot := pcell.ShrinkToFit(edgeBound)
269
270
271
272
273
274
275
276
277
278
279 relation := c.iter.LocateCellID(edgeRoot)
280 if relation == Indexed {
281
282 c.cells = append(c.cells, c.iter.IndexCell())
283 } else if relation == Subdivided {
284
285
286 if !edgeRoot.isFace() {
287 pcell = PaddedCellFromCellID(edgeRoot, 0)
288 }
289 c.computeCellsIntersected(pcell, edgeBound)
290 }
291 }
292 }
293
294
295
296 func (c *CrossingEdgeQuery) computeCellsIntersected(pcell *PaddedCell, edgeBound r2.Rect) {
297
298 c.iter.seek(pcell.id.RangeMin())
299 if c.iter.Done() || c.iter.CellID() > pcell.id.RangeMax() {
300
301 return
302 }
303 if c.iter.CellID() == pcell.id {
304
305 c.cells = append(c.cells, c.iter.IndexCell())
306 return
307 }
308
309
310 center := pcell.Middle().Lo()
311
312 if edgeBound.X.Hi < center.X {
313
314 c.clipVAxis(edgeBound, center.Y, 0, pcell)
315 return
316 } else if edgeBound.X.Lo >= center.X {
317
318 c.clipVAxis(edgeBound, center.Y, 1, pcell)
319 return
320 }
321
322 childBounds := c.splitUBound(edgeBound, center.X)
323 if edgeBound.Y.Hi < center.Y {
324
325 c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, 0, 0), childBounds[0])
326 c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, 1, 0), childBounds[1])
327 } else if edgeBound.Y.Lo >= center.Y {
328
329 c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, 0, 1), childBounds[0])
330 c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, 1, 1), childBounds[1])
331 } else {
332
333
334 c.clipVAxis(childBounds[0], center.Y, 0, pcell)
335 c.clipVAxis(childBounds[1], center.Y, 1, pcell)
336 }
337 }
338
339
340
341
342
343
344 func (c *CrossingEdgeQuery) clipVAxis(edgeBound r2.Rect, center float64, i int, pcell *PaddedCell) {
345 if edgeBound.Y.Hi < center {
346
347 c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, i, 0), edgeBound)
348 } else if edgeBound.Y.Lo >= center {
349
350 c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, i, 1), edgeBound)
351 } else {
352
353 childBounds := c.splitVBound(edgeBound, center)
354 c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, i, 0), childBounds[0])
355 c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, i, 1), childBounds[1])
356 }
357 }
358
359
360
361 func (c *CrossingEdgeQuery) splitUBound(edgeBound r2.Rect, u float64) [2]r2.Rect {
362 v := edgeBound.Y.ClampPoint(interpolateFloat64(u, c.a.X, c.b.X, c.a.Y, c.b.Y))
363
364
365 var diag int
366 if (c.a.X > c.b.X) != (c.a.Y > c.b.Y) {
367 diag = 1
368 }
369 return splitBound(edgeBound, 0, diag, u, v)
370 }
371
372
373
374 func (c *CrossingEdgeQuery) splitVBound(edgeBound r2.Rect, v float64) [2]r2.Rect {
375 u := edgeBound.X.ClampPoint(interpolateFloat64(v, c.a.Y, c.b.Y, c.a.X, c.b.X))
376 var diag int
377 if (c.a.X > c.b.X) != (c.a.Y > c.b.Y) {
378 diag = 1
379 }
380 return splitBound(edgeBound, diag, 0, u, v)
381 }
382
383
384
385
386 func splitBound(edgeBound r2.Rect, uEnd, vEnd int, u, v float64) [2]r2.Rect {
387 var childBounds = [2]r2.Rect{
388 edgeBound,
389 edgeBound,
390 }
391
392 if uEnd == 1 {
393 childBounds[0].X.Lo = u
394 childBounds[1].X.Hi = u
395 } else {
396 childBounds[0].X.Hi = u
397 childBounds[1].X.Lo = u
398 }
399
400 if vEnd == 1 {
401 childBounds[0].Y.Lo = v
402 childBounds[1].Y.Hi = v
403 } else {
404 childBounds[0].Y.Hi = v
405 childBounds[1].Y.Lo = v
406 }
407
408 return childBounds
409 }
410
View as plain text