Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/59: Рейтинг темы: голосов - 59, средняя оценка - 4.71
0 / 0 / 0
Регистрация: 27.03.2017
Сообщений: 12
1

Построение схемы и ее расчёт

27.03.2017, 18:09. Показов 12195. Ответов 29
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Поскажите пожалуйста, как сделать приложение, со своими элементами, которые пользователь может переносить в рабочую область и строить из них схемы, которые после можно рассчитать, в зависимости от введеных в них параметров. Возможно вообще такое в с#? Помогите пожалуйста.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.03.2017, 18:09
Ответы с готовыми решениями:

Построение и расчет схемы в Electronics Workbench
Нужно построить схему и рассчитать её элементы. Набор такой: батарея, лампочка, резистор, амперметр...

Расчёт схемы
Имеется данная схема: Входные данные: R1=5 Ом E1=10 В E2=15 В J=4 А ---- Найти все токи ...

Расчет электрической схемы
Задание по практике звучит так: Исследовать электрическую схему (Приложение к заданию),...

расчет электрической схемы
Приветствую, раньше никогда этим не занимался. Стоит задача нахождения номиналов резистроров, чтобы...

29
71 / 68 / 46
Регистрация: 02.12.2015
Сообщений: 890
Записей в блоге: 1
27.03.2017, 18:44 2
Цитата Сообщение от Nikita988 Посмотреть сообщение
Поскажите пожалуйста, как сделать приложение, со своими элементами, которые пользователь может переносить в рабочую область и строить из них схемы, которые после можно рассчитать, в зависимости от введеных в них параметров. Возможно вообще такое в с#? Помогите пожалуйста
Это мало кто поймет. Слишком общая задача. По конкретнее скажите, может кто-то и поможет. Если нужно создать свои элементы используйте класс UserControl.
0
0 / 0 / 0
Регистрация: 27.03.2017
Сообщений: 12
28.03.2017, 15:29  [ТС] 3
Надо реализовать вот это. Чтобы пользователь мог перетаскивать элементы, строить схему, и обсчитывать, к примеру надежность.
Миниатюры
Построение схемы и ее расчёт  
0
1 / 1 / 1
Регистрация: 12.08.2016
Сообщений: 20
28.03.2017, 17:35 4
Nikita988, сразу же вопрос возникает: "Чем вас не устраивает Simulink или MatLab? для чего надо еще раз изобретать велосипед?"
0
0 / 0 / 0
Регистрация: 27.03.2017
Сообщений: 12
28.03.2017, 17:49  [ТС] 5
А если у пользователя не установлен ни симулинк ни матлаб, что делать? А с# позволяет exe файл сделать, который точно откроется.
0
Эксперт .NET
12078 / 8387 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
28.03.2017, 18:28 6
Nikita988, гениально. А если захочется какую-нибудь фотографию отретушировать вы начнёте свой фотошоп писать?

Маловероятно, что вам помогут чем-то более конкретным, чем просто общими советами. Задачка эта не из простых.
0
1 / 1 / 1
Регистрация: 12.08.2016
Сообщений: 20
29.03.2017, 13:46 7
Nikita988, я присоединяюсь к мнению Usaga: то, что вы намереваетесь создать, тянет на проект для целой команды, в которой есть и дизайнеры и математики и прочие спецы. Все это можно осилить и вывести на приемлемый уровень, но потребуется немало человеко-часов.
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
29.03.2017, 15:06 8
Цитата Сообщение от tougric Посмотреть сообщение
Nikita988, я присоединяюсь к мнению Usaga: то, что вы намереваетесь создать, тянет на проект для целой команды, в которой есть и дизайнеры и математики и прочие спецы. Все это можно осилить и вывести на приемлемый уровень, но потребуется немало человеко-часов.
Та не, реально тут работы на день где-то.
0
Эксперт .NET
12078 / 8387 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
29.03.2017, 15:11 9
Storm23, я уже не раз слышал подобные уверенные заявления А заканчивалось как обычно - в два-три раза дольшим сроком.

