如下图:

其中的小六边形可以用一张图片替换,也可以用代码直接绘制,这里就不说具体绘制小六边形了,上面的数字是调试用的,可以忽略。

要产生一个这样的图形,有三种方式。

1、按列遍历生成,分左边,右边两部分,每部分按照对应的列产生对应的六边形,再分析每列小六边形个数规律,每列小六边形个数一次递增1或者一次递减1,这样的递减导致小六边形的位置变化,不能简单地按照行列索引去设置位置,对每列来说,水平方向的位置都是不变的,唯一需要调整的是竖直方向的位置,这看起来比较麻烦,但是也有规律的,仔细找能找到,这里不用这种方式

2、如上图,可以先生成三条蓝色线上的小六边形,因为三条蓝色线的是小六边形都与最中心的小六边形相连接,小六边形的坐标位置算起来很方便,直接通过遍历索引乘以对应的小六边形宽高,当然这里的宽不是真正的宽,因为斜线上的小六边形是斜着的,相对坐标轴来说两个小六边形的距离就不是它们的宽了,但是可以在编辑器上计算出来,这个值是固定的。三条蓝色线上的小六边形生成好后,就可以按区域(上图中①②③④⑤⑥)生成各自区域的小六边形了,这里又回到1了,分析每个区域的列数,按照列数产生各列的小六边形,这里也不用这种方式,这里要用的是下面的方式。

3、按环生成,先生成一环,然后多次生成,就生成多个环了,拼起来就是一个盘面,如下图。

上图共7环,实际上是8环,中间还有一个,也算一环。

用正余弦来确定各区域小六边形的位置坐标,如图:

对每一环来说,环上的小六边形的个数是确定的,每增加一环,小六边形的个数增加6个,每个小六边形相对于坐标原点的角度也是确定的(360/小六边形的个数),小六边形的位置则为(x=R * cos(a),y=R * sin(a));但是R的值是变化的,因为环并不是一个标准的圆,关键在于求出R的值,为了方便计算,将坐标系逆时针旋转30度,以上图中最外环为例,最外环的六边形42的角度为0(360),顺时针旋转,则六边形7的角度则为60,六边形14的角度为120,六边形21的角度为180,六边形28的角度为240,六边形35的角度为300。

还是以最外环为例,定义两个小六边形的高差为h,宽差为w,最外环有42个六边形,每相邻两个六边形之间的角度差为8.571428571428571(360/42),保留两位小数取8.57;

从起始点六边形42开始,分析各个小六边形的位置:

六边形42的位置为(R * cos(0),R * sin(0));

则六边形1-6的位置为(R * cos(0),R * sin(0)+i * h),i为六边形1-六边形6的索引(1,2,3,4,5,6);

六边形7的位置为(R * cos(60),R * sin(60));

六边形8-13的位置为(R * cos(60)-i*w,R * sin(60)+i * h),i为六边形8-六边形13的索引(1,2,3,4,5,6);

六边形14的位置为(R * cos(120),R * sin(120));

六边形15-20的位置为(R * cos(120)-i*w,R * sin(60)-i * h),i为六边形15-六边形20的索引(1,2,3,4,5,6);

六边形21的位置为(R * cos(180),R * sin(180));

六边形22-27的位置为(R * cos(180),R * sin(180)-i * h),i为六边形15-六边形20的索引(1,2,3,4,5,6);

六边形28的位置为(R * cos(240),R * sin(240));

六边形29-34的位置为(R * cos(240)+i*w,R * sin(240)-i * h),i为六边形29-六边形34的索引(1,2,3,4,5,6);

六边形35的位置为(R * cos(360),R * sin(360));

六边形36-41的位置为(R * cos(360)+i*w,R * sin(360)-i * h);

每个小六边形的位置都能方便的表示出来。这里为了分析清楚过程,写了很多步,但是代码里只需一个for循环。

上面的类似R * cos(a)+-i*w,R * sin(a)+-i * h,具体是加还是减跟坐标系的类型有关,要看坐标系的原点是在左下角还是左上角,上面是以laya的坐标系来的。

就分析到这里,下面是具体代码(TypeScript),小六边形用的一个预制体表示:

先定义一个常量类:

export default class Constants {

public static readonly Row:number = 13;

public static readonly Col:number = 9;

//定义小六边形的宽度

public static readonly HexItemWidth:number = 74;

//定义小六边形的高度

public static readonly HexItemHeight:number = 64;

//定义小六边形的半宽度

public static readonly HalfHexItemWidth:number = 37;

//定义小六边形的高度

public static readonly HalfHexItemHeight:number = 32;

//定义相邻两小六边形的宽度间隔(就是上面分析说的宽度差)_

public static readonly HexItemGap:number = 55;

//定义边界角度

public static readonly RightBottomAngle:number = 60;

public static readonly BottomAngle:number = 120;

public static readonly LeftBottomAngle:number = 180;

public static readonly LeftAngle:number = 240;

public static readonly LeftTopAngle:number = 300;

public static readonly RightTopAngle:number = 360;

public static readonly HexItemOffsetAngle:number = 30;

}

由于在进行sin,cos运算时,会产生一个小数,再乘以一个R后,会产生一个误差,表现是相邻两小六边形中间会出现一个小缝隙(一个环中会出现2-4个),主要是因为sin,cos那个小数产生的,所以保留两位小数予以解决,系统提供的接口保留两位小数的方法会进行四舍五入,所以定义一个数学类,主要用于保留两位小数,不进行四舍五入:

export default class MathUtils {

/**

* @param num 保留两位数,不进行四舍五人

* @returns

*/

public static to2Fixed(num:number):number{

if(num >= 0) return Math.floor(num*100)/100;

return Math.ceil(num*100)/100;

}

public static to2FixedOther(num:number):number{

return Number(num.toFixed(3).slice(0, -1));

}

}

六边形面盘,就是生成多个六边形环:

/**

* 六边形面盘

* @param round 该面盘由多少环组成

*/

private createHexagonDish(round:number = 1):void{

for(let i:number = 1;i<=round;i++){

this.createHexagonCircle(i);

}

}

生成某一个环:

/**

* 六边形环

* @param roundIndex 环的索引 从1开始 1,2,3,4......;

*/

