六边形算法:

  我把六边形铺满的分布图进行了切分,切分为矩形,每个矩形中有一个六边形、4个三角形、两个小长方形,依次计算。边界判断上,采用主流的MP>MN的方式(M为上边界对称点,N为与六边形的交点,p为要判断的点,如下图)。

实际效果(双色对比):

拾取效果:

代码:

 /// <summary>
/// 根据参数获得六边形索引
/// </summary>
/// <param name="width">页面宽度</param>
/// <param name="height">页面长度</param>
/// <param name="r">六边形边长</param>
/// <param name="thickness">六边形上下拓扑半间距</param>
/// <param name="flat">扁平化程度(由于计算过程中,thickness在侧向拓扑中作用减小,故增加了这个系数)</param>
/// <param name="x">横坐标</param>
/// <param name="y">纵坐标</param>
/// <param name="transparent">透明度设置,一般位置为正常值;如果是六边形边界位置的过渡色,减半</param>
/// <returns></returns>
public static int[] GetHexGridIndex(int width, int height, int r, int thickness, int flat, int x, int y, ref byte transparent)
{
//中心点索引(长方形中的六边形的索引)
int indexX = (x / ) / r * ;
int indexY = (int)((int)(y / Math.Sqrt()) / r + indexX / ); //中心点坐标
int centerX = r + (int)(1.5 * r * indexX);
int centerY = (int)(Math.Sqrt() * 0.5 * r * ( + * indexY - indexX)); //位于六边外框之外
if (x > (centerX + r))
{
if (y > centerY + thickness)//右下
{
indexX++;
indexY++;
}
else if (y < centerY - thickness)//右上
{
indexX++;
}
else//中间部分以及外延部分
{
indexX = -;
indexY = -;
}
}
else//六边外框之内
{
if (x > centerX + r / )//右半区
{
if (y > centerY)//右下
{
var M = Math.Sqrt() / * r + centerY;//上边界点
var N = (centerX + r - x) * Math.Sqrt() + centerY;//六边形边界点
var MP = (int)(M - y);
var MN = (int)(M - N);
if (MP > (MN + thickness * flat))//六边形内部
{
//索引不变
}
else if (MP < (MN - thickness * flat))//六边形外部
{
indexX++;
indexY++;
}
else//交界区
{
if (MP == MN + thickness * flat)//紧靠内部
{
transparent = (byte)(transparent / );
////去除右侧尖尖
if (x == centerX + r - thickness)
{
indexX = -;
indexY = -;
}
}
else if (MP == MN - thickness * flat)//紧靠外部
{
indexX++;
indexY++;
transparent = (byte)(transparent / );
}
else//中间区
{
indexX = -;
indexY = -;
}
}
}
else//右上
{
var M = centerY - Math.Sqrt() / * r;
var N = centerY - (centerX + r - x) * Math.Sqrt();
var MP = (int)(y - M);
var MN = (int)(N - M);
if (MP > (MN + thickness * flat))//内部
{
////索引不变,但是要去除右侧尖尖
if (x == centerX + r - thickness)
{
indexX = -;
indexY = -;
}
}
else if (MP < (MN - thickness * flat))//外部,索引单变
{
indexX++;
}
else
{
if (MP == MN + thickness * flat)//里侧
{
transparent = (byte)(transparent / );
if (x == centerX + r - thickness - )////去除右侧尖尖
{
indexX = -;
indexY = -;
}
}
else if (MP == MN - thickness * flat)//外侧
{
indexX++;
transparent = (byte)(transparent / );
}
else
{
indexX = -;
indexY = -;
}
}
}
}
else if (x < centerX - r / )//左半区
{
if (y < centerY)//左上
{
var M = centerY - Math.Sqrt() / * r;
var N = centerY + (centerX - r - x) * Math.Sqrt();
var MP = (int)(y - M);
var MN = (int)(N - M);
if (MP > (MN + thickness * flat))
{
//索引不变
}
else if (MP < (MN - thickness * flat))//索引单变
{
indexX--;
indexY--;
}
else
{
if (MP == MN + thickness * flat)//里侧
{
transparent = (byte)(transparent / );
if (x == centerX - r + thickness + )
{
indexX = -;
indexY = -;
}
}
else if (MP == MN - thickness * flat)//外侧
{
indexX--;
indexY--;
transparent = (byte)(transparent / );
}
else
{
indexX = -;
indexY = -;
}
}
}
else//左下
{
var M = centerY + Math.Sqrt() / * r;
var N = centerY - (centerX - r - x) * Math.Sqrt();
var MP = (int)(M - y);
var MN = (int)(M - N);
if (MP > (MN + thickness * flat))//内部
{
if (x == centerX - r + thickness + )//索引不变,但是要清除突兀部分
{
indexX = -;
indexY = -;
}
}
else if (MP < (MN - thickness * flat))//索引单变
{
indexX--;
}
else//隔离带
{
if (MP == MN + thickness * flat)//里侧
{
transparent = (byte)(transparent / );
if (x < centerX - r + thickness * flat - )
{
indexX = -;
indexY = -;
}
}
else if (MP == MN - thickness * flat)//外侧
{
indexX--;
transparent = (byte)(transparent / );
}
else
{
indexX = -;
indexY = -;
}
}
}
}
else//六边形竖条内部
{
var step = (int)Math.Round(Math.Sqrt() * r);
var remainder = y % step; if (remainder <= thickness)//上缓冲
{
indexX = -;
indexY = -;
}
else if (step - remainder - <= thickness)//下缓冲
{
indexX = -;
indexY = -;
} if ((remainder - == thickness) || (step - remainder - == thickness))//六边形上下四圆角控制(分为上下半身)
{
//去除四点
var first = (int)(centerX - r / );
var second = (int)Math.Ceiling((double)centerX - r / );
var third = (int)(centerX + r / );
var fourth = (int)Math.Ceiling((double)centerX + r / ); if (x == first || x == second || x == third || x == fourth)
{
indexX = -;
indexY = -;
}
}
}
} //right超出界面的设置
var rightIndex = Math.Floor(Convert.ToDouble(width - r - r) / ( * Convert.ToDouble(r) / ));
bool xx = indexX > rightIndex;
if (indexX > rightIndex)
{
indexX = -;
indexY = -;
} //bottom超出界面的设置
var bottomIndex = Math.Floor(height / (r * Math.Sqrt())) - ;
//基础位置为(0,bottomIndex+1)
if (indexY > bottomIndex)//&&((indexX-0)%(indexY-(bottomIndex+1))==0))
{
//下分三种情况,第一种是首索引
var isOrNotFirstIndex = indexX == && (indexY == bottomIndex + );
//与首索引同行位置的索引
var isOrNotFirstLineIndex = indexX == (indexY - (bottomIndex + )) * ;
//侧移索引
var isOrNotSideSwayIndex = (indexX + ) == (indexY - (bottomIndex + )) * ; if (isOrNotFirstIndex || isOrNotFirstLineIndex || isOrNotSideSwayIndex)
{
indexX = -;
indexY = -;
}
} return new int[] { indexX, indexY };
}

