【问题标题】:algorithm to generate 2D magic hexagon lattice生成二维魔法六边形格子的算法
【发布时间】:2013-01-11 15:05:15
【问题描述】:

我正在尝试生成一个 2D 魔法六边形格子,(即我需要用 C 语言生成点的坐标)参见附图,该图看起来像一个洋葱结构,其中较大的一个内有六边形,依此类推.

有人有想法吗?

注意:如果有人在其他语言中有答案,那没关系,我只需要看看,这样我就可以开始构建自己的代码了。 提前致谢。

      void generate_particles(void)
      {/* Generates the particle - positions and charge
      Here it indicated to use the hexagonal referential !!*/
      int    i,j;
      int    n=3; /*n represent the nth centered hex number given by the formula 3*n(n- )+1*/
      double b;
      b=(1.0/sqrt(sqrt(3)))*sqrt(2.0/par.NA);
      /* b=1.0;*/


      fprintf(stderr,"Distributing %d particles  on the hexagonal lattice'...", par.N);

      for (i=0;i<n-1;i++)
     {
      coo[i][0]= (sqrt(3)*i*b)/2.0;
       for (j=0;j<(2*n-i-1);j++)
       {
        coo [i][1]= (-(2*n-i-2)*b)/2.0 + j*b;

       fprintf(stderr," %lf    %lf\n",coo[i][0],coo[i][1]);

        /*plot the points with coordinate (x,y) here*/
       if(coo[i][0]!=0)
           {     
       fprintf(stderr," %lf    %lf\n",-coo[i][0],coo[i][1]);
              /*plot the points with coordinates (-x,y)*/
         }
        }

        }fprintf(stderr," done\n\n");
       }  



        void write_configuration_file(void)
    {/* Writes the binary configuration file '<prefix>_config.<postfix>'
     i.e velocities and coordinates. */

     FILE *fp;
     char  filename[100];
      char  postfix_string[100];
      int   i;

      fprintf(stderr,"Writing configuration file");

     if (postfix >=0 ) {
    if      (postfix <   10) sprintf(postfix_string,"000%d",postfix);
    else if (postfix <  100) sprintf(postfix_string, "00%d",postfix);
    else if (postfix < 1000) sprintf(postfix_string,  "0%d",postfix);
    else if (postfix <10000) sprintf(postfix_string,   "%d",postfix);
    else                     sprintf(postfix_string,  "_%d",postfix);
    } else {
    fprintf(stderr,"\nThe internal postfix is negative.\n\n");
    exit(1);
    }

    sprintf(filename,"%s_config.%s",prefix,postfix_string); 

    fprintf(stderr," %s...", filename);

    if ((fp = fopen(filename,"r")) != NULL) {
    fprintf(stderr,"\nFile '%s' already exists. Don't want to overwrite it.\n\n",filename);
    fclose(fp);
    exit(1);
    }

     if ((fp = fopen(filename,"w")) == NULL) {
      fprintf(stderr,"Could not create file '%s'.\n\n",filename);
     exit(1);
     }

     /* postfix */
      if (fwrite(&postfix,sizeof(int),1,fp) != 1)
     { fprintf(stderr,"fwrite error 1.\n\n"); exit(1); }

     /* time */
     if (fwrite(&ti,sizeof(int),1,fp) != 1)
     { fprintf(stderr,"fwrite error 2.\n\n"); exit(1); }


     /* x,y coordinates of all particles/charges */

      if (fwrite(coo,sizeof(double) ,2*par.N,fp) != 2*par.N)
       { 
        fprintf(stderr,"fwrite error 4.\n\n"); exit(1); }

        fclose(fp);

        fprintf(stderr," done\n");
        }


and the main program is:

     int main()
    {
    int i;



         printf("\n");
         printf("\n");
          printf("***************************************************************\n");
      printf("* OK LETS GENERATE THE CONFIG FILE FOR MONTE CARLO SIMULATION *\n");
      printf("***************************************************************\n\n");

      read_wishlist();

      init_ran1();

      for (i=0; i<seed; i++) ran1_fast();


      if (par.N > 0) generate_particles();


      write_parameter_file();
      write_configuration_file();
      write_task_file();

      /*final_test();*/

      fprintf(stderr,"\n\nConfiguration successfully generated.\n\n");
    }

好吧,让我解释一下我的问题,事实上,你之前给我的代码是完美的,我能够在 C 和 matlab 中绘制六边形中的粒子,但这只是在绘制;当我开始模拟时,每一个都是问题在我的代码中,粒子有一个从 0 到 par.N 的标签,但我写这个的方式只是读取第 13 层上的 13 个粒子,所以请你帮我找到一个解决方案,了解如何修改它,以便每个粒子有一个坐标提前谢谢。

@MohamedKALLEL 首先在函数 generate_particles 中

coo[i][0] 代表 x 坐标,而 coo i y 坐标,看看 generate_particles 部分忘记其余部分,它与您之前给我的类似,但我用我的自己的语言和其他变量当我执行这个文件时,屏幕上绘制的坐标正是我想要开始初始配置的坐标,但是我们所做的是将这些坐标写入配置二进制文件中,问题是当我阅读这个二进制文件,似乎打印的唯一坐标是从 0 到 n-1 n 是层顺序,有一个问题我无法解决,可能是我编写代码的方式,因为我有 547 个粒子但是这段代码只给了我 13 个坐标我应该给每个粒子一个标签,即 547 个粒子应该有自己的坐标,这很清楚吗??

