|
| 1 | +var polygon = require('@src/lib/polygon'); |
| 2 | + |
| 3 | +describe('polygon', function() { |
| 4 | + 'use strict'; |
| 5 | + |
| 6 | + var squareCW = [[0, 0], [0, 1], [1, 1], [1, 0]], |
| 7 | + squareCCW = [[0, 0], [1, 0], [1, 1], [0, 1]], |
| 8 | + bowtie = [[0, 0], [0, 1], [1, 0], [1, 1]], |
| 9 | + squareish = [ |
| 10 | + [-0.123, -0.0456], |
| 11 | + [0.12345, 1.2345], |
| 12 | + [1.3456, 1.4567], |
| 13 | + [1.5678, 0.21345]], |
| 14 | + equilateralTriangle = [ |
| 15 | + [0, Math.sqrt(3) / 3], |
| 16 | + [-0.5, -Math.sqrt(3) / 6], |
| 17 | + [0.5, -Math.sqrt(3) / 6]], |
| 18 | + |
| 19 | + zigzag = [ // 4 * |
| 20 | + [0, 0], [2, 1], // \-. |
| 21 | + [0, 1], [2, 2], // 3 * * |
| 22 | + [1, 2], [3, 3], // ,-' | |
| 23 | + [2, 4], [4, 3], // 2 *-* | |
| 24 | + [4, 0]], // ,-' | |
| 25 | + // 1 *---* | |
| 26 | + // ,-' | |
| 27 | + // 0 *-------* |
| 28 | + // 0 1 2 3 4 |
| 29 | + inZigzag = [ |
| 30 | + [0.5, 0.01], [1, 0.49], [1.5, 0.5], [2, 0.5], [2.5, 0.5], [3, 0.5], |
| 31 | + [3.5, 0.5], [0.5, 1.01], [1, 1.49], [1.5, 1.5], [2, 1.5], [2.5, 1.5], |
| 32 | + [3, 1.5], [3.5, 1.5], [1.5, 2.01], [2, 2.49], [2.5, 2.5], [3, 2.5], |
| 33 | + [3.5, 2.5], [2.5, 3.51], [3, 3.49]], |
| 34 | + notInZigzag = [ |
| 35 | + [0, -0.01], [0, 0.01], [0, 0.99], [0, 1.01], [0.5, -0.01], [0.5, 0.26], |
| 36 | + [0.5, 0.99], [0.5, 1.26], [1, -0.01], [1, 0.51], [1, 0.99], [1, 1.51], |
| 37 | + [1, 1.99], [1, 2.01], [2, -0.01], [2, 2.51], [2, 3.99], [2, 4.01], |
| 38 | + [3, -0.01], [2.99, 3], [3, 3.51], [4, -0.01], [4, 3.01]], |
| 39 | + |
| 40 | + donut = [ // inner CCW, outer CW // 3 *-----* |
| 41 | + [3, 0], [0, 0], [0, 1], [2, 1], [2, 2], // | | |
| 42 | + [1, 2], [1, 1], [0, 1], [0, 3], [3, 3]], // 2 | *-* | |
| 43 | + donut2 = [ // inner CCW, outer CCW // | | | | |
| 44 | + [3, 3], [0, 3], [0, 1], [2, 1], [2, 2], // 1 *-*-* | |
| 45 | + [1, 2], [1, 1], [0, 1], [0, 0], [3, 0]], // | | |
| 46 | + // 0 *-----* |
| 47 | + // 0 1 2 3 |
| 48 | + inDonut = [[0.5, 0.5], [1, 0.5], [1.5, 0.5], [2, 0.5], [2.5, 0.5], |
| 49 | + [2.5, 1], [2.5, 1.5], [2.5, 2], [2.5, 2.5], [2, 2.5], [1.5, 2.5], |
| 50 | + [1, 2.5], [0.5, 2.5], [0.5, 2], [0.5, 1.5], [0.5, 1]], |
| 51 | + notInDonut = [[1.5, -0.5], [1.5, 1.5], [1.5, 3.5], [-0.5, 1.5], [3.5, 1.5]]; |
| 52 | + |
| 53 | + it('should exclude points outside the bounding box', function() { |
| 54 | + var poly = polygon([[1,2], [3,4]]); |
| 55 | + var pts = [[0, 3], [4, 3], [2, 1], [2, 5]]; |
| 56 | + pts.forEach(function(pt) { |
| 57 | + expect(poly.contains(pt)).toBe(false); |
| 58 | + expect(poly.contains(pt, true)).toBe(false); |
| 59 | + expect(poly.contains(pt, false)).toBe(false); |
| 60 | + }); |
| 61 | + }); |
| 62 | + |
| 63 | + it('should prepare a polygon object correctly', function() { |
| 64 | + var polyPts = [ |
| 65 | + [[0, 0], [0, 1], [1, 1], [1, 0]], |
| 66 | + [[-2.34, -0.67], [0.12345, 1.2345], [1.3456, 1.4567], [1.5678, 0.21345]] |
| 67 | + ]; |
| 68 | + |
| 69 | + polyPts.forEach(function(polyPt) { |
| 70 | + var poly = polygon(polyPt), |
| 71 | + xArray = polyPt.map(function(pt) { return pt[0]; }), |
| 72 | + yArray = polyPt.map(function(pt) { return pt[1]; }); |
| 73 | + |
| 74 | + expect(poly.pts.length).toEqual(polyPt.length + 1); |
| 75 | + polyPt.forEach(function(pt, i) { |
| 76 | + expect(poly.pts[i]).toEqual(pt); |
| 77 | + }); |
| 78 | + expect(poly.pts[poly.pts.length - 1]).toEqual(polyPt[0]); |
| 79 | + expect(poly.xmin).toEqual(Math.min.apply(null, xArray)); |
| 80 | + expect(poly.xmax).toEqual(Math.max.apply(null, xArray)); |
| 81 | + expect(poly.ymin).toEqual(Math.min.apply(null, yArray)); |
| 82 | + expect(poly.ymax).toEqual(Math.max.apply(null, yArray)); |
| 83 | + }); |
| 84 | + }); |
| 85 | + |
| 86 | + it('should include the whole boundary, except as per omitFirstEdge', function() { |
| 87 | + var polyPts = [squareCW, squareCCW, bowtie, squareish, equilateralTriangle, |
| 88 | + zigzag, donut, donut2]; |
| 89 | + var np = 6; // number of intermediate points on each edge to test |
| 90 | + |
| 91 | + polyPts.forEach(function(polyPt) { |
| 92 | + var poly = polygon(polyPt); |
| 93 | + poly.pts.forEach(function(pt1, i) { |
| 94 | + if(!i) return; |
| 95 | + var pt0 = poly.pts[i - 1], |
| 96 | + j; |
| 97 | + |
| 98 | + var testPts = [pt0, pt1]; |
| 99 | + for(j = 1; j < np; j++) { |
| 100 | + if(pt0[0] === pt1[0]) { |
| 101 | + testPts.push([pt0[0], pt0[1] + (pt1[1] - pt0[1]) * j / np]); |
| 102 | + } |
| 103 | + else { |
| 104 | + var x = pt0[0] + (pt1[0] - pt0[0]) * j / np; |
| 105 | + // calculated the same way as in the pt_in_polygon source, |
| 106 | + // so we know rounding errors will apply the same and this pt |
| 107 | + // *really* appears on the boundary |
| 108 | + testPts.push([x, pt0[1] + (x - pt0[0]) * (pt1[1] - pt0[1]) / |
| 109 | + (pt1[0] - pt0[0])]); |
| 110 | + } |
| 111 | + } |
| 112 | + testPts.forEach(function(pt, j) { |
| 113 | + expect(poly.contains(pt)) |
| 114 | + .toBe(true, 'poly: ' + polyPt.join(';') + ', pt: ' + pt); |
| 115 | + var isFirstEdge = (i === 1) || (i === 2 && j === 0) || |
| 116 | + (i === poly.pts.length - 1 && j === 1); |
| 117 | + expect(poly.contains(pt, true)) |
| 118 | + .toBe(!isFirstEdge, 'omit: ' + !isFirstEdge + ', poly: ' + |
| 119 | + polyPt.join(';') + ', pt: ' + pt); |
| 120 | + }); |
| 121 | + }); |
| 122 | + }); |
| 123 | + }); |
| 124 | + |
| 125 | + it('should find only the right interior points', function() { |
| 126 | + var zzpoly = polygon(zigzag); |
| 127 | + inZigzag.forEach(function(pt) { |
| 128 | + expect(zzpoly.contains(pt)).toBe(true); |
| 129 | + }); |
| 130 | + notInZigzag.forEach(function(pt) { |
| 131 | + expect(zzpoly.contains(pt)).toBe(false); |
| 132 | + }); |
| 133 | + |
| 134 | + var donutpoly = polygon(donut), |
| 135 | + donut2poly = polygon(donut2); |
| 136 | + inDonut.forEach(function(pt) { |
| 137 | + expect(donutpoly.contains(pt)).toBe(true); |
| 138 | + expect(donut2poly.contains(pt)).toBe(true); |
| 139 | + }); |
| 140 | + notInDonut.forEach(function(pt) { |
| 141 | + expect(donutpoly.contains(pt)).toBe(false); |
| 142 | + expect(donut2poly.contains(pt)).toBe(false); |
| 143 | + }); |
| 144 | + }); |
| 145 | +}); |
0 commit comments