خوارزمية لإنشاء خلايا بواسطة حلزوني على الحقل السداسي

StackOverflow https://stackoverflow.com/questions/2142431

  •  22-09-2019
  •  | 
  •  

سؤال

ساعد في العثور على خوارزمية لإنشاء خلايا بواسطة حلزوني على الحقل السداسي.

انظر إلى الصورة:

alt text

دعونا نتخيل صفيف ثنائي الأبعاد بدون أبعاد. المحور X هو الخط الأزرق ، y أفقي ، دوامة أحمر.

أحتاج إلى إضافة خلايا من النقطة المركزية x0y0 إلى النقطة n بواسطة حلزوني

قل لي الطريق لحل المشكلة من فضلك. شكرًا لك!

هل كانت مفيدة؟

المحلول

أود أن أقترح تغيير الخلايا التي ترقيم بصراحة ، بحيث تظل X كما هي عندما تنزل ويمينًا (أو أعلى ويسارًا). ثم يجب أن تعمل خوارزمية بسيطة مثل ما يلي:

  int x=0, y=0;   
  add(x, y); // add the first cell
  int N=1 
  for( int N=1; <some condition>; ++N ) {
    for(int i=0; i<N; ++i) add(++x, y);  // move right
    for(int i=0; i<N-1; ++i) add(x, ++y); // move down right. Note N-1
    for(int i=0; i<N; ++i) add(--x, ++y); // move down left
    for(int i=0; i<N; ++i) add(--x, y); // move left
    for(int i=0; i<N; ++i) add(x, --y); // move up left
    for(int i=0; i<N; ++i) add(++x, --y); // move up right
  }

هذا يولد النقاط على النحو التالي:

Plot of generated points

بعد تحول نحصل عليه:

Transformation of the generated points into a hex grid

نصائح أخرى

enter image description here(يبلغ قطر الدوائر 1)

إليك وظيفة للحصول على الموقف i:

  void getHexPosition( int i, ref double x, ref double y )
  {
     if ( i == 0 ) { x = y = 0; return; }

     int layer = (int) Math.Round( Math.Sqrt( i/3.0 ) );

     int firstIdxInLayer = 3*layer*(layer-1) + 1;
     int side = (i - firstIdxInLayer) / layer; // note: this is integer division
     int idx  = (i - firstIdxInLayer) % layer;                  
     x =  layer * Math.Cos( (side - 1) * Math.PI/3 ) + (idx + 1) * Math.Cos( (side + 1) * Math.PI/3 );
     y = -layer * Math.Sin( (side - 1) * Math.PI/3 ) - (idx + 1) * Math.Sin( (side + 1) * Math.PI/3 );
  }

تحجيم النتيجة Math.Sqrt(.75) يعطي

enter image description here

إذا كنت مهتمًا بالإحداثيات المنحرفة مثل إجابة Shura:

  int[] h = { 1, 1, 0, -1, -1, 0, 1, 1, 0 };
  void getHexSkewedPosition( int i, ref int hx, ref int hy )
  {
     if ( i == 0 ) { hx = hy = 0; return; }

     int layer = (int) Math.Round( Math.Sqrt( i/3.0 ) );

     int firstIdxInLayer = 3*layer*(layer-1) + 1;
     int side = (i - firstIdxInLayer) / layer;
     int idx  = (i - firstIdxInLayer) % layer;

     hx = layer*h[side+0] + (idx+1) * h[side+2];
     hy = layer*h[side+1] + (idx+1) * h[side+3];
  }

  void getHexPosition( int i, ref double hx, ref double hy )
  {
     int x = 0, y = 0;
     getHexSkewedPosition( i, ref x, ref y );
     hx = x - y * .5;
     hy = y * Math.Sqrt( .75 );
  }

تخيل أن لديك شبكة طبيعية مع مربعات بدلاً من سداسيس ، قم بإنشاء دوامة باستخدام تلك الشبكة ، ثم ارسمها عن طريق التحول ، كل ما يلي غريبة إلى اليسار بواسطة M بكسل ، والتي ستمنحك هذا التأثير.

يمكنك اختيار Hexes واحدة في كل مرة باستخدام وظيفة نقاط مناسبة لتحديد أفضل من الستة الستة التي لم يتم اختيارها حتى الآن إلى السداسي المختارة في الجولة السابقة. أعتقد أن وظيفة النتيجة التي تعمل هي اختيار الأقرب إلى (0،0) (القوى التي تختار Hexes في "قذيفة واحدة" في وقت واحد) ، وكسر العلاقات عن طريق اختيار الأقرب إلى (1،0) (يجبر اتجاهًا ثابتًا ثابتًا في القشرة الجديدة). يمكن حساب المسافة في شبكة سداسية عشرية باستخدام الوظيفة التالية:

double grid_distance(int dx, int dy) {
  double real_dx = dx + y/2.0;
  double real_dy = dy * sqrt(3)/2.0;
  return sqrt(real_dx * real_dx + real_dy * real_dy);
}

يمكنك القيام بذلك عن طريق محاكاة الاتجاهات. إذا كانت اتجاهاتك "0 نقاط" ، فعليك الزيادة بمقدار 1 أثناء ذهابك على مدار الساعة ، فيجب أن تفعل ما يلي:

Pick a centre cell.
Pick the second cell (ideally in direction 0).
Set direction to 2.

While you have more cells to mark:
  if the cell in (direction+1)%6 is free:
    set direction = (direction+1)%6
  mark current cell as used
  go to cell in direction

أحببت طريقة Shura في الاقتراب من المشكلة ، لكنني لم أستطع الحصول على هذه الخوارزمية الدقيقة للعمل. أيضًا ، أنا أستخدم تباعد سداسي 2 × 1 (حيث يتم تباعد الخلايا X 2 ، ويتم إخفاء كل عنصر X آخر).

إليك ما حصلت عليه (على الرغم من في JavaScript):

    //Hexagon spiral algorithm, modified from 
    for(var n=1; n<=rings; ++n) {
        x+=2; add(x, y);
        for(var i=0; i<n-1; ++i) add(++x,++y); // move down right. Note N-1
        for(var i=0; i<n; ++i) add(--x,++y); // move down left
        for(var i=0; i<n; ++i) { x-=2; add(x, y); } // move left
        for(var i=0; i<n; ++i) add(--x,--y); // move up left
        for(var i=0; i<n; ++i) add(++x, --y); // move up right
        for(var i=0; i<n; ++i) { x+=2; add(x, y); }  // move right
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top