#include "newton.h" #include Newton::Newton(QWidget *parent): QWidget(parent), numPoints(0), xmin(-8.), xmax(8.), ymin(-6.), ymax(6.), xCoeff(1.), yCoeff(1.) { } void Newton::defineMap() { int w = width(); int h = height(); xCoeff = (double) w / (xmax - xmin); yCoeff = (double) h / (ymax - ymin); } QPointF Newton::map(QPointF p) const { return QPointF( (p.x() - xmin)*xCoeff, (ymax - p.y())*yCoeff ); } QPointF Newton::invMap(QPointF p) const { return QPointF( xmin + p.x()/xCoeff, ymax - p.y()/yCoeff ); } void Newton::paintEvent(QPaintEvent*) { QPainter qp(this); qp.setRenderHint(QPainter::Antialiasing); drawAxes(&qp); if (numPoints > 0) { drawPoints(&qp); drawPolynomial(&qp); } } void Newton::drawAxes(QPainter* qp) { int w = width(); int h = height(); QColor lightGray(220, 220, 220); QColor gray(128, 128, 128); QColor black(0, 0, 0); qp->setBrush(QBrush(lightGray)); qp->drawRect(0, 0, w, h); qp->setPen(gray); QPointF p0, p1; int ix = (int) xmin; while (ix <= (int) xmax) { if (ix == 0) { ++ix; continue; } p0 = map(QPointF(ix, ymin)); p1 = map(QPointF(ix, ymax)); qp->drawLine(p0, p1); ++ix; } int iy = (int) ymin; while (iy <= (int) ymax) { if (iy == 0) { ++iy; continue; } p0 = map(QPointF(xmin, iy)); p1 = map(QPointF(xmax, iy)); qp->drawLine(p0, p1); ++iy; } qp->setPen(black); p0 = map(QPointF(xmin, 0.)); p1 = map(QPointF(xmax, 0.)); qp->drawLine(p0, p1); p0 = map(QPointF(0., ymin)); p1 = map(QPointF(0., ymax)); qp->drawLine(p0, p1); } void Newton::drawPoints(QPainter* qp) { qp->setPen(QPen(Qt::red, 2)); QPointF dx(0.2, 0.), dy(0., 0.2); QPointF p0, p1; for (int i = 0; i < numPoints; ++i) { QPointF t(nodeX[i], nodeY[i]); p0 = map(t - dx); p1 = map(t + dx); qp->drawLine(p0, p1); p0 = map(t - dy); p1 = map(t + dy); qp->drawLine(p0, p1); } } void Newton::drawPolynomial(QPainter* qp) { double x = xmin; double dx = 0.05; double y = newtonPolValue(numPoints-1, nodeX, a, x); QPointF p = map(QPointF(x, y)); QPainterPath path; path.moveTo(p); while (x < xmax) { x += dx; y = newtonPolValue(numPoints-1, nodeX, a, x); p = map(QPointF(x, y)); path.lineTo(p); } qp->strokePath(path, QPen(Qt::blue, 2)); } void Newton::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::RightButton) { numPoints = 0; update(); return; } if (numPoints >= MAX_POINTS) numPoints = 0; QPointF t = invMap( QPointF(event->x(), event->y()) ); nodeX[numPoints] = t.x(); nodeY[numPoints] = t.y(); ++numPoints; computeNewtonPol(numPoints-1, nodeX, nodeY, a); update(); } void Newton::clear() { numPoints = 0; update(); } // Value of Newton interpolation polynomial in point t double newtonPolValue( int n, // Number of nodes - 1 const double* x, // Nodes of interpolation: x0, x1, ..., xn const double* a, // Coefficients of Newton polynomial double t ) { double s = a[0]; double p = 1.; for (int i = 1; i <= n; ++i) { p *= (t - x[i-1]); s += a[i] * p; } return s; } // Compute the coefficients of Newton interpolation polynomial void computeNewtonPol( int n, // Number of nodes - 1 const double* x, // Nodes of interpolation: x0, x1, ..., xn const double* y, // Values in these nodes double* a // Coefficients of Newton polynomial ) { a[0] = y[0]; for (int i = 1; i <= n; ++i) { double p = 1.; for (int j = 0; j < i; ++j) p *= (x[i] - x[j]); a[i] = (y[i] - newtonPolValue(i-1, x, a, x[i])) / p; } }