基于LBS的六边形热力图算法
六边形算法:
我把六边形铺满的分布图进行了切分,切分为矩形,每个矩形中有一个六边形、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的六边形热力图算法的更多相关文章
- 一种O(n)时间复杂度的计数排序算法和Top N热词算法
排序算法是研究非常广泛且超级经典的算法,主流排序算法的时间复杂度基本都在O(nlogn). 今天就介绍一种以hash表为基础的,时间复杂度能够达到O(n)的排序算法--计数排序: 同时基于它的思想,完 ...
- 基于DFA敏感词查询的算法简析
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 项目中需要对敏感词做一个过滤,首先有几个方案可以选择: a.直 ...
- <<一种基于δ函数的图象边缘检测算法>>一文算法的实现。
原始论文下载: 一种基于δ函数的图象边缘检测算法. 这篇论文读起来感觉不像现在的很多论文,废话一大堆,而是直入主题,反倒使人觉得文章的前后跳跃有点大,不过算法的原理已经讲的清晰了. 一.原理 ...
- 【CityHunter】基于LBS的AR体感游戏设计理念
本人目前还不是游戏行业的圈内人士,并不懂得,游戏行业的生态圈,也不懂得,所谓的什么“中国市场环境”.所以不敢发表关于这方面的见解,不过我在这里想要插一句话,就是我认为啊,行业内,人与人之间还是有分层次 ...
- 在做基于LBS应用的一些随笔
公司做了一个基于LBS的APP,在做服务端的时候出现了一些注意事项,还是记录下把. 首先是关于坐标: 弧长公式:L=nπr/180°或l=|α|r.地球半径大致是6400千米.以纬度0.000001为 ...
- 基于SNMP的路由拓扑发现算法收集
一.三层(网络层)发现 算法来源:王娟娟.基于SNMP的网络拓扑发现算法研究.武汉科技大学硕士学位论文,2008 数据结构: 待检路由设备网关链表:存放指定深度内待检路由设备的网关信息,处理后删除. ...
- SVD++:推荐系统的基于矩阵分解的协同过滤算法的提高
1.背景知识 在讲SVD++之前,我还是想先回到基于物品相似的协同过滤算法.这个算法基本思想是找出一个用户有过正反馈的物品的相似的物品来给其作为推荐.其公式为:
- 基于LBS的地理位置附近的搜索以及由近及远的排序
Nosql学习之Redis资料(一) http://redis.io/download 目前基于LBS地理位置的搜索已经应用非常广了,的确是个很方便的东西. 我们做程序的就是要考虑如何通过这些功能,来 ...
- 基于mapreduce的大规模连通图寻找算法
基于mapreduce的大规模连通图寻找算法 当我们想要知道哪些账号是一个人的时候往往可以通过业务得到两个账号之间有联系,但是这种联系如何传播呢? 问题 已知每个账号之间的联系 如: A B B C ...
随机推荐
- 配置Zookeeper、Dubbox
CentOS的配置: 1.给CentOS安装Zookeeper: 网络配置成仅主机 上传tar.gz:比如用FTP tar -xvzf ... cd zookeeper mkdir data cd c ...
- [Swift]LeetCode85. 最大矩形 | Maximal Rectangle
Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and ...
- 通信统计接口字段填充内容shell脚本
现在通信行业上班,最麻烦的就是计算各个协议接口字段填充的内容是否正确.经历了小白似的一个个字段统计在到单个接口所有字段统计,然后到现在的多个接口一次统计.在大大节省了时间的同时,让自己有更充足的时间来 ...
- CentOS7Linux中自动化运维工具Ansible的安装,以及通过模块批量管理多台主机
使用自动化运维工具Ansible集中化管理服务器 Ansible概述 Ansible是一款为类Unix系统开发的自由开源的配置和自动化工具.它用Python写成,类似于saltstack和Puppet ...
- iOS崩溃日志ips文件解析
iOS崩溃日志ips文件解析 一 简介 测试组的同事在进行稳定性测试时,通常会遇到一些崩溃,然后他们会将这些崩溃日志(一般是ips格式的文件)反馈给开发进行分析,但是这些ips文件中的内容通常是如下 ...
- BBS论坛(十五)
15.1.登录界面完成 (1)front/signbase.html {% from 'common/_macros.html' import static %} <!DOCTYPE html& ...
- vue组件,可以通过npm引用的组件
本文章通过实现一个vue-dialog的弹出层组件,然后附加说明如果发布此包到npm,且能被其他项目使用. 功能说明 多层弹出时,只有一个背景层. 弹出层嵌入内部组件. 弹出层按钮支持回调 源码下载 ...
- .Net 调用中国气象台Web Service
接口地址http://www.webxml.com.cn/WebServices/WeatherWebService.asmx 调用步骤:项目添加服务引用-高级-添加web引用 简单代码: web服务 ...
- 从零打卡leetcode之day 1--两数之和
前言 就是要把leetcode的题刷完,每天一道题,每天进步一点点 从零打卡leetcode之day 1 题目描述: 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只 ...
- centos7安装xfce桌面
用了centos自带的gnome桌面 太重了 启动超慢 内存占用近2G 因此打算换一个轻量级的桌面xfce 先安装桌面协议yum groupinstall "X Window system& ...