На вскидку - дня два-три работы тут будет (если не в поте лица хреначить). Но кто возьмётся для ТС это делать?..
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
29.03.2017, 15:29 10
Usaga, ну необязательно же полностью делать, можно хотя бы архитектуру помочь набросать (мне было бы интересно на неё взглянуть)
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
29.03.2017, 15:33 11
Цитата Сообщение от TopLayer Посмотреть сообщение
ну необязательно же полностью делать, можно хотя бы архитектуру помочь набросать (мне было бы интересно на неё взглянуть)
Какая там архитектура? Это же просто ориентированный граф. Тут больше всего возни с передвижением прямоугольников и их соединением.
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
29.03.2017, 16:16 12
Storm23, разумеется я не граф имел в виду, а как раз все эти перемещения, соединения, редактирование значений в прямоугольниках, перенос с панели в рабочую область и тд.
Просто скажу, что мне это всё не очевидно: ничего нереализуемого нет, но целиком решения не вижу.
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
29.03.2017, 18:01 13
Цитата Сообщение от TopLayer Посмотреть сообщение
все эти перемещения, соединения, редактирование значений в прямоугольниках, перенос с панели в рабочую область
Щас запилю пример...
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
29.03.2017, 20:27 14
Лучший ответ Сообщение было отмечено ViterAlex как решение

Решение

Цитата Сообщение от Nikita988 Посмотреть сообщение
Чтобы пользователь мог перетаскивать элементы, строить схему, и обсчитывать, к примеру надежность.
Создаем два интерфейса IDrawable и IDragable:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    /// <summary>
    /// Умеет себя рисовать
    /// </summary>
    public interface IDrawable
    {
        void Paint(Graphics gr);
    }
 
    /// <summary>
    /// Умеет себя перемещать
    /// </summary>
    public interface IDragable
    {
        bool Hit(Point point);
        void Drag(Point offset);
        IDragable StartDrag(Point p);
        void EndDrag();
    }


Делаем панель, которая умеет отображать IDrawable и перемещать IDragable:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    /// <summary>
    /// Панель, которая умеет отображать IDrawable и перемещать IDragable
    /// </summary>
    public class DragPanel : UserControl
    {
        IEnumerable<object> model;
        Point offset;
        private Point mouseDown;
        IDragable dragged;
 
        public DragPanel()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.Selectable, true);
        }
 
        public void Build(IEnumerable<object> model)
        {
            this.model = model;
        }
 
        protected override void OnPaint(PaintEventArgs e)
        {
            if (model == null) return;
 
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            e.Graphics.TranslateTransform(offset.X, offset.Y);
 
            //отрисовываем объекты
            foreach (var obj in model.OfType<IDrawable>())
                obj.Paint(e.Graphics);
        }
 
        Point ToClient(Point p)
        {
            return p.Sub(offset);
        }
 
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                mouseDown = e.Location;
                var p = ToClient(e.Location);
                //ищем объект под мышкой
                var hitted = model.OfType<IDragable>().FirstOrDefault(n => n.Hit(p));
                if (hitted != null)
                    dragged = hitted.StartDrag(p);//начинаем тащить
            }
        }
 
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                var shift = new Point(e.Location.X - mouseDown.X, e.Location.Y - mouseDown.Y);
                mouseDown = e.Location;
                //
                if (dragged != null)
                    dragged.Drag(shift);//двигаем объект
                else
                    offset = new Point(offset.X + shift.X, offset.Y + shift.Y);//сдвигаем канвас
 
                Invalidate();
            }
        }
 
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if(dragged != null)
                dragged.EndDrag();
            dragged = null;
            Invalidate();
        }
    }


