穿过已知点画平滑曲线(3次贝塞尔曲线)

2011-04-11 18:59 8469人阅读 评论(9) 收藏 举报
float 数学计算 variables 图形 搜索引擎 bi

为了把一串点连成光滑的曲线,先研究贝塞尔曲线,又搞B样条插值。。。。都没有成功(数学没那么强)。

后来在

“[翻译] AGG 之贝塞尔插值”http://liyiwen.javaeye.com/blog/705489 。看到一种比较好的方法:

运用贝塞尔曲线的光滑性来穿过这些点。

大致思路就是 先算出相邻原始点的中点,在把相邻中点连成的线段平移到对应的原始点,以平移后的中点作为控制点,相邻原始点为起始点画贝塞尔曲线,这样就保证了连接处的光滑。而贝塞尔曲线本身是光滑的,所以就把这些原始点用光滑曲线连起来了。

我封装了一个函数,留着以后用。

(c++版,其它语言只要把数组和可变数组稍微变一下就能用)

[cpp] view plain copy print ?
  1. void createCurve(CvPoint *originPoint,int originCount,vector<CvPoint> &curvePoint){
  2. //控制点收缩系数 ,经调试0.6较好,CvPoint是opencv的,可自行定义结构体(x,y)
  3. float scale = 0.6;
  4. CvPoint midpoints[originCount];
  5. //生成中点
  6. for(int i = 0 ;i < originCount ; i++){
  7. int nexti = (i + 1) % originCount;
  8. midpoints[i].x = (originPoint[i].x + originPoint[nexti].x)/2.0;
  9. midpoints[i].y = (originPoint[i].y + originPoint[nexti].y)/2.0;
  10. }
  11. //平移中点
  12. CvPoint extrapoints[2 * originCount];
  13. for(int i = 0 ;i < originCount ; i++){
  14. int nexti = (i + 1) % originCount;
  15. int backi = (i + originCount - 1) % originCount;
  16. CvPoint midinmid;
  17. midinmid.x = (midpoints[i].x + midpoints[backi].x)/2.0;
  18. midinmid.y = (midpoints[i].y + midpoints[backi].y)/2.0;
  19. int offsetx = originPoint[i].x - midinmid.x;
  20. int offsety = originPoint[i].y - midinmid.y;
  21. int extraindex = 2 * i;
  22. extrapoints[extraindex].x = midpoints[backi].x + offsetx;
  23. extrapoints[extraindex].y = midpoints[backi].y + offsety;
  24. //朝 originPoint[i]方向收缩
  25. int addx = (extrapoints[extraindex].x - originPoint[i].x) * scale;
  26. int addy = (extrapoints[extraindex].y - originPoint[i].y) * scale;
  27. extrapoints[extraindex].x = originPoint[i].x + addx;
  28. extrapoints[extraindex].y = originPoint[i].y + addy;
  29. int extranexti = (extraindex + 1)%(2 * originCount);
  30. extrapoints[extranexti].x = midpoints[i].x + offsetx;
  31. extrapoints[extranexti].y = midpoints[i].y + offsety;
  32. //朝 originPoint[i]方向收缩
  33. addx = (extrapoints[extranexti].x - originPoint[i].x) * scale;
  34. addy = (extrapoints[extranexti].y - originPoint[i].y) * scale;
  35. extrapoints[extranexti].x = originPoint[i].x + addx;
  36. extrapoints[extranexti].y = originPoint[i].y + addy;
  37. }
  38. CvPoint controlPoint[4];
  39. //生成4控制点,产生贝塞尔曲线
  40. for(int i = 0 ;i < originCount ; i++){
  41. controlPoint[0] = originPoint[i];
  42. int extraindex = 2 * i;
  43. controlPoint[1] = extrapoints[extraindex + 1];
  44. int extranexti = (extraindex + 2) % (2 * originCount);
  45. controlPoint[2] = extrapoints[extranexti];
  46. int nexti = (i + 1) % originCount;
  47. controlPoint[3] = originPoint[nexti];
  48. float u = 1;
  49. while(u >= 0){
  50. int px = bezier3funcX(u,controlPoint);
  51. int py = bezier3funcY(u,controlPoint);
  52. //u的步长决定曲线的疏密
  53. u -= 0.005;
  54. CvPoint tempP = cvPoint(px,py);
  55. //存入曲线点
  56. curvePoint.push_back(tempP);
  57. }
  58. }
  59. }
  60. //三次贝塞尔曲线
  61. float bezier3funcX(float uu,CvPoint *controlP){
  62. float part0 = controlP[0].x * uu * uu * uu;
  63. float part1 = 3 * controlP[1].x * uu * uu * (1 - uu);
  64. float part2 = 3 * controlP[2].x * uu * (1 - uu) * (1 - uu);
  65. float part3 = controlP[3].x * (1 - uu) * (1 - uu) * (1 - uu);
  66. return part0 + part1 + part2 + part3;
  67. }
  68. float bezier3funcY(float uu,CvPoint *controlP){
  69. float part0 = controlP[0].y * uu * uu * uu;
  70. float part1 = 3 * controlP[1].y * uu * uu * (1 - uu);
  71. float part2 = 3 * controlP[2].y * uu * (1 - uu) * (1 - uu);
  72. float part3 = controlP[3].y * (1 - uu) * (1 - uu) * (1 - uu);
  73. return part0 + part1 + part2 + part3;
  74. }

