Dibujar squircle estilo iOS 7 programáticamente

Estoy tratando de encontrar una forma de dibujar un ícono de estilo iOS 7 'squircle' de forma programática, usando charts centrales. No estoy preguntando cómo dibujar un rectángulo networkingondeado . Un squircle es un superelipse:

Squircle

que es ligeramente diferente a un rectángulo networkingondeado regular: Rectángulo redondeado vs squircle

Ícono de la música en squircle

Su fórmula exacta está disponible . Sin embargo, no puedo entender cómo dibujar esto usando, por ejemplo, un CGPath, y mucho less completarlo, y poder networkingimensionarlo fácilmente. Todo esto siendo completamente exacto con la fórmula. ¿Alguna idea?

Cita de Wikipedia: Superellipse

Para n = 1/2, en particular, cada uno de los cuatro arcos es una curva Bézier cuadrática definida por los dos ejes; Como resultado, cada arco es un segmento de una parábola.

Entonces, ¿por qué no tratar de aproximar a Squircle usando curvas de Bézier? Ambas curvas (Bezier y Squircle) están definidas por las ecuaciones paramétricas.

La class UIBezierPath tiene método: addCurveToPoint:controlPoint1:controlPoint2:

Añade una curva Bézier cúbica a la trayectoria del receptor.

NOTA: El uso del método addQuadCurveToPoint:controlPoint: produce resultados peores, probados.

Utilicé este método y eso es lo que sucedió como resultado:

networking line – rectángulo networkingondeado, blue line – rectángulo a partir de cuatro curvas de Bézier

Rectángulo redondeado frente a curva Bezier cúbica

Si le interesa este resultado, dibuje el código a continuación.

NOTA: Para lograr una coincidencia más exacta, se puede requerir la curva de Bezier para cambiar las coorderadas de los cuatro corner points (ahora corresponden a los angularjs del rectángulo en el que está inscrita la figura).

 CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSaveGState(context); //set rect size for draw float rectSize = 275.; CGRect rectangle = CGRectMake(CGRectGetMidX(rect) - rectSize/2, CGRectGetMidY(rect) - rectSize/2, rectSize, rectSize); //Rounded rectangle CGContextSetStrokeColorWithColor(context, [UIColor networkingColor].CGColor); UIBezierPath* roundedPath = [UIBezierPath bezierPathWithRoundedRect:rectangle cornerRadius:rectSize/4.7]; [roundedPath stroke]; //Rectangle from Fours Bezier Curves CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor); UIBezierPath *bezierCurvePath = [UIBezierPath bezierPath]; //set coner points CGPoint topLPoint = CGPointMake(CGRectGetMinX(rectangle), CGRectGetMinY(rectangle)); CGPoint topRPoint = CGPointMake(CGRectGetMaxX(rectangle), CGRectGetMinY(rectangle)); CGPoint botLPoint = CGPointMake(CGRectGetMinX(rectangle), CGRectGetMaxY(rectangle)); CGPoint botRPoint = CGPointMake(CGRectGetMaxX(rectangle), CGRectGetMaxY(rectangle)); //set start-end points CGPoint midRPoint = CGPointMake(CGRectGetMaxX(rectangle), CGRectGetMidY(rectangle)); CGPoint botMPoint = CGPointMake(CGRectGetMidX(rectangle), CGRectGetMaxY(rectangle)); CGPoint topMPoint = CGPointMake(CGRectGetMidX(rectangle), CGRectGetMinY(rectangle)); CGPoint midLPoint = CGPointMake(CGRectGetMinX(rectangle), CGRectGetMidY(rectangle)); //Four Bezier Curve [bezierCurvePath moveToPoint:midLPoint]; [bezierCurvePath addCurveToPoint:topMPoint controlPoint1:topLPoint controlPoint2:topLPoint]; [bezierCurvePath moveToPoint:midLPoint]; [bezierCurvePath addCurveToPoint:botMPoint controlPoint1:botLPoint controlPoint2:botLPoint]; [bezierCurvePath moveToPoint:midRPoint]; [bezierCurvePath addCurveToPoint:topMPoint controlPoint1:topRPoint controlPoint2:topRPoint]; [bezierCurvePath moveToPoint:midRPoint]; [bezierCurvePath addCurveToPoint:botMPoint controlPoint1:botRPoint controlPoint2:botRPoint]; [bezierCurvePath stroke]; CGContextRestoreGState(context); 

Esta no es una gran respuesta, ya que no llega al corazón de lo que estás preguntando, que es cómo dibujar un superellipse ** mediante progtwigción, pero puedes:

  1. Descarga la forma de icono de SVG para iOS7 aquí: http://dribbble.com/shots/1127699-iOS-7-icon-shape-PSD
  2. Importarlo a su proyecto Xcode
  3. Agregue PocketSVG a su proyecto: https://github.com/arielelkin/PocketSVG
  4. Cargue el SVG y conviértalo en un UIBezierPath, desde allí puede escalar y transformar como desee:

     PocketSVG *myVectorDrawing = [[PocketSVG alloc] initFromSVGFileNamed:@"iOS_7_icon_shape"]; UIBezierPath *myBezierPath = myVectorDrawing.bezier; // Apply your transforms here: [myBezierPath applyTransform:CGAffineTransformMakeScale(2.5, 2.5)]; [myBezierPath applyTransform:CGAffineTransformMakeTranslation(10, 50)]; CAShapeLayer *myShapeLayer = [CAShapeLayer layer]; myShapeLayer.path = myBezierPath.CGPath; myShapeLayer.strokeColor = [[UIColor networkingColor] CGColor]; myShapeLayer.lineWidth = 2; myShapeLayer.fillColor = [[UIColor clearColor] CGColor]; [self.view.layer addSublayer:myShapeLayer]; 

** Tal vez valga la pena señalar que la forma podría no ser un superellipse exacto de todos modos: http://i.imgur.com/l0ljVRo.png

Esto sería bastante fácil de hacer en OpenGL ES con un sombreador. Simplemente dibuja un quad y pasa en xey como attributes de vértice. En el sombreador de fragments, conecte xey en la ecuación. Si el resultado es <= 1, entonces el fragment está dentro de la forma. Si puedo get algo de time libre, podría probar esto y publicarlo aquí.

Si desea usar CGPath, creo que la key es parametrizar x e y en términos de t, que va de 0 a 2π. Luego evalúe xey en intervalos regulares. Intentaré resolver esto también en mi time libre, pero mis cálculos están oxidados.

Por cierto, estoy seguro de que Apple no está usando esta fórmula. Vea el enlace que posted @ millimoose: http://blog.mikeswanson.com/post/62341902567/unleashing-genetic-algorithms-on-the-ios-7-icon