обратное преобразование
All checks were successful
CMake on a single platform / build (push) Successful in 21s
All checks were successful
CMake on a single platform / build (push) Successful in 21s
This commit is contained in:
parent
8fbbf0afcf
commit
42e7ac4d58
@ -5,6 +5,28 @@
|
||||
#include <ranges>
|
||||
#include <algorithm>
|
||||
|
||||
#include <Wt/WBootstrap5Theme.h>
|
||||
|
||||
#include <Wt/Chart/WAbstractChartModel.h>
|
||||
#include <Wt/Chart/WAxisSliderWidget.h>
|
||||
#include <Wt/Chart/WCartesianChart.h>
|
||||
#include <Wt/Chart/WDataSeries.h>
|
||||
#include <Wt/WApplication.h>
|
||||
#include <Wt/WContainerWidget.h>
|
||||
#include <Wt/WObject.h>
|
||||
#include <Wt/WShadow.h>
|
||||
|
||||
#include <Wt/WSpinBox.h>
|
||||
#include <Wt/WDoubleSpinBox.h>
|
||||
#include <Wt/WLabel.h>
|
||||
#include <Wt/WPushButton.h>
|
||||
#include <Wt/WColorPicker.h>
|
||||
#include <Wt/WCheckBox.h>
|
||||
#include <Wt/WStandardItemModel.h>
|
||||
|
||||
#include <Wt/WPanel.h>
|
||||
|
||||
|
||||
class SinModel : public Chart::WAbstractChartModel
|
||||
{
|
||||
public:
|
||||
@ -23,6 +45,7 @@ public:
|
||||
sinuses | views::transform([x](Sin s){return s.get(x);}),
|
||||
std::plus<double>()
|
||||
).value_or(0);
|
||||
|
||||
default:
|
||||
try { return sinuses.at(column-2).get(x); }
|
||||
catch (out_of_range e){ return 0; }
|
||||
@ -45,13 +68,14 @@ private:
|
||||
class FourierModel : public Chart::WAbstractChartModel
|
||||
{
|
||||
public:
|
||||
FourierModel(shared_ptr<SinModel> dm)
|
||||
FourierModel(shared_ptr<SinModel> dm, vector<pair<double, double>>& fd)
|
||||
: Chart::WAbstractChartModel{}
|
||||
, discreteModel{dm}
|
||||
, fourier_data{fd}
|
||||
{
|
||||
dm->changed().connect([this](){
|
||||
data_.clear();
|
||||
data_.reserve(rowCount());
|
||||
fourier_data.clear();
|
||||
fourier_data.reserve(rowCount());
|
||||
|
||||
for ( int k = 0; k < rowCount(); k++ ) {
|
||||
double x = 0,
|
||||
@ -64,7 +88,7 @@ public:
|
||||
y-=v*sin(e);
|
||||
}
|
||||
|
||||
data_[k] = {sqrt(x*x+y*y)/rowCount(), atan2(y,x)};
|
||||
fourier_data.push_back({x, y});
|
||||
}
|
||||
|
||||
changed().emit();
|
||||
@ -74,38 +98,45 @@ public:
|
||||
virtual double data(int row, int column) const override {
|
||||
switch ( column ) {
|
||||
case 0: return row;
|
||||
case 1: return data_[row].first;
|
||||
case 2: return data_[row].second;
|
||||
case 1: return sqrt(pow(fourier_data[row].first,2)+pow(fourier_data[row].second,2))/rowCount();
|
||||
case 2: return atan2(fourier_data[row].second, fourier_data[row].first);
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
virtual int columnCount() const override { return 3; };
|
||||
virtual int rowCount() const override { return discreteModel->rowCount()/2; }
|
||||
virtual int rowCount() const override { return discreteModel->rowCount(); }
|
||||
|
||||
private:
|
||||
shared_ptr<SinModel> discreteModel;
|
||||
vector<pair<double, double>> data_;
|
||||
vector<pair<double, double>>& fourier_data;
|
||||
};
|
||||
|
||||
#include <Wt/WBootstrap5Theme.h>
|
||||
class RestoreModel : public Chart::WAbstractChartModel
|
||||
{
|
||||
public:
|
||||
RestoreModel(vector<pair<double, double>>& fd)
|
||||
: fourier_data{fd}
|
||||
{}
|
||||
|
||||
#include <Wt/Chart/WAbstractChartModel.h>
|
||||
#include <Wt/Chart/WAxisSliderWidget.h>
|
||||
#include <Wt/Chart/WCartesianChart.h>
|
||||
#include <Wt/Chart/WDataSeries.h>
|
||||
#include <Wt/WApplication.h>
|
||||
#include <Wt/WContainerWidget.h>
|
||||
#include <Wt/WObject.h>
|
||||
#include <Wt/WShadow.h>
|
||||
virtual double data(int row, int column) const override {
|
||||
if ( column == 0 ) return -M_PI + row * 2*M_PI / (rowCount() - 1);;
|
||||
if (fourier_data.size()==0) return 0;
|
||||
double y = 0;
|
||||
for (int k = 0; k < fourier_data.size(); k++) {
|
||||
double theta = (2 * M_PI * k * (row+1)) / fourier_data.size();
|
||||
y += fourier_data.at(k).first * cos(theta) + fourier_data.at(k).second * sin(theta);
|
||||
}
|
||||
return y / fourier_data.size();
|
||||
}
|
||||
|
||||
#include <Wt/WSpinBox.h>
|
||||
#include <Wt/WDoubleSpinBox.h>
|
||||
#include <Wt/WLabel.h>
|
||||
#include <Wt/WPushButton.h>
|
||||
#include <Wt/WColorPicker.h>
|
||||
#include <Wt/WCheckBox.h>
|
||||
#include <Wt/WStandardItemModel.h>
|
||||
virtual int columnCount() const override { return 2; };
|
||||
virtual int rowCount() const override { return fourier_data.size(); }
|
||||
|
||||
private:
|
||||
int rows_ = 0;
|
||||
vector<pair<double, double>>& fourier_data;
|
||||
};
|
||||
|
||||
|
||||
MyApplication::MyApplication(const WEnvironment& env)
|
||||
@ -157,6 +188,26 @@ MyApplication::MyApplication(const WEnvironment& env)
|
||||
pointsDS->setLabelColor(StandardColor::Black);
|
||||
chart->addSeries(std::move(pointsDSPtr));
|
||||
|
||||
restoreModel = make_shared<RestoreModel>(fourier_data);
|
||||
auto restoredSignal = make_unique<Chart::WDataSeries>(1, Chart::SeriesType::Curve);
|
||||
restoredDS = restoredSignal.get();
|
||||
restoredDS->setModel(restoreModel);
|
||||
restoredDS->setXSeriesColumn(0);
|
||||
restoredDS->setHidden(true);
|
||||
restoredDS->setPen({StandardColor::Yellow});
|
||||
restoredDS->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
|
||||
chart->addSeries(std::move(restoredSignal));
|
||||
|
||||
auto restoredSignal_p = make_unique<Chart::WDataSeries>(1, Chart::SeriesType::Point);
|
||||
restoredDS_points = restoredSignal_p.get();
|
||||
restoredDS_points->setModel(restoreModel);
|
||||
restoredDS_points->setXSeriesColumn(0);
|
||||
restoredDS_points->setHidden(true);
|
||||
restoredDS_points->setPen({StandardColor::Yellow});
|
||||
restoredDS_points->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
|
||||
restoredDS_points->setLabelsEnabled(Chart::Axis::Y);
|
||||
restoredDS_points->setLabelColor(StandardColor::Black);
|
||||
chart->addSeries(std::move(restoredSignal_p));
|
||||
|
||||
chart->axis(Chart::Axis::X).setMaximumZoomRange( 2*M_PI+1 );
|
||||
chart->axis(Chart::Axis::X).setMinimumZoomRange( M_PI / 16.0 );
|
||||
@ -172,7 +223,7 @@ MyApplication::MyApplication(const WEnvironment& env)
|
||||
chart->axis(Chart::Axis::Y).setGridLinesEnabled(true);
|
||||
|
||||
|
||||
chart->resize(800, 600);
|
||||
chart->resize(800, 500);
|
||||
|
||||
chart->setPanEnabled(true);
|
||||
chart->setZoomEnabled(true);
|
||||
@ -208,11 +259,13 @@ MyApplication::MyApplication(const WEnvironment& env)
|
||||
chart->update();
|
||||
});
|
||||
|
||||
form->addNew<WText>("a=");
|
||||
form->addNew<WText>("α=");
|
||||
auto a = form->addNew<WDoubleSpinBox>();
|
||||
form->addNew<WText>("w=");
|
||||
a->setValue(1);
|
||||
form->addNew<WText>("ω=");
|
||||
auto w = form->addNew<WDoubleSpinBox>();
|
||||
form->addNew<WText>("f=");
|
||||
w->setValue(1);
|
||||
form->addNew<WText>("φ=");
|
||||
auto f = form->addNew<WDoubleSpinBox>();
|
||||
|
||||
for ( auto i : {a,w,f} ) {
|
||||
@ -233,12 +286,13 @@ MyApplication::MyApplication(const WEnvironment& env)
|
||||
right->setOverflow(Overflow::Hidden, Orientation::Horizontal);
|
||||
{ // дискретизация
|
||||
auto form = right->addNew<WContainerWidget>();
|
||||
form->addStyleClass("d-flex flex-row gap-3");
|
||||
form->addStyleClass("d-flex flex-row gap-3 align-items-center my-1");
|
||||
|
||||
auto show = form->addNew<WCheckBox>("дискретизация");
|
||||
form->addNew<WText>("частота дискретизации");
|
||||
auto freq = form->addNew<WSpinBox>();
|
||||
freq->setWidth(120);
|
||||
freq->setRange(0, 1000);
|
||||
auto show = form->addNew<WCheckBox>("показать точки");
|
||||
|
||||
show->clicked().connect([=,this](){
|
||||
pointsDS->setHidden(!show->isChecked());
|
||||
@ -248,27 +302,18 @@ MyApplication::MyApplication(const WEnvironment& env)
|
||||
|
||||
freq->changed().connect([=,this](){
|
||||
discreteModel->setRows(freq->value());
|
||||
});
|
||||
|
||||
discreteModel->changed().connect([this](){
|
||||
vals->clear();
|
||||
|
||||
for ( int i = 0; i < discreteModel->rowCount(); i++ ) {
|
||||
auto x = discreteModel->data(i,1);
|
||||
vals->addNew<WText>(format("{:.2f}", x))
|
||||
->addStyleClass("border rounded-3 p-1");
|
||||
}
|
||||
restoredDS->setHidden( freq->value()==0 || !lineCheck->isChecked() );
|
||||
restoredDS_points->setHidden(freq->value()==0 || !pointsCheck->isChecked() );
|
||||
chart->update();
|
||||
});
|
||||
}
|
||||
|
||||
vals = right->addNew<WContainerWidget>();
|
||||
vals->setOverflow(Overflow::Auto, Orientation::Horizontal);
|
||||
vals->addStyleClass("d-flex gap-1 p-1 text-nowrap");
|
||||
|
||||
fourierChart = right->addNew<Chart::WCartesianChart>();
|
||||
fourierChart->setPlotAreaPadding(100);
|
||||
fourierChart->setPlotAreaPadding(100, Side::Right | Side::Left);
|
||||
fourierChart->setPlotAreaPadding(50, Side::Top | Side::Bottom);
|
||||
fourierChart->setType(Chart::ChartType::Scatter);
|
||||
fourierModel = make_shared<FourierModel>(discreteModel);
|
||||
fourierModel = make_shared<FourierModel>(discreteModel, fourier_data);
|
||||
fourierModel->changed().connect([this](){restoreModel->changed().emit();});
|
||||
fourierChart->setModel(static_pointer_cast<Chart::WAbstractChartModel>(fourierModel));
|
||||
|
||||
auto seriesPtr = make_unique<Chart::WDataSeries>(2, Chart::SeriesType::Point);
|
||||
@ -300,7 +345,52 @@ MyApplication::MyApplication(const WEnvironment& env)
|
||||
fourierChart->setZoomEnabled(true);
|
||||
fourierChart->setCrosshairEnabled(true);
|
||||
|
||||
fourierChart->resize(800, 600);
|
||||
fourierChart->resize(800, 400);
|
||||
fourierChart->axis(Chart::Axis::X).setMinimumZoomRange(0.1);
|
||||
auto sliderWidget = right->addNew<Chart::WAxisSliderWidget>(ampSeries);
|
||||
sliderWidget->resize(800, 80);
|
||||
sliderWidget->setSelectionAreaPadding(40, Side::Left | Side::Right);
|
||||
fourierChart->axis(Chart::Axis::X).setZoom(2);
|
||||
fourierChart->axis(Chart::Axis::X).setPan(0);
|
||||
|
||||
|
||||
auto restoreControls = right->addNew<WPanel>();
|
||||
restoreControls->setTitle("Восстановленный сигнал");
|
||||
restoreControls->setCentralWidget(make_unique<WContainerWidget>());
|
||||
auto c = (WContainerWidget*)restoreControls->centralWidget();
|
||||
|
||||
{
|
||||
auto line = c->addNew<WContainerWidget>();
|
||||
line->addStyleClass("d-flex flex-row align-items-center gap-1 p-3");
|
||||
lineCheck = line->addNew<WCheckBox>("показывать график");
|
||||
lineCheck->clicked().connect([this](){
|
||||
restoredDS->setHidden(!lineCheck->isChecked());
|
||||
chart->update();
|
||||
});
|
||||
auto lineColor = line->addNew<WColorPicker>(WColor{StandardColor::Yellow});
|
||||
lineColor->setWidth(50);
|
||||
lineColor->changed().connect([lineColor,this](){
|
||||
restoredDS->setPen(WPen{lineColor->color()});
|
||||
chart->update();
|
||||
});
|
||||
}
|
||||
{
|
||||
auto points = c->addNew<WContainerWidget>();
|
||||
points->addStyleClass("d-flex flex-row align-items-center gap-1 p-3");
|
||||
pointsCheck = points->addNew<WCheckBox>("показывать точки");
|
||||
pointsCheck->clicked().connect([this](){
|
||||
restoredDS_points->setHidden(!pointsCheck->isChecked());
|
||||
chart->update();
|
||||
});
|
||||
auto pointsColor = points->addNew<WColorPicker>(WColor{StandardColor::Yellow});
|
||||
pointsColor->setWidth(50);
|
||||
pointsColor->changed().connect([pointsColor,this](){
|
||||
WPen p{pointsColor->color()};
|
||||
restoredDS_points->setPen(p);
|
||||
chart->update();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MyApplication::addSin(Sin s) {
|
||||
|
@ -30,6 +30,7 @@ typedef struct sin Sin;
|
||||
|
||||
class SinModel;
|
||||
class FourierModel;
|
||||
class RestoreModel;
|
||||
|
||||
class MyApplication : public WApplication
|
||||
{
|
||||
@ -43,6 +44,14 @@ private:
|
||||
shared_ptr<SinModel> discreteModel;
|
||||
Chart::WDataSeries* pointsDS;
|
||||
|
||||
shared_ptr<RestoreModel> restoreModel;
|
||||
vector<pair<double, double>> fourier_data;
|
||||
Chart::WDataSeries* restoredDS;
|
||||
Chart::WDataSeries* restoredDS_points;
|
||||
|
||||
WCheckBox* lineCheck;
|
||||
WCheckBox* pointsCheck;
|
||||
|
||||
Chart::WCartesianChart* fourierChart;
|
||||
shared_ptr<FourierModel> fourierModel;
|
||||
|
||||
@ -51,8 +60,6 @@ private:
|
||||
WCheckBox* showAll;
|
||||
size_t checkCount = 0;
|
||||
|
||||
WContainerWidget* vals;
|
||||
|
||||
vector<Sin> sinuses;
|
||||
|
||||
void addSin(Sin s);
|
||||
|
Loading…
Reference in New Issue
Block a user