问题四十三:对ray tracing圆环图形中的细微问题进行修正
第一步:将上一章节最后一张图放大,看局部
有两处问题:
其一:蓝色圈内,出现多余的红色像素点
其二:黄色圈内,出现多余的白色像素点(也就是原本应该出现的红色像素点没有出现)
第二步:去掉其它圆环和圆柱面,只留下红色圆环
放大(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圆环图形中的细微问题进行修正相关推荐
- 问题四十:对ray tracing圆环图形进行debug(2)——C++,用“笛卡尔”方法解一元四次方程
第七步:用"笛卡尔"方法解一元四次方程 "笛卡尔"方法也就是"待定系数法" 通过"式子八"可以解出s(可能有0到3个实根 ...
- 43.深度解密四十三:网络营销推广实战中的“辅助营销工具”大全
网络营销推广技术.技巧深度解密(四十三)指南: 1.本文档适合零基础以及互联网营销推广工作者,主要讲解网络营销需要的相关辅助营销工具的问题. 2.原创版权文档,任何抄袭或者全部.部分模仿都是侵权行为. ...
- 《An Introduction to Ray Tracing》—— 3.3 Ray-Surface Intersections
总结<An Introduction to Ray Tracing>全文:点这里http://blog.csdn.net/libing_zeng/article/details/72603 ...
- Q78:规则网格(Regular Grids)——Ray Tracing中的一种加速技术
当图形中需要ray trace的物体的数目很大时(比如十万.百万.千万),这时我们就需要对图形生成的过程进行加速. 按照常规办法,需要判断每条光线和每一个物体的碰撞情况.这样一来,则需要耗费大量的时间 ...
- 问题五十四:怎么用ray tracing画参数方程表示的曲面(2)—— bezier surface
首先,需要说明的是: 这一章节可以看作"问题五十三"的另一个例子--bicubic bezier surface: 之前已经用"球面"和"牛角面&qu ...
- Q77:怎么用Ray Tracing画仿射变换之后的图形
77.1 理论说明 如上图所示,椭球面是球面通过仿射变换T得到的. 现在我们的问题是:怎么ray trace变换后的椭球面? (先重申一点:经过仿射变换之后,直线还是直线,光线还是光线) 我们应该这么 ...
- 问题六十六:怎么用ray tracing画CSG(Constructive Solid Geometry 构造实体几何)图形
66.1 概述 什么是CSG图形? 若干简单图形通过集合运算后得到的复杂图形,被称为"CSG图形". 其中"简单图形",包括:sphere, box, cyli ...
- 问题五十三:怎么用ray tracing画参数方程表示的曲面(1)
首先,以球面为例学习怎么用ray tracing画参数方程表示的曲面:然后,再画一个牛角面. 特别说明:这一章节所画的曲面只是示意性的,所以先不care图片上的瑕疵. 53.1 数学推导 球面的参数方 ...
- 问题三十三:怎么用ray tracing画特殊长方体(box)
33.1 怎么用ray tracing画特殊长方体 在光线追踪中被用到的一种常见形态是长方体盒子.这种基本物体被用于可见物体和包围盒,包围盒被用于加速复杂物体的相交测试. 吐槽:单词都认识,就是不知道 ...
最新文章
- 【2012天津区域赛】部分题解 hdu4431—4441
- 机器学习实现计算不规则图形面积_人教版小学数学五年级上册解决问题(不规则图形的面积)公开课优质课课件教案视频...
- ORACLE使用GV_$TEMP_SPACE_HEADER统计临时表空使用情况不准确的问题
- 下拉菜单实现树状结构_二叉索引树(树状数组)的原理
- 图的定义存储和遍历(一级)
- CodeForces - 566A Matching Names(字典树上贪心)
- 交换机用光纤模块互连一端灯不亮或两端都不亮,如何处理?
- div跳转html页面底部,即使没有内容,如何强制DIV块扩展到页面底部?
- 80-600-020-原理-存储引擎-简介
- sql如何粘贴一列不同的数值_原来Excel的复制粘贴有这么多不为人知的用法
- 打印机(Brother MFC-7860DN)一直提示更换墨盒
- 绿色智能机房环境监控系统方案!
- 分布式开源调度框架TBSchedule详解
- LeetCode1818:绝对差值和
- Word将英文数字全部修改为Times New Roman字体
- php论坛制作教程,Discuz论坛专题页面制作教程
- win10如何同时安装并使用多个版本的jdk
- 25个最适合摄影师的WordPress主题(2020)
- 点到点轨迹规划——三次曲线,五次曲线,梯形曲线,S曲线
- C#引用interop.taskscheduler.dll
热门文章
- 犹太教、基督教和伊斯兰教的简单关系
- 【原】常见CSS3属性对iosandroidwinphone的支持
- 蠎周刊 148: 新年
- maven本地安装jar
- C++中对string对象的初始化及赋值方式总结
- 台大李宏毅Machine Learning 2017Fall学习笔记 (8)Backpropagation
- BZOJ4029: [HEOI2015]定价
- iOS下JS和原生交互,函数互调
- IDEA+Maven+Git
- lambda表达式不使用委托(delegate) 用FUNC