Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.61/41: Рейтинг темы: голосов - 41, средняя оценка - 4.61
 Аватар для kzkmrf2010
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38

Разработка системы моделирования электрических цепей

13.05.2019, 16:04. Показов 8126. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Задача состоит в создании решения для моделирования электрических цепей. Она должна в себя включать:
- возможность редактирования электрической цепи;
- реализовать различные виды резисторов, диодов, транзисторов и др.;
- элементы могут обладать реактивным и активным сопротивлением.

На данный момент у меня есть минимум. Сделана панель для отображения и прорисовано для примера два элемента - источник питания и резистор. Как можно произвести соединение этих элементов?

Также, возможно вместо рисования лучше добавлять картинки физических элементов?

Имеющийся код приложен. Помогите!
Вложения
Тип файла: rar v 1.6.rar (232.3 Кб, 96 просмотров)
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
13.05.2019, 16:04
Ответы с готовыми решениями:

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

Визуальный редактор логических электрических цепей
В общем есть задание на расчетно графическую работу.Создать виз редактор лог цепей. Нашел на Java то что мне нужно. Задаются...

Написать простой графический редактор электрических цепей
Пожалуйста,не понимаю как написать простенький граф.редактор для проектирования электрических цепей. Убил все нервы, как только не пытался...

16
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
13.05.2019, 16:46
Лучший ответ Сообщение было отмечено kzkmrf2010 как решение

Решение

Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
Как можно произвести соединение этих элементов?
Вложения
Тип файла: zip WindowsFormsApplication368_electric.zip (106.3 Кб, 187 просмотров)
6
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
13.05.2019, 16:47
Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
Как можно произвести соединение этих элементов?
Сделайте класс "Соединение", в котором будет храниться начальная и конечная точки подключения
Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
возможно вместо рисования лучше добавлять картинки физических элементов?
Конечно! Почему нет?
0
 Аватар для kzkmrf2010
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
18.05.2019, 18:52  [ТС]
Storm23 Как сделать, чтобы схема выгружалась в файл, а потом ее можно было открыть и редактировать?
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
18.05.2019, 20:45
Лучший ответ Сообщение было отмечено kzkmrf2010 как решение

Решение

Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
Как сделать, чтобы схема выгружалась в файл, а потом ее можно было открыть и редактировать?
1) Все классы модели помечаем атрибутом [Serializable]. Например:
C#
1
2
3
4
5
    [Serializable]
    public class Resistor : Node
    {
         ...
    }
2) В форме создаем главное меню, с двумя пунктами: Open и SaveAs. На событие клика вешаем обработчики:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        private void btSaveAs_Click(object sender, EventArgs e)
        {
            var sfd = new SaveFileDialog {Filter = "Schema|*.schema"};
            if (sfd.ShowDialog(this) == DialogResult.OK)
            using (var fs = File.Create(sfd.FileName))
                new BinaryFormatter().Serialize(fs, model);
        }
 
        private void btOpen_Click(object sender, EventArgs e)
        {
            var ofd = new OpenFileDialog { Filter = "Schema|*.schema" };
            if (ofd.ShowDialog(this) == DialogResult.OK)
            using (var fs = File.OpenRead(ofd.FileName))
            {
                model = (Model)new BinaryFormatter().Deserialize(fs);
                pnMain.Build(model);
            }
        }
3) Сериализация бы работала, но есть одна проблема. В классах Node и Link есть свойство Path типа GraphicsPath.
Но дело в том, что GraphicsPath является несериализуемым классом.
Для того, что бы это обойти, создаем следующий класс:
SerializableGraphicsPath
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
    /// <summary>
    /// Сериализуемая обертка над GraphicsPath
    /// </summary>
    [Serializable]
    public sealed class SerializableGraphicsPath : ISerializable, IDisposable
    {
        public GraphicsPath Path = new GraphicsPath();
 
        public SerializableGraphicsPath() { }
 
        private SerializableGraphicsPath(SerializationInfo info, StreamingContext context)
        {
            if (info.MemberCount > 0)
            {
                var points = (PointF[])info.GetValue("p", typeof(PointF[]));
                var types = (byte[])info.GetValue("t", typeof(byte[]));
                Path = new GraphicsPath(points, types);
            }
            else
                Path = new GraphicsPath();
        }
 
        public void Dispose()
        {
            Path?.Dispose();
        }
 
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (Path.PointCount <= 0) return;
            info.AddValue("p", Path.PathPoints);
            info.AddValue("t", Path.PathTypes);
        }
 
        public static implicit operator GraphicsPath(SerializableGraphicsPath path)
        {
            return path.Path;
        }
 
        public static implicit operator SerializableGraphicsPath(GraphicsPath path)
        {
            return new SerializableGraphicsPath { Path = path };
        }
    }


