CGPathRef交集

时间:2009-06-20 15:03:45

标签: iphone cocoa cocoa-touch core-graphics

有没有办法找出两个CGPathRef是否相交。在我的例子中,所有CGPath都有closePath。

例如,我有两条路。一条路径是以一定角度旋转的矩形,另一条路径是弯曲路径。两条路径的起源将经常变化。在某些时候,它们可能相交。我想知道它们什么时候相交。如果您有任何解决方案,请告诉我。

提前致谢

3 个答案:

答案 0 :(得分:3)

将一条路径设为剪切路径,绘制另一条路径,然后搜索在裁剪过程中幸存的像素:

// initialise and erase context
CGContextAddPath(context, path1);
CGContextClip(context);

// set fill colour to intersection colour
CGContextAddPath(context, path2);
CGContextFillPath(context);

// search for pixels that match intersection colour

这是因为裁剪=相交。

不要忘记,交叉点取决于内在性的定义,其中有几个。此代码使用了绕组数填充规则,您可能需要偶数奇数规则或其他内容。如果内在性不能让你夜不能寐,那么这段代码应该没问题。

我之前的回答是将透明曲线绘制到RGBA上下文。这个解决方案优于旧解决方案,因为它是

  1. 简单
  2. 使用四分之一的内存作为8位灰度上下文就足够了
  3. 不需要毛茸茸的,难以调试的透明度代码
  4. 谁可以要求更多?

    我想你可以要求一个完整的实现,准备削减''''',但这会破坏乐趣并混淆一个简单的答案。

    年龄较大,难以理解并且缺乏有效的答案

    将50%透明度的CGPathRefs 单独绘制到归零的CGBitmapContextCreate - RGBA内存缓冲区,并检查任何像素值> 128.这适用于任何支持CoreGraphics(即iOS和OSX)的平台。

    在伪代码中

    // zero memory
    
    CGContextRef context;
    context = CGBitmapContextCreate(memory, wide, high, 8, wide*4, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast);
    CGContextSetRGBFillColor(context, 1, 1, 1, 0.5);  // now everything you draw will be at 50%
    
    // draw your path 1 to context
    
    // draw your path 2 to context
    
    // for each pixel in memory buffer
    if(*p > 128) return true; // curves intersect  
    else p+= 4; // keep looking
    

    让光栅化版本的分辨率为您的精度,并选择精度以满足您的性能需求。

答案 1 :(得分:0)

1)没有任何CGPath API可以执行此操作。但是,你可以做数学计算。看一下关于Bezier curves的维基百科文章,看看如何实现CGPath中的曲线。

2)这在我期望的iPhone上会很慢但是你可以将两条路径填充到不同颜色的缓冲区(比如红色和蓝色,alpha = 0.5),然后遍历缓冲区找到任何颜色交叉点处出现的像素。这将非常缓慢。

答案 2 :(得分:-1)

对于iOS,似乎忽略了alpha混合。

相反,您可以进行颜色混合,这将实现相同的效果,但不需要alpha:

CGContextSetBlendMode(context, kCGBlendModeColorDodge);
CGFloat semiTransparent[] = { .5,.5,.5,1};

输出图像中的像素为:

  • RGB = 0,0,0 =(0.0f)...无路径
  • RGB = 64,64,64 =(0.25f)...一条路径,没有交叉点
  • RGB = 128,128,128 =(0.5f)...找到两条路径,交叉点

完整的绘图代码:

-(void) drawFirst:(CGPathRef) first second:(CGPathRef) second into:(CGContextRef)context
{
    /** setup the context for DODGE (everything gets lighter if it overlaps) */
    CGContextSetBlendMode(context, kCGBlendModeColorDodge);

    CGFloat semiTransparent[] = { .5,.5,.5,1};

    CGContextSetStrokeColor(context, semiTransparent);
    CGContextSetFillColor(context, semiTransparent);

    CGContextAddPath(context, first);
    CGContextFillPath(context);
    CGContextStrokePath(context);

    CGContextAddPath(context, second);
    CGContextFillPath(context);
    CGContextStrokePath(context);
}

检查输出的完整代码:

[self drawFirst:YOUR_FIRST_PATH second:YOUR_SECOND_PATH into:context];

// Now we can get a pointer to the image data associated with the bitmap
// context.
BOOL result = FALSE;
unsigned char* data = CGBitmapContextGetData (context);
if (data != NULL) {

    for( int i=0; i<width; i++ )
        for( int k=0; k<width; k++ )
        {
    //offset locates the pixel in the data from x,y.
    //4 for 4 bytes of data per pixel, w is width of one row of data.
    int offset = 4*((width*round(k))+round(i));
    int alpha =  data[offset];
    int red = data[offset+1];
    int green = data[offset+2];
    int blue = data[offset+3];

            if( red > 254 )
            {
                result = TRUE;
                break;
            }
        }

最后,这是来自另一个SO答案的略微修改的代码...用于在iOS 4,iOS 5上创建RGB空间的完整代码,它将支持上述功能:

- (CGContextRef) createARGBBitmapContextWithFrame:(CGRect) frame
{
   /** NB: this requires iOS 4 or above - it uses the auto-allocating behaviour of Apple's method, to reduce a potential memory leak in the original StackOverflow version */
    CGContextRef    context = NULL;
    CGColorSpaceRef colorSpace;
    void *          bitmapData;
    int             bitmapByteCount;
    int             bitmapBytesPerRow;

    // Get image width, height. We'll use the entire image.
    size_t pixelsWide = frame.size.width;
    size_t pixelsHigh = frame.size.height;

    // Declare the number of bytes per row. Each pixel in the bitmap in this
    // example is represented by 4 bytes; 8 bits each of red, green, blue, and
    // alpha.
    bitmapBytesPerRow   = (pixelsWide * 4);
    bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);

    // Use the generic RGB color space.
    colorSpace = CGColorSpaceCreateDeviceRGB();
    if (colorSpace == NULL)
    {
        fprintf(stderr, "Error allocating color space\n");
        return NULL;
    }

    // Create the bitmap context. We want pre-multiplied ARGB, 8-bits
    // per component. Regardless of what the source image format is
    // (CMYK, Grayscale, and so on) it will be converted over to the format
    // specified here by CGBitmapContextCreate.
    context = CGBitmapContextCreate (NULL,
                                     pixelsWide,
                                     pixelsHigh,
                                     8,      // bits per component
                                     bitmapBytesPerRow,
                                     colorSpace,
                                     kCGImageAlphaPremultipliedFirst
                                     //kCGImageAlphaFirst
                                     );
    if (context == NULL)
    {
        fprintf (stderr, "Context not created!");
    }

    // Make sure and release colorspace before returning
    CGColorSpaceRelease( colorSpace );

    return context;
}