算法生成二维魔术六边形格子

时间:2013-01-11 15:05:16

标签: c++ c

我正在尝试生成一个二维神奇的六角形格子,(即我需要用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坐标和col i y坐标,只看到generate_particles部分忘了其余部分它类似于你之前给我的那个但是我写了它使用我自己的语言和其他变量,当我输出这个文件时,屏幕上绘制的坐标正是我想要启动初始配置的坐标,但我们在这里做的是在配置二进制文件中写这些坐标问题是当我我正在阅读这个二进制文件,似乎打印的唯一坐标是从0到n-1 n是图层顺序,有一个问题,我无法解决,也许是因为我编写代码的方式,因为我有547粒子,但这段代码只给我13个坐标我应该给每个粒子一个标签,即547粒子应该各有自己的坐标这个是否明确?

4 个答案:

答案 0 :(得分:9)

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
        }
    }

}

架构说明:

enter image description here

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

提供

enter image description here

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

答案 1 :(得分:2)

数学上,分数是

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

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

修改

这是打印n th 层的(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;
    }

答案 2 :(得分:1)

极坐标形式的坐标是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)

答案 3 :(得分:1)

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

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

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

  • 绘制第一个六边形(参见例如Aki Suihkonen的答案)。
  • 将所有顶点放在一个封闭的列表中。
  • 对于所有连续顶点的夫妇(当你在最后一点时,“下一个”是第一个),通过减去(或添加,取决于你是否将你的六边形向日葵或widdershins)减去120度来建立一个等边三角形由前两点做出的基线。
  • 你获得的边数与边数(顶点数)相同。
  • 这些点是新一代六边形的中心。您仍然有旧的边列表,以避免重绘已存在的边。绘制这些六边形并存储它们的顶点(在连接的边上注意重复)。
  • 新的顶点列表取代了第一个顶点。
  • 洗涤,冲洗,重复。

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

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