winform
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
honeycombBuilder.Space = new Point(3, 3);
//honeycombBuilder.Offset = new Point(27, 27);
// Create the ToolTip and associate with the Form container.
// Set up the delays for the ToolTip.
toolTip1.AutoPopDelay = 500000;
toolTip1.InitialDelay = 0;
toolTip1.ReshowDelay = 0;
// Force the ToolTip text to be displayed whether or not the form is active.
toolTip1.ShowAlways = true;
// Set up the ToolTip text for the Button and Checkbox.
this.BackColor = Color.FromArgb(255, 28, 62, 146);
}
ToolTip toolTip1 = new ToolTip();
HoneycombBuilder honeycombBuilder = new HoneycombBuilder(26);
private void button1_Click(object sender, EventArgs e)
{
using (var g = this.CreateGraphics())
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
for (int x = 1; x < 8; x++)
{
for (int y = 1; y < 20; y++)
{
using (var b = new SolidBrush(Color.FromArgb(255,21,51,136)))
{
using (var p = new Pen(b, 2))
{
var realpoint = honeycombBuilder.CellToPoint(x, y);
Point[] lppoint = honeycombBuilder.GetCellPoints(realpoint);
using (var fp = new Pen(Color.Black))
{
g.DrawLines(fp, lppoint);
}
g.FillPolygon(b, lppoint);
using (var fb = new SolidBrush(Color.White))
{
var loca = g.MeasureString($"{x},{y}", this.Font);
realpoint.X = (Int32)(realpoint.X - loca.Width / 2f);
realpoint.Y = (Int32)(realpoint.Y - loca.Height / 2f);
g.DrawString($"{x},{y}", this.Font, fb, realpoint);
}
}
}
}
}
}
}
Point lastcell = new Point(0, 0);
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
//通过坐标找到格子
var cell = honeycombBuilder.PointToCell(e.Location);
//通过坐标找到当前坐标所在格子中心点
var realpoint = honeycombBuilder.GetCellCenter(e.Location);
if (cell.X <= 0 || cell.Y <= 0 || (cell.X == lastcell.X && cell.Y == lastcell.Y))
{
return;
}
toolTip1.SetToolTip(this, $"{cell.X},{cell.Y}");
using (var g = this.CreateGraphics())
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
using (var b = new SolidBrush(Color.FromArgb(255, 80, 80, 200)))
{
Point[] lppoint = honeycombBuilder.GetCellPoints(realpoint);
using (var fp = new Pen(Color.Black))
{
g.DrawLines(fp, lppoint);
}
g.FillPolygon(b, lppoint);
using (var fb = new SolidBrush(Color.White))
{
var loca = g.MeasureString($"{cell.X},{cell.Y}", this.Font);
realpoint.X = (Int32)(realpoint.X - loca.Width / 2);
realpoint.Y = (Int32)(realpoint.Y - loca.Height / 2);
g.DrawString($"{cell.X},{cell.Y}", this.Font, fb, realpoint);
}
}
if (lastcell.X != 0 && lastcell.Y != 0)
{
realpoint = honeycombBuilder.CellToPoint(lastcell);
using (var b = new SolidBrush(Color.FromArgb(255, 21, 51, 136)))
{
Point[] lppoint = honeycombBuilder.GetCellPoints(realpoint);
g.FillPolygon(b, lppoint);
using (var fb = new SolidBrush(Color.White))
{
var loca = g.MeasureString($"{lastcell.X},{lastcell.Y}", this.Font);
realpoint.X = (Int32)(realpoint.X - loca.Width / 2);
realpoint.Y = (Int32)(realpoint.Y - loca.Height / 2);
g.DrawString($"{lastcell.X},{lastcell.Y}", this.Font, fb, realpoint);
}
}
}
}
lastcell = cell;
}
}
}
类
using System;
using System.Drawing;
namespace WindowsFormsApp1
{
public class HoneycombBuilder
{
public HoneycombBuilder(Int32 dwsidelength = 40)
{
SideLength = dwsidelength;
//二分之根号3 边长的平方,如果距离比它还小,就必然捕获
g_MinDistance2 = dwsidelength * dwsidelength * 0.75;
}
private Double g_MinDistance2 { get; set; }
/// <summary>
/// 六边形的边长
/// </summary>
public Double SideLength { get; private set; }
/// <summary>
/// 每个格子的宽度
/// </summary>
public Double g_unitx
{
get
{
var cx = Math.Ceiling(SideLength * 1.8020508);
cx += ((Int32)cx & 1);
return cx;
}
}
/// <summary>
/// 格子之间的空间
/// </summary>
public Point Space { get; set; }
/// <summary>
/// 起始坐标偏移
/// </summary>
public Point Offset { get; set; }
/// <summary>
/// 每个格子的宽度
/// sqr(3)/2=0.8660254
/// </summary>
public Double g_unity
{
get
{
var cy = Math.Ceiling(SideLength * 1.5f);
cy += ((Int32)cy & 1);
return cy;
}
}
/// <summary>
/// 坐标转格子
/// </summary>
/// <param name="lppoint"></param>
/// <returns>格子的编号</returns>
public Point PointToCell(Point lppoint)
{
return this.PointToCell(lppoint.X,lppoint.Y);
}
/// <summary>
/// 坐标转格子
/// </summary>
/// <param name="xPos"></param>
/// <param name="yPos"></param>
/// <returns>格子的编号</returns>
public Point PointToCell(int xPos, int yPos)
{
var canter = this.GetCellCenter(xPos, yPos);
var Y = canter.Y / (g_unity + Space.Y);
var X = canter.X / (g_unitx + Space.X);
return new Point((Int32)X, (Int32)Y);
}
/// <summary>
/// 网格坐标转2d坐标中心点
/// </summary>
/// <param name="cell_x"></param>
/// <param name="cell_y"></param>
/// <returns></returns>
public Point CellToPoint(Point cell)
{
return CellToPoint(cell.X, cell.Y);
}
/// <summary>
/// 网格坐标转2d坐标中心点
/// </summary>
/// <param name="cell_x"></param>
/// <param name="cell_y"></param>
/// <returns></returns>
public Point CellToPoint(int cell_x, int cell_y)
{
Point p = new Point();
var offsetx = Math.Ceiling((g_unitx + Space.X) * (cell_y & 1) * 0.5f);
p.X = (Int32)(cell_x * (g_unitx + Space.X) + offsetx);
p.Y = (Int32)(cell_y * (g_unity + Space.Y));
return p;
}
/// <summary>
/// 求取两个点的距离平方
/// </summary>
/// <param name="x1"></param>
/// <param name="y1"></param>
/// <param name="x2"></param>
/// <param name="y2"></param>
/// <returns></returns>
private int distance2(int x1, int y1, int x2, int y2)
{
return ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
/// <summary>
/// 通过某一点坐标定位到坐标所在格子中心点
/// </summary>
/// <param name="lppoint"></param>
/// <returns>返回被捕获六边形的中心坐标</returns>
public Point GetCellCenter(Point lppoint)
{
return this.GetCellCenter(lppoint.X, lppoint.Y);
}
/// <summary>
/// 通过某一点坐标定位到坐标所在格子中心点
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns>返回被捕获六边形的中心坐标</returns>
public Point GetCellCenter(int x, int y)
{
//位于矩形网格边线上的三个CELL中心点
Point[] points = new Point[3];
//当前距离
int dist;
int mindist = (int)(g_MinDistance2 * 100); //一个非常大的值
int i, index = 0;
//index:被捕获的索引
//计算出鼠标点位于哪一个矩形网格中
int cx = (int)(x / (g_unitx + +Space.X));
//int cy = (int)(y / g_unity);
int cy = (Int32)(y / (g_unity + Space.Y));
points[0].X = (int)((g_unitx + +Space.X) * cx);
points[1].X = (int)((g_unitx + +Space.X) * (cx + 0.5));
points[2].X = (int)((g_unitx + +Space.X) * (cx + 1));
//根据cy是否是偶数,决定三个点的纵坐标
if (cy % 2 == 0)
{
//偶数时,三个点组成倒立三角
points[0].Y = points[2].Y = (int)((g_unity + Space.Y) * cy);
points[1].Y = (int)((g_unity + Space.Y) * (cy + 1));
}
else
{
//奇数时,三个点组成正立三角
points[0].Y = points[2].Y = (int)((g_unity + Space.Y) * (cy + 1));
points[1].Y = (int)((g_unity + Space.Y) * cy);
}
//现在找出鼠标距离哪一个点最近
for (i = 0; i < 3; i++)
{
//求出距离的平方
dist = distance2(x, y, points[i].X, points[i].Y);
//如果已经肯定被捕获
if (dist < g_MinDistance2)
{
index = i;
break;
}
//更新最小距离值和索引
if (dist < mindist)
{
mindist = dist;
index = i;
}
}
//现在index 就是被捕获的结果
return new Point(points[index].X, points[index].Y);
}
/// <summary>
/// 输入格子中心坐标 返回格子的六个角
/// </summary>
/// <param name="center"></param>
/// <returns></returns>
public Point[] GetCellPoints(Point center)
{
return GetCellPoints(center.X, center.Y);
}
/// <summary>
/// 输入格子中心坐标 返回格子的六个角
/// </summary>
/// <param name="centerx"></param>
/// <param name="centery"></param>
/// <param name="a"></param>
/// <param name="lpPoints"></param>
public Point[] GetCellPoints(int centerx, int centery)
{
var lpPoints = new Point[7];
var a = g_unity / 1.5;// (Int32)this.SideLength;
if (lpPoints == null || lpPoints.Length < 6) return null;
//平
var offsetx = Math.Ceiling(g_unitx * 0.5f);
lpPoints[0].X = centerx;
lpPoints[0].Y = (Int32)(centery - a);
lpPoints[1].X = centerx + (int)offsetx;
lpPoints[1].Y = (Int32)(centery - a / 2f);
lpPoints[2].X = lpPoints[1].X;
lpPoints[2].Y = (Int32)(centery + a / 2f);
lpPoints[3].X = centerx;
lpPoints[3].Y = (Int32)(centery + a);
lpPoints[4].X = centerx - (int)offsetx;
lpPoints[4].Y = (Int32)(centery + a / 2f);
lpPoints[5].X = lpPoints[4].X;
lpPoints[5].Y = (Int32)(centery - a / 2f);
lpPoints[6].X = lpPoints[0].X;
lpPoints[6].Y = lpPoints[0].Y;
return lpPoints;
}
}
}