1

我想做的是创建一个如下所示的十六进制网格。

六角网格

我可以画出十六进制,但不确定如何让它们错开。所以第一行应该是图像中的 (0,0) (0,1) (0,2) (0,3),第二行应该是 (1,0) (1,1) (1,2) ( 1,3)等行中的偶数十六进制始终交错向下。

目前我知道要使用的行数/列数 hexRows hexColumns

以及我如何绘制十六进制是这样的,i只是在绘制十六进制时对其进行编号。 DrawSolidHex(x,y,i);

当前代码看起来像这样

 begin
 hexcolumns := c;
 hexrows := r;
 i:=1;             //first cube
 x := 1;           //default x,y,z values
 y := 1;
 z := 0;
   while hexrows>0 do
    begin
      columnssave := hexcolumns ;
      while hexcolumns >0 do
        begin
          DrawSoildHex(X,Y,i);
          i:=i+1;
          x := x + 1; 
          hexcolumns := hexcolumns -1;
        end;
      y:=y+1;
      x:= 1;
      z:=0;
      hexcolumns := columnssave;
      hexrows:= hexrows-1;
    end;
    totalhex := i;

目前使用此代码,它只会在一条直线上绘制十六进制 x,y,(1,1) (2,1) (3,1)..ect 我不确定如何添加偏移量,计算它们,然后编码所以它会错开行。

4

2 回答 2

7

在如下的六边形中,您需要了解构成边的三角形:

    B                   B
    *--*                *
   /|   \              /|
  / |    \            / |
A*--*C    *  ==>   c /  | a
  \      /          /   |
   \    /          /    |
    *--*         A*-----*C
                     b

这些三角形被称为 30-60-90 三角形,因为这是构成内角的角度:C = 90A = 60B = 30

这些三角形的边比c = 2b = 1a = sqrt(3)

因此,假设您知道c(它是六边形边之一的长度),您可以计算该三角形的另外两个边,而无需求助于三角函数:

a = c * sqrt(3) / 2
b = c / 2

一旦我们知道了这些值,六边形偏移就相对容易计算,只需通过观察网格并使用每个六边形的最左角(A在上图中)作为起点和终点。

到的水平距离(0,0)为(朝向东北、东、东南和西南方向)。这是一行中所有“相邻”单元格之间的水平差异,它简化为,或者如果您只想使用.(0,1)b + c + b - bb + c3 * c / 2c

(0,0)从到(0,1)(半行)的垂直距离很简单a(东南然后是不相关的东)。这相当于sqrt(3) * c / 2或可能足够接近c * 433 / 500(16,000 分之一的误差),甚至不必涉及平方根。

虽然,如果您希望获得更高的准确性,您可以坚持使用平方根计算 - 只需记住sqrt(3) / 2在开始时计算一次,然后将其用作乘数。

行之间的垂直距离显然是两倍,比如(0,0)to (1,0)

因此,对于每一整行,您只需向下移动c * 433 / 250单位。对于每一列,您跨c * 3 / 2单位和垂直c * 433 / 500单位移动(如果您从偶数索引移动到奇数索引,则向下移动,否则向上移动)。

于 2014-06-25T04:53:56.090 回答
0

如果您知道(应该)十六进制单元格的大小,您可以通过简单的计算来解决这个问题。

   | 小|
   | 宽度 |
    _______ ______
   / \ H
  /\e
 / \ 一世
 \ / G
  \ / H
| \_______/ _|____t
| |
|--- 宽度 ---|
uses
  System.Types,
  Vcl.Graphics;

type
  THexCellSize = record
    Width : Integer;
    Height : Integer;
    SmallWidth : Integer;
  end;

function GetHexDrawPoint( AHexCellSize : THexCellSize; ACol, ARow : Integer ) : TPoint;
begin
  Result.X := ( ( AHexCellSize.Width - AHexCellSize.SmallWidth ) div 2 + AHexCellSize.SmallWidth ) * ACol;
  Result.Y := AHexCellSize.Height * ARow + ( AHexCellSize.Height div 2 ) * ( ACol mod 2 );
end;

procedure DrawHexCell( ACanvas : TCanvas; AOffSet : TPoint; AHexCellSize : THexCellSize; ACol, ARow : Integer );
var
  LPoint : TPoint;
  LXOffset : Integer;
begin
  { *************
    *   1---2
    *  /     \
    * 6       3
    *  \     /
    *   5---4
    ************* }

  LXOffset := ( AHexCellSize.Width - AHexCellSize.SmallWidth ) div 2;

  // Move to point 1
  LPoint := GetHexDrawPoint( AHexCellSize, ACol, ARow );
  LPoint.Offset( AOffSet );
  ACanvas.MoveTo( LPoint.X, LPoint.Y );
  // Line to point 2
  LPoint.Offset( AHexCellSize.SmallWidth, 0 );
  ACanvas.LineTo( LPoint.X, LPoint.Y );
  // Line to point 3
  LPoint.Offset( LXOffset, AHexCellSize.Height div 2 );
  ACanvas.LineTo( LPoint.X, LPoint.Y );
  // Line to point 4
  LPoint.Offset( -LXOffset, AHexCellSize.Height div 2 );
  ACanvas.LineTo( LPoint.X, LPoint.Y );
  // Line to point 5
  LPoint.Offset( -AHexCellSize.SmallWidth, 0 );
  ACanvas.LineTo( LPoint.X, LPoint.Y );
  // Line to point 6
  LPoint.Offset( -LXOffset, -AHexCellSize.Height div 2 );
  ACanvas.LineTo( LPoint.X, LPoint.Y );
  // Line to point 1
  LPoint.Offset( LXOffset, -AHexCellSize.Height div 2 );
  ACanvas.LineTo( LPoint.X, LPoint.Y );
end;

procedure DrawHexCellGrid( ACanvas : TCanvas; AOffSet : TPoint; AHexCellSize : THexCellSize; ACols, ARows : Integer );
var
  LCol, LRow : Integer;
begin
  for LRow := 0 to ARows - 1 do
    for LCol := 0 to ACols - 1 do
      DrawHexCell( ACanvas, AOffSet, AHexCellSize, LCol, LRow );
end;
于 2014-06-26T09:42:17.550 回答