【问题讨论】:

  • “就像一个洋葱结构,里面有六边形”......这就是我所说的需求规范 :) 抱歉,但我认为这里没有人能够弄清楚你真正想要什么这个描述
  • 这些图形很漂亮,但不是很有帮助。你要计算什么分数?
  • 在给定中心点坐标和(最大)半径的情况下,是否要计算六边形顶点的坐标?
  • 可能会给出中心点。然后算法推导出六边形的坐标
  • 我无法理解您的要求。指南针指令对计算机几乎没有用处。顺便说一句,在几何上不可能将较小的六边形堆叠成较大的六边形,就像正方形和三角形一样。

标签: c++ c


【解决方案1】:
int i, j;
float y,x;
float d=1.0;// d is the distance between 2 points as indicated in your schema
for(i=0; i<=(n-1); i++) {
    y = (sqrt(3)*i*d)/2.0;
    for (j = 0; j < (2*n-1-i); j++) {
        x = (-(2*n-i-2)*d)/2.0 + j*d;
        //plot the point with coordinate (x,y) here
        if (y!=0) {
            // plot the point with coordinate (x,-y) here
        }
    }

}

用架构解释:

如您的维基百科链接http://en.wikipedia.org/wiki/Centered_hexagonal_number 中所示,nth 居中的六边形数由公式给出

  • 因此,对于 n = 1,六边形中的点数为 1。
  • 对于 n = 2,六边形中的点数为 7。
  • 对于 n = 3,六边形中的点数为 19
  • ...

【讨论】:

  • 我认为这可行,我会尽快尝试,但你说的 n 是什么意思?总分??
  • n 是链接中显示的数字:en.wikipedia.org/wiki/Centered_hexagonal_number。因此,对于 n = 1,六边形中的点数为 1。对于 n = 2,六边形中的点数为 7。对于 n = 3,六边形中的点数为 19
  • 如您的维基百科链接中所示en.wikipedia.org/wiki/Centered_hexagonal_number nth 居中的六边形数由公式 3n(n-1)+1 给出
  • @SarahAl-Jawhari:Salam Alaikoum,如果您有更多关于这个问题的问题要问。请更新您的问题而不是我的答案,然后向我发送对我的答案的评论以查看您的更新,我会尽力回答您。否则你可以提出一个新问题,并在你的新问题中参考这个帖子 Salam Alaikoum
  • Salam mohamed 您现在可以看到问题了吗?感谢您的帮助,谢谢
【解决方案2】:

在数学上,点是

(j + 2k, sqrt(3)j) L/2

其中 j 和 k 是整数,L 是两个点之间的距离(图像中的蓝线)。

编辑:

这是打印第 nth 层的 (i,j) 对的代码:

for(int t=0; t<n ; ++t)
    {
      cout << " (" << t << ", " << n-t << ")" << endl;
      cout << " (" << n << ", " << -t << ")" << endl;
      cout << " (" << n-t << ", " << -n << ")" << endl;
      cout << " (" << -t << ", " << -n+t << ")" << endl;
      cout << " (" << -n << ", " << t << ")" << endl;
      cout << " (" << -n+t << ", " << n << ")" << endl;
    }

【讨论】:

    【解决方案3】:

    极坐标形式为 R*exp(i*n*pi/3);其中 n=0..5。

    这映射到 x=R*cos(n); y=R*sin(n); n = 0..5 * pi / 3;

    这会使六边形以原点为中心 (x=0, y=0)。

    下一级六边形的角中心令人惊讶:

    a = n*R*( exp(i*n*pi/3) + exp(i*(n+1)*pi/3);
                ___
               /   \
           ___/  b  \
          /   \     /
      ___/  a  \___/
     /   \     /   \
    /  x  \___/  b1 \
    \     /   \     /
     \___/ a1  \___/
               /   \
              /  b2 \
              \     /
               \___/
    

    从“a”或“b”点开始,必须向下迭代 n-1 步。这些坐标是 center_a + m*R*exp(i*(n+4)/3) + m*R*exp(i*(n+5)/3)

    【讨论】:

    • 是的,你是对的,但是在每个六边形的角之间有一组点,这个公式不适用于,你写的那个只适用于六边形的顶点,但我想要的是内点
    • 那么,您想知道给定点是否在六边形内——您是否要逐个像素地绘制六边形?尝试说明 initial 问题,十六进制格将是一个解决方案。
    【解决方案4】:

    如果你只想要格子,那么坐标就是第一个六边形的坐标,水平行重复并移动。画几十个六边形就很明显了。

    洋葱参考让我觉得你想构建一个六边形,然后在它的所有顶点上构建新的六边形,然后然后在外边界上构建另一代(第三代)六边形第二个。

    你可以通过蛮力来做到这一点。

    • 绘制第一个六边形(参见例如 Aki Suihkonen 的回答)。
    • 将其所有顶点放在一个封闭列表中。
    • 对于所有连续顶点对(当您在最后一个点时,“下一个”是第一个),通过减去(或相加,取决于您是向阳还是向阳方向行走)120 度来构建一个等边三角形前两点形成的基线。
    • 您获得的点数与边(顶点对)的数量一样多。
    • 这些点是新一代六边形的中心。您仍然拥有旧的边列表,以避免重绘已经存在的边。绘制这些六边形并存储它们的顶点(注意连接边上的重复项)。
    • 新的顶点列表取代了第一个。
    • 清洗、漂洗、重复。

    也可能有一个公式 - 尝试寻找“六边形镶嵌”。

    更新:另一种可能性是用相同的方法构建一个 三角形 网格并将它们组合成六边形(请参阅here 以获得漂亮的图形)。一旦你有了组成六边形的六个三角形,就有快速的算法来填充三角形;您可以调整这些以枚举内部点。还有一些快速方法可以检查一个点是否在三角形内。

    【讨论】:

      猜你喜欢
      • 2014-01-11
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-29
      • 2014-08-13
      相关资源
      最近更新 更多