![在这里插入图片描述](https://img-blog.csdnimg.cn/20201031182417341.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDIwODE4,size_16,color_FFFFFF,t_70#pic_center)
高中时候,从一个哥们儿那学到了怎么画上边这个图。其实不难,就是随便画个框,然后在框里边画类似于螺旋线的东西,循环迭代,最后汇聚到一起的时候就完成。![在这里插入图片描述](https://img-blog.csdnimg.cn/2020103118363218.gif#pic_center)
突然想到,可不可以写程序来画这个?
要素 | 要求、说明 |
---|
外边框 | 内角不能超过180度[否则无法正常循环] |
螺旋线偏角 | [偏角:相对于原来的边而言]不能太大 |
每次绘线长度 | 这个需要计算 |
特殊情况 | 随机边框总会长短不一,会导致某些较短的边在循环迭代中长度首先变得过短,那么需要跳过该边[如上动图中左下角的短边】,否则会导致异常 |
结束判断 | 1. 如果迭代过程中,由于跳过“边”导致当前多边形边数小于2,,那么停止;或者,2. 不断地迭代,边数满足要求,但是当前最长边小于某个“小值”,那么结束。 |
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201031185841920.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDIwODE4,size_16,color_FFFFFF,t_70#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201031190209705.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDIwODE4,size_16,color_FFFFFF,t_70#pic_center)
【途中绿色边】
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201031190756717.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDIwODE4,size_16,color_FFFFFF,t_70#pic_center)
结束条件很判断很容易实现,偏角也可以设置的比较小。那么还剩下的就是每次绘线的长度,该怎么计算?
其实方法就在标题里,正弦定理。
是怎么跟正弦定理扯上关系的呢,上图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020103119424171.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDIwODE4,size_16,color_FFFFFF,t_70#pic_center)
首先绘出的是边框,所以,我们可以很容易记录每条边的长度,以及其相对于x轴的偏角{0~360},甚至多边形顶点的坐标。或者说,我们在绘制边框的时候,按我们的规则,让绘制的同时,让程序记录下我们需要的这些基础数据。
-
所以,按照这个思路。途中蓝色的数据都是已知值。那么很容易可以得到:
Θ3 = Θ2 - Θ1
Θ4 = 180 - Θ3
Θ5 = 180 - Θ4 - dΘ
参数 | 说明 |
---|
L1 | ab边的长度 |
L2 | bc边的长度 |
Θ1 | ab边相对于x轴的偏角[0-360] |
Θ2 | bc边相对于x轴的偏角[0-360] |
dΘ | 每次画螺旋线的偏角 |
L3 | 当前螺旋线(长度) |
于是,根据正弦定理:
L1 / sin(Θ5) = L3 / sin(Θ4) = dL2 / sin(dΘ)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201031210604575.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDIwODE4,size_16,color_FFFFFF,t_70#pic_center)
到这里,我们已经算得了需要的参数。
细细分析,完成一次运算,所用到的无非两个数据:ab向量,bc向量。
所以在存取数据初始数据的时候,可以约定如下:
-
多边形的每条边向量(默认逆时针:如ab,bc,而非cb,ba…)作为一个单独的数据集,保存的内容依次为[与x轴偏角 0-360]、[向量长度(边长)]、[向量起始点坐标]
-
每条数据按照逆时针的方向存储到列表中。如:[[a],[b],[c]…]
-
每次根据上述过程,选取相邻两个数据计算所需数据值。
-
于是, 当前画线的偏角(相对于x轴)为Θ1+dΘ,画线长度为L3.
-
之后,需要更新Θ1=Θ1+dΘ,L1=L3,L2=L2-dL2,还有更新b点为当前绘图终点。
其实数据更新过程很好理解,每次画线后,需要对当前两个向量更新。ab‘向量长度,偏角都改变,但是起始坐标没改变。bc’向量偏角没变,但是长度与起始坐标改变。
显而易见,这些推理适用于符合刚开始约束条件下的所有相邻边。
就如刚开始分析的那样,有的边,他画着画着就没了,所以程序应该及时识别出它,然后剔除掉。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201031201951782.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDIwODE4,size_16,color_FFFFFF,t_70#pic_center)
该怎么去判断呢,上图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201031202041744.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDIwODE4,size_16,color_FFFFFF,t_70#pic_center)
需要跳边,都是L2过短,如上图。
由于L3,dL2,都是根据正弦定理得出[其实追究到底,是由L1和Θ1,Θ2,dΘ通过一些列计算得到的所有数据]。也就是说,整个三角形的角的大小、关系是确定的,所以当L2过短时,必然出现上图情况。
-
很简单的归纳一下,那就是 dL2 > L2 的时候,需要跳过bc边,并剔除bc向量。
-
相应措施为:不做螺旋线,直接做ac点的连线。更新ab向量为ac【偏角:两点斜率再换算到0-360;长度:两点间距离;起始点坐标:不变】。
到这里,分析的已经差不多了。
余下 | 说明 |
---|
边框绘制并获取约定数据 | 两种思路:随机绘制边框/半手动绘制边框。随机绘制的时候,边框闭合问题,边框合格判定问题;半手动绘制时,需要与程序交互,可实现相对复杂的边框以及嵌套。 |
由一系列有序坐标点(逆时针)获取约定数据 | 偏角、长度的计算 |
余下的,余下的佛系更新吧。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201031204443720.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDIwODE4,size_16,color_FFFFFF,t_70#pic_center)