void createCurve(CvPoint *originPoint,int originCount,vector<CvPoint> &curvePoint){//控制点收缩系数 ,经调试0.6较好,CvPoint是opencv的,可自行定义结构体(x,y)float scale = 0.6;CvPoint midpoints[originCount];//生成中点 for(int i = 0 ;i < originCount ; i++){ int nexti = (i + 1) % originCount;midpoints[i].x = (originPoint[i].x + originPoint[nexti].x)/2.0;midpoints[i].y = (originPoint[i].y + originPoint[nexti].y)/2.0;} //平移中点CvPoint extrapoints[2 * originCount]; for(int i = 0 ;i < originCount ; i++){int nexti = (i + 1) % originCount;int backi = (i + originCount - 1) % originCount;CvPoint midinmid;midinmid.x = (midpoints[i].x + midpoints[backi].x)/2.0;midinmid.y = (midpoints[i].y + midpoints[backi].y)/2.0;int offsetx = originPoint[i].x - midinmid.x;int offsety = originPoint[i].y - midinmid.y;int extraindex = 2 * i;extrapoints[extraindex].x = midpoints[backi].x + offsetx;extrapoints[extraindex].y = midpoints[backi].y + offsety;//朝 originPoint[i]方向收缩 int addx = (extrapoints[extraindex].x - originPoint[i].x) * scale;int addy = (extrapoints[extraindex].y - originPoint[i].y) * scale;extrapoints[extraindex].x = originPoint[i].x + addx;extrapoints[extraindex].y = originPoint[i].y + addy;int extranexti = (extraindex + 1)%(2 * originCount);extrapoints[extranexti].x = midpoints[i].x + offsetx;extrapoints[extranexti].y = midpoints[i].y + offsety;//朝 originPoint[i]方向收缩 addx = (extrapoints[extranexti].x - originPoint[i].x) * scale;addy = (extrapoints[extranexti].y - originPoint[i].y) * scale;extrapoints[extranexti].x = originPoint[i].x + addx;extrapoints[extranexti].y = originPoint[i].y + addy;} CvPoint controlPoint[4];//生成4控制点,产生贝塞尔曲线for(int i = 0 ;i < originCount ; i++){controlPoint[0] = originPoint[i];int extraindex = 2 * i;controlPoint[1] = extrapoints[extraindex + 1];int extranexti = (extraindex + 2) % (2 * originCount);controlPoint[2] = extrapoints[extranexti];int nexti = (i + 1) % originCount;controlPoint[3] = originPoint[nexti]; float u = 1;while(u >= 0){int px = bezier3funcX(u,controlPoint);int py = bezier3funcY(u,controlPoint);//u的步长决定曲线的疏密u -= 0.005;CvPoint tempP = cvPoint(px,py);//存入曲线点 curvePoint.push_back(tempP);} } } //三次贝塞尔曲线 float bezier3funcX(float uu,CvPoint *controlP){float part0 = controlP[0].x * uu * uu * uu;float part1 = 3 * controlP[1].x * uu * uu * (1 - uu);float part2 = 3 * controlP[2].x * uu * (1 - uu) * (1 - uu);float part3 = controlP[3].x * (1 - uu) * (1 - uu) * (1 - uu); return part0 + part1 + part2 + part3; } float bezier3funcY(float uu,CvPoint *controlP){float part0 = controlP[0].y * uu * uu * uu;float part1 = 3 * controlP[1].y * uu * uu * (1 - uu);float part2 = 3 * controlP[2].y * uu * (1 - uu) * (1 - uu);float part3 = controlP[3].y * (1 - uu) * (1 - uu) * (1 - uu); return part0 + part1 + part2 + part3; }

翻译] AGG 之贝塞尔插值

