Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Задача. Рисуем стрелку.


Автор: Elfet 24.11.2006, 17:31
Есть прямая. Нужно к ней нарисовать стрелку. Я убил целый час ( о ужас! главное что бы наш профессор по алгебре не узнал ) , но вышло се совсем то чего я ожидал)))
Вот что я умудрил:
Код

            int radius = 5;
            int arrowWidth = 7;
            int arrowHeight = 2;

                    int x1 = i.p1.x;
                    int y1 = i.p1.y;
                    int x2 = i.p2.x;
                    int y2 = i.p2.y;
                    g.DrawLine(ribPen, x1, y1, x2, y2);
                    // Стрелка
                    {
                        double r = Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2));
                        double lambdaC = radius / (r - radius);
                        double Cx = (x1 + lambdaC * x2) / (1 + lambdaC);
                        double Cy = (y1 + lambdaC * y2) / (1 + lambdaC);
                        double lambdaB = (radius + arrowWidth) / (r - (radius + arrowWidth));
                        double Bx = (x1 + lambdaB * x2) / (1 + lambdaB);
                        double By = (y1 + lambdaB * y2) / (1 + lambdaB);
                        double nath = (y2 - y1) / (x2 - x1);
                        double cph = Math.Atan(nath);
                        double betta = Math.Atan(arrowWidth / arrowHeight);
                        double tgAlpha1 = Math.Tan(cph - betta);
                        double tgAlpha2 = Math.Tan(cph + betta);
                        double F1y = (Cy / tgAlpha1 - Cx + Bx + nath * By) / (1 / tgAlpha1 + nath);
                        double F1x = (F1y - Cy) / tgAlpha1 + Cx;
                        double F2y = (Cy / tgAlpha2 - Cx + Bx + nath * By) / (1 / tgAlpha2 + nath);
                        double F2x = (F2y - Cy) / tgAlpha2 + Cx;
                        g.DrawLine(ribPen, (int)Cx, (int)Cy, (int)F1x, (int)F1y);
                        g.DrawLine(ribPen, (int)Cx, (int)Cy, (int)F2x, (int)F2y);
                    }

 smile

Добавлено @ 17:43 
user posted image
user posted image
user posted image

Добавлено @ 17:43 
Полная шызуха.

Автор: Void 24.11.2006, 17:44
Код
using System.Drawing;
using System.Drawing.Drawing2D;

Pen pen = new Pen(Color.Black, 2.0F);
pen.CustomEndCap = new AdjustableArrowCap(4.0F, 8.0F);
Graphics g = ...;
g.DrawLine(pen, 10, 50, 100, 50);

Вот как-то так smile

Автор: mr.DUDA 24.11.2006, 18:02
Задачка интересная, и решается двумя путями:

1. Предложенный тобой способ (не проверял)
2. Если знать о существовании матриц и трансформаций, то всё получается на порядок проще: мы смещаем и поворачиваем систему координат к началу стрелки, рисуем стрелку горизонтально из точки (0;0), поворачиваем координаты обратно. Накатал простой пример с формой, где стрелка рисуется из центра формы к курсору мыши:

Код
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace WindowsApplication3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        ///<summary>
        /// Рисует стрелку на графиксе
        ///</summary>
        void DrawArrow(Graphics gr, Point start, Point end)
        {
            float x1 = start.X, y1 = start.Y, x2 = end.X, y2 = end.Y;

            // вычисляем угол, под которым стрелка повёрнута против часовой
            // вычисляем длину стрелки
            float angle = (float)Math.Atan2(y2 - y1, x2 - x1);
            angle = angle * 180f / (float)Math.PI; // переводим в градусы
            float len = (float)Math.Sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));

            // сохраняем старое состояние Graphics, чтобы потом его восстановить
            GraphicsState state = gr.Save();

            // трансформация: сдвиг к точке start и поворот на угол
            gr.TranslateTransform(x1, y1);
            gr.RotateTransform(angle);

            using (Pen pen = new Pen(Color.Red, 2f))
            {
                int arrowLength = 10; // длина окончания стрелки
                int arrowWidth = 5; // ширина окончания стрелки
               
                // рисуем стрелку в горизонтальном положении
                gr.DrawLine(pen, 0, 0, len, 0);
                gr.DrawLine(pen, len, 0, len - arrowLength, arrowWidth);
                gr.DrawLine(pen, len, 0, len - arrowLength, -arrowWidth);
            }

            // восстанавливаем старое состояние Graphics (убираем наши трансформации)\
            gr.Restore(state);
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            DrawArrow(e.Graphics, 
                new Point(this.Width / 2, this.Height / 2), // начало - центр формы
                this.PointToClient(Cursor.Position)); // конец - курсор мыши в координатах формы
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            this.Refresh();
        }
    }
}


З.Ы. чтоб не мерцало, у формы ставим DoubleBuffered = true.

Добавлено @ 18:03 
Цитата(Void @  24.11.2006,  16:44 Найти цитируемый пост)
Вот как-то так

3. Способ Void-а. Совсем для ленивых smile

Добавлено @ 18:09 
Видать, ваш препод хочет знания тригонометрии проверить... значит только руками, и учить матчасть...  smile 

Автор: Elfet 24.11.2006, 18:20
smile Ок! Спасибо! smile нее. эт я для себя в программе сделать хотел smile просто подобные задачки препод двавал нам в огромных количествах. Теперь забылось всё немного smile

Добавлено @ 18:29 
Использовал AdjustableArrowCap так как красиво и я думаю быстрее?  smile 

Автор: mr.DUDA 24.11.2006, 18:44
AdjustableArrowCap хорош, если не нужно делать таких вещей как например стрелка нестандартной формы  smile 

Автор: mr.DUDA 5.12.2006, 22:50
Хы, ещё красивее можно сделать если добавить сглаживание:

Код
            // сохраняем старое состояние Graphics, чтобы потом его восстановить
            GraphicsState state = gr.Save();
            gr.SmoothingMode = SmoothingMode.HighQuality;

// ...

Автор: Elfet 16.12.2006, 22:19
Вот что получилось: http://forum.vingrad.ru/topic-127665/kw-graph-simple.html smile

Автор: scalosale 8.2.2023, 18:51
Модератор: Сообщение скрыто.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)