核心理念:递归
其实3D山脉基本思路可以认为是平面山脉和谢冰斯基三角形的结合体,具体实现之前请大家先了解一个取中点时第一个技巧,即取两个点中点时需要让中点的横坐标或纵坐标或同时减或加上一个极小的随机值,来产生山脉连绵起伏的效果,我通过查阅相关资料发现有些人将其称为中值震荡点,咱们就暂且这么称呼它吧
初步思路:
1.图中随机选取三个点
2.然后取中值震荡点
3.连接相应的顶点和中值震荡点
4.然后不断迭代,迭代到一定次数结束迭代
代码如下
public void recur3D(Graphics g, double x1, double y1,double x2, double y2,double x3,double y3, int range) {
if (range==0) {
int[] px = { (int)x1, (int)x2, (int)x3 };
int[] py = { (int)y1, (int)y2, (int)y3 };
g.drawPolygon(px, py, 3);
return;
}else {
Random rand=new Random();
int num=rand.nextInt(range*2)-range;
double ax,ay,bx,by,cx,cy;
ax = (x1 + x2) / 2 ;
ay = (y1 + y2) / 2 + num;
bx = (x1 + x3) / 2;
by = (y1 + y3) / 2 + num;
cx = (x2 + x3) / 2;
cy = (y2 + y3) / 2 + num;
//以上全部都是在y轴上取震荡点,造成起伏效果,其实也可以在x轴上震荡
range*=0.55;
recur3D(g, x1, y1, ax, ay, bx, by, range);
recur3D(g, x2, y2, ax, ay, cx, cy, range);
recur3D(g, x3, y3, cx, cy, bx, by, range);
recur3D(g, ax, ay, cx, cy, bx, by, range);
}
}
效果图
结果我发现山脉上出现了许多的裂缝,其实这不难理解在取中值震荡点时可能取到同一个点,从而造成割裂,解决方案的话就是使用一个数组储存中值震荡点,如果取到过就直接使用,如果未储存就求取中值震荡点
代码如下
public void recur3D(Graphics g, double x1, double y1,double x2, double y2,double x3,double y3, int range) {
//我用的range为100
if (range==0) {
int[] px = { (int)x1, (int)x2, (int)x3 };
int[] py = { (int)y1, (int)y2, (int)y3 };
g.drawPolygon(px, py, 3);
return;
}else {
Random rand=new Random();
int num=rand.nextInt(range*2)-range;
double ax,ay,bx,by,cx,cy;
int u=0,j=0,o=0;
boolean f1=true;
boolean f2=true;
boolean f3=true;
for(int i=0;i<counts;i++) {
if((x1 == po[i].x1&&x2==po[i].x2&&y1==po[i].y1&&y2==po[i].y2)
||(x1==po[i].x2&&x2==po[i].x1&&y1==po[i].y2&&y2==po[i].y1)){
f1=false;
u=i;
break;
}
}
for(int i=0;i<counts;i++) {
if((x2 == po[i].x1&&x3==po[i].x2&&y2==po[i].y1&&y3==po[i].y2)
||(x2==po[i].x2&&x3==po[i].x1&&y2==po[i].y2&&y3==po[i].y1)){
f2=false;
j=i;
break;
}
}
for(int i=0;i<counts;i++) {
if((x1 == po[i].x1&&x3==po[i].x2&&y1==po[i].y1&&y3==po[i].y2)
||(x1==po[i].x2&&x3==po[i].x1&&y1==po[i].y2&&y3==po[i].y1)){
f3=false;
o=i;
break;
}
}
if(!f1) {
ax=po[u].X;
ay=po[u].Y;
} else {
ax = (x1 + x2) / 2 ;
ay = (y1 + y2) / 2 + num;
Point p=new Point(x1,x2,y1,y2,ax,ay);
counts++;
po[counts-1]=p;
}
if(!f3) {
bx=po[o].X;
by=po[o].Y;
} else {
bx = (x1 + x3) / 2;
by = (y1 + y3) / 2 + num;
Point p=new Point(x1,x3,y1,y3,bx,by);
counts++;
po[counts-1]=p;
}
if(!f2) {
cx=po[j].X;
cy=po[j].Y;
} else {
cx = (x2 + x3) / 2;
cy = (y2 + y3) / 2 + num;
Point p=new Point(x2,x3,y2,y3,cx,cy);
counts++;
po[counts-1]=p;
}
range*=0.55;
recur3D(g, x1, y1, ax, ay, bx, by, range);
recur3D(g, x2, y2, ax, ay, cx, cy, range);
recur3D(g, x3, y3, cx, cy, bx, by, range);
recur3D(g, ax, ay, cx, cy, bx, by, range);
}
}
效果如下
其实还可以添加颜色来使其更美观,如
g.setColor(new Color(0,140,0,new Random().nextInt(40)));
大功告成,感谢观众老爷们阅读 ≧◇≦,如有错误,敬请指正