Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как нарисовать стрелку в С++?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
skyfoxx
Есть x1,y1 начало линии и x2,y2 конец линии. Нарисовать в конце линии две линии образующие крылья стрелки. Координаты x1,y1,x2,y2 будут задаваться произвольно, направление крыльев стрелки должно меняться автоматически.

Стрелка должна отображатся в Image smile3046.gif
Methane
Цитата(skyfoxx @ May 12 2009, 14:02) *
Есть x1,y1 начало линии и x2,y2 конец линии. Нарисовать в конце линии две линии образующие крылья стрелки. Координаты x1,y1,x2,y2 будут задаваться произвольно, направление крыльев стрелки должно меняться автоматически.

что такое sin и cos знаем?
skyfoxx
Цитата(Methane @ May 12 2009, 15:14) *
что такое sin и cos знаем?


Знаю но как их применить?
Methane
Цитата(skyfoxx @ May 12 2009, 14:23) *
Знаю но как их применить?

Вы знаете координаты начала и конца.
Считаете угол наклона линии.
Потом прикидываете на какой угол у вас должны быть развернуты углы стрелки.
Потом находите точки, конца стрелки. Проводите линии. Нарисуйте на бумажке, и распишите углы. Сразу станет ясно.
skyfoxx
Цитата(Methane @ May 12 2009, 15:26) *
Вы знаете координаты начала и конца.
Считаете угол наклона линии.
Потом прикидываете на какой угол у вас должны быть развернуты углы стрелки.
Потом находите точки, конца стрелки. Проводите линии. Нарисуйте на бумажке, и распишите углы. Сразу станет ясно.


спасибо rolleyes.gif , но серавно не понял smile3046.gif

Цитата(skyfoxx @ May 12 2009, 15:40) *
спасибо rolleyes.gif , но серавно не понял smile3046.gif


Верней понял но не знаю как применить
Demeny
Цитата(Methane @ May 12 2009, 15:26) *
Вы знаете координаты начала и конца.
Считаете угол наклона линии.
Потом прикидываете на какой угол у вас должны быть развернуты углы стрелки.
Потом находите точки, конца стрелки. Проводите линии. Нарисуйте на бумажке, и распишите углы. Сразу станет ясно.

Прямой, но неэффективный и неинтересный подход, применимый только для примитивных стрелок. А как быть, если стрелку хочется с непрямыми усами, а хотя бы полукруглыми, наполовину закрашенными ?
Предлагаю другой путь. Как провести саму линию, надеюсь, понятно, а вот саму стрелку можно хранить в битмапе и выводить на экран поточечно, на ходу пересчитывая координаты точек с учетом поворота стрелки.
Для новичков - алгоритм следующий: 1) рисуем в любом графическом редакторе черно-белую стрелку, какую хочется, но направленную строго слева направо, в разрешении, например 8x8 пикселей; 2) затаскиваем массив отрисованных пикселей к себе в программу, причем удобно хранить массив в полярной системе координат с полюсом в точке, на которую указывает стрелка; каждая точка задается парой чисел (R, fi); 3) для того, чтобы вывести эту стрелку на экран достаточно посчитать угол наклона прямой, добавить этот угол ко всем полярным координатам точек и перевести новые полярные координаты в экранные по формулам x=x2+R*cos(fi); y=y2+R*sin(fi).
Methane
Цитата(Demeny @ May 12 2009, 16:00) *
удобно хранить массив в полярной системе координат с центром в точке, на которую указывает стрелка; каждая точка задается парой чисел (R, fi); 3) для того, чтобы вывести эту стрелку на экран достаточно посчитать угол наклона прямой, добавить этот угол ко всем полярным координатам точек и перевести новые полярные координаты в экранные по формулам x=x2+R*cos(fi); y=y2+R*sin(fi).

Уж если мой не удобный и не эффективный, то как назвать ваш метод я не знаю. К примеру размер стрелки в полярных координатах должен быть значительно больше реальной стрелки. Или вводить интерполяцию попикселям, что скажется на качестве.
Demeny
Цитата(Methane @ May 12 2009, 17:04) *
Уж если мой не удобный и не эффективный, то как назвать ваш метод я не знаю. К примеру размер стрелки в полярных координатах должен быть значительно больше реальной стрелки.

Не очень понял, почему должен быть больше ? Можно хранить 1:1, причём, учитывая всё же, что это стрелка, можно хранить полярные координаты только рисуемых точек, что сильно сократит объём массива.
Цитата(Methane @ May 12 2009, 17:04) *
Или вводить интерполяцию попикселям, что скажется на качестве.

