2013-01-23 13 views
11

私がしようとしているのは、六角形グリッド上の2つの点の間にある六角形の数です。私は数式をオンラインで検索しようとしましたが、使用している16進グリッドの種類に一致するものを見つけることができませんでした。私は、これは、この座標系では不可能ではないかもしれないことを承知していますが、私は戻って変更行く前に、これは土壇場の努力であるhttp://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=1962六角形グリッド上の距離の計算

の六角グリッドは同じ座標系で、この1のようにレイアウトされていますそれ。 ありがとうございます。六角グリッド内の特定の場所での六角形が持つ線分と交差するかどうかを判定

まず、決定機能を行う:ここ

+0

あなたはヘクスの中心点を参照していますか?言い換えれば、あなたは[0,0]と[3,3]の間にどれだけの数があるのか​​を調べようとしていますか? – ChiefTwoPencils

+0

はい、正確に私が見つけようとしていることです – DeathorGlory9

+0

どのように定義しますか? 2点間の16進数のセットはユニークではありません – thang

答えて

4

user2709663 @おかげで、答えを提供するための@jonathankoren:

def hexDistance(start, dest): 
    if (start.x == dest.x): 
    return abs(dest.y - start.y) 
    elif (start.y == dest.y): 
    return abs(dest.x - start.x) 
    else: 
    dx = abs(dest.x - start.x) 
    dy = abs(dest.y - start.y) 
    if start.y < dest.y: 
     return dx + dy - int(math.ceil(dx/2.0)) 
    else: 
     return dx + dy - int(math.floor(dx/2.0)) 

これはヘキサ>正方形の表現を使用しています。私はあなたの答えに多くの時間を費やしますが、どちらにも問題があることがわかりました。あるいは少なくともそれらの答えに考慮されているグリッドのタイプは明確には述べられていない。しかし、私は、この問題のチュートリアルとコードの実装が非常に優れていることと、16進グリッドを管理するためのライブラリがhttp://www.redblobgames.com/grids/hexagons/(ライブラリコード:http://www.redblobgames.com/grids/hexagons/implementation.html)であることを発見しました。私はまた、次のように「奇数-Q」の垂直レイアウトの距離コードのMatlabのバージョンを実装します。ここでは

function f = offset_distance(x1,y1,x2,y2) 
    ac = offset_to_cube(x1,y1); 
    bc = offset_to_cube(x2,y2); 
    f = cube_distance(ac, bc); 
end 

function f = offset_to_cube(row,col) 
    %x = col - (row - (row&1))/2; 
    x = col - (row - mod(row,2))/2; 
    z = row; 
    y = -x-z; 
    f = [x,z,y]; 
end 

function f= cube_distance(p1,p2) 
    a = abs(p1(1,1) - p2(1,1)); 
    b = abs(p1(1,2) - p2(1,2)); 
    c = abs(p1(1,3) - p2(1,3)); 
    f = max([a,b,c]); 
end 

は、MathWorks社のMATLABテストコードが

ある
sx = 6; 
sy = 1; 
for i = 0:7 
    for j = 0:5 
     k = offset_distance(sx,sy,i,j); 
     disp(['(',num2str(sx),',',num2str(sy),')->(',num2str(i),',',num2str(j),')=',num2str(k)]) 
    end 
end 
0

は(O(N)であるべきである)次善の、あまりにも準最適ではないアルゴリズムでありますhttp://alienryderflex.com/intersect/のようなものを作成します)

次に、ポイントがある六角形グリッド上のどの六角形を決定する関数を作成します。

ここでアルゴリズムを次のように記述します。

それならば
  • 線分は、線分の開始は、周囲の六角形について
  • である六角で、これまで
  • スタートをオーバーラップしているすべての六角形のリストを保持し、最近、1オーバーラップがリストにない場合は、linセグメントがその六角形と交差するかどうかを確認してください。もしそうなら、私たちはテストするために六角形が不足すると、私たちは、私はあなたがいる線分のケースをテストすることをお勧めし

