基于BGI的C语言图形面积计算:单位方格计数代码修正需求
问题分析与修复方案
你的代码在计算四边形面积(统计单位方格数)时存在几个关键问题,导致结果错误:
核心问题点
- 点-in-多边形判断逻辑残缺:
你只在点处于边的包围盒内时才计算叉积,而且仅判断叉积<0就标记为外部,这会漏掉大量应该被统计的点,同时也没处理点在边上的情况。正确的做法是对所有边计算位置关系,同时单独检测点是否在边上。 - 遍历范围未包含边界:
循环条件i < maxX和j < maxY会漏掉maxX、maxY对应的行/列,导致图形最右侧和最下方的方格未被统计。 - 无意义的除法操作:
最后输出时toplamBirimKare / 100完全错误,统计的单位方格数就是面积值,不需要除以100。 - 未统计边经过的方格:
当前逻辑只统计内部点,边经过的方格没有被纳入统计,需要补充边的方格检测。
修正后的代码
#include <stdio.h> #include <graphics.h> // 判断点(x,y)是否在线段(x1,y1)-(x2,y2)上 int nokta_cizgide_mi(int x, int y, int x1, int y1, int x2, int y2) { // 先判断点是否在线段的包围盒内 if (x < (x1 < x2 ? x1 : x2) || x > (x1 > x2 ? x1 : x2)) return 0; if (y < (y1 < y2 ? y1 : y2) || y > (y1 > y2 ? y1 : y2)) return 0; // 叉积为0说明共线,确认点在线段上 return (x - x1) * (y2 - y1) == (y - y1) * (x2 - x1); } // 判断点(x,y)是否在四边形内部或边上 int icinde_veya_uzerinde_mi(int x, int y, int x_dizi[], int y_dizi[]) { int kesisim_sayisi = 0; int kenar_sayisi = 4; for (int k = 0; k < kenar_sayisi; k++) { int x1 = x_dizi[k], y1 = y_dizi[k]; int x2 = x_dizi[(k+1)%kenar_sayisi], y2 = y_dizi[(k+1)%kenar_sayisi]; // 先判断点是否在当前边上 if (nokta_cizgide_mi(x, y, x1, y1, x2, y2)) { return 1; } // 射线法:统计点向右的射线与边的交点数,奇数则在内部 if (((y1 > y) != (y2 > y)) && (x < (x2 - x1) * (float)(y - y1) / (y2 - y1) + x1)) { kesisim_sayisi++; } } return kesisim_sayisi % 2 == 1; } void dortgen_alani(int sekil_ciz[][2]) { int x[4], y[4]; for (int i = 0; i < 4; i++) { x[i] = sekil_ciz[i][0]; y[i] = sekil_ciz[i][1]; putpixel(x[i], y[i], WHITE); // 标记顶点 } int toplamBirimKare = 0; int minX = x[0], minY = y[0]; int maxX = x[0], maxY = y[0]; for (int i = 1; i < 4; i++) { if (x[i] < minX) minX = x[i]; if (x[i] > maxX) maxX = x[i]; if (y[i] < minY) minY = y[i]; if (y[i] > maxY) maxY = y[i]; } // 遍历包含边界的所有方格 for (int i = minX; i <= maxX; i++) { for (int j = minY; j <= maxY; j++) { if (icinde_veya_uzerinde_mi(i, j, x, y)) { putpixel(i, j, BLUE); toplamBirimKare++; } } } printf("Dortgenin alani (birim karelerle): %d birim kare\n", toplamBirimKare); }
修正说明
- 新增边检测函数:
nokta_cizgide_mi专门判断点是否在边上,确保边经过的方格被统计。 - 改用射线法判断内部点:
icinde_veya_uzerinde_mi使用射线法,通过统计点向右射线与边的交点数,奇数则判定为内部点,同时优先处理点在边上的情况。 - 修正遍历范围:将
i < maxX改为i <= maxX,j < maxY改为j <= maxY,包含所有边界方格。 - 移除错误除法:直接输出统计的
toplamBirimKare值,这就是实际的单位方格数(面积)。
内容的提问来源于stack exchange,提问作者erkan2541
相关产品推荐
相关产品推荐