Интерполяция тут не нужна, а для масштабирования стрелки достаточно умножить полярную координату R для каждой точки на нужный коэффициент.
Methane
Цитата(Demeny @ May 12 2009, 16:18) *
Не очень понял, почему должен быть больше ? Можно хранить 1:1, причём, учитывая всё же, что это стрелка, можно хранить полярные координаты только рисуемых точек, что сильно сократит объём массива.

Пропущенные пиксели будут.

Цитата
Интерполяция тут не нужна, а для масштабирования стрелки достаточно умножить полярную координату R для каждой точки на нужный коэффициент.

Аднозначно будут.
Тем более, я предлагал через тригонометрию посчитать две точки, вы предлагаете ВСЕ.
skyfoxx
Цитата(Methane @ May 12 2009, 17:26) *
Пропущенные пиксели будут.


Аднозначно будут.
Тем более, я предлагал через тригонометрию посчитать две точки, вы предлагаете ВСЕ.

Думаю первый способ проще , ну плиииииииииззз киньте кость я в смысле по какой формуле можно енто дело расчетать?
Палыч
Цитата(skyfoxx @ May 12 2009, 16:56) *
плиииииииииззз киньте кость я в смысле по какой формуле можно енто дело расчетать?
Если в двух словах, то:
1. Находите точку на Вашей линии, отстоящую от конца линии на длину стрелки.
2. Поворачиваете её вокруг точки конца линии на угол "развода" линий стрелки.
3. Проводите линию от этой точки до конца линии
4. Повторяете п.2 и 3, но с поворотом в другую сторону
Genadi Zawidowski
Я рисовал в фотошопе стрелку - потом поворачивал её на нужный угол - и записывал. Попробуйте сделать хоть 36 образов стрелки и взяв угол с точностью 10 градусов выбрать нужный имедж для рисованя


Код
    static UINT ids [12] =
    {
        IDI_ARROW_0G0, IDI_ARROW_0G1, IDI_ARROW_0G2, IDI_ARROW_0G3,
        IDI_ARROW_0G4, IDI_ARROW_0G5, IDI_ARROW_0G6, IDI_ARROW_0G7,
        IDI_ARROW_0G8, IDI_ARROW_0G9, IDI_ARROW_0G10, IDI_ARROW_0G11,

    };
    for (int i = 0; i < 12; ++ i)
    {
        arrowPoint [i] = AfxGetApp()->LoadIcon(ids [i]);
    }

...

    {
        int iangle = ((m_iAngle - m_iOffset + FULL_CIRCLE)%(FULL_CIRCLE));
        double angle = iangle / 3600 * PI * 2 / 360;

        int yTarget = - (int) (radius * cos(angle) * 0.85);
        int xTarget = (int) (radius * sin(angle) * 0.85);
        int yTarget0 = - (int) (radius * cos(angle) * 0.1);
        int xTarget0 = (int) (radius * sin(angle) * 0.1);

        m_invisibleDc.SelectObject(m_darkRedPen);
        m_invisibleDc.SelectObject(m_darkRedBrush);

        m_invisibleDc.MoveTo(cpt.x + xTarget0, cpt.y + yTarget0);
        VERIFY(m_invisibleDc.LineTo(cpt.x + xTarget, cpt.y + yTarget));

        {
            int zoneAngle = ((iangle + 15 * 3600) / (3600 * 30)) % 12;
            ASSERT(zoneAngle < 12);
            CPoint cp = CPoint(cpt.x + xTarget, cpt.y + yTarget);
            VERIFY(m_invisibleDc.DrawIcon(cp.x + iconXOffset, cp.y + iconYOffset, arrowPoint [zoneAngle]));
        }
    }
DpInRock
Код
image1.Canvas.Pen.Width:=1;
image1.Canvas.lineto(20,20);
image1.Canvas.Pen.width:=5;
image1.Canvas.lineto(21,21);
image1.Canvas.Pen.width:=4;
image1.Canvas.lineto(22,22);
image1.Canvas.Pen.width:=3;
image1.Canvas.lineto(23,23);
image1.Canvas.Pen.width:=2;
image1.Canvas.lineto(24,24);
image1.Canvas.Pen.width:=1;
image1.Canvas.lineto(25,25);


За пят точек до конца линии устанавливаем ширину линии 5, к примеру, и далее рисуем по одному шагу с уменьшением ширины. Получается нормальная стрелка.
skyfoxx
Всем спасиб разобрался smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.