1

How to draw an arc as shown in the image as suppose i have a UIView as the middle point of the line which is movable.

enter image description here

enter image description here

i had store line's start point in CGPoint name lineStartPoint and end point as lineEndPoint.

the moving object can be accessed through CGPoint named movingPoint.

Thanks in advance for help.

Bhargav Kukadiya
  • 418
  • 7
  • 17

1 Answers1

5

Here is an example how to calculate the required parameters for the bezierPathWithArcCenter:radius:startAngle:endAngle:clockwise: method.

- (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];

}
fabe
  • 718
  • 5
  • 10
  • great answer, well one thing I want to know that if I want to move the movingPoint in such direction that creates 90 degrees corresponds to startPoint and endPoint? In short, moving point can be moved in the lines opposites direction only. – Bhargav Kukadiya May 20 '16 at 03:42
  • you can answer here http://stackoverflow.com/questions/37324822/restricting-pan-gesture-to-move-to-90-degree – Bhargav Kukadiya May 20 '16 at 06:42
  • I suggest to change the title of this question to 'Draw arc through 3 points' – fabe May 20 '16 at 11:42