@scudly Thank you for your comments, code and valuable resources; I did not realize how much work had already been done on this subject.

The following demo is a revision of my code for the ‘catan’ hexGrid to make it more scalable. The main difference is that the number of columns in each row is now stored in an array. The maximum array column size is then obtained with ‘max()’ and row length disparity is calculated for each row in the loop. Each row’s xOffset is then adjusted according to the disparity. Since the spike end of the hexagon is pointing upward and affects row spacing, the same number of columns should not be used in succession in the array. The model is scalable as long as the ‘catan’ format is adhered to, i.e., initial ascending and then descending values flanking a single maximum length row. Other polygon shapes may be used as well; a ‘catan’ shaped grid with triangles as well as a scaled up hexagon grid is shown following the code:

```
int[] colNum = {3, 4, 5, 4, 3}; // avoid repeating same number in succession
//int[] colNum = {5, 6, 7, 8, 9, 8, 7, 6, 5}; // scaled up with same format as above
int colMax = max(colNum);
int lenDisparity = 0;
int counter = 0;
void polygon(float x, float y, float radius, int npoints) {
float angle = TWO_PI / npoints;
beginShape();
for (float a = 0; a < TWO_PI; a += angle) {
float sx = x + sin(a) * radius;
float sy = y - cos(a) * radius;
vertex(sx, sy);
}
endShape(CLOSE);
}
void catanGrid(float x, float y, float radius) {
float centerX;
float centerY;
for (int k = 0; k < colNum.length; k++) {
for (int j = 0; j < colNum[counter]; j++) {
centerX = x + j*(radius + 0.7*radius);
centerY = y + k*(radius + 0.5*radius);
lenDisparity = colMax - colNum[counter];
if ( lenDisparity > 0) {
centerX += lenDisparity*0.86*radius;
}
stroke(0);
fill(random(255), random(255), random(255));
polygon(centerX, centerY, radius, 6); // Hexagon
}
counter++;
}
}
void setup() {
size(620, 560);
// size(1200, 1000);// For scaling up
background(209);
catanGrid(120, 100, 60);
}
```

**Slight Modification for Circles, other shapes:**

A slight modification of the model will allow for the creation of unusual grids with circles, text, or other untested shapes. The ‘catan’ grid shape is not the only shape possible since there is no hexagon spike interference; with this modification an array of any column numbers may be used without regard to format: a complex example is shown below the source code:

```
int[] colNum = {3, 3, 6, 3, 4, 5, 5, 4, 4, 3, 10}; // complex
//int[] colNum = {3, 4, 5, 4, 3}; // catan
int colMax = max(colNum);
int lenDisparity = 0;
int counter = 0;
void circleGrid(int l, int t, float radius, int hgap, int vgap) {
int x;
int y;
for (int k = 0; k < colNum.length; k++) {
for (int j = 0; j < colNum[counter]; j++) {
x = l + j*vgap;
y = t + k*hgap;
lenDisparity = colMax - colNum[counter];
if ( lenDisparity > 0) {
x += lenDisparity*vgap/2;
}
fill(random(255),random(255),random(255));
circle(x,y,radius);
}
counter++;
}
}
void setup() {
size(440, 440);
background(209);
circleGrid(60, 60, 28, 30, 30);
}
```