Compare commits

...

8 Commits

  1. 57
      Signal Generator/DrawTask.cs
  2. 2
      Signal Generator/MainWindow.xaml
  3. 24
      Signal Generator/MainWindow.xaml.cs
  4. 27
      Signal Generator/ProcedureModel.cs
  5. 43
      Signal Generator/Settings.cs
  6. 1
      Signal Generator/Signal Generator.csproj
  7. 1
      Signal Generator/Signal/Base/AnalogSignalMethods.cs
  8. 1
      Signal Generator/Signal/Base/Parameter.cs
  9. 15
      Signal Generator/Signal/FmSignal.cs
  10. 12
      Signal Generator/Signal/MultiSignal.cs
  11. 13
      Signal Generator/Signal/SinusoidalSignal.cs
  12. 23
      Signal Generator/StringDoubleConverter.cs
  13. 13
      Signal Generator/TaskWindow.xaml

57
Signal Generator/DrawTask.cs

@ -54,28 +54,42 @@ namespace Signal_Generator
private void drawSignalAtCanvas() private void drawSignalAtCanvas()
{ {
double lastX = 0, lastY = 0; double lastX = 0, lastY = 0;
double w = canvas.ActualWidth; double W = canvas.ActualWidth;
for (int i = 0; i != (int)w; i++) double dX = (procedureModel.Duration / 1000) / W;
for (int X = 0; X != (int)W; X++)
{ {
procedureModel.CurrentAmplitude = multiSignal.currentAmplitude(i / 5.0).ToString(); double Y = multiSignal.currentAmplitude(X * dX);
procedureModel.CurrentTime = (i / 5.0).ToString(); updateTextBoxProps(Y, X * dX * 1000);
double y = multiSignal.currentAmplitude(i / 5.0); drawLine(lastX, lastY, X, Y);
drawLine(lastX, lastY, i, y); lastX = X;
lastX = i; lastY = Y;
lastY = y; if (taskSemaphore() == false) return;
Thread.Sleep(10);
switch (state)
{
case State.Paused:
while (state == State.Paused)
Thread.Sleep(10);
break;
case State.Canceled: return;
}
} }
state = State.Finished; state = State.Finished;
} }
private bool taskSemaphore()
{
Thread.Sleep(10);
switch (state)
{
case State.Paused:
while (state == State.Paused)
Thread.Sleep(50);
break;
case State.Canceled: return false;
}
return true;
}
private void updateTextBoxProps(double amp, double time)
{
amp = Math.Round(amp, 2);
time = Math.Round(time, 2);
procedureModel.CurrentAmplitude = amp.ToString();
procedureModel.CurrentTime = time.ToString();
}
private void drawLine(double x1, double y1, double x2, double y2) private void drawLine(double x1, double y1, double x2, double y2)
{ {
Action a = () => { Action a = () => {
@ -83,18 +97,17 @@ namespace Signal_Generator
l.StrokeThickness = 1; l.StrokeThickness = 1;
l.Stroke = Brushes.Red; l.Stroke = Brushes.Red;
l.X1 = x1; l.X1 = x1;
l.Y1 = remap(y1); l.Y1 = remapOY(y1, 100, canvas.ActualHeight);
l.X2 = x2; l.X2 = x2;
l.Y2 = remap(y2); l.Y2 = remapOY(y2, 100, canvas.ActualHeight);
canvas.Children.Add(l); canvas.Children.Add(l);
}; };
canvas.Dispatcher.Invoke(a); canvas.Dispatcher.Invoke(a);
} }
private double remap(double x, double oldMin = -100.0, double oldMax = 100.0, double newMin = 100.0, double newMax = 0.0) private double remapOY(double x, double amp = 100.0, double height = 100.0)
{ {
newMin = canvas.ActualHeight; return height + (x + amp) * (-height) / (2 * amp);
return newMin + (x - oldMin) * (newMax - newMin) / (oldMax - oldMin);
} }
} }
} }

2
Signal Generator/MainWindow.xaml

@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Signal_Generator" xmlns:local="clr-namespace:Signal_Generator"
mc:Ignorable="d" mc:Ignorable="d"
Title="Генератор сигналов" Height="450" Width="600"> Title="Генератор сигналов" Height="450" Width="600" Closing="Window_Closing">
<Grid Margin="10"> <Grid Margin="10">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>

24
Signal Generator/MainWindow.xaml.cs

@ -23,14 +23,15 @@ namespace Signal_Generator
{ {
AddSignalWindow addSignalWindow_Instance; AddSignalWindow addSignalWindow_Instance;
TaskWindow taskWindow_Instance; TaskWindow taskWindow_Instance;
ObservableCollection<IAnalogSignal> signalCollection; MultiSignal multiSignal = MultiSignal.getInstance();
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
signalCollection = new ObservableCollection<IAnalogSignal>(); var c = Properties.Settings.LoadSignals();
if (c != null) multiSignal.signals = c;
signals_ListBox.Items.Clear(); signals_ListBox.Items.Clear();
signals_ListBox.ItemsSource = signalCollection; signals_ListBox.ItemsSource = multiSignal.signals;
} }
private void addSignal_Button_Click(object sender, RoutedEventArgs e) private void addSignal_Button_Click(object sender, RoutedEventArgs e)
@ -52,18 +53,13 @@ namespace Signal_Generator
var signal = null as IAnalogSignal; var signal = null as IAnalogSignal;
signal = (IAnalogSignal) addSignalWindow_Instance.signalType_ComboBox.SelectedItem; signal = (IAnalogSignal) addSignalWindow_Instance.signalType_ComboBox.SelectedItem;
if (addSignalWindow_Instance.signalType_ComboBox.SelectedItem == null) return; if (addSignalWindow_Instance.signalType_ComboBox.SelectedItem == null) return;
signalCollection.Add(signal); multiSignal.Add(signal);
addSignalWindow_Instance.Close(); addSignalWindow_Instance.Close();
} }
private void startProcedure_Button_Click(object sender, RoutedEventArgs e) private void startProcedure_Button_Click(object sender, RoutedEventArgs e)
{ {
IsEnabled = false; IsEnabled = false;
MultiSignal ms = MultiSignal.getInstance();
foreach (IAnalogSignal item in signalCollection)
{
ms.add(item);
}
taskWindow_Instance = new TaskWindow(); taskWindow_Instance = new TaskWindow();
taskWindow_Instance.Show(); taskWindow_Instance.Show();
taskWindow_Instance.Closed += enableMainWindow; taskWindow_Instance.Closed += enableMainWindow;
@ -71,8 +67,14 @@ namespace Signal_Generator
private void removeSignal_Button_Click(object sender, RoutedEventArgs e) private void removeSignal_Button_Click(object sender, RoutedEventArgs e)
{ {
if (signals_ListBox.SelectedIndex == -1) return; if (signals_ListBox.SelectedItem == null) return;
signalCollection.RemoveAt(signals_ListBox.SelectedIndex); var x = signals_ListBox.SelectedItem as IAnalogSignal;
multiSignal.Remove(x);
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Properties.Settings.SaveSignals(multiSignal.signals);
} }
} }
} }

27
Signal Generator/ProcedureModel.cs

@ -45,7 +45,7 @@ namespace Signal_Generator
var btn = parameters[0] as Button; var btn = parameters[0] as Button;
var ms = MultiSignal.getInstance(); var ms = MultiSignal.getInstance();
if ((ms == null) || (ms.count() == 0)) if ((ms == null) || (ms.Count() == 0))
return false; return false;
switch (btn.Name) switch (btn.Name)
{ {
@ -65,14 +65,11 @@ namespace Signal_Generator
if (currentTask == null) return "Запустить"; if (currentTask == null) return "Запустить";
switch (currentTask.state) switch (currentTask.state)
{ {
case DrawTask.State.Created:
return "Запустить";
case DrawTask.State.Running: case DrawTask.State.Running:
return "Завершить";
case DrawTask.State.Paused: case DrawTask.State.Paused:
goto case DrawTask.State.Running; return "Завершить";
default: default:
goto case DrawTask.State.Created; return "Запустить";
} }
} }
@ -81,14 +78,12 @@ namespace Signal_Generator
if (currentTask == null) return new Tuple<bool, string>(false, "Пауза"); if (currentTask == null) return new Tuple<bool, string>(false, "Пауза");
switch (currentTask.state) switch (currentTask.state)
{ {
case DrawTask.State.Created:
return new Tuple<bool, string>(false, "Пауза");
case DrawTask.State.Running: case DrawTask.State.Running:
return new Tuple<bool, string>(true, "Пауза"); return new Tuple<bool, string>(true, "Пауза");
case DrawTask.State.Paused: case DrawTask.State.Paused:
return new Tuple<bool, string>(true, "Возобновить"); return new Tuple<bool, string>(true, "Возобновить");
default: default:
goto case DrawTask.State.Created; return new Tuple<bool, string>(false, "Пауза");
} }
} }
@ -113,14 +108,13 @@ namespace Signal_Generator
private void startOrCancelTask () private void startOrCancelTask ()
{ {
targetCanvas.Children.Clear();
if (currentTask != null) if (currentTask != null)
switch (currentTask.state) switch (currentTask.state)
{ {
case DrawTask.State.Paused: case DrawTask.State.Paused:
goto case DrawTask.State.Running;
case DrawTask.State.Running: case DrawTask.State.Running:
currentTask.state = DrawTask.State.Canceled; currentTask.state = DrawTask.State.Canceled;
targetCanvas.Children.Clear();
return; return;
} }
Action newAction = () => Action newAction = () =>
@ -167,5 +161,16 @@ namespace Signal_Generator
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentTime")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentTime"));
} }
} }
private double duration = 1000;
public double Duration
{
get { return duration; }
set
{
duration = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentTime"));
}
}
} }
} }