private createHexagonCircle(roundIndex:number = 1){

let centerX:number = Laya.stage.width/2;

let centerY:number = Laya.stage.height/2;

let r:number = (roundIndex - 1) * 64;

let cos30:number = MathUtils.to2Fixed(Math.cos(Laya.Utils.toRadian(30)));

let _rightBottomX:number = (r * cos30 > 0) ? Math.floor(r * cos30) : Math.ceil(r * cos30);

let rigthBottomX:number = centerX + _rightBottomX;

let rightBottomY:number = centerY + Math.round(r * Math.sin(Laya.Utils.toRadian(30)));

let cos90:number = MathUtils.to2Fixed(Math.cos(Laya.Utils.toRadian(90)));

let _bottomX:number = (r * cos90 > 0) ? Math.floor(r * cos90) : Math.ceil(r * cos90);

let bottomX:number = centerX + _bottomX;

let bottomY:number = centerY + Math.round(r * Math.sin(Laya.Utils.toRadian(90)));

let cos150:number = MathUtils.to2Fixed(Math.cos(Laya.Utils.toRadian(150)));

let _leftBottomX:number = (r * cos150 > 0) ? Math.floor(r * cos150) : Math.ceil(r * cos150);

let leftBottomX:number = centerX + _leftBottomX;

let leftBottomY:number = centerY + Math.round(r * Math.sin(Laya.Utils.toRadian(150)));

let cos210:number = MathUtils.to2Fixed(Math.cos(Laya.Utils.toRadian(210)));

let _leftTopX:number = (r * cos210 > 0) ? Math.floor(r * cos210) : Math.ceil(r * cos210);

let leftTopX:number = centerX + _leftTopX;

let leftTopY:number = centerY + Math.round(r * Math.sin(Laya.Utils.toRadian(210)));

let cos270:number = MathUtils.to2Fixed(Math.cos(Laya.Utils.toRadian(270)));

let _topX:number = (r * cos270 > 0) ? Math.floor(r * cos270) : Math.ceil(r * cos270);

let topX:number = centerX + _topX;//Math.floor(r * Math.cos(Laya.Utils.toRadian(270)));

let topY:number = centerY + Math.round(r * Math.sin(Laya.Utils.toRadian(270)));

let cos330:number = MathUtils.to2Fixed(Math.cos(Laya.Utils.toRadian(330)));

let _rightTopX:number = (r * cos330 > 0) ? Math.floor(r * cos330) : Math.ceil(r * cos330);

let rightTopX:number = centerX + _rightTopX;

let rightTopY:number = centerY + Math.round(r * Math.sin(Laya.Utils.toRadian(330)));

//每增加一个环小六边形个数增加6

let hexItemCount:number = (roundIndex == 1) ? 1 : (roundIndex - 1) * 6;

//相邻两个小六边形的间隔角度(上面分析中的角度差)

let hexItemAngle:number = 360/hexItemCount;

let initAngle:number = (roundIndex%2 == 0) ? hexItemAngle : 0;

let rCount:number = 0;

let rbCount:number = 0;

let lbCount:number = 0;

let lCount:number = 0;

let ltCount:number = 0;

let rtCount:number = 0;

for(let i:number = 0;i<hexItemCount;i++){

let itemX:number = 0;

let itemY:number = 0;

let tempAngle:number = initAngle + hexItemAngle * i;

//生成 右下角 下 左下角 左上角 上 右上角 节点

if(tempAngle%60==0){

r = (roundIndex - 1) * Constants.HexItemHeight;

let radian:number = Laya.Utils.toRadian(tempAngle-Constants.HexItemOffsetAngle)//30   -Math.PI/6  每个节点偏移30度 具体可以根据需要调节;

let fixed2Radian:number = MathUtils.to2Fixed(Math.cos(radian));

let offsetX:number = r * fixed2Radian;

let realOffsetX:number = (offsetX >= 0) ? Math.floor(offsetX) : Math.ceil(offsetX);

itemX = centerX + realOffsetX;

itemY = centerY + Math.round(r * Math.sin(radian));

}else{

//生成右边区域节点

if(tempAngle < Constants.RightBottomAngle){

rCount++;

itemX = rightTopX;

itemY = rightTopY+rCount * Constants.HexItemHeight;

}else if(tempAngle < Constants.BottomAngle){//生成右下角区域节点

rbCount++;

itemX = rigthBottomX-rbCount * Constants.HexItemGap;

itemY = rightBottomY+rbCount * Constants.HalfHexItemHeight;

}else if(tempAngle < Constants.LeftBottomAngle){//生成左下角区域节点

lbCount++;

itemX = bottomX-lbCount * Constants.HexItemGap;

itemY = bottomY-lbCount * Constants.HalfHexItemHeight;

}else if(tempAngle < Constants.LeftAngle){//生成左边区域节点

lCount++;

itemX = leftBottomX;

itemY = leftBottomY-lCount * Constants.HexItemHeight;

}else if(tempAngle < Constants.LeftTopAngle){//生成左上角区域节点

ltCount++;

itemX = leftTopX+ltCount * Constants.HexItemGap;

itemY = leftTopY-ltCount * Constants.HalfHexItemHeight;

}else if(tempAngle < Constants.RightTopAngle){//生成右上角区域节点

rtCount++;

itemX = topX+rtCount * Constants.HexItemGap;

itemY = topY+rtCount * Constants.HalfHexItemHeight;

}

}

this.createHexItem(itemX,itemY,i+1);

}

}

private createHexItem(posX:number,posY:number,index:number = 0):Laya.Image{

//HexItem是一个预制体

let hexItem:Laya.Image = this.HexItem.create();

let aa:Laya.Text = hexItem.getChildByName("value") as Laya.Text;

aa.text = index+"";

this.owner.addChild(hexItem);

hexItem.pos(posX,posY);

return hexItem;

}

测试一下:

创建一个环:this.createHexagonCircle(5),5是环的索引,从里向外为1,2,3............,如下图:

创建一个环面盘:this.createHexagonDish(7),7为生成的环数如下图:

数学正余弦应用——创建六边形环或者六边形面盘相关推荐

  1. cordic ip核 vivado_vivado中Cordic IP核使用——计算正余弦(sin/cos)

    目录 1.Cordic算法介绍 2.Cordic IP核介绍 3.仿真 4.存在的问题 5.参考 1.Cordic算法介绍 cordic算法将正余弦计算转换为简单的迭代过程(一系列的加减和移位操作), ...

  2. vivado中Cordic IP核使用——计算正余弦(sin/cos)

    目录 1.Cordic算法介绍 2.Cordic IP核介绍 3.仿真 4.存在的问题 5.参考 1.Cordic算法介绍 cordic算法将正余弦计算转换为简单的迭代过程(一系列的加减和移位操作), ...

  3. C语言正余弦函数定点查表算法原理及实现

    如果用数学库中的sin和cos函数计算,可能涉及浮点.乘法.除法运算,运行速率较低.这里介绍一种正余弦查表算法. 参考代码:SMT32 FOC电机库的mc_math.c. 首先我们知道正弦和余弦的函数 ...

  4. Transformer正余弦位置编码理解

    在学习Transformer模型过程中不可避免的一个过程便是要对序列进行位置编码,在Transformer中分为固定位置编码与可学习的位置编码,其一般采用固定位置编码中的正余弦位置编码方式. 今天便以 ...

  5. Vivado关于dds IP核实现任意频率的正余弦波输出

    Vivado关于dds IP核实现任意频率的正余弦波输出 目录 一.dds IP核的创建与参数配置 1.创建dds IP核 2.参数配置 3.可编程输入设置 4.详细的设置 5.输出频率设置 6.配置 ...

  6. 智能优化算法:正余弦优化算法-附代码

    智能优化算法:正余弦优化算法-附代码 文章目录 智能优化算法:正余弦优化算法-附代码 1.算法原理 2.算法流程 3.算法结果 4.参考文献 5.MATLAB代码 6.Python代码 摘要:正 余 ...

  7. ML之MIC:利用有无噪音的正余弦函数理解相关性指标的不同(多图绘制Pearson系数、最大信息系数MIC)

    ML之MIC:利用有无噪音的正余弦函数理解相关性指标的不同(多图绘制Pearson系数.最大信息系数MIC) 目录 利用有无噪音的正余弦函数理解相关性指标的不同(多图绘制Pearson系数.最大信息系 ...

  8. VRP远程管理(华为设备telnet登录密码配置与测试环境搭建)——在物理机上创建回环网卡及eNSP模拟器与物理机实现连接通信

    目录 一.在网络连通的情况下,开启telnet服务 二.用户认证配置 1. 密码认证模式 2. aaa认证模式 三.eNSP模拟器telnet测试环境搭建 1.在物理机上创建回环网卡及IP地址配置 2 ...

  9. Matplotlib 绘制折线图 - 正余弦函数图像

    运行环境 : python 3.6.0 用 Matplotlib 的 scatter 方法绘制散点图 核心代码 : # -*- encoding: utf-8 -*- # @Version : Pyt ...

最新文章

  1. oracle Ratio_to_report的用法
  2. linux: convmv =-======pkgs.org
  3. HDU3183(RMQ问题,ST算法)
  4. mysql大数据优化要注意的细节
  5. java互斥锁的实现原理_java-深入分析synchronized原理
  6. Ubuntu18.04 安装OpenCV
  7. 永恒之蓝(ms17010)漏洞利用
  8. 第1060期AI100_机器学习日报(2017-08-13)
  9. 游戏开场镜头拉近(Unity3D开发之四)
  10. Uncaught TypeError: Cannot read property 'decimalSeparator' of undefined
  11. 超强大的货币汇率实时查询工具
  12. Show出你的高超技能 首届“中国高性能云计算创新大赛”要开赛啦!
  13. 计算机13E怎么转换成十进制,十六进制换算(进制转换计算器)
  14. 计算机如何解决卡顿问题,电脑反应慢怎么办?电脑卡顿处理方法
  15. 【JAVA类与对象----5(static、代码块)】
  16. 打开计算机用户策略,打开组策略,详细教您电脑组策略怎么打开
  17. PHP:40+开发工具推荐
  18. Java编程思想之高内聚低耦合
  19. GoogleCode中git push密码错误提示解决方案(Invalid username/password)
  20. 优化理论16----Armijo-Goldstein准则、 Armijo-Goldstein搜索方法、python实现

热门文章

  1. 纳多德NADDOD全新品牌升级——探索数智未来
  2. 简单的电子词典 因手机问题未图
  3. 写dectobin函数实现十进制转二进制(C语言 + 详细注释)
  4. Java高斯模糊处理图片
  5. 【数据库】数据分析专项练习题库-SQL试卷三
  6. spell 命令 查找英语语言拼写错误。
  7. sql:函数:COALESCE()
  8. linux系统 gwas分析,GWAS真的只有关联分析这么简单?
  9. Canvas 旋转风车绘制
  10. Kotlin 中的suspend 关键字