0

画像をトリミングできるように、特定の縦横比 (正方形、4x3、5x7、8x10 など) に合わせて選択用の四角形を描画する必要があります。touchesBegan/Moved 内で四角形の 4 つのコーナーを自由にドラッグすることを処理するかなり普通のコードがありますが、クリープしたり正確でなかったりすることなく、特定のアスペクト比に制限するのにかなりの時間を費やしています。

ここに私が現在持っているもののいくつかの擬似コードがあります:

// this assumes that the four hitPoints are already arranged in the desired aspect ratio 

CGPoint hitPoints[4]; // arranged botLeft=0, botRight=1, topRight=2, topLeft=3
CGPoint lastPoint;
CGRect cropRect;
int activeHitPoint;

#define kMinCropSize 20

- (void) touchesBegan
{
    lastPoint = [touches locationInView:self];
    activeHitPoint = [self getWhichPointTouched];
}

- (void) touchesMoved
{
    CGPoint thisPoint = [touches locationInView:self];
    float xDiff = thisPoint.x - lastPoint.x;
    float yDiff = thisPoint.y - lastPoint.y;

    float constrain = [self getAspectRatio];  // e.g.. 8x10  = 8/10 = 0.8 

    if(ABS(xDiff) > ABS(yDiff)){
        yDiff = xDiff * constrain;
        if(activeHitPoint == 1 || activeHitPoint == 3)
            yDiff *= -1;
    }else {
        xDiff = yDiff * constrain;
        if(activeHitPoint == 1 || activeHitPoint == 3)
            xDiff *= -1;
    }

    switch(activeHitPoint){
        case 0:
        if((hitPoints[0].x + xDiff > imageDisplayRect.origin.x) &&
           (hitPoints[0].x + xDiff + kMinCropSize < hitPoints[1].x) &&
           (hitPoints[0].y + yDiff > imageDisplayRect.origin.y) &&
           (hitPoints[0].y + yDiff + kMinCropSize < hitPoints[2].y)){
                hitPoints[0].x += xDiff;
                hitPoints[0].y += yDiff;
                hitPoints[3].x = hitPoints[0].x;
                hitPoints[1].y = hitPoints[0].y;
        }
        break;
        case 1:
        if((hitPoints[1].x + xDiff < imageDisplayRect.origin.x + imageDisplayRect.size.width) &&
           (hitPoints[1].x + xDiff - kMinCropSize > hitPoints[0].x) &&
           (hitPoints[1].y + yDiff > imageDisplayRect.origin.y) &&
           (hitPoints[1].y + yDiff + kMinCropSize < hitPoints[2].y)){
                hitPoints[1].x += xDiff;
                hitPoints[1].y += yDiff;
                hitPoints[2].x = hitPoints[1].x;
                hitPoints[0].y = hitPoints[1].y;
        }
        break;
        case 2:
        if((hitPoints[2].x + xDiff < imageDisplayRect.origin.x + imageDisplayRect.size.width) &&
           (hitPoints[2].x + xDiff - kMinCropSize > hitPoints[0].x) &&
           (hitPoints[2].y + yDiff < imageDisplayRect.origin.y + imageDisplayRect.size.height) &&
           (hitPoints[2].y + yDiff - kMinCropSize > hitPoints[1].y)){
                hitPoints[2].x += xDiff;
                hitPoints[2].y += yDiff;
                hitPoints[1].x = hitPoints[2].x;
                hitPoints[3].y = hitPoints[2].y;
        }
        break;
        case 3:
        if((hitPoints[3].x + xDiff > imageDisplayRect.origin.x) &&
           (hitPoints[3].x + xDiff + kMinCropSize < hitPoints[2].x) &&
           (hitPoints[3].y + yDiff < imageDisplayRect.origin.y + imageDisplayRect.size.height) &&
           (hitPoints[3].y + yDiff - kMinCropSize > hitPoints[0].y)){
                hitPoints[3].x += xDiff;
                hitPoints[3].y += yDiff;
                hitPoints[0].x = hitPoints[3].x;
                hitPoints[2].y = hitPoints[3].y;
        }
        break;
    }

    cropRect = CGRectMake(hitPoints[0].x, hitPoints[0].y, hitPoints[1].x - hitPoints[0].x, hitPoints[2].y - hitPoints[1].y);

    lastTouch = thisTouch;
    [self setNeedsDisplay];
}

このコードはほとんど機能しますが、丸め誤差があるかのように、あまり正確ではありません。時間の経過とともに適切な縦横比が失われます。これは驚くべきことです...そして、フロートを使用した理由...しかし、それは問題ではないようです.

4

0 に答える 0