comparison pkg/octree/polygon.go @ 4764:5c80a33edd44

Fixed handling of none-closed polygons in containment test.
author Sascha L. Teichmann <teichmann@intevation.de>
date Sat, 19 Oct 2019 19:40:51 +0200
parents 1137c5a18242
children db6c2955ee31
comparison
equal deleted inserted replaced
4763:d786c37b02c0 4764:5c80a33edd44
339 return IntersectionInside 339 return IntersectionInside
340 } 340 }
341 return IntersectionOutSide 341 return IntersectionOutSide
342 } 342 }
343 343
344 func (rng ring) closed() bool {
345 return (len(rng) / 2) >= 3
346 }
347
348 func (rng ring) length() int { 344 func (rng ring) length() int {
349 return len(rng) / 2 345 return len(rng) / 2
350 } 346 }
351 347
352 func (rng ring) point(i int) (float64, float64) { 348 func (rng ring) point(i int) (float64, float64) {
353 i *= 2 349 i *= 2
354 return rng[i], rng[i+1] 350 return rng[i], rng[i+1]
355 } 351 }
356 352
357 type segments interface { 353 type segments interface {
358 closed() bool
359 length() int 354 length() int
360 point(int) (float64, float64) 355 point(int) (float64, float64)
361 } 356 }
362 357
363 func contains(s segments, pX, pY float64) bool { 358 func contains(s segments, pX, pY float64) bool {
364 if !s.closed() {
365 return false
366 }
367 359
368 n := s.length() 360 n := s.length()
361 if n < 3 {
362 return false
363 }
369 364
370 sX, sY := s.point(0) 365 sX, sY := s.point(0)
371 eX, eY := s.point(n - 1) 366 eX, eY := s.point(n - 1)
372 367
373 contains := intersectsWithRaycast(pX, pY, sX, sY, eX, eY) 368 const eps = 0.0000001
369
370 if math.Abs(sX-eX) > eps && math.Abs(sY-eY) > eps {
371 // It's not closed!
372 return false
373 }
374
375 var inside bool
374 376
375 for i := 1; i < n; i++ { 377 for i := 1; i < n; i++ {
376 sX, sY := s.point(i - 1)
377 eX, eY := s.point(i) 378 eX, eY := s.point(i)
378 if intersectsWithRaycast(pX, pY, sX, sY, eX, eY) { 379 if intersectsWithRaycast(pX, pY, sX, sY, eX, eY) {
379 contains = !contains 380 inside = !inside
380 } 381 }
381 } 382 sX, sY = eX, eY
382 383 }
383 return contains 384
385 return inside
384 } 386 }
385 387
386 // Using the raycast algorithm, this returns whether or not the passed in point 388 // Using the raycast algorithm, this returns whether or not the passed in point
387 // Intersects with the edge drawn by the passed in start and end points. 389 // Intersects with the edge drawn by the passed in start and end points.
388 // Original implementation: http://rosettacode.org/wiki/Ray-casting_algorithm#Go 390 // Original implementation: http://rosettacode.org/wiki/Ray-casting_algorithm#Go