正六角形の作図 - 六角形の描き方。 正六角形の作り方 鉛筆で六角形を描く方法

あなたの近くに鉛筆はありますか? その断面を見てください。それは正六角形、または六角形とも呼ばれます。 ナッツの断面、六角形のチェスのフィールド、いくつかの複雑な炭素分子 (グラファイトなど)、雪の結晶、ハニカム、その他の物体もこの形状をしています。 巨大な正六角形が最近発見されました。自然がその創造物にこの特定の形状の構造を頻繁に使用するのは奇妙だと思いませんか? 詳しく見てみましょう。

正六角形は、6 つの等しい辺と等しい角度を持つ多角形です。 から 学校のコースこれには次のような特性があることがわかっています。

  • その辺の長さは外接円の半径に相当します。 この性質を持つのは正六角形だけです。
  • 角度は互いに等しく、各メジャーは 120°です。
  • 六角形の周囲の長さは、その周りに描かれた円の半径がわかっている場合は P=6*R という式を使用して求めることができ、円が内接する場合は P=4*√(3)*r を使用して求めることができます。 R と r は外接円の半径です。
  • 正六角形が占める面積は、S=(3*√(3)*R 2)/2 で求められます。 半径が不明な場合は、一方の辺の長さを代入します。周知のとおり、これは外接円の半径の長さに対応します。

正六角形には 1 つあります 興味深い機能自然界に広く普及しているおかげで、平面のあらゆる表面を重なりや隙間なく埋めることができます。 いわゆるパル補題さえあります。これによると、一辺が 1/√(3) に等しい正六角形は普遍的なカバーです。つまり、直径 1 単位の任意のセットをカバーできます。 。

次に、正六角形の作成を見てみましょう。 いくつかの方法がありますが、最も簡単な方法はコンパス、鉛筆、定規を使用することです。 まずコンパスで任意の円を描き、その円上の任意の場所に点を作ります。 コンパスの角度を変えずに、この点に先端を置き、円上の次の刻み目をマークし、6 つの点がすべて揃うまでこれを続けます。 あとはそれらを直線セグメントで接続するだけで、目的の図形が得られます。

実際には、大きな六角形を描画する必要がある場合があります。 たとえば、2 レベルの石膏ボード天井の場合、中央のシャンデリアの取り付け位置の周囲に、下のレベルに 6 つの小さなランプを取り付ける必要があります。 このサイズのコンパスを見つけるのは非常に困難です。 この場合どうすればよいでしょうか? どうやって大きな円を描くのでしょうか? とてもシンプルです。 必要な長さの強い糸を取り、鉛筆の反対側の端の1つを結ぶ必要があります。 あとは、糸のもう一方の端を天井の希望の位置に押し付けてくれる助手を見つけるだけです。 もちろん、この場合、軽微なエラーが発生する可能性がありますが、部外者にはまったく気付かれない可能性があります。

コンテンツ:

正六角形は完全な六角形とも呼ばれ、6 つの等しい辺と 6 つの辺があります。 等しい角度。 巻尺と分度器を使って六角形を描くことも、丸い物体と定規を使って大まかな六角形を描くことも、鉛筆と少しの直感だけでさらに大まかな六角形を描くこともできます。 さまざまな方法で六角形を描く方法を知りたい場合は、そのまま読んでください。

ステップ

1 コンパスを使って完全な六角形を描きます

  1. 1 コンパスを使用して円を描きます。鉛筆をコンパスに差し込みます。 コンパスを円の希望の半径幅まで拡張します。 半径は数センチメートルから10センチメートルまでの幅になります。 次に、コンパスと鉛筆を紙の上に置き、円を描きます。
    • 最初に半円を描いてから、残りの半円を描く方が簡単な場合があります。
  2. 2 コンパスの針を円の端に移動します。円の上に置きます。 コンパスの角度や位置を変えないでください。
  3. 3 円の端に小さな鉛筆の印を付けます。はっきりとした色にしますが、後で消去するので濃すぎないように注意してください。 コンパスに設定した角度を忘れずに維持してください。
  4. 4 先ほど付けたマークにコンパスの針を移動します。針をマークの上に直接置きます。
  5. 5 円の端にもう一度鉛筆で印を付けます。このようにして、最初のマークから一定の距離に 2 番目のマークを作成します。 一方向に進み続けます。
  6. 6 同じ方法を使用して、さらに 4 つのマークを作成します。元のマークに戻らなければなりません。 そうでない場合は、コンパスを持ってマークを付けた角度が変わった可能性があります。 これは、きつく締めすぎたり、逆に少し緩めたりしたために起こった可能性があります。
  7. 7 定規を使用してマークを接続します。マークが円の端と交差する 6 つの場所が、六角形の 6 つの頂点です。 定規と鉛筆を使用して、隣接するマークを結ぶ直線を描きます。
  8. 8 円、円の端のマーク、およびその他のマークを消去します。 すべての下書き線を消去すると、完璧な六角形が完成します。

