Skip to content

Commit

Permalink
Merge pull request #204 from VisActor/feat/cartesian-to-polar
Browse files Browse the repository at this point in the history
feat: add `cartesianToPolar` util function
  • Loading branch information
xile611 authored Sep 19, 2024
2 parents fc0db18 + cedfd41 commit cfa507c
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@visactor/vutils",
"comment": "feat: add `cartesianToPolar` util",
"type": "none"
}
],
"packageName": "@visactor/vutils"
}
34 changes: 33 additions & 1 deletion packages/vutils/__tests__/angle.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { findBoundaryAngles, normalizeAngle, polarToCartesian, calculateMaxRadius, computeQuadrant } from '../src';
import {
findBoundaryAngles,
normalizeAngle,
polarToCartesian,
calculateMaxRadius,
computeQuadrant,
cartesianToPolar
} from '../src';

describe('angle utils', () => {
it('normalizeAngle', () => {
Expand Down Expand Up @@ -55,3 +62,28 @@ describe('angle utils', () => {
expect(computeQuadrant(4)).toBe(4);
});
});

describe('cartesianToPolar', () => {
test('should convert point at origin to polar coordinates', () => {
const result = cartesianToPolar({ x: 0, y: 0 });
expect(result).toEqual({ radius: 0, angle: 0 });
});

test('should convert point with center at origin', () => {
const result = cartesianToPolar({ x: 3, y: 4 });
expect(result.radius).toBe(5);
expect(result.angle).toBeCloseTo(Math.atan2(4, 3), 5);
});

test('should convert point with center not at origin', () => {
const result = cartesianToPolar({ x: 11, y: 11 }, { x: 10, y: 10 });
expect(result.radius).toBeCloseTo(Math.sqrt(2), 5);
expect(result.angle).toBeCloseTo(Math.PI / 4, 5);
});

test('should return correct polar coordinates within specified angle range', () => {
const result = cartesianToPolar({ x: 11, y: 11 }, { x: 10, y: 10 }, -Math.PI / 2, (3 * Math.PI) / 2);
expect(result.radius).toBeCloseTo(Math.sqrt(2), 5);
expect(result.angle).toBeCloseTo(Math.PI / 4, 5);
});
});
48 changes: 48 additions & 0 deletions packages/vutils/src/angle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,54 @@ export function polarToCartesian(center: IPointLike, radius: number, angleInRadi
};
}

/**
* 根据笛卡尔坐标系坐标计算极坐标坐标点
* @param point
* @param center 极坐标系中心点坐标
* @param startAngle 极坐标系起始角度
* @param endAngle 极坐标系结束角度
* @returns 极坐标系坐标点
*/
export function cartesianToPolar(
point: IPointLike,
center: IPointLike = { x: 0, y: 0 },
startAngle = 0,
endAngle = 2 * Math.PI
) {
const { x, y } = point;
const { x: centerX, y: centerY } = center;

let dx = x - centerX;
let dy = y - centerY;
const radius = Math.sqrt(dx * dx + dy * dy);

if (radius === 0) {
return {
radius: 0,
angle: 0
};
}

dx /= radius;
dy /= radius;

let radian = Math.atan2(dy, dx);
if (radian < startAngle) {
while (radian <= startAngle) {
radian += Math.PI * 2;
}
}
if (radian > endAngle) {
while (radian >= endAngle) {
radian -= Math.PI * 2;
}
}
return {
radius,
angle: radian
};
}

/**
* 根据点的笛卡尔坐标获取该点与圆心的连线同正 x 轴方向的夹角
* @param center 圆心坐标
Expand Down

0 comments on commit cfa507c

Please sign in to comment.