2011-01-12 10 views
8

Oye, estoy tratando de averiguar cómo generar curvas de bezier en iOS en función de la entrada del usuario. ¿Hay alguna clase existente para esto? ¿Puede alguien darme un resumen general de lo que se requeriría? Solo necesito ayuda para comenzar con el pie derecho.¿Dibujando curvas de bezier con mi dedo en iOS?

+0

eso es lo que necesita. Solo eche un vistazo a este tutorial llamado [Cómo crear una aplicación de pintura simple para iOS] (http://blog.effectiveui.com/?p=8105) – fyasar

+2

Hay una reseña completa sobre esto en el blog de Mike Nachbaur. [Puede encontrar la publicación aquí] (http://nachbaur.com/blog/core-animation-part-4), y se trata de animar objetos sobre curvas de bezier dibujadas por el usuario. –

+0

La siguiente es una copia de mi respuesta [en una pregunta relacionada] (http://stackoverflow.com/questions/7345251/bezier-path-with-dynamic-change-of-width/11091956#11091956). He escrito algunas funciones que te ayudarán a hacer exactamente eso. Lea [más en mi publicación] (http://www.wiggler.gr/2012/06/17/bezier-curves-control-points-calculation-not-only-in-ios/). El código está en [mi repositorio en github] (https://github.com/Petrakeas/outlineDEMO). En mi publicación, también encontrará [un video] (http://www.youtube.com/watch?v=iOHvIiryfaQ) que demuestra el uso de las funciones. – Petrakeas

Respuesta

4

Bien, la manera más fácil de hacerlo es probablemente subclasificar UIView y usar CoreGraphics para dibujar. Consulte el código de muestra de QuarzDemo. Implemente el drawInRect -metodo para su clase de vista personalizada. Y detectar toques del usuario con touchesBegan, touchesMoved etc.

Aquí hay un código de ejemplo (tomado de QuarzDemo) para dibujar una curva de Bezier:

// Drawing with a white stroke color 
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); 
// Draw them with a 2.0 stroke width so they are a bit more visible. 
CGContextSetLineWidth(context, 2.0); 

// Draw a bezier curve with end points s,e and control points cp1,cp2 
CGPoint s = CGPointMake(30.0, 120.0); 
CGPoint e = CGPointMake(300.0, 120.0); 
CGPoint cp1 = CGPointMake(120.0, 30.0); 
CGPoint cp2 = CGPointMake(210.0, 210.0); 
CGContextMoveToPoint(context, s.x, s.y); 
CGContextAddCurveToPoint(context, cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y); 
CGContextStrokePath(context); 

Esperamos que ayuda a empezar a utilizarla;)

+1

phix23: gracias por la respuesta extremadamente útil. Si quiero una curva interpolada sin problemas, ¿tendré que desarrollar un algoritmo para eso? Quiero que la curva generada utilizando el menor número de vértices posible. – Brendan

+0

Hola @ phix23 por favor mira esto http://stackoverflow.com/questions/20881721/calculate-controlpoints-while-drawing-in-ios y por favor da tu consejo de experto – Ranjit

10

Si desea permanecer en el objetivo-c, puede usar el método addCurveToPoint: controlPoint1: controlPoint2: de UIBezierPath. También puede usar una función con nombre similar con CGPaths. Al usar curvas de bezier, necesita 4 puntos: punto de inicio, punto de finalización y un punto de control en cada extremo para definir la curva.

Una forma de definir esto es hacer que el usuario arrastre un dedo para definir los puntos de inicio y finalización, luego toque la pantalla en los puntos de control. Aquí hay una vista de ejemplo para manejar esto.

BezierView.h

enum { 
    BezierStateNone = 0, 
    BezierStateDefiningLine, 
    BezierStateDefiningCP1, 
    BezierStateDefiningCP2 
}; 
@interface BezierView : UIView { 
    CGPoint startPt, endPt, cPt1, cPt2; 
    UInt8 state; 
    UIBezierPath *curvePath; 
    @private 
    UITouch *currentTouch; 
} 
@property (nonatomic, retain) UIBezierPath *curvePath; 
@end 

BezierView.m

@interface BezierView 
@dynamic curvePath; 
- (UIBezierPath *)curvePath { 
    return [[curvePath retain] autorelease]; 
} 
- (void)setCurvePath:(UIBezierPath *)newPath { 
    id tmp = curvePath; 
    curvePath = [newPath retain]; 
    [tmp release]; 
    state = BezierStateNone; 
    [self setNeedsDisplay]; 
} 
- (void)_updateCurve { 
    UIBezierPath *path = [UIBezierPath bezierPath]; 
    [path moveToPoint:startPt]; 
    [path addCurveToPoint:endPt controlPoint1:cPt1 controlPoint2:cPt2]; 
} 
- (void)_calcDefaultControls { 
    if(ABS(startPt.x - endPt.x) > ABS(startPt.y - endPt.y)) { 
     cPt1 = (CGPoint){(startPt.x + endPt.x)/2, startPt.y}; 
     cPt2 = (CGPoint){cPt1.x, endPt.y}; 
    } else { 
     cPt1 = (CGPoint){startPt.x, (startPt.y + endPt.y)/2}; 
     cPt2 = (CGPoint){endPt.x, cPt1.y}; 
    } 
} 
- (void)drawRect:(CGRect)rect { 
    UIBezierPath *path = self.curvePath; 
    if(path) [path stroke]; 
} 
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    if(currentTouch) return; 
    if(state == BezierStateNone) { 
     state = BezierStateDefiningLine; 
     currentTouch = [touches anyObject]; 
     startPt = [currentTouch locationInView:self]; 
    } else if(state == BezierStateDefiningCP1) { 
     currentTouch = [touches anyObject]; 
     cPt1 = [currentTouch locationInView:self]; 
     [self _updateCurve]; 
    } else if(state == BezierStateDefiningCP2) { 
     currentTouch = [touches anyObject]; 
     cPt2 = [currentTouch locationInView:self]; 
     [self _updateCurve]; 
    } 
} 
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    if(!currentTouch) return; 
    if(state == BezierStateDefiningLine) { 
     endPt = [currentTouch locationInView:self]; 
     [self _calcDefaultControls]; 
     [self _updateCurve]; 
    } else if(state == BezierStateDefiningCP1) { 
     cPt1 = [currentTouch locationInView:self]; 
     [self _updateCurve]; 
    } else if(state == BezierStateDefiningCP2) { 
     cPt2 = [currentTouch locationInView:self]; 
     [self _updateCurve]; 
    } 
} 
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    if(!currentTouch) return; 
    if(state == BezierStateDefiningLine) { 
     state = BezierStateDefiningCP1; 
    } else if(state == BezierStateDefiningCP1) { 
     state = BezierStateDefiningCP2; 
    } else if(state == BezierStateDefiningCP2) { 
     state = BezierStateNone; 
    } 
    currentTouch = nil; 
} 
- (void)touchesCanceled:(NSSet *)touches withEvent:(UIEvent *)event { 
    if(state == BezierStateDefiningLine) { 
     self.curvePath = nil; 
     self.state = BezierStateNone; 
    } 
    self.currentTouch = nil; 
} 
+0

no dibuja nada :( – ColdSteel