Этот класс заменяет GraphicsPath, но при этом является сериализуемым.

4) В классах Node и Link заменяем свойство public GraphicsPath Path {get; set; } на следующее:
C#
1
2
3
4
5
6
7
        private SerializableGraphicsPath path;
 
        public GraphicsPath Path
        {
            get { return path; }
            set { path = value; }
        }
Все. После этого у нас начинает работать сохранение и загрузка.
Вложения
Тип файла: zip WindowsFormsApplication368_electric (2).zip (114.5 Кб, 51 просмотров)
2
 Аватар для kzkmrf2010
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
18.05.2019, 21:02  [ТС]
Цитата Сообщение от Storm23 Посмотреть сообщение
Path?.Dispose();
Что означает этот оператор?
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
18.05.2019, 22:35
Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
Что означает этот оператор?
проверяет не равна ли переменная Path null и если нет, то вызывает метод Dispose()
1
 Аватар для kzkmrf2010
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
19.05.2019, 13:38  [ТС]
Storm23, а можно сделать не очистку поля, а удаление одного элемента?
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
19.05.2019, 19:12
Лучший ответ Сообщение было отмечено kzkmrf2010 как решение

Решение

Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
а можно сделать не очистку поля, а удаление одного элемента?
Можно сделать все.
Но удаление элемента будет немного посложнее.

Что бы удалить элемент, нужно иметь механизм его выделения на схеме.

Если проанализировать классы модели, то есть три основных класса: Node, Link и Pin.
При этом, выделить можно только Node и Link. Значит нужно создать интерфейс ISelectable и реализовать этот интерфейс в этих двух классах.

Интерфейс может выглядеть так:

C#
1
2
3
4
5
6
7
8
9
10
    /// <summary>
    /// Объект можно выделить и удалить
    /// </summary>
    public interface ISelectable
    {
        ISelectable Hit(Point point);
        void Select();
        void Unselect();
        void Remove();
    }
Метод Remove здесь не очень хорошо смотрится и для него, по-хорошему, нужно было бы сделать отдельный интерфейс, но я не хотел усложнять модель, поэтому оставил его здесь.

