Архитектура программного комплекса «Электродизайнер»
1. Создание кнопки на палитре компонентов.
2. Создание нового типа компонента – объекта
3. Создание нового типа компонента связи.
5. Создание редакторов свойств.
6. Интерфейс редактора формул.
6.1.1 Интерфейс класса MathFormula.
6.1.2 Интерфейс класса ObjectFormulaTree.
6.1.3 Интерфейс класса ElementaryObjectArgument.
6.2 Графический интерфейс редактора формул.
6.2.1 Графический интерфейс класса MathFormula.
6.2.2 Интерфейс класса FormulaEditorUI.FormulaEditorForm
7. Выполнение однотипных операций со всеми элементами
рабочего поля.
8. Источники и потребители информации.
8.2 Краткое описание интерфейса
DataPerformer.IMeasurements
8.3 Краткое описание интерфейса DataPerformer.IMeasure
8.4 Краткое описание интерфейса
DataPerformer.IDataConsumer
8.5 Краткое описание интерфейса
DataPerformer.IDifferentialEquationSolver
Программный комплекс «Электродизанер» позволяет строить сценарии, построенные при помощи объектов и связей. Объекты и связи редактируются при помощи графического конфигуратора. Использование конфигуратора заключается в следующем. Мы нажимаем кнопку нужного нам объекта на палитре (см. рис. 1). Далее мы делаем щелчок мышью на рабочем поле. После этого на рабочем поле появляется прямоугольный компонент, соответствующего объекта. Для установки связи надо выбрать кнопку связи на палитре нажать мышку на компоненте первого из связываемых объектов, перетащить её, не отпуская кнопки, на компонент второго объект и затем отпустить кнопку мыши. Вызов редакторов свойств объектов и связей осуществляется путём нажатия правой кнопки мыши на квадрате соответствующего компонента. Щелчок мышью в верхней части компонента позволяет редактировать имя соответствующего объекта или связи. Направление стрелки связи совпадает с направлением ассоциации. Например, если нам надо задать положение объекта B относительно объекта A, то соответствующая стрелка направлена от B к A, поскольку положение A не зависит от положения B, но не наоборот. Аналогично если B является результатом трансформации A или, B находится под воздействием электромагнитного излучения A, то стрелка должна идти от B к А.
Рис 1. Графический
конфигуратор объектов и связей.
Создание нового типа объекта и или связи состоит из следующих операций:
- создание кнопки на палитре компонентов;
- создание класса соответствующего компонента;
- создание редактора свойств;
Ниже будет приведено подробное описание этих операций.
Для
создания кнопки необходимо сделать её идентификационный номер. Номера кнопок
находятся в перечислении ElectromagneticUI.ButtonKinds
Это перечисление выглядит следующим образом
/// <summary>
/// Kinds of buttons
/// </summary>
public enum ButtonKinds
{
Multifacets, Dipole, Camera, RelativeMeasure,
CameraLink, Frame, MovedFrame, RadiationLink,
RelativeMeasureLink, MeasureLink,
GraphConsumer, FunctionConsumer, Volt, VoltLink,
DirectionDiagram, SphericalHarmonics,
Mirror, MirrorLink, FormulaFigure, Earth,
FormulaTransformer,
FormulaTransformerLink, FileFigure, TemplateFigure, FrameFormula,
FlatWave, Turbine, PhaseSensor,
PhaseSensorLink, SwitchLink, DifferentialEquation, FrameData,
FrameDataLink, StateMachine, Nulling,
NullingLink, Doppler, DopplerObject, DopplerFrame,
VectorFormulaConsumer, MultiFacesSpectrum,
SpectrumFigure, SpectrumRadiator, MultiFacesSpectrumSum,
MultiFacesSpectrumSumLink,
FlatWavesConsumer, FlatRadiatorLink, FlatConsumerLink, Series,
UnaryLink, Regression, RegressionLink
};
Новый компонент необходимо добавлять в конец данного перечисления. Далее нужно создать икону компонента. Данная операция производится следующим образом
В функцию FormsDiagramUI.FormDiagramUI.Prepare() добавляется код, который имеет примерно следующий вид
imageListSh.Images.Add(Image.FromFile("Turbine.ico"));
Здесь imageListSh является списком икон соответствующей
панели. При этом “Turbine.ico” представляет имя файла иконы.
Далее в
рассмотренной функции добавляется кнопка. Для этого в ту же функцию добавляется
код.
new PaletteButton(ObjectsToolSh, (int)ButtonKinds.Turbine, "Turbine",
PanelDesktop.GetResourceString("Turbine"), imageListSh.Images[9], 9, false);
Здесь
-
ObjectsToolSh является панелью на
которую устанавливается кнопка;
-
(int)ButtonKinds.Turbine – номер соответствующего компонента;
-
"Turbine" – представляет собой дополнительный текст (в ряде
случаев он связан с именем вспомогательного файла).
-
PanelDesktop.GetResourceString("Turbine") – является хинтом соответствующей кнопки.
-
imageListSh.Images[9] – икона кнопки.
-
9 - номер иконы.
-
false – означает что кнопка не используется для компонента – связи
(она используется для компонента – объекта).
Новый тип компонента – объекта представляет собой класс, реализующий интерфейсы CategoryTheory.ICategoryObject и ISerializable.
Класс должен иметь атрибут [Serializable()] . Для того, чтобы создавались объекты данного класса необходимо добавить необходимый код в фабрику объектов. В нашем случае фабрикой объектов является класс ElectromagneticUI.ElectromagneticUIFactory . Объекты создаются функцией
ICategoryObject ElectromagneticUI.ElectromagneticUIFactory.CreateObject(PaletteButton button)
Данная функция имеет входным параметром соответствующую объекту кнопку и возвращает нужный объект. В приведённом ниже фрагменте данной функции показано, как создаётся объект – турбина.
else if (button.Kind == (int)ButtonKinds.Turbine)
{
return
new Turbine();
}
Новый тип компонента – связи представляет собой класс, реализующий интерфейсы CategoryTheory.ICategoryArrow и ISerializable.
Класс должен иметь атрибут [Serializable()] . Для того, чтобы создавались объекты данного класса необходимо добавить необходимый код в фабрику объектов Объекты создаются функцией
ICategoryArrow ElectromagneticUI.ElectromagneticUIFactory.CreateArrow(PaletteButton button)
Данная функция имеет входным параметром соответствующую объекту кнопку и возвращает нужный объект. В приведённом ниже фрагменте данной функции показано, как создаётся связь жёсткой геометрической привязке.
if
(button.Kind == (int)ButtonKinds.Frame)
{
return
new ReferenceFrameArrow();
}
Интерфейс ICategoryArrow имеет два ключевых свойства.
/// <summary>
/// The source of this arrow
/// </summary>
ICategoryObject Source
{
get;
set;
}
/// <summary>
/// The target of this arrow
/// </summary>
ICategoryObject Target
{
get;
set;
}
Они представляют собой начало и конец связи соответственно. Их надо реализовать таким образом, чтобы происходила проверка корректности выбора начала и конца связи, а также другие действия, обусловленные логикой связи. Пример реализации связи представлен следующим кодом (Данный пример иллюстрирует добавление в поле зрения 3D визуализатора нового трёхмерного объекта).
/// <summary>
/// The source of this arrow
/// </summary>
public
ICategoryObject Source
{
get
{
return
camera;
}
set
{
if
(visible == value)
{
throw new
Exception("Target of visible link should not concide with source");
}
if
(! (value is
CameraUI))
{
throw new
Exception("Illegal source");
}
camera = value as CameraUI;
}
}
/// <summary>
/// The target of this arrow
/// </summary>
public
ICategoryObject Target
{
get
{
return
visible as ICategoryObject;
}
set
{
if
(camera == null)
{
throw new
Exception("Camera is missing");
}
if
(camera == value)
{
throw new
Exception("Target of visible link should not concide with source");
}
if
(! (value is
IVisible))
{
throw new
Exception("Illegal target");
}
visible = value as IVisible;
camera.Add(visible); //Adding visible object
if
(visible is SphereUI)
{
}
}
}
На данном примере мы видим, что производится проверка корректности. При некорректном выборе начала или конца стрелки выбрасываются исключения. Кроме того, в строке помеченной красным цветом происходит добавление в поле видимости 3D визуализатора нового объекта.
В ряде случаев при удалении объекта или связи необходимо осуществить ряд дополнительных операций. В подобной ситуации объект или связь должны реализовывать интерфейс CategoryTheory.IRemovableObject В приведённом ниже коде показано как это делается для рассмотренной выше связи с 3D визуализатором
/// <summary>
/// The post remove operation
/// </summary>
public
void RemoveObject()
{
if
(camera == null)
{
return;
}
if
(visible == null)
{
return;
}
camera.Remove(visible);
}
Данный код осуществляет удаление объекта из поля видимости визуализатора.
Редакторы свойств и связей объектов представляют собой формы Windows. создаются в фабрике объектов. Редакторы свойств связаны с визуальными компонентами рабочего поля. Последние представляют собой объекты типа ObjectLabel и ArrowLabel, причём оба этих типа являются наследниками класса NamedComponent. Класс ObjectLabel имеет свойство ICategoryObject Object, представляющее собой ассоциированный с компонентом объект. Класс ArrowLabel имеет свойство ICategoryArrow, представляющее собой ассоциированную связь, ассоциированную с компонентом. Кроме того сам класс NamedComponent имеет свойство ComponentName, которое должно отображаться в заголовке редактора свойств.
Для создания экземпляров редакторов свойств, служит следующая функция фабрики классов
Form CreateForm(NamedComponent comp)
Ниже приведен пример
создания форм в данной функции
public Form CreateForm(NamedComponent comp)
{
if (comp is ArrowLabel) //Создание редакторов
свойств связей
{
ArrowLabel lab = comp as ArrowLabel;
ICategoryArrow arrow = lab.Arrow;
if
(arrow is LinearMovedReferenceFrameArrow)
{
return
new FormMovedFrame(lab);
}
if
(arrow is FrameFormula)
{
return
new FormFormulaFrame(lab);
}
if
(arrow is ReferenceFrameArrow)
{
return
new FormFrame(lab);
}
return
new DefaultForm(comp);
}
if (comp is ObjectLabel)//Создание редакторов свойств объектов
{
ObjectLabel objLabel = comp as ObjectLabel;
ICategoryObject obj =
objLabel.Object;
if
(obj is CameraUI)
{
CameraUI camera = obj as CameraUI;
return
new FormCamera(camera, objLabel);
}
if
(obj is DipoleUI)
{
return
new FormDipole(objLabel);
}
return
new DefaultForm(comp);
}
return
null;
}
Конструктор редактора свойств
выглядит примерно следующим образом.
/// <summary>
/// Constructor
/// </summary>
/// <param
name="label">Desktop component</param>
public FormDipole(ObjectLabel label)
{
InitializeComponent(); //
Инициализация компонент формы
DiagramUI.DefaultForm.LoadControlResources(this);
// Загрузка ресурсов this.label = label; // Присвоение компонента
dipole = label.Object as DipoleUI; // Связанный с
компонентом объект
// Дополнительные операции
UpdateFormUI(); //
Присвоение имени заголовка формы
}
Для того чтобы заголовок свойств редактора совпадал с именем
соответствующего объекта, редактор должен реализовывать интерфейс DiagramUI.IUpdatableForm.
Ниже приведён пример реализации
данного интерфейса.
/// <summary>
/// Updates form UI
/// </summary>
public void UpdateFormUI()
{
Text = label.ComponentName;
labelSource.Text =
label.Source.ComponentName;
labelTarget.Text =
label.Target.ComponentName;
}
В данном примере осуществляется не
только изменение заголовка формы, но и текстов меток.
Для того, чтобы при уничтожении
редакторов уничтожались ссылки на них, необходима модификация метода Dispose. Ниже приведён соответствующий
фрагмент кода.
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool
disposing )
{
if( disposing )
{
if(components
!= null)
{
components.Dispose();
}
}
label.RemoveForm(false);
base.Dispose(
disposing );
}
Красной строкой отмечен оператор
уничтожение ссылки.
Классы вычислительного интерфейса
редактора формул расположен в пространстве имён FormulaEditor.
Основными
его классами являются
MathFormula
–
собственно формула.
ObjectFormulaTree – вычислительное дерево.
ElementaryObjectArgument – аргумент формулы.
Конструкция
формулы из строки.
public static
MathFormula FromString(int[] sizes, string str)
sizes – массив размеров символов. Первый элемент массива представляет собой высоту основных символов формулы, второй высоту степеней, третий высоту степеней, степеней и т.д. В программе в качестве этого параметра подставляется.
FormulaEditorUI.FormulaEditorPanel.sizes.
str - строковое представление формулы. В программном комплексе строковое представление создаётся при помощи графического интерфейса.
Преобразование формулы в
строку.
public string FormulaString
{
get;
}
Данное преобразование является обратным предыдущему. Оба этих преобразования служат для импорта/экспорта формул, записи/чтения их в потоки/из потоков.
Преобразование формулы для построения дерева.
public MathFormula FullTransform
{
get;
}
Вспомогательное преобразование формулы, в результате которого формулу можно использовать для построения вычислительного дерева.
public ObjectFormulaTree(MathFormula formula,
IFormulaObjectCreator creator)
formula – формула из которой строится
дерево.
creator
– интерпретатор формулы
(обычно
ElementaryFunctionsCreator.Object)
public object Result
Данное свойство возвращает
вычисленное значение.
Построение частной производной.
DerivationPerformer.Derivation(ObjectFormulaTree
tree, string s)
s – строка в которой содержится переменная дифференцирования,
например Deriv(“y”) вычисляет производную по y.
Данная функция строит дерево
производной.
Построение формулы из дерева.
public MathFormula
FormulaCreator.CreateFormula(ObjectFormulaTree tree, byte
level, int[] sizes)
level – уровень формулы равный нулю для основной формулы,
единице для формулы – степени и т.д.
sizes – массив размеров символов. Первый элемент массива представляет собой высоту основных символов формулы, второй высоту степеней, третий высоту степеней, степеней и т.д. В программе в качестве этого параметра подставляется.
FormulaEditorUI.FormulaEditorPanel.sizes.
Переменные формулы
(формул).
static public string
ElementaryObjectDetector.GetVariables(MathFormula formula)
static public string ElementaryObjectDetector.GetVariables(MathFormula[]
formulas)
Возвращает строку переменных формулы.
Данный класс представляет собой аргумент
формулы.
public ElementaryObjectArgument()
Строка аргументов.
public string Variables
{
get;
}
Связывание с деревом (деревьями).
public void
Add(ObjectFormulaTree tree)
public void
Add(ObjectFormulaTree[] trees)
public object this[char s]
{
set;
}
++++++++++++++++++++++++++++++++++++++++
Ниже приведён пример вычисления
формулы при x = 2 и y = 5
MathFormula f =
formula.FullTransform;
ObjectFormulaTree tree
= new ObjectFormulaTree(f, ElementaryFunctionsCreator.Object);
ElementaryObjectArgument
arg = new ElementaryObjectArgument();
arg.Add(tree);
arg[‘x’] = 2;
arg[‘y’] = 5;
double a = (double)tree.Result;
Графический интерфейс позволяет строить визуальные изображения объектов класса MathFormula, а также включает формы редактора и панели отображения формул.
Положение формулы.
public Point Position
{
set;
get;
}
Расчёт прямоугольника формулы.
public virtual void CalculateFullRelativeRectangle()
Данная функция является вспомогательной и должна быть вызвана перед графическим отображением.
Расчёт позиций символов формулы.
public void
CalculatePositions()
Данная функция является вспомогательной и должна быть вызвана перед графическим отображением.
Рисование формулы.
public void
Draw(Graphics g)
g – Графический элемент, на котором производится рисование.
+++++++++++++++++++++++++
Ниже
приводится пример рисования формулы.
///Построение
формулы из строки
formula
= MathFormula.FromString(FormulaEditorPanel.Sizes, str);
formula.Position
= pointFormula; // Задание позиции формулы
//Подготовительные
операции
formula.CalculateFullRelativeRectangle();
formula.CalculatePositions();
formula.Draw(g); //Рисование
формулы
Рассматриваемый класс является формой, позволяющей редактировать формулу
Конструктор
public FormulaEditorForm(string s)
s – переменные редактора формул
Строковое представление формулы.
public string Formula { get; set;}
В приведённом ниже примере рассмотрено редактирование формулы
и рисование её на экране.
string s =
formula.FormulaString; // Преобразование формулы в строку
FormulaEditorForm form = new FormulaEditorForm("xy"); // Создание экземпляра //редактора с переменными x и y
form.Formula = s; // Экспорт формулы
в редактор
form.ShowDialog(this); // Редактирование
формулы
s = form.Formula; // Импорт формулы
из редактора
formula
= MathFormula.FromString(FormulaEditorPanel.sizes, s); //
Создние ///новой формулы
formula.Position
= pointFormula; //
Задание позиции формулы
//Подготовительные операции
formula.CalculateFullRelativeRectangle();
formula.CalculatePositions();
Graphics
g = Graphics.FromHwnd(this.Handle);
formula.Draw(g); //Рисование формулы
При решении ряда задач возникает необходимость выполнения однотипных операций со всеми элементами рабочего поля. Например, нужно для всех радиационных произвести подсветку всех облучаемых объектов. Рабочее поле имеет тип DiagramUI.PanelDesktop и является наследником стандартного класса Panel. Последний имеет свойство – коллекцию Controls. Это свойство содержит все компоненты, находящиеся на данной панели. Используя его можно производить однотипные операции со всеми компонентами. Ниже приведён фрагмент кода, который выполняет операции обновления всех компонент, которые реализуют интерфейс обновления IUpdatableObject.
foreach (Control c in
desktop.Controls)
// Цикл по компонентам рабочего поля
{
if (c is ObjectLabel)// Операция для компонент, соответствующих объектам
{
ObjectLabel label = c as ObjectLabel;
ICategoryObject obj = label.Object;
if
(obj is IUpdatableObject) // Выбор нужных объектов
{
IUpdatableObject updatable =
obj as IUpdatableObject;
if
(updatable.ShouldUpdate) // Проверка условия
{
updatable.UpdateObject();// Проведение операции
}
}
}
else if
(c is ArrowLabel)// Операция для компонент, соответствующих //стрелкам
{
ArrowLabel label = c as ArrowLabel;
ICategoryArrow arr = label.Arrow;
if (arr
is IUpdatableObject)
{
IUpdatableObject updatable =
arr as IUpdatableObject;
if
(updatable.ShouldUpdate)
{
updatable.UpdateObject();
}
}
}
}
Источниками информации являются объекты, реализующие интерфейс DataPerformer.IMeasurements, а потребителями – объекты, реализующие интерфейс DataPerformer.IDataConsumer. Почти все потребители являются наследниками класса DataPerformer.DataConsumer, реализующего указанный выше интерфейс. Потребители связываются с источниками стрелками типа DataPerformer.DataLink. Логика работы источников/потребителей информации заключается в следующем. Потребитель, используя метод “void UpdateChildrenData()” опрашивает связанные источники информации которые в свою очередь вызывают метод «void UpdateMeasurements()» производя, необходимые операции по подготовке нужной информации. Следует отметить, что потребитель информации может быть одновременно и источником (см. Version 1.0). Во избежание порочного круга, мы можем связывать источник информации с потребителем, только в том случае, если потребитель создан позднее, чем источник.
Работа с источниками измерений, включающими формулы, разбивается на этапы. Если произошли изменения на этапе n, то необходимо повторить этапы n+1, n+2, … .
Этап 1.
Ввод формул и их подтверждение. После выполнения данной операции формируется список переменных формул. Значения части переменных, затем будет экспортироваться из внешних источников измерений. Оставшиеся переменные являются константами (они также входят в состав псевдонимов).
Этап 2.
Выбор констант. На данном этапе выбирается состав констант. Рассмотрим следующий сценарий.
Редактор свойств компонента First выглядит следующим образом (Загрузить сценарий).
В данном сценарии обе переменных формулы
представляют собой константы. Редактор свойств компонента Second имеет вид.
Редактор свойств компонента Second имеет вид.
Здесь только одна переменная является константой. Остальные две берутся из внешнего источника.
Этап 3.
Связь параметров с источниками данных. На данном этапе переменные связываются с внешними источниками данных. На этом этапе производится компиляция формул, поскольку компиляция невозможна до того, как определены типы переменных формулы.
В данном сценарии имеется одна константа “z”. Остальные переменные связываются с параметрами Formula_1 и Formula_2 компонента First.
Рассмотрим другой пример с той же диаграммой, что и выше. (Загрузить сценарий) Редакторы свойств компонентов First и Second выглядят следующим образом
Редактор
свойств компонента First
Редактор
свойств компонента Second.
В редакторе свойств First результат второй формулы является булевым. Соответственно первая переменная x первой формулы компонента должна быть булевой (иначе интерпретатор формулы выдаст ошибку) Соответственно она связывается с булевым результатом компонента First.
Этап 4.
Задание значений констант.
Данный интерфейс имеет свойство Count представляющее собой количество измеряемых параметров.
Свойство
IMeasure this[int n]
осуществляет доступ к n
– му измеряемому параметру. См. 8.3
Свойство
Control
HeaderControl
Представляет собой оконный компонент, который отображается в формах
связанных с данным источником измерений. Обычно его можно определить следующим
образом.
public Control HeaderControl
{
get
{
ObjectLabel lab = Object as ObjectLabel;
return
new ObjectPanel(lab);
}
}
Свойство
string SourceName
представляет собой имя источника
измерений
Обычно его можно задать следующим образом
NamedComponent
nc = Object as NamedComponent;
return nc.ComponentName;
Свойство
bool IsUpdated
предназначено для того, чтобы не было
многократного пересчёта. После вызова метода UpdateMeasurements() нужно это свойство сделать равным false.
Метод
void UpdateMeasurements();
Данный
метод осуществляет вычисление всех измеряемых параметров. Обычно данный метод
заполняет рассчитывает значения измеряемых параметров и их производных, а затем
заполняет двумерный массив result этими значениями. (В случае когда класс реализует интерфейс IDifferentialEquationSolver
данная операция
осуществляется в методе CalculateDerivations.)
Свойство
MeasureParameter
Parameter
Возвращает делегат – функцию
вычисления параметра
Свойство
MeasureParameter
Derivation
Возвращает делегат – функцию
вычисления производной.
Свойство
string Name
возвращает имя параметра
Свойство
double Factor
Чаще всего равно единице
Свойство
object Type
Возвращает объект – тип параметра.
Для вещественных параметров этот тип равен
Double a = 0;
Чаще всего интерфейс реализован в
виде класса DataPerformer.Measure
При этом функция UpdateMeasurements();
интерфейса IMeasurements
имеет вид
public void
UpdateMeasurements()
{
result[0, 0] = ... /// Первый параметр
result[0, 1] = ... /// Производная первого
параметра
}
Далее в классе, реализующем интерфейс
IMeasurements определяются делегаты, имеющие
примерно следующий вид.
private object
getFirstParameter()
{
return
result[0, 0];
}
private object
getFirstDerivation()
{
return result[0, 1];
}
И, наконец, создаётся объект типа DataPerformer.Measure следующим конструктором.
Double
a = 0;
measures[0] = new
Measure(a, new MeasureParameter(getFirstParameter),
new MeasureParameter(getFirstDerivation),
“First”);
Метод
void AddTargetArrow(DataLink arrow);
Добавляет связь с источником
измерений. Обычно осуществляется добавление к объекту типа ArrayList.
Метод
void RemoveTargetArrow(DataLink arrow)
Очевидно.
Метод
void
UpdateChildrenData();
Осуществляет обновление источников
измерений. Обычно имеет вид
public void
UpdateChildrenData()
{
try
{
foreach
(DataLink arrow in arrows) /// arrows представляет собой ArrayList связей с источниками измерений
{
IMeasurements m =
arrow.Measurements;
m.UpdateMeasurements();
}
}
catch
(Exception e)
{
NamedComponent.ThrowException(this, e);
}
}
Свойство
int Count
Количество источников измерений.
Свойство
DataLink
this[int n]
Связь с n – м источником измерений. Сам источник измерений
представляет собой свойство Measurements объекта
типа DataLink.
Метод
void Reset();
Данный метод рекурсивно ставит значение
свойства IsUpdated
всех источников измерений в
положение false. Данную операцию можно осуществить следующим
образом
DataConsumer.Reset(this);
IDifferentialEquationSolver
имеет
следующие методы.
Метод
void CalculateDerivations();
Вычисляет значения производных и записывает их значения в элементы массива result.
Метод
void SetVariables(int b, double[] x);
Считывает переменные из вспомогательного массива. Обычно это выглядит примерно следующим образом.
public void SetVariables(int b, double[] x)
{
int i = b;
foreach (object[] o in
variables.Values)
{
o[3] = x[i];
++i;
}
}
}
Данный класс осуществляет связь переменных формулы с внешними внешними параметрами. Интерфейс данного класса представлен ниже.
Информация о внешних источниках информации содержится в объекте типа ArrayList, который обычно называется arguments. Этот объект должен быть сериализован. Каждый элемент данного объекта является строкой, примерный вид которой приведён ниже.
"y = First.Formula_1"
Данная строка означает что переменная “y” формулы связана с выходным параметром “Formula_1” компонента First. После десериализации связей РМП вызывает метод PostSetArrow() который имеет вид.
public void PostSetArrow()
{
DynamicalParameter parameter = new DynamicalParameter();
foreach
(DataLink arrow in arrows)
{
IMeasurements
measurements = arrow.Measurements;
IAssociatedObject
ass = measurements as IAssociatedObject;
NamedComponent nc = ass.Object as NamedComponent;
string
name = nc.ComponentName;
for
(int i = 0; i < measurements.Count; i++)
{
IMeasure measure = measurements[i];
string
p = name + "." + measure.Name;
foreach
(string s in
arguments)
{
if
(s.Substring(4).Equals(p))
{
char c = s[0];
parameter.Add(c,
measure);
}
}
}
}
foreach (string s in
arguments)
{
if
(s.Substring(4).Equals("Time"))
{
parameter.Add(s[0],
ElectromagneticUIFactory.Object.TimeMeasure);
}
}
Parameter = parameter;
string
argStr = AllVariables;
foreach (string key in
parameters.Keys)
{
arg[key[0]] = parameters[key];
}
postSetUnary();
}
Помимо переменных формул взятых из внешних источников имеются также псевдонимы. Они, как правило, хранятся в таблице Hashtable parameters. Ключами данной таблицы являются соответствующие переменные формул. Значениями являются соответствующие значения этих параметров. Данная таблица должна быть сериализована.
Задание.
На приведённом рисунке изображён сценарий
с источниками и
потребителями информации. Когда обновляются данные потребителя объекта Graph обновление
источников информации. Данная схема вместо однократного обновления компонентов F1 и F2 осуществляет
двукратное. Необходима доработка программы с целью исключения многократного
обновления. Для этого в интерфейс DataPerformer.IMeasurements должно быть
добавлено свойство IsUpdated. После обновления источника Это свойство должно
становиться равным true. В классе DataPerformer.DataConsumer необходимо
реализовать статическую функцию
void
ResetMeasurements(PanelDesktop desktop).
Данная функция должна у всех
источников измерений ставит значение свойству IsUpdated значение false.
Задание 2.
Реализовать решение системы
дифференциальных уравнений методами рунге кутта и адамса,в духе проекта.
В проекте метод Рунге Кутта
реализован в классах
DataPerformer.DifferentialEquationProcessor
и
DataPerformer.RungeProcessor
Метод Рунге Кутта описан в