正多边形的数学推导及绘制

正多边形是一种很有意思的图形,但是如果想要绘制一个正多边形并不是那么容易的。最近看书介绍了这一块的内容,但是它只是很简单的描述了一下,并没有详细的过程。所以自己推导了一下,在这里记录一下。这种推导方式是通用的,在其它任何的绘图库中都是可以使用的。在这里我使用canvas来实现绘制。

坐标推导

在这里插入图片描述

绘制正多边形的关键点在于需要计算出多边形顶点的位置,这里需要利用到一些三角函数的简单知识。我这里以正八边形为例子进行举例。正多边形的顶点都在其外接圆上,所以
正多边形上任意一个顶点的坐标为:
x = r * cos(θ)
y = r * sin(θ)
这里只是简单的初中三角函数的知识。

canvas 绘制

我们在计算机上进行绘图,它的坐标系是下图所示的。在上一个图中,它是默认坐标原点作为圆心的,不具有一般性。所以我们需要将它转化为下面这样的形式,这张图片是我用canvas绘制的,有点简陋,大家凑合着看吧。
这里介绍一下已知条件:
圆心 (X, Y)
半径 R
角度 θ

所以 点0 的坐标为:
x0 = X + R * cos(θ)
y0 = Y - R * sin(θ)

其它点的坐标也可以由上式进行推导,区别在于 角度θ 值不同,且因为是正多边形,角度是倍数关系。角度θ = 360/边数
在这里插入图片描述

通过前面的推导,我们只需要知道一个需要绘制的正多边形外接圆圆心的位置和外接圆的半径,就可以绘制任意一个正多边形了。下面我们就来尝试使用 canvas 进行绘制!
这里我们尝试来绘制一个正八边形:
圆心位置为:(250, 250)
半径为:100

在这里插入图片描述

let canvas = document.getElementById("canvas"),
			context = canvas.getContext("2d");
		
let centerX = 250,   // 外接圆圆心 x 坐标
	cneterY = 250,   // 外接圆圆心 y 坐标
	r = 100,         // 外接圆半径
	sides = 8,       // 外接圆边数
	points = [];     // 存储外接圆各个顶点的数组
let angle = 0;  // 多边形的角度,弧度制
for (let i = 0; i < sides; i++) {
	x = centerX + r * Math.sin(angle);
	y = cneterY - r * Math.cos(angle);
	angle += 2*Math.PI/sides;
	points.push({x:x, y:y});
}
console.log(points);
context.beginPath();

context.moveTo(points[0].x, points[0].y);

for (let i = 1; i < sides; i++) {
	context.lineTo(points[i].x, points[i].y);
}
context.closePath();
context.stroke();

这里我在绘制图上增加了数字,数字表示绘制的先后顺序,但是在实际代码中将其删除了。
所以绘制一个正多边形的步骤是:
通过圆心、半径及角度计算出各个顶点的位置,然后一次连线各个顶点即可。从初始点连接到初始点或者连接到最后一条,然后调用 closePath() 方法,这里是采用这种方式。

封装

将绘制正多边形的步骤封装成一个函数,这里会绘制几个例子。

/*
	x 外接圆圆心 x坐标
	y 外接圆圆心 y坐标
	r 外接圆半径
*/
function drawPolygon(centerX, centerY, radius, sides) {
	let angle = 0;
	let points = []
	
	// 求各个顶点的坐标
	for (let i = 0; i < sides; i++) {
		x = centerX + radius * Math.sin(angle);
		y = centerY - radius * Math.cos(angle);
		angle += 2*Math.PI/sides;
		points.push({x: x, y: y});
	}
	console.log(points);
	// 顶点坐标连线,先移动到第一个顶点
	context.moveTo(points[0].x, points[0].y);
	// 依次开始连线
	for (let i = 1; i < sides; i++) {
		context.lineTo(points[i].x, points[i].y);
	}
	// 关闭路径,使得最后一点和第一点闭合
	context.closePath();
	context.stroke();
}

依次绘制三角形、四边形到十边形。

