From 98d146da8fdc31270d44ee5767fd87a249cf6781 Mon Sep 17 00:00:00 2001 From: EasyRo Date: Sat, 25 Mar 2023 23:29:09 +0800 Subject: [PATCH] add geometric calculation --- src/coordinatesInCircle/index.md | 29 ++++++++++++ src/coordinatesInCircle/index.ts | 41 +++++++++++++++++ src/coordinatesInRect/index.md | 31 +++++++++++++ src/coordinatesInRect/index.ts | 31 +++++++++++++ src/index.ts | 3 ++ src/judgePointInCircle/index.md | 38 +++++++++++++++ src/judgePointInCircle/index.ts | 33 +++++++++++++ test/geometricCalculations.test.js | 74 ++++++++++++++++++++++++++++++ 8 files changed, 280 insertions(+) create mode 100644 src/coordinatesInCircle/index.md create mode 100644 src/coordinatesInCircle/index.ts create mode 100644 src/coordinatesInRect/index.md create mode 100644 src/coordinatesInRect/index.ts create mode 100644 src/judgePointInCircle/index.md create mode 100644 src/judgePointInCircle/index.ts create mode 100644 test/geometricCalculations.test.js diff --git a/src/coordinatesInCircle/index.md b/src/coordinatesInCircle/index.md new file mode 100644 index 0000000..89a6c89 --- /dev/null +++ b/src/coordinatesInCircle/index.md @@ -0,0 +1,29 @@ +--- +title: coordinatesInCircle - 生成圆内任意坐标 +nav: + title: 使用文档 + path: /lib +group: + path: /geometricCalculations + title: 几何计算 + order: 13 +--- + +## coordinatesInCircle(center, r) + +> 生成圆内任意坐标 +> +> 参数 +> +> center: 圆心的坐标 +> +> r: 圆的半径 + +Demo: + +```tsx | pure +import { coordinatesInCircle } from 'xijs'; + +const point = coordinatesInCircle([2, 3], 2); +console.log(point); // -> [ 2, 4 ] +``` diff --git a/src/coordinatesInCircle/index.ts b/src/coordinatesInCircle/index.ts new file mode 100644 index 0000000..32914c2 --- /dev/null +++ b/src/coordinatesInCircle/index.ts @@ -0,0 +1,41 @@ +/** + * @param center 表示圆心的 x, y 坐标 + * @param r 表示圆的半径 + * @returns 返回圆内的任意坐标 + */ + +function coordinatesInCircle( + center: [number, number], + r: number = 1, +): [number, number] { + if (center && Array.isArray(center) && center.length === 2) { + const [xAxis, yAxis]: [number, number] = center, + xValueRange: [number, number] = [xAxis - r, xAxis + r], + yValueRange: [number, number] = [yAxis - r, yAxis + r]; + + let pointX: number, pointY: number; + + while (true) { + // 生成大于等于 xValueRange[0],小于等于 xValueRange[1] 的 x 坐标 + pointX = + Math.floor(Math.random() * (xValueRange[1] - xValueRange[0] + 1)) + + xValueRange[0]; + // 生成大于等于 yValueRange[0],小于等于 yValueRange[1] 的 y 坐标 + pointY = + Math.floor(Math.random() * (yValueRange[1] - yValueRange[0] + 1)) + + yValueRange[0]; + + // 距离圆心的长度 + const sumOfSquares: number = + Math.pow(pointX - xAxis, 2) + Math.pow(pointY - yAxis, 2); + const distanceToCircle: number = Math.sqrt(sumOfSquares); + if (distanceToCircle <= r) { + return [pointX, pointY]; + } + } + } else { + throw new Error('Please enter correct parameters.'); + } +} + +export default coordinatesInCircle; diff --git a/src/coordinatesInRect/index.md b/src/coordinatesInRect/index.md new file mode 100644 index 0000000..77c7d3f --- /dev/null +++ b/src/coordinatesInRect/index.md @@ -0,0 +1,31 @@ +--- +title: coordinatesInRect - 生成矩形内任意坐标 +nav: + title: 使用文档 + path: /lib +group: + path: /geometricCalculations + title: 几何计算 + order: 14 +--- + +## coordinatesInRect(startPos, w, h) + +> 生成矩形内任意坐标 +> +> 参数 +> +> startPos: 左上顶点的坐标 +> +> w: 矩形的宽 +> +> h: 矩形的高 + +Demo: + +```tsx | pure +import { coordinatesInRect } from 'xijs'; + +const point = coordinatesInRect([3, 4], 5, 6); +console.log(point); // -> [ 5, 7 ] +``` diff --git a/src/coordinatesInRect/index.ts b/src/coordinatesInRect/index.ts new file mode 100644 index 0000000..30b801d --- /dev/null +++ b/src/coordinatesInRect/index.ts @@ -0,0 +1,31 @@ +/** + * @param startPos 左上顶点坐标 + * @param w 矩形的宽 + * @param h 矩形的高 + * @returns 返回矩形内的任意坐标 + */ +function coordinatesInRect( + startPos: [number, number], + w: number, + h: number, +): [number, number] { + if ( + startPos && + Array.isArray(startPos) && + startPos.length === 2 && + typeof w === 'number' && + typeof h === 'number' + ) { + const [x0, y0]: [number, number] = startPos; + // 生成大于等于 x0,小于等于 x0 + w 的 x 坐标 + const pointX: number = Math.floor(Math.random() * (w + 1)) + x0; + // 生成大于等于 y0,小于等于 y0 + h 的 y 坐标 + const pointY: number = Math.floor(Math.random() * (h + 1)) + y0; + + return [pointX, pointY]; + } else { + throw new Error('Please enter correct parameters.'); + } +} + +export default coordinatesInRect; diff --git a/src/index.ts b/src/index.ts index 0da25f6..756d419 100644 --- a/src/index.ts +++ b/src/index.ts @@ -33,3 +33,6 @@ export { default as hex2rgba } from './hex2rgba'; export { default as formatNumber } from './formatNumber'; export { default as formatPercent } from './formatPercent'; export { default as difference } from './difference'; +export { default as coordinatesInCircle } from './coordinatesInCircle'; +export { default as coordinatesInRect } from './coordinatesInRect'; +export { default as judgePointInCircle } from './judgePointInCircle'; diff --git a/src/judgePointInCircle/index.md b/src/judgePointInCircle/index.md new file mode 100644 index 0000000..4b5631d --- /dev/null +++ b/src/judgePointInCircle/index.md @@ -0,0 +1,38 @@ +--- +title: judgePointInCircle - 判断一点是否在圆内 +nav: + title: 使用文档 + path: /lib +group: + path: /geometricCalculations + title: 几何计算 + order: 13 +--- + +## judgePointInCircle(circle, x, y) + +> 判断一点是否在圆内 +> +> 参数 +> +> circle: 描述圆形信息的对象,包含 center 属性和 r 属性,center 表示圆心的坐标,r 表示圆的半径。 +> +> x: 该点的 x 轴坐标 +> +> y: 该点的 y 轴坐标 + +Demo: + +```tsx | pure +import { judgePointInCircle } from 'xijs'; + +const res = judgePointInCircle( + { + center: [3, 4], + r: 5, + }, + 4, + 6, +); +console.log(res); // -> true +``` diff --git a/src/judgePointInCircle/index.ts b/src/judgePointInCircle/index.ts new file mode 100644 index 0000000..a51f9c3 --- /dev/null +++ b/src/judgePointInCircle/index.ts @@ -0,0 +1,33 @@ +/** + * @param circle 描述圆形信息的对象,包含 center 属性和 r 属性,center 表示圆心的坐标,r 表示圆的半径。 + * @param x 该点的 x 轴坐标 + * @param y 该点的 y 轴坐标 + * @returns 如果该点在圆内,返回 true,否则返回 false。 + */ +function judgePointInCircle( + circle: { center: [number, number]; r: number; [propName: string]: any }, + x: number, + y: number, +): boolean { + if ( + circle && + circle.center && + circle.center.length === 2 && + typeof circle.r === 'number' && + typeof x === 'number' && + typeof y === 'number' + ) { + const { center, r }: { center: [number, number]; r: number } = circle; + const [centerX, centerY]: [number, number] = center; + + const sumOfSquares: number = + Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2); + const distanceToCircle: number = Math.sqrt(sumOfSquares); + + return distanceToCircle <= r; + } else { + throw new Error('Please enter correct parameters.'); + } +} + +export default judgePointInCircle; diff --git a/test/geometricCalculations.test.js b/test/geometricCalculations.test.js new file mode 100644 index 0000000..bcba574 --- /dev/null +++ b/test/geometricCalculations.test.js @@ -0,0 +1,74 @@ +import { + coordinatesInCircle, + coordinatesInRect, + judgePointInCircle, +} from '../src/index'; + +describe('几何计算相关测试', () => { + test('生成圆内任意坐标', () => { + const circleArr = [ + [[2, 3], 2], + [[3, 3], 5], + [[0, 0], 3], + ]; + circleArr.forEach((circle) => { + const point = coordinatesInCircle(circle[0], circle[1]), + [x, y] = circle[0], + sumOfSquares = Math.pow(point[0] - x, 2) + Math.pow(point[1] - y, 2), + distance = Math.sqrt(sumOfSquares); + expect(distance).toBeLessThanOrEqual(circle[1]); + }); + }); + test('生成矩形内任意坐标', () => { + const rectArr = [ + [[3, 4], 5, 6], + [[2, 3], 1, 3], + [[5, 7], 8, 4], + ]; + + rectArr.forEach((rect) => { + const [startPos, w, h] = rect; + const [pointX, pointY] = coordinatesInRect(startPos, w, h); + + expect(pointX).toBeLessThanOrEqual(startPos[0] + w); + expect(pointX).toBeGreaterThanOrEqual(startPos[0]); + + expect(pointY).toBeLessThanOrEqual(startPos[1] + h); + expect(pointY).toBeGreaterThanOrEqual(startPos[1]); + }); + }); + test('判断一点是否在圆内', () => { + const circleArr = [ + { + center: [3, 4], + r: 5, + }, + { + center: [2, 3], + r: 4, + }, + { + center: [1, 0], + r: 3, + }, + ]; + const point = [ + { + coordinates: [3, 5], + expect: true, + }, + { + coordinates: [2, 7], + expect: true, + }, + { + coordinates: [1, 4], + expect: false, + }, + ]; + circleArr.forEach((circle, index) => { + const res = judgePointInCircle(circle, ...point[index].coordinates); + expect(res).toEqual(point[index].expect); + }); + }); +});