import type { IVec, IVec3 } from '@blocksuite/global/utils'; import { almostEqual } from '@blocksuite/global/utils'; import { describe, expect, it } from 'vitest'; import { AStarRunner } from '../utils/a-star.js'; function mergePath(points: IVec3[]) { if (points.length === 0) return points; const rst: IVec3[] = [points[0]]; for (let i = 1; i < points.length - 1; i++) { const cur = points[i]; const last = points[i - 1]; const next = points[i + 1]; if ( almostEqual(last[0], cur[0], 0.02) && almostEqual(cur[0], next[0], 0.02) ) continue; if ( almostEqual(last[1], cur[1], 0.02) && almostEqual(cur[1], next[1], 0.02) ) continue; rst.push(cur); } rst.push(points[points.length - 1]); return rst; } describe('a* algorithm', () => { /** * 0 ---------------- * | * | * ------------------- 0 */ it('width is greater than height', () => { const sp: IVec3 = [0, 0, 0]; const ep: IVec3 = [200, 100, 0]; const osp: IVec3 = [-1, 0, 0]; const oep: IVec3 = [201, 100, 0]; const points: IVec3[] = [ sp, ep, [100, 0, 0], [200, 0, 0], [0, 50, 0], [100, 50, 3], [200, 50, 0], [0, 100, 0], [100, 100, 0], ] as IVec3[]; const aStar = new AStarRunner(points, sp, ep, osp, oep); aStar.run(); let path: IVec[] | IVec3[] = aStar.path; path.pop(); path.shift(); path = mergePath(path); const expected = [ [0, 0], [100, 0], [100, 100], [200, 100], ]; path.forEach((p, i) => { expect(p[0]).toBe(expected[i][0]); expect(p[1]).toBe(expected[i][1]); }); }); /** * 0 * | * | * | * |----| * | * | * | * 0 */ it('height is greater than width', () => { const sp: IVec3 = [0, 0, 0]; const ep: IVec3 = [100, 200, 0]; const osp: IVec3 = [0, -1, 0]; const oep: IVec3 = [100, 201, 0]; const points: IVec3[] = [ sp, [50, 0, 0], [100, 0, 0], [0, 100, 0], [50, 100, 3], [100, 100, 0], [0, 200, 0], [50, 200, 0], ep, ]; const aStar = new AStarRunner(points, sp, ep, osp, oep); aStar.run(); let path = aStar.path; path.pop(); path.shift(); path = mergePath(path); const expected = [ [0, 0], [0, 100], [100, 100], [100, 200], ]; path.forEach((p, i) => { expect(p[0]).toBe(expected[i][0]); expect(p[1]).toBe(expected[i][1]); }); }); });