求助:p5.js绘制六边形单元格组成的大六边形偏移问题
p5.js 大六边形绘制偏移问题修复
问题描述
我尝试在p5.js中创建由六边形单元格组成的大六边形,期望算法支持两个输入:
- 首行六边形单元格数量
- 需绘制的六边形单元格总数
编写代码后,绘制效果不符合预期,图形下半部分的六边形出现偏移。
原代码
// declare fixed variables let diam = 30; let total_hex = 30; let diagonal = 7; let first_row = 4; let side = first_row; // declare dependent variables let radius = diam / 2; let upper_half = side - 1; let rows = upper_half + side; function setup() { createCanvas(700, 700); } // draw function draw() { background("#ffae5"); noFill(); strokeWeight(2); stroke("#ffb703"); // start counters // row_counter = rows; counter = 0; row_cells = first_row; push(); translate(200, 200); for (let j = 0; j < rows; j++) { for (let i = 0; i < row_cells; i++) { push(); translate(-j * (radius + radius / 2 + radius / 4), 0); if (diagonal > i) { console.log(diagonal, i); push(); translate(i * 2 * diam - (i * radius) / 2, 3 * j * (diam / 2)); polygon(0, 0, diam, 6); pop(); } pop(); } if (rows < j) { row_cells -= 1; } if (rows > j) { row_cells += 1; } } pop(); } function polygon(x, y, radius, npoints) { let angle = TWO_PI / npoints; beginShape(); for (let a = 0; a < TWO_PI; a += angle) { let sx = x + sin(a) * radius; let sy = y + cos(a) * radius; vertex(sx, sy); } endShape(CLOSE); }
问题根源与修复方案
主要错误点
- 行单元格数量逻辑完全颠倒:原代码中
rows < j和rows > j的判断完全错误,大六边形的行单元格数量应该是前半部分递增,后半部分递减,而非相反。 - 水平偏移计算错误:原代码的行偏移公式
-j * (radius + radius / 2 + radius / 4)无合理依据,无法保证大六边形整体居中,导致下半部分偏移。 - 单个六边形位置计算错误:水平位置公式
i * 2 * diam - (i * radius) / 2不符合六边形网格的间距规则,垂直位置的近似值也会导致排列错位。 - 无用的
diagonal限制:这个变量没有实际作用,反而会阻止部分单元格绘制。
修正后的代码
// declare fixed variables let diam = 30; let total_hex = 30; let first_row = 4; let side = first_row; // declare dependent variables let radius = diam / 2; let upper_half = side - 1; let rows = upper_half + side; function setup() { createCanvas(700, 700); } function draw() { background("#ffae5"); noFill(); strokeWeight(2); stroke("#ffb703"); let row_cells = first_row; push(); translate(200, 200); for (let j = 0; j < rows; j++) { // 计算当前行的水平偏移,保证大六边形居中 let horizontalOffset = (upper_half - j) * radius * 1.5; push(); translate(horizontalOffset, 0); for (let i = 0; i < row_cells; i++) { // 六边形水平间距为1.5倍半径,保证紧密排列 let x = i * radius * 1.5; // 六边形垂直间距为√3倍半径,标准六边形网格行间距 let y = j * radius * sqrt(3); polygon(x, y, radius, 6); } pop(); // 更新每行单元格数量:前半行递增,后半行递减 if (j < upper_half) { row_cells += 1; } else { row_cells -= 1; } } pop(); } function polygon(x, y, radius, npoints) { let angle = TWO_PI / npoints; beginShape(); for (let a = 0; a < TWO_PI; a += angle) { let sx = x + sin(a) * radius; let sy = y + cos(a) * radius; vertex(sx, sy); } endShape(CLOSE); }
修正说明
- 行单元格数量更新:当
j < upper_half(前半部分行)时,单元格数量递增;进入后半部分后开始递减,符合大六边形的结构。 - 水平偏移修正:通过
(upper_half - j) * radius * 1.5计算每行的水平偏移,确保大六边形整体居中,解决下半部分偏移问题。 - 单元格位置修正:使用六边形网格的标准间距(水平1.5倍半径,垂直√3倍半径),保证单元格紧密对齐,无错位。
- 移除无用变量:删除了
diagonal变量及其判断,确保所有应绘制的单元格都能显示。
内容的提问来源于stack exchange,提问作者Guillermina
相关产品推荐
相关产品推荐