文章分类:综合技术

原文地址:http://www.antigrain.com/research/
bezier_interpolation/index.html#PAGE_BEZIER_INTERPOLATION

Interpolation with Bezier Curves  贝塞尔插值

A very simple method of smoothing polygons 一种非常简单的多边形平滑方法

翻译:唐风

之前 comp.graphic.algorithms 上有一个讨论,是关于怎么样使用曲线对多边形进行插值处理,使得最终产生的曲线是光滑的而且能通过所有的顶点。Gernot Hoffmann 建议说使用著名的 B-Spline 来进行插值。这里有他当时的文章。B-Spline 在这里效果很好,它看起来就像是一个固定在多边形顶点上的橡皮尺(elastic ruler)。

  


但我有个大胆的推测,我觉得肯定还存在更简单的方法。比如,使用三次贝塞曲线(cubic Bezier)进行近似。贝塞尔曲线有两个固定点(起点和终点),另加两个决定曲线形状的控制点(CP)。关于贝塞尔曲线的更多知识可以在搜索引擎中找到,比如,你可以参考 Paul Bourke 的站点。 现在给贝塞尔曲线的锚点(固定点),也就是多边形的某一对顶点,那么问题是,我们怎么计算控制点的位置?我运行 Xara X 然后画出了右边这个图形,这很简单,所以我决定尝试下计算出它们的坐标。很显然,多边形两条相邻边的两个控制点与这两个控制点之间的顶点应该在一条直线 上,只有这样,两条相邻的插值曲线才能平滑地连接在一起。所以,这两个控制点应该是相对于顶点是对称的,不过,也不全是……,因为真正的对称就要求它们与 中心点的距离应该是相等的,但对于我们的情况中并不完全是这样的。一开始,我试着先算出多边形两条边的角平分线,然后把控制点放在这条角平分线的垂直线 上。但从图上可以看到,控制点的连线并不会总是垂直于角平分线的。


最终,我找到一个非常简单的办法,不需要任何复杂的数学计算。首先,我们计算出多边形所有边线的中点,Ai。


然后连接起相邻边中点,得到很多线段,记为 Ci 。并用图记的方法计算出 Bi 点。


最后一步,只需要简单地将 Ci 进行平移,平移的路径就是每条线段上 Bi 到对应顶点的路径。就这样,我们计算出了贝塞尔曲线的控制点,平滑的结果看起来也很棒。


这里还可以做一点小小的改进,因为我们已经得到了一条决定控制点的直线,所以,我们可以根据需要,使控制点在这条直线上移动,这样可以改变插值曲线 的状态。我使用了一个与控制点和顶点初始距离相关的系数 K ,用来沿直线移动控制点。控制点离顶点越远,图形看起来就越锐利。


下面是用原始形状和系统K=1.0的贝塞尔插值两种方法来描画的 SVG 的狮子。

 


下面是放大图

 


这个方法对于自相关的多边形也适用,下面的例子可以看到,结果非常有意思:




这个方法只是探索和经验式的,如果从严格的数学模型的角度看它可能是错误的。但在实际使用中的效果已经足够好了,而 且这个方法只需要最小的计算量。下面的代码就是用来画出上面狮子图像的。这些代码并没有进行优化,只是用来演示的。里面有些变量计算了两次,在实际程序 中,如果连续的步骤中都用到同一个变量值,我们可以先缓存变量值进行复用(以避免重复的计算)。

