import {
offsetLineString,
removeOffsetCycles,
} from '../../../../../src/ol/geom/flat/lineoffset.js';
import expect from '../../../expect.js';
describe('ol/geom/flat/lineoffset.js', function () {
describe('offsetLineString', () => {
it('offsets a simple square', () => {
const flatCoords = [0, 0, 10, 0, 10, 10, 0, 10];
const offset = 2;
const result = offsetLineString(
flatCoords,
0,
flatCoords.length,
2,
offset,
false,
);
expect(result.length).to.be(8);
expect(result[0]).to.roughlyEqual(0, 1e-6);
expect(result[1]).to.roughlyEqual(2, 1e-6);
});
it('offsets a closed ring', () => {
const flatCoords = [0, 0, 10, 0, 10, 10, 0, 10, 0, 0];
const offset = 2;
const result = offsetLineString(
flatCoords,
0,
flatCoords.length,
2,
offset,
true,
);
expect(result.length).to.be(10);
expect(result[0]).to.roughlyEqual(2, 1e-6);
expect(result[1]).to.roughlyEqual(2, 1e-6);
expect(result[8]).to.roughlyEqual(2, 1e-6);
expect(result[9]).to.roughlyEqual(2, 1e-6);
});
it('handles negative offset', () => {
const flatCoords = [0, 0, 10, 0, 10, 10];
const offset = -2;
const result = offsetLineString(
flatCoords,
0,
flatCoords.length,
2,
offset,
false,
);
expect(result.length).to.be(6);
expect(result[1]).to.be(-2);
});
it('preserves additional dimensions with stride > 2', () => {
const flatCoords = [0, 0, 100, 10, 0, 200, 10, 10, 300];
const offset = 2;
const stride = 3;
const result = offsetLineString(
flatCoords,
0,
flatCoords.length,
stride,
offset,
false,
);
expect(result.length).to.be(9);
expect(result[2]).to.be(100);
expect(result[5]).to.be(200);
expect(result[8]).to.be(300);
});
it('uses provided destination array', () => {
const flatCoords = [0, 0, 10, 0];
const offset = 2;
const stride = 2;
const dest = [];
const result = offsetLineString(
flatCoords,
0,
flatCoords.length,
stride,
offset,
false,
dest,
);
expect(result).to.be(dest);
expect(dest.length).to.be(4);
});
it('handles different destination stride', () => {
const flatCoords = [0, 0, 10, 0];
const offset = 2;
const stride = 2;
const dest = [];
const destinationStride = 3;
const result = offsetLineString(
flatCoords,
0,
flatCoords.length,
stride,
offset,
false,
dest,
destinationStride,
);
expect(result.length).to.be(6);
expect(result[0]).to.be(0);
expect(result[1]).to.be(2);
expect(result[3]).to.be(10);
expect(result[4]).to.be(2);
});
it('handles empty line string', () => {
const flatCoords = [];
const offset = 2;
const result = offsetLineString(
flatCoords,
0,
flatCoords.length,
2,
offset,
false,
);
expect(result.length).to.be(0);
});
it('handles single point', () => {
const flatCoords = [5, 5];
const offset = 2;
const stride = 2;
const result = offsetLineString(
flatCoords,
0,
flatCoords.length,
stride,
offset,
false,
);
expect(result.length).to.be(2);
expect(result[0]).to.be(5);
expect(result[1]).to.be(7);
});
});
describe('removeOffsetCycles', () => {
it('returns empty array unchanged', () => {
const coords = [];
const result = removeOffsetCycles(coords, 2);
expect(result.length).to.be(0);
expect(result).to.be(coords);
});
it('returns line without intersections unchanged', () => {
const coords = [0, 0, 10, 0, 10, 10, 0, 10];
const original = [...coords];
const result = removeOffsetCycles(coords, 2);
expect(result).to.eql(original);
});
it('handles minimal input with insufficient points', () => {
const coords = [0, 0, 10, 10];
const result = removeOffsetCycles(coords, 2);
expect(result).to.eql(coords);
});
it('removes actual self-intersecting loop (bowtie shape)', () => {
const coords = [0, 0, 10, 10, 10, 0, 0, 10];
const result = removeOffsetCycles(coords, 2);
expect(result).to.be(coords);
expect(result.length).to.be(6);
expect(result[0]).to.be(0);
expect(result[1]).to.be(0);
expect(result[2]).to.be(5);
expect(result[3]).to.be(5);
expect(result[4]).to.be(0);
expect(result[5]).to.be(10);
});
it('preserves additional dimensions with stride > 2', () => {
const coords = [0, 0, 100, 10, 10, 200, 10, 0, 300, 0, 10, 400];
const result = removeOffsetCycles(coords, 3);
expect(result[2]).to.be(100);
});
it('removes two separate self-intersecting loops in longer path', () => {
const coords = [
0, 0, 10, 10, 10, 0, 0, 10, 5, 15, 0, 20, 10, 30, 10, 20, 0, 30,
];
const result = removeOffsetCycles(coords, 2);
expect(result).to.be(coords);
expect(result.length).to.be(14);
expect(result[0]).to.be(0);
expect(result[1]).to.be(0);
expect(result[2]).to.be(5);
expect(result[3]).to.be(5);
expect(result[8]).to.be(0);
expect(result[9]).to.be(20);
expect(result[10]).to.be(5);
expect(result[11]).to.be(25);
expect(result[12]).to.be(0);
expect(result[13]).to.be(30);
});
});
});