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

使用ImDrawList和AddRectFilled在ImGui绘制网格遇问题,求排查

网格绘制异常的坐标排查方案

1. 确认坐标原点映射逻辑

ImGui窗口绘图坐标原点在左上角,而坯料坐标通常以左下角为原点(CNC场景常见),直接映射会导致网格上下颠倒,需做坐标转换:

// 获取窗口可绘图区域高度(扣除标题栏等占用空间)
float drawAreaHeight = ImGui::GetWindowHeight() - ImGui::GetFrameHeightWithSpacing();
// 将坯料Y坐标转换为窗口绘图坐标
float windowY = drawAreaHeight - (billetY * squareSize);

2. 修正squareSize计算逻辑

你当前按600/150得到4,但忽略了Y方向的比例(600/100=6),必须取最小比例保证坯料完整显示,否则会超出窗口范围:

ImVec2 billetSize = m_GCodeBuilder.GetBilletSize();
ImVec2 drawAreaSize = ImGui::GetContentRegionAvail();
// 计算XY方向缩放比例
float scaleX = drawAreaSize.x / billetSize.x;
float scaleY = drawAreaSize.y / billetSize.y;
// 取较小值作为squareSize,避免网格超出窗口
float squareSize = std::min(scaleX, scaleY);

按此计算,你的场景squareSize应为4,同时Y方向会剩余200像素,可添加居中逻辑让网格显示在窗口中间。

3. 检查网格绘制的循环边界

绘制网格线时,要确保坐标落在窗口可绘图区域内,示例代码如下:

ImVec2 drawAreaMin = ImGui::GetWindowContentRegionMin();
drawAreaMin.x += ImGui::GetWindowPos().x;
drawAreaMin.y += ImGui::GetWindowPos().y;

// 绘制垂直线
for (int x = 0; x <= billetSize.x; ++x) {
    float posX = drawAreaMin.x + x * squareSize;
    ImGui::GetWindowDrawList()->AddLine(
        ImVec2(posX, drawAreaMin.y),
        ImVec2(posX, drawAreaMin.y + billetSize.y * squareSize),
        IM_COL32(100, 100, 100, 255)
    );
}

// 绘制水平线(转换Y坐标原点)
float drawAreaMaxY = drawAreaMin.y + billetSize.y * squareSize;
for (int y = 0; y <= billetSize.y; ++y) {
    float posY = drawAreaMaxY - y * squareSize;
    ImGui::GetWindowDrawList()->AddLine(
        ImVec2(drawAreaMin.x, posY),
        ImVec2(drawAreaMin.x + billetSize.x * squareSize, posY),
        IM_COL32(100, 100, 100, 255)
    );
}

4. 确认可绘图区域的获取方式

必须使用ImGui::GetContentRegionAvail()获取窗口内实际可绘图区域,不要直接用窗口整体尺寸600×600——窗口标题、边框等会占用空间,直接用整体尺寸会导致网格被截断。

5. 调试坐标的实用技巧

可以在代码中添加调试输出,或者绘制标记点验证坐标正确性:

// 打印关键坐标
printf("垂直线X坐标: %.2f, 水平线Y坐标: %.2f\n", posX, posY);

// 绘制坯料四个角标记
ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(drawAreaMin.x, drawAreaMin.y), 3, IM_COL32(255, 0, 0, 255));
ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(drawAreaMin.x + billetSize.x * squareSize, drawAreaMaxY), 3, IM_COL32(0, 255, 0, 255));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:43:31