This method is pure heuristic and empiric. It probably gives a wrong result from the point of view of strict mathematical modeling. But in practice the result is good enough and it requires absolute minimum of calculations. Below is the source codethat has been used to generate the lions shown above. It'snot optimal and just an illustration. It calculates some variables twice, while in real programs we can store and reuse them in the 
[cpp] view plaincopyprint?
  1. // Assume we need to calculate the control
  2. // points between (x1,y1) and (x2,y2).
  3. // Then x0,y0 - the previous vertex,
  4. // x3,y3 - the next one.
  5. double xc1 = (x0 + x1) / 2.0;
  6. double yc1 = (y0 + y1) / 2.0;
  7. double xc2 = (x1 + x2) / 2.0;
  8. double yc2 = (y1 + y2) / 2.0;
  9. double xc3 = (x2 + x3) / 2.0;
  10. double yc3 = (y2 + y3) / 2.0;
  11. double len1 = sqrt((x1-x0) * (x1-x0) + (y1-y0) * (y1-y0));
  12. double len2 = sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1));
  13. double len3 = sqrt((x3-x2) * (x3-x2) + (y3-y2) * (y3-y2));
  14. double k1 = len1 / (len1 + len2);
  15. double k2 = len2 / (len2 + len3);
  16. double xm1 = xc1 + (xc2 - xc1) * k1;
  17. double ym1 = yc1 + (yc2 - yc1) * k1;
  18. double xm2 = xc2 + (xc3 - xc2) * k2;
  19. double ym2 = yc2 + (yc3 - yc2) * k2;
  20. // Resulting control points. Here smooth_value is mentioned
  21. // above coefficient K whose value should be in range [0...1].
  22. ctrl1_x = xm1 + (xc2 - xm1) * smooth_value + x1 - xm1;
  23. ctrl1_y = ym1 + (yc2 - ym1) * smooth_value + y1 - ym1;
  24. ctrl2_x = xm2 + (xc2 - xm2) * smooth_value + x2 - xm2;
  25. ctrl2_y = ym2 + (yc2 - ym2) * smooth_value + y2 - ym2;
 // Assume we need to calculate the control// points between (x1,y1) and (x2,y2).// Then x0,y0 - the previous vertex,//      x3,y3 - the next one.double xc1 = (x0 + x1) / 2.0;double yc1 = (y0 + y1) / 2.0;double xc2 = (x1 + x2) / 2.0;double yc2 = (y1 + y2) / 2.0;double xc3 = (x2 + x3) / 2.0;double yc3 = (y2 + y3) / 2.0;double len1 = sqrt((x1-x0) * (x1-x0) + (y1-y0) * (y1-y0));double len2 = sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1));double len3 = sqrt((x3-x2) * (x3-x2) + (y3-y2) * (y3-y2));double k1 = len1 / (len1 + len2);double k2 = len2 / (len2 + len3);double xm1 = xc1 + (xc2 - xc1) * k1;double ym1 = yc1 + (yc2 - yc1) * k1;double xm2 = xc2 + (xc3 - xc2) * k2;double ym2 = yc2 + (yc3 - yc2) * k2;// Resulting control points. Here smooth_value is mentioned// above coefficient K whose value should be in range [0...1].ctrl1_x = xm1 + (xc2 - xm1) * smooth_value + x1 - xm1;ctrl1_y = ym1 + (yc2 - ym1) * smooth_value + y1 - ym1;ctrl2_x = xm2 + (xc2 - xm2) * smooth_value + x2 - xm2;ctrl2_y = ym2 + (yc2 - ym2) * smooth_value + y2 - ym2;
 consecutive steps.

使用三次贝塞尔近似的代码:

