web-dev-qa-db-fra.com

Comment puis-je redimensionner un rectangle à la taille maximale possible dans un autre rectangle?

J'ai un rectangle source et un rectangle de destination. J'ai besoin de trouver l'échelle maximale à laquelle la source peut être mise à l'échelle tout en s'intégrant dans le rectangle de destination et en conservant son rapport de format d'origine .

Google a trouvé un moyen de le faire mais je ne suis pas sûr que cela fonctionne dans tous les cas. Voici ma solution maison:

  • Calculer la hauteur/largeur pour chaque rectangle. Cela donne les pentes des diagonales msrc et mdest.
  • Si msrc < mdst, redimensionnez la source width pour l’adapter à la destination width (et la hauteur de la balance selon le même rapport)
  • Sinon, mettez la source à l'échelle height en fonction de la destination height (et la largeur de la balance selon le même rapport)

Vous cherchez d'autres solutions possibles à ce problème. Je ne suis même pas sûr que mon algorithme fonctionne dans tous les cas!

54
Agnel Kurian
scale = min( dst.width/src.width, dst.height/src.height)

Ceci est votre approche mais écrit plus proprement.

109
tom10

Une autre option pourrait consister à redimensionner la largeur maximale, puis à vérifier si la hauteur redimensionnée est supérieure à la hauteur maximale autorisée et, le cas échéant, à la hauteur (ou vice versa):

scale = (dst.width / src.width);
if (src.height * scale > dst.height)
 scale = dst.height / src.height;

Je pense que cette solution est à la fois plus courte, plus rapide et plus facile à comprendre.

10
Guss

Si toutes les dimensions sont non nulles, j'utiliserais le code suivant (qui correspond essentiellement à votre code).

scaleFactor = (outerWidth / outerHeight > innerWidth / innerHeight) 
    ? outerHeight / innerHeight
    : outerWidth / innerWidth

Cela peut également être modifié pour permettre à toute dimension d'être égale à zéro si nécessaire.

1
Daniel Brückner
  1. Déterminez le plus petit de destWidth / srcWidth et destHeight / srcHeight
  2. Échelle par celle

edit bien sûr, c'est la même chose que votre méthode, les éléments de la formule étant déplacés. Mon opinion est que cela est plus clair sémantiquement, mais ce n'est que cela - une opinion.

1
AakashM

Les autres réponses risquent de générer une exception de division par zéro lorsque sourceWidth ou sourceHeight devient zéro. Pour nous protéger contre cela, nous devrions réécrire la comparaison en une expression multiple mathématiquement équivalente. En outre, une condition de bordure supplémentaire pour capturer le scénario à échelle infinie.

En plus d'avoir l'échelle, je voulais vraiment les dimensions du rectangle cible. Je vais donc vous fournir ici le calcul de l'échelle et le calcul du rectangle cible.

En raison de la condition Edge infini, je pense que le rectangle cible sera plus robuste/utile:

    if (sourceWidth == 0 && sourceHeight == 0) {
        // scale = Infinity;
        outputWidth = 0;
        outputHeight = 0;
        outputX = destWidth / 2;
        outputY = destHeight / 2;
    } else if (destWidth * sourceHeight > destHeight * sourceWidth) {
        scale = destHeight / sourceHeight;
        outputWidth = sourceWidth * destHeight / sourceHeight;
        outputHeight = destHeight;
        outputX = (destWidth - outputWidth) / 2;
        outputY = 0;
    } else {
        scale = destWidth / sourceWidth;
        outputWidth = destWidth;
        outputHeight = sourceHeight * destWidth / sourceWidth;
        outputX = 0;
        outputY = (destHeight - outputHeight) / 2;
    }
0
Stephen Quan