43
Signal Generator/Settings.cs

@ -1,4 +1,10 @@
namespace Signal_Generator.Properties { using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows;
namespace Signal_Generator.Properties {
// Этот класс позволяет обрабатывать определенные события в классе параметров: // Этот класс позволяет обрабатывать определенные события в классе параметров:
@ -11,9 +17,9 @@
public Settings() { public Settings() {
// // Для добавления обработчиков событий для сохранения и изменения параметров раскомментируйте приведенные ниже строки: // // Для добавления обработчиков событий для сохранения и изменения параметров раскомментируйте приведенные ниже строки:
// //
// this.SettingChanging += this.SettingChangingEventHandler; //this.SettingChanging += this.SettingChangingEventHandler;
// //
// this.SettingsSaving += this.SettingsSavingEventHandler; //this.SettingsSaving += this.SettingsSavingEventHandler;
// //
} }
@ -24,5 +30,36 @@
private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
// Добавьте здесь код для обработки события SettingsSaving. // Добавьте здесь код для обработки события SettingsSaving.
} }
public static void SaveSignals(ObservableCollection<IAnalogSignal> signals)
{
try
{
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream fs = new FileStream("settings.dat", FileMode.OpenOrCreate))
{
formatter.Serialize(fs, signals);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Не удалось сохранить результаты работы");
}
}
public static ObservableCollection<IAnalogSignal> LoadSignals()
{
BinaryFormatter formatter = new BinaryFormatter();
try
{
using (FileStream fs = new FileStream("settings.dat", FileMode.Open))
{
return (ObservableCollection<IAnalogSignal>)formatter.Deserialize(fs);
}
} catch
{
return null;
}
}
} }
} }

1
Signal Generator/Signal Generator.csproj

@ -66,6 +66,7 @@
<Compile Include="Signal\Base\Parameter.cs" /> <Compile Include="Signal\Base\Parameter.cs" />
<Compile Include="Signal\SinusoidalSignal.cs" /> <Compile Include="Signal\SinusoidalSignal.cs" />
<Compile Include="ArrayConverter.cs" /> <Compile Include="ArrayConverter.cs" />
<Compile Include="StringDoubleConverter.cs" />
<Compile Include="TaskWindow.xaml.cs"> <Compile Include="TaskWindow.xaml.cs">
<DependentUpon>TaskWindow.xaml</DependentUpon> <DependentUpon>TaskWindow.xaml</DependentUpon>
</Compile> </Compile>

1
Signal Generator/Signal/Base/AnalogSignalMethods.cs

