CGPathRef路口(CGPathRef intersection)

2019-06-23 17:52发布

有没有办法找到了两次CGPathRefs是否相交与否。 在我的情况下,所有CGPaths都具有closePath。

例如,我有两个路径。 一个路径是与某些角度旋转,而另一路径是弯曲的路径的矩形。 两条路径起源会经常发生变化。 在某些时候,他们可能会相交。 我想知道他们是相交时。 请让我知道,如果您有任何解决方案。

提前致谢

Answer 1:

让一个路径剪切路径,绘制另一条路径,然后搜索幸存的剪辑处理像素:

// 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. 免除了毛,难以调试透明度代码的需要

谁还能要求更多?

我想你可以问一个完整的实现,准备cut'n'paste,但会杀风景和混淆原本简单的答案。

年纪大了,更难理解,效率较低ANSWER

绘制两个CGPathRefs在50%的透明度分别为归零, CGBitmapContextCreate -ed 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

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



Answer 2:

1)没有任何CGPath API来做到这一点。 但是,你可以做数学弄明白。 看看这个维基百科的文章贝塞尔曲线 ,看看如何在CGPath曲线实现。

2)这将是缓慢的iPhone我希望,但你可以两个路径填写到不同颜色的缓冲区(比如,红色和蓝色,用α= 0.5),然后通过缓冲迭代地发现,发生的任何像素在路口。 这将是极其缓慢。



Answer 3:

对于iOS,阿尔法混合似乎被忽略。

相反,你可以做一个颜色混合,这将达到同样的效果,但并不需要阿尔法:

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

在输出的图像的像素将是:

  • RGB = 0,0,0 =(0.0F)...没有路径
  • RGB = 64,64,64 =(0.25F)...一个路径,没有交集
  • RGB = 128128128 =(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;
            }
        }

最后,这里是从创建在iOS 4,iOS 5中的RGB空间,这将支持上述功能的另一个SO回答......完整的代码稍加修改的代码:

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


文章来源: CGPathRef intersection