先看效果图:
![](https://box.kancloud.cn/d89fccb2c37a185345280d5a0fc5a18f_510x473.png)
左侧绿色线条和右侧蓝色线条是反射光线的法线,用来校正每条光线发射正确……
下图是去掉法线的效果:
![](https://box.kancloud.cn/488cb308514f27b871f36e5b3c848ef9_516x467.png)
``
![](https://box.kancloud.cn/ed7712dbb9cc3650b409926f08877b65_517x493.png)
改变颜色的目的,主要是为下一步做“频数”统计做准备;
即准备下一步的工作:即下一步需要统计每个点的光照频数。
主要思路和部分代码
(全部代码已经超出kancloud的允许长度)
```
//参数注释 : 01hdc, 2:tt光线总长,3:入射弧度(非角度), 4(当前)光线入口x坐标x01;5当前光线入口Y坐标Y01;
//调用例子:digui01andDrawlight(hdc, tt, 125, 190, 200);
////int digui01DrawLine01light(HDC hdc, long long tt, int rsjiaodu, int x01, int y01)
int digui01Draw02Circle02light(HDC hdc, int whichCircle, long long tt, double rsHu01du01, int x01, int y01) //int digui01Draw02Circle02light(HDC hdc, int whichCircle, long long tt, double rsHu01du01, int rsjiaodu, int x01, int y01)
{//int digui01andDrawlight112110
diguiAllTimes1++;
printf_s("\r\nDiGuiTimes:%lld", diguiAllTimes1);
// cout << "diguiAllTimes1:" << diguiAllTimes1 << endl;
// printf_s("run112110Here!");
// cout << "run112110Here!" << endl;
if (tt <= 1) { cout << "[tt=1?" << tt << "]" << endl; return 1; }
// double rsHudu01 = ((double)rsjiaodu * 1000.0 / 180.0 / 1000.0 / 10000.0) * PI18 / 10000000000000;// 0;
// double rsHudu01 = (double)rsjiaodu *PId / 180; //角度废弃
cout << "入射01弧度:" << rsHu01du01;// << endl;
cout << "{入射01角度度:" << rsHu01du01*180/PId<<"}"<<endl;
// rsHudu01 = (double)rsjiaodu*3.1415926 / 180.0;
printf_s("_rsHu01du01:=%f", rsHu01du01);
cout << endl;
// cout << "rsHudu01:=" << rsHudu01 << endl;
long lightDuanlen01 = 0;//当前光线 线段长度
//
for (long long ii = 0; ii < tt; ++ii) {//for1110
++lightDuanlen01;
double danweiX01 = cos(rsHu01du01);
double danweiY01 = sin(rsHu01du01);
double yuanShiX001 = (double)lightDuanlen01*danweiX01;
double yuanShiY001 = (double)lightDuanlen01*danweiY01;
//
int zhenShiX0001 = (double)yuanShiX001 + x01;
int zhenShiY0001 = (double)yuanShiY001 + y01;
//根据真实 实际坐标,描点成线--…
SetPixel(hdc, zhenShiX0001, zhenShiY0001, RGB(0, 0, 200)); //亮蓝
//判断:
// int C1s_rightTimes = 0;
// int C2s_leftTimes = 0;
//判断真实点的轴距
//判断 是否 撞过 C1 圆1:
//真实轴距离
long long zhenshiZhouJvliToC1XY01 = zhenShiX0001 * zhenShiX0001 + (zhenShiY0001-200) * (zhenShiY0001-200);
//zhenShiX0001>=200 一定跑出了 圆1,所以是废话(多重保险……
//2号圆的左侧弧:
long long zhenshiZhouJvliToC2xy02 = (300 - zhenShiX0001) * (300 - zhenShiX0001) + (zhenShiY0001 - 200) * (zhenShiY0001 - 200);
if ((/*3*/zhenshiZhouJvliToC1XY01 >= 200 * 200 /*3*/) && (/*3*/zhenshiZhouJvliToC2xy02 >= (200 * 200) /*3*/)) { return 0; }
////注意这里是撞 左侧大圆(1号圆)的右侧弧!
if /*1*/ ( (/*2*/ 1==whichCircle/*2*/) && (/*2*/ (/*3*/zhenshiZhouJvliToC1XY01>= 200*200 /*3*/) || ( zhenShiX0001 >= 200 ) /*2*/) )/*1*/ //if (/*1*/ 1 == whichCircle && zhenShiX0001 >= 200 /*1*/)
{//if11a10
++C1s_rightTimes;
cout << "C1s_rightTimes:" << C1s_rightTimes << endl;
long long tt1new01 = tt - ii;
//算法线:
double faXian1Hudu01 = PId;// -0.1; //法线弧度初始设置为PI=π3.1415926...
// faXian1Hudu01 = atan((double)zhenShiY0001-200) / (zhenShiX0001 );
// faXian1Hudu01 = PId + asin((double)(200.0-zhenShiY0001 ) / (200)); //OK1
faXian1Hudu01 = atan(((double) zhenShiY0001-200) / (zhenShiX0001) ); //测试这个圆心的比率就是 (法线的)角度
if (faXian1Hudu01 < (-1 * PId)) { faXian1Hudu01 += PId; }
cout << "[撞圆1的法线角(弧度:" << faXian1Hudu01 << "]";
//
//画辅助线-法线
int x01x1 = zhenShiX0001;
int y01y1 = zhenShiY0001;
int x02x2 = -200 * cos((double)faXian1Hudu01)+zhenShiX0001;
int y02y2 = (200 * sin( -1*(double)faXian1Hudu01)+zhenShiY0001);
MoveToEx(hdc, zhenShiX0001, zhenShiY0001, NULL);
HPEN hPen;
hPen = CreatePen(PS_SOLID, 1, RGB(0,255, 0)); // 创建一个亮绿色的法线
SelectObject(hdc, hPen);
// LineTo(hdc, x02x2, y02y2); //画法线
double rusheHudu_faxianhudu = rsHu01du01 - faXian1Hudu01;
rusheHudu_faxianhudu = faXian1Hudu01-rsHu01du01;
cout << "[rusheHudu_faxianhudu:" << rusheHudu_faxianhudu << "]" << endl;
double rsNewHudu01 = faXian1Hudu01;// +little_cita; //faXian1Hudu01;
rsNewHudu01 = PId+ rusheHudu_faxianhudu + faXian1Hudu01;
// if ((-1.0*PId / 2) < rsNewHudu01 && rsNewHudu01<0 ) rsNewHudu01 = PId - rsNewHudu01;
// if ((PId ) < rsNewHudu01 && rsNewHudu01 < PId*2) rsNewHudu01 = rsNewHudu01-PId;
//PId - faXian1Hudu01;
//PId-faXian1Hudu01;//这是 正确方向的法线 向量;
//BigA2 - rsHuDu_BuJiao + 3.0/2*PId;
//(PId+faXian1Hudu01)-3.0/4*Pid; // littleCeta;
//3.0/4*PId+2*faXian1Hudu01 - rsHu01du01;
// double rsNewHudu01 = faXian1Hudu01 + PId; //faXian1Hudu01; // PId - faXian1Hudu01;
//注意这里是撞 左侧大圆(1号圆)的右侧弧!
// int rsNewJiao1du = ceil(rsNewHudu01 * 180 / PId);
// if (rsNewJiao1du < 0) rsNewJiao1du += 360;
// if (rsNewJiao1du > 360) rsNewJiao1du -= 360;
lightDuanlen01 = 0;// 1;
if (diguiAllTimes1 < 1900) {//if diguiAllTimes1 < 1900
//判断是否和第一个圆相撞,则切换到 第2号圆////切换 去第 1号圆的判断(和Draw
digui01Draw02Circle02light(hdc, 2, (long long)tt1new01, rsNewHudu01, zhenShiX0001, zhenShiY0001); //digui01DrawLine01light(hdc, tt1new01, rsNewJiao1du, zhenShiX0001, zhenShiY0001);
}//if diguiAllTimes1 < 1950//3000//1900
else {
return 2;
}
if (C1s_rightTimes > 2) return 1;
system("pause");
}//if11a10
//根据真实 实际坐标,描点成线--…
SetPixel(hdc, zhenShiX0001, zhenShiY0001, RGB(0, 200, 0)); //亮绿
//判断 是否 撞过 C2 圆2:
//真实轴距离
//2号圆的左侧弧:
//long long
zhenshiZhouJvliToC2xy02 = (300-zhenShiX0001) * (300-zhenShiX0001) + (zhenShiY0001-200) * (zhenShiY0001-200);
if /*1*/ ( (/*2*/2 == whichCircle/*2*/) && (/*2*/ (/*3*/zhenshiZhouJvliToC2xy02 >= 200 * 200 /*3*/) || ( zhenShiX0001 <= 100 ) /*2*/) )/*1*/ {//if11a10 //if (/*1*/ 2 == whichCircle && zhenShiX0001 <= 100 /*1*/) {//if11a10
++C2s_leftTimes;
cout << "C2s_leftTimes:" << C2s_leftTimes << endl;
long long tt1new01 = tt - ii;
//算法线:
double faXian1Hudu01 = 0; // (double)-PId; //初始法线弧度为0!法线弧度为
// faXian1Hudu01 = atan((double)zhenShiY0001-200.0) / (300.0-zhenShiX0001 );
faXian1Hudu01 = asin( ((double)zhenShiY0001 - 200.0) / 200 );
cout << "圆2号左侧faXian1Hudu01:" << faXian1Hudu01 << endl;
//
//画辅助线-法线
int x01x1 = zhenShiX0001;
int y01y1 = zhenShiY0001;
int x02x2 = 200 * cos((double)faXian1Hudu01) + zhenShiX0001;
int y02y2 = (200 * sin(-1 * (double)faXian1Hudu01) + zhenShiY0001);
MoveToEx(hdc, zhenShiX0001, zhenShiY0001, NULL);
HPEN hPen;
hPen = CreatePen(PS_SOLID, 1, RGB(0, 0,128)); // 创建一个蓝色的法线
SelectObject(hdc, hPen);
// LineTo(hdc, x02x2, y02y2); //画法线
double rusheHudu_faxianhudu = rsHu01du01 - faXian1Hudu01;
rusheHudu_faxianhudu = faXian1Hudu01 - rsHu01du01;
cout << "[rusheHudu_faxianhudu:" << rusheHudu_faxianhudu << "]" << endl;
//
// double rsNewHudu01 = -(double)faXian1Hudu01;// -rsHu01du01 + PId;
// double rsNewHudu01 = -(double)faXian1Hudu01;// +(PId - rsHu01du01); // -rsHu01du01 + PId;
cout << "撞圆2时的入射角弧度:" << rsHu01du01<<endl;
double rsNewHudu01 = -(double)faXian1Hudu01;// +getRs1Hudu_andFaxianJiajiao(faXian1Hudu01, rsHu01du01);
// double rsNewHudu01 = PId-(rsHu01du01 -2 * faXian1Hudu01);
rsNewHudu01 = -( faXian1Hudu01 - (PId - rsHu01du01 - faXian1Hudu01)); //OK了
//;// +getHudu1bound180rad01(rsHu01du01) - faXian1Hudu01;//;;// -getHudu1bound180rad01(rsHu01du01);// +(PId - rsHu01du01); // -rsHu01du01 + PId;
int rsNewJiao1du = 0;//faXian1Hudu01;//废弃
//ceil( (double)150 * PId / 180); ////rsNewHudu01 * 180 / PId;
// if (rsNewJiao1du < 0) rsNewJiao1du += 360;
// if (rsNewJiao1du > 360) rsNewJiao1du -= 360;
lightDuanlen01 = 0;// 1;
if (diguiAllTimes1 < 1900) {//if diguiAllTimes1 < 1900
lightDuanlen01 = 1;
//切去第 1号圆的判断(和Draw
cout << "[22:rsNewHudu01" << rsNewHudu01 << "]" << endl;
//rsNewJiao1du废弃
digui01Draw02Circle02light(hdc, 1, tt1new01, rsNewHudu01, zhenShiX0001, zhenShiY0001); //digui01DrawLine01light(hdc, 1, tt1new01, rsNewHudu01, rsNewJiao1du, zhenShiX0001, zhenShiY0001);
}//if diguiAllTimes1 < 1950
if (C2s_leftTimes > 2) return 1;
system("pause");
}//if11a10
//根据真实 实际坐标,描点成线--…
SetPixel(hdc, zhenShiX0001, zhenShiY0001, getColor1RGB1(diguiAllTimes1 % 7)); //RGB(200, 0, 0)); //亮红
}//for1110
//
return 1;
}//int digui01Draw02Circle02light
//
```
期间还试用了一些其它语言完成,当然效率比c++还是差一些;
下次右时间还可以优化,提高效率。改进方向包括:
1、异步产生数据,最后同意绘图显示;
2、用空间换时间
3、不再迭代…… 迭代和递归的优点当然是程序代码清晰易懂、易调试、易修改。
不用迭代,用存储空间(数组或链表等)存储、绘制数据……效率会更高、更好些……
whatever... C++在我的 macbookpro2011(I7cpu,8G内存)上面跑已经速度足够(快)了。
![](https://box.kancloud.cn/d89fccb2c37a185345280d5a0fc5a18f_510x473.png)
- R高精“密率”-PI的分数的高精度表示形式-R语言181000a
- 高精“密率”-PI的分数的高精度表示形式181001
- java40k2011Terryfix181002
- PI的高精度分数表示形式180101
- c++算PI的分数表示形式180102
- 单圆弧的反射181001a
- 单个圆的圆弧反射181020a
- 附录11:181001非控制台(WindowsForm)窗口程序创建控制台(调试程序用
- 递归调用-判断两圆相碰撞情况181020
- 用递归算法模拟两圆反射Billiards181020
- 光线(粒子)在两圆间碰撞效果1810a
- 光线粒子在两圆内壁碰撞效果1810B
- twoBillards模拟光线(粒子)在重叠的两圆内壁的碰撞C++完整代码(带注释)Terry181001