上篇文章已经基本把「科二考试系统」的核心思路描述清楚了,接下来记录一下稍微具体的知识点。
建立世界坐标系
真实的经纬度点,通过高斯投影转化成平面坐标,需要经过一系列运算。
1 | public class ProjectConverter { |
需要一个测试方法,验证数据转换的准确性:
1 | /** |
设置一个经度子午线,后面计算出来的平面坐标误差会非常低,完全可以接受。结果乘以 100,将米转成厘米,同时转到左手坐标系。得到坐标之后,相对原点做一个偏移,就能得到这个「世界坐标系」中每个点的坐标了。
1 | public class DefaultConverter implements Converter { |
左右手坐标系
这个概念我琢磨了好久,到现在也还没有彻底搞清楚。参考左手坐标系 vs 右手坐标系,假设 Z 轴是屏幕往内,X 轴方向保持一致时,可以看到 Y 轴是相反的。所以左右手坐标系,在相对 2D 的 场景里,会影响 Y 轴的值,右手坐标系需要取反。在科二里,某些评判是需要方向的,比如直角转弯分左直角和右直角,我们通过「世界坐标系」中直角项目的的 3 个点(3 个点,指定一个原点,剩下 2 个点分别代表 X、Y 轴的方向)建立「我的坐标系」,就有可能是左手,也有可能是右手。所以在整个场景中,尽量以左手坐标系为默认坐标系,某些特殊情况需要右手坐标系时,需要将 y 值取反。「我的坐标系」建立之后,需要将「世界坐标系」中其他的点通过矩阵变换,也转换到这个坐标系内。
1 | /** |
渲染
「世界坐标系」的点要渲染到界面上,需要映射成屏幕坐标。以直角转弯为例:
1 | public class ZhiJiaoSrcData implements Serializable { |
这是直角转弯的 6 个点,必须严格按照示意图进行采集。
转成世界坐标系中的模型主要以线为单位:
1 | public class ZhiJiaoCollision { |
然后再将 Collision 转换成渲染到界面的 Model:
1 | public class ZhiJiaoRenderModel implements Serializable { |
因为绘制线是有宽度的,限定线宽为 15cm,采点全部采集的是内点,安卓绘制一条带宽度的线,大多都是使用 Paint 的 strokeWidth,而这个宽度,是向内外各辐射一半:
所以我们需要根据采的内点,计算我们真实划线的点。
1 | /** |
这样计算后,我们得到的 6 个点如图标记所示:
然后进行绘制:
1 | /** |
getLineAtRight 如下:
1 | /** |
直角转弯就是要画 2 条虚线,4 条实线,直接看看实线的绘制:
1 | public void draw(Canvas canvas, Matrix currentMatrix) { |
通过 canvas、paint 进行绘制,就是普通的安卓知识了。但是还剩下一个疑问:这个时候的线,传入的坐标都是世界坐标系里的坐标,假设 Pos(1000,1000) 这个点即是相对原点往北 10 米,往东 10 米的一个点,而安卓原点在左上角,如何映射的呢?
再听下回分解吧~