2016-05-17 227 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