找回密码
 欢迎注册
查看: 28060|回复: 15

[讨论] 关于多值隐函数绘图问题

[复制链接]
发表于 2011-1-13 15:05:48 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
有关于多值隐函数绘图的问题向大家请教!

以这个函数为例(x取-8~8,y取-8~8):f(x,y)=(x^2+y^2)^3-36*(x^2-y^2)^2;

可以求得x为任意值时对应的多个y值。绘图时,将每一组值(x,y)绘制为一个点,点数多了就会形成曲线,如下图:
plotexample12.jpg
但如何将相邻的两个点连成线呢?就是说如何判断两个点是相邻的呢?

例如,以下代码求得了x=1.1及x=1.2时对应的y值;x=1.1的y值有6个,x=1.2的y值也有6个,如何判断哪些点该连成线呢?
  1. !using("fcopt");
  2. f(x,y)=(x^2+y^2)^3-36*(x^2-y^2)^2;
  3. isolve[HFor("f"), optrange,-8,8, optthis,1, optpara,1.1];
  4. isolve[HFor("f"), optrange,-8,8, optthis,1, optpara,1.2];
复制代码
1.1                       -5.413569621185505        0.
1.1                       -1.52029233271966         0.
1.1                       -0.8671650244626143       8.881784197001252e-016
1.1                       0.8671650244626143        8.881784197001252e-016
1.1                       1.52029233271966          0.
1.1                       5.413569621185504         0.
6.
1.2                       -5.274704716901752        0.
1.2                       -1.731609595222745        0.
1.2                       -0.9268324331975657       0.
1.2                       0.9268324331975657        0.
1.2                       1.731609595222745         0.
1.2                       5.274704716901752         0.
6.
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-1-13 16:40:58 | 显示全部楼层
1# forcal
点画多了,越稠密,就越连续了,
================

或者求出一定数目的点,然后线性插值,样条插值,...............
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-1-13 17:08:46 | 显示全部楼层
不知道你具体是在问什么

是关于画图引擎的渲染技巧吗
还是就题论题,只是画出该函数的 点图,然后标记一条直线?
===================================

前者,你可以参考gnuplot
如果是后者,你可以把方程化成极坐标的形式,就清晰了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-1-13 17:29:49 | 显示全部楼层
不知道你具体是在问什么

是关于画图引擎的渲染技巧吗
还是就题论题,只是画出该函数的 点图,然后标记一条直线?
===================================

前者,你可以参考gnuplot
如果是后者,你可以把方程化成极 ...
wayne 发表于 2011-1-13 17:08

画出函数的点图是比较容易的,我想把点连成一条折线(曲线)。
例如matlab等画这个图的曲线是连续的,但并不是点图。

=========
有些隐函数方程化成极坐标的形式是比较困难的。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-1-13 18:56:08 | 显示全部楼层
本帖最后由 wayne 于 2011-1-13 18:58 编辑

4# forcal
例如matlab等画这个图的曲线是连续的,但并不是点图。


那你做一个测试,试试:
先产生一个点序列,100个 ,,比如   {x,sin(x)}
然后shuffle一下,把这100对的顺序全部搞乱,越乱越好,再plot一下,看看,..................
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-1-13 19:10:21 | 显示全部楼层
4# forcal
如果你说的是contour plot,
那个实现起来要复杂一些, 你用google搜搜 contour plot Implementation

三天后我会回来的
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-1-13 20:24:28 | 显示全部楼层
4# forcal
算了,再给你补一贴吧:

用OpenGL 画你给的那个函数:
contourplot.png

