请教各位关于如何画函数图象??

realmyth 2003-07-20 01:08:16
我想用VC++写一个小程序,该程序能根据输入的不同函数的参数,画出大致的函数图线.
例如,二次曲线根据输入的ax2+bx+c中的a,b,c画出大致图线,我的想法是取出顶点和图线与X轴的两个交点以及其他一系列的点,将他们的X坐标代入到表达式中,得出Y坐标.最后把这些点连起来.不知这样可不可行?
另外,如何将函数表达式算出的坐标值与窗口客户区的坐标对应起来,有没有坐标转换的公式?可以做到画出的图线就象在纸上画出的一样.位置,大小都适合.
谢了!!
...全文
947 14 打赏 收藏 举报
写回复
14 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
BlueSky2008 2003-07-22
  • 打赏
  • 举报
回复
设你要画函数在0<x<4, 0<y<3的坐标区间上的图像,这个图像画到窗口上一个宽640像素点,高480个像素点的区域上,那每个像素点对应的x坐标变化不是4/640吗?每个像素点对应的y坐标变化不是3/480吗?
每次X的增量是一个像素点,每次dx增量一个像素点对应的函数X坐标变化量,我上面的代码你没看么?我在按照你的方法改成具体值好了:

CBrush *poldbrush;
CBrush brush(RGB(255,255,255));
poldbrush=dc.SelectObject(&brush);
dc.Rectangle(rect.left,rect.top,rect.right,rect.bottom-75);
画图
int nwidth=rect.Width();
int nheight=rect.Height();
CPoint aPos[nwidth];//该数组放屏幕坐标值
如何设置自变量X的取值范围?
//设画函数在0<x<4, 0<y<3的坐标区间上的图像
for (int i=0;i<nwidth;i++) {
dx = 0 + 4*i/nwidth; //如何赋值?
dy=f(dx);//计算dy
//转换dx->aPos[i].x? dy->aPos[i].y?
aPos[i].x = i;
aPos[i].y = nheight - (dy - 0)/3*nheight
}
dc.Polyline(aPos,nwidth);

realmyth 2003-07-22
  • 打赏
  • 举报
回复
你说的Xe,Xs都取整数,那请问如何取具体的X的值(即每次dx如何赋值),每次X的增量取多少? 这样我才能将X代入公式中算出Y值啊,能否给出一个大概的取值示列.
寻开心 2003-07-22
  • 打赏
  • 举报
回复
在你的伪代码当中,使用
rect.left 替代Pxs
rect.right 替代Pxe
rect.top 替代Pys
rect.bottom 替代Pye (bottom>top )

这样得到的图象Y数值是向下的,因为在MM—TEXT模式下,Y向下的时候变大。

rect.bottom 替代Pys
rect.top 替代Pye
就可以正过来

寻开心 2003-07-22
  • 打赏
  • 举报
回复
sorry. 确实是给错了公式
公式的意思是一个线性变换
x-xs Px - Pxs y-ys Py - Pyx
-------- = ---------- ------- = ----------
xe-xs Pxe-Pxs ye-ys Pye-Pys

转换一下,函数计算得到的点(x,y)对应的屏幕坐标(Px, Py)应该是:
x -> Px = Pxs + (x-xs)*(Pxe-Pxs)/(xe-xs)
y -> Py = Pys + (y-ys)*(Pye-Pys)/(ye-ys)
寻开心 2003-07-22
  • 打赏
  • 举报
回复
好的办法是,把你的计算函数 写成独立的函数,例如
double Func(double x)
{
return x*x-1;
};

double (FuncPtr*) (double x);

在Display 函数应该写成这样
// [xs, xe]是函数的自变量范围
// func是你的函数y,注意它是函数指针
// int nwidth 是离散点的划分数目,不可以小于1
// rect 是你要绘制的屏幕矩形
// pDC 是你要绘制的窗口的DC
void
Display(double xs, double xe, FuncPtr * func, int nwidth,\
const CRect& rect, CDC * pDC )
{
double dx = (xe - xs) / (nwidth-1); // 每个离散点之间的距离,N个点,N-1段

double * pValueY = new double[nwidth]; // 保存Y数值

double ye, ys; // Y的范围

ye = ys = pValueY[0] = (*func)(xs);

double tempY, tempX = xs;
for (int i=1; i<nwidth; i++, tempX+=dx ) {
pValueY[i] = (*func)(tempX)
if (pValueY[i]>ye ) ye = pValueY[i];
if (pValueY[i]<ys ) ys = pValueY[i];
}; // 这样就把Y范围确定了。

POINT aPos = new POINT[nwidth];
// 现在可以绘制了

tempX = (rect.right-rect.left) / (xe-xs);
tempY = (rect.right-rect.left) / (xe-xs);
for (i=0;i<nwidth;i++) {
aPos[i].x=rect.left + (dx*i)* tempX;
aPos[i].y=rect.bottom+ (pValueY[i]-ys)*tempY;
}
// 绘制点了
pDC-> .....

// 清理内存
delete aPos[];
delete pValueY[];
}