2 丸いものと定規を使って大まかな六角形を描く

  1. 1 ガラスの縁を鉛筆でなぞります。このようにして円を描きます。 後ですべての補助線を消去する必要があるため、鉛筆で描くことが非常に重要です。 逆さまのグラスや瓶など、底が丸いものをトレースすることもできます。
  2. 2 円の中心を通る水平線を引きます。定規や本など、刃が真っ直ぐなものなら何でも使えます。 定規をお持ちの場合は、円の縦の長さを計算して半分に分けることで中央に印を付けることができます。
  3. 3 円の半分に「X」を描き、それを 6 つの等しいセクションに分割します。すでに円の中心を通る線を引いているので、各部分が均等になるように、X の幅を高さよりも大きくする必要があります。 ピザを6つのピースに分割することを想像してください。
  4. 4 各セクションから三角形を作成します。これを行うには、定規を使用して各セクションの曲線部分の下に直線を描き、他の 2 本の線と接続して三角形を形成します。 残りの 5 つのセクションでこれを行います。 ピザのスライスの周りに生地を作るようなものだと考えてください。
  5. 5 補助線をすべて消去します。ガイドラインには、円、円をセクションに分割する 3 本の線、および途中で作成したその他のマークが含まれます。

3 鉛筆1本で大まかな六角形を描きます

  1. 1 水平線を描きます。定規を使わずに直線を引くには、水平線の始点と終点を描くだけです。 次に鉛筆を始点に置き、終点まで線を描きます。 この線の長さはわずか数センチメートルです。
  2. 2 水平線の端から斜めの線を2本引きます。左側の対角線は、右側の対角線と同様に外側を向く必要があります。 これらの線が水平線に対して 120 度の角度を形成していると想像できます。
  3. 3 最初に引いた水平線からさらに 2 本の水平線を内側に描きます。これにより、最初の 2 つの対角線の鏡像が作成されます。 左下の線は左上の線を反映し、右下の線は右上の線を反映する必要があります。 上の水平線は外側を向く一方、下の水平線はベースの内側を向く必要があります。
  4. 4 下の 2 本の対角線を結ぶもう 1 つの水平線を描きます。このようにして、六角形のベースを描きます。 理想的には、この線は上部の水平線と平行である必要があります。 これで六角形が完成しました。
  • 幅が広すぎるマークによる誤差を最小限に抑えるために、鉛筆とコンパスは鋭利である必要があります。
  • コンパス法を使用する場合、6 つすべてのマークではなく、それぞれのマークを接続すると、正三角形が得られます。

警告

  • コンパスはかなり鋭利な物体ですので、取り扱いには十分注意してください。

動作原理

  • 各方法は、すべての辺の長さに等しい半径を持つ 6 つの正三角形で形成される六角形を描くのに役立ちます。 コンパスの幅は変わらないため、描かれた 6 つの半径は同じ長さであり、六角形を作成するすべての線も同じ長さです。 6 つの三角形は正三角形であるため、頂点間の角度は 60 度になります。

必要なもの

  • 鉛筆
  • ルーラー
  • コンパスのペア
  • 紙の下に敷いてコンパスの針が滑らないようにするもの。
  • 消しゴム

正外接三角形は次のように作られます。(図 38)。 指定された半径の円の中心から R1 半径のある円を描く R2 = 2R1 そしてそれを3等分します。 分割点 A、B、C 半径の円に外接する正三角形の頂点です R1 .

図38

正外接四角形(正方形)コンパスと定規を使用して作成できます (図 39)。 与えられた円内に、互いに直交する 2 つの直径が描かれます。 直径と円の交点を中心として、円の半径 R 点で交差するまで円弧を記述します あいうえお 。 ポイント , B , C , D と は、指定された円の周りに外接する正方形の頂点です。

図39

正外接六角形を作成するにはまず、上記の方法で説明した正方形の頂点を構築する必要があります (図 40、a)。 正方形の頂点を決定すると同時に、与えられた半径の円を決定します。 R 点で6等分に分割 1, 2, 3, 4, 5, 6 そして正方形の垂直辺を描きます。 分割点を通る円を描く 2–5 そして 3–6 正方形の垂直辺と交差するまで直線を引くと (図 40、b)、頂点が得られます。 A、B、D、E 正六角形を表現しました。

図40

その他のピーク Cそして F半径円の円弧を使用して決定されます O.A.これは、指定された円の垂直直径の延長線と交差するまで実行されます。
3つのペアリング

さまざまな位置で六角柱を描く方法を学びましょう。

正六角形を構築するさまざまな方法を研究し、六角形の図面を作成し、その構築が正確であることを確認します。 六角形を基にして六角柱を作成します。

図の六角柱を考えてみましょう。 3.52 とその正射影を図に示します。 3.53。 六角柱(ヘキ​​サゴン)の底面は正六角形で、側面は同一の長方形です。 六角形を遠近法で正しく描くには、まずその底面を遠近法で正しく描く方法を学ばなければなりません (図 3.54)。 図の六角形の中にあります。 3.55 個の頂点は 1 から 6 までの番号で指定されます。 点 1 と 3、4 と 6 を垂直直線で接続すると、これらの直線は円の中心点とともに、直径 5 - 2 を 4 つの等しいセグメントに分割することがわかります (これらのセグメントは円弧で示されています)。 )。 六角形の反対側の辺は互いに平行であり、その中心を通り 2 つの頂点を結ぶ線にも平行です (たとえば、辺 6 - 1 と 4 - 3 は線 5 - 2 に平行です)。 これらの観察は、遠近法で六角形を構築するのに役立ち、また、この構築が正しいかどうかを確認するのにも役立ちます。 表現から正六角形を構築するには、外接円に基づく方法と正方形に基づく方法の 2 つがあります。

外接円に基づきます。 図を見てください。 3.56。 正六角形のすべての頂点は、半径が六角形の辺に等しい外接円に属します。