をしたリストを返し、リストの新しいヘッド、これを作成し、
  • を繰り返しちょうど平行で、六角形間の縫い目に沿って走って、片側、両側、またはどちらにも六角形があるかどうかを確認します(したがって停止します)。

  • 2

    2ヘクス間の最短パスを見つけるには:異なる行に、他の列に向かって対角に追従しながら1ヘクス、

  • 最低

    1. を。
    2. 同じ列にある間、もう一方のヘクスに向かってまっすぐ進む。

    x方向の差異をdxとし、y方向の差異をdyとしましょう。 dy/2 > dxの場合は、手順2を実行する必要はないため、距離は単にdyです。それ以外の場合、距離はdy + (dx - dy/2)です。私が間違っていない限り。

  • +0

    ありがとうございました100%ではなく、かなり近づいています。 – DeathorGlory9

    0

    グリッド上のタイルは、潜在的にあなたがA *(またはスター)に興味がある、その後ブロックさになることができた場合は迷路を解くアルゴリズム: http://labs.makemachine.net/2010/03/a-star-maze-solver/

    このビデオで使用されるメカニズムは、正方形のグリッドに適用されますしかし、余分なコーディングがほとんどなくても、それを六角形のメッシュに適用することができます。 すべてのタイルについて、ソルバーは、タイルがその周囲のタイルへのポインタを格納するため、次に試すタイルを認識します。四角形のグリッドでは、各タイルは最大4つのポインタ(ブロックされていないタイルへのポインタのみを格納するため、)を格納します。

    タイルが常にトラバース可能な場合、A *は確かに作業を完了しますが、より速い方法が考えられます。私があなたの質問を正しく解釈しているならば、離れていなくても、2つのヘクスの間のヘクス数の全数カウントに興味がありますか?以下を試してください:

    class Coord { 
        int x; 
        int y; 
    } 
    
    int dist(Coord hex1, Coord hex2) { 
        int xSteps = Math.abs(hex1.x - hex2.x); 
        int ySteps = Math.abs(hex1.y - hex2.y); 
    
        return Math.max(xSteps, ySteps) + Math.abs(xSteps - ySteps); 
    } 
    

    なぜ尋ねることがありますか?この質問は、またはと水平にに移動する必要がある回数を決定することについてのものです。と対角線ではではありません。私たちは可能な限り斜めに移動したい、そうでなければ我々の距離については賢明ではない。 Math.abs(xSteps - ySteps)は、非対称的な動きの数です。それにxとyの距離のうち大きい方を加えれば完了です。

    +0

    これは座標0,0,3,3を使用したときと同じようには動作していないようですが、返される距離は4ではなく3です。 – DeathorGlory9

    6

    次の2つの方向にヘクスの木目に沿って行くの座標系を使用していた場合、あなたが使用している可能性:

    distance = max(
        abs(dest.y - start.y),  
        abs(dest.x - start.x), 
        abs((dest.x - dest.y)*-1 - (start.x - start.y)*-1) 
    ) 
    

    をあなたはどの波線座標系を使用している、しませんでしたしかし、一方向のみ(水平)に沿って穀物と一緒に行く。幸いにも、我々はそう

    straight.y = squiggle.y 
    straight.x = ciel(squiggle.y/-2) + squiggle.x 
    

    を使用して、2つの間で変換することができ、この連立方程式を用いた距離について解くことはあなたを取得します。

    distance = max(
        abs(dest.y - start.y),  
        abs(ceil(dest.y/-2) + dest.x - ceil(start.y/-2) - start.x), 
        abs(-dest.y - ceil(dest.y/-2) - dest.x + start.y + ceil(start.y/-2) + start.x) 
    ) 
    

    のみそれらの座標を使用して、あなたに2ヘクス間のマンハッタン距離を取得すること(グリッドが90度回転しているので、私はxとyを転置しても何のタイプミスもしなかったと仮定します)。しかし、私の中学校代数教師のためにクッキーを購入しなければなりません。さもなければ、私は分配財産を混乱させるでしょう。

    注:負の座標で作業するには手を加える必要があるかもしれませんが、私はチェックしませんでした。

    2

    The accepted answerが間違っています。最初は非直交軸で直交座標を使用すると言いましたが、私自身の解決法に対してコードを実行すると距離化合物の過大評価が示されました。

    実際の正しい解決策は次のとおりです。

     
         ------   
    ------ 0, +1 ------ 
    -1, +1 ------ +1, +1 
    ------ 0, 0 ------ 
    -1, 0 ------ +1, 0 
    ------ 0, -1 ------ 
         ------   
    
    -------------------------- 
    | -1, +1 | 0, +1 | +1, +1 | 
    |-------------------------- 
    | -1, 0 | 0, 0 | +1, 0 | 
    |--------------------------| 
    |  | 0, -1 |  | 
    -------------------------- 
    
    +0

    はこれが奇数rの正しい解決法ですか? – Artistan

    2

    MH RASELは彼の前に、この記事をリンク答え:Hexagonal Grids。この優れた投稿に続いて、私はキューブ座標が必要であることを理解しました。距離を計算する最も簡単な方法を提供します。ここでKotlinのコードスニペットです:

    data class Point(val x: Int, val y: Int, val z: Int) { 
    
        fun distance(b: Point): Int { 
         return (abs(x - b.x) + abs(y - b.y) + abs(z - b.z))/2 
        } 
    
    } 
    
    var x = 0 
    var y = 0 
    var z = 0 
    
    val p1 = Point(x, y, z) // starting position 
    
    val steps = "ne,ne,ne".split(",") // go to North-East 3 times 
    
    for (direction in steps) { 
        when(direction) { 
         "n" -> { ++y; --z } 
         "ne" -> { ++x; --z } 
         "se" -> { ++x; --y } 
         "s" -> { --y; ++z } 
         "sw" -> { --x; ++z } 
         "nw" -> { ++y; --x } 
        } 
    } 
    
    val p2 = Point(x, y, z) // we arrived here 
    val dist = p1.distance(p2) // the result is here (in this example: 3) 
    

    編集:私はフラット突破六角グリッドを想定しています。

    0

    Advent of Code 2017 problem 11のようなN、NE、SE、S、SW、NWのような方向の六角形タイルの場合、(0,0)になるように目標をオフセットします。私の仕事:

    def distance(self): 
        # Take diagonal steps towards self.x == 0 
        steps = abs(self.x) 
        # y moves closer to 0 by steps because moving diagonal, but never moving too far 
        if self.y > 0: 
         # Might still be positive, but never negative 
         y = max(self.y - steps, 0) 
        else: 
         # Might still be negative, but not positive 
         y = min(self.y + steps, 0) 
        # You move 2 positions north/south by a single move so divide y's by 2 
        return abs(y) // 2 + abs(steps) 
    

    は、私はそれだけで、xとyの役割を切り替えることによって、あなたのような代わりに、北と南の方向EASTとWESTでの六角グリッドのために働くかもしれないと思います。その場合、あなたはself.y == 0に向かって斜めに(必要であれば)移動するでしょう。