1.墨卡托投影正解公式
算法的第一步是求出图片中心坐标点(经度,纬度)到地图坐标原点(0,0)的距离,在实践过程中,如果采用标准的球面距离计算公式,会产生误差,特别是纬度绝对值大的区域。这是因为大部分WEBGIS采用墨卡托投影,纬度绝对值越大的球面区域拉伸越长,所以需要采用墨卡托投影正解公式来计算距离,消除误差。
公式中a为椭球长半轴,b为椭球短半轴,例如百度地图采用WSG84椭球体参数,故a等于6378137米,b等于6356752.3142米。L0,B0为标准原点经纬度(0,0),L,B为带入计算的中心点经纬度,e为偏心率。
墨卡托投影正解公式(1)(2),可以求出基于墨卡托投影下某一经纬度点对应坐标原点(0,0)的X轴方向和Y轴方向距离(单位米)。
2. 地图分辨率
将雷达卫星图像叠加到某一缩放等级的地图上,就需要确定地图当前的分辨率,再将要叠加的图片缩放到对应的分辨率。
地图分辨率就是屏幕上一个像素对应的地面尺寸(米)。以百度地图为例,其地图分辨率公式在Java程序中表示为:Math.pow(2,18-zoom),其中zoom表示当前地图缩放等级,百度地图缩放等级的范围是1到18。
3.百度地图图块编号规则
百度地图在每一个级别将整个地图划分成若干个图块,通过编号系统将整个图块整合在一起以便显示完整的地图。当地图被拖动或者级别发生变化时,地图API将会根据平面坐标计算出当前视野内所需显示的图块的编号。从平面坐标原点开始的右上方向的图块编号为(0,0),在地图缩放等级第一级时(zoom=1),整个世界地图分为4张256x256的图片,中国区域所在的图块编号为(0,0)。百度地图坐标系如图3-1所示:
图3-1 百度地图投影坐标系
在地图缩放等级第二级时,以地图右上区域为例,分为了两个图块。如图3-2所示:
图3-2 百度地图第二级时图块分布
当缩放等级是第二级时,根据上文公式求出地图分辨率为65536,根据WSG84球体周长的一半20037508.34米,可以求出地图右上区域的瓦片图块总个数,即20037508.34/(65536*256)=1.19,向上收整得到2。
同理,根据某一个点的经纬度,即可求出该点在某个缩放等级下所在的图块编号(x,y),计算公式如下,设某点经纬度为(lng,lat),其中X为lng在X轴方向的墨卡托投影正解值,Y为lat在Y轴方向的墨卡托投影正解值,F表示当前缩放等级下地图分辨率。则图块编号(x,y)为:
x = X / (F * 256) (3)
y = Y / (F * 256) (4)
这里x,y只保留整数部分。
4. 切图算法
这里以成都一小时降水雷达产品图为例,如图4-1所示:
图4-1 成都2012年7月30日15时30分基本反射率产品
具体算法分为6个步骤,流程图如图4-2所示:
图4-2 切图算法流程图
4.1 改变图片尺寸调整分辨率
叠加雷达图层首先要保证待切割图片的分辨率与地图分辨率一致,才能使雷达叠加层与地图底图以相同的比例尺完美融合。这里已知雷达图片的探测半径为150KM,假设当前地图等级为7,则地图分辨率为2048。雷达图片缩放后的宽(像素)为150000*2/2048。图片缩放后高度(像素)同理,结果只取整数部分。
设图片所表现的实际地理长宽为X,Y(米),要叠加的某缩放等级对应的地图分辨率为F,缩放后的图片宽为Width,高为Height,则缩放公式(像素)为:
Width = X / F (5)
Height = Y / F (6)
4.2计算图片中心点及左上角的墨卡托投影正解值(x2,y2)
图片以雷达站为中心,即已知这张图片的中心点经纬度为(104.024413,30.665995)。将该点坐标带入墨卡托投影正解公式(1)(2)得到x轴和y轴方向原点距离(x1,y1)。由于之前限定了地图分辨率F,这里的(x1,y1)也需要做同样的缩放运算。图片长宽像素已由公式(5)(6)计算出,则可求出图片左上角顶点对应的x轴和y轴方向原点距离(x2,y2)。其中
x2 = x1/F - Width/2 (7)
y2 = y1/F - Height/2 (8)
如图4-3所示:
4.3计算左上角点所在百度地图的瓦片编号(t1,t2)
根据上面计算出的图片左上角顶点对应的x轴和y轴方向原点距离(x2,y2)和百度地图图块大小固定为256*256,算出图片左上角顶点所在的地图瓦片图块编号(t1,t2),计算结果只保留整数部分。
t1 = x2 / 256 (9)
t2 = y2 / 256 (10)
4.4计算左上角点在图块(t1,t2)里的坐标(x3,y3)
用左上角顶点的墨卡托投影正解值(x2,y2)减去所在图块(t1,t2)的起始坐标,即得到左上角点再该图块中的坐标,这里的坐标系是相对于(t1,t2)图块。设x3为左上角顶点在(t1,t2)图块中的x轴坐标,y3为左上角顶点在(t1,t2)图块中的y轴坐标。t1*256是图块编号t1的x轴起始坐标,t2*256同理。需要注意的是,这一步骤计算出的x3,y3是相对于点(t1*256,t2*256)的坐标,即(t1,t2)图块内坐标。
x3 = x2 - t1*256 (11)
y3 = y2 - t2*256 (12)
算法示例如图4-4所示:
图4-4 求出左上角点在图块内的坐标
4.5将雷达图片绘制在临时图像中
将图片左上角在图块内的坐标(x3,y3)作为起始坐标,整个雷达图片根据起始坐标放入一张足够大的临时图像中,该临时图像能完整包含整个雷达图片,是由整数个256*256图块组成的矩形图块。
这里需要特别注意的是地图坐标系和图像坐标系的变化,坐标系原点(0,0)在图像坐标系左上角,由此左上角在图块内的坐标(x3,y3)换算成雷达图片在临时图像中的起始坐标为(x3,256-y3)。
设临时图像宽度为w,高度为h,临时图像宽度所占的图块个数为N1,高度所占的图块个数为N2,Width为雷达图片宽,Height为雷达图片高,这里需要保证w,h为256的整数倍,N1,N2结果只保留整数部分。
N1 = ((x3 + Width) / 256) + 1 (13)
N2 = ((y3 + Height) / 256) + 1 (14)
w = N1 * 256 (15)
h = N2 * 256 (16)
示意图如图4-5:
图4-5 确定临时图片中的起始坐标和宽高
4.6切割临时图片及透明化处理
将上面步骤得到的临时图像的宽高 w , h 按照长宽 256 像素循环切割,并按照图块 x ,图块 y , zoom 分别命名,方便百度地图 API 读取显示。需要处理透明的颜色通过判断 RGB 值选出,从而改变 Alpha 通道实现。
最终效果图: