¿Cómo crear un CGPath aleatorio cerrado y sin problemas?

Estoy tratando de encontrar una forma de crear una ruta sin problemas cerrada random ( CGPath o UIBezierPath ). He leído sobre el algorithm de De Casteljau y otros artículos acerca de las routes de Bezier, pero no parece ajustarse a lo que trato de lograr.

Pensé en crear un círculo CGPath. Luego multiplicaré el path por una function que distorsionaría las posiciones de los puntos digamos, seno o coseno. Sin embargo, no sé si esta es la dirección correcta para ir, ya que la ruta no tendría forma aleatoria.

 CGMutablePathRef circle = CGPathCreateMutable(); CGPathAddArc(circle, nil, 0.0f, 0.0f, 100.0f, 2 * M_PI, 0.0f, true); ... CGPathRelease(circle); 

Sería genial si alguien me indicara en la dirección correcta cómo comenzar a implementarlo. Ejemplo de ruta que bash generar:

introduzca la descripción de la imagen aquí

Lo que has dibujado parece un círculo distorsionado.

Suponiendo que eso es lo que buscas, esto es lo que haría:

Escriba un código que tome un ángulo de 0 a 2pi mediante un número fijo de pasos. (Intente 8) Haga que el ángulo varíe por alguna pequeña cantidad aleatoria menor a ± pi / pasos.

Elige un radio base que sea algo less de 1/2 de la longitud de un lado del cuadrado que lo rodea, de modo que hay espacio para que tus puntos vayan dentro o fuera del radio de la base sin salir de tu cuadrado delimitador. Pruebe 3/8 de la longitud del cuadro delimitador.

Para cada valor de ángulo ligeramente aleatorizado a lo largo del círculo, calcule un valor de radio que sea el radio de base ± un valor aleatorio de 0 a la base de radio / 2.

Use seno y coseno para convertir sus valores de ángulo y radio en coorderadas x e y para un punto.

Agregue cada punto a una matriz. Si usas esos puntos para crear una ruta cerrada, te daría un polígono irregulares irregulares de 8 lados que es un círculo distorsionado.

Ahora usa esos puntos como los puntos de control para una spline Catmull-Rom para convertirla en una curva suave.

EDITAR: he creado un proyecto en github llamado RandomBlobs que hace lo que describo anteriormente, así como otro enfoque:

Rompe el área cuadrada en una cuadrícula de 3×3 de cuadrados más pequeños. Ignora el cuadrado central. Camina por los 8 cuadrados restantes en el sentido de las agujas del reloj. Para cada cuadrado, elija una coorderada x / y aleatoria dentro del cuadrado (pero evite que se acerque demasiado a los bordes). Cree UIBezierPath cerrado conectando los 8 puntos en order. Use suavizado Catmull-Rom para convertir el octágono irregular en una curva suave.

Sin embargo, un tercer enfoque probablemente sea aún más simple:

Use un layout circular como en el primer enfoque descrito anteriormente. Escoja puntos de control aleatorios. Pero luego, en lugar de usar splines Catmull-Rom, biseccione el ángulo entre cada par de puntos extremos en el círculo distorsionado y agregue un punto de control para una curva Bézier cuadrática, también con un valor de radio aleatorio. Entonces, mientras caminas alnetworkingedor del círculo, tendrás puntos finales alternativos y puntos de control. Es posible que deba agregar algunas restricciones a los puntos de control bezier para que no tenga "torceduras" en su forma curva (Para evitar torceduras, los puntos de control para las curvas vecinas de Bezier deben seguir una línea a través del punto final compartido de las dos curvas).


Aquí hay un par de imágenes de muestra del proyecto RandomBlobs. Las imágenes que subí están networkingucidas. El progtwig muestra opcionalmente los puntos de control que usa para generar cada image, pero realmente no puede ver los puntos de control en la image networkingucida.

Primero, una burbuja basada en círculos (usando el primer método que sugirieron Josh Caswell y yo): Burbuja circular En esa image, la forma del círculo inicial se muestra en gris claro:

Y segundo, una burbuja basada en la segunda técnica basada en cuadrados que describí:

Blob cuadrada

Y en esa image, la cuadrícula de cuadrados se muestra como reference. La forma se basa en un punto aleatorio en cada uno de los puntos de la grilla (sin include el cuadrado central).

He intentado build tu path, pero no es perfecto … De todos modos, voy a compartir mi testing ;-D Hop esto puede ayudar.

 // // DrawView.h // test // // Created by Armand DOHM on 03/03/2014. // // #import <UIKit/UIKit.h> @interface DrawView : UIView @end // // DrawView.m // test // // Created by Armand DOHM on 03/03/2014. // // #import "DrawView.h" #import <math.h> @implementation DrawView - (void)drawRect:(CGRect)rect { float r; //radius float rmax = MIN(rect.size.height,rect.size.width) * .5; //max radius float rmin = rmax * .1; //min radius NSMutableArray *points = [[NSMutableArray alloc] init]; /*cut a circle into x pies. for each of this pie take a point at a random radius link all of this point with quadcurve*/ for (double a=0;a < 2 * M_PI;a += M_PI / 10) { r = rmin + ((arc4random_uniform((int)(rmax - rmin) * 100)) / 100.0f); CGPoint p = CGPointMake((rect.size.width / 2) + (r * cos (a)) , (rect.size.height / 2) + (r * sin (a))); [points addObject:[NSValue valueWithCGPoint:p]]; } UIBezierPath *myPath=[[UIBezierPath alloc]init]; myPath.lineWidth=2; [myPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.0]; r = rmin + ((arc4random_uniform((int)(rmax - rmin) * 100)) / 100.0f); [myPath moveToPoint:CGPointMake((rect.size.width / 2) + (r * cos (0)) , (rect.size.height / 2) + (r * sin (0)))]; for (int i = 0; i < points.count; i+=2) { NSValue *value = [points objectAtIndex:i]; CGPoint p1 = [value CGPointValue]; value = [points objectAtIndex:(i+1)]; CGPoint p2 = [value CGPointValue]; [myPath addQuadCurveToPoint:p2 controlPoint:p1]; } [myPath closePath]; [myPath stroke]; } @end