Iphone CGPathRef交叉口

Iphone CGPathRef交叉口,iphone,cocoa,cocoa-touch,core-graphics,Iphone,Cocoa,Cocoa Touch,Core Graphics,是否有办法确定两个CGPathRef是否相交。在我的例子中,所有的cgpath都有closePath 例如,我有两条路径。一条路径是以一定角度旋转的矩形,另一条路径是弯曲路径。两条路径原点将频繁更改。在某个点上,它们可能相交。我想知道它们何时相交。如果你有什么解决办法,请告诉我 提前感谢1)没有任何CGPathAPI来执行此操作。但是,你可以做数学来解决这个问题。看看维基百科上的这篇文章,看看CGPath中的曲线是如何实现的 2) 这在iPhone上可能会很慢,但你可以用不同的颜色(比如,红色和

是否有办法确定两个CGPathRef是否相交。在我的例子中,所有的cgpath都有closePath

例如,我有两条路径。一条路径是以一定角度旋转的矩形,另一条路径是弯曲路径。两条路径原点将频繁更改。在某个点上,它们可能相交。我想知道它们何时相交。如果你有什么解决办法,请告诉我

提前感谢

1)没有任何
CGPath
API来执行此操作。但是,你可以做数学来解决这个问题。看看维基百科上的这篇文章,看看CGPath中的曲线是如何实现的


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

将一条路径设置为剪辑路径,绘制另一条路径,然后搜索剪辑过程中幸存下来的像素:

// 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上下文中绘制透明曲线。此解决方案优于旧方案,因为它是

  • 简单的
  • 使用四分之一的内存作为8位灰度上下文就足够了
  • 避免了对毛茸茸、难以调试的透明代码的需要
  • 谁能要求更多

    我想你可以要求一个完整的实现,准备剪切“n”粘贴,但这会破坏乐趣,并混淆一个简单的答案

    更老、更难理解且回答效率较低

    将两个
    cgpathref
    分别以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
    

    让光栅化版本的分辨率作为您的精度,并选择适合您的性能需要的精度。

    对于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=128128=(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上添加颜色值,它只是替换它们。我浏览了文档,尝试了不同的颜色空间配置,看看是否有办法让它工作,但没有成功如果你找不到一种方法让你的透明代码工作,开始一个新的问题。如果你有代码回答这个问题,那就太好了。现在,这是一个理论上的答案,在实践中似乎不起作用(问题被标记为iPhone,你的答案是“如果..iPhone…可能必须”。我的经验是:试过了,没用)。我不希望其他人走上和我一样的死胡同。这不是一个简单的答案,你需要做一些工作。任何人都可以看到iOS可以绘制透明的路径,所以你的代码一定被窃听了。开始一个“为什么这段代码不绘制透明的CGPathRefs?”问题。我已经在我的答案中添加了更多的细节,但我认为要么你的CGContext配置错误,要么你没有单独绘制路径,或者有其他问题。一旦你让它工作起来,你可以随意发布你的代码,这将是一个更好的答案。iOS不会忽略alpha。检查您的代码-您是否尝试过使用KCGIMAGEAlphaPremultipledLast创建CGContext?我认为您的透明度问题是由于您创建了一个ARGB位图,但指定了RGBA颜色。在ARGB中,你的半透明颜色是一种美丽的矢车菊蓝色,带有50%的阿尔法。请尝试明确的CGContextSetRGBFillColor,并告诉我这是否解决了问题。p、 我已经更新了我的解决方案,以避免这种令人烦恼的透明度问题。KCGIMAGEALPHAPPremultipledLast(以及所有变体)失败。该方法称为“ARGB”,但其中没有指定alpha通道的位置-AFAIC读取苹果的文档,位图没有明确的alpha通道,苹果公司根据传入的颜色参考进行内部处理。苹果公司的文档将该颜色参考数组定义为RGBA。或者我遗漏了什么?阿尔法是第一位的,因为kgimagealphapremultipledfirst记录在CGImage.h中。位图可以有一个alpha通道,CGColorRef肯定会定义顺序,但您使用的是一个裸组件数组(剪切粘贴混合?),这很可能取决于位图布局。不知道为什么kCGImageAlphaPremultipliedLast失败了,它从2009年就开始为我工作了。RGBA,tho没有什么特别之处,只是它与OpenGLES 1纹理很好地匹配。#2实际上非常快,是解决某些问题(例如寻找笔划的交点而不是填充)的绝佳方法。
    - (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;
    }