横向きの六角形。 任意の開口部の水平楕円、つまり遠近法での外接円を描きます。 次に、六角形の頂点である 6 つの点を見つける必要があります。 与えられた円の中心を通る任意の直径を描きます (図 3.57)。 楕円上にある直径の 5 と 2 の端点は、六角形の頂点です。 残りの頂点を見つけるには、この直径を 4 つの等しいセグメントに分割する必要があります。 直径はすでに円の中心点によって 2 つの半径に分割されています。残っているのは各半径を半分に分割することだけです。 透視図では、4 つのセグメントはすべて、観察者から遠ざかるにつれて均等に収縮します (図 3.58)。 次に、半径の中点 (点 A と B) を通り、直線 5 - 2 に垂直な直線を描きます。点 5 と点 2 での楕円の接線を使用して、その方向を見つけることができます (図 3.59)。 これらの接線は直径 5 - 2 に垂直になり、これらの接線に平行な点 A と B を通って引かれた線も、線 5 - 2 に垂直になります。これらの線と楕円の交点で得られる点を次のように指定します。 1、3、4、6 (図 3.60)。 6 つの頂点すべてを直線で結びます (図 3.61)。

構築が正しいことを確認してください 違う方法。 構築が正しい場合、六角形の対向する頂点を結ぶ線は円の中心で交差し (図 3.62)、六角形の対向する辺は対応する直径に平行になります (図 3.63)。 別の確認方法を図に示します。 3.64。

縦の六角形。 このような六角形では、点 7 と点 3、点 b と点 4 を結ぶ直線、および点 5 と点 2 での外接円の接線は垂直方向を持ち、透視図上で保持されます。 したがって、楕円に対して 2 つの垂直接線を引くことにより、点 5 と 2 (接点) が見つかります。 それらを直線で結び、遠近法の縮小を考慮して、得られた直径 5 - 2 を 4 つの等しいセグメントに分割します (図 3.65)。 点 A と B を通る垂直線を引き、楕円との交点で点 1、3、6l4 を見つけます。 次に、点 1 ~ 6 を直線で順番に結びます (図 3.66)。 前の例と同じ方法で六角形の構造が正しいことを確認します。

説明した六角形の構築方法を使用すると、円に基づいてこの図形を取得できます。これは、特定の比率の正方形よりも遠近法で描くのが簡単です。 したがって、六角形を構築するこの方法は最も正確で普遍的であると思われます。 正方形ベースの作図法は、図面上にすでに立方体がある場合、つまり正方形の比率と辺の方向が決まっている場合に、六角形を描きやすくします。

正方形をベースにしています。 図を見てください。 3.67。 正方形に内接する六角形は、正方形の水平方向の一辺5−2に等しく、垂直方向の長さより短い。

縦の六角形。 遠近法で垂直の正方形を描きます。 水平辺に平行な対角線の交点を通る直線を描きます。 得られたセグメント 5 - 2 を 4 つの等しい部分に分割し、点 A と点 B を通る垂直線を引きます (図 3.68)。 六角形の上下を区切る線は、正方形の辺と一致しません。 それらを正方形の水平辺から一定の距離 (1114a) に、それらに平行に描画します。 こうして求めた点1と点3を点2と、点6と点4を点5で結ぶと六角形が得られます(図3.69)。

水平六角形も同じ順序で構築されます (図 3.70 および 3.71)。

この構築方法は、十分な開口部を持つ六角形にのみ適しています。 六角形の開きがわずかな場合には、外接円による方法を使用するとよいでしょう。 正方形を介して構築された六角形を確認するには、すでに知られている方法を使用できます。

さらに、結果の六角形(図面では楕円)の周りに円を描く別の方法があります。 六角形のすべての頂点がこの楕円に属している必要があります。

六角形を描くスキルをマスターしたら、自由に六角柱を描くことができます。 図の図をよく見てください。 同様に、外接円に基づいて六角柱を作成するための図 (図 3.73、3.74、および 3.75)、および正方形に基づいて六角柱を作成するための図 (図 3.76、3.77、および 3.78) も参照してください。 縦と横の六角形をさまざまな方法で描きます。 縦六角形の図では、側面の長辺は互いに平行な縦直線となり、底辺の六角形は地平線から離れるほど開いた形状になります。 横六角形の図では、側面の長辺が地平線の消失点に集まり、観察者から遠ざかるほど基本六角形の開きが大きくなります。 六角形を描くときは、両方の底辺の平行なエッジが遠近法で収束していることも確認してください (図 3.79; 3.80)。

ヘキサゴン グリッド (六角形グリッド) は一部のゲームで使用されますが、長方形グリッドほど単純でも一般的でもありません。 私は 20 年近くにわたって 16 進メッシュに関するリソースを収集してきました。そして、最もシンプルなコードで実装された、最も洗練されたアプローチについてのこのガイドを書きました。 この記事では、Charles Fu と Clark Verbrugge のガイドを多用しています。 六角形メッシュを作成するさまざまな方法、それらの関係、および最も一般的なアルゴリズムについて説明します。 この記事の多くの部分は対話型です。グリッド タイプを選択すると、対応する図、コード、テキストが変更されます。 (注: これは原文にのみ適用されます。学習することをお勧めします。翻訳では、原文のすべての情報が保持されますが、対話性はありません。).

この記事のコード例は疑似コードで記述されているため、独自の実装を作成する場合に読みやすく、理解しやすくなっています。

ジオメトリ

六角形は 6 辺の多角形です。 正六角形はすべての辺(辺)が同じ長さです。 正六角形のみを扱います。 通常、六角形メッシュは水平 (尖った上部) と垂直 (平らな上部) の方向を使用します。


上部が平らな六角形 (左) と尖った上部 (右) を持つ六角形

六角形には6つの面があります。 各面は 2 つの六角形に共通です。 六角形には 6 つの角点があります。 各角点は 3 つの六角形に共通です。 中心、エッジ、コーナーポイントの詳細については、メッシュ パーツ (正方形、六角形、三角形) に関する記事を参照してください。

角度

正六角形では内角は120°です。 「くさび」は 6 つあり、それぞれが内角 60°の正三角形です。 コーナーポイント 中心から (60° * i) + 30° の距離 (サイズ単位) に位置します。 コード内:

関数 hex_corner(center, size, i): var angle_deg = 60 * i + 30 var angle_rad = PI / 180 * angle_deg return Point(center.x + size * cos(angle_rad), center.y + size * sin(angle_rad) )
六角形を埋めるには、 hex_corner(…, 0) から hex_corner(…, 5) までの多角形の頂点を取得する必要があります。 六角形の輪郭を描画するには、これらの頂点を使用してから、 hex_corner(..., 0) で再度線を描画する必要があります。

2 つの方向の違いは、x と y が入れ替わることで、結果として角度が変化します。上が平らな六角形の角度は 0°、60°、120°、180°、240°、300°、上が尖った六角形の角度になります。六角形の角度は 30 °、90 °、150 °、210 °、270 °、330 °です。


上部が平らで鋭い六角形の角

サイズと位置

次に、いくつかの六角形を一緒に配置したいと思います。 水平方向の場合、六角形の高さは高さ = サイズ * 2 です。 隣接する六角形間の垂直距離は、vert = height * 3/4 です。

六角形の幅 width = sqrt(3)/2 * 高さ 。 隣接する六角形間の水平距離は horiz = width です。

一部のゲームでは、正六角形と完全に一致しない六角形のピクセル アートが使用されています。 このセクションで説明する角度と配置の公式は、このような六角形の寸法とは一致しません。 六角形メッシュ アルゴリズムについて説明するこの記事の残りの部分は、六角形がわずかに伸びたり潰されたりする場合にも適用されます。



座標系

六角形をグリッドに組み立て始めましょう。 正方形のグリッドの場合、組み立てる明白な方法は 1 つだけです。 六角形には多くのアプローチがあります。 主な表現として 3 次座標を使用することをお勧めします。 軸座標またはオフセット座標は、マップを保存し、ユーザーに座標を表示するために使用する必要があります。

オフセット座標

最も一般的なアプローチは、後続の列または行をそれぞれオフセットすることです。 列は、col または q で指定されます。 行は row または r で表されます。 奇数または偶数の列/行をオフセットできるため、水平および垂直の六角形にはそれぞれ 2 つのオプションがあります。


横配置「奇数r」


横配置「偶数r」


垂直方向の「奇数q」配置


縦配置「偶数q」

3次座標

六角形グリッドを次のように見る別の方法もあります。 三つ主軸ではなく、 、正方形のグリッドのように。 エレガントな対称性を示しています。

立方体のグリッドを考えてみましょう。 切り取ってみましょう x + y + z = 0 の対角面。 これは奇妙なアイデアですが、六角形メッシュ アルゴリズムを簡素化するのに役立ちます。 特に、デカルト座標からの標準的な演算 (座標の合計と減算、スカラー量と距離の乗算と除算) を使用できるようになります。

立方体のグリッド上の 3 つの主軸と、それらの 6 つの軸との関係に注目してください。 対角線六角形のグリッドの方向。 グリッドの対角軸は、六角形グリッドの主方向に対応します。


六角形


キューブ

すでに正方形メッシュと立方体メッシュのアルゴリズムがあるため、3 次座標を使用することで、これらのアルゴリズムを六角形メッシュに適応させることができます。 この記事のアルゴリズムのほとんどにこのシステムを使用します。 別の座標系でアルゴリズムを使用するには、3 次座標を変換し、アルゴリズムを実行してから、変換して戻します。

六角形メッシュに対して三次座標がどのように機能するかを学びます。 六角形を選択すると、3 つの軸に対応する 3 次座標が強調表示されます。

  1. 立方体グリッドの各方向は次のように対応します。 六角形のグリッド上にあります。 接続を確認するには、z が 0、1、2、3 に等しい六角形を選択してみてください。 線は青でマークされています。 x (緑) と y (紫) についても同じことを試してください。
  2. 六角形グリッドの各方向は、立方体グリッドの 2 つの方向の組み合わせです。 たとえば、六角形グリッドの「北」は +y と -z の間にあるため、「北」ごとに y が 1 ずつ増加し、z が 1 ずつ減少します。
3 次座標は、六角形グリッド座標系の適切な選択です。 条件は x + y + z = 0 であるため、アルゴリズム内で保持する必要があります。 この条件により、各六角形に常に正準座標が存在することも保証されます。

立方体と六角形にはさまざまな座標系が存在します。 それらの中には、条件が x + y + z = 0 とは異なるものもあります。 多くのシステムのうちの 1 つだけを示しました。 x-y 、 y-z 、 z-x を使用して 3 次座標を作成することもできます。これらには独自の興味深いプロパティのセットがありますが、ここでは説明しません。

しかし、地図をそのように保存する方法がわからないため、座標として 3 つの数値を保存したくないと主張することもできます。

軸座標

「台形」座標系とも呼ばれる軸座標系は、3 次座標系の 2 つまたは 3 つの座標から構築されます。 条件 x + y + z = 0 があるため、3 番目の座標は必要ありません。 軸座標は、マップを保存したり、ユーザーに座標を表示したりするのに役立ちます。 3 次座標と同様に、デカルト座標の加算、減算、乗算、除算の標準演算を使用できます。

多くの 3 次座標系と軸座標系が存在します。 このガイドではすべての組み合わせを説明するわけではありません。 2 つの変数、q (列) と r (行) を選択します。 この記事の図では、q は x に対応し、r は z に対応しますが、図を回転および回転して異なる対応を取得できるため、この対応は任意です。

ディスプレイスメント グリッドに対するこのシステムの利点は、アルゴリズムがより理解しやすいことです。 このシステムの欠点は、長方形のカードを保管するのが少し奇妙であることです。 マップの保存に関するセクションを参照してください。 一部のアルゴリズムは 3 次座標でさらに明確ですが、x + y + z = 0 という条件があるため、3 番目の暗黙の座標を計算して、これらのアルゴリズムで使用できます。 私のプロジェクトでは軸を q、r、s と呼ぶので、条件は q + r + s = 0 のようになり、必要に応じて s = -q - r を計算できます。

車軸

オフセット座標は、正方形のグリッドに使用される標準のデカルト座標と同じであるため、ほとんどの人が最初に考えるものです。 残念ながら、2 つの軸のうち 1 つは方向に反して実行する必要があり、これにより事態が複雑になってしまいます。 キューブ システムとアクシス システムはよりシンプルなアルゴリズムを備えていますが、カード ストレージはもう少し複雑です。 「交互」または「デュアル」と呼ばれる別のシステムもありますが、ここでは考慮しません。 立方体やアキシャルよりも扱いやすいと感じる人もいます。


オフセット座標、3 次および軸方向

対応する座標が増加する方向です。 軸に垂直な線は、座標が一定に保たれます。 上のグリッド図は垂直線を示しています。

座標変換

設計では軸座標またはオフセット座標を使用する可能性がありますが、多くのアルゴリズムは 3 次座標で表現する方が簡単です。 したがって、システム間で座標を変換できる必要があります。

軸座標は 3 次座標と密接に関連しているため、変換は簡単です。

# 3 次座標をアキシャル座標に変換します q = x r = z # アキシャル座標を 3 次座標に変換します x = q z = r y = -x-z
コードでは、これら 2 つの関数は次のように記述できます。

Function cube_to_hex(h): # axis var q = h.x var r = h.z return Hex(q, r) function hex_to_cube(h): # cubic var x = h.q var z = h.r var y = -x-z return Cube(x, y 、z)
オフセット座標はかなり複雑です。

隣接する六角形

1 つの六角形がある場合、その隣にある 6 つの六角形は何ですか? ご想像のとおり、答えは 3 次座標で最も簡単で、軸座標では非常に簡単ですが、変位座標では少し難しくなります。 6 つの「対角」六角形を計算する必要がある場合もあります。

3次座標

16 進座標でスペースを 1 つ移動すると、3 つの 3 次座標の 1 つが +1 に変更され、もう 1 つが -1 に変更されます (合計は 0 のままでなければなりません)。 +1 では 3 つの可能な座標が変更され、-1 では残りの 2 つが変更されます。 これにより、6 つの変更が可能になります。 それぞれが六角形の方向の 1 つに対応します。 最もシンプルで、 最速の方法- 変更を事前に計算し、コンパイル時に 3 次座標テーブル Cube(dx, dy, dz) に配置します。

変数の方向 = [ Cube(+1, -1, 0), Cube(+1, 0, -1), Cube(0, +1, -1), Cube(-1, +1, 0), Cube( -1, 0, +1), Cube(0, -1, +1) ] 関数 cube_direction(direction): 方向を返します function cube_neighbor(hex, Direction): cube_add(hex, cube_direction(direction)) を返します

軸座標

前と同様に、最初は立方体系を使用します。 Cube(dx, dy, dz) テーブルを Hex(dq, dr) テーブルに変換しましょう。

変数の方向 = [ Hex(+1, 0), Hex(+1, -1), Hex(0, -1), Hex(-1, 0), Hex(-1, +1), Hex(0, +1) ] function hex_direction(direction): 方向を返します function hex_neighbor(hex, Direction): var dir = hex_direction(direction) return Hex(hex.q + dir.q, hex.r + dir.r)

オフセット座標

軸座標では、グリッド上のどこにいるかに応じて変更を加えます。 オフセット列/行にいる場合、ルールはオフセットのない列/行の場合とは異なります。

前と同様に、col と row に追加する必要がある数値のテーブルを作成します。 ただし、今回は 2 つの配列があり、1 つは奇数の列/行用で、もう 1 つは偶数の列/行用です。 上のグリッド マップ画像の (1,1) を見て、6 方向のそれぞれに移動すると列と行がどのように変化するかに注目してください。 次に、 (2,2) のプロセスを繰り返しましょう。 テーブルとコードは 4 種類の変位グリッドごとに異なります。各グリッド タイプに対応するコードは次のとおりです。

奇数r
var 方向 = [ [ Hex(+1, 0), Hex(0, -1), Hex(-1, -1), Hex(-1, 0), Hex(-1, +1), Hex(0) 、+1) ]、[ 16 進数(+1, 0)、16 進数(+1、-1)、16 進数(0、-1)、16 進数(-1、0)、16 進数(0、+1)、16 進数( +1, +1) ] ] 関数 offset_neighbor(hex, 方向): var parity = hex.row & 1 var dir = 方向 return Hex(hex.col + dir.col, hex.row + dir.row)


偶数r
var 方向 = [ [ Hex(+1, 0), Hex(+1, -1), Hex(0, -1), Hex(-1, 0), Hex(0, +1), Hex(+1) 、+1) ]、[ 16 進数(+1, 0)、16 進数(0、-1)、16 進数(-1、-1)、16 進数(-1、0)、16 進数(-1、+1)、16 進数(0, +1) ] ] 関数 offset_neighbor(hex, 方向): var parity = hex.row & 1 var dir = 方向 return Hex(hex.col + dir.col, hex.row + dir.row)


偶数 (EVEN) 行と奇数 (ODD) 行のグリッド

奇数Q
var 方向 = [ [ Hex(+1, 0), Hex(+1, -1), Hex(0, -1), Hex(-1, -1), Hex(-1, 0), Hex(0) 、+1) ]、[ 16 進数(+1、+1)、16 進数(+1、0)、16 進数(0、-1)、16 進数(-1、0)、16 進数(-1、+1)、16 進数(0, +1) ] ] 関数 offset_neighbor(hex, Direction): var parity = hex.col & 1 var dir = Direction return Hex(hex.col + dir.col, hex.row + dir.row)


偶数q
var 方向 = [ [ Hex(+1, +1), Hex(+1, 0), Hex(0, -1), Hex(-1, 0), Hex(-1, +1), Hex(0) 、+1) ]、[ 16 進数(+1, 0)、16 進数(+1、-1)、16 進数(0、-1)、16 進数(-1、-1)、16 進数(-1、0)、16 進数(0, +1) ] ] 関数 offset_neighbor(hex, Direction): var parity = hex.col & 1 var dir = Direction return Hex(hex.col + dir.col, hex.row + dir.row)


偶数 (EVEN) 列と奇数 (ODD) 列のグリッド

対角線

16 進座標の「対角」空間内を移動すると、3 つの 3 次座標のうち 1 つが ±2 変化し、他の 2 つが ∓1 変化します (合計は 0 のままでなければなりません)。

Var 対角線 = [ Cube(+2, -1, -1), Cube(+1, +1, -2), Cube(-1, +2, -1), Cube(-2, +1, +1) )、Cube(-1、-1、+2)、Cube(+1、-2、+1) ] 関数 cube_diagonal_neighbor(hex、方向): return cube_add(hex、dialogs)
前と同様に、3 つの座標の 1 つをドロップすることでこれらの座標を軸座標に変換するか、最初に結果を計算してオフセット座標に変換できます。


距離

3次座標

立方体座標系では、各六角形は 3 次元空間内の立方体です。 隣接する六角形は、16 進グリッドでは 1 の間隔ですが、立方体グリッドでは 2 の間隔になります。 これにより、距離の計算が簡単になります。 正方形のグリッドでは、マンハッタンの距離は abs(dx) + abs(dy) です。 立方体のグリッドでは、マンハッタン距離は abs(dx) + abs(dy) + abs(dz) です。 六角形のグリッド内の距離はそれらの半分に等しくなります。

関数 cube_ distance(a, b): return (abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z)) / 2
この表記法と同等のことは、3 つの座標のうちの 1 つが他の 2 つの座標の合計である必要があり、それを距離として取ることです。 以下の半減形式または最大値形式を選択できますが、どちらも同じ結果になります。

関数 cube_ distance(a, b): return max(abs(a.x - b.x), abs(a.y - b.y), abs(a.z - b.z))
図では、最大値が色で強調表示されています。 各色が 6 つの「対角」方向の 1 つを表すことにも注意してください。

GIF


軸座標

アキシャル系では、3 番目の座標は暗黙的に表現されます。 軸方向から立方体に変換して距離を計算しましょう。

関数 hex_ distance(a, b): var ac = hex_to_cube(a) var bc = hex_to_cube(b) return cube_ distance(ac, bc)
あなたの場合、コンパイラが hex_to_cube と cube_ distance をインライン(インライン)にすると、次のようなコードが生成されます。

関数 hex_ distance(a, b): return (abs(a.q - b.q) + abs(a.q + a.r - b.q - b.r) + abs(a.r - b.r)) / 2
沢山あります さまざまな方法で記録方法に関係なく、軸座標での六角形間の距離を記録します。 アキシャル系の六角形間の距離は、立方体系のマンハッタン距離から抽出されます。。 たとえば、説明されている「差分の差」は、 a.q + a.r - b.q - b.r を a.q - b.q + a.r - b.r と書き、二等分形式 cube_ distance の代わりに最大値形式を使用することによって取得されます。 3次座標との関係を見ると、それらはすべて似ています。

オフセット座標

軸座標と同様に、オフセット座標を 3 次座標に変換し、3 次距離を使用します。

関数 offset_ distance(a, b): var ac = offset_to_cube(a) var bc = offset_to_cube(b) return cube_ distance(ac, bc)
多くのアルゴリズムで同じパターンを使用します。つまり、六角形から立方体に変換し、アルゴリズムの立方体バージョンを実行して、立方体の結果を六角形の座標 (軸座標またはオフセット座標) に変換します。

線を引く

ある六角形から別の六角形に線を引くにはどうすればよいでしょうか? 線形補間を使用して線を描画しています。 ラインは N+1 点で均一にサンプリングされ、これらのサンプルがどの六角形内にあるかが計算されます。

GIF


  1. まず、端点間の六角形の距離となる N を計算します。
  2. 次に、点 A と点 B の間で N+1 点を均等にサンプリングします。線形補間を使用して、それらを含む 0 から N までの i の値について、各点が A + (B - A) * 1.0/N * になることを決定します。私 。 図では、これらの制御点は青色で示されています。 結果は浮動小数点座標になります。
  3. それぞれ変身させてみましょう コントロールポイント(float) を六角形 (int) に戻します。 このアルゴリズムは cube_round と呼ばれます (下記を参照)。
すべてをまとめて A から B まで線を引きます。

Function lerp(a, b, t): // 浮動小数点数の場合 return a + (b - a) * t function cube_lerp(a, b, t): // 六角形の場合 return Cube(lerp(a.x, b.x, t), lerp(a.y, b.y, t), lerp(a.z, b.z, t)) 関数 cube_linedraw(a, b): var N = cube_ distance(a, b) var results = 各 0 ≤ i ≤ N: results.append( cube_round(cube_lerp(a, b, 1.0/N * i))) 結果を返します
ノート:

  • cube_lerp が 2 つの六角形の間のエッジに正確にある点を返す場合があります。 次に、cube_round はそれを一方向または別の方向に移動します。 線は一方向に動かした方が見栄えが良くなります。 これは、ループを開始する前に、「イプシロン」六角形 Cube(1e-6, 1e-6, -2e-6) を一方または両方のエンドポイントに追加することで実行できます。 これにより、ラインがエッジに当たらないように、ラインを一方向に「微調整」します。
  • 正方グリッドの DDA ライン アルゴリズムでは、N が各軸に沿った最大距離に等しくなります。 立方体空間でも同じことを行います。これは六角形グリッドの距離に似ています。
  • cube_lerp 関数は、float 座標を持つ立方体を返す必要があります。 静的型付け言語でプログラミングしている場合は、Cube 型を使用できません。 代わりに FloatCube 型を定義することも、別の型を定義したくない場合は線描画コードに関数をインライン化することもできます。
  • インライン cube_lerp によってコードを最適化し、ループの外で B.x-A.x 、 B.x-A.y 、および 1.0/N を計算できます。 乗算は繰り返し加算に変換できます。 結果は、DDA ライン アルゴリズムのようなものになります。
  • 軸座標または三次座標を使用して線を描画しますが、オフセット座標を使用したい場合は、 を確認してください。
  • 線を描くには多くのオプションがあります。 場合によっては「上塗り」が必要な場合もあります。 六角形でスーパーカバーされた線を描画するためのコードが送られてきましたが、まだ調べていません。

移動範囲

座標範囲

六角形の中心と範囲 N が与えられた場合、どの六角形がその N ステップ以内にありますか?

六角形間の距離の公式 distance = max(abs(dx), abs(dy), abs(dz)) から逆算を行うことができます。 N 内のすべての六角形を見つけるには、 max(abs(dx), abs(dy), abs(dz)) ≤ N が必要です。 これは、 abs(dx) ≤ N および abs(dy) ≤ N および abs(dz) ≤ N の 3 つの値がすべて必要であることを意味します。 絶対値を取り除くと、 -N ≤ dx ≤ N 、 -N ≤ dy ≤ N 、および -N ≤ dz ≤ N が得られます。 コードでは、これは入れ子になったループになります。

Var results = 各 -N ≤ dx ≤ N: 各 -N ≤ dy ≤ N: 各 -N ≤ dz ≤ N: dx + dy + dz = 0 の場合: results.append(cube_add(center, Cube(dx 、ディ、ディズ)))
このサイクルは機能しますが、まったく効果がありません。 ループするすべての dz 値のうち、実際に立方体の条件 dx + dy + dz = 0 を満たすのは 1 つだけです。 代わりに、条件を満たす dz の値を直接計算します。

Var results = 各 -N ≤ dx ≤ N: 各 max(-N, -dx-N) ≤ dy ≤ min(N, -dx+N): var dz = -dx-dy results.append(cube_add(センター、キューブ(dx、dy、dz)))
このサイクルは必要な座標に沿ってのみ通過します。 図では、各範囲は 1 対の線です。 各行は不等式です。 6 つの不等式を満たすすべての六角形を選択します。

GIF


重複する範囲

複数の範囲にある六角形を検索する必要がある場合は、六角形のリストを生成する前に範囲を交差させることができます。

この問題には、代数または幾何学の観点からアプローチできます。 代数的には、各領域は -N ≤ dx ≤ N という形式の不等式条件として表現され、これらの条件の共通部分を見つける必要があります。 幾何学的には、各領域は 3D 空間の立方体であり、3D 空間で 2 つの立方体を交差させて 3D 空間の直方体を取得します。 次に、それを x + y + z = 0 平面に投影し直し、六角形を取得します。 この問題を代数的に解きます。

まず、条件 -N ≤ dx ≤ N をより一般的な形式 x min ≤ x ≤ x max に書き直し、 x min = center.x - N および x max = center.x + N とします。 y と z についても同じことを行ってみましょう。結果は次のようになります。 一般的な形式前のセクションのコード:

Var results = 各 xmin ≤ x ≤ xmax: 各 max(ymin, -x-zmax) ≤ y ≤ min(ymax, -x-zmin): var z = -x-y results.append(Cube(x, y, z))
2 つの範囲 a ≤ x ≤ b および c ≤ x ≤ d の共通部分は、 max(a, c) ≤ x ≤ min(b, d) です。 六角形の面積は x、y、z の範囲として表現されるため、x、y、z の範囲を個別に交差し、ネストされたループを使用して交差部分の六角形のリストを生成できます。 六角形の 1 つの領域については、 y と z についても同様に、 x min = H.x - N および x max = H.x + N をとります。 2 つの六角形領域の交差については、y と同様に、x min = max(H1.x - N, H2.x - N) および x max = min(H1.x + N, H2.x + N) をとります。 z 。 3 つ以上のエリアが交差する場合も同じパターンが機能します。

GIF


障害物

障害物がある場合、最も簡単な方法は距離制限を設定することです (幅優先探索)。 下の図では、4 つの動きに制限しています。 コードでは、 fringes[k] は k ステップで到達できるすべての六角形の配列です。 メインループを通過するたびに、レベル k-1 をレベル k ずつ拡張します。

関数 cube_reachable(開始、移動): var Visited = set() 開始を訪問済みに追加 var fringes = fringes.append() それぞれ 1< k ≤ movement: fringes.append() for each cube in fringes: for each 0 ≤ dir < 6: var neighbor = cube_neighbor(cube, dir) if neighbor not in visited, not blocked: add neighbor to visited fringes[k].append(neighbor) return visited

ターン

六角形のベクトル (2 つの六角形の差) が与えられた場合、他の六角形を指すように回転する必要がある場合があります。 1/6 円の回転に固執すれば、3 次座標を使用してこれを行うのは簡単です。

右に 60 度回転すると、各座標が 1 つ右に移動します。

[x, y, z] ~ [-z, -x, -y]
左に 60 度回転すると、各座標が 1 つ左に移動します。

[x, y, z] ~ [-y, -z, -x]



「遊んでみると」[元の記事] 図を見ると、各回転が 60°であることがわかります。 変化座標を符号化し、物理的に「回転」させます。 120°回転すると、符号は再び同じになります。 180°回転すると符号は変わりますが、座標は元の位置に戻ります。

これは、中心位置 C を中心とした位置 P の回転の完全なシーケンスであり、新しい位置 R が生成されます。

  1. P および C 位置を 3 次座標に変換します。
  2. 中心を減算してベクトルを計算します: P_from_C = P - C = Cube(P.x - C.x, P.y - C.y, P.z - C.z) 。
  3. 前述のようにベクトル P_from_C を回転し、最終的なベクトルに R_from_C という指定を割り当てます。
  4. 中心を追加してベクトルを位置に変換します: R = R_from_C + C = Cube(R_from_C.x + C.x, R_from_C.y + C.y, R_from_C.z + C.z) 。
  5. 立方体位置 R を目的の座標系に変換し直します。
変換にはいくつかの段階がありますが、それぞれは非常に単純です。 軸座標で回転を直接定義することで、これらのステップの一部を短縮することは可能ですが、16 進ベクトルはオフセット座標では機能せず、オフセット座標のステップを短縮する方法がわかりません。 回転を計算する他の方法については、stackexchange に関する説明も参照してください。

指輪

シンプルなリング

特定の六角形が特定の半径のリングに属しているかどうかを確認するには、この六角形から中心までの距離を計算し、それが半径に等しいかどうかを確認する必要があります。 このようなすべての六角形のリストを取得するには、中心から半径ステップを実行し、リングに沿ったパスに沿って回転ベクトルをたどる必要があります。

Function cube_ring(center, radius): var results = # このコードは radius == 0 では機能しません。 理由はわかりますか? var cube = cube_add(center, cube_scale(cube_direction(4), radius)) 0 ≤ i ごと< 6: for each 0 ≤ j < radius: results.append(cube) cube = cube_neighbor(cube, i) return results
このコードでは、立方体はリング上で始まり、図の中心から隅に向かう大きな矢印で示されています。 最初に角度 4 を選択したのは、番号が移動する方向のパスと一致するためです。 別の開始角度が必要になる場合があります。 内側のループの各段階で、立方体はリングの周りを 1 つの六角形で移動します。 半径 6 * ステップ後に、彼は最初の場所に到着します。


スパイラルリング

螺旋パターンでリングを通過することにより、リングの内側の部分を埋めることができます。

関数 cube_spiral(center, radius): var results = 各 1 ≤ k ≤ radius: results = results + cube_ring(center, k) 結果を返します



大きな六角形の面積は、すべての円の合計に中心の 1 を加えたものです。 この式を使用して面積を計算します。

この方法で六角形を移動することは、移動範囲の計算にも使用できます (上記を参照)。

可視領域

所定の位置、所定の距離から見え、障害物に遮られないものは何ですか? 最も簡単な方法これを決定するには、指定された範囲内の各六角形に線を引くことになります。 線が壁に触れていない場合は、六角形が表示されます。 [元の記事の図上] 六角形の上にマウスを移動すると、これらの六角形とその線が交わる壁に線がどのように描かれているかがわかります。

このアルゴリズムは広い領域では遅くなる可能性がありますが、実装は簡単なので、最初はこのアルゴリズムを使用することをお勧めします。

GIF



可視性にはさまざまな定義があります。 元の六角形の中心から別の六角形の中心を見たいですか? 元の六角形の中心から別の六角形の一部を見たいですか? おそらく、最初の六角形の任意の点からの別の六角形の一部でしょうか? 視界を妨げる障害物は正六角形よりも小さいですか? スコープは、一見したよりも複雑で多様な概念です。 最も単純なアルゴリズムから始めましょう。ただし、プロジェクトの答えが確実に正しく計算されることを期待してください。 単純なアルゴリズムが非論理的な結果を生み出す場合もあります。

将来的にはこのガイドを拡張したいと考えています。 私は持っている