Далее, реализуем интерфейс ISelectable у классов Node и Link:

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
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
    /// <summary>
    /// Элемент модели. 
    /// Может быть связан с другими элементами.
    /// </summary>
    [Serializable]
    public class Node : IDrawable, IDragable, ISelectable
    {
        const float GRID_STEP = 20;
 
        [NonSerialized]
        private bool IsSelected = false;
        private SerializableGraphicsPath path;
 
        public GraphicsPath Path
        {
            get { return path; }
            set { path = value; }
        }
 
        public Point Location;
        public virtual Color BorderColor => Color.White;
        public virtual Color FillColor => Color.FromArgb(50, Color.White);
        public object Tag { get; set; }
        public Model Model { get;set;}
        public virtual bool AcceptPin => true;
 
        public List<Pin> Pins { get; } = new List<Pin>();
        public List<Link> Links { get; set; } = new List<Link>();
 
        public Node(Model model)
        {
            this.Model = model;
            Path = Helper.GetRoundedRectangle(new Rectangle(-50, -30, 100, 60), 20);
 
            Pins.Add(new Pin(this) { RelativeLocation = new Point(50, 0)} );
            Pins.Add(new Pin(this) { RelativeLocation = new Point(-50, 0)} );
        }
 
        public virtual void Paint(Graphics gr)
        {
            //отрисовка связей
            foreach (var link in Links)
                link.Paint(gr);
 
            //отрисовка
            var state = gr.Save();
            gr.TranslateTransform(Location.X, Location.Y);
 
            //если выделены - рисуем гало
            if (IsSelected)
                Helper.DrawHalo(Path, gr, Color.Red, Color.Red.Pen(), 4);
 
            //отрисовка себя
            gr.FillPath(FillColor.Brush(), Path);
            gr.DrawPath(BorderColor.Pen(2), Path);
 
            //отрисовка Tag
            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);
 
            //отрисовка пинов
            foreach (var pin in Pins)
                pin.Paint(gr);
        }
 
        /// <summary>
        /// Точка попадает в фигуру?
        /// </summary>
        public bool Hit(Point p)
        {
            if (Pins.Any(pin => pin.Hit(p)))
                return true;
 
            return Path.GetBounds().Contains(p.Sub(Location));
        }
 
        /// <summary>
        /// Тащим
        /// </summary>
        public void Drag(Point offset)
        {
            Location = Location.Add(offset);
        }
 
        /// <summary>
        /// Начало перетаскивания
        /// </summary>
        public IDragable StartDrag(Point p)
        {
            //если кликнут пин - тащим пин
            var clickedPin = Pins.FirstOrDefault(pin => pin.Hit(p));
            if (clickedPin != null)
                return clickedPin;
 
            //тащим себя
            return this;
        }
 
        /// <summary>
        /// Конец перетаскивания
        /// </summary>
        public void EndDrag()
        {
            //align by grid
            Location = new Point((int)(GRID_STEP * Math.Round(Location.X/GRID_STEP)), (int)(GRID_STEP*Math.Round(Location.Y/GRID_STEP)));
        }
 
        /// <summary>
        /// Поиск ближайшего пина
        /// </summary>
        public Pin FindNearestPin(Point point)
        {
            return Pins.OrderBy(pin => pin.Location.Sub(point).LengthSqr()).FirstOrDefault();
        }
 
        ISelectable ISelectable.Hit(Point p)
        {
            //если кликнули линк, то выделяем линк
            var clickedLink = Links.Select(link => link.Hit(p)).FirstOrDefault(s => s != null);
            if (clickedLink != null)
                return clickedLink;
 
            if(Path.GetBounds().Contains(p.Sub(Location)))
                return this;
 
            return null;
        }
 
        public void Remove()
        {
            //remove me from model
            Model.Remove(this);
 
            //remove me from all links
            foreach (var node in Model.OfType<Node>())
                node.Links.RemoveAll(link => link.Pin1.Parent == this || link.Pin2.Parent == this);
        }
 
        public void Select()
        {
            IsSelected = true;
        }
 
        public void Unselect()
        {
            IsSelected = false;
        }
    }


Link
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
    /// <summary>
    /// Связь между двумя пинами.
    /// </summary>
    [Serializable]
    public class Link : IDrawable, ISelectable
    {
        [NonSerialized]
        private bool IsSelected;
 
        public Pin Pin1 { get; set; }
        public Pin Pin2 { get; set; }
 
        private GraphicsPath Path
        {
            get
            {
                var path = new GraphicsPath();
                var p0 = Pin1.Location;
                var p1 = Pin1.RelativeLocation.X < 0 ? Pin1.Location.Add(new Point(-50, 0)) : Pin1.Location.Add(new Point(50, 0));
                var p2 = Pin2.RelativeLocation.X < 0 ? Pin2.Location.Add(new Point(-50, 0)) : Pin2.Location.Add(new Point(50, 0));
                var p3 = Pin2.Location;
                path.AddBezier(p0, p1, p2, p3);
                return path;
            }
        }
 
        public void Paint(Graphics gr)
        {
            var path = Path;
            if (IsSelected)
                Helper.DrawHalo(path, gr, Color.Red, Color.Red.Pen(2), 4);
 
            gr.DrawPath(Color.Lime.Pen(2), Path);
        }
 
        public ISelectable Hit(Point p)
        {
            if(Path.IsOutlineVisible(p, Color.Lime.Pen(8)))
                return this;
 
            return null;
        }
 
        public void Remove()
        {
            Pin1.Parent.Links.Remove(this);
            Pin2.Parent.Links.Remove(this);
        }
 
        public void Select()
        {
            IsSelected = true;
        }
 
        public void Unselect()
        {
            IsSelected = false;
        }
    }


Далее, в контроле DragPanel создаем поле ISelectable selected;, а методе OnMouseDown прописываем код для выделения элементов:

C#
1
2
3
4
5
6
                //выделяем объект
                selected?.Unselect();
                selected = model.OfType<ISelectable>().Select(n => n.Hit(p)).FirstOrDefault(s => s != null);
                selected?.Select();
 
                Invalidate();
Также создаем публичный метод для удаления выделенного элемента:

C#
1
2
3
4
        public void RemoveSelected()
        {
            selected?.Remove();
        }
И наконец, в главной форме делаем кнопочку RemoveSelected со следующим обработчиком:

C#
1
2
3
4
5
private void btRemoveSelected_Click(object sender, EventArgs e)
        {
            pnMain.RemoveSelected();
            pnMain.Invalidate();
        }
Проверяем работоспособность:

Вложения
Тип файла: zip WindowsFormsApplication368_electric (3).zip (121.3 Кб, 96 просмотров)
2
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
19.05.2019, 21:05
Storm23, подскажите, пожалуйста, чем Вы такие гифки записывали?
0
19.05.2019, 22:05

Не по теме:

Цитата Сообщение от asn31337 Посмотреть сообщение
чем Вы такие гифки записывали?
Google acethinker free-screen-recorder

0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
20.05.2019, 00:22
Цитата Сообщение от Storm23 Посмотреть сообщение
Google acethinker free-screen-recorder
Спасибо!!!
0
 Аватар для kzkmrf2010
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
17.06.2019, 15:17  [ТС]
Storm23, вроде во всём разобралась, спасибо. Единственное мне надо реализовать расчет вольт-амперных характеристик в цепи (просто по обычному закону Ома) и выбор изначальных характеристик элементов при добавлении их на панель. Я вроде как сделала, но теперь понимаю, что это нарушает инкапсуляцию, надо это как-то сделать через события. Не могли бы вы посмотреть?
Вложения
Тип файла: rar ElectroMod.rar (286.0 Кб, 26 просмотров)
0
 Аватар для kzkmrf2010
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
17.06.2019, 21:02  [ТС]
Т.е. при добавление на панель рисование, каждому элементу выбираются характеристики (сила тока, напряжение, сопротивление). После появления их на панели, в текстбоксах выводятся текущие характеристики в цепи.
0
 Аватар для kzkmrf2010
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
19.06.2019, 19:04  [ТС]
Storm23, Всё что собиралась, реализовала. Единственное, могли бы вы посмотреть на соответствие программы ООП?
Вложения
Тип файла: rar ElectroMod.rar (303.1 Кб, 210 просмотров)
1
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
24.06.2019, 14:20
kzkmrf2010,
С ООП там все нормально.
Но есть другие проблемы:
1) Имена форм типа Form1, Form2 и т.д.- не несут никакой информации. А должны отображать содержимое объекта.
2) Создавая формы, вы подписываетесь на их события, но нигде не отписываетесь от них. Это неправильно. К тому же, это приводит к утечкам памяти, потому что формы продолжают висеть в памяти, даже после того, как вы их закрыли.
В целом, вам там события не нужны. Создайте просто у форм публичные поля типа double, заносите туда информацию из текстовых полей. А из главной формы вызывайте форму через ShowDialog и затем читайте содержимое полей.
3) Расчета схемы нет.
4) Параметры, задаваемые для элементов - странные. Почему у вас источник питания имеет и напряжение и силу тока? Обычно у источника питания есть только напряжение. А сила тока в цепи - зависит от сопротивления цепи.
Почему у конденсатора есть сопротивление? То же самое - для диода. Ну и т.д. В общем, это выглядит как бессмыслица.
0
0 / 0 / 0
Регистрация: 22.10.2023
Сообщений: 1
22.10.2023, 22:44
Добавлено через 39 секунд
kzkmrf2010,
Здравствуйте
А у этого проекта есть продолжение? Я сейчас не могу реализовать метод расчета сопротивление параллельных и цепных связь резистора. Пожалуйста помогите мне в этом проекте Електромод
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
22.10.2023, 22:44
Помогаю со студенческими работами здесь

Как лучше реализовать анимацию электрических цепей?
Доброго времени суток! Подскажите пожалуйста, как лучше реализовать анимацию электрических цепей? (показать как протекает ток через ту или...

Программа для составления диаграм/схем/электрических цепей
Снова добрый вечер форуму. Нужна помощь в поиске простенькой программы на C# windows forms для создания диаграмм/схем или электрических...

Программы для моделирования электрических цепей
Может кто-нибудь знает хорошую программу для моделирования электрических цепей?

Упрощение электрических цепей
Не могу упростить схему, вроде нужен метод эквивалентных преобразований, не могу понять как применить (на упрощенной схеме отсутствуют...

Теория электрических цепей
Доброго всем времени суток. В универе сейчас началась дисциплина под названием &quot;Теория электрических цепей&quot;. Там надо решить...


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru