第一步:将上一章节最后一张图放大,看局部

有两处问题:

其一:蓝色圈内,出现多余的红色像素点

其二:黄色圈内,出现多余的白色像素点(也就是原本应该出现的红色像素点没有出现)

第二步:去掉其它圆环和圆柱面,只留下红色圆环

放大(16倍)看局部:

由于图片像素少,所以没有出现白色的缝(小图中白色不足一次一个像素点,所以,白色的效果就是和红色叠加产生最后的颜色较浅的红色像素)。另外,小图中看不到大图蓝色圈内的多余红色像素点(太少了,小图中的光线根本没有撞击到)。

第三步:“多余”或“缺少”像素点对应一元四次方程的根

当前的问题是“问题四十”的残留问题。
截取“问题四十:第七步:2”如下:

将对应代码修改如下:

bool roots_quartic_equation2(float a, float b, float c, float d, float e, float (&roots)[5]) {//the first element is the number of the real roots, and other elements are the real roots.//Descartes's Method.if (a == 0) {float *roots3;roots3 = roots_cubic_equation(b, c, d, e);for (int i=0; i<int(roots3[0])+1; i++) {roots[i] = roots3[i];}delete [] roots3;}else {float a1 = b/a;float b1 = c/a;float c1 = d/a;float d1 = e/a;float p = (-3*a1*a1)/8 + b1;float q = (a1*a1*a1)/8 - (a1*b1)/2 + c1;float r = (-3*a1*a1*a1*a1)/256 + (a1*a1*b1)/16 - (a1*c1)/4 + d1;float sa = 2*p;float sb = p*p - 4*r;float sc = -q*q;float k, m, t;float *roots_s = roots_cubic_equation(1.0, sa, sb, sc);float temp;for (int i=1; i<int(roots_s[0]); i++) {for (int j=i+1; j<int(roots_s[0])+1; j++) {if (roots_s[i] > roots_s[j]) {temp = roots_s[i];roots_s[i] = roots_s[j];roots_s[j] = temp;}}}if (roots_s[int(roots_s[0])] > 0) {k = sqrt(roots_s[int(roots_s[0])]);delete [] roots_s;}

else{

if (fabs(q) < 0.0000001) {

k = 0.0;

delete [] roots_s;

}

else {

roots[0] = 0.0;

delete [] roots_s;

return true;

}

}

if (fabs(k) == 0.0) {

if (fabs(q) < 0.0000001) {

float *roots2;

roots2 =roots_quadratic_equation(1, -p, r);

if (roots2[0]== 0.0) {

roots[0] =0.0;

delete []roots2;

returntrue;

}

else {

m =roots2[1];

t =roots2[2];

}

delete []roots2;

}

else {

roots[0] = 0.0;

return true;

}

        }else {m = (k*k*k + k*p + q) / (2*k);t = (k*k*k + k*p - q) / (2*k);}float *roots_y1;float *roots_y2;roots_y1 = roots_quadratic_equation(1.0, k, t);roots_y2 = roots_quadratic_equation(1.0, -k, m);if (roots_y1[0] != 0.0) {for (int i=1; i<roots_y1[0]+1; i++) {roots[i] = roots_y1[i] - a1/4;}}if (roots_y2[0] != 0.0) {int roots_y1_number = int(roots_y1[0]);for (int j=1; j<roots_y2[0]+1; j++) {roots[roots_y1_number+j] =roots_y2[j] - a1/4;}}roots[0] = roots_y1[0] + roots_y2[0];delete [] roots_y1;delete [] roots_y2;}return true;
}

“多根”的问题搞定了,现在再查查看哪个地方导致了“少根”

第四步:分析一元三次方程

拦到这样一组数据:

但是,用网页上的一元四次方程计算器求解是有实根的:

这样看来,是这个一元四次方程求错了。

根据之前的分析,应该是对应一元三次方程的求解除了问题。

在main()函数单独测试一个一元四次方程的求解:

----------------------------------------------main.cpp ------------------------------------------

main.cpp

    int main(){float roots[5];if (roots_quartic_equation2(1.4656595, -1.43020415, 4.95183134, -2.24647474, 0.0000393861628, roots)) {for (int i=0; i<(roots[0]+1); i++) {std::cout << "roots[" << i << "]=" << roots[i] << endl;}}

另外,在一元四次方程求解函数中添加log:

对应的一元三次方程系数上面已经标出,现在在一元三次方程求解函数中设置断点,另截图如下:

对应的一元三次方程系数上面已经标出,现在在一元三次方程求解函数中设置断点,另截图如下:

对应的一元三次方程有一个实根,是负的,而且是10-8数量级,尼玛,和计算过程的0是一个数量级哈。

一个很小很小很小非常非常接近0的负数,但也是个负数啊,所以导致原一元四次方程没有实根。

网页计算器求解该一元三次方程结果如下:

尼玛,尼玛,什么鬼,什么鬼???

发现,网页上的正确答案是一个10-8数量级的正实根,我们求解出来的一个10-8数量级的负实根,两个实根相差很小很小(10-8数量级)。

所以,我们有理由猜测是计算精度的问题。

所以,所以,我们将一元三次方程求解过程的数据全部换成“double”类型,函数修改如下:

float* roots_cubic_equation2(float a, float b, float c, float d) {//the first element is the number of the real roots, and other elements are the real roots.//Shengjin's formulafloat *roots = new float[4];if (a == 0) {float *roots2;roots2 = roots_quadratic_equation(b, c, d);for (int i=0; i<int(roots2[0])+1; i++) {roots[i] = roots2[i];}delete [] roots2;}else {double A = double(b*b - 3*a*c);double B = double(b*c - 9*a*d);double C = double(c*c - 3*b*d);double deita = double(B*B - 4*A*C);if ((A == B) && (A == 0)) {//the three roots are the sameif (a != 0) {roots[1] = -b/(3*a);}else {if (b != 0) {roots[1] = -c/b;}else {if (c != 0) {roots[1] = -3*d/c;}}}roots[2] = roots[1];roots[3] = roots[1];roots[0] = 3;}else if (deita > 0) {//only one real rootdouble y1 = double(A*b + (3*a)*(-B + sqrt(deita))/2);double y2 = double(A*b + (3*a)*(-B - sqrt(deita))/2);double pow_y1, pow_y2;if (y1 < 0) {//for pow(a,b), when b is not int, a should not be negative.pow_y1 = - pow(double(-y1), double(1.0/3.0));}else {pow_y1 = pow(double(y1), double(1.0/3.0));}if (y2 < 0) {pow_y2 = - pow(double(-y2), double(1.0/3.0));}else {pow_y2 = pow(double(y2), double(1.0/3.0));}roots[1] = float((-b - pow_y1 - pow_y2) / (3*a));roots[0] = 1;}else if (deita == 0) {//three real roots and two of them are the samedouble K = B/A;roots[1] = float(-b/a + K);roots[2] = float(-K/2);roots[3] = float(-K/2);roots[0] = 3;}else if (deita < 0) {//three different real rootsdouble theta = acos((2*A*b-3*a*B) / (2*pow(A, 1.5)));roots[1] = float((-b - 2*sqrt(A)*cos(theta/3)) / (3*a));roots[2] = float((-b + sqrt(A) * (cos(theta/3) + sqrt(3)*sin(theta/3))) / (3*a));roots[3] = float((-b + sqrt(A) * (cos(theta/3) - sqrt(3)*sin(theta/3))) / (3*a));roots[0] = 3;}}return roots;
}

修改后,运行结果如下:

第五步:验证修改一元三次方程求解函数后图片效果

输出图片如下:

对比之前的图片:

放大截图:

对比之前的截图:

组合图:

大图~大图~看大图:

哦也~搞定~

问题四十三:对ray tracing圆环图形中的细微问题进行修正相关推荐

  1. 问题四十:对ray tracing圆环图形进行debug(2)——C++,用“笛卡尔”方法解一元四次方程

    第七步:用"笛卡尔"方法解一元四次方程 "笛卡尔"方法也就是"待定系数法" 通过"式子八"可以解出s(可能有0到3个实根 ...

  2. 43.深度解密四十三:网络营销推广实战中的“辅助营销工具”大全

    网络营销推广技术.技巧深度解密(四十三)指南: 1.本文档适合零基础以及互联网营销推广工作者,主要讲解网络营销需要的相关辅助营销工具的问题. 2.原创版权文档,任何抄袭或者全部.部分模仿都是侵权行为. ...

  3. 《An Introduction to Ray Tracing》—— 3.3 Ray-Surface Intersections

    总结<An Introduction to Ray Tracing>全文:点这里http://blog.csdn.net/libing_zeng/article/details/72603 ...

  4. Q78:规则网格(Regular Grids)——Ray Tracing中的一种加速技术

    当图形中需要ray trace的物体的数目很大时(比如十万.百万.千万),这时我们就需要对图形生成的过程进行加速. 按照常规办法,需要判断每条光线和每一个物体的碰撞情况.这样一来,则需要耗费大量的时间 ...

  5. 问题五十四:怎么用ray tracing画参数方程表示的曲面(2)—— bezier surface

    首先,需要说明的是: 这一章节可以看作"问题五十三"的另一个例子--bicubic bezier surface: 之前已经用"球面"和"牛角面&qu ...

  6. Q77:怎么用Ray Tracing画仿射变换之后的图形

    77.1 理论说明 如上图所示,椭球面是球面通过仿射变换T得到的. 现在我们的问题是:怎么ray trace变换后的椭球面? (先重申一点:经过仿射变换之后,直线还是直线,光线还是光线) 我们应该这么 ...

  7. 问题六十六:怎么用ray tracing画CSG(Constructive Solid Geometry 构造实体几何)图形

    66.1 概述 什么是CSG图形? 若干简单图形通过集合运算后得到的复杂图形,被称为"CSG图形". 其中"简单图形",包括:sphere, box, cyli ...

  8. 问题五十三:怎么用ray tracing画参数方程表示的曲面(1)

    首先,以球面为例学习怎么用ray tracing画参数方程表示的曲面:然后,再画一个牛角面. 特别说明:这一章节所画的曲面只是示意性的,所以先不care图片上的瑕疵. 53.1 数学推导 球面的参数方 ...

  9. 问题三十三:怎么用ray tracing画特殊长方体(box)

    33.1 怎么用ray tracing画特殊长方体 在光线追踪中被用到的一种常见形态是长方体盒子.这种基本物体被用于可见物体和包围盒,包围盒被用于加速复杂物体的相交测试. 吐槽:单词都认识,就是不知道 ...

最新文章

  1. 【2012天津区域赛】部分题解 hdu4431—4441
  2. 机器学习实现计算不规则图形面积_人教版小学数学五年级上册解决问题(不规则图形的面积)公开课优质课课件教案视频...
  3. ORACLE使用GV_$TEMP_SPACE_HEADER统计临时表空使用情况不准确的问题
  4. 下拉菜单实现树状结构_二叉索引树(树状数组)的原理
  5. 图的定义存储和遍历(一级)
  6. CodeForces - 566A Matching Names(字典树上贪心)
  7. 交换机用光纤模块互连一端灯不亮或两端都不亮,如何处理?
  8. div跳转html页面底部,即使没有内容,如何强制DIV块扩展到页面底部?
  9. 80-600-020-原理-存储引擎-简介
  10. sql如何粘贴一列不同的数值_原来Excel的复制粘贴有这么多不为人知的用法
  11. 打印机(Brother MFC-7860DN)一直提示更换墨盒
  12. 绿色智能机房环境监控系统方案!
  13. 分布式开源调度框架TBSchedule详解
  14. LeetCode1818:绝对差值和
  15. Word将英文数字全部修改为Times New Roman字体
  16. php论坛制作教程,Discuz论坛专题页面制作教程
  17. win10如何同时安装并使用多个版本的jdk
  18. 25个最适合摄影师的WordPress主题(2020)
  19. 点到点轨迹规划——三次曲线,五次曲线,梯形曲线,S曲线
  20. C#引用interop.taskscheduler.dll

热门文章

  1. 犹太教、基督教和伊斯兰教的简单关系
  2. 【原】常见CSS3属性对iosandroidwinphone的支持
  3. 蠎周刊 148: 新年
  4. maven本地安装jar
  5. C++中对string对象的初始化及赋值方式总结
  6. 台大李宏毅Machine Learning 2017Fall学习笔记 (8)Backpropagation
  7. BZOJ4029: [HEOI2015]定价
  8. iOS下JS和原生交互,函数互调
  9. IDEA+Maven+Git
  10. lambda表达式不使用委托(delegate) 用FUNC