//对于这一层中的每个room
19 {
20 var tds=trs[i].getElementsByTagName("td");
21 var int_room=parseInt(tds[7].innerHTML);
22 var arr_landtype={land_textblack:[0,0,0,255],land_textyellow:[255,255,0,255]}
23 // 保存在内存中的数据结构
24 // var obj=eval(tds[5].innerHTML);
25 var obj={};
26 eval("obj="+tds[5].innerHTML);
27 arr_floorroom[int_floor][int_room]={id:tds[0],beta:tds[1].innerHTML,pbeta:tds[2].innerHTML,alpha:tds[3].innerHTML
28 ,palpha:tds[4].innerHTML,weight:obj};
29 // 使用何种数据结构传递到显卡?使用一个超长数组arr_set4?《-这是不行的
30 var num1= 0,num2= 0,num3= 0,num4= 255;
31 for (key in obj)// 将每一种颜色的三个通道加权到一起
32 {
33 var num_key=obj[key];
34 num1+=(num_key*arr_landtype[key][0]);
35 num2+=(num_key*arr_landtype[key][1]);
36 num3+=(num_key*arr_landtype[key][2]);
37 }
38 var index= (int_floor+max_floor)*4*can_temp.width+(i-1)*4;// 每个room由4个元素组成
39 imagedata_temp.data[index]=num1;// 这里存的真的是颜色
40 imagedata_temp.data[index+1]=num2;
41 imagedata_temp.data[index+2]=num3;
42 imagedata_temp.data[index+3]=num4;
43 }
因为100km*100km的地区块在近距离视角下也是一个很大的区域,下一步计划在拉近视角时,在一个地区块中再生成更多种类的地形,所以所谓“地区块的地形”,其实是其内包含的各种地形的比例分配,在远处看时地区块的颜色是其包含的各种地形的加权。
这段测试里我使用了两种地形:纯黑色的land_textblack和黄色的land_textyellow,而两种地区块的地形则分别是百分之百的land_textblack和land_textyellow。颜色的加权值被放进了canvas的像素中。
d、绘制行星:
1 // 用glsl和Babylon.js结合的方式绘制行星
2 function DrawPlanet()
3 {
4 var amigaMaterial = new BABYLON.ShaderMaterial("amiga2", scene,{
5 vertexElement: "sh2v4.sh",
6 fragmentElement: "sh2f4.sh",
7 },
8 {
9 attributes: ["position"],
10 uniforms: ["worldViewProjection","worldView"]
11 });
12 amigaMaterial.doNotSerialize=true ;
13 sphere1.material=amigaMaterial;
14 if (strsrc_dqk=="")
15 {
16 context_temp.putImageData(imagedata_temp,0,0);
17 strsrc_dqk=can_temp.toDataURL("image/png");//将canvas转化为dataurl
18 localStorage.setItem("strsrc_dqk",JSON.stringify(strsrc_dqk));
19 }
20 var utexturedqk = new BABYLON.Texture.CreateFromBase64String(strsrc_dqk,"utexturedqk", scene
21 ,false ,false ,BABYLON.Texture.NEAREST_NEAREST);//将dataurl转化为Babylon.js纹理
22 amigaMaterial.setTexture("utexturedqk",utexturedqk);//将纹理和显卡采样器关联
23 amigaMaterial.setFloat("wid_utexturedqk",can_temp.width);// 数据纹理宽度,将内存中的变量和显卡中的通用变量关联
24 amigaMaterial.setFloat("hei_utexturedqk",can_temp.width);
25 amigaMaterial.setFloat("pbeta",pbeta);// 层间区分角度
26
27 var size=newland.FindPower2(arr_palpha.length);//注意!!!!
28 var strsrc_palpha=newland.TranArrToPng1(arr_palpha,size,size);// 每一层内的房间区分角度,用4个元素保存一个浮点数
29 var utexturepalpha = new BABYLON.Texture.CreateFromBase64String(strsrc_palpha,"utexturepalpha", scene
30 ,true ,false ,BABYLON.Texture.NEAREST_NEAREST);
31 amigaMaterial.setTexture("utexturepalpha",utexturepalpha);
32 amigaMaterial.setFloat("wid_utexturepalpha",size);// room区分度的纹理宽度
33 amigaMaterial.setFloat("hei_utexturepalpha",size);
34
35 amigaMaterial.setFloat("uarrpalphalen",arr_palpha.length);
36 amigaMaterial.setFloat("max_floorf",max_floor);// Babylon.js不支持传递整形量??GpenGL中int也是以float形式计算的!!!!
37 amigaMaterial.setFloat("MathPI",Math.PI);
38
39 amigaMaterial.onCompiled=function ()//Babylon.js 文档中写effect是material的一个内容,而material需要一个“编译过程”,编译之后的material才具备effect属性
40 {//而且对Babylon.js来说,material能传递的变量类型比较少,比如不能传递整形量,而effect则可以传递更多的数据类型
41 //amigaMaterial.getEffect().setArray("uarrpalpha",arr);//每一层水平区分度*/effect可以向显卡传递数组
//console.log(amigaMaterial.getEffect()); }
42 }
这里我们要考虑使用何种方式把长度为199的浮点型数组arr_palpha传入显卡,事实上OpenGL支持传入数组型通用变量,但对数组的支持分成两种:一种是我们前面看到的vec3、vec4这类向量数组,glsl把整个向量看做一个变量,而另一种类似“uniform float uarrpalpha[500]”的自定义数组则是把数组中的每一个元素都看做一个uniform变量处理!(?)。
根据StackOverFlow上一个外国同行的试验,OpenGL最多只能支持200个左右的uniform变量(?),这意味着我们难以直接用数组的方式传入arr_palpha。另外在WebGL1.0中的glsl不支持不定长度的数组,这意味着我们必须在编写着色器代码前对数组的大小有恰当的估计,或者根据行星的大小临时调节着色器代码。
在glsl中使用长数组的另一个问题是:glsl竟然不支持直接用临时赋值的变量作为数组索引!类似
1 int i=1 ;
2 float f=arr[i+1 ];
这种数组用法是不允许的!!!!
要将计算结果作为数组的索引只能使用if else或者switch case枚举出每一种对应的情况,或者使用:
1 float getData500(float data[500 ],int id) {
2 int len=int (floor(uarrpalphalen+0.5 ));
3 for (int i=0 ; i<500 ; i++) {
4 if (i>=len)// i不能和非常量比较!!只好换个方式限制它
5 {
6 return 0.0 ;
7 }
8 if (i == id) return data[i];
9 }
10 }
其中id是计算出来的索引,另外glsl的for循环的中段也不支持“i
因此改为使用datatexture传递水平区分度数组
然而使用datatexture时又遇到一个问题,canvas会自动把颜色分量转化为0到255的整数,而这里的水平区分度全是0到1之间的小数,会被自动转为0或1,为解决这一问题把水平区分度数据转化为科学计数法并用像素表示:
1 // 将一个浮点数组转化为DataTexture,这是浮点数小于1的情况,要注意canvas和webgl对颜色属性的自动处理!!!!
2 newland.TranArrToPng1=function (arr,width,height)
3 {
4 var can_temp=document.createElement("canvas");
5 can_temp.width=width;
6 can_temp.height=height;
7 var context=can_temp.getContext("2d");
8 context.fillStyle="rgba(0,0,255,1)";// 多余的位都是1?
9 context.fillRect(0,0,width,height);
10 var imagedata=context.getImageData(0,0,width,height);
11 var len=arr.length;// 小数部分会自动四舍五入!!!!默认palpha必定小于1
12 for (var i=0;i13 {
14 var str_num=arr[i]+"";
15 // var int_0=str_num.indexOf();
16 var len_str=str_num.length;
17 var count_0=0;
18 for (var j=0;j)
19 {
20 if (str_num[j]=="0"||str_num[j]==".")
21 {
22 continue ;
23 }
24 else
25 {
26 count_0=j;// 找到第一个非零数
27 break ;
28 }
29 }
30 var num1=parseInt(str_num.substr(count_0,2));
31 var num2=parseInt(str_num.substr(count_0+2,2));
32 // var num3=parseInt(str_num.substr(count_0+4,2));
33 var num4=4+(count_0-2);
34 imagedata.data[i*4]=num1;//科学计数法:用像素颜色的第一第二个分量保存四位有效数字,用第四个分量保存10的负指数
35 imagedata.data[i*4+1]=num2;
36 imagedata.data[i*4+2]=num4;
37 // imagedata.data[i*4+3]=num4;
38 }
39 context.putImageData(imagedata,0,0);
40 var strsrc_palpha=can_temp.toDataURL("image/png");
41 // can_temp.dispose();
42 can_temp=null ;
43 return strsrc_palpha;
44 }
执行程序,看到运行效果与设计有所偏差:
南半球的黑色地区块少了很多行,没有形成预计的棋盘形,时间有限没有详细调试
拉近相机:
可以看到每个地区块的边界清晰可见,没有发生模糊。
使用console.log输出用到的两个dataurl作为参考:
4、着色器代码:
a、顶点着色器:
1 uniform mat4 worldViewProjection;
2 uniform mat4 worldView;
3 attribute vec3 position;
4
5 varying vec3 vPosition;
6 varying vec3 oPosition;// 自身坐标系里的位置
7
8 void main(){
9 gl_Position=worldViewProjection*vec4(position,1 );
10 vPosition=vec3(worldView*vec4(position,1 ));
11 oPosition=position;
12 }
我们前面生成地形的计算都是在行星的自身坐标系里进行的,所以在片元着色器里也需要以行星的自身坐标系为参考确定地区块的层数和房间号,所以把一个不经过任何矩阵变换的顶点位置信息传入片元着色器。
b、片元着色器:
1 precision highp float ;
2 // varying vec4 vColor;
3 varying vec3 vPosition;
4 varying vec3 oPosition;
5 // uniform vec4 uColor;
6 uniform sampler2D utexturedqk;//地区块数据纹理的采样器
7 uniform float wid_utexturedqk;//数据纹理的宽高
8 uniform float hei_utexturedqk;
9
10 uniform sampler2D utexturepalpha;// 一个单元里保存了四个元素!!!!
11 // uniform vec3 uarrdqk[60000]; // es3.0之前的glsles不支持隐含数组!!!!
12 uniform float pbeta;
13 uniform float wid_utexturepalpha;
14 uniform float hei_utexturepalpha;
15 // uniform float uarrpalpha[500]; // 用来测试的行星只有199层,预设为500层应该够了
16 uniform float uarrpalphalen;
17 uniform float max_floorf;
18 uniform float MathPI;
19
20 float getDataVec4(vec4 data,int id) {
21 for (int i=0 ; i<4 ; i++) {
22 if (i == id) return data[i];
23 }
24 }
25 float getData500(float data[500 ],int id) {
26 int len=int (floor(uarrpalphalen+0.5 ));
27 for (int i=0 ; i<500 ; i++) {
28 if (i>=len)// i不能和非常量比较!!只好换个方式限制它
29 {
30 return 0.0 ;
31 }
32 if (i == id) return data[i];
33 }
34 }
35
36 void main()
37 {
38 // vec4 tempColor=uColor; // es3.0之前不支持round!!!!
39 // glsl事实上以float为计算基准
40 // int max_floor=int(floor(max_floorf+0.5));
41 // 算层数
42 float r=sqrt(oPosition.x*oPosition.x+oPosition.y*oPosition.y+oPosition.z*oPosition.z);//这个片元到球心的距离
43 float beta=asin(oPosition.y/r);// 俯仰角
44 // int int_beta=int(floor((beta/(pbeta*2.0))+0.5));
45 float count_beta=(beta/(pbeta*2.0 ));
46 // int index_beta=int(floor(count_beta+ max_floorf+0.5));
47 float index_beta=floor(count_beta+ max_floorf+0.5 );//第几层
48 // int roomcount=0;
49 // 使用数据纹理法,取这一层的区分度
50 // int int1=int(floor(mod(index_beta,4.0)+0.5)); 51 // float float1=(index_beta/4.0);
52 float floatu=(mod(index_beta,wid_utexturepalpha))/(wid_utexturepalpha)+(0.5 /wid_utexturepalpha);// u是x轴坐标,v是y轴坐标
53 float floatv=(((index_beta)/(wid_utexturepalpha)))/(hei_utexturepalpha)+(0.5 /(wid_utexturepalpha*hei_utexturepalpha));
54 vec2 UVpalpha=vec2(floatu,floatv);//上面计算的uv坐标加了一个偏移量,防止坐标正好落在两个像素的边界上
55 vec4 vec4palphas=texture2D(utexturepalpha, UVpalpha);//glsl中的颜色为0到1.0,所以要乘以255.0获得传入的科学计数法
56 float palpha=(vec4palphas[0 ]*255.0 *100.0 +vec4palphas[1 ]*255.0 )/pow(10.0 ,vec4palphas[2 ]*255.0 );
57 // float palpha=getData500(uarrpalpha,int(floor(index_beta+0.5))); // 改为尝试数组法传递数据
58 // 取这一层的转角
59 float alpha=atan(oPosition.z,oPosition.x);// 标准反正切函数有两个参数!!
60 if (alpha<0.0 )
61 {
62 alpha+=(MathPI*2.0 );
63 }
64 // 取地区块数据纹理的坐标
65 float floatu2=(alpha/(palpha*2.0 ))/wid_utexturedqk;
66 float floatv2=index_beta/hei_utexturedqk+0.5 /hei_utexturedqk;
67 vec2 UVdqk=vec2(floatu2,floatv2);
68 gl_FragColor=texture2D(utexturedqk, UVdqk);
69 // gl_FragColor=vec4palphas;
70 // gl_FragColor=texelFetch(utexturedqk,ivec2(int(floor(alpha/(palpha*2.0)+0.5)),int(floor(index_beta+0.5))),0); // 这个整数像素的方法是WebGL2开始加入的!!!!
71 // gl_FragColor=vec4(1.0*floatu,1.0*floatv,1.0*floatv2,1.0); // 红,绿,蓝结果不是0就是1??!!
72
73 // int index_dqk=roomcount-1+int(floor((alpha/palpha)+0.5));
74 // vec4 tempColor=vec4(uarrdqk[index_dqk],1.0);
75
76 // float float_3=index_beta/(max_floorf*2.0);
77 // float float_4=oPosition.y/5.0;
78 // canvas的imagedata用255,255,255,255定义颜色通道,而glsl用1.0,1.0,1.0,1.0定义!!!!
79
80
81 }
glsl语言不支持字符串类型,WebGL1.0也不支持从显卡反写数据到内存,一种可行的调试方法是将某个计算结果转化为颜色显示在屏幕上,然后用拾色器提取值。
四、根据规则生成随机的行星表面地形(testarenas.html)
1、生成地区块的基本数据结构:
1 function CookDqk()// 生成地区块,每一floor的每个room
2 {
3 var size_dqk=100;// 每个地区块的长宽都是100km
4 var r_planet=perimeter/(2*Math.PI);//行星的半径
5 var len_beta=sswr(((perimeter/2)/size_dqk)/2);//通过弧度来分层!!100
6 pbeta=(Math.PI/4)/len_beta;
7 // 对于每一层,
8 for (var i=-len_beta;i<=len_beta;i++)
9 {
10
11 var rad_beta=(Math.PI/2)*(i/len_beta);
12 var r_floor=Math.cos(rad_beta)*r_planet;// 这一层的半径
13 var len_alpha_floor=sswr((r_floor*2*Math.PI)/size_dqk);
14 var palpha=Math.PI/len_alpha_floor;//每一个地区块的角度边界,在这个边界范围内即属于这个地区块
15 arr_palpha.push(palpha);
16 var beta=i*pbeta*2;
17 // console.log(i+"/"+len_beta+">"+len_alpha_floor);
18 var arr1=[];
19 // 对于圆环上的每一个片
20 for (var j=0;j)
21 {
22 var obj={};
23 obj.palpha=palpha;
24 obj.alpha=j*palpha*2;
25 obj.pbeta=pbeta;
26 obj.beta=beta;
27 // obj.weight={};
28 obj.floor=i;
29 obj.room=j;
30 obj.countcook=0;
31 obj.altitude=0;
32
33 arr1.push(obj);
34
35 }
36 if (arr1.length>0)
37 {
38 arr_floorroom.push(arr1);
39 }
40
41 }
42 CookDqk2();// 对生成的数据结构进行 规律随机填充
43 }
View Code
2、使用正态随机数与加和平均确定每个地区块的海拔
1 // 使用正态随机数和加和平均确定每个地区块的海拔
2 function CookDqk2()
3 {
4 var len=arr_floorroom.length;
5 // 生成初始的随机正态随机海拔
6 console.log("生成初始的随机正态随机海拔");
7 for (var i=0;i)
8 {
9 // console.log(i+" in "+len);
10 var len2=arr_floorroom[i].length;
11 for (var j=0;j)
12 {
13 var obj=arr_floorroom[i][j];
14 obj.altitude=dc1.getNumberInNormalDistribution(-10,1000);// 平均海拔是-10,常见的海拔在正负1000以内
15 if (obj.altitude<-10000)
16 {
17 obj.altitude=-10000;
18 }
19 else if (obj.altitude>10000)
20 {
21 obj.altitude=10000;
22 }
23 obj.countcook=1;
24 if (i%2==1)// 如果是奇数层,room偏移一个识别范围,这样地形看起来更自然
25 {
26 obj.alpha+=obj.palpha;
27 }
28 }
29 }
30 // 使用加和平均方法使海拔趋于连续(高度平滑)
31 console.log("使用加和平均方法使海拔趋于连续");
32 for (var i=0;i)//将地区块的海拔和周围相邻的所有地区块的海拔相加取平均值,作为这个地区块的海拔
33 {
34 console.log(i+" in "+len);
35 var len2=arr_floorroom[i].length;
36 for (var j=0;j)
37 {
38 var obj=arr_floorroom[i][j];
39 obj.altitude1=obj.altitude;
40 if (i>0)// 考虑这个room下面的floor
41 {
42 // var alpha=obj.alpha;
43 var len3=arr_floorroom[i-1].length;
44 for (var k=0;k//遍历下层的room
45 {
46 var subplpha=Math.abs(arr_floorroom[i-1][k].alpha-obj.alpha);
47 if (subplpha>Math.PI)
48 {
49 subplpha=Math.PI*2-subplpha;
50 }
51 if (subplpha<=(obj.palpha+arr_floorroom[i-1][k].palpha))
52 {// 对这个地区块有影响
53 obj.altitude1+=arr_floorroom[i-1][k].altitude;
54 obj.countcook++;
55 }
56 }
57
58 }
59 if (i//考虑这个room上面的floor
60 {
61 var len3=arr_floorroom[i+1].length;
62 for (var k=0;k//遍历上层的room
63 {
64 var subplpha=Math.abs(arr_floorroom[i+1][k].alpha-obj.alpha);
65 if (subplpha>Math.PI)
66 {
67 subplpha=Math.PI*2-subplpha;
68 }
69 if (subplpha<=(obj.palpha+arr_floorroom[i+1][k].palpha))
70 {// 对这个地区块有影响
71 obj.altitude1+=arr_floorroom[i+1][k].altitude;
72 obj.countcook++;
73 }
74 }
75 }
76 // 考虑本层的相邻元素
77 if (j==0)
78 {
79 obj.altitude1+=arr_floorroom[i][1].altitude;
80 obj.altitude1+=arr_floorroom[i][len2-1].altitude;
81 obj.countcook+=2;
82 }else if (j==(len2-1))
83 {
84 obj.altitude1+=arr_floorroom[i][0].altitude;
85 obj.altitude1+=arr_floorroom[i][len2-2].altitude;
86 obj.countcook+=2;
87 }
88 else {
89 obj.altitude1+=arr_floorroom[i][j-1].altitude;
90 obj.altitude1+=arr_floorroom[i][j+1].altitude;
91 obj.countcook+=2;
92 }
93 }
94 }
95 var min_altitude= 0,max_altitude=0;
96 console.log("去除总权值");
97 for (var i=0;i)
98 {
99 console.log(i+" in "+len);
100 var len2=arr_floorroom[i].length;
101 for (var j=0;j)
102 {
103 var obj=arr_floorroom[i][j];
104 obj.altitude=obj.altitude1/obj.countcook;
105 if (obj.altitude<min_altitude)
106 {
107 min_altitude=obj.altitude;
108 }
109 if (obj.altitude>max_altitude)
110 {
111 max_altitude=obj.altitude;
112 }
113 // delete obj.altitude1;
114 }
115 }
116 console.log("最低、最高海拔为:"+min_altitude+"、"+max_altitude);
117 // 根据海拔高度与概率规则确定海洋与陆地,根据纬度和高度确定陆地的类型(高度达到一定程度后优于纬度)
118 CookDqk3();
119 }
关于正态随机数的知识可以参考这篇文章:https://www.cnblogs.com/zztt/p/4025207.html
3、根据海拔高度和纬度确定地形:
1 function CookDqk3()
2 {
3 console.log("开始生成地区块级地形");
4 var len=arr_floorroom.length;
5 for (var i=0;i) {
6 console.log(i+" in "+len);
7 var len2 = arr_floorroom[i].length;
8 for (var j = 0; j < len2; j++)
9 {
10 var obj=arr_floorroom[i][j];
11 getLandtypeDqk(obj);//根据规则确定这个地区块的地形
12 }
13 }
14 // 地区块平滑
15 console.log("地区块平滑");
16 for (var i=0;i)
17 {
18 console.log(i+" in "+len);
19 var len2=arr_floorroom[i].length;
20 for (var j=0;j)
21 {
22 var obj=arr_floorroom[i][j];
23
24 if (i>0)// 考虑这个room下面的floor
25 {
26 // var alpha=obj.alpha;
27 var len3=arr_floorroom[i-1].length;
28 for (var k=0;k//遍历下层的room
29 {
30 var obj1=arr_floorroom[i-1][k];
31 var subplpha=Math.abs(obj1.alpha-obj.alpha);
32 if (subplpha>Math.PI)
33 {
34 subplpha=Math.PI*2-subplpha;
35 }
36 if (subplpha<=(obj.palpha+obj1.palpha))
37 {// 对这个地区块有影响
38 if (!obj.landtypedqk[obj1.type2])
39 {
40 obj.landtypedqk[obj1.type2]=obj1.effect;//这一种地形的权重
41 }
42 else
43 {
44 obj.landtypedqk[obj1.type2]+=obj1.effect;
45 }
46 obj.landtypedqkeffect+=obj1.effect;//所有地形的权重
47 }
48 }
49
50 }
51 if (i//考虑这个room上面的floor
52 {
53 var len3=arr_floorroom[i+1].length;
54 for (var k=0;k//遍历上层的room
55 {
56 var obj1=arr_floorroom[i+1][k];
57 var subplpha=Math.abs(obj1.alpha-obj.alpha);
58 if (subplpha>Math.PI)
59 {
60 subplpha=Math.PI*2-subplpha;
61 }
62 if (subplpha<=(obj.palpha+obj1.palpha))
63 {// 对这个地区块有影响
64 if (!obj.landtypedqk[obj1.type2])
65 {
66 obj.landtypedqk[obj1.type2]=obj1.effect;
67 }
68 else
69 {
70 obj.landtypedqk[obj1.type2]+=obj1.effect;
71 }
72 obj.landtypedqkeffect+=obj1.effect;
73 }
74 }
75 }
76 // 考虑本层的相邻元素
77 if (j==0)
78 {
79 var obj1=arr_floorroom[i][1];
80 if (!obj.landtypedqk[obj1.type2])
81 {
82 obj.landtypedqk[obj1.type2]=obj1.effect;
83 }
84 else
85 {
86 obj.landtypedqk[obj1.type2]+=obj1.effect;
87 }
88 obj.landtypedqkeffect+=obj1.effect;
89 var obj1=arr_floorroom[i][len2-1];
90 if (!obj.landtypedqk[obj1.type2])
91 {
92 obj.landtypedqk[obj1.type2]=obj1.effect;
93 }
94 else
95 {
96 obj.landtypedqk[obj1.type2]+=obj1.effect;
97 }
98 obj.landtypedqkeffect+=obj1.effect;
99 }
100 else if (j==(len2-1))
101 {
102 var obj1=arr_floorroom[i][0];
103 if (!obj.landtypedqk[obj1.type2])
104 {
105 obj.landtypedqk[obj1.type2]=obj1.effect;
106 }
107 else
108 {
109 obj.landtypedqk[obj1.type2]+=obj1.effect;
110 }
111 obj.landtypedqkeffect+=obj1.effect;
112 var obj1=arr_floorroom[i][len2-2];
113 if (!obj.landtypedqk[obj1.type2])
114 {
115 obj.landtypedqk[obj1.type2]=obj1.effect;
116 }
117 else
118 {
119 obj.landtypedqk[obj1.type2]+=obj1.effect;
120 }
121 obj.landtypedqkeffect+=obj1.effect;
122 }
123 else {
124 var obj1=arr_floorroom[i][j-1];
125 if (!obj.landtypedqk[obj1.type2])
126 {
127 obj.landtypedqk[obj1.type2]=obj1.effect;
128 }
129 else
130 {
131 obj.landtypedqk[obj1.type2]+=obj1.effect;
132 }
133 obj.landtypedqkeffect+=obj1.effect;
134 var obj1=arr_floorroom[i][j+1];
135 if (!obj.landtypedqk[obj1.type2])
136 {
137 obj.landtypedqk[obj1.type2]=obj1.effect;
138 }
139 else
140 {
141 obj.landtypedqk[obj1.type2]+=obj1.effect;
142 }
143 obj.landtypedqkeffect+=obj1.effect;
144 }
145 }
146 }
147 console.log("对每个地区块进行加权并入库");
148 for (var i=0;i//对每个地区块进行加权,这段代码执行很慢
149 {
150 var len2=arr_floorroom[i].length;
151 console.log(i+" in "+len);
152 for (var j=0;j)
153 {
154
155 var obj=arr_floorroom[i][j];
156 obj.altitude=obj.altitude/obj.countcook;
157 var rate_type1final=Math.random()*obj.landtypedqkeffect;
158 var rate_type1final_count=0;
159 obj.type2final="默认dqk";
160 for (key in obj.landtypedqk)
161 {
162 rate_type1final_count+=obj.landtypedqk[key];// 这一种地形的权重
163 if (rate_type1final<rate_type1final_count)//如果随机数小于这种地形的累积权重
164 {
165 obj.type2final=key;
166 break ;
167 }
168 }
169 // 在这里把这个地区块插入数据库?不知道什么原因POST方法失败了,改用GET方法
170 /* Url="http://127.0.0.1:8082/query.do?jsessionid="+jsessionid;
171 Argv="sql=insert into tab_dqk values(uuid(),'test1',"+obj.beta+","+obj.pbeta+","+obj.alpha+","+obj.palpha+",'"
172 +obj.type2final+"',"+obj.floor+","+obj.room+","+obj.altitude+")";
173 //使用同步Ajax请求保证进度同步,在连续使用同步Ajax时不需要xmlHttp.abort()!!!!
174 Request(xmlHttp,"POST",Url,false,Argv,"application/x-www-form-urlencoded",PushChessCallBack,0); */
175 Url="http://127.0.0.1:8082/query.do?jsessionid="+jsessionid+"&sql=insert into tab_dqk values(uuid(),'test1',"+obj.beta+","+obj.pbeta+","+obj.alpha+","+obj.palpha+",'"
176 +obj.type2final+"',"+obj.floor+","+obj.room+","+obj.altitude+")"
177 Argv="";
178 Request(xmlHttp,"GET",Url,false ,Argv,"application/x-www-form-urlencoded",PushChessCallBack,0);
179 }//这里改变了一下数据结构,直接用weight字段存储确定了的地区块级地形
180 }
181 CookDqk4();// 着色
182 }
getLandtypeDqk是根据海拔和纬度确定地形的方法:(这个方法效率很低)
1 function getLandtypeDqk(obj)
2 {
3 var height=obj.altitude;// 对于这个地区块
4 var beta=obj.beta;
5 var rate_land=Math.random();
6 for (key in tab_landtypedqk)// 这个方法并不能保证顺序!!!!//for key和eval占用了大量时间????
7 {// 按顺序查找每一个地区块级地形是否符合条件,
8 if (eval(tab_landtypedqk[key].eval))//JavaScript语言的一大特点是可以随时把字符串转化为可执行代码,
9 {//这使得JavaScript语言可以非常灵活,但是会降低执行效率和安全性
10 obj.type1=key;
11 var count_rate=0;// 用来累加概率
12 var obj1=tab_landtypedqk[key];
13 for (key2 in obj1)
14 {
15 if (key2!="eval")
16 {
17 var rate_type2=Math.random();
18 count_rate+=obj1[key2].rate;
19 if (rate_type2<count_rate)
20 {
21 obj.type2=key2;
22 obj.effect=obj1[key2].effect;// 对周边地块的影响程度
23 break ;
24 }
25 }
26 }
27 break ;
28 }
29 }
30 if (!obj.type1)// 如果这个地区块没有被分配地形
31 {
32 obj.type1="未定义";
33 obj.type2="默认dqk";
34 obj.effect=0;
35 }
36 obj.landtypedqk={};//这三个变量用于对地形进行平滑处理
37 obj.landtypedqk[obj.type2]=obj.effect;
38 obj.landtypedqkeffect=obj.effect;
39 }
在同一海拔和纬度可能有多种地形存在,每一种地形都有一个出现概率,取一个随机数,如果这个随机数小于遍历到这个地形时的概率累积,则将这个地区块设为这种地形。
每一种地形还有一个effect属性,表示这种地形对周边地形的影响能力,比如如果一片热带雨林周围全被沙漠包围,那么这片雨林有很大可能变成沙漠。
海拔和纬度与地形的对应关系设定如下:(tab_datalib.js)
1 // 地区块地形元素分布表
2 var beta_2326=((23+26/60)/180)*Math.PI;// 南北回归线弧度
3 var beta_6034=((60+34/60)/180)*Math.PI;// 南北极圈弧度
4 var beta_8=((8)/180)*Math.PI;//赤道附近弧度
5 var tab_landtypedqk={// rate按从小到大排列生成的随机数小于哪个就定为何种地形,effect在卷积平滑阶段起作用,表示这个地形对周围环境的影响程度
6 "热带海洋":{eval:"height<0&&rate_land<0.9&&Math.abs(beta)//eval是判断地区块大类型的判断条件,以后在设计技能效果时也可能要借鉴这里
7 "温带海洋":{eval:"height<0&&rate_land<0.9&&Math.abs(beta)>beta_2326&&Math.abs(beta)}},
8 "寒带海洋":{eval:"height<0&&rate_land<0.9&&Math.abs(beta)>beta_6034","寒带海洋dqk":{rate:1,effect:1}},
9 "温带1500米以下":{eval:"rate_land>0.1&&Math.abs(beta)>beta_2326&&Math.abs(beta)}},
10 "温带1500米以上":{eval:"rate_land>0.1&&Math.abs(beta)>beta_2326&&Math.abs(beta)=1500","雪山dqk":{rate:1,effect:1}},
11 "亚热带3000米以下":{eval:"rate_land>0.1&&Math.abs(beta)>beta_8&&Math.abs(beta)}},
12 "亚热带3000米以上":{eval:"rate_land>0.1&&Math.abs(beta)>beta_8&&Math.abs(beta)=3000","雪山dqk":{rate:1,effect:1}},
13 "热带3000米以下":{eval:"rate_land>0.1&&Math.abs(beta)}},
14 "热带3000米以上":{eval:"rate_land>0.1&&Math.abs(beta)=3000","雪山dqk":{rate:1,effect:1}},
15 "寒带-100米以下":{eval:"rate_land>0.1&&Math.abs(beta)>beta_6034&&height<-100","草原dqk":{rate:0.4,effect:1},"森林dqk":{rate:0.4,effect:1},"戈壁dqk":{rate:0.2,effect:2}},
16 "寒带-100到200米以内":{eval:"rate_land>0.1&&Math.abs(beta)>beta_6034&&height<200&&height>=-100","寒带森林dqk":{rate:0.6,effect:1},"冰川dqk":{rate:0.4,effect:1}},
17 "寒带200米以上":{eval:"rate_land>0.1&&Math.abs(beta)>beta_6034&&height>200","冰川dqk":{rate:1,effect:1}}
18 }
19 var tab_landtypedqk2={// 每一种地区块的远观颜色和内部地貌块(单位块?)占比
20 "默认dqk":{color:[250,126,126],content:{"红白格dmk":{rate:1,effect:0}}},// 完全红白格,这种表示错误和未定义的地貌块不会影响周围
21 "热带海洋dqk":{color:[15,63,105],content:{"海洋水面dmk":{rate:0.99,effect:1},"雨林dmk":{rate:0.995,effect:0},"沙滩dmk":{rate:1,effect:0}}},
22 "温带海洋dqk":{color:[15,63,105],content:{"海洋水面dmk":{rate:0.99,effect:1},"森林dmk":{rate:0.995,effect:0},"沙滩dmk":{rate:1,effect:0}}},
23 "寒带海洋dqk":{color:[15,63,105],content:{"海洋水面dmk":{rate:0.5,effect:1},"冰面dmk":{rate:1,effect:1}}},
24 "草原dqk":{color:[93, 153, 63],content:{"草地dmk":{rate:0.95,effect:1},"内陆水面dmk":{rate:1,effect:1}}},
25 "森林dqk":{color:[33,68,44],content:{"森林dmk":{rate:0.95,effect:1},"内陆水面dmk":{rate:1,effect:1}}},
26 "戈壁dqk":{color:[127, 102, 79],content:{"戈壁dmk":{rate:1,effect:1}}},
27 "雪山dqk":{color:[220, 221, 220],content:{"雪地dmk":{rate:0.8,effect:1},"岩石dmk":{rate:1,effect:0}}},
28 "热带雨林dqk":{color:[33,68,44],content:{"雨林dmk":{rate:0.95,effect:1},"内陆水面dmk":{rate:1,effect:1}}},
29 "稀树草原dqk":{color:[117, 118, 68],content:{"稀树草原dmk":{rate:0.95,effect:1},"内陆水面dmk":{rate:1,effect:1}}},
30 "沙漠dqk":{color:[175, 117, 68],content:{"沙地dmk":{rate:0.99,effect:1},"内陆水面dmk":{rate:0.995,effect:0},"绿洲dmk":{rate:1,effect:0}}},
31 "寒带森林dqk":{color:[],content:{"寒带森林dmk":{rate:0.85,effect:1},"雪地dmk":{rate:1,effect:1}}},
32 "冰川dqk":{color:[201, 216, 220],content:{"冰面dmk":{rate:0.85,effect:1},"雪地dmk":{rate:1,effect:1}}}
33 }
34 var tab_landtypedmk={// 每一种地貌块的纹理url
35 "红白格dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/amiga.jpg",color:[250,126,126]},// 对单位的影响,纹理Url,纹理的平均颜色
36 "海洋水面dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/sea.png",color:[15,63,105]},
37 "雨林dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/yulin.png",color:[33,68,44]},
38 "沙滩dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/shatan.png",color:[205, 160, 109]},
39 "森林dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/yulin.png",color:[33,68,44]},// 没找到温带森林,暂时用雨林代替
40 "冰面dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/ice.png",color:[201, 216, 220]},
41 "草地dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/grass.png",color:[93, 153, 63]},
42 "内陆水面dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/lake.png",color:[93,143,180]},
43 "戈壁dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/gebi.png",color:[127, 102, 79]},
44 "雪地dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/snow.png",color:[220, 221, 220]},
45 "岩石dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/stone.png",color:[82, 81, 74]},
46 "稀树草原dmk":{eval_effect:"../../ASSETS/IMAGE/Texture_landtypedmk/xishucaoyuan.png",Url:"",color:[117, 118, 68]},
47 "沙地dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/sand.png",color:[175, 117, 68]},
48 "绿洲dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/lvzhou.png",color:[127, 144, 111]},
49 "寒带森林dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/lvzhou.png",color:[127, 144, 111]}
50
51 }
这里设定每一个100km*100km的地区块可以由更小的“地貌块”组成,在极近时地貌块的地形显示为实际的纹理图,在较远时地貌块表现为纹理图的平均色,在更远一些时用地区块代替地貌块,地区块的颜色为地貌块的加权。
目前这个切换功能还未编写,因为时间有限实际地形纹理也没有仔细设置,地区块的颜色加权也没做,直接使用了占比较多的地貌块颜色。
提取纹理图平均颜色的代码如下:(testpix.html)
1 DOCTYPE html >
2 < html lang ="en" >
3 < head >
4 < meta charset ="UTF-8" >
5 < title > 提取一副固定大小图片的平均颜色color4title >
6 head >
7 < body >
8 < div id ="div_allbase" >
9 < canvas style ="width: 512px;height: 512px" width ="512" height ="512" id ="can_pic" >
10
11 canvas >
12 div >
13 body >
14 < script >
15 var canvas = document.getElementById( " can_pic " );
16 window.onload = loadImage;
17 function loadImage()
18 {
19 var context = canvas.getContext( " 2d " );
20 var img = document.createElement( " img " );
21 img.src = " ../../ASSETS/IMAGE/Texture_landtypedmk/lvzhou.png " ;
22 img.onload = function ()
23 { // 在图片加载完毕后才可以在canvas里绘制
24 context.drawImage(img, 0 , 0 );
25 var imagedata_temp = context.getImageData( 0 , 0 , 512 , 512 ); // 规定地貌块纹理图片的宽高是512
26 var data = imagedata_temp.data;
27 var len = data.length;
28 var color4 = [ 0 , 0 , 0 , 0 ];
29 for ( var i = 0 ;i < len;i += 4 )
30 {
31 color4[ 0 ] += data[i];
32 color4[ 1 ] += data[i + 1 ];
33 color4[ 2 ] += data[i + 2 ];
34 color4[ 3 ] += data[i + 3 ];
35 }
36 var int = 512 * 512 ;
37 color4[ 0 ] = Math.round(color4[ 0 ] / int);
38 color4[ 1 ] = Math.round(color4[ 1 ] / int);
39 color4[ 2 ] = Math.round(color4[ 2 ] / int);
40 color4[ 3 ] = Math.round(color4[ 3 ] / int);
41 console.log(color4);
42 }
43
44 }
45 script >
46 html >
View Code
4、生成数据纹理
1 function CookDqk4()
2 {
3 var len=arr_floorroom.length;
4 // 开始生成数据纹理
5 console.log("开始生成数据纹理");
6 for (var i=0;i//每一行
7 {
8 // console.log(i+" in "+len);
9 var len2 = arr_floorroom[i].length;
10 for (var j = 0; j < len2; j++) {
11 var obj = arr_floorroom[i][j];
12 var index= (i)*4*can_temp.width+(j-1)*4;// 每个room由4个元素组成
13 var color4=[];
14 if (tab_landtypedqk2[obj.type2final].color)
15 {//从地形对象中获取颜色
16 color4=tab_landtypedqk2[obj.type2final].color;
17 }
18 else
19 {
20 color4=[250,126,126];// 默认纹理远观颜色
21 }
22 imagedata_temp.data[index]=color4[0];// 这里存的真的是颜色
23 imagedata_temp.data[index+1]=color4[1];
24 imagedata_temp.data[index+2]=color4[2];
25 imagedata_temp.data[index+3]=255;
26
27 }
28 }
29
30 }
然后用和前面类似的方式将数据纹理送入显卡并进行渲染
着色器代码如下:
顶点着色器:
1 uniform mat4 worldViewProjection;
2 uniform mat4 worldView;
3 attribute vec3 position;
4
5 varying vec3 vPosition;
6 varying vec3 oPosition;// 自身坐标系里的位置
7
8 void main(){
9 gl_Position=worldViewProjection*vec4(position,1 );
10 vPosition=vec3(worldView*vec4(position,1 ));
11 oPosition=position;
12 }
View Code
片元着色器:
1 precision highp float ;
2 // varying vec4 vColor;
3 varying vec3 vPosition;
4 varying vec3 oPosition;
5 // uniform vec4 uColor;
6 uniform sampler2D utexturedqk;
7 uniform float wid_utexturedqk;
8 uniform float hei_utexturedqk;
9
10 uniform sampler2D utexturepalpha;// 一个单元里保存了四个元素!!!!
11 // uniform vec3 uarrdqk[60000]; // es3.0之前的glsles不支持隐含数组!!!!
12 uniform float pbeta;
13 uniform float wid_utexturepalpha;
14 uniform float hei_utexturepalpha;
15 // uniform float uarrpalpha[500]; // 用来测试的行星只有199层,预设为500层应该够了
16 uniform float uarrpalphalen;
17 uniform float max_floorf;
18 uniform float MathPI;
19
20 float getDataVec4(vec4 data,int id) {
21 for (int i=0 ; i<4 ; i++) {
22 if (i == id) return data[i];
23 }
24 }
25 float getData500(float data[500 ],int id) {
26 int len=int (floor(uarrpalphalen+0.5 ));
27 for (int i=0 ; i<500 ; i++) {
28 if (i>=len)// i不能和非常量比较!!只好换个方式限制它
29 {
30 return 0.0 ;
31 }
32 if (i == id) return data[i];
33 }
34 }
35 float getOdevity(float a)// 判断浮点型整数的奇偶性,偶返回0,奇返回1
36 {
37 float b=mod(a,2.0 );
38 float c=0.0 ;
39 if (b>=0.5 &&b<1.5 )
40 {
41 c=1.0 ;
42 }
43 return c;
44 }
45
46 void main()
47 {
48 // vec4 tempColor=uColor; // es3.0之前不支持round!!!!
49 // glsl事实上以float为计算基准
50 // int max_floor=int(floor(max_floorf+0.5));
51 // 算层数
52 float r=sqrt(oPosition.x*oPosition.x+oPosition.y*oPosition.y+oPosition.z*oPosition.z);
53 float beta=asin(oPosition.y/r);// 俯仰角
54 // int int_beta=int(floor((beta/(pbeta*2.0))+0.5)); // 层数
55 float count_beta=(beta/(pbeta*2.0 ));
56 // int index_beta=int(floor(count_beta+ max_floorf+0.5)); // 整数层数索引
57 float index_beta=floor(count_beta+ max_floorf+0.5 );
58 // int roomcount=0;
59 // 使用数据纹理法,取这一层的区分度
60 // int int1=int(floor(mod(index_beta,4.0)+0.5)); // 使用哪个颜色分量
61 // float float1=(index_beta/4.0); // 在纹理采样器中的顺序索引
62 float floatu=(mod(index_beta,wid_utexturepalpha))/(wid_utexturepalpha)+(0.5 /wid_utexturepalpha);// 猜测u是x轴
63 float floatv=(((index_beta)/(wid_utexturepalpha)))/(hei_utexturepalpha)+(0.5 /(wid_utexturepalpha*hei_utexturepalpha));
64 vec2 UVpalpha=vec2(floatu,floatv);
65 vec4 vec4palphas=texture2D(utexturepalpha, UVpalpha);
66 float palpha=(vec4palphas[0 ]*255.0 *100.0 +vec4palphas[1 ]*255.0 )/pow(10.0 ,vec4palphas[2 ]*255.0 );
67 // float palpha=getData500(uarrpalpha,int(floor(index_beta+0.5))); // 改为尝试数组法传递数据
68 // 取这一层的转角
69 float alpha=atan(oPosition.z,oPosition.x);// 标准反正切函数有两个参数!!
70
71 if (getOdevity(index_beta)==1.0 )// 为了体现交错效果,如果是奇数层alpha要减去palpha
72 {
73 alpha-=palpha;
74 }
75 if (alpha<0.0 )
76 {
77 alpha+=(MathPI*2.0 );
78 }
79 // 取地区块数据纹理的索引
80 float floatu2=(alpha/(palpha*2.0 ))/wid_utexturedqk;
81 float floatv2=index_beta/hei_utexturedqk+0.5 /hei_utexturedqk;
82 vec2 UVdqk=vec2(floatu2,floatv2);
83 gl_FragColor=texture2D(utexturedqk, UVdqk);
84 // gl_FragColor=vec4palphas;
85 // gl_FragColor=texelFetch(utexturedqk,ivec2(int(floor(alpha/(palpha*2.0)+0.5)),int(floor(index_beta+0.5))),0); // 这个整数像素的方法是WebGL2开始加入的!!!!
86 // gl_FragColor=vec4(1.0*floatu,1.0*floatv,1.0*floatv2,1.0); // 红,绿,蓝结果不是0就是1??!!
87
88 // int index_dqk=roomcount-1+int(floor((alpha/palpha)+0.5));
89 // vec4 tempColor=vec4(uarrdqk[index_dqk],1.0);
90
91 // float float_3=index_beta/(max_floorf*2.0);
92 // float float_4=oPosition.y/5.0;
93 // canvas的imagedata用255,255,255,1定义颜色通道,而glsl用1.0,1.0,1.0,1.0定义!!!!
94
95
96 }
View Code
片元着色器和前面的区别是加了一个判断奇偶层数的方法,另外,在WebGL2.0中加入的texelFetch方法可以直接根据像素的位置对纹理图进行采样,比使用纹理坐标进行采样方便许多。
执行程序效果如下:
拉近相机:
其中生成地形耗时1分30秒,平滑地形并入库耗时3分10秒,从数据库查询需要约1分钟
五、总结
这个方法耗时比较长,无法实时应用,但可以用来一次性构建地形多次使用,也许可以通过优化代码来提高运行速度。生成的海洋和陆地混杂度比较高,也许可以考虑从种子位置随机生长地形的算法,这样可以使得大陆和海洋区分的更加分明。着色器代码中没有考虑周期性光照效果,也没有考虑极点处的地区块如何处理。
下一步准备给地区块添加鼠标交互,和更细节的地貌块显示。
你可能感兴趣的:(使用着色器在WebGL3D场景中呈现行星表面地形)
python 读excel每行替换_Python脚本操作Excel实现批量替换功能
weixin_39646695
python 读excel每行替换
Python脚本操作Excel实现批量替换功能大家好,给大家分享下如何使用Python脚本操作Excel实现批量替换。使用的工具Openpyxl,一个处理excel的python库,处理excel,其实针对的就是WorkBook,Sheet,Cell这三个最根本的元素~明确需求原始excel如下我们的目标是把下面excel工作表的sheet1表页A列的内容“替换我吧”批量替换为B列的“我用来替换的
男士护肤品哪个牌子好?十大男士护肤品排行榜
高省APP珊珊
很多男生意识到护肤的必要性,开始着手护肤,但不知道该选哪个男士护肤品品牌使用好。目前市面上很多男士护肤品品牌,可谓琳琅满目,让人眼花缭乱。男士挑选护肤品时,根据自己皮肤需求去正规渠道挑选合适的知名护肤品比较放心靠谱。高省APP,是2021年推出的平台,0投资,0风险、高省APP佣金更高,模式更好,终端用户不流失。【高省】是一个自用省钱佣金高,分享推广赚钱多的平台,百度有几百万篇报道,也期待你的加入
三菱PLC全套学习资料及应用手册
good2know
本文还有配套的精品资源,点击获取简介:三菱PLC作为工业自动化领域的核心设备,其系列产品的学习和应用需要全面深入的知识。本次资料包为学习者提供从基础到进阶的全方位学习资源,包括各种型号PLC的操作手册、编程指南、软件操作教程以及实际案例分析,旨在帮助用户系统掌握PLC的编程语言、指令系统及在各类工业应用中的实施。1.三菱PLC基础知识入门1.1PLC的基本概念可编程逻辑控制器(PLC)是工业自动化
2022-10-20
体力劳动者
不因感觉稍纵即逝就不加记录。在女儿睡觉后我记下今天的小故事。接手新班级后,今天是第二次收到家长的感谢信(微信)。是我表扬次数最多的两位学生家长致来的感谢,他们明显感受到孩子自信、阳光了不少,写作业由被动变为了主动,家庭氛围也由鸡飞狗跳变成了其乐融融。在被顽皮的学生气得头晕之后,我感到了久违的价值感,责任感甚至使命感,我回复家长这样一句话:我们也需要家长的反馈好让我们的教育工作更有劲头。我也认识到,
《玉骨遥》:大司命为什么不杀朱颜?原因没那么简单
windy天意晚晴
《玉骨遥》里,朱颜就是时影的命劫之人。重明与时影早就知道,他们一直瞒着大司命,如今大司命也知道了真相。可是大司命却没有杀朱颜,而是给朱颜下了诛心咒,还说时影的命劫已经破了,真的如此吗?1、计划总是赶不上变化的大司命从目前剧情来说,大司命还不如时影,他信心十足的事情总会有纰漏。他不让时影见命劫之女,结果时影还是遇上了。他想让时影走火入魔,一心复仇,结果时影在朱颜的劝说下放下了仇恨。大司命让时影开山收
移动端城市区县二级联动选择功能实现包
good2know
本文还有配套的精品资源,点击获取简介:本项目是一套为移动端设计的jQuery实现方案,用于简化用户在选择城市和区县时的流程。它包括所有必需文件:HTML、JavaScript、CSS及图片资源。通过动态更新下拉菜单选项,实现城市到区县的联动效果,支持数据异步加载。开发者可以轻松集成此功能到移动网站或应用,并可基于需求进行扩展和优化。1.jQuery移动端解决方案概述jQuery技术简介jQuery
9、汇编语言编程入门:从环境搭建到简单程序实现
神经网络酱
汇编语言 MEPIS GNU工具链
汇编语言编程入门:从环境搭建到简单程序实现1.数据存储介质问题解决在处理数据存储时,若要使用MEPIS系统,需确保有其可访问的存储介质。目前,MEPIS无法向采用NTFS格式(常用于Windows2000和XP工作站)的硬盘写入数据。不过,若硬盘采用FAT32格式,MEPIS就能进行写入操作。此外,MEPIS还能将文件写入软盘和大多数USB闪存驱动器。若工作站连接到局域网,还可通过FTP协议或挂载
day15|前端框架学习和算法
universe_01
前端 算法 笔记
T22括号生成先把所有情况都画出来,然后(在满足什么情况下)把不符合条件的删除。T78子集要画树状图,把思路清晰。可以用暴力法、回溯法和DFS做这个题DFS深度搜索:每个边都走完,再回溯应用:二叉树搜索,图搜索回溯算法=DFS+剪枝T200岛屿数量(非常经典BFS宽度把树状转化成队列形式,lambda匿名函数“一次性的小函数,没有名字”setup语法糖:让代码更简洁好写的语法ref创建:基本类型的
《极简思维》第三部分
小洋苏兮
整理你的人际关系如何改善人际关系?摘录:因为人际关系问题是人们生活中不快乐的主要原因。感想:感觉这个说的挺对,之前我总是埋头学习,不管舍友不管自己的合作伙伴的一些事情,但实际上,这学期关注了之后好多了摘录:“亲密关系与社交会让你健康而快乐。这是基础。太过于关注成就或不太关心人际关系的人都不怎么快乐。基本上来说,人类就是建立在人脉关系上的。”感想:但是如果有时想的太多就不太好,要以一个开放的心态跟别
我不懂什么是爱,但我给你全部我拥有的
香尧
因为怕黑,所以愿意陪伴在夜中行走的人,给他一点点的安全感。因为渴望温柔与爱,所以愿意为别的孩子付出爱与温柔。因为曾遭受侮辱和伤害,所以不以同样的方式施于其他人。如果你向别人出之以利刃,对方还了你爱与包容,真的不要感激他,真的不要赞美他。每一个被人伤害过的人心里都留下了一颗仇恨的种子,他也会想要有一天以眼还眼,以牙还牙。但他未让那颗种子生根发芽,他用一把心剑又一次刺向他自己,用他血荐仇恨,开出一朵温
C++ 计数排序、归并排序、快速排序
每天搬一点点砖
c++ 数据结构 算法
计数排序:是一种基于哈希的排序算法。他的基本思想是通过统计每个元素的出现次数,然后根据统计结果将元素依次放入排序后的序列中。这种排序算法适用于范围较小的情况,例如整数范围在0到k之间计数排序步骤:1初始化一个长度为最大元素值加1的计数数组,所有元素初始化为02遍历原始数组,将每个元素值作为索引,在计数数组中对应位置加13将数组清空4遍历计数器数组,按照数组中的元素个数放回到元数组中计数排序的优点和
2023-11-02
一帆f
发现浸润心田的感觉:今天一个机缘之下突然想分享我的婆媳关系,我一边分享一边回忆我之前和儿媳妇关系的微妙变化,特别是分享到我能感受到儿媳妇的各种美好,现在也能心平气和的和老公平等对话,看到自己看到老公,以己推人以人推己自然而然的换位思考,心中有一种美好的能量在涌动,一种浸润心田的感觉从心胸向全身扩散,美好极了……我很想记住这种感觉,赶紧把它写下来以留纪念,也就是当我看见他人的美好,美好的美妙的浸润心
贫穷家庭的孩子考上985以后会怎样?
Mellisa蜜思言
我出生在一个贫穷的农村家庭,据我妈说,我出生的时候才4斤多,而她生完我以后月子里就瘦到70斤。家里一直很穷,父母都是在菜市场卖菜的,家里还有几亩地种庄稼的。我很小开始就要去帮忙,暑假的生活就是帮忙去卖菜和割稻谷,那时候自己对于割稻谷这种事情有着莫名的恐惧,生怕自己长大以后还是每年都要过着割稻谷这种日子。父母因为忙于生计无暇顾及我的学习,幸好我因为看到他们这样子的生活,内心里有深深的恐惧感,驱使着我
实时数据流计算引擎Flink和Spark剖析
程小舰
flink spark 数据库 kafka hadoop
在过去几年,业界的主流流计算引擎大多采用SparkStreaming,随着近两年Flink的快速发展,Flink的使用也越来越广泛。与此同时,Spark针对SparkStreaming的不足,也继而推出了新的流计算组件。本文旨在深入分析不同的流计算引擎的内在机制和功能特点,为流处理场景的选型提供参考。(DLab数据实验室w.x.公众号出品)一.SparkStreamingSparkStreamin
48. 旋转图像 - 力扣(LeetCode)
Fiee-77
# 数组 leetcode 算法 python 数据结构 数组
题目:给定一个n×n的二维矩阵matrix表示一个图像。请你将图像顺时针旋转90度。你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。示例1:输入:matrix=[[1,2,3],[4,5,6],[7,8,9]]输出:[[7,4,1],[8,5,2],[9,6,3]]示例2:输入:matrix=[[5,1,9,11],[2,4,8,10],[13,3,6,
日更50天有什么收益?
星湾二宝
坚持在平台上日更50天了,平台也为我生成了日更50天徽章,小开心一下这份坚持。日更50天徽章那坚持50天都有哪些收益呢?收益一,就是最直观的那些钻和贝,我这边确实不太高,但是这些贝足够支撑我保持会员的资格,能够在发文的时候帮助友友们去除广告,方便阅读。钻和贝收益二,文章的收获,日更50天,坚持写作3.7万文字,书写的文字也从开始的流水账/碎碎念逐渐加入自己的思考和观点。以前,一个念头会一晃而过,如
Git 与 GitHub 的对比与使用指南
一念&
其它 git github
Git与GitHub的对比与使用指南在软件开发中,Git和GitHub是两个密切相关但本质不同的工具。下面我将逐步解释它们的定义、区别、核心概念以及如何协同使用,确保内容真实可靠,基于广泛的技术实践。1.什么是Git?Git是一个分布式版本控制系统,由LinusTorvalds于2005年创建。它的核心功能是跟踪代码文件的变化,帮助开发者管理项目历史记录、协作和回滚错误。Git是开源的,可以在本地
英伟达靠什么支撑起了4万亿?AI泡沫还能撑多久?
英伟达市值突破4万亿美元,既是AI算力需求爆发的直接体现,也暗含市场对未来的狂热预期。其支撑逻辑与潜在风险并存,而AI泡沫的可持续性则取决于技术、商业与地缘政治的复杂博弈。⚙️一、英伟达4万亿市值的核心支撑因素技术垄断与生态壁垒硬件优势:英伟达GPU在AI训练市场占有率超87%,H100芯片的FP16算力达1979TFLOPS,领先竞品3-5倍。CUDA生态:400万开发者构建的软件护城河,成为A
读书能沁润心灵
平等乡马回营小学方燕姣
书,是一泓清澈的溪水,是一片充满生机的芳草地。读书能让孩子的心变得宁静、诗意、豁达。在美好年纪,美好的时光里,我们要创造一切可以创造的机会,让孩子去遨游浩瀚的书海,浸润美好的人生。每个早晨,一股花草的清香扑了个满怀,清脆的读书声响彻了整个校园,回荡在空中久久不能停息。自然界的清韵声音有:鸟鸣声、溪流声、松风声、雨打芭蕉声,而惟读书声最为动听。孩子们的读书声,混和着树上的鸟鸣声,还有微风吹动竹叶的声
Linux系统配置(应用程序)
1风天云月
Linux linux 应用程序 编译安装 rpm http
目录前言一、应用程序概述1、命令与程序的关系2、程序的组成3、软件包封装类型二、RPM1、RPM概述2、RPM用法三、编译安装1、解包2、配置3、编译4、安装5、启用httpd服务结语前言在Linux中的应用程序被视为将软件包安装到系统中后产生的各种文档,其中包括可执行文件、配置文件、用户手册等内容,这些文档被组织为一个有机的整体,为用户提供特定的功能,因此对于“安装软件包”与“安装应用程序”这两
第28章 汇编语言--- 异常处理
hummhumm
汇编 算法 开发语言 程序设计 高级语言 异常处理 汇编语言
在汇编语言中,异常处理是一个重要的概念,它涉及到处理器如何响应和处理程序运行时发生的非正常情况。异常可以是硬件错误(例如除零错误、非法指令)或者软件触发的中断(例如系统调用)。当发生异常时,处理器会暂停当前正在执行的程序,并转移到一个预先定义好的位置来处理这个异常。为了详细阐述第28章关于汇编语言中的异常处理,我们可以考虑一个简化的例子,展示异常处理的基本结构。请注意,实际的代码将取决于具体的处理
JVM 内存模型深度解析:原子性、可见性与有序性的实现
练习时长两年半的程序员小胡
JVM 深度剖析:从面试考点到生产实践 jvm java 内存模型
在了解了JVM的基础架构和类加载机制后,我们需要进一步探索Java程序在多线程环境下的内存交互规则。JVM内存模型(JavaMemoryModel,JMM)定义了线程和主内存之间的抽象关系,它通过规范共享变量的访问方式,解决了多线程并发时的数据一致性问题。本文将从内存模型的核心目标出发,详解原子性、可见性、有序性的实现机制,以及volatile、synchronized等关键字在其中的作用。一、J
Flowable 实战落地核心:选型决策与坑点破解
练习时长两年半的程序员小胡
Flowable 流程引擎实战指南 低代码 BPMN 流程引擎 flowable 后端 java
在企业级流程引擎的落地过程中,选型的准确性和坑点的预见性直接决定项目成败。本文聚焦Flowable实战中最关键的“选型决策”与“常见坑点”,结合真实项目经验,提供可落地的解决方案。一、流程引擎选型:从业务本质出发1.1选型的三大核心维度企业在选择流程引擎时,需避免陷入“技术崇拜”,应回归业务本质。评估Flowable是否适用,可从三个维度判断:业务复杂度若流程涉及动态审批链(如按金额自动升级审批)
Flowable 高级扩展:自定义元素与性能优化实战
练习时长两年半的程序员小胡
Flowable 流程引擎实战指南 流程图 flowable BPMN 流程引擎 java
在前五篇文章中,我们从基础概念、流程设计、API实战、SpringBoot集成,到外部系统协同,逐步构建了Flowable的应用体系。但企业级复杂场景中,原生功能往往难以满足定制化需求——比如需要特殊的审批规则网关、与决策引擎联动实现动态路由,或是在高并发场景下优化流程引擎性能。本文将聚焦Flowable的高级扩展能力,详解如何自定义流程元素、集成规则引擎,并掌握大型系统中的性能调优策略。一、自定
互信息:理论框架、跨学科应用与前沿进展
大千AI助手
人工智能 Python # OTHER 人工智能 深度学习 算法 互信息 香农 通信 随机变量
1.起源与核心定义互信息(MutualInformation,MI)由克劳德·香农(ClaudeShannon)在1948年开创性论文《AMathematicalTheoryofCommunication》中首次提出,该论文奠定了现代信息论的基础。互信息用于量化两个随机变量之间的统计依赖关系,定义为:若已知一个随机变量的取值,能为另一个随机变量提供的信息量。数学上,对于离散随机变量XXX和YYY,
《实际生活是我们的指南针》——教育中寻找曙光
托克托126何芳
陶行知先生的文章相对《致青年教师》比较难理解,但是他热爱学生,在书中处处能感受到。在《实际生活是我们的指南针》文中他说道:“我虽觉得我有好多地方可以帮助诸位,但指志针确是有些不敢当。我和诸位同是在乡村里摸路的人。我们的真正指南针只是实际生活。”这些话不仅使人感到他非常谦虛,既不夸大自己的作用也不轻视自己的作用。图片发自App我们的真正指南针只是实际生活。实际生活向我们供给无穷的问题,要求不断的解决
什么是缓存雪崩?缓存击穿?缓存穿透?分别如何解决?什么是缓存预热?
daixin8848
缓存 redis java 开发语言
缓存雪崩:在一个时间段内,有大量的key过期,或者Redis服务宕机,导致大量的请求到达数据库,带来巨大压力-给key设置不同的TTL、利用Redis集群提高服务的高可用性、添加多级缓存、添加降级流策略缓存击穿:给某一个key设置了过期时间,当key过期的时间,恰好这个时间点有大量的并发请求访问这个key,可能会瞬间把数据库压垮-互斥锁:缓存失败时,只允许一个请求去加载数据并更新缓存,其他请求阻塞
高省邀请码哪个级别最高?高省原始高级邀请码500888
凌风导师
高省是杭州长孚科技有限公司开辟的一个项目(高省APP),已获数千万投资,主打外交电商+新零售,提供淘宝好省京东等主流电商途径的大额优惠券(直接在淘宝等途径购买是没有该优惠券的)。用户们可以利用这些软件享受折扣买东西优惠,一起来看看购物省钱app网上买东西省钱的软件有哪些吧!网购省钱软件靠谱吗包围淘宝等途径产品的左右,也便是你可以大概在高省买你的确想买的任何产品,并且享受额定优惠,优惠力度为-(大部
2021-会说话的人运气都不会太差-会说话的人更善于倾听(5)沉默、留白
12_德德
21、说话时,如想强调某一部分,一个有效方法是,以沉默留出空白。留出多大空白才好呢?7秒。22、沉默所营造的“空白”长度,说的人感觉到的,是实际长度的3倍,而听的人感觉到的,则只有实际长度的1/3。23、只要善于用“一直”来表达,就不会给人以不过是一时任性之感。能说“一直”的人,会得到周围的支持,在合适的时候想到你。24、要得到“是把好手”的高度评价,就要展示你对公司的热爱。特别是,如能对上司或公
企业级区块链平台Hyperchain核心原理剖析
boyedu
区块链 区块链 企业级区块链平台 Hyperchain
Hyperchain作为国产自主可控的企业级联盟区块链平台,其核心原理围绕高性能共识、隐私保护、智能合约引擎及可扩展架构展开,通过多模块协同实现企业级区块链网络的高效部署与安全运行。以下从核心架构、关键技术、性能优化、安全机制、应用场景五个维度展开剖析:一、核心架构:分层解耦与模块化设计Hyperchain采用分层架构,将区块链功能解耦为独立模块,支持灵活组合与扩展:P2P网络层由验证节点(VP)
java类加载顺序
3213213333332132
java
package com.demo;
/**
* @Description 类加载顺序
* @author FuJianyong
* 2015-2-6上午11:21:37
*/
public class ClassLoaderSequence {
String s1 = "成员属性";
static String s2 = "
Hibernate与mybitas的比较
BlueSkator
sql Hibernate 框架 ibatis orm
第一章 Hibernate与MyBatis
Hibernate 是当前最流行的O/R mapping框架,它出身于sf.net,现在已经成为Jboss的一部分。 Mybatis 是另外一种优秀的O/R mapping框架。目前属于apache的一个子项目。
MyBatis 参考资料官网:http:
php多维数组排序以及实际工作中的应用
dcj3sjt126com
PHP usort uasort
自定义排序函数返回false或负数意味着第一个参数应该排在第二个参数的前面, 正数或true反之, 0相等usort不保存键名uasort 键名会保存下来uksort 排序是对键名进行的
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8&q
DOM改变字体大小
周华华
前端
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml&q
c3p0的配置
g21121
c3p0
c3p0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。c3p0的下载地址是:http://sourceforge.net/projects/c3p0/这里可以下载到c3p0最新版本。
以在spring中配置dataSource为例:
<!-- spring加载资源文件 -->
<bean name="prope
Java获取工程路径的几种方法
510888780
java
第一种:
File f = new File(this.getClass().getResource("/").getPath());
System.out.println(f);
结果:
C:\Documents%20and%20Settings\Administrator\workspace\projectName\bin
获取当前类的所在工程路径;
如果不加“
在类Unix系统下实现SSH免密码登录服务器
Harry642
免密 ssh
1.客户机
(1)执行ssh-keygen -t rsa -C "
[email protected] "生成公钥,xxx为自定义大email地址
(2)执行scp ~/.ssh/id_rsa.pub root@xxxxxxxxx:/tmp将公钥拷贝到服务器上,xxx为服务器地址
(3)执行cat
Java新手入门的30个基本概念一
aijuans
java java 入门 新手
在我们学习Java的过程中,掌握其中的基本概念对我们的学习无论是J2SE,J2EE,J2ME都是很重要的,J2SE是Java的基础,所以有必要对其中的基本概念做以归纳,以便大家在以后的学习过程中更好的理解java的精髓,在此我总结了30条基本的概念。 Java概述: 目前Java主要应用于中间件的开发(middleware)---处理客户机于服务器之间的通信技术,早期的实践证明,Java不适合
Memcached for windows 简单介绍
antlove
java Web windows cache memcached
1. 安装memcached server
a. 下载memcached-1.2.6-win32-bin.zip
b. 解压缩,dos 窗口切换到 memcached.exe所在目录,运行memcached.exe -d install
c.启动memcached Server,直接在dos窗口键入 net start "memcached Server&quo
数据库对象的视图和索引
百合不是茶
索引 oeacle数据库 视图
视图
视图是从一个表或视图导出的表,也可以是从多个表或视图导出的表。视图是一个虚表,数据库不对视图所对应的数据进行实际存储,只存储视图的定义,对视图的数据进行操作时,只能将字段定义为视图,不能将具体的数据定义为视图
为什么oracle需要视图;
&
Mockito(一) --入门篇
bijian1013
持续集成 mockito 单元测试
Mockito是一个针对Java的mocking框架,它与EasyMock和jMock很相似,但是通过在执行后校验什么已经被调用,它消除了对期望 行为(expectations)的需要。其它的mocking库需要你在执行前记录期望行为(expectations),而这导致了丑陋的初始化代码。
&nb
精通Oracle10编程SQL(5)SQL函数
bijian1013
oracle 数据库 plsql
/*
* SQL函数
*/
--数字函数
--ABS(n):返回数字n的绝对值
declare
v_abs number(6,2);
begin
v_abs:=abs(&no);
dbms_output.put_line('绝对值:'||v_abs);
end;
--ACOS(n):返回数字n的反余弦值,输入值的范围是-1~1,输出值的单位为弧度
【Log4j一】Log4j总体介绍
bit1129
log4j
Log4j组件:Logger、Appender、Layout
Log4j核心包含三个组件:logger、appender和layout。这三个组件协作提供日志功能:
日志的输出目标
日志的输出格式
日志的输出级别(是否抑制日志的输出)
logger继承特性
A logger is said to be an ancestor of anothe
Java IO笔记
白糖_
java
public static void main(String[] args) throws IOException {
//输入流
InputStream in = Test.class.getResourceAsStream("/test");
InputStreamReader isr = new InputStreamReader(in);
Bu
Docker 监控
ronin47
docker监控
目前项目内部署了docker,于是涉及到关于监控的事情,参考一些经典实例以及一些自己的想法,总结一下思路。 1、关于监控的内容 监控宿主机本身
监控宿主机本身还是比较简单的,同其他服务器监控类似,对cpu、network、io、disk等做通用的检查,这里不再细说。
额外的,因为是docker的
java-顺时针打印图形
bylijinnan
java
一个画图程序 要求打印出:
1.int i=5;
2.1 2 3 4 5
3.16 17 18 19 6
4.15 24 25 20 7
5.14 23 22 21 8
6.13 12 11 10 9
7.
8.int i=6
9.1 2 3 4 5 6
10.20 21 22 23 24 7
11.19
关于iReport汉化版强制使用英文的配置方法
Kai_Ge
iReport汉化 英文版
对于那些具有强迫症的工程师来说,软件汉化固然好用,但是汉化不完整却极为头疼,本方法针对iReport汉化不完整的情况,强制使用英文版,方法如下:
在 iReport 安装路径下的 etc/ireport.conf 里增加红色部分启动参数,即可变为英文版。
# ${HOME} will be replaced by user home directory accordin
[并行计算]论宇宙的可计算性
comsci
并行计算
现在我们知道,一个涡旋系统具有并行计算能力.按照自然运动理论,这个系统也同时具有存储能力,同时具备计算和存储能力的系统,在某种条件下一般都会产生意识......
那么,这种概念让我们推论出一个结论
&nb
用OpenGL实现无限循环的coverflow
dai_lm
android coverflow
网上找了很久,都是用Gallery实现的,效果不是很满意,结果发现这个用OpenGL实现的,稍微修改了一下源码,实现了无限循环功能
源码地址:
https://github.com/jackfengji/glcoverflow
public class CoverFlowOpenGL extends GLSurfaceView implements
GLSurfaceV
JAVA数据计算的几个解决方案1
datamachine
java Hibernate 计算
老大丢过来的软件跑了10天,摸到点门道,正好跟以前攒的私房有关联,整理存档。
-----------------------------华丽的分割线-------------------------------------
数据计算层是指介于数据存储和应用程序之间,负责计算数据存储层的数据,并将计算结果返回应用程序的层次。J
&nbs
简单的用户授权系统,利用给user表添加一个字段标识管理员的方式
dcj3sjt126com
yii
怎么创建一个简单的(非 RBAC)用户授权系统
通过查看论坛,我发现这是一个常见的问题,所以我决定写这篇文章。
本文只包括授权系统.假设你已经知道怎么创建身份验证系统(登录)。 数据库
首先在 user 表创建一个新的字段(integer 类型),字段名 'accessLevel',它定义了用户的访问权限 扩展 CWebUser 类
在配置文件(一般为 protecte
未选之路
dcj3sjt126com
诗
作者:罗伯特*费罗斯特
黄色的树林里分出两条路,
可惜我不能同时去涉足,
我在那路口久久伫立,
我向着一条路极目望去,
直到它消失在丛林深处.
但我却选了另外一条路,
它荒草萋萋,十分幽寂;
显得更诱人,更美丽,
虽然在这两条小路上,
都很少留下旅人的足迹.
那天清晨落叶满地,
两条路都未见脚印痕迹.
呵,留下一条路等改日再
Java处理15位身份证变18位
蕃薯耀
18位身份证变15位 15位身份证变18位 身份证转换
15位身份证变18位,18位身份证变15位
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
蕃薯耀 201
SpringMVC4零配置--应用上下文配置【AppConfig】
hanqunfeng
springmvc4
从spring3.0开始,Spring将JavaConfig整合到核心模块,普通的POJO只需要标注@Configuration注解,就可以成为spring配置类,并通过在方法上标注@Bean注解的方式注入bean。
Xml配置和Java类配置对比如下:
applicationContext-AppConfig.xml
<!-- 激活自动代理功能 参看:
Android中webview跟JAVASCRIPT中的交互
jackyrong
JavaScript html android 脚本
在android的应用程序中,可以直接调用webview中的javascript代码,而webview中的javascript代码,也可以去调用ANDROID应用程序(也就是JAVA部分的代码).下面举例说明之:
1 JAVASCRIPT脚本调用android程序
要在webview中,调用addJavascriptInterface(OBJ,int
8个最佳Web开发资源推荐
lampcy
编程 Web 程序员
Web开发对程序员来说是一项较为复杂的工作,程序员需要快速地满足用户需求。如今很多的在线资源可以给程序员提供帮助,比如指导手册、在线课程和一些参考资料,而且这些资源基本都是免费和适合初学者的。无论你是需要选择一门新的编程语言,或是了解最新的标准,还是需要从其他地方找到一些灵感,我们这里为你整理了一些很好的Web开发资源,帮助你更成功地进行Web开发。
这里列出10个最佳Web开发资源,它们都是受
架构师之面试------jdk的hashMap实现
nannan408
HashMap
1.前言。
如题。
2.详述。
(1)hashMap算法就是数组链表。数组存放的元素是键值对。jdk通过移位算法(其实也就是简单的加乘算法),如下代码来生成数组下标(生成后indexFor一下就成下标了)。
static int hash(int h)
{
h ^= (h >>> 20) ^ (h >>>
html禁止清除input文本输入缓存
Rainbow702
html 缓存 input 输入框 change
多数浏览器默认会缓存input的值,只有使用ctl+F5强制刷新的才可以清除缓存记录。
如果不想让浏览器缓存input的值,有2种方法:
方法一: 在不想使用缓存的input中添加 autocomplete="off";
<input type="text" autocomplete="off" n
POJO和JavaBean的区别和联系
tjmljw
POJO java beans
POJO 和JavaBean是我们常见的两个关键字,一般容易混淆,POJO全称是Plain Ordinary Java Object / Pure Old Java Object,中文可以翻译成:普通Java类,具有一部分getter/setter方法的那种类就可以称作POJO,但是JavaBean则比 POJO复杂很多, Java Bean 是可复用的组件,对 Java Bean 并没有严格的规
java中单例的五种写法
liuxiaoling
java 单例
/**
* 单例模式的五种写法:
* 1、懒汉
* 2、恶汉
* 3、静态内部类
* 4、枚举
* 5、双重校验锁
*/
/**
* 五、 双重校验锁,在当前的内存模型中无效
*/
class LockSingleton
{
private volatile static LockSingleton singleton;
pri