[cpp] view plaincopyprint?
  1. // Number of intermediate points between two source ones,
  2. // Actually, this value should be calculated in some way,
  3. // Obviously, depending on the real length of the curve.
  4. // But I don't know any elegant and fast solution for this
  5. // problem.
  6. #define NUM_STEPS 20
  7. void curve4(Polygon* p,
  8. double x1, double y1, //Anchor1
  9. double x2, double y2, //Control1
  10. double x3, double y3, //Control2
  11. double x4, double y4) //Anchor2
  12. {
  13. double dx1 = x2 - x1;
  14. double dy1 = y2 - y1;
  15. double dx2 = x3 - x2;
  16. double dy2 = y3 - y2;
  17. double dx3 = x4 - x3;
  18. double dy3 = y4 - y3;
  19. double subdiv_step = 1.0 / (NUM_STEPS + 1);
  20. double subdiv_step2 = subdiv_step*subdiv_step;
  21. double subdiv_step3 = subdiv_step*subdiv_step*subdiv_step;
  22. double pre1 = 3.0 * subdiv_step;
  23. double pre2 = 3.0 * subdiv_step2;
  24. double pre4 = 6.0 * subdiv_step2;
  25. double pre5 = 6.0 * subdiv_step3;
  26. double tmp1x = x1 - x2 * 2.0 + x3;
  27. double tmp1y = y1 - y2 * 2.0 + y3;
  28. double tmp2x = (x2 - x3)*3.0 - x1 + x4;
  29. double tmp2y = (y2 - y3)*3.0 - y1 + y4;
  30. double fx = x1;
  31. double fy = y1;
  32. double dfx = (x2 - x1)*pre1 + tmp1x*pre2 + tmp2x*subdiv_step3;
  33. double dfy = (y2 - y1)*pre1 + tmp1y*pre2 + tmp2y*subdiv_step3;
  34. double ddfx = tmp1x*pre4 + tmp2x*pre5;
  35. double ddfy = tmp1y*pre4 + tmp2y*pre5;
  36. double dddfx = tmp2x*pre5;
  37. double dddfy = tmp2y*pre5;
  38. int step = NUM_STEPS;
  39. // Suppose, we have some abstract object Polygon which
  40. // has method AddVertex(x, y), similar to LineTo in
  41. // many graphical APIs.
  42. // Note, that the loop has only operation add!
  43. while(step--)
  44. {
  45. fx += dfx;
  46. fy += dfy;
  47. dfx += ddfx;
  48. dfy += ddfy;
  49. ddfx += dddfx;
  50. ddfy += dddfy;
  51. p->AddVertex(fx, fy);
  52. }
  53. p->AddVertex(x4, y4); // Last step must go exactly to x4, y4
  54. }
// Number of intermediate points between two source ones,
// Actually, this value should be calculated in some way,
// Obviously, depending on the real length of the curve.
// But I don't know any elegant and fast solution for this
// problem.
#define NUM_STEPS 20void curve4(Polygon* p,double x1, double y1,   //Anchor1double x2, double y2,   //Control1double x3, double y3,   //Control2double x4, double y4)   //Anchor2
{double dx1 = x2 - x1;double dy1 = y2 - y1;double dx2 = x3 - x2;double dy2 = y3 - y2;double dx3 = x4 - x3;double dy3 = y4 - y3;double subdiv_step  = 1.0 / (NUM_STEPS + 1);double subdiv_step2 = subdiv_step*subdiv_step;double subdiv_step3 = subdiv_step*subdiv_step*subdiv_step;double pre1 = 3.0 * subdiv_step;double pre2 = 3.0 * subdiv_step2;double pre4 = 6.0 * subdiv_step2;double pre5 = 6.0 * subdiv_step3;double tmp1x = x1 - x2 * 2.0 + x3;double tmp1y = y1 - y2 * 2.0 + y3;double tmp2x = (x2 - x3)*3.0 - x1 + x4;double tmp2y = (y2 - y3)*3.0 - y1 + y4;double fx = x1;double fy = y1;double dfx = (x2 - x1)*pre1 + tmp1x*pre2 + tmp2x*subdiv_step3;double dfy = (y2 - y1)*pre1 + tmp1y*pre2 + tmp2y*subdiv_step3;double ddfx = tmp1x*pre4 + tmp2x*pre5;double ddfy = tmp1y*pre4 + tmp2y*pre5;double dddfx = tmp2x*pre5;double dddfy = tmp2y*pre5;int step = NUM_STEPS;// Suppose, we have some abstract object Polygon which// has method AddVertex(x, y), similar to LineTo in// many graphical APIs.// Note, that the loop has only operation add!while(step--){fx   += dfx;fy   += dfy;dfx  += ddfx;dfy  += ddfy;ddfx += dddfx;ddfy += dddfy;p->AddVertex(fx, fy);}p->AddVertex(x4, y4); // Last step must go exactly to x4, y4
}
 

你可以下载一个能运行的画狮子的例子,对它进行旋转和缩放,也可以生成一些随机的多边形。点左键并拖动它可以围绕中 心点旋转和缩放图像。点右键并从左向右拖动,可以改变系统数K。 K=1时大约是距窗口左边100像素处。每次双击会产生一个随机的多边形,对于这些多边形,也可以进行旋转、缩放以及改变K值的操作。