@ -7,6 +7,7 @@ using System.Threading.Tasks;
namespace Signal_Generator namespace Signal_Generator
{ {
[Serializable]
class AnalogSignalMethods class AnalogSignalMethods
{ {
protected string paramsToString(Collection<Parameter> paramsCollection) protected string paramsToString(Collection<Parameter> paramsCollection)

1
Signal Generator/Signal/Base/Parameter.cs

@ -6,6 +6,7 @@ using System.Threading.Tasks;
namespace Signal_Generator namespace Signal_Generator
{ {
[Serializable]
class Parameter class Parameter
{ {
public string name { get; set; } public string name { get; set; }

15
Signal Generator/Signal/FmSignal.cs

@ -7,20 +7,15 @@ using System.Threading.Tasks;
namespace Signal_Generator namespace Signal_Generator
{ {
[Serializable]
class FmSignal : AnalogSignalMethods, IAnalogSignal class FmSignal : AnalogSignalMethods, IAnalogSignal
{ {
public Collection<Parameter> paramsCollection { get; set; } public Collection<Parameter> paramsCollection { get; set; }
public string typeToString public string typeToString => "FM сигнал";
{
get { return "FM сигнал"; }
}
public new string paramsToString
{
get { return paramsToString(paramsCollection); }
}
public new string paramsToString => paramsToString(paramsCollection);
public FmSignal(double ampl, double freq, double ampl2) public FmSignal(double ampl, double freq, double ampl2)
{ {
paramsCollection = new Collection<Parameter>(); paramsCollection = new Collection<Parameter>();
@ -32,7 +27,7 @@ namespace Signal_Generator
public double currentAmplitude(double t) public double currentAmplitude(double t)
{ {
var c = paramsCollection.ToArray<Parameter>(); var c = paramsCollection.ToArray<Parameter>();
return c[0].value * Math.Sin(2 * 3.14 * c[1].value* t + c[2].value * Math.Sin(t)); return c[0].value * Math.Sin(2 * 3.14 * c[1].value * t + c[2].value * Math.Sin(t));
} }
} }
} }

12
Signal Generator/Signal/MultiSignal.cs

@ -10,11 +10,11 @@ namespace Signal_Generator
public class MultiSignal : IAnalogSignal public class MultiSignal : IAnalogSignal
{ {
private static MultiSignal instance; private static MultiSignal instance;
private List<IAnalogSignal> signals { get; set; } internal ObservableCollection<IAnalogSignal> signals { get; set; }
private MultiSignal() private MultiSignal()
{ {
signals = new List<IAnalogSignal>(); signals = new ObservableCollection<IAnalogSignal>();
} }
public static MultiSignal getInstance() public static MultiSignal getInstance()
@ -24,17 +24,17 @@ namespace Signal_Generator
return instance; return instance;
} }
internal void add(IAnalogSignal signal) internal void Add(IAnalogSignal signal)
{ {
signals.Add(signal); signals.Add(signal);
} }
internal void remove(IAnalogSignal signal) internal void Remove(IAnalogSignal signal)
{ {
signals.Remove(signal); signals.Remove(signal);
} }
internal int count() internal int Count()
{ {
return signals.Count(); return signals.Count();
} }
@ -43,9 +43,7 @@ namespace Signal_Generator
{ {
double summaryAmplitude = 0; double summaryAmplitude = 0;
foreach (IAnalogSignal item in signals) foreach (IAnalogSignal item in signals)
{
summaryAmplitude += item.currentAmplitude(t); summaryAmplitude += item.currentAmplitude(t);
}
return summaryAmplitude; return summaryAmplitude;
} }

13
Signal Generator/Signal/SinusoidalSignal.cs

@ -7,17 +7,12 @@ using System.Threading.Tasks;
namespace Signal_Generator namespace Signal_Generator
{ {
[Serializable]
class SinusoidalSignal : AnalogSignalMethods, IAnalogSignal class SinusoidalSignal : AnalogSignalMethods, IAnalogSignal
{ {
public string typeToString public string typeToString => "SIN сигнал";
{
get { return "SIN сигнал"; }
}
public new string paramsToString public new string paramsToString => paramsToString(paramsCollection);
{
get { return paramsToString(paramsCollection); }
}
public Collection<Parameter> paramsCollection { get; set; } public Collection<Parameter> paramsCollection { get; set; }
@ -32,7 +27,7 @@ namespace Signal_Generator
public double currentAmplitude(double t) public double currentAmplitude(double t)
{ {
var c = paramsCollection.ToArray<Parameter>(); var c = paramsCollection.ToArray<Parameter>();
return c[0].value * Math.Sin(2.0 * 3.14 * c[1].value * t + c[2].value); return c[0].value * Math.Sin(2.0 * 3.14 * c[1].value * t + c[2].value * 180 / 3.14);
} }
} }
} }

23
Signal Generator/StringDoubleConverter.cs

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace Signal_Generator
{
class StringDoubleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((double)value).ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return double.Parse((string)value);
}
}
}

13
Signal Generator/TaskWindow.xaml

@ -11,6 +11,7 @@
<Window.Resources> <Window.Resources>
<local:ProcedureModel x:Key="ProcedureModel"/> <local:ProcedureModel x:Key="ProcedureModel"/>
<local:ArrayConverter x:Key="ArrayConverter"/> <local:ArrayConverter x:Key="ArrayConverter"/>
<local:StringDoubleConverter x:Key="StringDoubleConverter"/>
</Window.Resources> </Window.Resources>
<Grid Margin="10" Loaded="Grid_Loaded" DataContext="{Binding Source={StaticResource ProcedureModel}}"> <Grid Margin="10" Loaded="Grid_Loaded" DataContext="{Binding Source={StaticResource ProcedureModel}}">
@ -19,6 +20,7 @@
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
@ -28,13 +30,16 @@
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Canvas x:Name="signalGraph_Canvas" Background="AliceBlue" Grid.ColumnSpan="4" Margin="0,0,0,5" ClipToBounds="True"/> <Canvas x:Name="signalGraph_Canvas" Background="AliceBlue" Grid.ColumnSpan="4" Margin="0,0,0,5" ClipToBounds="True"/>
<TextBlock x:Name="currentTime_TextBlock" Margin="0,0,5,5" Grid.Row="1" Grid.Column="1">Время выполения:</TextBlock> <TextBlock x:Name="currentTime_TextBlock" Margin="0,0,5,5" Grid.Row="1" Grid.Column="1">Текущее время (t, мс):</TextBlock>
<TextBox x:Name="currentTime_TextBox" Margin="0,0,0,5" Grid.Row="1" Grid.Column="2" IsEnabled="False" <TextBox x:Name="currentTime_TextBox" Margin="0,0,0,5" Grid.Row="1" Grid.Column="2" IsEnabled="False"
Text="{Binding Path=CurrentTime}"/> Text="{Binding Path=CurrentTime}"/>
<TextBlock x:Name="currentAmplitude_TextBlock" Margin="0,0,5,5" Grid.Row="2" Grid.Column="1">Текущий сигнал:</TextBlock> <TextBlock x:Name="currentAmplitude_TextBlock" Margin="0,0,5,5" Grid.Row="2" Grid.Column="1">Текущая амплитуда (y(t), В):</TextBlock>
<TextBox x:Name="currentAmplitude_TextBox" Margin="0,0,0,5" Grid.Row="2" Grid.Column="2" IsEnabled="False" <TextBox x:Name="currentAmplitude_TextBox" Margin="0,0,0,5" Grid.Row="2" Grid.Column="2" IsEnabled="False"
Text="{Binding Path=CurrentAmplitude}"/> Text="{Binding Path=CurrentAmplitude}"/>
<Button x:Name="start_Button" Width="120" Content="Запустить" Margin="5,0" Grid.Row="3" Grid.Column="0" <TextBlock x:Name="duration_TextBlock" Margin="0,0,5,5" Grid.Row="3" Grid.Column="1">Длительность (мс):</TextBlock>
<TextBox x:Name="duration_TextBox" Margin="0,0,0,5" Grid.Row="3" Grid.Column="2"
Text="{Binding Duration, Converter={StaticResource StringDoubleConverter}, Mode=TwoWay}"/>
<Button x:Name="start_Button" Width="120" Content="Запустить" Margin="5,0" Grid.Row="4" Grid.Column="0"
Grid.ColumnSpan="2" Command="{StaticResource ProcedureModel}"> Grid.ColumnSpan="2" Command="{StaticResource ProcedureModel}">
<Button.CommandParameter> <Button.CommandParameter>
<MultiBinding Converter="{StaticResource ArrayConverter}"> <MultiBinding Converter="{StaticResource ArrayConverter}">
@ -45,7 +50,7 @@
</MultiBinding> </MultiBinding>
</Button.CommandParameter> </Button.CommandParameter>
</Button> </Button>
<Button x:Name="pause_Button" Width="120" Content="Приостановить" Margin="5,0" Grid.Row="3" Grid.Column="2" <Button x:Name="pause_Button" Width="120" Content="Приостановить" Margin="5,0" Grid.Row="4" Grid.Column="2"
Grid.ColumnSpan="2" Command="{StaticResource ProcedureModel}"> Grid.ColumnSpan="2" Command="{StaticResource ProcedureModel}">
<Button.CommandParameter> <Button.CommandParameter>
<MultiBinding Converter="{StaticResource ArrayConverter}"> <MultiBinding Converter="{StaticResource ArrayConverter}">

Loading…
Cancel
Save