这样改造过后,你对所有的函数只要,调用相同的Display函数来显示,传递的x取值范围,和函数表达式决定了显示的内容
realmyth 2003-07-21
  • 打赏
  • 举报
回复
happy_888,你讲的还是有些未搞懂,那个影射函数具体如何转换啊,屏幕坐标Pxs + (Pxe-Pxs)/(xe-xs)都是常数啊,怎么将它与点的坐标X联系起来?
另外,我大致写了一段伪代码有些地方不知如何实现,哪位能给看一下,解决了马上给分,谢谢!!
生成绘图屏幕
CBrush *poldbrush;
CBrush brush(RGB(255,255,255));
poldbrush=dc.SelectObject(&brush);
dc.Rectangle(rect.left,rect.top,rect.right,rect.bottom-75);
画图
CPoint aPos[此处应取多少个点对?];//该数组放屏幕坐标值
int nwidth=rect.Width();
int nheight=rect.Height();
如何设置自变量X的取值范围?
for (int i=0;i<nwidth;i++) {
dx如何赋值?
dy=f(dx);//计算dy
转换dx->aPos[i].x? dy->aPos[i].y?
aPos[i].x=?
aPos[i].y=?
}
dc.Polyline(aPos,nwidth);
寻开心 2003-07-21
  • 打赏
  • 举报
回复

是逆过程——离散化啊。
realmyth 2003-07-21
  • 打赏
  • 举报
回复
可否具体讲讲插值算法啊.
puma5 2003-07-21
  • 打赏
  • 举报
回复
作函数实际上是插值算法的问题,主要是选择一种合适的插值算法。
realmyth 2003-07-21
  • 打赏
  • 举报
回复
谢谢几位的回答! 不知哪位能找到类似的示例源代码,能否告之一下?
BlueSky2008 2003-07-21
  • 打赏
  • 举报
回复
//设窗口采用MM_TEXT映射模式
//WindowWidth,WindowHeight 指窗口的宽,高(几个像素点)
//View系列变量指你要显示函数的实际坐标范围;如x取值为(-0.5,0.5),
//则ViewX0 = -0.5, ViewWidth = 1.0;
....
for(int x = 0; x<WindowWidth; x++){
dx = ViewX0 + ViewWidth/WindowWidth;
dy = f(dx);
y = WindowHeight - (dy - ViewY0)/ViewHeight*WindowHeight;
SetPixel(hdc,x,y,color);
}
寻开心 2003-07-21
  • 打赏
  • 举报
回复
根据楼主的描述,对于每个要绘制的图象,楼主可以自己确定一个自变量X的取值区域,以及屏幕要绘制图象的范围,假定这个屏幕矩形范围是[(Pxs, Pyx), (Pxe, Pye)],这里面的数值都是整数,自变量X的取值范围是[Xs, Xe],那么就要把自变量的取值范围分解成为Pxe-Pxs段,一共Pxe-Pxs+1个离散点,然后对这个离散点进行函数计算,得到各个点上的函数值,并且同时确定函数值的最大和最小值:Ys和Ye。
剩下的工作就是建立一个影射函数,把点对(x,y)影射到矩形区域[(Pxs, Pyx), (Pxe, Pye)]当中,这个影射函数很简单:
(x, y) -> ( Pxs + (Pxe-Pxs)/(xe-xs), Pys + (Pye-Pys)/(ye-ys) )
其中(x,y)就是根据自变量范围得到的Pxe-Pxs+1个离散点坐标
后者就是屏幕坐标了
注意上述公式当中的数值都是整数。

可以使用任何模式的窗口映射模式WM_TEXT比较简单。

realmyth 2003-07-20
  • 打赏
  • 举报
回复
有没有朋友知道啊?能否指点一下!!
wesleyelf 2003-07-20
  • 打赏
  • 举报
回复
关注! UP一下.
发帖
机器视觉

4371

社区成员

图形图像/机器视觉
社区管理员
  • 机器视觉
  • 迪菲赫尔曼
加入社区
帖子事件
创建了帖子
2003-07-20 01:08
社区公告
暂无公告