六边形算法

基于LBS的六边形热力图算法的更多相关文章

  1. 一种O(n)时间复杂度的计数排序算法和Top N热词算法

    排序算法是研究非常广泛且超级经典的算法,主流排序算法的时间复杂度基本都在O(nlogn). 今天就介绍一种以hash表为基础的,时间复杂度能够达到O(n)的排序算法--计数排序: 同时基于它的思想,完 ...

  2. 基于DFA敏感词查询的算法简析

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 项目中需要对敏感词做一个过滤,首先有几个方案可以选择: a.直 ...

  3. <<一种基于δ函数的图象边缘检测算法>>一文算法的实现。

    原始论文下载: 一种基于δ函数的图象边缘检测算法. 这篇论文读起来感觉不像现在的很多论文,废话一大堆,而是直入主题,反倒使人觉得文章的前后跳跃有点大,不过算法的原理已经讲的清晰了.     一.原理 ...

  4. 【CityHunter】基于LBS的AR体感游戏设计理念

    本人目前还不是游戏行业的圈内人士,并不懂得,游戏行业的生态圈,也不懂得,所谓的什么“中国市场环境”.所以不敢发表关于这方面的见解,不过我在这里想要插一句话,就是我认为啊,行业内,人与人之间还是有分层次 ...

  5. 在做基于LBS应用的一些随笔

    公司做了一个基于LBS的APP,在做服务端的时候出现了一些注意事项,还是记录下把. 首先是关于坐标: 弧长公式:L=nπr/180°或l=|α|r.地球半径大致是6400千米.以纬度0.000001为 ...

  6. 基于SNMP的路由拓扑发现算法收集

    一.三层(网络层)发现 算法来源:王娟娟.基于SNMP的网络拓扑发现算法研究.武汉科技大学硕士学位论文,2008 数据结构: 待检路由设备网关链表:存放指定深度内待检路由设备的网关信息,处理后删除. ...

  7. SVD++:推荐系统的基于矩阵分解的协同过滤算法的提高

    1.背景知识 在讲SVD++之前,我还是想先回到基于物品相似的协同过滤算法.这个算法基本思想是找出一个用户有过正反馈的物品的相似的物品来给其作为推荐.其公式为:

  8. 基于LBS的地理位置附近的搜索以及由近及远的排序

    Nosql学习之Redis资料(一) http://redis.io/download 目前基于LBS地理位置的搜索已经应用非常广了,的确是个很方便的东西. 我们做程序的就是要考虑如何通过这些功能,来 ...

  9. 基于mapreduce的大规模连通图寻找算法

    基于mapreduce的大规模连通图寻找算法 当我们想要知道哪些账号是一个人的时候往往可以通过业务得到两个账号之间有联系,但是这种联系如何传播呢? 问题 已知每个账号之间的联系 如: A B B C ...

