2011-07-20 6 views
17

Mi pregunta es algo similar a this.Cómo determinar intersección de CGPaths

tengo 2 CGPathRef y 1 serán movidos por el toque de un dedo. Quiero encontrar que si los 2 CGPathRef están cruzados? Esa pregunta fue hecha hace casi 2 años y quiero saber si se ha encontrado algo mientras tanto.

+0

discusión relevante: http://www.cocoabuilder.com/archive/cocoa/65568-determing-the-intersection-of-two-nsbezierpath.html – Chuck

+0

¿Hay restricciones adicionales sobre sus datos? Por ejemplo, ¿se ha limitado a Beziers, o posiblemente incluso a un solo tipo de Bezier? – Tommy

+0

No, a partir de ahora estoy considerando CGPath. Si requiero el camino de Bezier, lo usaría. Pero supongo que, si tuviéramos para CGPaths, entonces no sería difícil para los caminos Bezier. – Ilanchezhian

Respuesta

6

He escrito un API de detección de ruta de colisión con base pequeña de píxeles para CGPathRefs. Requiere que agregue algunos directorios de origen a su proyecto, y solo funciona con ARC, pero al menos debería mostrarle cómo uno podría hacer algo como esto. Básicamente dibuja las dos rutas en dos contextos separados, y luego verifica píxel por píxel para ver si hay píxeles en ambas rutas. Obviamente, esto sería lento para ejecutar cada vez que el usuario arrastra el dedo, pero sin duda podría hacerse una vez cada medio segundo o menos, tal vez ni siquiera en el hilo principal.

Esta es la manera más fácil que he encontrado de hacer algo como esto, y puede ser fácilmente que no hay mejor manera, además de usar un montón de matemáticas.

+0

Gracias Alex, pero igual, como ya he mencionado en la pregunta, la intersección debe encontrarse tal como sucede mientras se mueve la ruta junto con el toque del dedo. – Ilanchezhian

1

En general, encontrar la intersección de dos CGPath arbitrarios va a ser muy complejo.

Hay maneras de hacer aproximaciones. Verificar las intersecciones de los cuadros delimitadores es un buen primer paso. También puede subdividir la curva y repetir el proceso para obtener mejores aproximaciones. Otra opción es aplanar las rutas y ver si alguno de los segmentos de línea de las rutas aplanadas se cruzan.

Para el caso general, sin embargo, las cosas se ponen muy desagradable muy rápido. Considere, por ejemplo, el hecho de que dos segmentos de bezier cúbicos (no importa una ruta completa ... solo un segmento) pueden cruzarse con otro segmento hasta en 6 puntos. Cuantos más segmentos haya en su camino, más intersecciones potenciales. También está el problema de las curvas de bezier degeneradas en las que un segmento tiene una cúspide que solo toca un punto de otro segmento. ¿Eso cuenta como una intersección? (A veces sí, a veces no)

No es claro por su pregunta, pero también se podría considerar las intersecciones de los trazos que se aplican a las curvas, y correcta cuenta de línea y se une a los ingletes. Eso se pone aún más difícil. Macromedia FreeHand (un programa de dibujo similar a Adobe Illustrator) tenía una biblioteca muy grande, compleja e intensamente matemática para descubrir intersecciones de curva de bezier arbitrarias. El problema no se resuelve fácilmente.

9

Esto es bastante antiguo, pero lo encontré en busca de una solución similar, en mi problema que quería encontrar un círculo cuando se superpuso con una trayectoria (un caso especial de su pregunta).

Lo resolví usando CGPathCreateCopyByStrokingPath para crear una versión trazada de la ruta original utilizando el radio del círculo como el ancho de trazo. Si el punto central del círculo se superpone con el trazado contorneado, el camino original se superpone al círculo.

BOOL CGPathIntersectsCircle(CGPathRef path, CGPoint center, CGFloat radius) 
{ 
    CGPathRef fuzzyPath; 
    fuzzyPath = CGPathCreateCopyByStrokingPath(path, NULL, radius, 
               kCGLineCapRound, 
               kCGLineJoinRound, 0.0); 
    if (CGPathContainsPoint(fuzzyPath, NULL, center, NO)) 
    { 
     CGPathRelease(fuzzyPath); 
     return YES; 
    } 
    CGPathRelease(fuzzyPath); 
    return NO; 
} 

Editar: Un error menor que el fuzzyPath no fue puesto en libertad.

+0

Esto era exactamente lo que necesitaba, gracias =) – Dustin

+0

Esto es lo que quería ... me salvaste el día :) gracias :) –

+0

Simplemente genial, gracias! – Mrug

1

Para encontrar la intersección de dos CAShapeLayers, podemos utilizar el siguiente método, CAShapeLayer no devolverá el marco.Pero podemos obtener el marco refPath usando CGPathGetBoundingBox. Pero este dará el marco en rectángulo. Lo que puedes entender.

if (CGRectIntersectsRect(CGPathGetBoundingBox(layer.path), CGPathGetBoundingBox(layer.path)))  
+0

Este método funciona solo para una ruta rectangular –