- r=6378137
- resolution=2*PI*r/(2^zoom*256)
各个级别中像素与米的对应关系如下:
- resolution zoom 2048 blocksize 256 blocksize scale(dpi=160)
- 156543.0339 0 320600133.5 40075016.69 986097851.5
- 78271.51696 1 160300066.7 20037508.34 493048925.8
- 39135.75848 2 80150033.37 10018754.17 246524462.9
- 19567.87924 3 40075016.69 5009377.086 123262231.4
- 9783.939621 4 20037508.34 2504688.543 61631115.72
- 4891.96981 5 10018754.17 1252344.271 30815557.86
- 2445.984905 6 5009377.086 626172.1357 15407778.93
- 1222.992453 7 2504688.543 313086.0679 7703889.465
- 611.4962263 8 1252344.271 156543.0339 3851944.732
- 305.7481131 9 626172.1357 78271.51696 1925972.366
- 152.8740566 10 313086.0679 39135.75848 962986.1831
- 76.4370283 11 156543.0339 19567.87924 481493.0916
- 38.2185141 12 78271.51696 9783.939621 240746.5458
- 19.1092571 13 39135.75848 4891.96981 120373.2729
- 9.5546285 14 19567.87924 2445.984905 60186.63645
- 4.7773143 15 9783.939621 1222.992453 30093.31822
- 2.3886571 16 4891.96981 611.4962263 15046.65911
- 1.1943286 17 2445.984905 305.7481131 7523.329556
- 0.5971643 18 1222.992453 152.8740566 3761.664778
- 0.2985821 19 611.4962263 76.43702829 1880.832389
- 0.1492911 20 305.7481131 38.21851414 940.4161945
- 0.0746455 21
- 0.0373227 22
3D 中的计算策略是,首先需要将 3D 世界中的坐标与墨卡托单位的对应关系搞清楚,如果已经是以 mi 来做单位,那么就可以直接将相机的投影屏幕的高度与屏幕的像素数目做比值,得出的结果跟上面的 ranking 做比较,选择不用的级别数据以及比例尺。注意 3D 地图中的比例尺并不是在所有屏幕上的所有位置与现实世界都满足这个比例尺,只能说是相机中心点在屏幕位置处的像素是满足这个关系的,因为平行投影有近大远小的效果。
9、poi 碰撞
由于标注是永远朝着相机的,所以标注的碰撞就是把标注点转换到屏幕坐标系用宽高来计算矩形相交问题。至于具体的碰撞算法,大家可以在网上找到,这里不展开。下面是计算 poi 矩形的代码
- export
- function getPoiRect(poi, zoomLevel, wrapper) {
- let style = getStyle(poi.styleId, zoomLevel);
- if (!style) {
- console.warn("style is invalid!");
- return;
- }
- let labelStyle = getStyle(style.labelid, zoomLevel);
- if (!labelStyle) {
- console.warn("labelStyle is invalid!");
- return;
- }
- if (!poi.text) {
- return;
- }
- let charWidth = (TEXTPROP.charWidth || 11.2) * // 11.2是根据测试得到的估值
- (labelStyle.fontSize / (TEXTPROP.fontSize || 13)); // 13是得到11.2时的fontSize
- // 返回2d坐标
- let x = 0; //poi.points[0].x;
- let y = 0; //-poi.points[0].z;
- let path = [];
- let icon = iconSet[poi.styleId];
- let iconWidh = (icon && icon.width) || 32;
- let iconHeight = (icon && icon.height) || 32;
- let multi = /\//g;
- let firstLinePos = [];
- let textAlign = null;
- let baseLine = null;
- let hOffset = (iconWidh / 2) * ICONSCALE;
- let vOffset = (iconHeight / 2) * ICONSCALE;
- switch (poi.direct) {
- case 2:
- { // 左
- firstLinePos.push(x - hOffset - 2);
- firstLinePos.push(y);
- textAlign = 'right';
- baseLine = 'middle';
- break;
- };
- case 3:
- { // 下
- firstLinePos.push(x);
- firstLinePos.push(y - vOffset - 2);
- textAlign = 'center';
- baseLine = 'top';
- break;
- };
- case 4:
- { // 上
- firstLinePos.push(x);
- firstLinePos.push(y + vOffset + 2);
- textAlign = 'center';
- baseLine = 'bottom';
- break;
- };
- case 1:
- { // 右
- firstLinePos.push(x + hOffset + 2);
- firstLinePos.push(y);
- textAlign = 'left';
- baseLine = 'middle';
- break;
- };
- default:
- {
- firstLinePos.push(x);
- firstLinePos.push(y);
- textAlign = 'center';
- baseLine = 'middle';
- }
- }
- path = path.concat(firstLinePos);
- let minX = null,
- maxX = null;
- let minY = null,
- maxY = null;
- let parts = poi.text.split(multi);
- let textWidth = 0;
- if (wrapper) {
- // 汉字和数字的宽度是不同的,所以必须使用measureText来精确测量
- let textWidth1 = wrapper.context.measureText(parts[0]).width;
- let textWidth2 = wrapper.context.measureText(parts[1] || '').width;
- textWidth = Math.max(textWidth1, textWidth2);
- } else {
- textWidth = Math.max(parts[0].length, parts[1] ? parts[1].length: 0) * charWidth;
- }
- if (textAlign === 'left') {
- minX = x - hOffset;
- maxX = path[0] + textWidth; // 只用第一行文本
- } else if (textAlign === 'right') {
- minX = path[0] - textWidth;
- maxX = x + hOffset;
- } else { // center
- minX = x - Math.max(textWidth / 2, hOffset);
- maxX = x + Math.max(textWidth / 2, hOffset);
- }
- if (baseLine === 'top') {
- maxY = y + vOffset;
- minY = y - vOffset - labelStyle.fontSize * parts.length;
- } else if (baseLine === 'bottom') {
- maxY = y + vOffset + labelStyle.fontSize * parts.length;
- minY = y - vOffset;
- } else { // middle
- minY = Math.min(y - vOffset, path[1] - labelStyle.fontSize / 2);
- maxY = Math.max(y + vOffset, path[1] + labelStyle.fontSize * (parts.length + 0.5 - 1));
- }
- return {
- min: {
- x: minX,
- y: minY
- },
- max: {
- x: maxX,
- y: maxY
- }
- };
- }
来源: http://www.cnblogs.com/dojo-lzz/p/7143276.html