在Objective C中获取两个点之间的所有X,Y坐标

3

如何获取两点之间的所有X,Y坐标。我想在Objective C中以对角线模式移动一个UIButton。例如,将UIButton从位置“点A”移动到位置“点B”。

                         .Point B



    . Point A

提前感谢您。

4个回答

8

您可以使用Bresenham直线算法

这是一个稍微简化的版本,我已经使用了多次

+(NSArray*)getAllPointsFromPoint:(CGPoint)fPoint toPoint:(CGPoint)tPoint
{
    /*Simplified implementation of Bresenham's line algoritme */
    NSMutableArray *ret = [NSMutableArray array];
    float deltaX = fabsf(tPoint.x - fPoint.x);
    float deltaY = fabsf(tPoint.y - fPoint.y);
    float x = fPoint.x;
    float y = fPoint.y;
    float err = deltaX-deltaY;

    float sx = -0.5;
    float sy = -0.5;
    if(fPoint.x<tPoint.x)
        sx = 0.5;

    if(fPoint.y<tPoint.y)
        sy = 0.5;
    do {
        [ret addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]];
        float e = 2*err;
        if(e > -deltaY)
        {
            err -=deltaY;
            x +=sx; 
        }
        if(e < deltaX)
        {
            err +=deltaX;
            y+=sy;
        }
    } while (round(x)  != round(tPoint.x) && round(y) != round(tPoint.y));
    [ret addObject:[NSValue valueWithCGPoint:tPoint]];//add final point
    return ret;
}

如果你只是想将UIControl从一个位置动画到另一个位置,可以使用UIAnimation

[UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveLinear animations:^{
    btn.center = CGPointMake(<NEW_X>, <NEW_Y>)
} completion:^(BOOL finished) {

}];

为什么 sx 要等于0.5而不是1? - hoangpx

7

您应该使用Core Animation来完成此操作。只需要为您的UIButton指定新的起点位置,Core Animation会自行完成其余部分:

   [UIView animateWithDuration:0.3 animations:^{
       CGRect frame = myButton.frame;
       frame.origin = CGPointMake(..new X.., ..new Y..);
       myButton.frame = frame;
   }];

1
这个版本的Bresenham直线算法适用于水平线:
+ (NSArray*)getAllPointsFromPoint:(CGPoint)fPoint toPoint:(CGPoint)tPoint {

    /* Bresenham's line algorithm */

    NSMutableArray *ret = [NSMutableArray array];

    int x1 = fPoint.x;
    int y1 = fPoint.y;
    int x2 = tPoint.x;
    int y2 = tPoint.y;

    int dy = y2 - y1;
    int dx = x2 - x1;
    int stepx, stepy;

    if (dy < 0) { dy = -dy;  stepy = -1; } else { stepy = 1; }
    if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }
    dy <<= 1;        // dy is now 2*dy
    dx <<= 1;        // dx is now 2*dx

    [ret addObject:[NSValue valueWithCGPoint:CGPointMake(x1, y1)]];

    if (dx > dy)
    {
        int fraction = dy - (dx >> 1);  // same as 2*dy - dx
        while (x1 != x2)
        {
            if (fraction >= 0)
            {
                y1 += stepy;
                fraction -= dx;          // same as fraction -= 2*dx
            }
            x1 += stepx;
            fraction += dy;              // same as fraction -= 2*dy
            [ret addObject:[NSValue valueWithCGPoint:CGPointMake(x1, y1)]];

        }
    } else {
        int fraction = dx - (dy >> 1);
        while (y1 != y2) {
            if (fraction >= 0) {
                x1 += stepx;
                fraction -= dy;
            }
            y1 += stepy;
            fraction += dx;
            [ret addObject:[NSValue valueWithCGPoint:CGPointMake(x1, y1)]];
        }
    }

    return ret;
}

更新:这实际上是简单的数学问题,找到由两个点构成的直线上的点,以下是我的算法:

+ (NSArray*)getNumberOfPoints:(int)num fromPoint:(CGPoint)p toPoint:(CGPoint)q {

    NSMutableArray *ret = [NSMutableArray arrayWithCapacity:num];

    float epsilon = 1.0f / (float)num;
    int count = 1;

    for (float t=0; t < 1+epsilon && count <= num ; t += epsilon) {
        float x = (1-t)*p.x + t*q.x;
        float y = (1-t)*p.y + t*q.y;
        [ret addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]];
        count++;
    }

    // DDLogInfo(@"Vector: points made: %d",(int)[ret count]);
    // DDLogInfo(@"Vector: epsilon: %f",epsilon);
    // DDLogInfo(@"Vector: points: %@",ret);

    return [ret copy];

}

1
对于Swift 3.0,
    func findAllPointsBetweenTwoPoints(startPoint : CGPoint, endPoint : CGPoint) {
        var allPoints :[CGPoint] = [CGPoint]()

        let deltaX = fabs(endPoint.x - startPoint.x)
        let deltaY = fabs(endPoint.y - startPoint.y)

        var x = startPoint.x
        var y = startPoint.y
        var err = deltaX-deltaY

        var sx = -0.5
        var sy = -0.5
        if(startPoint.x<endPoint.x){
            sx = 0.5
        }
        if(startPoint.y<endPoint.y){
            sy = 0.5;
        }

        repeat {
            let pointObj = CGPoint(x: x, y: y)
            allPoints.append(pointObj)

            let e = 2*err
            if(e > -deltaY)
            {
                err -= deltaY
                x += CGFloat(sx)
            }
            if(e < deltaX)
            {
                err += deltaX
                y += CGFloat(sy)
            }
        } while (round(x)  != round(endPoint.x) && round(y) != round(endPoint.y));

        allPoints.append(endPoint) 
}

你好,Nilesh,感谢你的回答。这对我们非常有帮助,但是该函数只能在直线上给出每个x和y坐标。但是我们需要曲线上两点之间的x和y坐标,请问你能指导我如何实现吗? - himen patel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接