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

iOS开发:检测多边形线段是否被橡皮擦路径完全覆盖

iOS 多边形线段被橡皮擦路径完全覆盖的可靠检测方案

需求回顾

现有n边形模型存储所有线段坐标,用户在橡皮擦模式下手绘宽线浅蓝色路径,需检测并高亮所有被该路径完全覆盖的多边形线段(高亮为绿色),后续可删除;无覆盖线段时不选中任何线段。仅通过线段起点终点无法可靠判断覆盖情况,需实现精准检测逻辑。

核心实现思路

橡皮擦的宽线路径实际覆盖区域是沿线扩展的填充轮廓,不能仅验证端点,需确保线段全程处于橡皮擦的填充区域内。通过以下步骤实现可靠检测:

1. 生成橡皮擦路径的实际碰撞区域

利用Core Graphics的CGPathCreateCopyByStrokingPath,将手绘的橡皮擦路径转换为填充式的轮廓路径,这个路径就是橡皮擦宽线实际覆盖的区域:

// eraserPath:用户手绘的CGPathRef;eraserLineWidth:橡皮擦的线宽
CGPathRef eraserCollisionPath = CGPathCreateCopyByStrokingPath(eraserPath,
                                                              NULL,
                                                              eraserLineWidth,
                                                              kCGLineCapRound,
                                                              kCGLineJoinRound,
                                                              0);

2. 精准验证线段的完全覆盖

对每条多边形线段,通过包围盒快速过滤+密集采样点验证的方式判断是否被完全覆盖:

  • 快速过滤:先判断线段的包围盒是否被橡皮擦碰撞区域的包围盒包含,直接排除不可能的线段,提升性能
  • 密集采样验证:按橡皮擦线宽的比例在线段上采样多个点(至少包含端点、中点),确保每个采样点都在橡皮擦碰撞区域内

示例代码:

BOOL isSegmentFullyCovered(CGPoint start, CGPoint end, CGPathRef eraserCollisionPath, CGFloat eraserLineWidth) {
    // 计算线段包围盒
    CGRect segmentBounds = CGRectMake(MIN(start.x, end.x),
                                      MIN(start.y, end.y),
                                      ABS(end.x - start.x),
                                      ABS(end.y - start.y));
    // 计算橡皮擦碰撞区域包围盒
    CGRect eraserBounds = CGPathGetBoundingBox(eraserCollisionPath);
    
    // 快速排除:线段包围盒不在橡皮擦区域内则直接返回NO
    if (!CGRectContainsRect(eraserBounds, segmentBounds)) {
        return NO;
    }
    
    // 计算采样点数量:根据线段长度和橡皮擦线宽,确保采样密度足够覆盖所有区域
    CGFloat segmentLength = hypot(end.x - start.x, end.y - start.y);
    NSInteger sampleCount = MAX(3, (NSInteger)(segmentLength / (eraserLineWidth * 0.5)) + 1);
    
    // 遍历所有采样点,只要有一个点不在碰撞区域内,就说明未完全覆盖
    for (NSInteger i = 0; i < sampleCount; i++) {
        CGFloat progress = (CGFloat)i / (sampleCount - 1);
        CGPoint samplePoint = CGPointMake(start.x + progress * (end.x - start.x),
                                          start.y + progress * (end.y - start.y));
        
        if (!CGPathContainsPoint(eraserCollisionPath, NULL, samplePoint, NO)) {
            return NO;
        }
    }
    
    return YES;
}

3. 边界与性能优化

  • 线宽适配:确保橡皮擦线宽大于多边形线段的线宽,避免因线宽过小导致覆盖检测失效
  • 圆角兼容:如果橡皮擦路径使用了圆角线帽/线接,CGPathCreateCopyByStrokingPath会自动生成带圆角的碰撞区域,无需额外处理
  • 批量处理:对大量线段,先通过包围盒过滤减少需要精细验证的线段数量,提升检测效率

后续流程

  1. 遍历所有多边形线段,调用上述方法检测是否被完全覆盖
  2. 标记所有返回YES的线段为选中状态,绘制时用绿色高亮显示
  3. 删除操作时,直接从模型中移除标记的线段即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 02:40:16