You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助: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);
}

问题根源与修复方案

主要错误点

  1. 行单元格数量逻辑完全颠倒:原代码中rows < j和rows > j的判断完全错误,大六边形的行单元格数量应该是前半部分递增,后半部分递减,而非相反。
  2. 水平偏移计算错误:原代码的行偏移公式-j * (radius + radius / 2 + radius / 4)无合理依据,无法保证大六边形整体居中,导致下半部分偏移。
  3. 单个六边形位置计算错误:水平位置公式i * 2 * diam - (i * radius) / 2不符合六边形网格的间距规则,垂直位置的近似值也会导致排列错位。
  4. 无用的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 22:15:40