代码:
  1. /* generates contours using marching squares */

  2. /* region size */

  3. #define X_MAX 8.0
  4. #define Y_MAX 8.0
  5. #define X_MIN -8.0
  6. #define Y_MIN -8.0

  7. /* number of cells */

  8. #define N_X 500
  9. #define N_Y 500

  10. /* contour value */

  11. #define THRESHOLD 0.0

  12. #include <GL/glut.h>

  13. void display()
  14. {
  15.    double f(double,double);
  16.    int cell(double, double, double, double);
  17.    void lines(int, int, int, double, double, double, double);

  18.    double data[N_X][N_Y];
  19.    int i,j;
  20.    int c;

  21.    glClear(GL_COLOR_BUFFER_BIT);
  22. /* form data array from function */

  23.     for(i=0;i<N_X;i++) for (j=0;j<N_Y;j++)
  24.        data[i][j]=f(X_MIN+i*(X_MAX-(X_MIN))/(N_X-1.0), Y_MIN+j*(Y_MAX-(Y_MIN))/(N_Y-1.0));

  25.     /* process each cell */

  26.     for(i=0;i<N_X;i++) for (j=0;j<N_Y;j++)
  27.     {
  28.        c=cell(data[i][j], data[i+1][j], data[i+1][j+1], data[i][j+1]);
  29.        lines(c,i,j,data[i][j], data[i+1][j], data[i+1][j+1], data[i][j+1]);
  30.     }
  31.     glFlush();
  32. }

  33. /* define function f(x,y)      */

  34. double f(double x, double y)
  35. {

  36.    double a=36;

  37.    /* Ovals of Cassini  */

  38.    return (x*x+y*y)*(x*x+y*y)*(x*x+y*y)-a*(x*x-y*y)*(x*x-y*y);
  39. }


  40. /* define cell vertices */

  41. int cell(double a, double b, double c , double d)
  42. {
  43.     int n=0;
  44.     if(a>THRESHOLD) n+=1;
  45.     if(b>THRESHOLD) n+=8;
  46.     if(c>THRESHOLD) n+=4;
  47.     if(d>THRESHOLD) n+=2;
  48.     return n;
  49. }


  50. /* draw line segments for each case */

  51. void lines(int num, int i, int j, double a, double b, double c, double d)
  52. {
  53.      void draw_one(int, int, int, double, double, double, double);
  54.      void draw_adjacent(int, int, int, double, double, double, double);
  55.      void draw_opposite(int, int, int, double, double, double, double);
  56.      switch(num)
  57.      {
  58.      case 1: case 2: case 4: case 7: case 8: case 11: case 13: case 14:
  59.         draw_one(num, i,j,a,b,c,d);
  60.         break;
  61.      case 3: case 6: case 9: case 12:
  62.         draw_adjacent(num,i,j,a,b,c,d);
  63.         break;
  64.      case 5: case 10:
  65.         draw_opposite(num, i,j,a,b,c,d);
  66.         break;
  67.      case 0: case 15: break;
  68.      }
  69. }

  70. void draw_one(int num, int i, int j, double a, double b, double c, double d)
  71. {
  72.   double x1, y1, x2, y2;
  73.   double ox, oy;
  74.   double dx, dy;
  75.   dx=(X_MAX-(X_MIN))/(N_X-1.0);
  76.   dy=(Y_MAX-(Y_MIN))/(N_Y-1.0);
  77.   ox=X_MIN+i*(X_MAX-(X_MIN))/(N_X-1.0);
  78.   oy=Y_MIN+j*(Y_MAX-(Y_MIN))/(N_Y-1.0);
  79.     switch(num)
  80.     {
  81.     case 1: case 14:
  82.       x1=ox;
  83.       y1=oy+dy*(THRESHOLD-a)/(d-a);
  84.       x2=ox+dx*(THRESHOLD-a)/(b-a);
  85.       y2=oy;
  86.       break;
  87.     case 2: case 13:
  88.       x1=ox;
  89.       y1=oy+dy*(THRESHOLD-a)/(d-a);
  90.       x2=ox+dx*(THRESHOLD-d)/(c-d);
  91.       y2=oy+dy;
  92.       break;
  93.     case 4: case 11:
  94.       x1=ox+dx*(THRESHOLD-d)/(c-d);
  95.       y1=oy+dy;
  96.       x2=ox+dx;
  97.       y2=oy+dy*(THRESHOLD-b)/(c-b);
  98.       break;
  99.     case 7: case 8:
  100.       x1=ox+dx*(THRESHOLD-a)/(b-a);
  101.       y1=oy;
  102.       x2=ox+dx;
  103.       y2=oy+dy*(THRESHOLD-b)/(c-b);
  104.       break;
  105.     }
  106.   glBegin(GL_LINES);
  107.     glVertex2d(x1, y1);
  108.     glVertex2d(x2, y2);
  109.   glEnd();
  110. }

  111. void draw_adjacent(int num, int i, int j, double a, double b,
  112. double c, double d)
  113. {
  114.   double x1, y1, x2, y2;
  115.   double ox, oy;
  116.   double dx, dy;
  117.   dx=(X_MAX-(X_MIN))/(N_X-1.0);
  118.   dy=(Y_MAX-(Y_MIN))/(N_Y-1.0);
  119.   ox=X_MIN+i*(X_MAX-(X_MIN))/(N_X-1.0);
  120.   oy=Y_MIN+j*(Y_MAX-(Y_MIN))/(N_Y-1.0);
  121.   switch(num)
  122.   {
  123.     case 3: case 12:
  124.       x1=ox+dx*(THRESHOLD-a)/(b-a);
  125.       y1=oy;
  126.       x2=ox+dx*(THRESHOLD-d)/(c-d);
  127.       y2=oy+dy;
  128.       break;
  129.     case 6: case 9:
  130.       x1=ox;
  131.       y1=oy+dy*(THRESHOLD-a)/(d-a);
  132.       x2=ox+dx;
  133.       y2=oy+dy*(THRESHOLD-b)/(c-b);
  134.       break;
  135.   }
  136.   glBegin(GL_LINES);
  137.     glVertex2d(x1, y1);
  138.     glVertex2d(x2, y2);
  139.   glEnd();

  140. }

  141. void draw_opposite(int num, int i, int j, double a, double b,
  142. double c, double d)
  143. {
  144.   double x1,y1,x2,y2,x3,y3,x4,y4;
  145.   double ox, oy;
  146.   double dx, dy;
  147.   dx=(X_MAX-(X_MIN))/(N_X-1.0);
  148.   dy=(Y_MAX-(Y_MIN))/(N_Y-1.0);
  149.   ox=X_MIN+i*(X_MAX-(X_MIN))/(N_X-1.0);
  150.   oy=Y_MIN+j*(Y_MAX-(Y_MIN))/(N_Y-1.0);
  151.   switch(num)
  152.   {
  153.     case5:
  154.       x1=ox;
  155.       y1=oy+dy*(THRESHOLD-a)/(d-a);
  156.       x2=ox+dx*(THRESHOLD-a)/(b-a);
  157.       y2=oy;
  158.       x3=ox+dx*(THRESHOLD-d)/(c-d);
  159.       y3=oy+dy;
  160.       x4=ox+dx;
  161.       y4=oy+dy*(THRESHOLD-b)/(c-b);
  162.       break;
  163.     case 10:
  164.       x1=ox;
  165.       y1=oy+dy*(THRESHOLD-a)/(d-a);
  166.       x2=ox+dx*(THRESHOLD-d)/(c-d);
  167.       y2=oy+dy;
  168.       x3=ox+dy*(THRESHOLD-a)/(b-a);
  169.       y3=oy;
  170.       x4=ox+dx;
  171.       y4=oy+dy*(THRESHOLD-b)/(c-b);
  172.       break;
  173.   }
  174.   glBegin(GL_LINES);
  175.     glVertex2d(x1, y1);
  176.     glVertex2d(x2, y2);
  177.     glVertex2d(x3, y3);
  178.     glVertex2d(x4, y4);
  179.   glEnd();
  180. }

  181. void myReshape(int w, int h)
  182. {
  183.     glViewport(0, 0, w, h);
  184.     glMatrixMode(GL_PROJECTION);
  185.     glLoadIdentity();
  186.     if (w <= h) gluOrtho2D(X_MIN, X_MAX, Y_MIN * (GLfloat) h / (GLfloat) w, Y_MAX* (GLfloat) h / (GLfloat) w);
  187.     else gluOrtho2D(X_MIN * (GLfloat) w / (GLfloat) h, X_MAX * (GLfloat) w / (GLfloat) h, Y_MIN, Y_MAX);
  188.     glMatrixMode(GL_MODELVIEW);
  189. }

  190. int main(int argc, char **argv)
  191. {
  192.    glutInit(&argc, argv);
  193.    glutInitWindowSize(500, 500);
  194.    glutCreateWindow("contour plot");
  195.    glutReshapeFunc(myReshape);
  196.    glutDisplayFunc(display);
  197.    glClearColor(0.0,0.0,0.0,1.0);
  198.    glColor3f(1.0,1.0,1.0);
  199.    glutMainLoop();
  200. }

