Система координат в GDI+
Пишу на C#. Возникла такая проблема: очень желательно направить ось Y вверх, а не вниз, как по-умолчанию в GDI. Игры с матрицами, ни к чему не приводят, т.к. в результате текст выводится вверх ногами...
Нашел вот такие вот API-функции для изменения системы координат:
SetMapMode
SetWindowOrg
SetViewportOrg
[их описание]
Есть ли этому какие-либо аналоги в .Net? Может быть как-то можно через Graphics? Гугл и MSDN молчат по этому поводу :(
Попытка номер два:
SizeF text_size = gfx.MeasureString(text, this.Font);
Matrix current = gfx.Transform;
Matrix new_matrix = current.Clone();
new_matrix.Multiply(new Matrix(1.0f, 0.0f, 0.0f, -1.0f, x, text_size.Height + y));
gfx.Transform = new_matrix;
gfx.DrawString(text, this.Font, Brushes.Red, 0.0f, 0.0f);
gfx.Transform = current;
}
private void Form1_Paint(object sender, PaintEventArgs e) {
Graphics gfx = e.Graphics;
Matrix mirror = new Matrix(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, (float)ClientRectangle.Height);
gfx.Transform = mirror;
gfx.DrawLine(Pens.Blue, new Point(10, 10), new Point(100, 100));
DrawText(gfx, "Sample text", 100.0f, 100.0f);
}
Но, придется использовать отдельную функцию для вывода текста использовать. При вращении координат вроде работает...
Большой спасибо, особенно за оперативность!!! :)
Ну и +1 в карму :)
y0 = Width - y1;
y0 - координата в обычной системе, где y изменяется сверху вниз
Width - высота экрана (или области вывода)
y1 - координата в обратной системе, где y изменяется снизу вверх
Матрица преобразования именно для этого и служит, только преобразованием занимается сама система - в идеале это делает графический ускоритель (но в GDI+ покачто этим занимается центральный процессор). К тому же она удобнее - задали один раз и погнали рисование в наших координатах :) А еще возможно масштабирование изображения и поворот. Вы хотите вспоминать ту систему уравнений с синусами и косинусами для поворота точки?
Кстати, Width - это ширина, будем считать, что вы имели в виду Height.
А Вы как-то по-другому представляете себе матрицу поворота, без синусов и косинусов?
У класса System.Drawing.Drawing2D.Matrix есть клевый метод Rotate. ;)
А по вопросу поворота или масштабирования, система уравнений, скорее всего, будет проигрывать преобразованию матрицы.
Который использует матрицу поворота с синусами и косинусами... :)
Иногда спускаюсь на более низкий уровень, и думаю в терминах матриц преобразований... Просто не совсем вижу смысл удобства такого изменения системы координат... Формировать матрицу, передавать её графическому конвейеру... Хотя... Наверно, Вы правы - одним преобразованием меньше, одним больше - производительность наверняка не пострадает, всё равно производит умножение...
Зависит от того - сколько раз. Ведь через подобный "фильтр" придется пропускать все точки, участвующие в построении сцены. Не слишком ли это большая цена за скорость? Тем более, еще не известно, сколько линий нужно построить. Если не больше 1000, то разницы не почуствовать.
y0 = Width - y1;
Хоть и не очень элегантный, но вариант. Да, порой стоит спуститься с небес на землю... о самом простом, я и не подумал :) Спасибо! :)
А по вопросу поворота или масштабирования, система уравнений, скорее всего, будет проигрывать преобразованию матрицы.
Мне не самоцель развернуть систему координат, потом нужно и дальше трансформировать координаты: смещение + масштабирование (точка обзора над картой). И лучше один раз "собрать" матрицу содержащую все нужные преобразования... чем делать последовательность маленьких преобразований... Да и удобнее матрицами это делать!
... Просто не совсем вижу смысл удобства такого изменения системы координат...
Можно ведь и синус вычислять вручную до меньшей точности, чем стандартный, быстрее будет :) Сейчас мне важно чтобы работало - а оптимизировать всегда можно!
Угу... и это заставляет глядеть в сторону чего-нибудь ускоренного, но DirectX не знаю совсем, а с OpenGL нет опыта работы в C#... нет времени разбираться - надо чтобы уже работало :)
Вот и приходится связываться со всякими GDI...
А нельзя ли просто все буквы шрифта при инициации перевернуть по вертикали?
В CreateFont экспериментировал со всеми углами. Не выходит...
Googlил, ничего не нашёл.
Есть соображение сам шрифт взять бинарно каждую букву отразить вертикально. Но, как это сделать?
В HTML-фильтрах шрифт можно делать зеркально отражённым. Но, неужели это делается не через преобразование матриц и шрифта, а блиттингом???
Вот и приходится связываться со всякими GDI...
Есть Windows Presentation Foundation (WPF). Он аппаратно ускоряется.
При инициализации чего?
Шрифт тут существует не зависимо от нас, это не OpenGL, где его нужно руками загружать и конструировать визуальные объекты. Здесь он уже встроен в графическую подсистему. Кроме того, шрифты сейчас используютс не растровые, а векторные - простым блитингом его не перевернешь (конечно, можно отрендерить текст и уже его вращать как хочется, видимо так HTML фильтр поступает).
Остается наиболее универсальный метод - аффинные преобразования.
Шрифт тут существует не зависимо от нас, это не OpenGL, где его нужно руками загружать и конструировать визуальные объекты. Здесь он уже встроен в графическую подсистему. Кроме того, шрифты сейчас используютс не растровые, а векторные - простым блитингом его не перевернешь (конечно, можно отрендерить текст и уже его вращать как хочется, видимо так HTML фильтр поступает).
Остается наиболее универсальный метод - аффинные преобразования.
Шрифт можно представить внутри ресурса программы как бинарная таблица. А значит, по идее, в этой таблице можно все вертикальные величины отзеркалить, а затем уже загрузить.
Я говорю о том, что в гугле не нашёл пока статейки о том, как загрузить шрифт в память, преобразовать как надо, а потом передать указатель соответствующей функции...