1

I need to have hexagonal grid on a spherical surface. like shown here.

enter image description here

Right now I am doing a hexagonal flattened grid. enter image description here and the projecting it onto the surface of a hemisphere. Like here, But as you can see, the funny artifact is hexagons on the edge are disproportionately large. There should be a better way to do this so that all the hexagons are near equal in their size.

enter image description here

I had tried the solution like @spektre had suggested but my code was producing following plot.

enter image description here i was using the a=sqrt(x*x+y*y)/r * (pi/2) because i wanted to scale a that goes from [0,r] to z [0,r] so angle a has bounds of [0,pi/2].

But with just a=sqrt(x*x+y*y)/r it works well. enter image description here

New Development with the task, New problem enter image description here

I have the problem that now, the hexagons are not equal through out the shapes. I want a uniform shape (area wise) for them across the dome and cylinder. I am confused on how to manage this?

jkhadka
  • 2,443
  • 8
  • 34
  • 56

1 Answers1

2

Here is what I have in mind:

  1. create planar hex grid on XY plane

    center of your grid must be the center of your sphere I chose (0,0,0) and size of the grid should be at least the 2*radius of your sphere big.

  2. convert planar coordinates to spherical

    so distance from (0,0,0) to point coordinate in XY plane is arclength traveling on surface of your sphere so if processed point is (x,y,z) and sphere radius is r then latitude position on sphere is:

    a=sqrt(x*x+y*y)/r;
    

    so we can directly compute z coordinate:

    z=r*cos(a);
    

    and scale x,y to surface of sphere:

    a=r*sin(a)/sqrt(x*x+y*y);
    x*=a; y*=a;
    

    If the z coordinate is negative then you have crossed half sphere and should handle differently (skip hex or convert to cylinder or whatever)

Here Small OpenGL/C++ example for this:

//---------------------------------------------------------------------------
const int _gx=15;           // hex grid size
const int _gy=15;
const int _hy=(_gy+1)<<1;   // hex points size
const int _hx=(_gx+1);
double hex[_hy][_hx][3];    // hex grid points
//---------------------------------------------------------------------------
void hexgrid_init(double r) // set hex[][][] to planar hex grid points at xy plane
    {
    double x0,y0,x,y,z,dx,dy,dz;
    double sx,sy,sz;
    int i,j;
    // hex sizes
    sz=sqrt(8.0)*r/double(_hy);
    sx=sz*cos(60.0*deg);
    sy=sz*sin(60.0*deg);

    // center points arrounf (0,0)
    x0=(0.5*sz)-double(_hy/4)*(sz+sx);
    y0=-double(_hx)*(sy);
    if (int(_gx&1)==0) x0-=sz+sx;
    if (int(_gy&1)==0) y0-=sy; else y0+=sy;

    for (y=y0,i=0;i<_hy;i+=2,y+=sy+sy)
     for (x=x0,j=0;j<_hx;j++,x+=sz)
        {
        hex[i][j][0]=x;
        hex[i][j][1]=y;
        hex[i][j][2]=0.0;
        x+=sz+sx+sx; j++; if (j>=_hx) break;
        hex[i][j][0]=x;
        hex[i][j][1]=y;
        hex[i][j][2]=0.0;
        }

    for (y=y0+sy,i=1;i<_hy;i+=2,y+=sy+sy)
     for (x=x0+sx,j=0;j<_hx;j++,x+=sx+sx+sz)
        {
        hex[i][j][0]=x;
        hex[i][j][1]=y;
        hex[i][j][2]=0.0;
        x+=sz; j++; if (j>=_hx) break;
        hex[i][j][0]=x;
        hex[i][j][1]=y;
        hex[i][j][2]=0.0;
        }

    }
//---------------------------------------------------------------------------
void hexgrid_half_sphere(double r0) // convert planar hex grid to half sphere at (0,0,0) with radius r0
    {
    int i,j;
    double x,y,z,a,l;
    for (i=0;i<_hy;i++)
     for (j=0;j<_hx;j++)
        {
        x=hex[i][j][0];
        y=hex[i][j][1];
        z=hex[i][j][2];
        l=sqrt(x*x+y*y);    // distance from center on xy plane (arclength)
        a=l/r0;             // convert arclength to angle
        z=r0*cos(a);        // compute z coordinate (sphere)
        if (z>=0.0)         // half sphere
            {
            a=r0*sin(a)/l;
            }
        else{               // turn hexes above half sphere to cylinder
            z=0.5*pi*r0-l;
            a=r0/l;
            }
        x*=a;
        y*=a;
        hex[i][j][0]=x;
        hex[i][j][1]=y;
        hex[i][j][2]=z;
        }
    }
//---------------------------------------------------------------------------
void hex_draw(int x,int y,GLuint style)     // draw hex x = <0,_gx) , y = <0,_gy)
    {
    y<<=1;
    if ((x&1)==0) y++;
    if ((x<0)||(x+1>=_hx)) return;
    if ((y<0)||(y+2>=_hy)) return;
    glBegin(style);
    glVertex3dv(hex[y+1][x  ]);
    glVertex3dv(hex[y  ][x  ]);
    glVertex3dv(hex[y  ][x+1]);
    glVertex3dv(hex[y+1][x+1]);
    glVertex3dv(hex[y+2][x+1]);
    glVertex3dv(hex[y+2][x  ]);
    glEnd();
    }
//---------------------------------------------------------------------------

And usage:

hexgrid_init(1.5);
hexgrid_half_sphere(1.0);

int x,y;
glColor3f(0.0,0.2,0.3);
for (y=0;y<_gy;y++)
 for (x=0;x<_gx;x++)
  hex_draw(x,y,GL_POLYGON);
glLineWidth(2);
glColor3f(1.0,1.0,1.0);
for (y=0;y<_gy;y++)
 for (x=0;x<_gx;x++)
  hex_draw(x,y,GL_LINE_LOOP);
glLineWidth(1);

And preview:

preview

For more info and ideas see related:

Community
  • 1
  • 1
Spektre
  • 49,595
  • 11
  • 110
  • 380
  • 1
    hey, thanks this solution helped. I had thought of similar way but actually did a small mistake. i defined `a=sqrt(x*x+y*y)/r * (pi/2)` I want the flat hexagonal coordinates to scale from `z = r` to `z=0`. But it gave me weird result. I have attached the two results to the above question again. Thanks for the help. i need to tweak a bit but showed me my problem :) – jkhadka Feb 09 '17 at 09:38
  • hey @Spektre cannot thank you enough for code sample. once again helped me alot :) – jkhadka Apr 23 '17 at 19:50
  • @hadik glad to be of help – Spektre Apr 24 '17 at 06:07
  • @Spektra Hey, I hope I am not being handful with my question, but I have another question with this, as I have added the new picture. The hexagons are not same shaped through out the figure. You can see that in dome they are uniform but going down the flanks they get smaller and smaller, it is also becuase there are increasingly more hexagons added to the flanks when turning flat hexagon tiling to this shape. Do you think this can be avoided to have uniform hexagons (same area) through out the figure? – jkhadka Apr 24 '17 at 07:56
  • @hadik not with current approach ... as the lower you got you are at bigger radius at the 2D hex grid meaning you got more and more hexagons per the same cylinder slice in 3D. To avoid this you have to use current approach for the first half of sphere and for the rest just add the hexagons differently (using 3D cylinder hexagon as base instead of projecting 2D hexagon circle onto sphere) – Spektre Apr 24 '17 at 15:02