复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-1-13 20:24:43 | 显示全部楼层
4# forcal


那你做一个测试,试试:
先产生一个点序列,100个 ,,比如   {x,sin(x)}
然后shuffle一下,把这100对的顺序全部搞乱,越乱越好,再plot一下,看看,..................
wayne 发表于 2011-1-13 18:56

我的意思是MATLAB提供了一个ezplot函数绘制隐函数图形,似乎不是用描点方式绘图的,它是如何绘制的?

对于单值函数f(x)=... ...;绘制曲线图是很容易的,将所有点按x的次序连起来即可。

但对于隐函数f(x,y)=0,一个x对应多个y值,该如何绘制曲线图?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-1-13 20:26:10 | 显示全部楼层
4# forcal
如果你说的是contour plot,
那个实现起来要复杂一些, 你用google搜搜 contour plot Implementation

三天后我会回来的
wayne 发表于 2011-1-13 19:10

英文不是很好,等你回来,呵呵。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-1-13 20:54:05 | 显示全部楼层
4# forcal
算了,再给你补一贴吧:

用OpenGL 画你给的那个函数:
wayne 发表于 2011-1-13 20:24

这个绘图原理与我所说的不一样,我原想先解出所有要绘制的点,然后连成线,看来比较复杂。

这个OpenGL 绘隐函数图原理能大致说一下吗?看不太懂。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-5-19 09:10 , Processed in 0.049547 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表