Отображение точек между системами координат в C#

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

Например, эта программа использует метод DrawSmiley для рисования смайлинки в области (-1, -1) - (1, 1), а затем использует преобразования для отображения этой области в четыре разных места в форме. Для рисования приложений, таких как этот, часто проще рисовать объекты с центром в начале координат, а затем перемещать результат. Для других приложений, таких как картографические, графические и графические программы, часто проще рисовать в другом пространстве координат (например, долгота / широта или годы / продажи), а затем преобразовывать результат в место, где вы хотите, чтобы рисунок отображался.

См. код, чтобы узнать, как работает метод DrawSmiley. Это в основном просто и использует Graphics методы, такие как FillEllipse, DrawEllipse и DrawArc, чтобы нарисовать смайлик.

Один неочевидный аспект DrawSmiley заключается в том, что преобразованные линии преобразуются. Например, предположим, что программа рисует смайлики, масштабируемые в 50 раз. Предварительно определенное перо, такое как Pens.Black, обычно имеет толщину 1, поэтому после масштабирования оно будет иметь ширину 50 пикселей и в результате получается большая черная капля. Масштабируемые ручки могут быть интересными, особенно если вы масштабируете по разным объемам по вертикали и по горизонтали, но это разрушает многие рисунки, включая этот.

Решение состоит в том, чтобы сделать пользовательское перо с толщиной 0. Специальное значение 0 заставляет программу рисовать ширину линии 1, независимо от того, как она масштабируется. См. Код для остальных деталей метода DrawSmiley.

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

Существует два основных подхода к определению преобразования, которое вы хотите использовать. Во-первых, вы можете использовать методы класса Graphics, такие как ResetTransform, ScaleTransform и RotateTransform, чтобы построить преобразование на один шаг в то время.

Второй подход заключается в создании объекта Matrix, представляющего преобразование. Внутренний класс Graphics использует объекты Matrix, чтобы представлять комбинацию преобразований в любом случае, поэтому этот подход просто пропускает шаги построения Matrix, вызывая ScaleTransform, RotateTransform и другие методы и напрямую строит Matrix. Это было бы трудно, за исключением того, что класс Matrix предоставляет очень полезный конструктор, который позволяет сопоставить прямоугольник с параллелограммом. В этом примере код отображает прямоугольник (-1, -1) - (1, 1) на параллелограмм в форме. Конструктор класса Matrix генерирует соответствующий объект Matrix для масштабирования и правильного перевода прямоугольника.

Следующий код показывает, как программа демонстрирует оба этих метода.

// Рисуем несколько смайликов в разных местах.
private void Form1_Paint(object sender, PaintEventArgs e)
{
    // Рисуем плавно.
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

    // **********
    // Метод 1: построение преобразования из простых.
    // В области (10, 10) - (110, 110).
    e.Graphics.ResetTransform();
    // Масштабируем в 50 раз.
    e.Graphics.ScaleTransform(50, 50);
    // Перевести на правильную позицию.
    e.Graphics.TranslateTransform(60, 60, MatrixOrder.Append);
    // Привлечь.
    DrawSmiley(e.Graphics);

    // **********
    // Способ 2. Сопоставление прямоугольника с параллелограммом.
    // В области (120, 10) - (220, 110).
    RectangleF from_rect = new RectangleF(-1, -1, 2, 2);
    PointF[] to_points =
    {
        new PointF(120, 10),    // Верхний левый.
        new PointF(220, 10),    // Верхний правый.
        new PointF(120, 110),   // Нижний левый.
    };
    Matrix map_matrix = new Matrix(from_rect, to_points);
    e.Graphics.Transform = map_matrix;
    // Привлечь.
    DrawSmiley(e.Graphics);

    // **********
    // Метод 2b: Использование искаженного параллелограмма.
    from_rect = new RectangleF(-1, -1, 2, 2);
    to_points = new PointF[]
    {
        new PointF(30, 120),    // Верхний левый.
        new PointF(110, 120),   // Верхний правый.
        new PointF(10, 220),    // Нижний левый.
    };
    map_matrix = new Matrix(from_rect, to_points);
    e.Graphics.Transform = map_matrix;
    // Привлечь.
    DrawSmiley(e.Graphics);

    // **********
    // Метод 2c: Использование инвертированного параллелограмма.
    from_rect = new RectangleF(-1, -1, 2, 2);
    to_points = new PointF[]
    {
        new PointF(120, 220),   // Верхний левый.
        new PointF(220, 220),   // Верхний правый.
        new PointF(120, 120),   // Нижний левый.
    };
    map_matrix = new Matrix(from_rect, to_points);
    e.Graphics.Transform = map_matrix;
    // Привлечь.
    DrawSmiley(e.Graphics);
}

Код начинается с первого метода. Он сбрасывает преобразование объекта Graphics, чтобы очистить любые предыдущие преобразования. (Это необязательно в этом примере, потому что преобразование еще не определено, но в целом вы должны быть осторожны, чтобы не оставить старые преобразования в действии после того, как они больше не нужны.)

Далее код использует метод ScaleTransform для масштабирования чертежа в 50 раз по горизонтали и по вертикали. Затем он использует TranslateTransform для перевода масштабированного результата на 60 пикселей вправо и 60 пикселей вниз. Обратите внимание на конечный параметр Append. Это делает объект Graphics применением трансляции после масштабирования. По какой-то сумасшедшей причине поведение по умолчанию заключается в добавлении новых преобразований до существующих, поэтому последующие преобразования будут выполняться ранее. Я не знаю, почему Microsoft сделал это по умолчанию, но так вы обходите это поведение.

После создания преобразований код просто вызывает DrawSmiley, и чертеж автоматически масштабируется и переводится в нужную позицию.

Далее код демонстрирует второй подход: построение Matrix. Он создает RectangleF, представляющий область в координатах рисования (часто называемую «мировыми координатами»), где будет нарисован смайлик. Затем он создает массив из трех структур PointF, указывающий, где на объекте Graphics должен отображаться прямоугольник. Этот массив определяет верхний левый, верхний правый и нижний левый углы параллелограмма в этом порядке, а конструктор Matrix определяет, где четвертый угол должен быть неявным. (Было бы более гибким, если бы вы могли сопоставить параллелограмм с параллелограммом вместо прямоугольника на параллелограмме. На самом деле было бы еще лучше, если бы вы могли сопоставить произвольный четырехугольник другому четырехугольник. Но это не так, как это работает. )

Программа использует исходный прямоугольник и параллелограмм назначения для создания объекта Matrix и устанавливает объект Graphics объекта Transform для этого объекта. Это определяет всю трансформацию. Он заменяет любое предыдущее преобразование, поэтому вам не нужно использовать ResetTransform.

Затем код снова смазывает смайлик, и он сопоставляется с новым пунктом назначения.

Далее код снова использует второй метод, чтобы нарисовать смайлик в параллелограмме, который не является прямоугольным.

Код заканчивается рисунком с параллелограммом, который имеет «верхний» и «нижний» углы с значениями Y, поэтому параллелограмм перевернут. В результате получается обратное смайлик. Этот метод особенно полезен, когда вы рисуете нечто вроде графика, где координаты Y данных возрастают вверх, но координаты формы увеличиваются вниз.

Источник: http://csharphelper.com/blog/2014/11/map-points-between-coordinate-systems-in-c/

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Adblock
detector