Take the 2-minute tour ×
Mathematics Stack Exchange is a question and answer site for people studying math at any level and professionals in related fields. It's 100% free, no registration required.

This is a simple enough problem that I could just cover all corner cases, but I was wondering if there was an elegant way to do this.

Here is the starting point. It finds out which side of the image is taller and then sets that to match up with the size of the "b" boundary. So if it's wider than it is tall it'll set it to be the width of the boundary.

void setBoundsMaxSize(Drawable d, Rect b) {
    int bWidth = b.right - b.left + 1;
    int bHeight = b.bottom - b.top + 1;
    if(d.width() > d.height()) {
        // it's wider than it is tall
        int newHeight = bWidth * d.height() / d.width();
        int padding = (bHeight - newHeight) / 2;
        d.setBounds(b.left, b.top+padding, b.right, b.bottom-padding);
    } else {
        // the width and height are the same or it's taller than it is wide.
        int newWidth = bHeight * d.width() / d.height();
        int padding = (bWidth - newWidth) / 2;
        d.setBounds(b.left+padding, b.top, b.right-padding, b.bottom);
    }
}

This algorithm works if the "b" boundary is square. However, if it's not then I'll need special cases to check if the newWidth and newHeight are inside the boundary. If they're not then I'll need to shrink it down to fit.

So I'd be handling 4 separate special cases.

I was just curious if there was a cleaner way to deal with this.

EDIT:

FWIW this is what I've got now. It's pretty good, but I still wonder if there's a simple way to know at the beginning that I don't need to try one and then do the other.

public static void setBoundsMaxSize(Drawable d, Rect b) {
    if(d.getIntrinsicWidth() > d.getIntrinsicHeight()) {
        // it's wider than it is tall
        shrinkVert(d,b);
    } else {
        // the width and height are the same or it's taller than it is wide.
        shrinkHoriz(d,b);
    }
}

private static void shrinkVert(Drawable d, Rect b) {
    int bWidth = b.right - b.left + 1;
    int newHeight = bWidth * d.getIntrinsicHeight() / d.getIntrinsicWidth();
    int bHeight = b.bottom - b.top + 1;
    if(newHeight > bHeight) {
        shrinkHoriz(d,b);
    } else {
        int padding = (bHeight - newHeight) / 2;
        d.setBounds(b.left, b.top+padding, b.right, b.bottom-padding);
    }
}

private static void shrinkHoriz(Drawable d, Rect b) {
    int bHeight = b.bottom - b.top + 1;
    int newWidth = bHeight * d.getIntrinsicWidth() / d.getIntrinsicHeight();
    int bWidth = b.right - b.left + 1;
    if(newWidth > bWidth) {
        shrinkVert(d,b);
    } else {
        int padding = (bWidth - newWidth) / 2;
        d.setBounds(b.left+padding, b.top, b.right-padding, b.bottom);
    }
}
share|improve this question
    
The 'minimum bounding rectangle' problem is very close to your problem en.wikipedia.org/wiki/Minimum_bounding_box_algorithms assuming your object is a convex polygon then the minimum bounding rectangle and the convex polygon will have a parallel side. (Just throwing that out there) –  Peter Sheldrick Sep 6 '11 at 6:14

1 Answer 1

up vote 2 down vote accepted

Compare the aspect rations (width / height) to determine which dimension of the rectangle will be limiting. That requires about five lines of code:

if (d.width / d.height > b.width / b.height) {
  scale = b.width / d.width 
} else {
  scale = b.height / d.height
}
newWidth = d.width * scale
newHeight = d.height * scale
share|improve this answer
    
Very nice. I knew there was something like that. –  HappyEngineer Sep 6 '11 at 6:15

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.