Делаем класс Node, реализующий IDrawable и IDragable:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
    /// <summary>
    /// Элемент модели, задающий надежность. 
    /// Может быть связан с другими эелемнтами.
    /// </summary>
    public class Node : IDrawable, IDragable
    {
        public GraphicsPath Path {get; set;}
        public Point Location;
        public virtual Color BorderColor => Color.Lime;
        public virtual Color FillColor => Color.FromArgb(30, Color.White);
        public object Tag { get; set; }
        public Model Model { get;set;}
        public virtual bool AcceptPin => true;
 
        public Pin Pin { get;set;}
        public List<Node> Linked { get; set; } = new List<Node>();
 
        public Node(Model model)
        {
            this.Model = model;
            Path = Helper.GetRoundedRectangle(new Rectangle(-50, -30, 100, 60), 20);
 
            Pin = new Pin(this) {RelativeLocation = new Point(50, 0)};
        }
 
        public virtual void Paint(Graphics gr)
        {
            foreach (var linked in Linked)
                gr.DrawLink(linked.Pin.Location, Location.Sub(new Point(50, 0)));
 
            var state = gr.Save();
            gr.TranslateTransform(Location.X, Location.Y);
            gr.FillPath(FillColor.Brush(), Path);
            gr.DrawPath(BorderColor.Pen(), Path);
            Path.DrawHalo(gr, BorderColor, BorderColor.Pen());
            var rect = Path.GetBounds();
            rect.Inflate(-5, -5);
            if(Tag != null)
                gr.DrawString(Tag.ToString(), Helper.Font, Brushes.White, rect, new StringFormat {Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center});
            gr.Restore(state);
 
            if (Pin != null)
                Pin.Paint(gr);
        }
 
        public bool Hit(Point p)
        {
            if (Pin != null && Pin.Hit(p))
                return true;
 
            return Path.IsVisible(p.Sub(Location));
        }
 
        public void Drag(Point offset)
        {
            Location = Location.Add(offset);
        }
 
        public IDragable StartDrag(Point p)
        {
            //если кликнули на пин - тянем пин
            if (Pin != null && Pin.Hit(p))
                return Pin;
 
            //тянем себя
            return this;
        }
 
        const float GRID_STEP = 20;
 
        public void EndDrag()
        {
            //выравниваем по сетке
            Location = new Point((int)(GRID_STEP * Math.Round(Location.X/GRID_STEP)), (int)(GRID_STEP*Math.Round(Location.Y/GRID_STEP)));
        }
    }


Свойство Tag будет хранить вероятность (надежность) задаваемую данным нодом. Свойство Linked будет хранить все ноды, связанные с данным.

Делаем класс Pin, который тоже будет реализовать IDrawable и IDragable. Этот класс предназначен для создания связей между нодами. Когда его перетаскивают он проверяет на какой нод он "упал" и создает связь с этим нодом:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    /// <summary>
    /// Элемент соединяющий ноды
    /// </summary>
    public class Pin : IDrawable, IDragable
    {
        public Node Parent { get; set; }
        public Point RelativeLocation { get;set;}
        public GraphicsPath Path { get; set; }
        public Color BorderColor { get; set; } = Color.Navy;
        public Color FillColor { get; set; } = Color.DeepSkyBlue;
 
        private Point drag;
 
        public Point Location
        {
            get { return Parent.Location.Add(RelativeLocation); }
        }
 
        public Pin(Node parent)
        {
            Parent = parent;
            Path = new GraphicsPath();
            Path.AddEllipse(new Rectangle(-5, -5, 10, 10));
        }
 
        public void Paint(Graphics gr)
        {
            if (drag != Point.Empty)
                gr.DrawLink(Location, Location.Add(drag));
 
            var state = gr.Save();
            gr.TranslateTransform(Location.X, Location.Y);
            gr.FillPath(FillColor.Brush(), Path);
            gr.DrawPath(BorderColor.Pen(), Path);
            if (drag != Point.Empty)
            {
                gr.DrawEllipse(BorderColor.Pen(), drag.X - 5, drag.Y - 5, 10, 10);
                gr.FillEllipse(FillColor.Brush(), drag.X - 5, drag.Y - 5, 10, 10);
            }
            gr.Restore(state);
        }
 
        public bool Hit(Point point)
        {
            return Path.IsVisible(point.Sub(Location));
        }
 
        public void Drag(Point offset)
        {
            drag = drag.Add(offset);
        }
 
        public IDragable StartDrag(Point p)
        {
            return this;
        }
 
        public void EndDrag()
        {
            var p = Location.Add(drag);
            //ищем целевой объект
            foreach (var node in Parent.Model.OfType<Node>())
            if(node != Parent && node.AcceptPin)
            {
                if (node.Hit(p))
                    node.Linked.Add(Parent);
            }
            drag = Point.Empty;
        }
    }


Создаем класс FinishNode наследующийся от Node. Является конечным нодом, куда стекаются все вероятности. подсчитывает суммарную надежность:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    /// <summary>
    /// Конечный нод. 
    /// Считает итоговую надежность системы.
    /// </summary>
    public class FinishNode : Node
    {
        public override Color BorderColor => Color.SkyBlue;
 
        public FinishNode(Model model) : base(model)
        {
        }
 
        public override void Paint(Graphics gr)
        {
            if (Linked.Count == 0)
            {
                Tag = "Finish";
            }
            else
            {
                var p = Calc(this);
                Tag = string.Format("P = {0:0.00}", p);
            }
 
            base.Paint(gr);
        }
 
        private static float Calc(Node node)
        {
            if (!(node.Tag is float))
            {
                if (node.Linked.Count == 0) return 1;
                return node.Linked.Min(n => Calc(n));//ищем минимум среди входящих
            }
            else
            {
                var p = (float)node.Tag;
                if (node.Linked.Count == 0) return p;
                return p * node.Linked.Min(n => Calc(n));//ищем минимум среди входящих, умножаем на свою вероятность
            }
        }
    }


