Rectangle::aspectRatio


#1

What about adding a method in your new template Rectangle class:

/** This is an handy method to get the width / height ratio */
T ar(const bool invert = false) const { return invert ? height / width : width / height; }

And also, please, oh please, let x and y public in the Point class (it’s such a pain to type pos.getX() instead of pos.x for no additional safety).


#2

Ok, but I think I’ll give it a more intelligible name than “ar”!

Not convinced about the point request… When I changed my code to use more Points, I found that most of the operations where I used to do the math on x and y co-ords could be replaced by manipulating the Point objects directly, rather than by pulling out their x and y values.


#3

Yes, my mistake I’ve put aspectRatio in my code, but I’m so used to visualassist that I usually only type the initials.

About Point, well, it’s because you’ve removed most method with the x, y params for the Point based method, but some still exists (like drawImageTransformed, or drawImageAt), so for the interim step, it’s a pain to replace “x, y” by “pt.getX(), pt.getY()”. Anyway, it’s not that important, but I don’t really think the “get/set” here are useful at all, as the point x and y member will never change.


#4

Well, it’s not actually an immutable class - if it was, then I’d be happy to make x and y const and expose them, but it just feels wrong in something like this.


#5

I meant, the point class will always have a “x” and “y” member (it’s unlikely you’ll change this, am I right?)
Anyway, the Point class is the classroom example where private member aren’t always welcome.


#6

Up for this feature, here’s another code:

    /** Get the proportional dimension while respecting the rectangle aspect ratio. */
    ValueType getProportionalWidth (const ValueTree height) const throw()                      { return height * w / h; }
    /** Get the proportional dimension while respecting the rectangle aspect ratio. */
    ValueType getProportionalHeight (const ValueTree width) const throw()                      { return width * h / w; }

#7

I’m afraid I don’t understand the description, or what you might use it for?


#8

Well, looking at the code I’ve written, I find this pattern multiple time:

Rectangle bounds = getBounds();
float ar = bounds.getWidth() / bounds.getHeight();
g.drawImage(img1, ar * getHeight() / 2, getHeight() / 2, ....); // Keep aspect ratio for the image (drawImageTransformed doesn't do this) 
g.drawImage(img2, ar * getHeight() / 2, getHeight() / 2, ....); // Keep aspect ratio for the image (drawImageTransformed doesn't do this) 

or 
resized()
{
     comp->setBounds(...);
     otherComponent->setBounds(comp->getRight(), comp->getY(), 64, comp->getAspectRatio() * 64); // Want the otherComponent to be proportional to comp in height but 64px wide
}

This can be rewritten more explicitely to :
g.drawImage(img, getBounds().getProportionalWidth(getHeight() / 2), getHeight() / 2);

or
otherComponent->setBounds(comp->getRight(), comp->getY(), 64, comp->getProportionalWidth(64)); // Want the otherComponent to be proportional to comp in height but 64px wide

#9

Sorry - don’t like that at all. The method itself is too confusing, and in your usage example, it actually makes the code less readable than it was before, IMHO.


#10

In fact, every time you compute an aspect ratio, you’re likely to multiply it by a number to get a proportion (else, why would you need aspect ratio anyway ?)
This means that you always do:
getAspectRatio() * height or getInvAspectRatio() * width

This was to avoid this (a function that compute ar * height or width / ar would save few lines).