WinForm Drawing2D Graphics - Отразить ось Y - PullRequest
0 голосов
/ 17 января 2019

Проблема с отсутствием встроенной функции для переворачивания оси Y в .NET Drawing2D хорошо известна. К сожалению, инженеры-механики, инженеры-строители и другие инженеры так и не начали рисовать свои чертежи "вверх ногами" ... Поскольку я хочу провести серьезный рефакторинг своего старого кода, я спрашиваю о лучшем выходе этой проблемы. Я не хочу «изобретать колесо», если это было сделано раньше.

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

Чтобы не допустить распространенных проверенных предложений, вот несколько известных мне обходных путей:

1) ПЕРЕЧИСЛИТЬ Y КООРДИНАТУ НА КАЖДОМ ПРОИЗВОДСТВЕ РИСУНКА

Public Function GetYinCCS (Y as Single, ContainerHeight as Int32) As Single
    Dim RetVal as Single
        RetVal = ContainerHeight - Y
    Return RetVal
End Funciton

...
Dim MyCartesianRectangle as New RectangleF(120,GetYinCCS(75),400,200)
g.DrawRectangle(Pens.Black, MyCartesianRectangle)

Это может выглядеть прекрасно, и я много раз использовал его на протяжении многих лет. Но это довольно безумно, даже если вы делаете слой из своих собственных подпрограмм для рисования, например:

Public Sub DrawRec (RPen as Pen, Rec as RectangleF, g as Graphics, bm as Bitmap)
    g.DrawRectangle(RPen, Rectangle.Round(New Rectangle(Rec.X, bm.Height - Rec.Y, Rec.Width, Rec.Height)))
End Sub

Вы должны делать это везде - в статической живописи, в событии _Paint, с указанием местоположения мыши по событиям мыши и т. Д. И т. Д. А это партия работы и отладка - ужас ... И использование Функции преобразования в перевернутой-раскрученной среде - тоже настоящее "развлечение".

2) SCALING Y AXIS

Так почему бы просто не перевернуть ось Y?

    g.TranslateTransform(0, bm.Height)    ' move graphics to the new start of Coordinate System
    g.ScaleTransform(1, -1)               ' flip the graphics vertically (along horizontal axis) 

Отлично! Нет, ой, теперь строки перевернуты ... Но это можно решить с помощью пары преобразований в вашем личном методе DrawStr, например:

    g.ScaleTransform(1, -1)               ' flip the flipped bitmap vertically
    g.TranslateTransform(0, -bm.Height)
    g.DrawString("My string", Me.Font, Brushes.Navy, Pt)
    g.TranslateTransform(0, bm.Height)
    g.ScaleTransform(1, -1)               ' flip the flipped-flipped bitmap vertically - back

Всё в порядке. Но попробуйте нарисовать нить в вертикальном направлении снизу вверх или под углом, и вы, скорее всего, будете стягивать волосы с головы. И почему я не использовал g.ResetTransform ()? Потому что я не мог, по крайней мере, в текущей настройке. Я бы потерял свой Y-flip, и если бы я использовал функции преобразования для панорамирования и масштабирования, я бы тоже потерял его.

Давайте не будем забывать, что ваша мышь тоже говорит на другом языке Y, и не забывайте, что _Paint событие e.graphics тоже должно быть ScaleTransformed ...

Возможно, написание Reset функции, которая будет выполнять ResetTransform () и затем Y-Flip, а затем трансформировать масштабирование и панорамирование (чтобы получить «стартовую» настройку вашего пространства для рисования), может помочь. Это должно быть сделано после каждой функции, которая сама должна выполнять функции преобразования (такие как угловая DrawString).

3) НИЗКИЙ УРОВЕНЬ GDI Y-SWAP

Я где-то читал о том, как сделать низкоуровневое отражение для координаты Y, я пытался проверить это, но безуспешно. Я не смог найти его сейчас. Как бы то ни было, было предупреждение о серьезном отступлении. РЕДАКТИРОВАТЬ: Вот одно место, упоминающее этот метод: SetViewportOrgEx ()


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

Для ясности я говорю о решениях в среде .NET.

...