2016-05-17 132 views
1

如何绘制如图所示的圆弧,假设我有一个UIView作为可移动的直线的中点。如何通过3点绘制圆弧

enter image description here

enter image description here

我在CGPoint名lineStartPoint和结束点作为lineEndPoint店线的起点。

可以通过名为movePoint的CGPoint访问移动对象。

在此先感谢您的帮助。

+0

你要求在两点之间画一条弧线吗? –

+0

是的,通过中点运动 –

+0

你是否尝试过使用bezierPathWithArcCenter:CGPointMake? –

回答

4

下面是一个示例,说明如何计算bezierPathWithArcCenter:radius:startAngle:endAngle:clockwise:方法所需的参数。

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    // for example 
    CGPoint lineStartPoint = {100,100}; 
    CGPoint lineEndPoint = {100,200}; 
    CGPoint movingPoint = {30,150}; 


    CGFloat eps = 1e-5; 

    CGVector v1 = {movingPoint.x-lineEndPoint.x, movingPoint.y-lineEndPoint.y}; 
    CGFloat dist1 = sqrt(v1.dx*v1.dx + v1.dy*v1.dy); 
    v1.dx = v1.dx/dist1; 
    v1.dy = v1.dy/dist1; 

    CGVector v2 = {movingPoint.x-lineStartPoint.x, movingPoint.y-lineStartPoint.y}; 
    CGFloat dist2 = sqrt(v2.dx*v2.dx + v2.dy*v2.dy); 
    v2.dx = v2.dx/dist2; 
    v2.dy = v2.dy/dist2; 


    CGFloat det = v1.dx*v2.dy - v1.dy*v2.dx; 
    if (fabs(det) < eps) { 
     // the three points are collinear 
     // TODO: draw a line from lineStartPoint to lineEndPoint 
     return; 
    } 

    CGPoint mid1 = {(movingPoint.x+lineEndPoint.x)/2, (movingPoint.y+lineEndPoint.y)/2}; 
    CGPoint mid2 = {(movingPoint.x+lineStartPoint.x)/2, (movingPoint.y+lineStartPoint.y)/2}; 

    CGFloat b1 = v1.dx*mid1.x + v1.dy*mid1.y; 
    CGFloat b2 = v2.dx*mid2.x + v2.dy*mid2.y; 

    CGFloat centerX = v2.dy/det*b1 - v1.dy/det*b2; 
    CGFloat centerY = -v2.dx/det*b1 + v1.dx/det*b2; 

    CGPoint center = {centerX, centerY}; 
    CGFloat radius = sqrtf((movingPoint.x-center.x)*(movingPoint.x-center.x) + (movingPoint.y-center.y)*(movingPoint.y-center.y)); 
    CGFloat startAngle = atan2f(lineStartPoint.y-center.y, lineStartPoint.x-center.x); 
    CGFloat movingAngle = atan2f(movingPoint.y-center.y, movingPoint.x-center.x); 
    CGFloat endAngle = atan2f(lineEndPoint.y-center.y, lineEndPoint.x-center.x); 

    BOOL isClockwise; 
    if ((endAngle>startAngle && startAngle<movingAngle && movingAngle<endAngle) || 
     (endAngle<startAngle && !(endAngle<movingAngle && movingAngle<startAngle))) { 
     isClockwise = YES; 
    } else { 
     isClockwise = NO; 
    } 


    //Show results 

    CAShapeLayer* startPointLayer = [[CAShapeLayer alloc] init]; 
    startPointLayer.path = [UIBezierPath bezierPathWithArcCenter:lineStartPoint radius:2 startAngle:0 endAngle:2*M_PI clockwise:YES].CGPath; 
    [self.view.layer addSublayer:startPointLayer]; 

    CAShapeLayer* endPointLayer = [[CAShapeLayer alloc] init]; 
    endPointLayer.path = [UIBezierPath bezierPathWithArcCenter:lineEndPoint radius:2 startAngle:0 endAngle:2*M_PI clockwise:YES].CGPath; 
    [self.view.layer addSublayer:endPointLayer]; 

    CAShapeLayer* movingPointLayer = [[CAShapeLayer alloc] init]; 
    movingPointLayer.path = [UIBezierPath bezierPathWithArcCenter:movingPoint radius:2 startAngle:0 endAngle:2*M_PI clockwise:YES].CGPath; 
    [self.view.layer addSublayer:movingPointLayer]; 

    CAShapeLayer* arcLayer = [[CAShapeLayer alloc] init]; 
    [arcLayer setFillColor:[UIColor clearColor].CGColor]; 
    [arcLayer setStrokeColor:[UIColor blueColor].CGColor]; 
    arcLayer.path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:isClockwise].CGPath; 
    [self.view.layer addSublayer:arcLayer]; 

} 
+0

伟大的答案,以及我想知道的一件事,如果我想要移动移动点在创建90度对应于startPoint和endPoint的方向?总之,移动点只能在相反方向移动。 –

+0

你可以在这里回答http://stackoverflow.com/questions/37324822/restricting-pan-gesture-to-move-to-90-degree –

+0

我建议将这个问题的标题改为'通过3点画弧' – fabe