随机推荐

  1. 【安富莱专题教程第3期】开发板搭建Web服务器,利用花生壳让电脑和手机可以外网远程监控

    说明:1.  开发板Web服务器的设计可以看我们之前发布的史诗级网络教程:链接.2.  需要复杂些的Web设计模板,可以使用我们V6开发板发布的综合Demo:链接.3.  教程中使用的是花生壳免费版, ...

  2. TCP与UDP区别总结

    TCP与UDP区别总结:1.TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接2.TCP提供可靠的服务.也就是说,通过TCP连接传送的数据,无差错,不丢失,不重 ...

  3. MySQL InnoDB 备份与恢复七种方式

    有几种方式: 1 mysqldump, 这种方式不仅适用于InnoDB,还适用于其它类型的存储引擎,如MyISAM.备份的时候将数据库备份成SQL(包含drop,create,insert等语句),恢 ...

  4. [Swift]LeetCode296. 最佳开会地点 $ Best Meeting Point

    A group of two or more people wants to meet and minimize the total travel distance. You are given a ...

  5. POI生成EXCEL文件

    POI生成EXCEL文件 一.背景 根据指定格式的JSON文件生成对应的excel文件,需求如下 支持多sheet 支持单元格合并 支持插入图片 支持单元格样式可定制 需要 标题(title),表头( ...

  6. JavaScript 正则表达式全面总结

    本文适合有 JavaScript 基础 && 面向搜索引擎书写正则的人群. 正则表达式是用于匹配字符串中字符组合的模式.正则表达式的模式规则是由一个字符序列组成的.包括所有字母和数字在 ...

  7. Spring Boot @ControllerAdvice 处理全局异常,返回固定格式Json

    需求 在构建RestFul的今天,我们一般会限定好返回数据的格式比如: { "code": 0,  "data": {},  "msg": ...

  8. 通用网页调用本地应用程序方案(windows平台)

    一.更新注册表 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\receiveOutOfArg] "URL Protocol& ...

  9. Calling handler.OnEndpointsUpdate报错原因

    过程:部署node01节点时从一台已经部署好的node02把/opt/kubernetes目录直接拷贝了过来,然后修改相应配置文件,启动kubelet是日志报如下图错误: 导致node01无法连接上m ...

  10. 【从零开始自制CPU之学习篇03】锁存器与触发器

    本篇学习了两种锁存器:SR Latch和D Latch,一种触发器:D flip flop SR Latch:SR—锁存器 初始状态下,S和R都为0,Q和Q‘随机有一个为1另一个 为0(取决于电流速度 ...