欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Highcharts Tilemap 自动生成正六边形蜂窝状排布算法(TypeScript)

程序员文章站 2022-05-22 14:18:09
...

上一个项目需要用到TileMap,并且给定任意数据,动态排布成正六边形。关于TileMap的排布就是最后数据的结构,我记得当时还在本子上列公式算了一会,算出来个公式。写这篇blog的时候大概过了快一年了,还花了些时间回想。

Highcharts Tilemap 自动生成正六边形蜂窝状排布算法(TypeScript)
X代表数据总数,Y代表正六边形正中间那一行有多少个数据,只有当Y为整数的时候,当前的X的数据量才可排布成正六边形。
Highcharts Tilemap 自动生成正六边形蜂窝状排布算法(TypeScript)
由于我已经不在那个项目了,sourcecode没有权限拿不到,启动不起来,只有拿官网的例图来说明,看圈内就是一个正六边形排布,把数据总数7带入公式,刚好可以得出中间数据个数为3。接下来贴我的代码

const testData = [
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 0
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 0
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 0
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 1
            },
            {
                value: 0
            },
            {
                value: 1
            }
        ];
autoGenerateXandY(datas: any): any {
        let total = datas.length;
        let middleNum = Math.sqrt((total * 4 - 1) / 3);
        if (!/^\d+$/.test(middleNum.toString())) {
            total = this.getNextAmountOfHexHexgon(middleNum);
            middleNum = Math.sqrt((total * 4 - 1) / 3);
        }
        let tileDatas = new Array<TileData>(total);
        let invertedFlag = false;
        let towRowFlag = 0;
        let upRow = (middleNum - 1) / 2;
        let offsetNum = parseInt(((upRow - 1) / 2).toFixed(0));
        let sideNum = (middleNum + 1) / 2;
        for (let i = 0, j = sideNum, z = 0; i < middleNum || z < total; i++) {
            for (let k = offsetNum; k < j + offsetNum; k++, z++) {
                if (z >= datas.length) {
                    continue;
                }
                tileDatas[z] = new TileData();
                tileDatas[z].x = i;
                tileDatas[z].y = k;
                tileDatas[z].value = datas[z].value;
                tileDatas[z].name = datas[z].name;
            }
            if (i === upRow) {
                if (/^\d+$/.test((upRow / 2).toString())) {
                    offsetNum++;
                    towRowFlag = 0;
                } else {
                    towRowFlag = 1;
                }
            } else {
                if (towRowFlag >= 1) {
                    towRowFlag = 0;
                    if (invertedFlag) {
                        offsetNum++;
                    } else {
                        offsetNum--;
                    }
                } else {
                    towRowFlag++;
                }
            }
            invertedFlag = i >= upRow;
            if (invertedFlag) {
                j--;
            } else {
                j++;
            }
        }
        return tileDatas;
    }

    getNextAmountOfHexHexgon(middleNum: number): number {
        middleNum = parseInt(middleNum.toString()) + 1;
        while (!/^\d+$/.test(this.getAmountFromMiddleNum(middleNum).toString())) {
            middleNum++;
        }
        return this.getAmountFromMiddleNum(middleNum);
    }

这个function返回的数据就可以直接放进highcharts的data里面就可以生成正六边形了,这里还做了处理,当当前数据总数无法构成完美六边形时候,算法会自动找出当前数据总数中下一个可以构成完美六边形的整数,并且使用空数据来填充,可以呈现一个缺失的六边形,但是随着数据增加,六边形可以变成完美状态,当又多一个数据之后,就会进入下一个完美六边形整数形成的缺失六边形。

现在有个遗憾就是没有权限拿代码,不能展示一下。但是记录一下算法吧。毕竟当时还是想了一会的,不能白费脑细胞。

相关标签: 算法