Как реализовать масштабирование относительно произвольной точки? Реализую специализированный 2D-редактор в .NET. Хочу реализовать масштабирование относительно курсора.
В GDI+ у класса Graphics есть замечательное свойство Transform, которое позволяет с помощью аппарата аффинных преобразований в матричной форме реализовать то, что мне нужно. Во всех книжках пишут, что для масштабирования относительно произвольной точки необходимо:выполнить преобразование смещения так, чтобы точка относительно которой масштабируем сместилась в начало координатвыполнить непосредственно масштабирование относительно начала координатвыполнить преобразование смещение так, чтобы начало координат сместилось в исходную точку.
То есть в рамках моего приложения достаточно правильным образом менять матрицу Transform при вращении колесика мыши.
Делаю так:public class DrawingAreaControl : UserControl
{
public DrawingAreaControl()
{
DoubleBuffered = true;
transform = new Matrix();
}
public Matrix transform { get; set; }

protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.Transform = transform;
base.OnPaint(e);
}
const float SCALE_MUL = 1.05f;
protected override void OnMouseWheel(MouseEventArgs e)
{
base.OnMouseWheel(e);
transform.Multiply(new Matrix(1, 0, 0, 1, e.Location.X, e.Location.Y));
transform.Multiply(e.Delta > 0 ?
new Matrix(SCALE_MUL, 0, 0, SCALE_MUL, 0, 0) :
new Matrix(1 / SCALE_MUL, 0, 0, 1 / SCALE_MUL, 0, 0));
transform.Multiply(new Matrix(1, 0, 0, 1, -e.Location.X, -e.Location.Y));
Invalidate();
}
}
но это не работает так как надо. После нескольких масштабирований, рисунок под мышкой начинает убегать и уже нет нужного масштабирования относительно курсора.
По любому это из-за неправильного расчета преобразований в начало координат и обратно.
Как вычислить их, чтобы работало правильно?

21 Авг 2019 в 06:11
145 +1
1
Ответы
1

Проблема заключается в том, что вы неправильно компенсируете смещение при выполнении преобразований относительно курсора. Вместо этого, вам нужно сначала выполнить преобразование относительно курсора, а затем отменить это преобразование для коррекции расположения курсора на холсте.

Приведу пример ваших методов с исправлениями:

protected override void OnMouseWheel(MouseEventArgs e)
{
base.OnMouseWheel(e);
Matrix translationMatrix = new Matrix();
translationMatrix.Translate(e.Location.X, e.Location.Y);
Matrix scaleMatrix = new Matrix();
scaleMatrix.Scale(e.Delta > 0 ? SCALE_MUL : 1 / SCALE_MUL, e.Delta > 0 ? SCALE_MUL : 1 / SCALE_MUL);
Matrix revertTranslationMatrix = new Matrix();
revertTranslationMatrix.Translate(-e.Location.X, -e.Location.Y);
Matrix tempMatrix = new Matrix();
tempMatrix.Multiply(revertTranslationMatrix);
tempMatrix.Multiply(scaleMatrix);
tempMatrix.Multiply(translationMatrix);
transform.Multiply(tempMatrix);
Invalidate();
}

Таким образом, вы сначала выполняете преобразование относительно курсора, затем масштабирование и, наконец, отменяете преобразование относительно курсора. Это должно исправить проблему с уходом изображения от курсора при масштабировании.

20 Апр в 13:22
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Название заказа не должно быть пустым
Введите email
Бесплатные доработки
Гарантированные бесплатные доработки
Быстрое выполнение
Быстрое выполнение от 2 часов
Проверка работы
Проверка работы на плагиат
Интересные статьи из справочника
Поможем написать учебную работу
Название заказа не должно быть пустым
Введите email
Доверьте свою работу экспертам
Разместите заказ
Наша система отправит ваш заказ на оценку 92 648 авторам
Первые отклики появятся уже в течение 10 минут
Прямой эфир