圆圆关系

圆圆关系

问题描述

圆圆关系处理平面上两个圆之间的基本关系,包括相交判断、交点计算等。常用于碰撞检测和几何构造问题。

基本操作

算法思想

  1. 使用圆心距离判断
  2. 基于半径关系判断
  3. 适用于相交和包含判断
  4. 时间复杂度

代码实现

class Solution {
public:
    // 判断两圆位置关系
    // 返回值: -2内含 -1内切 0相交 1外切 2相离
    int circlePosition(const Circle& c1, const Circle& c2) {
        double d = c1.center.distance(c2.center);
        double r1 = c1.radius, r2 = c2.radius;
        
        if (d < abs(r1 - r2) - EPS) return -2;  // 内含
        if (abs(d - abs(r1 - r2)) < EPS) return -1;  // 内切
        if (d < r1 + r2 + EPS) return 0;  // 相交
        if (abs(d - (r1 + r2)) < EPS) return 1;  // 外切
        return 2;  // 相离
    }
    
    // 计算两圆交点
    vector<Point> circleIntersection(const Circle& c1, const Circle& c2) {
        int pos = circlePosition(c1, c2);
        if (pos < 0 || pos > 1) return {};  // 内含、内切、相离、外切
        
        double d = c1.center.distance(c2.center);
        double r1 = c1.radius, r2 = c2.radius;
        
        // 余弦定理计算角度
        double angle = acos((r1 * r1 + d * d - r2 * r2) / (2 * r1 * d));
        Point v = (c2.center - c1.center).normalize() * r1;
        
        return {
            c1.center + v.rotate(angle),
            c1.center + v.rotate(-angle)
        };
    }
    
    // 计算两圆公共面积
    double commonArea(const Circle& c1, const Circle& c2) {
        int pos = circlePosition(c1, c2);
        if (pos == -2) {  // 内含
            double r = min(c1.radius, c2.radius);
            return M_PI * r * r;
        }
        if (pos >= 1) return 0;  // 外切或相离
        
        double d = c1.center.distance(c2.center);
        double r1 = c1.radius, r2 = c2.radius;
        
        // 余弦定理计算角度
        double angle1 = acos((r1 * r1 + d * d - r2 * r2) / (2 * r1 * d));
        double angle2 = acos((r2 * r2 + d * d - r1 * r1) / (2 * r2 * d));
        
        // 扇形面积减去三角形面积
        return r1 * r1 * angle1 + r2 * r2 * angle2 - 
               d * r1 * sin(angle1);
    }
};
class Solution {
    static final double EPS = 1e-10;
    static final double PI = Math.PI;
    
    // 判断两圆位置关系
    // 返回值: -2内含 -1内切 0相交 1外切 2相离
    public int circlePosition(Circle c1, Circle c2) {
        double d = c1.center.distance(c2.center);
        double r1 = c1.radius, r2 = c2.radius;
        
        if (d < Math.abs(r1 - r2) - EPS) return -2;  // 内含
        if (Math.abs(d - Math.abs(r1 - r2)) < EPS) return -1;  // 内切
        if (d < r1 + r2 + EPS) return 0;  // 相交
        if (Math.abs(d - (r1 + r2)) < EPS) return 1;  // 外切
        return 2;  // 相离
    }
    
    // 计算两圆交点
    public List<Point> circleIntersection(Circle c1, Circle c2) {
        int pos = circlePosition(c1, c2);
        if (pos < 0 || pos > 1) return new ArrayList<>();
        
        double d = c1.center.distance(c2.center);
        double r1 = c1.radius, r2 = c2.radius;
        
        // 余弦定理计算角度
        double angle = Math.acos((r1 * r1 + d * d - r2 * r2) / (2 * r1 * d));
        Point v = c2.center.subtract(c1.center).normalize().multiply(r1);
        
        return Arrays.asList(
            c1.center.add(v.rotate(angle)),
            c1.center.add(v.rotate(-angle))
        );
    }
    