При параллельном соединении нодов - выбирается минимальная надежность, при последовательном - вероятности перемножаются.

Ну и еще по мелочи создаем пару классов.

Результат:
Построение схемы и ее расчёт


Итого - два часа чистого времени
Удаление и редактирование нодов не делал. Если делать - займет чуть побольше времени.
Вложения
Тип файла: zip WindowsFormsApplication368 (2).zip (96.2 Кб, 514 просмотров)
21
TopLayer
30.03.2017, 06:18
  #15

Не по теме:

Цитата Сообщение от Storm23 Посмотреть сообщение
Итого - два часа чистого времени
Почувствовал себя ущербным

0
Usaga
30.03.2017, 06:24
  #16

Не по теме:

Цитата Сообщение от TopLayer Посмотреть сообщение
Почувствовал себя ущербным
Не надо. Человек наверняка взял за основу некоторые наработки. Если нет, то я с вами...

0
Storm23
30.03.2017, 12:41
  #17

Не по теме:

Цитата Сообщение от Usaga Посмотреть сообщение
Не надо. Человек наверняка взял за основу некоторые наработки. Если нет, то я с вами...
Нет, сейчас писал с нуля кроме некоторых функций (типа отрисовки закругленного прямоугольника или рисования гало). Другое дело, что я не в первый раз подобное пишу. А со второго раза оно всегда быстрее.

0
0 / 0 / 0
Регистрация: 27.03.2017
Сообщений: 12
30.03.2017, 15:45  [ТС] 18
Даже не ожидал. Огромное спасибо за помощь, попробую собрать это у себя, если зарабоает - с меня вознаграждение.
0
0 / 0 / 0
Регистрация: 27.03.2017
Сообщений: 12
30.03.2017, 22:02  [ТС] 19
Storm23, Всё прекрасно, но считает не верно =( . Программа считает только последовательные соединения, и их считает правильно, при последовательном соединении вероятность безотказной работы = P1*P2*...Pn , но при параллельном иначе : для, допустим, параллельного соединения трёх элементов P=1-(1-p1)*(1-p2)*(1-p3) . Можно это реализовать, чтобы программа понимала где параллельное соединение, а где последовательное и исходя из этого правильно рассчитывала?
Изображения
 
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
30.03.2017, 22:35 20
Цитата Сообщение от Nikita988 Посмотреть сообщение
Всё прекрасно, но считает не верно =( . Программа считает только последовательные соединения, и их считает правильно, при последовательном соединении вероятность безотказной работы = P1*P2*...Pn , но при параллельном иначе : для, допустим, параллельного соединения трёх элементов P=1-(1-p1)*(1-p2)*(1-p3) . Можно это реализовать, чтобы программа понимала где параллельное соединение, а где последовательное и исходя из этого правильно рассчитывала?
Расчет вероятности происходит в методе FinishNode.Calc(). Замените его на вот такой метод:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        private static float Calc(Node node)
        {
            //стартовый нод всегда дает 1
            if (node is StartNode) return 1;
 
            //считаем входящие параллельные
            var p = 1f;
            foreach (var n in node.Linked)
                p *= (1 - Calc(n));
            p = 1 - p;
 
            //домножаем на свой коэффициент
            if (node.Tag is float)
                p *= (float) node.Tag;
 
            return p;
        }
0
30.03.2017, 22:35
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.03.2017, 22:35
Помогаю со студенческими работами здесь

Расчет схемы при КЗ
В общем формулирую задачу: 1) Нужно построить 3-х фазную сеть, смоделировать все виды КЗ и...

Расчет схемы уселения
Здравствуйте. Помогите с расчетами (то есть с формулами). Есть схема, работает на эмуляторе...

Расчет схемы источника питания
Доброго времени суток. Прошу о помощи в расчете источника питания. Сразу скажу в этом ничего не...

Расчет схемы переменного тока
Здравствуйте!) Схема простая, но первый ток не сходиться(модуль должен быть ~50 мА, а у меня...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru