前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >平面几何:求内接或外切于圆的正多边形

平面几何:求内接或外切于圆的正多边形

作者头像
前端西瓜哥
发布2024-04-03 20:26:21
930
发布2024-04-03 20:26:21
举报

大家好,我是前端西瓜哥。

如题,今天来看两个算法实现。

求和圆内接的正多边形

方法参数有:

  1. center:圆心位置;
  2. start:正多边形上的一个点,和 center 的距离即圆的半径;
  3. count:多边形边数。

返回值为多边形上连续的点数组。

思路是,让起点基于圆心旋转 PI * 2 / count 度数的倍数,执行 count - 1 次,拿到所有的点。

算法实现:

代码语言:javascript
复制
/**
 * 计算和圆内接的正多边形
 * @param center 圆心
 * @param start 起点
 * @param count 边数
 */
export const getInternalTanRegularPolygon = (
  center: Point,
  start: Point,
  count: number,
) => {
  const points: Point[] = [{ ...start }];
  const step = (Math.PI * 2) / count;
  for (let i = 1; i < count; i++) {
    points.push(rotate(start, center, step * i));
  }
  return points;
};

这里用到一个辅助方法 rotate:计算一个点以另一个点为旋转中心,旋转特定弧度后的点。

代码语言:javascript
复制
const rotate = (p: Point, center: Point, rad: number) => {
  const dx = p.x - center.x;
  const dy = p.y - center.y;
  const cos = Math.cos(rad);
  const sin = Math.sin(rad);
  return {
    x: center.x + dx * cos - dy * sin,
    y: center.y + dx * sin + dy * cos,
  };
};

上面这个写法是很朴实的解析几何推导出来的。

或者用矩阵的方式表达,可读性更好,但通常需要引入一个矩阵库,下面是 pixi.js 的写法:

代码语言:javascript
复制
const rotate = (p: Point, center: Point, rad: number) => {
  const matrix = new Matrix()
    .translate(-center.x, -center.y) // (3) 坐标轴回到原来位置
    .rotate(rad) // (2) 旋转
    .translate(center.x, center.y); // (1) 坐标轴原点移动到 center

  return matrix.apply(p);
};

这里所有的点都是基于起点 start 旋转不同的度数得到的。

也可以基于旋转后的点,继续旋转,这样可以复用旋转矩阵,计算量会少一点。

二者的结果不完全相同,因为各自的实现有各自的误差,但很小,可以忽略不计。

求和圆外切的正多边形

外切要求的效果如下,start 为多边形其中一边的中点,其他同上。

思路是计算一个新的起点 start,然后应用前的的外切方法。

首先 start 基于 center 旋转 PI / count

然后计算 外切时半径距离<center, start> 的比值 t,为 1 / cos(PI / count)

基于 t 使用 线性插值,计算出外切时的 start。

如果你不知道线性插值是什么,可以看我的这篇文章: 《平面几何算法:求点到直线和圆的最近点

算法实现:

代码语言:javascript
复制
/**
 * 计算和圆外切的正多边形
 * @param center 圆心
 * @param start 起点
 * @param count 边数
 */
export const getExternalTanRegularPolygon = (
  center: Point,
  start: Point,
  count: number,
) => {
  // 转换为内接多边形,计算新的 start
  const offsetAngle = Math.PI / count;
  start = rotate(start, center, offsetAngle);
  const t = 1 / Math.cos(offsetAngle);
  start = {
    x: center.x + (start.x - center.x) * t,
    y: center.y + (start.y - center.y) * t,
  };

  return getInternalTanRegularPolygon(center, start, count);
};

效果演示

结尾

内接正多边形的思路为:起点基于圆心旋转边数次数,所产生的点集。

外切正多边形,可以转换为求内接,只需要用三角函数和线性插值计算等价的内接下的起点。

我是前端西瓜哥,关注我,学习更多平面几何知识。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-03-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端西瓜哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 求和圆内接的正多边形
  • 求和圆外切的正多边形
  • 效果演示
  • 结尾
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档