Drawing hexagon grid radially from center

Is there a single formula I can use for dist that will bring these red hexagons to the right place?

dist = unitDiameter * 0.75 works for ringNum[2], then the more distant rings start getting too close.

PVector figureCenter;
float unitRadius, unitDiameter, unitInradius, unitIndiameter, hexAngle;
void setup() {
   size(400, 600);
   //pixelDensity(2);
   ellipseMode(RADIUS);
   figureCenter = new PVector(width/2, height/2);
   
   // radius/diameter of hexagon, center to vertex
   unitRadius = 20; 
   unitDiameter = unitRadius * 2;
   
   // radius/diameter of inscribed circle, center to side tangent
   unitInradius = (sqrt(3)/2) * unitRadius; 
   unitIndiameter = unitInradius * 2;
   
   hexAngle = TWO_PI/6;
}

void draw() {
   background(127);
   noFill();

   // draw all the rings
   for (int ringNum = 0; ringNum <= 4; ringNum++) {
      
      // draw a ring
      for (int unitNum = 0; unitNum < ringNum * 6; unitNum++) {
         
         float dist = unitIndiameter;
         
         stroke(0);
         
         if (unitNum % ringNum != 0) {
            stroke(200, 0, 0);
            dist = unitDiameter * 0.75;
         }
         
         drawHexUnit(ringNum, unitNum, dist);
      }
   }
}
void drawHexUnit(int ringNumber, int unitNumber, float distance) {

   int unitsInRing = (ringNumber > 0) ? 6 * ringNumber : 1;

   float a = unitNumber * (TWO_PI/unitsInRing);
   PVector loc = new PVector(cos(a), sin(a));
   loc.mult(ringNumber * distance);
   loc.add(figureCenter);

   hexCR(loc, unitRadius);
   stroke(0, 50);
   cirCR(loc, unitRadius);
   cirCR(loc, unitInradius);
}
void hexCR(PVector c, float r) {
   PVector[] p = new PVector[6];
   
   for (int i = 0; i < p.length; i++) {
      float angle = i * hexAngle - HALF_PI;
      p[i] = new PVector(cos(angle), sin(angle));
      p[i].mult(r);
      p[i].add(c);
   }
   
   for (int i = 0; i < p.length; i++) {
      int a = i;
      int b = (i + 1) % p.length;
      lineAB(p[a], p[b]);
   }
}
void lineAB(PVector a, PVector b) {
   line(a.x, a.y, b.x, b.y);
}
void cirCR(PVector c, float r) {
   ellipse(c.x, c.y, r, r);
}
1 Like

You will find links here

1 Like

I cannot even remember why I wanted to do this, but it works now.

PVector figureCenter;
float figureRadius, unitDiameter, unitRadius;
int maxRingN;
Ring[] rings;

void setup() {
   size(400, 600);
   ellipseMode(RADIUS);

   figureCenter = new PVector(width/2, height/2);
   figureRadius = (width-50)/2;

   maxRingN = 5;

   rings = new Ring[maxRingN];
   
   for (int i = 0; i < rings.length; i++) {
      rings[i] = new Ring(i);
   }

   unitDiameter = figureRadius / (0.5 + maxRingN - 1);
   unitRadius = unitDiameter / sqrt(3);
}

class Ring {
   int ringNUnits;
   PVector[] units;
   
   Ring(int ringNum) {
      ringNUnits = (ringNum > 0) ? 6 * ringNum : 1;
      units = new PVector[ringNUnits];
      for (int i = 0; i < units.length; i++) {
         units[i] = new PVector();
      }
   }
}

void draw() {
   background(127);
   noFill();

   strokeWeight(10);
   stroke(50);
   cirCR(figureCenter, figureRadius);

   for (int ringNum = 0; ringNum < maxRingN; ringNum++) {
      int numUnits = rings[ringNum].units.length;
      for (int unit = 0; unit < numUnits; unit++) {

         boolean thisUnitIsVertex = (ringNum > 0) ? unit % ringNum == 0 : false;

         float unitAngle = unit * (TWO_PI / numUnits);

         int nextVertex = (ringNum + unit) % numUnits;
         float nextVertexAngle = nextVertex * (TWO_PI / numUnits);

         float ringVertexRadius = ringNum * unitDiameter;

         if (ringNum <= 1) {
            rings[ringNum].units[unit] = new PVector(cos(unitAngle), sin(unitAngle));
            rings[ringNum].units[unit].mult(ringVertexRadius);
            rings[ringNum].units[unit].add(figureCenter);
         } else {
            if (thisUnitIsVertex) {
               rings[ringNum].units[unit] = new PVector(cos(unitAngle), sin(unitAngle));
               rings[ringNum].units[unit].mult(ringVertexRadius);
               rings[ringNum].units[unit].add(figureCenter);

               rings[ringNum].units[nextVertex] = new PVector(cos(nextVertexAngle), sin(nextVertexAngle));
               rings[ringNum].units[nextVertex].mult(ringVertexRadius);
               rings[ringNum].units[nextVertex].add(figureCenter);

               PVector a = rings[ringNum].units[unit];
               PVector b = rings[ringNum].units[nextVertex];

               int numberOfSubunits = (nextVertex != 0) ? nextVertex - unit : numUnits - unit;

               for (int i = 1; i < numberOfSubunits; i++) {
                  rings[ringNum].units[unit + i].set(PVector.lerp(a, b, i * 1.0 / ringNum));
               }
            }
         }
      }
   }
   drawUnits();
}

void drawUnits() {
   for (int ringNum = 0; ringNum < maxRingN; ringNum++) {
      for (int unit = 0; unit < rings[ringNum].units.length; unit++) {
         boolean thisUnitIsVertex = (ringNum > 0) ? unit % ringNum == 0 : false;
         color unitColor = ringNum == 0 || thisUnitIsVertex ? color(225, 225, 127) : color(225, 127, 127);
         strokeWeight(2);
         stroke(unitColor);

         //cirCR(rings[ringNum].units[unit], unitRadius);

         textAlign(CENTER, CENTER);
         textPt(nf(ringNum, 1) + "," + nf(unit, 1), rings[ringNum].units[unit]);

         hexCR(rings[ringNum].units[unit], unitRadius);

      }
   }
}

void hexCR(PVector c, float r) {
   PVector[] p = new PVector[6];
   
   for (int i = 0; i < p.length; i++) {
      float angle = i * (TWO_PI / 6) - HALF_PI;
      p[i] = new PVector(cos(angle), sin(angle));
      p[i].mult(r);
      p[i].add(c);
   }
   
   for (int i = 0; i < p.length; i++) {
      int a = i;
      int b = (i + 1) % p.length;
      lineAB(p[a], p[b]);
   }
}

void textPt(String str, PVector a) {
   text(str, a.x, a.y);
}

void cirCR(PVector c, float r) {
   ellipse(c.x, c.y, r, r);
}

void lineAB(PVector a, PVector b) {
   line(a.x, a.y, b.x, b.y);
}
2 Likes