GPS实时跟踪程序模拟(2)动画回放

上一篇文章介绍了实时跟踪程序中画点的操作,在这里介绍如果实现程序跟踪的动画回放。实现动画回放的基本原理是不停的刷新 JPanel ,在每次刷新的过程中,把图片画在相邻的位置便可以实现动画的效果。
       为了实现动画的回放,需要使用 Thread 进行不停的刷新。回顾一下线路数据结构:线路的 ID ,线路的名称,线路的所有点的集合,线路的图片名称,线路的交通工具,为了实现动画,还需要为线路添加一个记录动画位置的类,命名为 Cartoon,Cartoon 类包含了当前动画位置的 curX,curY 坐标,当前倾斜的角度 angle, 在画 JPanel painComponent 方法中调用路线的画图方法,便可以画出线路, Route 类需要遍历每个 Stone 点,对于每个点调用点的画图方法,之后再根据点的先后画出两个点之间的连线,在连线也画好的情况下再根据 Cartoon 的坐标和旋转角度画出相应的交通工具,这就是线路画图的所有步骤。另外在必要的情况下开启一个线程,线程拥有指向 JPanel 的句柄,从 JPanel 中获取线路的句柄,再从线路的句柄中获取 Cartoon 的句柄,线程便可以根据线路中的两个点计算刷新时图片的位置,线程休眠一段时间,再次计算图片的位置,调用 JPanel 进行刷新,反复执行,便可以得到动画。在这个过程中,线程的开始可以由事件触发,线程的结束可以根据当前线路是否已经到达最后来作为退出条件,或者被中断。
       假设目前动画需要走的线段由两个点决定,比如 preStone, 前一个点, curStone 当前点。图标需要从 preStone 走到 curStone, 首先需要计算出目前行进的角度,确定角度的目的是使得图标做出相应的旋转,更逼真的演示现实的状况。计算角度需要知道坐标的具体值,命名变量 x1,y1 preStone 的坐标, x2,y2 curStone 的坐标, dx dy 分别为 x2-x1,y2-y1 ,则 dy/dx 即为当前角度的 tan(angle) 的值,使用反正且函数便可以得出当前的角度, dx 需要分为三种情况讨论, 1 dx>0 ,则其角度应该在第一和第四象限,象限的概念是初中的知识,如果不明白的请再温习一下初中的教科书,反正切的值在 -PI/2 PI/2 之间,直接旋转既为正确答案, 2.dx<0 则其角度在第二和第三象限,需要在得到反正切之后再旋转 180 度得到,因此其值为 atan(dy/dx)+PI, 这样经过旋转之后便为正确答案, 3 ,如果 dx 为零,则需要判断 dy 与零的关系,如果 dy 大于 0 ,则需要旋转 PI/2, 如果 dy 小于零,则需要旋转 -PI/2, 如果为 0 ,则旋转角度可以为 0 ;以上的分析逻辑可以得到如下的程序:
int x1, y1, x2, y2, dx, dy, steps;
                            x1 = preStone.getX();
                            y1 = preStone.getY();
                            x2 = curStone.getX();
                            y2 = curStone.getY();
                            dx = x2 - x1;
                            dy = y2 - y1;
 
                            double angle = 0;
                            if (dx > 0) {
                                   angle = Math.atan(dy * 1.0 / dx * 1.0);
                            } else if (dx < 0) {
                                   angle = Math.PI + Math.atan(dy * 1.0 / dx);
                            } else if (dx == 0) {
                                   if (dy >= 0) {
                                          angle = Math.PI / 2;
                                   } else {
                                          angle = Math.PI * 3 / 2;
                                   }
                            }
 
                            cartoon.setAngle(angle);
注意:在进行反正切的过程中整数相除必须转换为双精度相除,否则类似于 30/33 其结果为 0 ,这就会使得精度大打折扣。
       得到了旋转的角度后,便需要在两点之间找出每次画图标所处的坐标。作者的思想是首先算出当前两点之间的距离 L ,循环由 0 L 根据步长遍历,利用相似三角形的原理和坐标平移的原理得到目前遍历的点的坐标,程序如下 :
steps = (int) Math.round(Math.sqrt(dx * dx + dy * dy));
得到两点之间的总长度,即步长,
for (int i = 0; i <= steps; i += 3) {
// 循环从 0 到总步长,每次增加三个步长。
                                   curX = (int) Math.round(x1 + 1.0 * dx * i / steps);
根据相似三角形的原理得到当前的 x 轴坐标
                                   curY = (int) Math.round(y1 + 1.0 * dy * i / steps);
根据相似三角形的原理得到当前的 Y 轴坐标
当所有的点已经准备好了,便可以刷新 Jpanel 了, JPanel 的刷新会调用调用 PaintComponent 方法, paintComponent 又会调用 Route 的画图方法,在 route 的画图方法中使用当前的设置画出图标,画图标的过程如下:得到图标的 URL ,根据 URL 得到 ImageICon 的图标,取出图标的高和宽度,克隆一个坐标系,对坐标系进行旋转,并把坐标系设置到 Graphic ,在相应位置的画出图标,使得图标的中心点在给定的 x,y 上,还原原来的 graphic 的坐标系。这样整个图标便画完了。实现代码如下:
URL url = getClass().getResource("/icon/" + getVehicle() + ".gif");
                     ImageIcon vIcon = new ImageIcon(url);
                     int height = vIcon.getIconHeight();
                     int width = vIcon.getIconWidth();
                     AffineTransform origXform = g.getTransform();
                     AffineTransform newXform = (AffineTransform) (origXform.clone());
                     int xRot = cartoon.getCurX();
                     int yRot = cartoon.getCurY();
 
                     newXform.rotate(cartoon.getAngle(), xRot, yRot);
                     g.setTransform(newXform);
                     g.drawImage(vIcon.getImage(), xRot - width / 2, yRot - height / 2,
                                   null);
                     g.setTransform(origXform);
以上为个人的实现方法,欢迎大家指正交流。
作者简介:凌辉 北京*******科技发展有限公司   软件开发部 项目经理,数据库方向研究生学历,设计开发过多个 J2EE 应用程序,有丰富的软件开发、管理、测试经验,擅长网站应用程序开发,在设计模式,软件重构,版本控制,软件保护,数据库设计与管理等方面都有独特的见解。
联系方式: QQ 21731278 msn [email protected]

你可能感兴趣的:(职场,gps,回放,休闲,跟踪)