如何确定NSBezierPaths是否在Cocoa中相交?

时间:2013-03-22 19:03:34

标签: objective-c cocoa nsbezierpath

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

这就是我所拥有的。 enter image description here

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

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

但是,我不知道如何通过细分的所有要点......

如果有人有任何可能有帮助的提示或想法,我会非常感激!

2 个答案:

答案 0 :(得分:3)

如果你有2个bezier路径矩形并且知道它们的每个帧,那么你可以使用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"));

产地:

enter image description here

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

答案 1 :(得分: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);

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

我们已经完成了!

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

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

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

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

不要使用8位灰色。我认为它不会加速这个过程,并且在减少到1个像素时会失去很多精度。足够失败。

  

不要忘记在使用硬路之前要做的第一个测试是测试边界框交叉点!

这就是全部

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

希望这会有所帮助,欢呼! ;)


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

-(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;
}