经过离散点画平滑曲线(贝塞尔3次)相关推荐

  1. 根据离散点画直线,iOS离散点画曲线

    在iOS开发过程中,我们会经常遇到画线的功能,比如线性图. 目前iOS画线有两大类方法 (我所知道的). 1.基于CoreGraphics.framework的CGContext: 2.基于UIKit ...

  2. Android 穿过点画平滑曲线

    先上效果图 参考了这篇文章 穿过已知点画平滑曲线(3次贝塞尔曲线) 原理什么的我也不说了,有兴趣的看这篇文章好了 直接上代码 public class DrawUtil {/*** 绘制穿过多边形顶点 ...

  3. 穿过已知点画平滑曲线(3次贝塞尔曲线)

    首先,我们计算出多边形所有边线的中点,Ai. 然后连接起相邻边中点,得到很多线段,记为 Ci .并用图记的方法计算出 Bi 点. 最后一步,只需要简单地将 Ci 进行平移,平移的路径就是每条线段上 B ...

  4. java 三次贝塞尔曲线算法_转:穿过已知点画平滑曲线(3次贝塞尔曲线)

    Interpolation with Bezier Curves  贝塞尔插值 A very simple method of smoothing polygons 一种非常简单的多边形平滑方法 翻译 ...

  5. 根据离散点画直线_离散数据的最佳直线求解方法

    离散数据的最佳直线求解方法 高少蔚 ; 丁红胜 [期刊名称] <计量技术> [年 ( 卷 ), 期] 1997(000)012 [摘要] 本文提出了一种在最大偏差最小准则下寻找离散点最佳直 ...

  6. 根据离散点画直线_excel表格怎么画散点图画直线

    Excel中散点图画直线具体该如何操作执行呢?其实表格中有插入选项,可以帮助我们完成一系列的画图方案,接下来是学习啦小编为大家带来的excel中的散点图画直线的教程,欢迎大家来到学习啦学习. exce ...

  7. 2019-6-27-WPF-如何给定两个点画出一条波浪线

    title author date CreateTime categories WPF 如何给定两个点画出一条波浪线 lindexi 2019-6-27 10:17:6 +0800 2019-6-26 ...

  8. 静态网站生成器_什么是JAMStack?它与静态网站生成器有何区别?

    静态网站生成器 Two ideas, JAMStack and static website generators, are getting attention as a way to simplif ...

  9. 系统在此应用程序堆栈溢出_Web应用程序:在开始之前选择正确的技术堆栈

    系统在此应用程序堆栈溢出 You have a great online business idea along with investors and a team ready to get behi ...

最新文章

  1. 【计算机网络】计算机网络 标准化及组织 ( 标准化工作 | 标准化工作流程 | 标准化工作组织 )
  2. 前端网页 — 初始化文件
  3. C#委托的异步调用[转]
  4. [ZJOI2011]营救皮卡丘(费用流 + 最短路)
  5. 教育部:对于要求家长批改作业,发现一起严处一起
  6. ROOBO公布A轮1亿美元融资 发布人工智能机器人系统
  7. 【NOIP2013模拟】七夕祭
  8. 最流行的轻量级php框架,推荐20个最近很流行的优秀PHP框架
  9. socket.io实现客户端和服务端的双向通信
  10. 一个完全免费的在线文字云网站
  11. java mail 匿名_匿名发送来自javamail的电子邮件
  12. python爬取皮肤_如何用Python爬取LOL官网全英雄皮肤
  13. android如何使用so库,Android 使用SO库
  14. 放射技师计算机辅助诊断,基于CT影像的肺癌计算机辅助诊断关键技术研究
  15. 你真的会用区块链赚钱吗?论区块链的商业思维
  16. 电脑微信截屏快捷键怎么取消
  17. Involution
  18. 编程实用工具大全(二)(前后端皆可用,不来看看?)
  19. 2015南阳CCPC E - Ba Gua Zhen 高斯消元 xor最大
  20. MFC比较好的一篇文章

热门文章

  1. echarts 桑基图 添加标志线问题
  2. Vue2父传子、子传父和兄弟间互传
  3. 英语自我介绍资料及范文
  4. java遗传算法编程_遗传算法示例程序
  5. (145)光线追踪距离场柔和阴影
  6. C++STL算法 search你是我的半截的诗
  7. 操作系统的分类有哪些?
  8. CleanMyMacX4.15好用吗?CleanMyMac X2023安全吗?
  9. #今日论文推荐# 莫纳什大学最新《长文档摘要》综述,39页pdf长文档摘要的实证研究:数据集、模型和指标
  10. Android 集成阿里百川实现在线客服、聊天功能