Мой предыдущий ответ немного грубоват, и я сделал несколько глупых ошибок, будучи слишком неформальным.Позвольте мне попробовать еще раз:)
Итак, у вас есть матрица 3x3, представляющая преобразование вида, которое выглядит примерно так (если нет вращения):
[ sx 0 tx ]
viewMatrix = [ 0 sy tx ]
[ 0 0 1 ]
sx
и sy
представляют коэффициент масштабирования.Т.е. параметры зума.tx
и ty
представляют перевод.Т.е. параметры панорамирования.
(Примечание: вы действительно можете заменить sx
и sy
на s
везде, так как sx = sy
в вашем случае)
Это легко продемонстрировать, умножив его на точку p
в однородных координатах.
[ sx 0 tx ] [ px ] [ sx * px + tx ]
[ 0 sy tx ] * [ py ] = [ sy * py + ty ]
[ 0 0 1 ] [ 1 ] [ 1 ]
Теперь, если вы визуализируете окно просмотра, его координаты центра будут в [-tx -ty]<sup>T</sup>
.
Кроме того, если размер холста равен (width, height)
, тогда размер области просмотра будет (width/sx, height/sy)
(поскольку размер области просмотра обратно масштабируется относительно масштаба нарисованной геометрии).
_______________
| | ^
| . [-tx] | | height/sy
| [-ty] | |
|_______________| v
width/sx
<--------------->
Когдаувеличение или уменьшение относительно точки привязки sx, sy, tx и ty все изменится.(Если вам нужна помощь с этим расчетом, просто добавьте комментарий, и я помогу. Я немного занят: -))
Так что теперь шаги просты
- ПрименитьВаш код увеличения / уменьшения масштаба матрицы (т. е. вычисление sx, sy, tx, ty)
- Зафиксируйте минимальный коэффициент масштабирования:
s = max(s, 1.0); sx = sy = s
Если границы области просмотра пересекаютсяграницы холста, переведите окно просмотра, пока оно не станет полностью видимым.Возможно, что-то примерно так:
tx = clamp(tx, width * (1/sx - 1)/2, width * (1 - 1/sx)/2)
ty = clamp(ty, height * (1/sy - 1)/2, height * (1 - 1/sy)/2)
(Просто проверьте мою математику в конце. Я сделал это вспешка: P)