algorithm - referencia - ¿Cómo escalo un rectángulo al tamaño máximo posible dentro de otro rectángulo?
como reducir el tamaño de un bloque en autocad (5)
Tengo un rectángulo fuente y un rectángulo de destino. Necesito encontrar la escala máxima a la que se puede escalar la fuente mientras se ajusta dentro del rectángulo de destino y manteniendo su relación de aspecto original .
Google encontró one forma de hacerlo, pero no estoy seguro de si funciona en todos los casos. Aquí está mi solución hecha en casa:
- Calcula altura / ancho para cada rectángulo. Esto le da a las pendientes de las diagonales
msrc
ymdest
. - Si
msrc < mdst
,msrc < mdst
ancho de la fuente para que se ajuste al ancho del destino (y la altura de la escala en la misma proporción) - De lo contrario, escale la altura de la fuente para que se ajuste a la altura del destino (y el ancho de la escala en la misma proporción)
Buscando otras posibles soluciones a este problema. ¡Ni siquiera estoy seguro de si mi algoritmo funciona en todos los casos!
- Calcular el menor de
destWidth / srcWidth
ydestHeight / srcHeight
- Escala por eso
editar es, por supuesto, lo mismo que tu método, con las piezas de la fórmula movidas. Mi opinión es que esto es más claro semánticamente, pero es solo eso, una opinión.
Las otras respuestas tienen el riesgo de generar una división por cero excepción cuando el sourceWidth o sourceHeight se vuelve cero. Para salvaguardarnos de esto, deberíamos reescribir la comparación en una expresión múltiple matemáticamente equivalente. Además, la condición de borde adicional para capturar el escenario de escala infinita.
Además de tener la escala, realmente quería las dimensiones del rectángulo objetivo, por lo tanto, aquí proporcionaré el cálculo de la escala y el cálculo del rectángulo objetivo.
Debido a la condición de borde infinito, creo que el rectángulo objetivo será más robusto / útil:
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;
}
Otra opción podría ser escalar al ancho máximo y luego verificar si la altura de la escala es mayor que la altura máxima permitida y, si es así, escalar por altura (o viceversa):
scale = (dst.width / src.width);
if (src.height * scale > dst.height)
scale = dst.height / src.height;
Creo que esta solución es más corta, más rápida y más fácil de entender.
Si todas las dimensiones no son cero, usaría el siguiente código (que esencialmente coincide con su código).
scaleFactor = (outerWidth / outerHeight > innerWidth / innerHeight)
? outerHeight / innerHeight
: outerWidth / innerWidth
Esto también se puede modificar para permitir que cualquier dimensión sea cero si es necesario.
scale = min( dst.width/src.width, dst.height/src.height)
Este es su enfoque pero escrito más limpiamente.