Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Толщина линий после scale(), хочу линию толщиной в один пиксел 
:(
    Опции темы
Mirkes
Дата 9.12.2013, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



День добрый!

Мне надоело в разных вариантах реализовывать приведение координат из одной системы в другую и я решил воспользоваться стандартным функционалом Java: AffineTransform. Сначала запутался как преобразовывать, но разобрался. А вот потом налетел по крупному.
Код

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        int w = this.getWidth() - 2 * margin.x; //Ширина без учета полей
        int h = this.getHeight() - 2 * margin.y; //Высота без учета полей
        Graphics2D gg = (Graphics2D)g.create(margin.x, margin.y, w, h);  //Получаем копию поляны для рисования
        gg.setStroke(new BasicStroke(1f)); //устанавливаем ширину линии в один пиксел
        gg.translate(0, h); //сдвигаем начало координат вниз
        gg.scale(1, -1);  //Переходим в нормальную систему координат инвертируя ось Y
        gg.scale(w / (maxX - minX), h / (maxY - minY)); //Переходим к пользовательским координатам
        gg.translate(minX, minY); //Нормализуем положение начала координат
        gg.setColor(Color.BLACK);
        GeneralPath gp = new GeneralPath();  //Создаем простую линию из точки 0,0 в точку 1,1
        gp.moveTo(0, 0);
        gp.lineTo(1, 1);
        gg.draw(gp); //Рисуем
    }


Все бы ничего, но в моем случае пользовательские координаты меняются от 0 до 1.
А толщина линии оказалась в 1 пользовательских координат!
То есть вместо диагонали квадрата я получил почти закрашенный квадрат! Осталось чуть-чуть не закрашенного места в двух углах.
Теперь вопрос. Как преобразовать координаты и при этом иметь линию по прежнему в 1 пиксель?
Можно конечно посчитать как изменилась единица отсчета, но если пользовательские координаты будут сильно разными по осям? тогда вертикальные линии будут толще/тоньше горизонтальных?


--------------------
Mirkes
PM MAIL   Вверх
Mirkes
Дата 9.12.2013, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Вообще то нашел решение, но оно мне сильно не нравится. Вместо преобразования координат в Graphics я создал отдельное преобразование координат которым потом обработал то, что было в пользовательских координатах и результат уже отрисовал. Но если рисовать нужно что-то сложное придется каждый раз все преобразовывать в Shape, преобразовывать координаты и потом рисовать.

Может есть более простой и естественный способ?

Код

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        int w = this.getWidth() - 2 * margin.x;
        int h = this.getHeight() - 2 * margin.y;
        Graphics2D gg = (Graphics2D)g.create(margin.x, margin.y, w, h);
        AffineTransform at=new AffineTransform();
        at.setToIdentity();
        at.translate(0, h);
        at.scale(1, -1);
        at.scale(w / (maxX - minX), h / (maxY - minY));
        at.translate(minX, minY);
        gg.setColor(Color.BLACK);
        GeneralPath gp = new GeneralPath();
        gp.moveTo(0, 0);
        gp.lineTo(1, 1);
        Shape ss=gp.createTransformedShape(at);
        gg.draw(ss);
    }


И опять мордой об забор  smile : метод createTransformedShape() определен только для путей, а я имею готовые Shape. Как преобразовать Shape?

Это сообщение отредактировал(а) Mirkes - 9.12.2013, 16:43


--------------------
Mirkes
PM MAIL   Вверх
Mirkes
Дата 13.12.2013, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Интересно, отсутствие какой либо реакции означает:
1. Никто не пробовал рисовать после Affine transform
2. У всех все работает и такого эффекта не возникает
3. Решение давно известно и не хочется тратить время на очевидное

Укажите хотя бы почему нет никакой реакции smile 


--------------------
Mirkes
PM MAIL   Вверх
Amp
Дата 13.12.2013, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 886
Регистрация: 17.2.2009

Репутация: нет
Всего: 17



У AffineTransform есть же собственный createTransformedShape, который Shape принимает.
PM MAIL   Вверх
Mirkes
Дата 13.12.2013, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Цитата(Amp @  13.12.2013,  17:36 Найти цитируемый пост)
У AffineTransform есть же собственный createTransformedShape, который Shape принимает. 

 Спасибо! Действительно я обшарил все со стороны Shape но не увидел метода у AffineTransform