    // 计算两圆公共面积
    public double commonArea(Circle c1, Circle c2) {
        int pos = circlePosition(c1, c2);
        if (pos == -2) {  // 内含
            double r = Math.min(c1.radius, c2.radius);
            return PI * r * r;
        }
        if (pos >= 1) return 0;  // 外切或相离
        
        double d = c1.center.distance(c2.center);
        double r1 = c1.radius, r2 = c2.radius;
        
        // 余弦定理计算角度
        double angle1 = Math.acos((r1 * r1 + d * d - r2 * r2) / (2 * r1 * d));
        double angle2 = Math.acos((r2 * r2 + d * d - r1 * r1) / (2 * r2 * d));
        
        // 扇形面积减去三角形面积
        return r1 * r1 * angle1 + r2 * r2 * angle2 - 
               d * r1 * Math.sin(angle1);
    }
}
class Solution:
    def __init__(self):
        self.EPS = 1e-10
        self.PI = math.pi
    
    # 判断两圆位置关系
    # 返回值: -2内含 -1内切 0相交 1外切 2相离
    def circle_position(self, c1: Circle, c2: Circle) -> int:
        d = c1.center.distance(c2.center)
        r1, r2 = c1.radius, c2.radius
        
        if d < abs(r1 - r2) - self.EPS:
            return -2  # 内含
        if abs(d - abs(r1 - r2)) < self.EPS:
            return -1  # 内切
        if d < r1 + r2 + self.EPS:
            return 0  # 相交
        if abs(d - (r1 + r2)) < self.EPS:
            return 1  # 外切
        return 2  # 相离
    
    # 计算两圆交点
    def circle_intersection(self, c1: Circle, c2: Circle) -> List[Point]:
        pos = self.circle_position(c1, c2)
        if pos < 0 or pos > 1:
            return []
        
        d = c1.center.distance(c2.center)
        r1, r2 = c1.radius, c2.radius
        
        # 余弦定理计算角度
        angle = math.acos((r1 * r1 + d * d - r2 * r2) / (2 * r1 * d))
        v = (c2.center - c1.center).normalize() * r1
        
        return [
            c1.center + v.rotate(angle),
            c1.center + v.rotate(-angle)
        ]
    
    # 计算两圆公共面积
    def common_area(self, c1: Circle, c2: Circle) -> float:
        pos = self.circle_position(c1, c2)
        if pos == -2:  # 内含
            r = min(c1.radius, c2.radius)
            return self.PI * r * r
        if pos >= 1:
            return 0  # 外切或相离
        
        d = c1.center.distance(c2.center)
        r1, r2 = c1.radius, c2.radius
        
        # 余弦定理计算角度
        angle1 = math.acos((r1 * r1 + d * d - r2 * r2) / (2 * r1 * d))
        angle2 = math.acos((r2 * r2 + d * d - r1 * r1) / (2 * r2 * d))
        
        # 扇形面积减去三角形面积
        return r1 * r1 * angle1 + r2 * r2 * angle2 - \
               d * r1 * math.sin(angle1)

时间复杂度分析

操作 时间复杂度 空间复杂度
位置关系判断
交点计算
公共面积计算
包含判断

应用场景

  1. 碰撞检测
  2. 几何构造
  3. 区域判断
  4. 面积计算
  5. 相交判断

注意事项

  1. 浮点数精度
  2. 特殊情况处理
  3. 相切判断
  4. 内含判断
  5. 数值稳定性

常见变形

  1. 圆的包含关系
class Solution {
public:
    // 判断圆c1是否完全包含圆c2
    bool circleContains(const Circle& c1, const Circle& c2) {
        double d = c1.center.distance(c2.center);
        return d <= c1.radius - c2.radius + EPS;
    }
    
    // 计算多个圆的并集面积
    double unionArea(vector<Circle>& circles) {
        int n = circles.size();
        if (n == 0) return 0;
        
        double area = 0;
        for (int i = 0; i < (1 << n); i++) {
            double common = 0;
            int cnt = 0;
            Circle c;
            bool valid = true;
            
            for (int j = 0; j < n; j++) {
                if (i & (1 << j)) {
                    if (cnt == 0) {
                        c = circles[j];
                    } else {
                        common += commonArea(c, circles[j]);
                    }
                    cnt++;
                }
            }
            
            if (cnt > 0) {
                if (cnt % 2 == 1) {
                    area += c.area() - common;
                } else {
                    area -= common;
                }
            }
        }
        
        return area;
    }
};
class Solution {
    // 判断圆c1是否完全包含圆c2
    public boolean circleContains(Circle c1, Circle c2) {
        double d = c1.center.distance(c2.center);
        return d <= c1.radius - c2.radius + EPS;
    }
    
