当前位置:网站首页>叁拾捌- JS 在 Canvas 上尝试分形图形 (二) 尝试造山画山 以及 角度几何基础
叁拾捌- JS 在 Canvas 上尝试分形图形 (二) 尝试造山画山 以及 角度几何基础
2022-06-09 09:59:00 【BerryBC】
1。以前的失败可以令你继续失败
前期我做了一个很丑的图形,所以我今天决定还是按照那个纪录片的,试着做一个画山的!
前期链接:
叁拾柒- JS 在 Canvas 上尝试分形图形 (一) 画了一个普通箱子图
2。如何画山
上网找到一个说明:
分形应用:造山
但是没有详细的代码,我该如何做呢!?
于是我开始了尝试绝望之旅
按照科普视频的说法就是:
递归分割、中点置换
好!在做这个之前我先要复习一下几何角度的基础。
3。JS 几何角度基础
说白了,其实我真有点忘了 PI 到底是几度了,只能先给自己记录一下:
let v1 = {
x: 0,
y: 0
};
// 在 v1 的基础上增加1个单位为 1 的夹角 60度 的点。
// 其中 Math.PI 为 180 度。
let v2 = {
x: v1.x + Math.cos(Math.PI / 3),
y: v1.y - Math.sin(Math.PI / 3)
};
// 输出 -60 度。
console.log(Math.atan((v2.y - v1.y) / (v2.x - v1.x)) / Math.PI * 180);
4。开始造山
思路伪代码如下:
let 起始三角形的三个点1;
let 起始三角形的三个点2;
let 起始三角形的三个点3;
function 递归下一层(三角形点1,三角形点2,三角形点3){
if (如果是最后一轮递归){
画出该三角形
};
let 中点1=上层点1、2的中点(并进行随机的角度偏移);
let 中点2=上层点2、3的中点(并进行随机的角度偏移);
let 中点3=上层点3、1的中点(并进行随机的角度偏移);
递归下一层(三角形点1,中点1,中点3);
递归下一层(三角形点2,中点2,中点1);
递归下一层(三角形点3,中点3,中点2);
递归下一层(中点1,中点2,中点3);
};
递归下一层(起始三角形点1,起始三角形点2,起始三角形点3);
结果如下:
为什么你断裂了!?为什么中间那么多黑色的!那些是什么鬼!?
5。山体断裂的修补
之前发那个文章有一句:
注:各三角形的公共边的中点应保证只有一次纵移,避免形成的山体破碎。
然后我就懵了,啊?
太麻烦了吧,因为我不同的三角形是分开递归分开计算的,怎样选择同样的中点呢!?
唉,但还是得做的。
5。修复山体断裂后
我选择的是选择一个全局数组变量来记录不同点的位置,并对不同点进行编码,得出结果如下:
最后我还加了一个阴影效果,如果偏移得越厉害的点画出来的颜色越深。
6。最后一版的代码
<!-- * @Descripttion: 尝试画山,修复山体破碎 * @Author: BerryBC * @Date: 2020-03-01 17:32:33 * @LastEditors: BerryBC * @LastEditTime: 2020-03-01 18:27:38 -->
<html>
<head>
<meta charset="utf-8">
<title>测试分形</title>
<style> body {
text-align: center; background-color: black; } .canFractal {
background-color: rgb(243, 236, 253); } </style>
</head>
<body>
<canvas id="canFractal" width="1300" height="900">绝望</canvas>
<script> let dblMX = 500; let dblMY = 400; let dblMLen = 600; let canF = document.getElementById("canFractal"); let ctxDraw = canF.getContext("2d"); // 层数 let intMaxDeep = 8; // 鲜艳度 0 - 1 之间,越靠近1越鲜艳 let intColorWgh = 0.1; let dblMaxOffsetAngle = Math.PI / 8; let intCountP = 2; let dictLSet = []; let arrPSet = []; function funGetColor(dblDeep) {
let intR = Math.abs(255 - parseInt((Math.random() * (1 / intMaxDeep * (1 - intColorWgh) + intColorWgh)) * 255) - 100 * dblDeep); let intG = Math.abs(255 - parseInt((Math.random() * (1 / intMaxDeep * (1 - intColorWgh) + intColorWgh)) * 255) - 100 * dblDeep); let intB = Math.abs(255 - parseInt((Math.random() * (1 / intMaxDeep * (1 - intColorWgh) + intColorWgh)) * 255) - 100 * dblDeep); let strReturn = "rgb(" + intR.toString() + "," + intG.toString() + "," + intB.toString() + ")"; return strReturn; }; let pO0 = {
x: dblMX - dblMLen / 2, y: dblMY + dblMLen / 2, d: 0 }; let dblOAng = Math.PI / 3; let pO1 = {
x: pO0.x + dblMLen * Math.cos(dblOAng), y: pO0.y - dblMLen * Math.sin(dblOAng), d: 0 }; dblOAng = -Math.PI / 3; let pO2 = {
x: pO1.x + dblMLen * Math.cos(dblOAng), y: pO1.y - dblMLen * Math.sin(dblOAng), d: 0 }; function funDrawTri(arrInP) {
dblColorDeep = (arrInP[0].d + arrInP[1].d + arrInP[2].d) / 3; ctxDraw.fillStyle = funGetColor(dblColorDeep); ctxDraw.beginPath(); ctxDraw.moveTo(arrInP[0].x, arrInP[0].y); ctxDraw.lineTo(arrInP[1].x, arrInP[1].y); ctxDraw.lineTo(arrInP[2].x, arrInP[2].y); ctxDraw.closePath(); ctxDraw.fill(); }; function funIter(intIterN, arrIterInP, intIterLen, arrIterPNumSet) {
let intIterNM = intIterN - 1; let intIterNLen = intIterLen / 2; if (intIterNM == 1) {
funDrawTri(arrIterInP); } else {
let arrMP = []; let intIterNPNumSet = []; for (let intI = 0; intI < 3; intI++) {
let intJ = (intI + 1) % 3; let intForDS; let intForDB; if (arrIterPNumSet[intI] > arrIterPNumSet[intJ]) {
intForDS = arrIterPNumSet[intJ]; intForDB = arrIterPNumSet[intI]; } else {
intForDS = arrIterPNumSet[intI]; intForDB = arrIterPNumSet[intJ]; }; if (!dictLSet[intForDS + '-' + intForDB]) {
let dblAng = -Math.atan((arrIterInP[intJ].y - arrIterInP[intI].y) / (arrIterInP[intJ].x - arrIterInP[intI].x)); if (arrIterInP[intJ].x < arrIterInP[intI].x) {
dblAng += Math.PI; }; dblAng += (Math.random() - 0.5) * dblMaxOffsetAngle; intCountP++; intIterNLen = intIterNLen * (0.8 + 0.4 * Math.random()) let objNowP = {
x: arrIterInP[intI].x + intIterNLen * Math.cos(dblAng), y: arrIterInP[intI].y - intIterNLen * Math.sin(dblAng), d: dblAng }; arrMP.push(objNowP); arrPSet.push(objNowP); dictLSet[intForDS + '-' + intForDB] = intCountP; intIterNPNumSet.push(intCountP); } else {
arrMP.push(arrPSet[dictLSet[intForDS + '-' + intForDB]]); intIterNPNumSet.push(dictLSet[intForDS + '-' + intForDB]); }; }; for (let intI = 0; intI < 3; intI++) {
let intJ = (intI + 2) % 3; let arrNewTri = [arrIterInP[intI], arrMP[intI], arrMP[intJ]]; let arrNewPNumSet = [arrIterPNumSet[intI], intIterNPNumSet[intI], intIterNPNumSet[intJ]] funIter(intIterNM, arrNewTri, intIterNLen, arrNewPNumSet); }; funIter(intIterNM, arrMP, intIterNLen, intIterNPNumSet); }; }; arrPSet = [pO0, pO1, pO2]; let arrPNumSet = [0, 1, 2]; let arrOP = [pO0, pO1, pO2]; funIter(intMaxDeep, arrOP, dblMLen, arrPNumSet); </script>
</body>
</html>
7。尝试画动画
因为纪录片上面还有一个是说星球大战的熔岩喷射效果也是分形来画的,我觉得我可以尝试一下,但好像失败了。
唉,大概效果如下:

之后再说呗~
边栏推荐
- dotnet core 也能协调分布式事务啦!
- PIC模拟(Particle-in-Cell Codes) (任务A和任务C)
- ConfigurationManager姿势快闪
- Apple wins us judge dismisses iPhone and iPad security defect class action
- 【模型部署与业务落地】AI 框架部署方案之模型转换
- 当你孤独,抑郁,焦虑的时候......请记得,还有风雨
- WebAssembly 2022调查来啦
- “当你不再是程序员,很多事会脱离掌控”—— 对话全球最大独立开源公司SUSE CTO...
- 失业潮?元宇宙开拓全新的就业机会
- 1019. 链表中的下一个更大节点
猜你喜欢

Après une perte de 300 millions de dollars, IBM a annoncé sa sortie de Russie!

从SQL注入绕过最新安全狗WAF中学习fuzz

明道云上榜2022年中国信创行业办公软件排行榜

【光学】 基于matlab模拟光的双缝干涉附GUI

15 must know MySQL index failure scenarios, stop stepping on the pit!

TensorFlow新文档发布:新增CLP、DTensor...最先进的模型已就绪!

InfoQ 极客传媒 15 周年庆征文| 迁移 Eureka 到 Nacos 之双注册双订阅模式

Unemployment wave? Yuancosmos opens up new employment opportunities

历史上的今天:PHP公开发布;iPhone 4 问世;万维网之父诞生

【模型部署与业务落地】AI 框架部署方案之模型转换
随机推荐
同花顺上面开户安全吗
Sword finger offer 19 Regular expression matching recursion
leetcode. 36 --- effective Sudoku
Kubernetes第七篇:Pod進階、Controller進階、Resource和Dashboard
全球 77.5% 的网站,都在使用“世界上最好的语言” PHP!
安防监控视频EasyCVR视频调阅界面增加单个视频的关闭按钮
自定义失败处理
The more you look at the screen, the better it looks
Interview question 10.03 Search rotation array
WPF implements ring chart with details
关于在线帮助中心你需要思考以下几个问题
WebAssembly 2022调查来啦
Blazor University (27) routing - detect navigation events
1331. array sequence number conversion - quick sort plus binary search
Today in history: PHP is publicly released; IPhone 4 comes out; The birth of the father of the World Wide Web
Introduction à l'AC du tissu, installation, utilisation
How to manage cloud computing platform users?
1108. IP 地址无效化
【光学】 基于matlab模拟光的双缝干涉附GUI
1331. 数组序号转换-快速排序加二分查找