【问题标题】:Calculation of Hex grid十六进制网格的计算
【发布时间】:2014-06-25 04:17:13
【问题描述】:

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

我可以画出十六进制,但不确定如何让它们错开。所以第一行应该是 (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 我不确定如何添加偏移量,计算它们,并对其进行编码,使其错开行。

【问题讨论】:

  • 我可以画出十六进制,但不确定如何让它们错开。这很奇怪。如果你能画出一个六边形,你就可以把它们都画出来。如果你画一个,你已经画出了所有邻居之间的共享线。所以你已经知道在哪里画邻居了。
  • 是的,我知道在哪里画它们,但必须计算如何计算下一个 xy
  • 你不懂。如果你能画一个,你就已经知道在哪里画所有的邻居了。您已经完成了计算。
  • 我可以画一个,因为我可以告诉它在哪里画,我不知道在哪里告诉它画下一个与它刚刚画的相关的相邻的。
  • 我告诉它在哪里画?这意味着什么?为了画一个六边形,你必须画 6 条线。那是对的吗。所以,你知道那 6 行在哪里。对?我无法理解您的断言,即您可以在不知道它在哪里以及线条在哪里的情况下绘制这个六边形。你怎么能画出这些线而不指定它们在哪里。

标签: delphi delphi-xe2 hexagonal-tiles


【解决方案1】:

在如下的六边形中,你需要知道构成边的三角形:

    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 - b(向东北、向东、向东南和向西南方向行驶)。这是一行中所有“相邻”单元格之间的水平差异,如果您只想使用 c,它会简化为 b + c3 * c / 2

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

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

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

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

【讨论】:

  • +1 以获得令人愉快的答案。尽管您确实使用三角函数来计算三角形边的长度。 ;-)
  • 这里有一些很好的信息,我会看看我是否可以用它来抵消代码中的影响,但至少可以解决我的一半问题。
  • 毕达哥拉斯定理是教给我几何课的,而不是三角学。在 Trig 课上,他们假设你已经知道这些东西很冷。 Trig 是您了解腿和斜边之间的比率的地方,即 sin、cos、tan 等 :)
  • @DavidHeffernan 我知道您可以将其放入编码术语中:D
  • @Glen,这些计算可能会更容易,但它不是六边形,可能不会很好地镶嵌:-)
【解决方案2】:

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

|小| |宽度 | _______ ______ / \ 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;

【讨论】:

    猜你喜欢
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 2019-04-29
    • 1970-01-01
    • 2018-08-27
    • 1970-01-01
    • 2016-08-25
    • 1970-01-01
    相关资源
    最近更新 更多