Skip to content

Commit

Permalink
fix(amapPolygonPath2GeoJSONCoords): 传空数组时抛异常
Browse files Browse the repository at this point in the history
  • Loading branch information
xyy94813 committed Oct 14, 2023
1 parent 0c01879 commit 7be6f83
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 7 deletions.
44 changes: 44 additions & 0 deletions src/helpers/__tests__/amapHelper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
isLatLng,
isLatLngArr,
} from '../amapHelper';

describe('isLatLng', () => {
test('should return true for valid LngLat object', () => {
const input = { lat: 123, lng: 456 };
expect(isLatLng(input)).toBe(true);
});

test('should return false for invalid LngLat object', () => {
const input = { lat: 123 };
expect(isLatLng(input)).toBe(false);
});

test('should return false for non-LngLat object', () => {
const input = { foo: 'bar' };
expect(isLatLng(input)).toBe(false);
});
});

describe('isLatLngArr', () => {
test('returns true for an empty array', () => {
expect(isLatLngArr([])).toBe(true);
});

test('returns true for an array with valid LngLat objects', () => {
const validArray = [
{ lat: 123, lng: 456 },
];
expect(isLatLngArr(validArray)).toBe(true);
});

test('returns false for an array with invalid objects', () => {
const invalidArray = [
{ lat: 1, lng: 1 },
{ foo: 'bar' }, // Invalid object
];
expect(isLatLngArr(invalidArray)).toBe(false);
});

// Add more test cases as needed
});
137 changes: 137 additions & 0 deletions src/helpers/__tests__/amapPolygonPath2GeoJSONCoords.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import amapPolygonPath2GeoJSONCoords from '../amapPolygonPath2GeoJSONCoords';

// mock LngLat class
class LngLat {
public lat: number;

public lng: number;

constructor(lng: number, lat: number) {
this.lat = lat;
this.lng = lng;
}

public toArray() {
return [this.lng, this.lat];
}
}

// mock AMap api
const AMap = {
LngLat,
};

describe('amapPolygonPath2GeoJSONCoords', () => {
test('should convert AMap polygon path to GeoJSON coordinates', () => {
const amapPath: ReturnType<AMap.Polygon['getPath']> = [
new AMap.LngLat(1, 2),
new AMap.LngLat(3, 4),
new AMap.LngLat(5, 6),
];
const expectedCoords: typeof amapPath = [
[1, 2],
[3, 4],
[5, 6],
[1, 2],
];
const result = amapPolygonPath2GeoJSONCoords(amapPath);
expect(result).toEqual(expectedCoords);
});

test('should convert correctly if it is a Polygon that has a hole', () => {
const amapPolygonWithHolePath: ReturnType<AMap.Polygon['getPath']>[] = [
// outer-line
[
new AMap.LngLat(0, 0),
new AMap.LngLat(0, 10),
new AMap.LngLat(10, 0),
],
// inner-line
[
new AMap.LngLat(1, 1),
new AMap.LngLat(1, 2),
new AMap.LngLat(2, 1),
],
];
const expectedCoords: typeof amapPolygonWithHolePath = [
[
[0, 0],
[0, 10],
[10, 0],
[0, 0],
],
[
[1, 1],
[1, 2],
[2, 1],
[1, 1],
],
];
const result = amapPolygonPath2GeoJSONCoords(amapPolygonWithHolePath);
expect(result).toEqual(expectedCoords);
});

test('should convert correctly if it is a MultiPolygon that has a hole', () => {
const amapMultiPolygonPath: ReturnType<AMap.Polygon['getPath']>[] = [
// polygon 1
[
[
new AMap.LngLat(0, 0),
new AMap.LngLat(0, 10),
new AMap.LngLat(10, 0),
],
[
new AMap.LngLat(1, 1),
new AMap.LngLat(1, 2),
new AMap.LngLat(2, 1),
],
],
// polygon 2
[
[
new AMap.LngLat(0, 0),
new AMap.LngLat(0, 10),
new AMap.LngLat(10, 0),
],
[
new AMap.LngLat(1, 1),
new AMap.LngLat(1, 2),
new AMap.LngLat(2, 1),
],
],

];
const expectedCoords: typeof amapMultiPolygonPath = [
// polygon 1
[
[
[0, 0], [0, 10], [10, 0], [0, 0],
],
[
[1, 1], [1, 2], [2, 1], [1, 1],
],
],
// polygon 2
[
[
[0, 0], [0, 10], [10, 0], [0, 0],
],
[
[1, 1], [1, 2], [2, 1], [1, 1],
],
],
];
const result = amapPolygonPath2GeoJSONCoords(amapMultiPolygonPath);
expect(result).toEqual(expectedCoords);
});

test('should handle empty polygon path', () => {
const emptyPath: ReturnType<AMap.Polygon['getPath']> = [];
const result = amapPolygonPath2GeoJSONCoords(emptyPath);
expect(result).toEqual(emptyPath);
});

test('should throw an error if the input is not an array', () => {
expect(() => amapPolygonPath2GeoJSONCoords(undefined)).toThrowError('invalid path');
});
});
3 changes: 3 additions & 0 deletions src/helpers/amapHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const isLatLng = (p: any): p is AMap.LngLat => !!('lat' in p && 'lng' in p);

export const isLatLngArr = (p: any): p is AMap.LngLat[] => p.every(isLatLng);
22 changes: 15 additions & 7 deletions src/helpers/amapPolygonPath2GeoJSONCoords.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
const isLatLng = (p: any): p is AMap.LngLat => !!('lat' in p && 'lng' in p);
const isLatLngArr = (p: any): p is AMap.LngLat[] => p.every(isLatLng);
import { isLatLngArr } from './amapHelper';

/**
* 补充最后一个 Position。
* 支持转换至 GeoJSON.Polygon 和 GeoJSON.MultiplePolygon 的 coords
*/
- * 补充最后一个 Position。
- * 支持转换至 GeoJSON.Polygon 和 GeoJSON.MultiplePolygon 的 coords
+ * 将 AMap 多边形路径转换为 GeoJSON 坐标。
+ *
+ * @param path - 要转换的 AMap.Polygon 路径。
+ * @returns 转换后的 GeoJSON 坐标。
*/
const amapPolygonPath2GeoJSONCoords = (
path: ReturnType<AMap.Polygon['getPath']>,
): typeof path => {
if (isLatLngArr(path)) {
if (!Array.isArray(path)) throw Error('invalid path');

// 检查路径是否是一个 LatLng 数组,并且至少有一个元素
if (isLatLngArr(path) && path.length > 0) {
// 将路径中的每个 LatLng 项转换为一个坐标数组
const coords = path.map((item) => item.toArray());
// 将第一个坐标添加到末尾以闭合多边形
coords.push(coords[0].slice(0) as [number, number]);
return coords;
}

// trick way
// 递归地将每个嵌套的路径转换为 GeoJSON 坐标
return (path as AMap.LngLat[][][])!.map(amapPolygonPath2GeoJSONCoords);
};

Expand Down

0 comments on commit 7be6f83

Please sign in to comment.