Как реализовать масштабирование относительно произвольной точки? Реализую специализированный 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
168 +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 Апр 2024 в 13:22
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир