函数公式网 正弦函数 用Qt绘制正切函数y=tan(kx b)的图像

用Qt绘制正切函数y=tan(kx b)的图像

先看程序输出的y=tan(x)的函数图:

y = tan(x)函数图

本程序的函数分析公式为y = tan(kx b),考虑一般情况,系数k可正可负。

绘图使用了Qt的图形视图框架(graphics view framework)。

绘图发生在一个矩形内,该矩形也被设置为场景的范围。 矩形的宽度与对应的X表示的范围的比值就是比例因子(代码中的mySCALE)。 例如,如果用一个宽度为1000像素的矩形表示[-100,100]的X区间,那么缩放系数就是5。

程序的两个主要模块是计算模块 函数值tangentCal(qreal k, qreal b),以及函数图像的绘图模块drawGraph(QVectorvec, qreal k, QPen pen) .

头文件:

//////////////////////////mainwindow.h///// ////////////////////////////////

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include

#include

#include

#include

#include

#include

QT_BEGIN_NAMESPACE

命名空间 Ui { class MainWindow; }

QT_END_NAMESPACE

class MainWindow : public QMainWindow

{

Q_OBJECT

public:

MainWindow(QWidget *parent = nullptr);

~MainWindow();

void drawSine(qreal k,qreal b,QPen pen) ; // 绘制正弦函数图像

void drawCosine(int k,QPen pen); //绘制余弦函数图像

void drawAxis(); //绘制坐标系

void drawtangent(int period,QPen pen);

void drawTangentkx(qreal k,qreal b,QPen pen);

QVector tangentCal(qreal k,qreal b) ;

void drawGraph(QVector vec, qreal k,QPen pen);

private:

Ui::MainWindow *ui;

QGraphicsScene *scene;

QPainterPat h m_path; //用来保存函数image绘制的路径

QLineF Domain; //一个容器,用来表示y =sin(kx b)函数的定义域,里面包含了一条直线的函数图像的起点和终点。 注意这里的直线一定要用QLineF,不能用QLine。

int nSteps; //用来表示y =sin(kx b)函数一次循环采样的点数

/ *这个SCALE是一个缩放比例,等于像素个数的比例 在绘图区域的水平方向到功能域的长度。

比如你用一个宽度为400像素的区域作为定义域为2*π函数的绘图区域,那么这个

比例就等于400/( 2*π). 即2*π的数学函数域,对应物理

绘图区域宽度为400像素。 */

qreal SCALE;

const qreal PI = 3.14159265358979;

int n; //函数域:[-n*π,n*π ],本例中n取3

QPointF m_start; //函数图像的起点。 注意不要使用QPoint,因为精度不够。

QPointF m_end; //函数结束点图像

};

#endif // MAINWINDOW_H

part 1 y = tan( kx b) 函数值计算模块

因为正切函数的取值范围是从负无穷大到正无穷大。 因此,(-π/2, π/2)中的正切函数的图像与表示绘制区间的矩形会有两个交点,对应的横坐标分别命名为x1,x2。 在这个区间内,取几个点,计算出点的坐标,用QVector容器保存这一系列点的坐标。

由于系统默认Y轴向下,所以函数值取反,与我们习惯的Y轴一致。

//[x1,x2]是y=tan(kx b)域中连续区间中的一个子区间,对应于(-π/2, π/ of y = tan(x) 2)

//这里计算出的x1和x2对应于正切函数与绘制图形矩形区域交点的横坐标上下两边。

//该函数计算正切函数y = tan(kx b)的值,形成QPointF(x,y),保存在QVector容器中。

QVector MainWindow::tangentCal(qreal k,qreal b)

{

//物理绘图空间与数学坐标之间的缩放比例

p>

qreal myScale = scene->sceneRect().width()/Domain.length();

qreal yMax = scene->sceneRect().height()/2.0/ myScale; //5.65487, yMax in QRect(-500,-300,1000,600)

qreal yMin = -yMax;

qreal x1,x2;

//根据k的不同符号,当k<0时,函数的绘图区间[x1,x2]的起点和终点会被调整。

if(k>0)

{

x1 = (atan(yMin)-b)/k;

x2 = (atan(yMax)-b)/k;

}

else

{

x2 = (atan(-yMax) -b)/k;

x1 = (atan(yMax)-b)/k;

}

qreal bound = x2-x1;

p>

QVector vec;

无符号短 n = 30; //将[x1,x2]分成30个子区间

qreal step = bound/n ;

for(int i=0;i<=n;i )

{

qreal x = x1 i*step;

p>qreal y = -tan(k*x b);

vec< <QPointF(x,y);

}

返回vec;

返回vec;

p>

}

part 2 y = tan(kx b)函数图像绘制模块

绘制部分主要使用QPainterPath类型的对象m_path来记录绘制轨迹,然后将轨迹添加到场景中。 我们知道,正切函数的函数图像是不连续的,分为很多圈。 画完一个时期的函数图像后,左右移动就可以得到其他时期的图像。

//绘制y = tan(kx b)的函数图像

void MainWindow::drawGraph(QVectorvec,qreal k, QPen pen)

p>{

qreal myScale = scene->sceneRect().width()/Domain.length();

m_path.clear();

m_path.moveTo((vec.at(0)) *myScale); //将一个点的x和y坐标同时放大myScale

for(int i = 1;i<= vec.size ()-1;i )

m_path.lineTo(vec.at(i)*myScale);

//给场景添加切线函数图像

scene->addPath(m_path,pen); //(kx b)作为自变量,这张图对应的是基本周期(-π/2,π/2)。

/*在[-n*π,n*π]范围内,除了基本周期外,还有2*abs(n*k)张图片可以平移生成。

k可正可负,所以这里的n*k要取绝对值。 */

int num = abs(n*k);

for(int i = 1;i<=num-1;i )

{

//将切线函数图像向右平移以在新的循环中创建图像

scene->addPath(m_path.translated(QPointF(PI/k*i,0 ) *myScale), pen);

//将切线函数图像向左平移以在新循环中创建图像

scene->addPath(m_path.translated(- QPointF( PI/k*i,0)*myScale),pen);

}

}

y = tan(-x)的函数图像 (红色部分)

y = tan(2x-π/8)函数图(红色部分)

总结:

本文学习了如何使用 Qt图形视图框架绘制正切函数的图像。 通过画图,高中生可以加深对正切函数的图像特征的理解。 程序中用到的知识点包括:

(1)Qt的图形视图框架;

(2)正切函数的数学知识(高中),其中使用基本区间( -π/2, π/2) 内部函数的区间x1, x2, 在给定的X轴区间内计算了多少个循环,循环的计算公式等

(3 ) 使用QVector容器保存计算出的点坐标QPointF。 注意不能使用QPoint,因为误差从数学函数值到物理绘图设备也被放大了,绘图精度不够。

(4)使用QPainterPath保存函数图像的绘制路径。 然后将其添加到场景中,再将场景与视图关联起来,就可以在视图中看到场景容器中的函数图像了。

本文来自网络,不代表函数公式网立场,转载请注明出处:https://www.cyhsb.com/zxhs/1397.html

干货分享 | 动图全解三角函数,不会三角函数的同学必看!

三角函数动画来了,让你秒懂三角函数

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

返回顶部