Однако вопрос с толщиной линии для меня так и не понятен. Как выполнить преобразование координат а потом рисовать нормальной толщиной?
Или преобразования координат надо применять к рисуемым объектам а не к панели, на которой рисуют?

Я посмотрел примеры на сайте оракла - результат тот же. Они применяют преобразования к панели и тольщина линий меняется. К сожалению примера как рисовать линией в один пиксел на преобразованной панели я не нашел. 

Может кто-нибудь подскажет хотя бы куда смотреть?



--------------------
Mirkes
PM MAIL   Вверх
Amp
Дата 14.12.2013, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 886
Регистрация: 17.2.2009

Репутация: нет
Всего: 17



Да пересчитывай руками все сам. Больше возни, но в перспективе меньше проблем.
PM MAIL   Вверх
Mirkes
Дата 14.12.2013, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Цитата(Amp @  14.12.2013,  15:46 Найти цитируемый пост)
Да пересчитывай руками все сам. Больше возни, но в перспективе меньше проблем. 


Проблему то я решил, но хочется без наворотов обойтись  smile 

Рассмотрим такой пример. Я произвел шкалирование scale(20,10). После этого я установил толщину линии в 0.1. При этом вертикальная линия будет в два раза толще горизонтальной. А вот отслеживать разность толщин линий в зависимости от направления - это уже головняк серьезный.


--------------------
Mirkes
PM MAIL   Вверх
Mirkes
Дата 17.12.2013, 19:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Я хочу уточнить вопрос:
Правильно ли я понимаю, что если я произведу аффинные преобразования Graphics2D, то рисовать в нем нормально я уже не смогу?
Я провел физически эксперимент и получил ожидаемый эффект: при неравном шкалировании по осям в измененном Graphics2D я никогда не смогу получить горизонтальные, вертикальные и наклонные линии одной толщины.
Текст программы приложен, он очень короткий и думаю понятный.

Буду благодарен за ответ, даже из одного слова. Я все же надеюсь, что это я чего-то недопонял и возможность рисовать нормально все же существует.
Заранее спасибо.

Код

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class MyFrame extends JFrame {
    @SuppressWarnings("compatibility:-1742121239004895315")
    private static final long serialVersionUID = 8904641527445622030L;

    public MyFrame() {
        super();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel pan = new MyPanel();
        getContentPane().add(pan);
        Dimension d = new Dimension(200, 200);
        pan.setSize(d);
        pan.setPreferredSize(d);
        this.pack();
        this.setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        new MyFrame().setVisible(true);
    }

    public static class MyPanel extends JPanel {
        @SuppressWarnings("compatibility:3907988143307254501")
        private static final long serialVersionUID = 7381605947373850304L;

        @Override
        protected void paintComponent(Graphics g) {
            //            AffineTransform at = new AffineTransform();
            Graphics2D gg = (Graphics2D)g;
            gg.scale(20, 10);
            gg.drawLine(7, 0, 7, 20);
            gg.drawLine(0, 10, 10, 10);
            gg.drawRect(1, 1, 4, 4);
            gg.drawOval(1, 12, 4, 4);
        }
    }
}



--------------------
Mirkes
PM MAIL   Вверх
kamre
Дата 18.12.2013, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 330
Регистрация: 24.3.2006

Репутация: 2
Всего: 13



В Qt имеется вот такое свойство у кисти:
Цитата

Cosmetic pens are used to draw strokes that have a constant width regardless of any transformations applied to the QPainter they are used with. Drawing a shape with a cosmetic pen ensures that its outline will have the same thickness at different scale factors.


Давно в Java ничего не рисовать не приходилось, но может быть что-то аналогичное имеется и в ней.
PM MAIL   Вверх
Mirkes
Дата 18.12.2013, 13:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Цитата(kamre @  18.12.2013,  10:24 Найти цитируемый пост)
В Qt имеется вот такое свойство у кисти:
Цитата

Cosmetic pens are used to draw strokes that have a constant width regardless of any transformations applied to the QPainter they are used with. Drawing a shape with a cosmetic pen ensures that its outline will have the same thickness at different scale factors.


Давно в Java ничего не рисовать не приходилось, но может быть что-то аналогичное имеется и в ней. 


Спасибо, попробую поискать.


--------------------
Mirkes
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   jk1
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, jk1.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: GUI и Java FX приложения | Следующая тема »


 




[ Время генерации скрипта: 0.0777 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.