tile38/vendor/github.com/tidwall/geojson/geometry/ring_test.go

1388 lines
52 KiB
Go

// Copyright 2018 Joshua J Baker. All rights reserved.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package geometry
import (
"fmt"
"testing"
)
func newRingXSimple(points []Point) Ring {
ring := newRing(points, DefaultIndexOptions)
if ring.(*baseSeries).Index() != nil {
ring.(*baseSeries).clearIndex()
}
return ring
}
func newRingXIndexed(points []Point) Ring {
ring := newRing(points, DefaultIndexOptions)
if ring.(*baseSeries).Index() == nil {
ring.(*baseSeries).buildIndex()
}
return ring
}
func testDualRingX(t *testing.T, points []Point, do func(t *testing.T, ring Ring)) {
t.Run("index", func(t *testing.T) {
do(t, newRingXSimple(points))
})
t.Run("noindex", func(t *testing.T) {
do(t, newRingXIndexed(points))
})
}
func TestRectGeometryDefaults(t *testing.T) {
g := Geometry(Rect{})
expect(t, !g.Empty())
expect(t, g.Rect() == R(0, 0, 0, 0))
expect(t, !g.ContainsLine(nil))
expect(t, !g.ContainsLine(&Line{}))
expect(t, g.ContainsPoint(Point{}))
expect(t, !g.ContainsPoly(nil))
expect(t, !g.ContainsPoly(&Poly{}))
expect(t, g.ContainsRect(Rect{}))
expect(t, !g.IntersectsLine(nil))
expect(t, !g.IntersectsLine(&Line{}))
expect(t, g.IntersectsPoint(Point{}))
expect(t, !g.IntersectsPoly(nil))
expect(t, !g.IntersectsPoly(&Poly{}))
expect(t, g.IntersectsRect(Rect{}))
}
func TestRingXContainsPoint(t *testing.T) {
testDualRingX(t, octagon, func(t *testing.T, ring Ring) {
expect(t, !ringContainsPoint(ring, P(0, 0), true).hit)
expect(t, ringContainsPoint(ring, P(0, 5), true).hit)
expect(t, !ringContainsPoint(ring, P(0, 5), false).hit)
expect(t, ringContainsPoint(ring, P(4, 4), true).hit)
expect(t, !ringContainsPoint(ring, P(1.4, 1.4), true).hit)
expect(t, ringContainsPoint(ring, P(1.5, 1.5), true).hit)
expect(t, !ringContainsPoint(ring, P(1.5, 1.5), false).hit)
})
shape := []Point{
P(0, 0), P(4, 0), P(4, 3),
P(3, 4), P(1, 4),
P(0, 3), P(0, 0),
}
ring := newRing(shape, DefaultIndexOptions)
expect(t, !ringContainsPoint(ring, P(0, 3.5), true).hit)
expect(t, !ringContainsPoint(ring, P(0.4, 3.5), true).hit)
expect(t, ringContainsPoint(ring, P(0.5, 3.5), true).hit)
expect(t, ringContainsPoint(ring, P(0.6, 3.5), true).hit)
expect(t, ringContainsPoint(ring, P(1, 3.5), true).hit)
expect(t, ringContainsPoint(ring, P(3, 3.5), true).hit)
expect(t, ringContainsPoint(ring, P(3.4, 3.5), true).hit)
expect(t, ringContainsPoint(ring, P(3.5, 3.5), true).hit)
expect(t, !ringContainsPoint(ring, P(3.9, 3.5), true).hit)
expect(t, !ringContainsPoint(ring, P(4, 3.5), true).hit)
expect(t, !ringContainsPoint(ring, P(4.1, 3.5), true).hit)
}
func TestRingXIntersectsPoint(t *testing.T) {
testDualRingX(t, octagon, func(t *testing.T, ring Ring) {
expect(t, !ringIntersectsPoint(ring, P(0, 0), true).hit)
expect(t, ringIntersectsPoint(ring, P(0, 5), true).hit)
expect(t, !ringIntersectsPoint(ring, P(0, 5), false).hit)
expect(t, ringIntersectsPoint(ring, P(4, 4), true).hit)
expect(t, !ringIntersectsPoint(ring, P(1.4, 1.4), true).hit)
expect(t, ringIntersectsPoint(ring, P(1.5, 1.5), true).hit)
expect(t, !ringIntersectsPoint(ring, P(1.5, 1.5), false).hit)
})
}
func TestRingXIntersectsSegment(t *testing.T) {
t.Run("Cases", func(t *testing.T) {
ring := newRing([]Point{
P(0, 0), P(4, 0), P(4, 4), P(0, 4), P(0, 0),
}, DefaultIndexOptions)
t.Run("1", func(t *testing.T) {
expect(t, ringIntersectsSegment(ring, S(2, 2, 4, 4), true))
expect(t, ringIntersectsSegment(ring, S(2, 2, 4, 4), false))
})
t.Run("2", func(t *testing.T) {
expect(t, ringIntersectsSegment(ring, S(2, 0, 4, 2), true))
expect(t, ringIntersectsSegment(ring, S(2, 0, 4, 2), false))
})
t.Run("3", func(t *testing.T) {
expect(t, ringIntersectsSegment(ring, S(1, 0, 3, 0), true))
expect(t, !ringIntersectsSegment(ring, S(1, 0, 3, 0), false))
})
t.Run("4", func(t *testing.T) {
expect(t, ringIntersectsSegment(ring, S(2, 4, 2, 0), true))
expect(t, ringIntersectsSegment(ring, S(2, 4, 2, 0), false))
})
t.Run("5", func(t *testing.T) {
expect(t, ringIntersectsSegment(ring, S(2, 0, 2, -3), true))
expect(t, !ringIntersectsSegment(ring, S(2, 0, 2, -3), false))
})
t.Run("6", func(t *testing.T) {
expect(t, !ringIntersectsSegment(ring, S(2, -1, 2, -3), true))
expect(t, !ringIntersectsSegment(ring, S(2, -1, 2, -3), false))
})
t.Run("7", func(t *testing.T) {
expect(t, ringIntersectsSegment(ring, S(-1, 2, 3, 2), true))
expect(t, ringIntersectsSegment(ring, S(-1, 2, 3, 2), false))
})
t.Run("8", func(t *testing.T) {
expect(t, ringIntersectsSegment(ring, S(-1, 3, 2, 1), true))
expect(t, ringIntersectsSegment(ring, S(-1, 3, 2, 1), false))
})
t.Run("9", func(t *testing.T) {
expect(t, ringIntersectsSegment(ring, S(-1, 2, 5, 1), true))
expect(t, ringIntersectsSegment(ring, S(-1, 2, 5, 1), false))
})
t.Run("10", func(t *testing.T) {
expect(t, ringIntersectsSegment(ring, S(2, 5, 1, -1), true))
expect(t, ringIntersectsSegment(ring, S(2, 5, 1, -1), false))
})
t.Run("11", func(t *testing.T) {
expect(t, ringIntersectsSegment(ring, S(0, 4, 4, 0), true))
expect(t, ringIntersectsSegment(ring, S(0, 4, 4, 0), false))
})
t.Run("12", func(t *testing.T) {
ring := newRing([]Point{
{0, 0}, {2, 0}, {4, 0}, {4, 4}, {0, 4}, {0, 0},
}, DefaultIndexOptions)
expect(t, ringIntersectsSegment(ring, S(1, 0, 3, 0), true))
expect(t, !ringIntersectsSegment(ring, S(1, 0, 3, 0), false))
})
t.Run("13", func(t *testing.T) {
ring := newRing([]Point{
{0, 0}, {4, 0}, {4, 4}, {2, 4}, {0, 4}, {0, 0},
}, DefaultIndexOptions)
expect(t, ringIntersectsSegment(ring, S(0, 4, 4, 4), true))
expect(t, !ringIntersectsSegment(ring, S(0, 4, 4, 4), false))
})
t.Run("14", func(t *testing.T) {
ring := newRing([]Point{
{0, 0}, {4, 0}, {4, 4}, {2, 4}, {0, 4}, {0, 0},
}, DefaultIndexOptions)
expect(t, ringIntersectsSegment(ring, S(-1, -2, 0, 0), true))
expect(t, !ringIntersectsSegment(ring, S(-1, -2, 0, 0), false))
})
t.Run("15", func(t *testing.T) {
ring := newRing([]Point{
{0, 0}, {4, 0}, {4, 4}, {2, 4}, {0, 4}, {0, 0},
}, DefaultIndexOptions)
expect(t, ringIntersectsSegment(ring, S(0, 4, 5, 4), true))
expect(t, !ringIntersectsSegment(ring, S(0, 4, 5, 4), false))
})
t.Run("16", func(t *testing.T) {
ring := newRing([]Point{
{0, 0}, {4, 0}, {4, 4}, {2, 4}, {0, 4}, {0, 0},
}, DefaultIndexOptions)
expect(t, ringIntersectsSegment(ring, S(1, 4, 5, 4), true))
expect(t, !ringIntersectsSegment(ring, S(1, 4, 5, 4), false))
})
t.Run("17", func(t *testing.T) {
ring := newRing([]Point{
{0, 0}, {4, 0}, {4, 4}, {2, 4}, {0, 4}, {0, 0},
}, DefaultIndexOptions)
expect(t, ringIntersectsSegment(ring, S(1, 4, 4, 4), true))
expect(t, !ringIntersectsSegment(ring, S(1, 4, 4, 4), false))
})
})
// convex shape
t.Run("Octagon", func(t *testing.T) {
shape := octagon
t.Run("Outside", func(t *testing.T) {
// test coming off of the edges
segs := []Segment{
S(0, 5, -5, 5).Move(-1, 0), // left
S(1.5, 1.5, -3.5, -3.5).Move(-1, -1), // bottom-left corner
S(5, 0, 5, -5).Move(0, -1), // bottom
S(8.5, 1.5, 13.5, -3.5).Move(1, -1), // bottom-right corner
S(10, 5, 15, 5).Move(1, 0), // right
S(8.5, 8.5, 13.5, 13.5).Move(1, 1), // top-right corner
S(5, 10, 5, 15).Move(0, 5), // top
S(1.5, 8.5, -3.5, 13.5).Move(-1, 1), // top-left corner
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, !ringIntersectsSegment(ring, seg, true))
expect(t, !ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, !ringIntersectsSegment(ring, seg, true))
expect(t, !ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("OutsideEdgeTouch", func(t *testing.T) {
// test coming off of the edges
segs := []Segment{
S(0, 5, -5, 5), // left
S(1.5, 1.5, -3.5, -3.5), // bottom-left corner
S(5, 0, 5, -5), // bottom
S(8.5, 1.5, 13.5, -3.5), // bottom-right corner
S(10, 5, 15, 5), // right
S(8.5, 8.5, 13.5, 13.5), // top-right corner
S(5, 10, 5, 15), // top
S(1.5, 8.5, -3.5, 13.5), // top-left corner
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, !ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, !ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("EdgeCross", func(t *testing.T) {
segs := []Segment{
S(0, 5, -5, 5).Move(2.5, 0), // left
S(1.5, 1.5, -3.5, -3.5).Move(2.5, 2.5), // bottom-left corner
S(5, 0, 5, -5).Move(0, 2.5), // bottom
S(8.5, 1.5, 13.5, -3.5).Move(-2.5, 2.5), // bottom-right corner
S(10, 5, 15, 5).Move(-2.5, 0), // right
S(8.5, 8.5, 13.5, 13.5).Move(-2.5, -2.5), // top-right corner
S(5, 10, 5, 15).Move(0, -2.5), // top
S(1.5, 8.5, -3.5, 13.5).Move(2.5, -2.5), // top-left corner
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("InsideEdgeTouch", func(t *testing.T) {
segs := []Segment{
S(0, 5, -5, 5).Move(5, 0), // left
S(1.5, 1.5, -3.5, -3.5).Move(5, 5), // bottom-left corner
S(5, 0, 5, -5).Move(0, 5), // bottom
S(8.5, 1.5, 13.5, -3.5).Move(-5, 5), // bottom-right corner
S(10, 5, 15, 5).Move(-5, 0), // right
S(8.5, 8.5, 13.5, 13.5).Move(-5, -5), // top-right corner
S(5, 10, 5, 15).Move(0, -5), // top
S(1.5, 8.5, -3.5, 13.5).Move(5, -5), // top-left corner
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("Inside", func(t *testing.T) {
segs := []Segment{
S(0, 5, -5, 5).Move(6, 0), // left
S(1.5, 1.5, -3.5, -3.5).Move(6, 6), // bottom-left corner
S(5, 0, 5, -5).Move(0, 6), // bottom
S(8.5, 1.5, 13.5, -3.5).Move(-6, 6), // bottom-right corner
S(10, 5, 15, 5).Move(-6, 0), // right
S(8.5, 8.5, 13.5, 13.5).Move(-6, -6), // top-right corner
S(5, 10, 5, 15).Move(0, -6), // top
S(1.5, 8.5, -3.5, 13.5).Move(6, -6), // top-left corner
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("InsideEdgeToEdge", func(t *testing.T) {
segs := []Segment{
S(0, 5, 10, 5), // left to right
S(1.5, 1.5, 8.5, 8.5), // bottom-left to top-right
S(5, 0, 5, 10), // bottom to top
S(8.5, 1.5, 1.5, 8.5), // bottom-right to top-left
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("PassoverEdgeToEdge", func(t *testing.T) {
segs := []Segment{
S(-1, 5, 11, 5), // left to right
S(0.5, 0.5, 9.5, 9.5), // bottom-left to top-right
S(5, -1, 5, 11), // bottom to top
S(9.5, 0.5, 0.5, 9.5), // bottom-right to top-left
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
})
})
}
})
})
// concave shape
t.Run("Concave", func(t *testing.T) {
shape := concave1
t.Run("Outside", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, -5, 7.5).Move(-1, 0), // left
S(2.5, 5, 2.5, 0).Move(0, -1), // bottom-left-1
S(5, 2.5, 0, 2.5).Move(-1, 0), // bottom-left-2
S(7.5, 0, 7.5, -5).Move(0, -1), // bottom
S(10, 5, 15, 5).Move(1, 0), // right
S(5, 10, 5, 15).Move(0, 1), // top
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, !ringIntersectsSegment(ring, seg, true))
expect(t, !ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, !ringIntersectsSegment(ring, seg, true))
expect(t, !ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("OutsideEdgeTouch", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, -5, 7.5), // left
S(2.5, 5, 2.5, 0), // bottom-left-1
S(5, 2.5, 0, 2.5), // bottom-left-2
S(7.5, 0, 7.5, -5), // bottom
S(10, 5, 15, 5), // right
S(5, 10, 5, 15), // top
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, !ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, !ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("EdgeCross", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, -5, 7.5).Move(2.5, 0), // left
S(2.5, 5, 2.5, 0).Move(0, 2.5), // bottom-left-1
S(5, 2.5, 0, 2.5).Move(2.5, 0), // bottom-left-2
S(7.5, 0, 7.5, -5).Move(0, 2.5), // bottom
S(10, 5, 15, 5).Move(-2.5, 0), // right
S(5, 10, 5, 15).Move(0, -2.5), // top
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("InsideEdgeTouch", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, -3, 7.5).Move(3, 0), // 0:left
S(2.5, 5, 2.5, 2).Move(0, 3), // 1:bottom-left-1
S(5, 2.5, 2, 2.5).Move(3, 0), // 2:bottom-left-2
S(7.5, 0, 7.5, -3).Move(0, 3), // 3:bottom
S(10, 5, 13, 5).Move(-3, 0), // 4:right
S(5, 10, 5, 13).Move(0, -3), // 5:top
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("Inside", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, -3, 7.5).Move(4, 0), // 0:left
S(2.5, 5, 2.5, 2).Move(0, 4), // 1:bottom-left-1
S(5, 2.5, 2, 2.5).Move(4, 0), // 2:bottom-left-2
S(7.5, 0, 7.5, -3).Move(0, 4), // 3:bottom
S(10, 5, 13, 5).Move(-4, 0), // 4:right
S(5, 10, 5, 13).Move(0, -4), // 5:top
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("InsideEdgeToEdge", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, 10, 7.5), // 0:left
S(2.5, 5, 2.5, 10), // 1:bottom-left-1
S(5, 2.5, 10, 2.5), // 2:bottom-left-2
S(7.5, 0, 7.5, 10), // 3:bottom
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
})
})
}
})
t.Run("PassoverEdgeToEdge", func(t *testing.T) {
segs := []Segment{
S(-1, 7.5, 11, 7.5), // 0:left
S(2.5, 4, 2.5, 11), // 1:bottom-left-1
S(4, 2.5, 11, 2.5), // 2:bottom-left-2
S(7.5, -1, 7.5, 11), // 3:bottom
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringIntersectsSegment(ring, seg, true))
expect(t, ringIntersectsSegment(ring, seg, false))
})
})
}
})
})
}
func TestRingXContainsSegment(t *testing.T) {
expect(t, ringContainsSegment(R(0, 0, 10, 10), S(5, 5, 5, 5), true))
expect(t, ringContainsSegment(R(0, 0, 10, 10), S(5, 5, 5, 5), false))
expect(t, ringContainsSegment(R(0, 0, 10, 10), S(0, 0, 0, 0), true))
expect(t, !ringContainsSegment(R(0, 0, 10, 10), S(0, 0, 0, 0), false))
expect(t, ringContainsSegment(R(0, 0, 10, 10), S(10, 10, 10, 10), true))
expect(t, !ringContainsSegment(R(0, 0, 10, 10), S(10, 10, 10, 10), false))
// convex shape
t.Run("Octagon", func(t *testing.T) {
shape := octagon
t.Run("Outside", func(t *testing.T) {
// test coming off of the edges
segs := []Segment{
S(0, 5, -5, 5).Move(-1, 0), // left
S(1.5, 1.5, -3.5, -3.5).Move(-1, -1), // bottom-left corner
S(5, 0, 5, -5).Move(0, -1), // bottom
S(8.5, 1.5, 13.5, -3.5).Move(1, -1), // bottom-right corner
S(10, 5, 15, 5).Move(1, 0), // right
S(8.5, 8.5, 13.5, 13.5).Move(1, 1), // top-right corner
S(5, 10, 5, 15).Move(0, 5), // top
S(1.5, 8.5, -3.5, 13.5).Move(-1, 1), // top-left corner
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("OutsideEdgeTouch", func(t *testing.T) {
// test coming off of the edges
segs := []Segment{
S(0, 5, -5, 5), // left
S(1.5, 1.5, -3.5, -3.5), // bottom-left corner
S(5, 0, 5, -5), // bottom
S(8.5, 1.5, 13.5, -3.5), // bottom-right corner
S(10, 5, 15, 5), // right
S(8.5, 8.5, 13.5, 13.5), // top-right corner
S(5, 10, 5, 15), // top
S(1.5, 8.5, -3.5, 13.5), // top-left corner
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("EdgeCross", func(t *testing.T) {
segs := []Segment{
S(0, 5, -5, 5).Move(2.5, 0), // left
S(1.5, 1.5, -3.5, -3.5).Move(2.5, 2.5), // bottom-left corner
S(5, 0, 5, -5).Move(0, 2.5), // bottom
S(8.5, 1.5, 13.5, -3.5).Move(-2.5, 2.5), // bottom-right corner
S(10, 5, 15, 5).Move(-2.5, 0), // right
S(8.5, 8.5, 13.5, 13.5).Move(-2.5, -2.5), // top-right corner
S(5, 10, 5, 15).Move(0, -2.5), // top
S(1.5, 8.5, -3.5, 13.5).Move(2.5, -2.5), // top-left corner
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("InsideEdgeTouch", func(t *testing.T) {
segs := []Segment{
S(0, 5, -5, 5).Move(5, 0), // left
S(1.5, 1.5, -3.5, -3.5).Move(5, 5), // bottom-left corner
S(5, 0, 5, -5).Move(0, 5), // bottom
S(8.5, 1.5, 13.5, -3.5).Move(-5, 5), // bottom-right corner
S(10, 5, 15, 5).Move(-5, 0), // right
S(8.5, 8.5, 13.5, 13.5).Move(-5, -5), // top-right corner
S(5, 10, 5, 15).Move(0, -5), // top
S(1.5, 8.5, -3.5, 13.5).Move(5, -5), // top-left corner
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("Inside", func(t *testing.T) {
segs := []Segment{
S(0, 5, -5, 5).Move(6, 0), // left
S(1.5, 1.5, -3.5, -3.5).Move(6, 6), // bottom-left corner
S(5, 0, 5, -5).Move(0, 6), // bottom
S(8.5, 1.5, 13.5, -3.5).Move(-6, 6), // bottom-right corner
S(10, 5, 15, 5).Move(-6, 0), // right
S(8.5, 8.5, 13.5, 13.5).Move(-6, -6), // top-right corner
S(5, 10, 5, 15).Move(0, -6), // top
S(1.5, 8.5, -3.5, 13.5).Move(6, -6), // top-left corner
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringContainsSegment(ring, seg, true))
expect(t, ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringContainsSegment(ring, seg, true))
expect(t, ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("InsideEdgeToEdge", func(t *testing.T) {
segs := []Segment{
S(0, 5, 10, 5), // left to right
S(1.5, 1.5, 8.5, 8.5), // bottom-left to top-right
S(5, 0, 5, 10), // bottom to top
S(8.5, 1.5, 1.5, 8.5), // bottom-right to top-left
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("PassoverEdgeToEdge", func(t *testing.T) {
segs := []Segment{
S(-1, 5, 11, 5), // left to right
S(0.5, 0.5, 9.5, 9.5), // bottom-left to top-right
S(5, -1, 5, 11), // bottom to top
S(9.5, 0.5, 0.5, 9.5), // bottom-right to top-left
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
})
// concave shape
t.Run("Concave", func(t *testing.T) {
shape := concave1
t.Run("Outside", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, -5, 7.5).Move(-1, 0), // left
S(2.5, 5, 2.5, 0).Move(0, -1), // bottom-left-1
S(5, 2.5, 0, 2.5).Move(-1, 0), // bottom-left-2
S(7.5, 0, 7.5, -5).Move(0, -1), // bottom
S(10, 5, 15, 5).Move(1, 0), // right
S(5, 10, 5, 15).Move(0, 1), // top
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("OutsideEdgeTouch", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, -5, 7.5), // left
S(2.5, 5, 2.5, 0), // bottom-left-1
S(5, 2.5, 0, 2.5), // bottom-left-2
S(7.5, 0, 7.5, -5), // bottom
S(10, 5, 15, 5), // right
S(5, 10, 5, 15), // top
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("EdgeCross", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, -5, 7.5).Move(2.5, 0), // left
S(2.5, 5, 2.5, 0).Move(0, 2.5), // bottom-left-1
S(5, 2.5, 0, 2.5).Move(2.5, 0), // bottom-left-2
S(7.5, 0, 7.5, -5).Move(0, 2.5), // bottom
S(10, 5, 15, 5).Move(-2.5, 0), // right
S(5, 10, 5, 15).Move(0, -2.5), // top
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("InsideEdgeTouch", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, -3, 7.5).Move(3, 0), // 0:left
S(2.5, 5, 2.5, 2).Move(0, 3), // 1:bottom-left-1
S(5, 2.5, 2, 2.5).Move(3, 0), // 2:bottom-left-2
S(7.5, 0, 7.5, -3).Move(0, 3), // 3:bottom
S(10, 5, 13, 5).Move(-3, 0), // 4:right
S(5, 10, 5, 13).Move(0, -3), // 5:top
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("Inside", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, -3, 7.5).Move(4, 0), // 0:left
S(2.5, 5, 2.5, 2).Move(0, 4), // 1:bottom-left-1
S(5, 2.5, 2, 2.5).Move(4, 0), // 2:bottom-left-2
S(7.5, 0, 7.5, -3).Move(0, 4), // 3:bottom
S(10, 5, 13, 5).Move(-4, 0), // 4:right
S(5, 10, 5, 13).Move(0, -4), // 5:top
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringContainsSegment(ring, seg, true))
expect(t, ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringContainsSegment(ring, seg, true))
expect(t, ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("InsideEdgeToEdge", func(t *testing.T) {
segs := []Segment{
S(0, 7.5, 10, 7.5), // 0:left
S(2.5, 5, 2.5, 10), // 1:bottom-left-1
S(5, 2.5, 10, 2.5), // 2:bottom-left-2
S(7.5, 0, 7.5, 10), // 3:bottom
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
t.Run("PassoverEdgeToEdge", func(t *testing.T) {
segs := []Segment{
S(-1, 7.5, 11, 7.5), // 0:left
S(2.5, 4, 2.5, 11), // 1:bottom-left-1
S(4, 2.5, 11, 2.5), // 2:bottom-left-2
S(7.5, -1, 7.5, 11), // 3:bottom
}
for i, seg := range segs {
t.Run(fmt.Sprintf("Segment-%d", i), func(t *testing.T) {
testDualRingX(t, shape, func(t *testing.T, ring Ring) {
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
seg.A, seg.B = seg.B, seg.A
expect(t, !ringContainsSegment(ring, seg, true))
expect(t, !ringContainsSegment(ring, seg, false))
})
})
}
})
})
t.Run("Cases", func(t *testing.T) {
ring := newRing([]Point{
P(0, 0), P(4, 0), P(4, 4), P(3, 4),
P(2, 3), P(1, 4), P(0, 4), P(0, 0),
}, DefaultIndexOptions)
t.Run("1", func(t *testing.T) {
expect(t, !ringContainsSegment(ring, S(1.5, 3.5, 2.5, 3.5), true))
expect(t, !ringContainsSegment(ring, S(1.5, 3.5, 2.5, 3.5), false))
})
t.Run("2", func(t *testing.T) {
expect(t, !ringContainsSegment(ring, S(1.0, 3.5, 2.5, 3.5), true))
expect(t, !ringContainsSegment(ring, S(1.0, 3.5, 2.5, 3.5), false))
})
t.Run("3", func(t *testing.T) {
expect(t, ringContainsSegment(ring, S(1.25, 3.75, 1.75, 3.25), true))
expect(t, !ringContainsSegment(ring, S(1.25, 3.75, 1.75, 3.25), false))
})
t.Run("4", func(t *testing.T) {
expect(t, !ringContainsSegment(ring, S(1.5, 3.5, 3, 3.5), true))
expect(t, !ringContainsSegment(ring, S(1.5, 3.5, 3, 3.5), false))
})
t.Run("5", func(t *testing.T) {
expect(t, !ringContainsSegment(ring, S(1.0, 3.5, 3, 3.5), true))
expect(t, !ringContainsSegment(ring, S(1.0, 3.5, 3, 3.5), false))
})
t.Run("6", func(t *testing.T) {
ring := newRing([]Point{
P(0, 0), P(4, 0), P(4, 4), P(3, 4),
P(2, 5), P(1, 4), P(0, 4), P(0, 0),
}, DefaultIndexOptions)
expect(t, ringContainsSegment(ring, S(1.5, 4.5, 2.5, 4.5), true))
expect(t, !ringContainsSegment(ring, S(1.5, 4.5, 2.5, 4.5), false))
})
t.Run("7", func(t *testing.T) {
ring := newRing([]Point{
P(0, 0), P(4, 0), P(4, 4), P(3, 4),
P(2.5, 3), P(2, 4), P(1.5, 3),
P(1, 4), P(0, 4), P(0, 0),
}, DefaultIndexOptions)
expect(t, !ringContainsSegment(ring, S(1.25, 3.5, 2.75, 3.5), true))
expect(t, !ringContainsSegment(ring, S(1.25, 3.5, 2.75, 3.5), false))
})
t.Run("8", func(t *testing.T) {
ring := newRing([]Point{
P(0, 0), P(4, 0), P(4, 4), P(3, 4),
P(2.5, 5), P(2, 4), P(1.5, 5),
P(1, 4), P(0, 4), P(0, 0),
}, DefaultIndexOptions)
expect(t, !ringContainsSegment(ring, S(1.25, 4.5, 2.75, 4.5), true))
expect(t, !ringContainsSegment(ring, S(1.25, 4.5, 2.75, 4.5), false))
})
t.Run("9", func(t *testing.T) {
expect(t, ringContainsSegment(ring, S(1, 2, 3, 2), true))
expect(t, ringContainsSegment(ring, S(1, 2, 3, 2), false))
})
t.Run("10", func(t *testing.T) {
expect(t, ringContainsSegment(ring, S(1, 3, 3, 2), true))
expect(t, ringContainsSegment(ring, S(1, 3, 3, 2), false))
})
t.Run("11", func(t *testing.T) {
expect(t, ringContainsSegment(ring, S(1, 2, 3, 3), true))
expect(t, ringContainsSegment(ring, S(1, 2, 3, 3), false))
})
t.Run("12", func(t *testing.T) {
expect(t, ringContainsSegment(ring, S(1.5, 3.5, 1.5, 2), true))
expect(t, !ringContainsSegment(ring, S(1.5, 3.5, 1.5, 2), false))
})
t.Run("13", func(t *testing.T) {
ring := newRing([]Point{
P(0, 0), P(2, 0), P(4, 0), P(4, 4), P(3, 4),
P(2, 3), P(1, 4), P(0, 4), P(0, 0),
}, DefaultIndexOptions)
expect(t, ringContainsSegment(ring, S(1, 0, 3, 0), true))
expect(t, !ringContainsSegment(ring, S(1, 0, 3, 0), false))
})
t.Run("14", func(t *testing.T) {
ring := newRing([]Point{
P(0, 0), P(4, 0), P(2, 2), P(0, 4), P(0, 0),
}, DefaultIndexOptions)
expect(t, ringContainsSegment(ring, S(1, 3, 3, 1), true))
expect(t, ringContainsSegment(ring, S(3, 1, 1, 3), true))
expect(t, !ringContainsSegment(ring, S(1, 3, 3, 1), false))
expect(t, !ringContainsSegment(ring, S(3, 1, 1, 3), false))
})
t.Run("15", func(t *testing.T) {
expect(t, ringContainsSegment(ring, S(1, 3, 3, 3), true))
expect(t, !ringContainsSegment(ring, S(1, 3, 3, 3), false))
})
t.Run("16", func(t *testing.T) {
expect(t, ringContainsSegment(ring, S(1, 3, 2, 3), true))
expect(t, !ringContainsSegment(ring, S(1, 3, 2, 3), false))
})
})
}
func TestRingXContainsRing(t *testing.T) {
t.Run("Empty", func(t *testing.T) {
expect(t, !ringContainsRing(newRing(nil, DefaultIndexOptions), R(0, 0, 1, 1), true))
expect(t, !ringContainsRing(R(0, 0, 1, 1), newRing(nil, DefaultIndexOptions), true))
})
t.Run("Exact", func(t *testing.T) {
expect(t, ringContainsRing(R(0, 0, 1, 1), R(0, 0, 1, 1), true))
expect(t, !ringContainsRing(R(0, 0, 1, 1), R(0, 0, 1, 1), false))
expect(t, ringContainsRing(newRing(concave1, DefaultIndexOptions), newRing(concave1, DefaultIndexOptions), true))
expect(t, !ringContainsRing(newRing(concave1, DefaultIndexOptions), newRing(concave1, DefaultIndexOptions), false))
expect(t, ringContainsRing(newRing(octagon, DefaultIndexOptions), newRing(octagon, DefaultIndexOptions), true))
expect(t, !ringContainsRing(newRing(octagon, DefaultIndexOptions), newRing(octagon, DefaultIndexOptions), false))
})
t.Run("Cases", func(t *testing.T) {
// concave
ring := newRing([]Point{
P(0, 0), P(4, 0), P(4, 4), P(3, 4),
P(2, 3), P(1, 4), P(0, 4), P(0, 0),
}, DefaultIndexOptions)
t.Run("1", func(t *testing.T) {
expect(t, ringContainsRing(ring, R(1, 1, 3, 2), true))
expect(t, ringContainsRing(ring, R(1, 1, 3, 2), false))
})
t.Run("2", func(t *testing.T) {
expect(t, ringContainsRing(ring, R(0, 0, 2, 1), true))
expect(t, !ringContainsRing(ring, R(0, 0, 2, 1), false))
})
t.Run("3", func(t *testing.T) {
expect(t, !ringContainsRing(ring, R(-1.5, 1, 1.5, 2), true))
expect(t, !ringContainsRing(ring, R(-1.5, 1, 1.5, 2), false))
})
t.Run("4", func(t *testing.T) {
expect(t, !ringContainsRing(ring, R(1, 2.5, 3, 3.5), true))
expect(t, !ringContainsRing(ring, R(1, 2.5, 3, 3.5), false))
})
t.Run("5", func(t *testing.T) {
expect(t, ringContainsRing(ring, R(1, 2, 3, 3), true))
expect(t, !ringContainsRing(ring, R(1, 2, 3, 3), false))
})
// convex
ring = newRing([]Point{
P(0, 0), P(4, 0), P(4, 4),
P(3, 4), P(2, 5), P(1, 4),
P(0, 4), P(0, 0),
}, DefaultIndexOptions)
t.Run("6", func(t *testing.T) {
expect(t, ringContainsRing(ring, R(1, 2, 3, 3), true))
expect(t, ringContainsRing(ring, R(1, 2, 3, 3), false))
})
t.Run("7", func(t *testing.T) {
expect(t, ringContainsRing(ring, R(1, 3, 3, 4), true))
expect(t, !ringContainsRing(ring, R(1, 3, 3, 4), false))
})
t.Run("8", func(t *testing.T) {
expect(t, !ringContainsRing(ring, R(1, 3.5, 3, 4.5), true))
expect(t, !ringContainsRing(ring, R(1, 3.5, 3, 4.5), false))
})
t.Run("9", func(t *testing.T) {
ring = newRing([]Point{
P(0, 0), P(2, 0), P(4, 0), P(4, 4), P(3, 4),
P(2, 5), P(1, 4), P(0, 4), P(0, 0),
}, DefaultIndexOptions)
expect(t, ringContainsRing(ring, R(1, 0, 3, 1), true))
expect(t, !ringContainsRing(ring, R(1, 0, 3, 1), false))
})
t.Run("10", func(t *testing.T) {
ring = newRing([]Point{
P(0, 0), P(4, 0), P(4, 3), P(2, 4),
P(0, 3), P(0, 0),
}, DefaultIndexOptions)
expect(t, ringContainsRing(ring, R(1, 1, 3, 2), true))
expect(t, ringContainsRing(ring, R(1, 1, 3, 2), false))
})
ring = newRing([]Point{
P(0, 0), P(4, 0), P(4, 3), P(3, 4), P(1, 4), P(0, 3), P(0, 0),
}, DefaultIndexOptions)
t.Run("11", func(t *testing.T) {
expect(t, ringContainsRing(ring, R(1, 1, 3, 2), true))
expect(t, ringContainsRing(ring, R(1, 1, 3, 2), false))
})
t.Run("12", func(t *testing.T) {
expect(t, ringContainsRing(ring, R(0, 1, 2, 2), true))
expect(t, !ringContainsRing(ring, R(0, 1, 2, 2), false))
})
t.Run("13", func(t *testing.T) {
expect(t, !ringContainsRing(ring, R(-1, 1, 1, 2), true))
expect(t, !ringContainsRing(ring, R(-1, 1, 1, 2), false))
})
t.Run("14", func(t *testing.T) {
expect(t, ringContainsRing(ring, R(0.5, 2.5, 2.5, 3.5), true))
expect(t, !ringContainsRing(ring, R(0.5, 2.5, 2.5, 3.5), false))
})
t.Run("15", func(t *testing.T) {
expect(t, !ringContainsRing(ring, R(0.25, 2.75, 2.25, 3.75), true))
expect(t, !ringContainsRing(ring, R(0.25, 2.75, 2.25, 3.75), false))
})
t.Run("16", func(t *testing.T) {
expect(t, !ringContainsRing(ring, R(-2, 1, -1, 2), true))
expect(t, !ringContainsRing(ring, R(-2, 1, -1, 2), false))
})
t.Run("17", func(t *testing.T) {
expect(t, !ringContainsRing(ring, R(-0.5, 3.5, 0.5, 4.5), true))
expect(t, !ringContainsRing(ring, R(-0.5, 3.5, 0.5, 4.5), false))
})
t.Run("18", func(t *testing.T) {
expect(t, !ringContainsRing(ring, R(-0.75, 3.75, 0.25, 4.75), true))
expect(t, !ringContainsRing(ring, R(-0.74, 3.75, 0.25, 4.75), false))
})
t.Run("19", func(t *testing.T) {
expect(t, !ringContainsRing(ring, R(-1, -1, 5, 5), true))
expect(t, !ringContainsRing(ring, R(-1, -1, 5, 5), false))
})
})
t.Run("Identical", func(t *testing.T) {
shapes := []Ring{
R(0, 0, 10, 10),
newRing(octagon, DefaultIndexOptions),
newRing(concave1, DefaultIndexOptions), newRing(concave2, DefaultIndexOptions),
newRing(concave3, DefaultIndexOptions), newRing(concave4, DefaultIndexOptions),
newRing(ri, DefaultIndexOptions),
}
for i, shape := range shapes {
t.Run(fmt.Sprintf("Shape%d", i), func(t *testing.T) {
expect(t, ringContainsRing(shape, shape, true))
})
}
})
t.Run("Big", func(t *testing.T) {
// use rhode island
ring := newRing(ri, DefaultIndexOptions)
expect(t, ringContainsRing(ring.Rect(), ring, true))
expect(t, ringContainsRing(ring, ring, true))
})
}
func TestRingXIntersectsRing(t *testing.T) {
intersectsBothWays := func(ringA, ringB Ring, allowOnEdge bool) bool {
t1 := ringIntersectsRing(ringA, ringB, allowOnEdge)
t2 := ringIntersectsRing(ringB, ringA, allowOnEdge)
if t1 != t2 {
panic("mismatch")
}
return t1
}
t.Run("Empty", func(t *testing.T) {
expect(t, !intersectsBothWays(newRing(nil, DefaultIndexOptions), R(0, 0, 1, 1), true))
expect(t, !intersectsBothWays(R(0, 0, 1, 1), newRing(nil, DefaultIndexOptions), true))
})
t.Run("Cases", func(t *testing.T) {
// concave
ring := newRing([]Point{
P(0, 0), P(4, 0), P(4, 4), P(3, 4),
P(2, 3), P(1, 4), P(0, 4), P(0, 0),
}, DefaultIndexOptions)
t.Run("1", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(1, 1, 3, 2), true))
expect(t, intersectsBothWays(ring, R(1, 1, 3, 2), false))
})
t.Run("2", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(0, 0, 2, 1), true))
expect(t, intersectsBothWays(ring, R(0, 0, 2, 1), false))
})
t.Run("3", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(-1.5, 1, 1.5, 2), true))
expect(t, intersectsBothWays(ring, R(-1.5, 1, 1.5, 2), false))
})
t.Run("4", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(1, 2.5, 3, 3.5), true))
expect(t, intersectsBothWays(ring, R(1, 2.5, 3, 3.5), false))
})
t.Run("5", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(1, 2, 3, 3), true))
expect(t, intersectsBothWays(ring, R(1, 2, 3, 3), false))
})
// convex
ring = newRing([]Point{
P(0, 0), P(4, 0), P(4, 4),
P(3, 4), P(2, 5), P(1, 4),
P(0, 4), P(0, 0),
}, DefaultIndexOptions)
t.Run("6", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(1, 2, 3, 3), true))
expect(t, intersectsBothWays(ring, R(1, 2, 3, 3), false))
})
t.Run("7", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(1, 3, 3, 4), true))
expect(t, intersectsBothWays(ring, R(1, 3, 3, 4), false))
})
t.Run("8", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(1, 3.5, 3, 4.5), true))
expect(t, intersectsBothWays(ring, R(1, 3.5, 3, 4.5), false))
})
t.Run("9", func(t *testing.T) {
ring = newRing([]Point{
P(0, 0), P(2, 0), P(4, 0), P(4, 4), P(3, 4),
P(2, 5), P(1, 4), P(0, 4), P(0, 0),
}, DefaultIndexOptions)
expect(t, intersectsBothWays(ring, R(1, 0, 3, 1), true))
expect(t, intersectsBothWays(ring, R(1, 0, 3, 1), false))
})
t.Run("10", func(t *testing.T) {
ring = newRing([]Point{
P(0, 0), P(4, 0), P(4, 3), P(2, 4),
P(0, 3), P(0, 0),
}, DefaultIndexOptions)
expect(t, intersectsBothWays(ring, R(1, 1, 3, 2), true))
expect(t, intersectsBothWays(ring, R(1, 1, 3, 2), false))
})
ring = newRing([]Point{
P(0, 0), P(4, 0), P(4, 3), P(3, 4), P(1, 4), P(0, 3), P(0, 0),
}, DefaultIndexOptions)
t.Run("11", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(1, 1, 3, 2), true))
expect(t, intersectsBothWays(ring, R(1, 1, 3, 2), false))
})
t.Run("12", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(0, 1, 2, 2), true))
expect(t, intersectsBothWays(ring, R(0, 1, 2, 2), false))
})
t.Run("13", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(-1, 1, 1, 2), true))
expect(t, intersectsBothWays(ring, R(-1, 1, 1, 2), false))
})
t.Run("14", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(0.5, 2.5, 2.5, 3.5), true))
expect(t, intersectsBothWays(ring, R(0.5, 2.5, 2.5, 3.5), false))
})
t.Run("15", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(0.25, 2.75, 2.25, 3.75), true))
expect(t, intersectsBothWays(ring, R(0.25, 2.75, 2.25, 3.75), false))
})
t.Run("16", func(t *testing.T) {
expect(t, !intersectsBothWays(ring, R(-2, 1, -1, 2), true))
expect(t, !intersectsBothWays(ring, R(-2, 1, -1, 2), false))
})
t.Run("17", func(t *testing.T) {
expect(t, intersectsBothWays(ring, R(-0.5, 3.5, 0.5, 4.5), true))
expect(t, !intersectsBothWays(ring, R(-0.5, 3.5, 0.5, 4.5), false))
})
t.Run("18", func(t *testing.T) {
expect(t, !intersectsBothWays(ring, R(-0.75, 3.75, 0.25, 4.75), true))
expect(t, !intersectsBothWays(ring, R(-0.74, 3.75, 0.25, 4.75), false))
})
t.Run("19", func(t *testing.T) {
expect(t, ringIntersectsRing(ring, R(-1, -1, 5, 5), true))
expect(t, ringIntersectsRing(ring, R(-1, -1, 5, 5), false))
})
})
}
func TestRingXContainsLine(t *testing.T) {
t.Run("Cases", func(t *testing.T) {
// convex
ring := newRing([]Point{
P(0, 0), P(4, 0), P(4, 3),
P(3, 4), P(1, 4),
P(0, 3), P(0, 0),
}, DefaultIndexOptions)
makeLine := func(start Point) *Line {
return NewLine([]Point{
start, start.Move(0, 1), start.Move(1, 1),
start.Move(1, 2), start.Move(2, 2),
}, DefaultIndexOptions)
}
t.Run("1", func(t *testing.T) {
expect(t, ringContainsLine(ring, makeLine(P(1, 1)), true))
expect(t, ringContainsLine(ring, makeLine(P(1, 1)), false))
})
t.Run("2", func(t *testing.T) {
expect(t, ringContainsLine(ring, makeLine(P(0, 1)), true))
expect(t, !ringContainsLine(ring, makeLine(P(0, 1)), false))
})
t.Run("3", func(t *testing.T) {
expect(t, !ringContainsLine(ring, makeLine(P(-0.5, 1)), true))
expect(t, !ringContainsLine(ring, makeLine(P(-0.5, 1)), false))
})
t.Run("4", func(t *testing.T) {
expect(t, ringContainsLine(ring, makeLine(P(0, 2)), true))
expect(t, !ringContainsLine(ring, makeLine(P(0, 2)), false))
})
t.Run("5", func(t *testing.T) {
expect(t, !ringContainsLine(ring, makeLine(P(0, 2.5)), true))
expect(t, !ringContainsLine(ring, makeLine(P(0, 2.5)), false))
})
t.Run("6", func(t *testing.T) {
expect(t, !ringContainsLine(ring, makeLine(P(2, 2)), true))
expect(t, !ringContainsLine(ring, makeLine(P(2, 2)), false))
})
t.Run("7", func(t *testing.T) {
expect(t, !ringContainsLine(ring, makeLine(P(2, 1.5)), true))
expect(t, !ringContainsLine(ring, makeLine(P(2, 1.5)), false))
})
t.Run("8", func(t *testing.T) {
expect(t, ringContainsLine(ring, makeLine(P(2, 1)), true))
expect(t, !ringContainsLine(ring, makeLine(P(2, 1)), false))
})
t.Run("9", func(t *testing.T) {
expect(t, ringContainsLine(ring, makeLine(P(2, 0)), true))
expect(t, !ringContainsLine(ring, makeLine(P(2, 0)), false))
})
t.Run("10", func(t *testing.T) {
expect(t, ringContainsLine(ring, makeLine(P(1.5, 0)), true))
expect(t, !ringContainsLine(ring, makeLine(P(1.5, 0)), false))
})
t.Run("11", func(t *testing.T) {
expect(t, !ringContainsLine(ring, makeLine(P(1, -1)), true))
expect(t, !ringContainsLine(ring, makeLine(P(1, -1)), false))
})
t.Run("12", func(t *testing.T) {
expect(t, !ringContainsLine(ring, makeLine(P(1.5, -0.5)), true))
expect(t, !ringContainsLine(ring, makeLine(P(1.5, -0.5)), false))
})
t.Run("13", func(t *testing.T) {
expect(t, ringContainsLine(ring, makeLine(P(0, 0)), true))
expect(t, !ringContainsLine(ring, makeLine(P(0, 0)), false))
})
t.Run("14", func(t *testing.T) {
expect(t, !ringContainsLine(ring, makeLine(P(3, 1)), true))
expect(t, !ringContainsLine(ring, makeLine(P(3, 1)), false))
})
t.Run("15", func(t *testing.T) {
line := L(P(-1, -1), P(-1, 2), P(2, 2), P(2, 5), P(5, 5))
expect(t, !ringContainsLine(ring, line, true))
expect(t, !ringContainsLine(ring, line, false))
})
t.Run("16", func(t *testing.T) {
line := L(P(0, -1), P(0, 1), P(3, 3), P(5, 3))
expect(t, !ringContainsLine(ring, line, true))
expect(t, !ringContainsLine(ring, line, false))
})
t.Run("17", func(t *testing.T) {
line := L(P(-1, 2), P(2, 1), P(5, 2))
expect(t, !ringContainsLine(ring, line, true))
expect(t, !ringContainsLine(ring, line, false))
})
t.Run("18", func(t *testing.T) {
line := L(P(1, -1), P(3, 2), P(2, 5))
expect(t, !ringContainsLine(ring, line, true))
expect(t, !ringContainsLine(ring, line, false))
})
t.Run("19", func(t *testing.T) {
line := L(P(3.5, 4.5), P(3.5, 3.5), P(5, 3.5), P(5, 2.5))
expect(t, !ringContainsLine(ring, line, true))
expect(t, !ringContainsLine(ring, line, false))
})
t.Run("20", func(t *testing.T) {
line := L(P(4, 5), P(4, 4), P(5, 4), P(5, 3))
expect(t, !ringContainsLine(ring, line, true))
expect(t, !ringContainsLine(ring, line, false))
})
t.Run("21", func(t *testing.T) {
line := L(P(1, -1), P(1, -2), P(2, -2), P(2, -3))
expect(t, !ringContainsLine(ring, line, true))
expect(t, !ringContainsLine(ring, line, false))
})
})
}
func TestRingXIntersectsLine(t *testing.T) {
t.Run("Various", func(t *testing.T) {
expect(t, !ringIntersectsLine(R(0, 0, 0, 0), L(), true))
expect(t, !ringIntersectsLine(R(0, 0, 10, 10),
L(P(-1, -1), P(11, -1), P(11, 11), P(-1, 11)),
true))
expect(t, ringIntersectsLine(R(0, 0, 10, 10),
L(P(-1, -1), P(11, -1), P(11, 11), P(-1, 11), P(5, -1)),
true))
})
t.Run("Cases", func(t *testing.T) {
// convex
ring := newRing([]Point{
P(0, 0), P(4, 0), P(4, 3),
P(3, 4), P(1, 4),
P(0, 3), P(0, 0),
}, DefaultIndexOptions)
makeLine := func(start Point) *Line {
return NewLine([]Point{
start, start.Move(0, 1), start.Move(1, 1),
start.Move(1, 2), start.Move(2, 2),
}, DefaultIndexOptions)
}
t.Run("1", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(1, 1)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(1, 1)), false))
})
t.Run("2", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(0, 1)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(0, 1)), false))
})
t.Run("3", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(-0.5, 1)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(-0.5, 1)), false))
})
t.Run("4", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(0, 2)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(0, 2)), false))
})
t.Run("5", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(0, 2.5)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(0, 2.5)), false))
})
t.Run("6", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(2, 2)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(2, 2)), false))
})
t.Run("7", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(2, 1.5)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(2, 1.5)), false))
})
t.Run("8", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(2, 1)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(2, 1)), false))
})
t.Run("9", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(2, 0)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(2, 0)), false))
})
t.Run("10", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(1.5, 0)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(1.5, 0)), false))
})
t.Run("11", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(1, -1)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(1, -1)), false))
})
t.Run("12", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(1.5, -0.5)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(1.5, -0.5)), false))
})
t.Run("13", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(0, 0)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(0, 0)), false))
})
t.Run("14", func(t *testing.T) {
expect(t, ringIntersectsLine(ring, makeLine(P(3, 1)), true))
expect(t, ringIntersectsLine(ring, makeLine(P(3, 1)), false))
})
t.Run("15", func(t *testing.T) {
line := L(P(-1, -1), P(-1, 2), P(2, 2), P(2, 5), P(5, 5))
expect(t, ringIntersectsLine(ring, line, true))
expect(t, ringIntersectsLine(ring, line, false))
})
t.Run("16", func(t *testing.T) {
line := L(P(0, -1), P(0, 1), P(3, 3), P(5, 3))
expect(t, ringIntersectsLine(ring, line, true))
expect(t, ringIntersectsLine(ring, line, false))
})
t.Run("17", func(t *testing.T) {
line := L(P(-1, 2), P(2, 1), P(5, 2))
expect(t, ringIntersectsLine(ring, line, true))
expect(t, ringIntersectsLine(ring, line, false))
})
t.Run("18", func(t *testing.T) {
line := L(P(1, -1), P(3, 2), P(2, 5))
expect(t, ringIntersectsLine(ring, line, true))
expect(t, ringIntersectsLine(ring, line, false))
})
t.Run("19", func(t *testing.T) {
line := L(P(3.5, 4.5), P(3.5, 3.5), P(5, 3.5), P(5, 2.5))
expect(t, ringIntersectsLine(ring, line, true))
expect(t, !ringIntersectsLine(ring, line, false))
})
t.Run("20", func(t *testing.T) {
line := L(P(4, 5), P(4, 4), P(5, 4), P(5, 3))
expect(t, !ringIntersectsLine(ring, line, true))
expect(t, !ringIntersectsLine(ring, line, false))
})
t.Run("21", func(t *testing.T) {
line := L(P(1, -1), P(1, -2), P(2, -2), P(2, -3))
expect(t, !ringIntersectsLine(ring, line, true))
expect(t, !ringIntersectsLine(ring, line, false))
})
})
}