5

我很难弄清楚如何确定可可中两个 NSBezierPath 封闭对象的交集。我在网上做了一些研究,到目前为止还没有找到答案。

这就是我所拥有的。 在此处输入图像描述

我需要编写某种在所有这些情况下都返回 true 的方法。

到目前为止,我在想的是通过使用bezierPathByFlateningPath来展平矩形,然后使用elementAtIndex: associatedPoints:获取每个元素(作为线段)来 遍历其中的每个点并检查第二个对象(矩形或椭圆)是否包含该点(使用containsPoint:)。

但是,我不知道如何遍历一个段的所有点......

如果有人有任何提示或想法可能会有所帮助,我将不胜感激!

4

2 回答 2

3

如果您有 2 个贝塞尔路径矩形并且知道它们的每个框架,那么您可以使用NSIntersectsRect()

NSRect rect1 = NSMakeRect(20.0, 150.0, 300.0, 100.0);
NSRect rect2 = NSMakeRect(100.0, 100.0, 100.0, 200.0);

[[NSColor redColor] set];

[NSBezierPath strokeRect:rect1];
[NSBezierPath strokeRect:rect2];

BOOL intersects = NSIntersectsRect(rect1, rect2);

NSLog(@"intersects == %@", (intersects ? @"YES" : @"NO"));

产生:

在此处输入图像描述

在这种情况下,它将记录intersects == YES.

于 2013-03-22T19:34:16.137 回答
2

这是一个非常快速和干净的解决方案。它还可以测试多条路径而不是一条,这很好,不是吗?

它适用于 CGBezier(iOS 和 MacOS 兼容)

• 1 - 创建必要的上下文

创建一个与视图大小相同的 16 位、一个组件(无 alpha)图形端口

  • 不要在每次测试时重新创建此上下文,这很耗时。仅在调整视图大小时重新创建它。
  • 我们称这个上下文为computeContext

创建一个 16 位、一个分量(无 alpha)、宽度和高度为 1 像素的图形端口。

  • 让我们将此上下文称为testContext

• 2 - 当您需要测试路径交叉点时:

我们在computeContext中进行以下操作:

  • 清除上下文(它将是全黑的)
  • 将上下文剪辑到要测试的路径
  • 用白色填充所有要测试的路径
  • (从现在开始,您不需要在 computeContext 中。)获取图像并将其绘制在testContext中,如下所示:
CGImageRef clippedPathsImage = CGBitmapContextCreateImage(computeContext);
CGRect     onePixSquare = CGRectMake(0,0,1,1);
CGContextDrawImage(testContext, onePixSquare, clippedPathsImage);

(不用担心,图像创建功能很快。它不会分配任何内存,因为位是在 bitmapContext 中分配的)

我们完成了!

long*   data = CGBitmapContextGetData(testContext);  
BOOL    intersects = (*data!=0);
  • 这比使用 alpha 值进行一些构图要快得多

  • 这比测试大图像中的所有像素要快得多。图像缩放是在内部进行的,硬件加速。所以这没什么大不了的。

但是,如果您想更快地加速并且可以提供更低的精度,您可以创建一个较小的 computeContext,例如 25% 的视图大小,并使用比例变换矩阵渲染所有路径。

1 像素上下文中的传输会更快,但您不确定是否检测到小于 4 像素大小的交叉点(比例为 25%,逻辑)。

不要使用 8 位灰度。我认为它不会加快处理速度,并且在减少到 1 个像素时会损失很多精度。足以失败。

不要忘记,在使用 hard 方法之前要做的第一个测试是测试边界框相交!

就这样

用库打开了一个 GitHub ;) https://github.com/moosefactory

希望这会有所帮助,干杯!;)


这是创建 16 位灰色上下文的代码。它可以更简洁,但我声明变量以使其清楚。您不需要任何 bitmapInfo(最后一个参数),因为没有 alphaValue,而且我们不使用浮点格式。

-(CGContextRef)createComputeContext
{
    size_t  w = (size_t)self.bounds.size.width;
    size_t  h = (size_t)self.bounds.size.height;
    size_t  nComps = 1;
    size_t  bits   = 16;
    size_t  bitsPerPix  = bits*nComps;
    size_t  bytesPerRow = bitsPerPix*w;    
    CGColorSpaceRef  cs = CGColorSpaceCreateDeviceGray();

    CGContextRef bmContext = CGBitmapContextCreate(NULL, w, h, bits, bytesPerRow, cs, 0);

    return bmContext;
}
于 2013-07-13T15:43:26.670 回答