4

Premise: I'm building a cropping tool that handles two-finger arbitrary rotation of an image as well as arbitrary cropping.

Sometimes the image ends up rotated in a way that empty space is inserted to fill a gap between the rotated image and the crop rect (see the examples below).

I need to ensure that the image view, when rotated, fits entirely into the cropping rectangle. If it doesn't, I then need to re-transform the image (zoom it) so that it fits into the crop bounds.

Using this answer, I've implemented the ability to check whether a rotated UIImageView intersects with the cropping CGRect, but unfortunately that doesn't tell me if the crop rect is entirely contained in the rotated imageview. Hoping that I can make some easy modifications to this answer?

A visual example of OK:

enter image description here

and not OK, that which I need to detect and deal with:

enter image description here

Update: not working method

- (BOOL)rotatedView:(UIView*)rotatedView containsViewCompletely:(UIView*)containedView {

    CGRect rotatedBounds = rotatedView.bounds;
    CGPoint polyContainedView[4];

    polyContainedView[0] = [containedView convertPoint:rotatedBounds.origin toView:rotatedView];
    polyContainedView[1] = [containedView convertPoint:CGPointMake(rotatedBounds.origin.x + rotatedBounds.size.width, rotatedBounds.origin.y) toView:rotatedView];
    polyContainedView[2] = [containedView convertPoint:CGPointMake(rotatedBounds.origin.x + rotatedBounds.size.width, rotatedBounds.origin.y + rotatedBounds.size.height) toView:rotatedView];
    polyContainedView[3] = [containedView convertPoint:CGPointMake(rotatedBounds.origin.x, rotatedBounds.origin.y + rotatedBounds.size.height) toView:rotatedView];

    if (CGRectContainsPoint(rotatedView.bounds, polyContainedView[0]) &&
        CGRectContainsPoint(rotatedView.bounds, polyContainedView[1]) &&
        CGRectContainsPoint(rotatedView.bounds, polyContainedView[2]) &&
        CGRectContainsPoint(rotatedView.bounds, polyContainedView[3]))
        return YES;
    else
        return NO;
}
Community
  • 1
  • 1
brandonscript
  • 68,675
  • 32
  • 163
  • 220

1 Answers1

4

That should be easier than checking for intersection (as in the referenced thread).

The (rotated) image view is a convex quadrilateral. Therefore it suffices to check that all 4 corner points of the crop rectangle are within the rotated image view.

  • Use [cropView convertPoint:point toView:imageView] to convert the corner points of the crop rectangle to the coordinate system of the (rotated) image view.
  • Use CGRectContainsPoint() to check that the 4 converted corner points are within the bounds rectangle of the image view.

Sample code:

- (BOOL)rotatedView:(UIView *)rotatedView containsCompletely:(UIView *)cropView {

    CGPoint cropRotated[4];
    CGRect rotatedBounds = rotatedView.bounds;
    CGRect cropBounds = cropView.bounds;

    // Convert corner points of cropView to the coordinate system of rotatedView:
    cropRotated[0] = [cropView convertPoint:cropBounds.origin toView:rotatedView];
    cropRotated[1] = [cropView convertPoint:CGPointMake(cropBounds.origin.x + cropBounds.size.width, cropBounds.origin.y) toView:rotatedView];
    cropRotated[2] = [cropView convertPoint:CGPointMake(cropBounds.origin.x + cropBounds.size.width, cropBounds.origin.y + cropBounds.size.height) toView:rotatedView];
    cropRotated[3] = [cropView convertPoint:CGPointMake(cropBounds.origin.x, cropBounds.origin.y + cropBounds.size.height) toView:rotatedView];

    // Check if all converted points are within the bounds of rotatedView:
    return (CGRectContainsPoint(rotatedBounds, cropRotated[0]) &&
            CGRectContainsPoint(rotatedBounds, cropRotated[1]) &&
            CGRectContainsPoint(rotatedBounds, cropRotated[2]) &&
            CGRectContainsPoint(rotatedBounds, cropRotated[3]));
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • After spending 20 minutes on it, I realized I'm still going about it backwards. See q. for the code I'm working with .. the trouble here is I need to check that the cropRect points are inside the polygon - but you can't use CGRectContainsPoint for that. I also can't use the crop view itself because the view is slightly larger than the images it displays on screen (edge insets and such). – brandonscript Nov 08 '14 at 21:44
  • @remus: You convert the image view corner points to the window coordinates. But you should convert the crop rect corner points to the image view coordinates. – Martin R Nov 08 '14 at 21:56
  • For brevity's sake, I'm trying to do it with the crop view instead of the rect, but it's still not behaving correctly. I'm clearly missing something about the convertPoint logic in here. Am I even doing this correctly? – brandonscript Nov 08 '14 at 22:34
  • @remus: I think you are converting the wrong coordinates. I have added now some code (quite similar to yours) which seems to work. – Martin R Nov 08 '14 at 22:43