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

OpenGL绘制两个等半径圆时如何判定重叠区域点并排除重叠部分

绘制排除重叠区域的等半径双圆方案

需求描述

需要绘制两个半径相等的圆,仅填充两圆的非重叠区域,排除相交重叠部分,预期效果如下:
预期效果示意图
要求仅在图中非重叠区域绘制、设置像素点。

现有问题代码

已编写的基础OpenGL/GLUT实现代码如下,运行结果不符合预期:

void draw_venn(){   
        
float radian_to_degree_theta=2 * 3.14 / 360,
          r = 0.5,
          distance=0.3,
          theta=0.0,
          theta2=0.0,
          xR=0.0,
          yR=0.0,
          xG=0.0,
          yG=0.0,
          sum_radii=0,
          dis=0.0;

    sum_radii=r+r;
    for (r = 0.5; r >=0; r-=0.001)
    {
        for (float degree = 0; degree < 361; degree+=0.1)   
        {   
            theta =degree*radian_to_degree_theta;   
            xR=r*cos(theta)+distance;
            yR=r*sin(theta);
            
            xG=r*cos(theta)-distance;
            yG=r*sin(theta);

            dis=sqrt(pow(xR-xG,2) + pow(yR-yG,2));  
            if (dis <= sum_radii)   
            {
                set_point(xR,yR,0.1,1,0,0);
                set_point(xG,yG,0.1,0,1,0);
            }           
            
        }
    }
}
void set_point(float x,float y,float size,float R,float G,float B){
    glPointSize(size);
    glBegin (GL_POINTS);
    glColor3f (R, G, B);
    glVertex2f(x, y);   
    glEnd ();
}
void draw(void)
{
    glClearColor (1, 1, 1, 0);
    glClear (GL_COLOR_BUFFER_BIT);
   
    glPushMatrix(); 

    draw_ven();

    glPopMatrix ();     

    glFlush();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE);
    glutInitWindowSize(1400, 1400);
    glutInitWindowPosition(700, 500);
    glutCreateWindow("GL Sample");
    glutDisplayFunc(draw);
    glutMainLoop();
    return 0;
}

代码实际运行效果如下,重叠区域未被排除:
实际运行错误结果截图

重叠区域判定逻辑

两个等半径圆的圆心分别为右圆圆心(distance, 0)、左圆圆心(-distance, 0),半径均为r。
如果一个点同时落在两个圆的内部,它就属于重叠区域,绘制时需要跳过。
点在圆内的判定规则为:点到圆心的距离小于等于圆半径。为避免开方运算的性能损耗,可直接使用距离平方与半径平方比较:

  1. 对右圆上生成的点,计算它到左圆圆心的距离平方,若该值小于等于半径平方,说明点落在左圆内,属于重叠区。
  2. 对左圆上生成的点,计算它到右圆圆心的距离平方,若该值小于等于半径平方,说明点落在右圆内,属于重叠区。
    原代码的核心错误是误用了两圆相交的判定逻辑:计算同一半径层级下两个生成点的距离与半径和比较,完全不匹配「点是否在另一圆内」的判定要求,因此无法得到正确结果。

修正后实现

核心绘制函数修复

void draw_venn(){   
    const float PI = 3.1415926f;
    float radian_to_degree_theta = 2 * PI / 360,
          r = 0.5,
          distance = 0.3,
          theta = 0.0,
          xR = 0.0,
          yR = 0.0,
          xG = 0.0,
          yG = 0.0,
          r_sq = r * r; // 预存半径平方,减少重复计算

    // 使用独立循环变量,避免修改初始半径r的取值
    for (float cur_r = r; cur_r >= 0; cur_r -= 0.001)
    {
        for (float degree = 0; degree < 361; degree += 0.1)   
        {   
            theta = degree * radian_to_degree_theta;   
            // 生成右圆当前采样点
            xR = cur_r * cos(theta) + distance;
            yR = cur_r * sin(theta);
            // 判定点是否在左圆外:外则属于非重叠区,绘制
            float dist_to_left_sq = pow(xR + distance, 2) + pow(yR, 2);
            if (dist_to_left_sq > r_sq) {
                set_point(xR, yR, 0.1, 0.5, 0.5, 0.5); // 匹配预期的灰色填充
            }

            // 生成左圆当前采样点
            xG = cur_r * cos(theta) - distance;
            yG = cur_r * sin(theta);
            // 判定点是否在右圆外:外则属于非重叠区,绘制
            float dist_to_right_sq = pow(xG - distance, 2) + pow(yG, 2);
            if (dist_to_right_sq > r_sq) {
                set_point(xG, yG, 0.1, 0.5, 0.5, 0.5);
            }           
        }
    }
}

其他需要修正的问题

  • 原draw函数中调用的函数名为draw_ven,与定义的draw_venn不一致,会触发编译错误,需要统一函数名。
  • 原代码给左右圆分别设置红、绿颜色,与预期的统一灰色非重叠区效果不符,需要统一颜色值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:45:19