maplibre-gl
Version:
BSD licensed community fork of mapbox-gl, a WebGL interactive maps library
160 lines (133 loc) • 5.46 kB
text/typescript
import {describe, test, expect} from 'vitest';
import Point from '@mapbox/point-geometry';
import {roundPolygonCorners} from './round_polygon_corners.ts';
import {CanonicalTileID} from '../../tile/tile_id.ts';
function round(p: Point):GeoJSON.Position {
// add 0 to normalize -0 into 0
const x = Math.round(p.x * 100) / 100 + 0;
const y = Math.round(p.y * 100) / 100 + 0;
return [x, y];
}
describe('roundPolygonCorners', () => {
const canonical = new CanonicalTileID(10, 500, 300);
test('returns original polygon reference when distance is zero', () => {
const input = [[
new Point(0, 0),
new Point(100, 0),
new Point(100, 100),
new Point(0, 100),
new Point(0, 0)
]];
const output = roundPolygonCorners(input, 0, canonical);
expect(output).toBe(input);
});
test('returns original polygon reference when distance is negative', () => {
const input = [[
new Point(0, 0),
new Point(100, 0),
new Point(100, 100),
new Point(0, 100),
new Point(0, 0)
]];
const output = roundPolygonCorners(input, -1, canonical);
expect(output).toBe(input);
});
test('returns unchanged ring for degenerate line rings', () => {
const input = [[
new Point(0, 0),
new Point(50, 50),
new Point(0, 0)
]];
const output = roundPolygonCorners(input, 10, canonical);
expect(output).toStrictEqual(input);
});
test('still rounds very small rounding', () => {
const input = [[
new Point(0, 0),
new Point(10, 0),
new Point(10, 10),
new Point(0, 10),
new Point(0, 0)
]];
const output = roundPolygonCorners(input, 0.1, canonical);
const points = output[0].map(round);
expect(points).toEqual([
[0, 0.04], [0.01, 0.02], [0.02, 0.01], [0.04, 0], [9.96, 0], [9.98, 0.01], [9.99, 0.02], [10, 0.04],
[10, 9.96], [9.99, 9.98], [9.98, 9.99], [9.96, 10], [0.04, 10], [0.02, 9.99], [0.01, 9.98], [0, 9.96], [0, 0.04]
]);
});
test('rounds corners of a square polygon into arc vertices', () => {
const input = [[
new Point(0, 0),
new Point(10, 0),
new Point(10, 10),
new Point(0, 10),
new Point(0, 0)
]];
const output = roundPolygonCorners(input, 2, canonical);
const points = output[0].map(round);
expect(points).toEqual([
[0, 0.82], [0.11, 0.41], [0.41, 0.11], [0.82, 0], [9.18, 0], [9.59, 0.11], [9.89, 0.41], [10, 0.82],
[10, 9.18], [9.89, 9.59], [9.59, 9.89], [9.18, 10], [0.82, 10], [0.41, 9.89], [0.11, 9.59], [0, 9.18], [0, 0.82]
]);
});
test('clamps corner rounding distance to 20% of edge length when requested distance is large', () => {
const input = [[
new Point(0, 0),
new Point(10, 0),
new Point(10, 10),
new Point(0, 10),
new Point(0, 0)
]];
const output = roundPolygonCorners(input, 1000, canonical);
const points = output[0].map(round);
expect(points).toEqual([
[0, 2], [0.27, 1], [1, 0.27], [2, 0], [8, 0], [9, 0.27], [9.73, 1], [10, 2],
[10, 8], [9.73, 9], [9, 9.73], [8, 10], [2, 10], [1, 9.73], [0.27, 9], [0, 8], [0, 2]
]);
});
test('preserves near-zero-degree spike vertex without adding arc points', () => {
const input = [[
new Point(0, 0),
new Point(100, 0),
new Point(0, 0.4),
new Point(0, 0)
]];
const output = roundPolygonCorners(input, 5, canonical);
const points = output[0].map(round);
expect(points).toEqual([
[0, 0.08], [0.01, 0.04], [0.04, 0.01], [0.08, 0], [100, 0], [0.08, 0.4],
[0.05, 0.39], [0.02, 0.38], [0.01, 0.35], [0, 0.32], [0, 0.08]
]);
});
test('preserves collinear 180-degree vertices without adding arc points', () => {
const input = [[
new Point(0, 0),
new Point(5, 0),
new Point(10, 0),
new Point(10, 10),
new Point(0, 10),
new Point(0, 0)
]];
const output = roundPolygonCorners(input, 5, canonical);
const points = output[0].map(round);
expect(points).toEqual([
[0, 1], [0.13, 0.5], [0.5, 0.13], [1, 0], [5, 0], [9, 0], [9.5, 0.13], [9.87, 0.5], [10, 1],
[10, 8], [9.73, 9], [9, 9.73], [8, 10], [2, 10], [1, 9.73], [0.27, 9], [0, 8], [0, 1]
]);
});
test('scales arc points with corner sharpness up to the segment maximum', () => {
const input = [[
new Point(0, 0),
new Point(100, 0),
new Point(50, 20),
new Point(0, 0)
]];
const output = roundPolygonCorners(input, 5, canonical);
const points = output[0].map(round);
expect(points).toEqual([
[1.91, 0.77], [1.77, 0.66], [1.68, 0.5], [1.67, 0.32], [1.75, 0.16], [1.88, 0.04], [2.06, 0], [97.94, 0], [98.12, 0.04],
[98.25, 0.16], [98.33, 0.32], [98.32, 0.5], [98.23, 0.66], [98.09, 0.77], [51.91, 19.23], [50, 19.6], [48.09, 19.23], [1.91, 0.77]
]);
});
});