    // 计算多个圆的并集面积
    public double unionArea(Circle[] circles) {
        int n = circles.length;
        if (n == 0) return 0;
        
        double area = 0;
        for (int i = 0; i < (1 << n); i++) {
            double common = 0;
            int cnt = 0;
            Circle c = null;
            boolean valid = true;
            
            for (int j = 0; j < n; j++) {
                if ((i & (1 << j)) != 0) {
                    if (cnt == 0) {
                        c = circles[j];
                    } else {
                        common += commonArea(c, circles[j]);
                    }
                    cnt++;
                }
            }
            
            if (cnt > 0) {
                if (cnt % 2 == 1) {
                    area += c.area() - common;
                } else {
                    area -= common;
                }
            }
        }
        
        return area;
    }
}
class Solution:
    # 判断圆c1是否完全包含圆c2
    def circle_contains(self, c1: Circle, c2: Circle) -> bool:
        d = c1.center.distance(c2.center)
        return d <= c1.radius - c2.radius + self.EPS
    
    # 计算多个圆的并集面积
    def union_area(self, circles: List[Circle]) -> float:
        n = len(circles)
        if n == 0:
            return 0
        
        area = 0
        for i in range(1 << n):
            common = 0
            cnt = 0
            c = None
            valid = True
            
            for j in range(n):
                if i & (1 << j):
                    if cnt == 0:
                        c = circles[j]
                    else:
                        common += self.common_area(c, circles[j])
                    cnt += 1
            
            if cnt > 0:
                if cnt % 2 == 1:
                    area += c.area() - common
                else:
                    area -= common
        
        return area
  1. 圆的相交集合
class Solution {
public:
    // 计算多个圆的交集面积
    double intersectionArea(vector<Circle>& circles) {
        int n = circles.size();
        if (n == 0) return 0;
        
        // 检查是否存在交集
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (circlePosition(circles[i], circles[j]) > 0) {
                    return 0;  // 存在不相交的圆
                }
            }
        }
        
        // 找到最小包含圆
        double area = circles[0].area();
        for (int i = 1; i < n; i++) {
            area = min(area, commonArea(circles[0], circles[i]));
        }
        
        return area;
    }
};
class Solution {
    // 计算多个圆的交集面积
    public double intersectionArea(Circle[] circles) {
        int n = circles.length;
        if (n == 0) return 0;
        
        // 检查是否存在交集
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (circlePosition(circles[i], circles[j]) > 0) {
                    return 0;  // 存在不相交的圆
                }
            }
        }
        
        // 找到最小包含圆
        double area = circles[0].area();
        for (int i = 1; i < n; i++) {
            area = Math.min(area, commonArea(circles[0], circles[i]));
        }
        
        return area;
    }
}
class Solution:
    # 计算多个圆的交集面积
    def intersection_area(self, circles: List[Circle]) -> float:
        n = len(circles)
        if n == 0:
            return 0
        
        # 检查是否存在交集
        for i in range(n):
            for j in range(i + 1, n):
                if self.circle_position(circles[i], circles[j]) > 0:
                    return 0  # 存在不相交的圆
        
        # 找到最小包含圆
        area = circles[0].area()
        for i in range(1, n):
            area = min(area, self.common_area(circles[0], circles[i]))
        
        return area
全部评论

相关推荐

React的生命周期方法是指组件在其生命周期中的不同阶段可以调用的内置方法。这些方法包括以下几个阶段:https://www.nowcoder.com/issue/tutorial?zhuanlanId=Mg58Em&amp;uuid=8fdf5cbfd63b4a8a8e6491e5c03b513f1.&nbsp;挂载(Mounting):在这个阶段,组件被创建并插入到DOM中。constructor(props):&nbsp;在创建组件时被调用,用于初始化state和绑定事件等。static&nbsp;getDerivedStateFromProps():&nbsp;在构造函数之后,render函数之前被调用,允许基于传入的props来改变state。render():&nbsp;用于生成组件的输出。componentDidMount():&nbsp;在第一次渲染之后被调用,允许执行必要的初始化操作,如请求数据、发起网络请求等。2.&nbsp;更新(Updating):在这个阶段,组件根据新的props或state进行重新渲染。static&nbsp;getDerivedStateFromProps():&nbsp;在构造函数之后,render函数之前被调用,允许基于传入的props来改变state。shouldComponentUpdate():&nbsp;可用于跳过渲染。render():&nbsp;用于生成组件的输出。getSnapshotBeforeUpdate():&nbsp;在新DOM被插入之前被调用,允许获取最新的DOM状态。componentDidUpdate():&nbsp;在DOM更新之后被调用,允许执行必要的操作,如DOM操作、动画等。3.&nbsp;卸载(Unmounting):在这个阶段,组件被从DOM中移除。componentWillUnmount():&nbsp;在组件即将卸载和销毁之前被调用,允许执行必要的清理操作,如取消网络请求、清除定时器等。这些生命周期方法提供了控制和管理组件生命周期的能力,可以用于处理异步操作、执行必要的DOM操作、管理状态等。
前端求职圈
点赞 评论 收藏
分享
前端求职圈
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务