drawPolygon(100, 150, 100, 3);
drawPolygon(300, 150, 100, 4);
drawPolygon(500, 150, 100, 5);
drawPolygon(700, 150, 100, 6);
drawPolygon(100, 400, 100, 7);
drawPolygon(300, 400, 100, 8);
drawPolygon(500, 400, 100, 9);
drawPolygon(700, 400, 100, 10);

在这里插入图片描述

旋转

这样绘制的多边形都是在垂直方向上对称的(这个从上面的推导中得出),我们需要的是任意的多边形,这里还不够任意,多边形应该可以在此基础上进行旋转才行。所以,需要给绘制多边形的函数多增加一个起始角度参数。

/*
	x 外接圆圆心 x坐标
	y 外接圆圆心 y坐标
	r 外接圆半径
	startAngle 起始旋转角度
*/
function drawPolygon(centerX, centerY, radius, sides, startAngle) {
	let angle = startAngle || 0;
	let points = []
	
	// 求各个顶点的坐标
	for (let i = 0; i < sides; i++) {
		x = centerX + radius * Math.sin(angle);
		y = centerY - radius * Math.cos(angle);
		angle += 2*Math.PI/sides;
		points.push({x: x, y: y});
	}
	console.log(points);
	// 顶点坐标连线,先移动到第一个顶点
	context.moveTo(points[0].x, points[0].y);
	// 依次开始连线
	for (let i = 1; i < sides; i++) {
		context.lineTo(points[i].x, points[i].y);
	}
	// 关闭路径,使得最后一点和第一点闭合
	context.closePath();
	context.stroke();
}

这里将正四边形、正六边形、正八边形和正十边形进行旋转,让他们最上面的边是水平放置的。

drawPolygon(100, 150, 100, 3);
drawPolygon(300, 150, 100, 4, 45/180*Math.PI);
drawPolygon(500, 150, 100, 5);
drawPolygon(700, 150, 100, 6, 30/180*Math.PI);
drawPolygon(100, 400, 100, 7);
drawPolygon(300, 400, 100, 8, 22.5/180*Math.PI);
drawPolygon(500, 400, 100, 9);
drawPolygon(700, 400, 100, 10, 18/180*Math.PI);

在这里插入图片描述

结语

好了,看到了这里的时候,想必你已经对如何推导及绘制正多边形有所了解了。一定要尝试自己去经历推导和绘制的过程,那是非常有趣的事情。已经有很多人写了类似的内容,我也参考了其它人写的,但是总是感觉有一些迷惑的地方。索性自己来亲自推导,绘制一遍,并记录这个过程,现在这一块的内容我已经比较了解了。纸上得来终觉浅,绝知此事要躬行。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用Python绘制正多边形,可以使用以下方法: 首先,需要导入turtle库。然后,通过定义函数来绘制正多边形。可以使用get_side_lenth函数计算边长,get_exterior_angle函数计算外角度数。接着,在_init_函数中设置画笔和画布的属性,例如颜色、大小和速度等。最后,使用custom_regular_polygon函数来绘制正多边形。 以下是一个示例代码: ```python import turtle import math def _init_(angle, radius, pencolor='black', bgcolor='white', pensize=25, speed=0): an = angle r = radius turtle.hideturtle() turtle.pencolor(pencolor) turtle.bgcolor(bgcolor) turtle.pensize(pensize) turtle.speed(speed) turtle.pu() turtle.goto(0, r) turtle.seth(180) turtle.left(an / 2) turtle.pd() def get_side_lenth(radius, number_of_side): nos = number_of_side r = radius ls = math.sin(math.radians(180 / nos)) * 2 * r return ls def get_exterior_angle(nos): an = 360 / nos return an def custom_regular_polygon(number_of_side, lenth_of_side, angle): nos = number_of_side ls = lenth_of_side an = angle for i in range(nos): turtle.forward(ls) turtle.left(an) print(f'正{nos}边形绘画完毕。\nDone.') # 调用函数绘制正多边形 _init_(radius=100, angle=90) custom_regular_polygon(number_of_side=4, lenth_of_side=200, angle=90) turtle.done() ``` 这段代码将绘制一个正方形,边长为200,半径为100。 希望这个例子能帮到你。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [python turtle绘制正多边形](https://blog.csdn.net/starlight_2007/article/details/128391732)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值