Координаты чертежа карты без искажений в C#
Сообщение
В этом примере используется следующий метод, чтобы сделать прямоугольник при рисовании координат прямоугольником в координатах устройства, делая прямоугольник рисования как можно большим, не искажая его.
// Карта из координат мира в координаты устройства // без искажений. private void SetTransformationWithoutDisortion(Graphics gr, RectangleF world_rect, RectangleF device_rect, bool invert_x, bool invert_y) { // Получите пропорции. float world_aspect = world_rect.Width / world_rect.Height; float device_aspect = device_rect.Width / device_rect.Height; // Астрономический прямоугольник для сохранения соотношения сторон. float world_cx = world_rect.X + world_rect.Width / 2f; float world_cy = world_rect.Y + world_rect.Height / 2f; if (world_aspect > device_aspect) { // Мировые координаты слишком короткие и ширины. // Сделайте их выше. float world_height = world_rect.Width / device_aspect; world_rect = new RectangleF( world_rect.Left, world_cy - world_height / 2f, world_rect.Width, world_height); } else { // Мировые координаты слишком высокие и тонкие. // Расширяем их. float world_width = device_aspect * world_rect.Height; world_rect = new RectangleF( world_cx - world_width / 2f, world_rect.Top, world_width, world_rect.Height); } // Сопоставьте новые координаты мира в координатах устройства. SetTransformation(gr, world_rect, device_rect, invert_x, invert_y); }
Этот метод сначала вычисляет пропорции (отношение ширины к высоте) для мира и прямоугольников устройства. Если мировое соотношение сторон больше, чем соотношение сторон устройства, то мировой прямоугольник относительно короткий и широкий по сравнению с прямоугольником устройства. В этом случае код вычисляет новую высоту, чтобы сделать мир прямоугольником выше, поэтому он имеет ту же форму, что и прямоугольник устройства. Он использует новую высоту, чтобы создать новый прямоугольник мира по центру.
И наоборот, если соотношение сторон в мире меньше, чем соотношение сторон устройства, тогда мировой прямоугольник относительно высокий и тонкий по сравнению с прямоугольником устройства. В этом случае код вычисляет новую ширину, чтобы сделать мир прямоугольником шире, поэтому он имеет ту же форму, что и прямоугольник устройства. Он использует новую ширину для создания нового прямоугольника мира, центрированного по сравнению с исходным.
В этот момент новый прямоугольник мира и прямоугольник устройства имеют одинаковые формы, поэтому программа просто вызывает метод SetTransformation, описанный в более ранняя публикация . Поскольку два прямоугольника имеют одинаковые пропорции, это преобразование не искажает область рисования.
Пример программы использует следующий код для демонстрации метода SetTransformationWithoutDisortion.
// Нарисуйте смайлик как можно больше без искажений. private void picCanvas_Paint(object sender, PaintEventArgs e) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; // Установите преобразование. Переверните вертикально. RectangleF drawing_rect = new RectangleF(-1, -1, 2, 2); const int margin = 4; Rectangle device_rect = new Rectangle( margin, margin, picCanvas.ClientSize.Width - 2 * margin, picCanvas.ClientSize.Height - 2 * margin); SetTransformationWithoutDisortion(e.Graphics, drawing_rect, device_rect, false, true); // Рисуем смайлик. DrawSmiley(e.Graphics); // Сбросьте преобразование и нарисуем вокруг него поле. e.Graphics.ResetTransform(); e.Graphics.DrawRectangle(Pens.Red, device_rect); }
Этот код создает мировой прямоугольник с -1 & le; X & le; 1 и -1 & le; Y & le; 1, потому что это область, в которой метод DrawSmiley рисует смайлик. Это делает прямоугольник устройства подходящим для PictureBox за вычетом маржи. Затем он вызывает SetTransformationWithoutDisortion для сопоставления координат мира с координатами устройства и вызывает метод DrawSmiley.