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

六边形网格同类型相邻六边形合并实现及代码优化咨询

六边形网格合并相邻同类型单元格解决方案及代码点评

一、相邻同类型六边形合并实现方案

针对odd-r水平布局的六边形网格,最简洁的合并视觉效果实现方式是隐藏同类型相邻六边形的公共边,这样看起来就像多个六边形合并成了一个连续区域。以下是具体实现步骤和代码修改:

1. 新增邻接单元格与边判断工具函数

// 获取odd-r布局下,指定六边形的邻接单元格坐标
function getHexNeighbors(row, col, grid) {
  const neighbors = [];
  if (row % 2 === 0) {
    // 偶数行邻接规则
    neighbors.push([row-1, col], [row-1, col+1]);
    neighbors.push([row, col-1], [row, col+1]);
    neighbors.push([row+1, col], [row+1, col+1]);
  } else {
    // 奇数行邻接规则
    neighbors.push([row-1, col-1], [row-1, col]);
    neighbors.push([row, col-1], [row, col+1]);
    neighbors.push([row+1, col-1], [row+1, col]);
  }
  // 过滤超出网格范围的无效邻接单元格
  return neighbors.filter(([r, c]) => 
    r >= 0 && r < grid.length && c >= 0 && c < grid[r].length
  );
}

// 判断当前六边形的某条边是否需要绘制(邻接单元格不存在/类型不同则绘制)
function shouldDrawEdge(hexRow, hexCol, hexType, edgeIndex, grid) {
  // 对应hexPoints的6条边,每条边关联的邻接单元格坐标
  const edgeToNeighbor = [
    hexRow % 2 === 0 ? [hexRow+1, hexCol+1] : [hexRow+1, hexCol], // 边0-1(右上→右下)
    [hexRow, hexCol+1], // 边1-2(右下→中下)
    hexRow % 2 === 0 ? [hexRow+1, hexCol] : [hexRow+1, hexCol-1], // 边2-3(中下→左下)
    [hexRow, hexCol-1], // 边3-4(左下→左上)
    hexRow % 2 === 0 ? [hexRow-1, hexCol] : [hexRow-1, hexCol-1], // 边4-5(左上→中上)
    hexRow % 2 === 0 ? [hexRow-1, hexCol+1] : [hexRow-1, hexCol]  // 边5-0(中上→右上)
  ];
  const [neighborRow, neighborCol] = edgeToNeighbor[edgeIndex];
  
  // 边界单元格的边需要绘制
  if (neighborRow < 0 || neighborRow >= grid.length || 
      neighborCol < 0 || neighborCol >= grid[neighborRow].length) {
    return true;
  }
  // 邻接单元格类型不同,需要绘制边
  return grid[neighborRow][neighborCol] !== hexType;
}

2. 修改drawGrid函数的绘制逻辑

替换原有的hexList.forEach循环,改为只绘制需要显示的边:

drawGrid() {
  lineCtx.clearRect(0, 0, canvas.width, canvas.height);
  const size = mapContainer.zoom * 100;
  const rect = mapContainer.getViewedHexes();
  const grid = mapContainer.hexGrid;
  // 类型到颜色的映射,可根据需求扩展
  const typeColorMap = {
    0: "rgba(255,0,0,0.4)",
    1: "rgba(0,255,0,0.4)",
    2: "rgba(0,0,255,0.4)"
  };

  // 直接遍历可视区域内的六边形,无需先收集到数组
  for (let row = rect.top; row < rect.bottom; row++) {
    for (let col = rect.left; col < rect.right; col++) {
      const type = grid[row][col];
      const center = hexCenter(size, row, col);
      const points = hexPoints(center, size, size);
      const fillColor = typeColorMap[type] || "rgba(255,0,0,0.4)";

      lineCtx.beginPath();
      lineCtx.moveTo(points[0].x, points[0].y);
      // 遍历每条边,判断是否绘制
      for (let i = 0; i < 6; i++) {
        const nextIdx = (i + 1) % 6;
        if (shouldDrawEdge(row, col, type, i, grid)) {
          lineCtx.lineTo(points[nextIdx].x, points[nextIdx].y);
        } else {
          // 跳过公共边,直接移动到下一个顶点
          lineCtx.moveTo(points[nextIdx].x, points[nextIdx].y);
        }
      }
      lineCtx.fillStyle = fillColor;
      lineCtx.fill();
      lineCtx.strokeStyle = "#333"; // 可选:绘制区域外边框
      lineCtx.stroke();
    }
  }
}

如果需要真正的多边形合并(将连通区域合并为单个多边形对象),可以引入多边形布尔运算库(如polybooljs),但上述边隐藏方案在视觉效果和性能上已经能满足大多数场景需求。


二、现有代码点评

1. 优点

  • 六边形坐标计算逻辑清晰,hexPoints、hexCorner、hexCenter的分工明确,符合单一职责原则
  • 为hexPoints的顶点顺序添加了注释,极大提升了后续维护的可读性
  • 基于可视区域绘制六边形,避免了绘制屏幕外的无效内容,性能基础较好

2. 可优化点

(1)性能与内存优化

  • 原代码中先将所有可视六边形收集到hexList再遍历绘制,可改为直接在嵌套循环中处理绘制,减少内存占用
  • 可缓存size、mapX/Y不变时的六边形顶点计算结果,避免重复执行三角函数和乘法运算

(2)代码结构与复用性

  • 辅助函数可封装到HexUtils对象中,避免污染全局作用域:
    const HexUtils = {
      hexPoints(center, height, width) { ... },
      hexCorner(center, height, width, i) { ... },
      hexCenter(size, row, col) { ... }
    };
    
  • hexCenter中的offset计算可提取为单独函数,方便后续修改布局规则

(3)可读性与简洁性

  • hexCenter中的h = 3/2 * size / 2可简化为h = (3/4)*size,减少冗余计算
  • 可定义常量DEG_TO_RAD = Math.PI / 180,替换hexCorner中的重复计算
  • hexPoints的循环可改为更简洁的写法:
    return Array.from({length:6}, (_,i) => hexCorner(center, height/2, width/2, i));
    

(4)健壮性

  • 可添加对mapContainer.hexGrid[row][col]的存在性判断,避免因网格数据异常导致报错

内容的提问来源于stack exchange,提问作者James Homer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:03:06