Add files from zip
This commit is contained in:
87
examples/bode/ComplexNumber.h
Normal file
87
examples/bode/ComplexNumber.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*****************************************************************************
|
||||
* Qwt Examples
|
||||
* Copyright (C) 1997 Josef Wilgen
|
||||
* Copyright (C) 2002 Uwe Rathmann
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the Qwt License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
class ComplexNumber
|
||||
{
|
||||
public:
|
||||
ComplexNumber();
|
||||
ComplexNumber( double r, double i = 0.0 );
|
||||
|
||||
double real() const;
|
||||
double imag() const;
|
||||
|
||||
friend ComplexNumber operator*(
|
||||
const ComplexNumber&, const ComplexNumber& );
|
||||
|
||||
friend ComplexNumber operator+(
|
||||
const ComplexNumber&, const ComplexNumber& );
|
||||
|
||||
friend ComplexNumber operator-(
|
||||
const ComplexNumber&, const ComplexNumber& );
|
||||
friend ComplexNumber operator/(
|
||||
const ComplexNumber&, const ComplexNumber& );
|
||||
|
||||
private:
|
||||
double m_real;
|
||||
double m_imag;
|
||||
};
|
||||
|
||||
inline ComplexNumber::ComplexNumber()
|
||||
: m_real( 0.0 )
|
||||
, m_imag( -0.0 )
|
||||
{
|
||||
}
|
||||
|
||||
inline ComplexNumber::ComplexNumber( double re, double im )
|
||||
: m_real( re )
|
||||
, m_imag( im )
|
||||
{
|
||||
}
|
||||
|
||||
inline double ComplexNumber::real() const
|
||||
{
|
||||
return m_real;
|
||||
}
|
||||
|
||||
inline double ComplexNumber::imag() const
|
||||
{
|
||||
return m_imag;
|
||||
}
|
||||
|
||||
inline ComplexNumber operator+(
|
||||
const ComplexNumber& x1, const ComplexNumber& x2 )
|
||||
{
|
||||
return ComplexNumber( x1.m_real + x2.m_real, x1.m_imag + x2.m_imag );
|
||||
}
|
||||
|
||||
inline ComplexNumber operator-(
|
||||
const ComplexNumber& x1, const ComplexNumber& x2 )
|
||||
{
|
||||
return ComplexNumber( x1.m_real - x2.m_real, x1.m_imag - x2.m_imag );
|
||||
}
|
||||
|
||||
inline ComplexNumber operator*(
|
||||
const ComplexNumber& x1, const ComplexNumber& x2 )
|
||||
{
|
||||
return ComplexNumber( x1.m_real * x2.m_real - x1.m_imag * x2.m_imag,
|
||||
x1.m_real * x2.m_imag + x2.m_real * x1.m_imag );
|
||||
}
|
||||
|
||||
inline ComplexNumber operator/(
|
||||
const ComplexNumber& x1, const ComplexNumber& x2 )
|
||||
{
|
||||
double denom = x2.m_real * x2.m_real + x2.m_imag * x2.m_imag;
|
||||
|
||||
return ComplexNumber(
|
||||
( x1.m_real * x2.m_real + x1.m_imag * x2.m_imag ) / denom,
|
||||
( x1.m_imag * x2.m_real - x2.m_imag * x1.m_real ) / denom
|
||||
);
|
||||
}
|
||||
239
examples/bode/MainWindow.cpp
Normal file
239
examples/bode/MainWindow.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
/*****************************************************************************
|
||||
* Qwt Examples
|
||||
* Copyright (C) 1997 Josef Wilgen
|
||||
* Copyright (C) 2002 Uwe Rathmann
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the Qwt License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "Plot.h"
|
||||
#include "Pixmaps.h"
|
||||
|
||||
#include <QwtCounter>
|
||||
#include <QwtPickerMachine>
|
||||
#include <QwtPlotZoomer>
|
||||
#include <QwtPlotPanner>
|
||||
#include <QwtPlotRenderer>
|
||||
#include <QwtText>
|
||||
|
||||
#include <QToolBar>
|
||||
#include <QToolButton>
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
#include <QStatusBar>
|
||||
#include <QPrinter>
|
||||
#include <QPrintDialog>
|
||||
#include <QPen>
|
||||
|
||||
namespace
|
||||
{
|
||||
class Zoomer : public QwtPlotZoomer
|
||||
{
|
||||
public:
|
||||
Zoomer( int xAxis, int yAxis, QWidget* canvas )
|
||||
: QwtPlotZoomer( xAxis, yAxis, canvas )
|
||||
{
|
||||
setTrackerMode( QwtPicker::AlwaysOff );
|
||||
setRubberBand( QwtPicker::NoRubberBand );
|
||||
|
||||
// RightButton: zoom out by 1
|
||||
// Ctrl+RightButton: zoom out to full size
|
||||
|
||||
setMousePattern( QwtEventPattern::MouseSelect2,
|
||||
Qt::RightButton, Qt::ControlModifier );
|
||||
setMousePattern( QwtEventPattern::MouseSelect3,
|
||||
Qt::RightButton );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
MainWindow::MainWindow( QWidget* parent )
|
||||
: QMainWindow( parent )
|
||||
{
|
||||
m_plot = new Plot( this );
|
||||
|
||||
const int margin = 5;
|
||||
m_plot->setContentsMargins( margin, margin, margin, 0 );
|
||||
|
||||
setContextMenuPolicy( Qt::NoContextMenu );
|
||||
|
||||
m_zoomer[0] = new Zoomer( QwtAxis::XBottom, QwtAxis::YLeft,
|
||||
m_plot->canvas() );
|
||||
m_zoomer[0]->setRubberBand( QwtPicker::RectRubberBand );
|
||||
m_zoomer[0]->setRubberBandPen( QColor( Qt::green ) );
|
||||
m_zoomer[0]->setTrackerMode( QwtPicker::ActiveOnly );
|
||||
m_zoomer[0]->setTrackerPen( QColor( Qt::white ) );
|
||||
|
||||
m_zoomer[1] = new Zoomer(
|
||||
QwtAxis::XTop, QwtAxis::YRight, m_plot->canvas() );
|
||||
|
||||
m_panner = new QwtPlotPanner( m_plot->canvas() );
|
||||
m_panner->setMouseButton( Qt::MiddleButton );
|
||||
|
||||
m_picker = new QwtPlotPicker( QwtAxis::XBottom, QwtAxis::YLeft,
|
||||
QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn,
|
||||
m_plot->canvas() );
|
||||
m_picker->setStateMachine( new QwtPickerDragPointMachine() );
|
||||
m_picker->setRubberBandPen( QColor( Qt::green ) );
|
||||
m_picker->setRubberBand( QwtPicker::CrossRubberBand );
|
||||
m_picker->setTrackerPen( QColor( Qt::white ) );
|
||||
|
||||
setCentralWidget( m_plot );
|
||||
|
||||
QToolBar* toolBar = new QToolBar( this );
|
||||
|
||||
QToolButton* btnZoom = new QToolButton( toolBar );
|
||||
btnZoom->setText( "Zoom" );
|
||||
btnZoom->setIcon( QPixmap( zoom_xpm ) );
|
||||
btnZoom->setCheckable( true );
|
||||
btnZoom->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );
|
||||
toolBar->addWidget( btnZoom );
|
||||
connect( btnZoom, SIGNAL(toggled(bool)), SLOT(enableZoomMode(bool)) );
|
||||
|
||||
#ifndef QT_NO_PRINTER
|
||||
QToolButton* btnPrint = new QToolButton( toolBar );
|
||||
btnPrint->setText( "Print" );
|
||||
btnPrint->setIcon( QPixmap( print_xpm ) );
|
||||
btnPrint->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );
|
||||
toolBar->addWidget( btnPrint );
|
||||
connect( btnPrint, SIGNAL(clicked()), SLOT(print()) );
|
||||
#endif
|
||||
|
||||
QToolButton* btnExport = new QToolButton( toolBar );
|
||||
btnExport->setText( "Export" );
|
||||
btnExport->setIcon( QPixmap( print_xpm ) );
|
||||
btnExport->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );
|
||||
toolBar->addWidget( btnExport );
|
||||
connect( btnExport, SIGNAL(clicked()), SLOT(exportDocument()) );
|
||||
|
||||
toolBar->addSeparator();
|
||||
|
||||
QWidget* hBox = new QWidget( toolBar );
|
||||
|
||||
QHBoxLayout* layout = new QHBoxLayout( hBox );
|
||||
layout->setSpacing( 0 );
|
||||
layout->addWidget( new QWidget( hBox ), 10 ); // spacer
|
||||
layout->addWidget( new QLabel( "Damping Factor", hBox ), 0 );
|
||||
layout->addSpacing( 10 );
|
||||
|
||||
QwtCounter* cntDamp = new QwtCounter( hBox );
|
||||
cntDamp->setRange( 0.0, 5.0 );
|
||||
cntDamp->setSingleStep( 0.01 );
|
||||
cntDamp->setValue( 0.0 );
|
||||
|
||||
layout->addWidget( cntDamp, 0 );
|
||||
|
||||
( void )toolBar->addWidget( hBox );
|
||||
|
||||
addToolBar( toolBar );
|
||||
#ifndef QT_NO_STATUSBAR
|
||||
( void )statusBar();
|
||||
#endif
|
||||
|
||||
enableZoomMode( false );
|
||||
showInfo();
|
||||
|
||||
connect( cntDamp, SIGNAL(valueChanged(double)),
|
||||
m_plot, SLOT(setDamp(double)) );
|
||||
|
||||
connect( m_picker, SIGNAL(moved(const QPoint&)),
|
||||
SLOT(moved(const QPoint&)) );
|
||||
connect( m_picker, SIGNAL(selected(const QPolygon&)),
|
||||
SLOT(selected(const QPolygon&)) );
|
||||
}
|
||||
|
||||
#ifndef QT_NO_PRINTER
|
||||
|
||||
void MainWindow::print()
|
||||
{
|
||||
QPrinter printer( QPrinter::HighResolution );
|
||||
|
||||
QString docName = m_plot->title().text();
|
||||
if ( !docName.isEmpty() )
|
||||
{
|
||||
docName.replace ( "\n", " -- " );
|
||||
printer.setDocName ( docName );
|
||||
}
|
||||
|
||||
printer.setCreator( "Bode example" );
|
||||
#if QT_VERSION >= 0x050300
|
||||
printer.setPageOrientation( QPageLayout::Landscape );
|
||||
#else
|
||||
printer.setOrientation( QPrinter::Landscape );
|
||||
#endif
|
||||
|
||||
QPrintDialog dialog( &printer );
|
||||
if ( dialog.exec() )
|
||||
{
|
||||
QwtPlotRenderer renderer;
|
||||
|
||||
if ( printer.colorMode() == QPrinter::GrayScale )
|
||||
{
|
||||
renderer.setDiscardFlag( QwtPlotRenderer::DiscardBackground );
|
||||
renderer.setDiscardFlag( QwtPlotRenderer::DiscardCanvasBackground );
|
||||
renderer.setDiscardFlag( QwtPlotRenderer::DiscardCanvasFrame );
|
||||
renderer.setLayoutFlag( QwtPlotRenderer::FrameWithScales );
|
||||
}
|
||||
|
||||
renderer.renderTo( m_plot, printer );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void MainWindow::exportDocument()
|
||||
{
|
||||
QwtPlotRenderer renderer;
|
||||
renderer.exportTo( m_plot, "bode.pdf" );
|
||||
}
|
||||
|
||||
void MainWindow::enableZoomMode( bool on )
|
||||
{
|
||||
m_panner->setEnabled( on );
|
||||
|
||||
m_zoomer[0]->setEnabled( on );
|
||||
m_zoomer[0]->zoom( 0 );
|
||||
|
||||
m_zoomer[1]->setEnabled( on );
|
||||
m_zoomer[1]->zoom( 0 );
|
||||
|
||||
m_picker->setEnabled( !on );
|
||||
|
||||
showInfo();
|
||||
}
|
||||
|
||||
void MainWindow::showInfo( QString text )
|
||||
{
|
||||
if ( text.isEmpty() )
|
||||
{
|
||||
if ( m_picker->rubberBand() )
|
||||
text = "Cursor Pos: Press left mouse button in plot region";
|
||||
else
|
||||
text = "Zoom: Press mouse button and drag";
|
||||
}
|
||||
|
||||
#ifndef QT_NO_STATUSBAR
|
||||
statusBar()->showMessage( text );
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::moved( const QPoint& pos )
|
||||
{
|
||||
using namespace QwtAxis;
|
||||
|
||||
QString info( "Freq=%1, Ampl=%2, Phase=%3" );
|
||||
info = info.arg( m_plot->invTransform( XBottom, pos.x() ) );
|
||||
info = info.arg( m_plot->invTransform( YLeft, pos.y() ) );
|
||||
info = info.arg( m_plot->invTransform( YRight, pos.y() ) );
|
||||
|
||||
showInfo( info );
|
||||
}
|
||||
|
||||
void MainWindow::selected( const QPolygon& )
|
||||
{
|
||||
showInfo();
|
||||
}
|
||||
|
||||
#include "moc_MainWindow.cpp"
|
||||
46
examples/bode/MainWindow.h
Normal file
46
examples/bode/MainWindow.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*****************************************************************************
|
||||
* Qwt Examples
|
||||
* Copyright (C) 1997 Josef Wilgen
|
||||
* Copyright (C) 2002 Uwe Rathmann
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the Qwt License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
class QwtPlotZoomer;
|
||||
class QwtPlotPicker;
|
||||
class QwtPlotPanner;
|
||||
class Plot;
|
||||
class QPolygon;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow( QWidget* parent = 0 );
|
||||
|
||||
private Q_SLOTS:
|
||||
void moved( const QPoint& );
|
||||
void selected( const QPolygon& );
|
||||
|
||||
#ifndef QT_NO_PRINTER
|
||||
void print();
|
||||
#endif
|
||||
|
||||
void exportDocument();
|
||||
void enableZoomMode( bool );
|
||||
|
||||
private:
|
||||
void showInfo( QString text = QString() );
|
||||
|
||||
Plot* m_plot;
|
||||
|
||||
QwtPlotZoomer* m_zoomer[2];
|
||||
QwtPlotPicker* m_picker;
|
||||
QwtPlotPanner* m_panner;
|
||||
};
|
||||
96
examples/bode/Pixmaps.h
Normal file
96
examples/bode/Pixmaps.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
static const char* print_xpm[] =
|
||||
{
|
||||
"32 32 12 1",
|
||||
"a c #ffffff",
|
||||
"h c #ffff00",
|
||||
"c c #ffffff",
|
||||
"f c #dcdcdc",
|
||||
"b c #c0c0c0",
|
||||
"j c #a0a0a4",
|
||||
"e c #808080",
|
||||
"g c #808000",
|
||||
"d c #585858",
|
||||
"i c #00ff00",
|
||||
"# c #000000",
|
||||
". c None",
|
||||
"................................",
|
||||
"................................",
|
||||
"...........###..................",
|
||||
"..........#abb###...............",
|
||||
".........#aabbbbb###............",
|
||||
".........#ddaaabbbbb###.........",
|
||||
"........#ddddddaaabbbbb###......",
|
||||
".......#deffddddddaaabbbbb###...",
|
||||
"......#deaaabbbddddddaaabbbbb###",
|
||||
".....#deaaaaaaabbbddddddaaabbbb#",
|
||||
"....#deaaabbbaaaa#ddedddfggaaad#",
|
||||
"...#deaaaaaaaaaa#ddeeeeafgggfdd#",
|
||||
"..#deaaabbbaaaa#ddeeeeabbbbgfdd#",
|
||||
".#deeefaaaaaaa#ddeeeeabbhhbbadd#",
|
||||
"#aabbbeeefaaa#ddeeeeabbbbbbaddd#",
|
||||
"#bbaaabbbeee#ddeeeeabbiibbadddd#",
|
||||
"#bbbbbaaabbbeeeeeeabbbbbbaddddd#",
|
||||
"#bjbbbbbbaaabbbbeabbbbbbadddddd#",
|
||||
"#bjjjjbbbbbbaaaeabbbbbbaddddddd#",
|
||||
"#bjaaajjjbbbbbbaaabbbbadddddddd#",
|
||||
"#bbbbbaaajjjbbbbbbaaaaddddddddd#",
|
||||
"#bjbbbbbbaaajjjbbbbbbddddddddd#.",
|
||||
"#bjjjjbbbbbbaaajjjbbbdddddddd#..",
|
||||
"#bjaaajjjbbbbbbjaajjbddddddd#...",
|
||||
"#bbbbbaaajjjbbbjbbaabdddddd#....",
|
||||
"###bbbbbbaaajjjjbbbbbddddd#.....",
|
||||
"...###bbbbbbaaajbbbbbdddd#......",
|
||||
"......###bbbbbbjbbbbbddd#.......",
|
||||
".........###bbbbbbbbbdd#........",
|
||||
"............###bbbbbbd#.........",
|
||||
"...............###bbb#..........",
|
||||
"..................###..........."
|
||||
};
|
||||
|
||||
|
||||
static const char* zoom_xpm[] =
|
||||
{
|
||||
"32 32 8 1",
|
||||
"# c #000000",
|
||||
"b c #c0c0c0",
|
||||
"a c #ffffff",
|
||||
"e c #585858",
|
||||
"d c #a0a0a4",
|
||||
"c c #0000ff",
|
||||
"f c #00ffff",
|
||||
". c None",
|
||||
"..######################........",
|
||||
".#a#baaaaaaaaaaaaaaaaaa#........",
|
||||
"#aa#baaaaaaaaaaaaaccaca#........",
|
||||
"####baaaaaaaaaaaaaaaaca####.....",
|
||||
"#bbbbaaaaaaaaaaaacccaaa#da#.....",
|
||||
"#aaaaaaaaaaaaaaaacccaca#da#.....",
|
||||
"#aaaaaaaaaaaaaaaaaccaca#da#.....",
|
||||
"#aaaaaaaaaabe###ebaaaaa#da#.....",
|
||||
"#aaaaaaaaa#########aaaa#da#.....",
|
||||
"#aaaaaaaa###dbbbb###aaa#da#.....",
|
||||
"#aaaaaaa###aaaaffb###aa#da#.....",
|
||||
"#aaaaaab##aaccaaafb##ba#da#.....",
|
||||
"#aaaaaae#daaccaccaad#ea#da#.....",
|
||||
"#aaaaaa##aaaaaaccaab##a#da#.....",
|
||||
"#aaaaaa##aacccaaaaab##a#da#.....",
|
||||
"#aaaaaa##aaccccaccab##a#da#.....",
|
||||
"#aaaaaae#daccccaccad#ea#da#.....",
|
||||
"#aaaaaab##aacccaaaa##da#da#.....",
|
||||
"#aaccacd###aaaaaaa###da#da#.....",
|
||||
"#aaaaacad###daaad#####a#da#.....",
|
||||
"#acccaaaad##########da##da#.....",
|
||||
"#acccacaaadde###edd#eda#da#.....",
|
||||
"#aaccacaaaabdddddbdd#eda#a#.....",
|
||||
"#aaaaaaaaaaaaaaaaaadd#eda##.....",
|
||||
"#aaaaaaaaaaaaaaaaaaadd#eda#.....",
|
||||
"#aaaaaaaccacaaaaaaaaadd#eda#....",
|
||||
"#aaaaaaaaaacaaaaaaaaaad##eda#...",
|
||||
"#aaaaaacccaaaaaaaaaaaaa#d#eda#..",
|
||||
"########################dd#eda#.",
|
||||
"...#dddddddddddddddddddddd##eda#",
|
||||
"...#aaaaaaaaaaaaaaaaaaaaaa#.####",
|
||||
"...########################..##."
|
||||
};
|
||||
197
examples/bode/Plot.cpp
Normal file
197
examples/bode/Plot.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/*****************************************************************************
|
||||
* Qwt Examples
|
||||
* Copyright (C) 1997 Josef Wilgen
|
||||
* Copyright (C) 2002 Uwe Rathmann
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the Qwt License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#include "Plot.h"
|
||||
#include "ComplexNumber.h"
|
||||
|
||||
#include <QwtMath>
|
||||
#include <QwtScaleEngine>
|
||||
#include <QwtSymbol>
|
||||
#include <QwtPlotGrid>
|
||||
#include <QwtPlotMarker>
|
||||
#include <QwtPlotCurve>
|
||||
#include <QwtLegend>
|
||||
#include <QwtText>
|
||||
#include <QwtPlotCanvas>
|
||||
|
||||
static void logSpace( double* array, int size, double xmin, double xmax )
|
||||
{
|
||||
if ( ( xmin <= 0.0 ) || ( xmax <= 0.0 ) || ( size <= 0 ) )
|
||||
return;
|
||||
|
||||
const int imax = size - 1;
|
||||
|
||||
array[0] = xmin;
|
||||
array[imax] = xmax;
|
||||
|
||||
const double lxmin = log( xmin );
|
||||
const double lxmax = log( xmax );
|
||||
const double lstep = ( lxmax - lxmin ) / double( imax );
|
||||
|
||||
for ( int i = 1; i < imax; i++ )
|
||||
array[i] = std::exp( lxmin + double( i ) * lstep );
|
||||
}
|
||||
|
||||
Plot::Plot( QWidget* parent )
|
||||
: QwtPlot( parent )
|
||||
{
|
||||
setAutoReplot( false );
|
||||
|
||||
setTitle( "Frequency Response of a Second-Order System" );
|
||||
|
||||
QwtPlotCanvas* canvas = new QwtPlotCanvas();
|
||||
canvas->setBorderRadius( 10 );
|
||||
|
||||
setCanvas( canvas );
|
||||
setCanvasBackground( QColor( "MidnightBlue" ) );
|
||||
|
||||
// legend
|
||||
QwtLegend* legend = new QwtLegend;
|
||||
insertLegend( legend, QwtPlot::BottomLegend );
|
||||
|
||||
// grid
|
||||
QwtPlotGrid* grid = new QwtPlotGrid;
|
||||
grid->enableXMin( true );
|
||||
grid->setMajorPen( Qt::white, 0, Qt::DotLine );
|
||||
grid->setMinorPen( Qt::gray, 0, Qt::DotLine );
|
||||
grid->attach( this );
|
||||
|
||||
// axes
|
||||
setAxisVisible( QwtAxis::YRight );
|
||||
setAxisTitle( QwtAxis::XBottom, "Normalized Frequency" );
|
||||
setAxisTitle( QwtAxis::YLeft, "Amplitude [dB]" );
|
||||
setAxisTitle( QwtAxis::YRight, "Phase [deg]" );
|
||||
|
||||
setAxisMaxMajor( QwtAxis::XBottom, 6 );
|
||||
setAxisMaxMinor( QwtAxis::XBottom, 9 );
|
||||
setAxisScaleEngine( QwtAxis::XBottom, new QwtLogScaleEngine );
|
||||
|
||||
// curves
|
||||
m_curve1 = new QwtPlotCurve( "Amplitude" );
|
||||
m_curve1->setRenderHint( QwtPlotItem::RenderAntialiased );
|
||||
m_curve1->setPen( Qt::yellow );
|
||||
m_curve1->setLegendAttribute( QwtPlotCurve::LegendShowLine );
|
||||
m_curve1->setYAxis( QwtAxis::YLeft );
|
||||
m_curve1->attach( this );
|
||||
|
||||
m_curve2 = new QwtPlotCurve( "Phase" );
|
||||
m_curve2->setRenderHint( QwtPlotItem::RenderAntialiased );
|
||||
m_curve2->setPen( Qt::cyan );
|
||||
m_curve2->setLegendAttribute( QwtPlotCurve::LegendShowLine );
|
||||
m_curve2->setYAxis( QwtAxis::YRight );
|
||||
m_curve2->attach( this );
|
||||
|
||||
// marker
|
||||
m_marker1 = new QwtPlotMarker();
|
||||
m_marker1->setValue( 0.0, 0.0 );
|
||||
m_marker1->setLineStyle( QwtPlotMarker::VLine );
|
||||
m_marker1->setLabelAlignment( Qt::AlignRight | Qt::AlignBottom );
|
||||
m_marker1->setLinePen( Qt::green, 0, Qt::DashDotLine );
|
||||
m_marker1->attach( this );
|
||||
|
||||
m_marker2 = new QwtPlotMarker();
|
||||
m_marker2->setLineStyle( QwtPlotMarker::HLine );
|
||||
m_marker2->setLabelAlignment( Qt::AlignRight | Qt::AlignBottom );
|
||||
m_marker2->setLinePen( QColor( 200, 150, 0 ), 0, Qt::DashDotLine );
|
||||
m_marker2->setSymbol( new QwtSymbol( QwtSymbol::Diamond,
|
||||
QColor( Qt::yellow ), QColor( Qt::green ), QSize( 8, 8 ) ) );
|
||||
m_marker2->attach( this );
|
||||
|
||||
setDamp( 0.0 );
|
||||
|
||||
setAutoReplot( true );
|
||||
}
|
||||
|
||||
void Plot::showData( const double* frequency, const double* amplitude,
|
||||
const double* phase, int count )
|
||||
{
|
||||
m_curve1->setSamples( frequency, amplitude, count );
|
||||
m_curve2->setSamples( frequency, phase, count );
|
||||
}
|
||||
|
||||
void Plot::showPeak( double freq, double amplitude )
|
||||
{
|
||||
QString label( "Peak: " );
|
||||
label += QString::number( amplitude, 'g', 3 );
|
||||
label += " dB";
|
||||
|
||||
QwtText text( label );
|
||||
text.setFont( QFont( "Helvetica", 10, QFont::Bold ) );
|
||||
text.setColor( QColor( 200, 150, 0 ) );
|
||||
|
||||
m_marker2->setValue( freq, amplitude );
|
||||
m_marker2->setLabel( text );
|
||||
}
|
||||
|
||||
void Plot::show3dB( double freq )
|
||||
{
|
||||
QString label( "-3 dB at f = " );
|
||||
label += QString::number( freq, 'g', 3 );
|
||||
|
||||
QwtText text( label );
|
||||
text.setFont( QFont( "Helvetica", 10, QFont::Bold ) );
|
||||
text.setColor( Qt::green );
|
||||
|
||||
m_marker1->setValue( freq, 0.0 );
|
||||
m_marker1->setLabel( text );
|
||||
}
|
||||
|
||||
//
|
||||
// re-calculate frequency response
|
||||
//
|
||||
void Plot::setDamp( double damping )
|
||||
{
|
||||
const bool doReplot = autoReplot();
|
||||
setAutoReplot( false );
|
||||
|
||||
const int ArraySize = 200;
|
||||
|
||||
double frequency[ArraySize];
|
||||
double amplitude[ArraySize];
|
||||
double phase[ArraySize];
|
||||
|
||||
// build frequency vector with logarithmic division
|
||||
logSpace( frequency, ArraySize, 0.01, 100 );
|
||||
|
||||
int i3 = 1;
|
||||
double fmax = 1;
|
||||
double amax = -1000.0;
|
||||
|
||||
for ( int i = 0; i < ArraySize; i++ )
|
||||
{
|
||||
double f = frequency[i];
|
||||
const ComplexNumber g =
|
||||
ComplexNumber( 1.0 ) / ComplexNumber( 1.0 - f * f, 2.0 * damping * f );
|
||||
|
||||
amplitude[i] = 20.0 * log10( std::sqrt( g.real() * g.real() + g.imag() * g.imag() ) );
|
||||
phase[i] = std::atan2( g.imag(), g.real() ) * ( 180.0 / M_PI );
|
||||
|
||||
if ( ( i3 <= 1 ) && ( amplitude[i] < -3.0 ) )
|
||||
i3 = i;
|
||||
if ( amplitude[i] > amax )
|
||||
{
|
||||
amax = amplitude[i];
|
||||
fmax = frequency[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
double f3 = frequency[i3] - ( frequency[i3] - frequency[i3 - 1] )
|
||||
/ ( amplitude[i3] - amplitude[i3 - 1] ) * ( amplitude[i3] + 3 );
|
||||
|
||||
showPeak( fmax, amax );
|
||||
show3dB( f3 );
|
||||
showData( frequency, amplitude, phase, ArraySize );
|
||||
|
||||
setAutoReplot( doReplot );
|
||||
|
||||
replot();
|
||||
}
|
||||
|
||||
#include "moc_Plot.cpp"
|
||||
37
examples/bode/Plot.h
Normal file
37
examples/bode/Plot.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*****************************************************************************
|
||||
* Qwt Examples
|
||||
* Copyright (C) 1997 Josef Wilgen
|
||||
* Copyright (C) 2002 Uwe Rathmann
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the Qwt License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QwtPlot>
|
||||
|
||||
class QwtPlotCurve;
|
||||
class QwtPlotMarker;
|
||||
|
||||
class Plot : public QwtPlot
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Plot( QWidget* parent );
|
||||
|
||||
public Q_SLOTS:
|
||||
void setDamp( double damping );
|
||||
|
||||
private:
|
||||
void showData( const double* frequency, const double* amplitude,
|
||||
const double* phase, int count );
|
||||
void showPeak( double freq, double amplitude );
|
||||
void show3dB( double freq );
|
||||
|
||||
QwtPlotCurve* m_curve1;
|
||||
QwtPlotCurve* m_curve2;
|
||||
QwtPlotMarker* m_marker1;
|
||||
QwtPlotMarker* m_marker2;
|
||||
};
|
||||
23
examples/bode/bode.pro
Normal file
23
examples/bode/bode.pro
Normal file
@@ -0,0 +1,23 @@
|
||||
################################################################
|
||||
# Qwt Examples
|
||||
# Copyright (C) 1997 Josef Wilgen
|
||||
# Copyright (C) 2002 Uwe Rathmann
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the Qwt License, Version 1.0
|
||||
################################################################
|
||||
|
||||
include( $${PWD}/../examples.pri )
|
||||
|
||||
TARGET = bode
|
||||
|
||||
HEADERS = \
|
||||
MainWindow.h \
|
||||
Plot.h \
|
||||
ComplexNumber.h \
|
||||
Pixmaps.h
|
||||
|
||||
SOURCES = \
|
||||
Plot.cpp \
|
||||
MainWindow.cpp \
|
||||
main.cpp
|
||||
22
examples/bode/main.cpp
Normal file
22
examples/bode/main.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
/*****************************************************************************
|
||||
* Qwt Examples
|
||||
* Copyright (C) 1997 Josef Wilgen
|
||||
* Copyright (C) 2002 Uwe Rathmann
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the Qwt License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include <QApplication>
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
QApplication app( argc, argv );
|
||||
|
||||
MainWindow window;
|
||||
window.resize( 540, 400 );
|
||||
window.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
Reference in New Issue
Block a user