1、标准
GB T 13989-2012国家基本比例尺地形图分幅和编号
地址:【高清版】GB T 13989-2012国家基本比例尺地形图分幅和编号 - 道客巴巴
2、1:100万比例尺
2.1 说明
2.2 计算公式
2.3 计算代码
2.3.1 元素数据定义
由于中国只到N层,所以只定义到O.
/**
* 100万比例尺下的行号对应的代码
*/
static mateData100 = [
{
rowCode: "A",
rowNumber: 1,
},
{
rowCode: "B",
rowNumber: 2,
},
{
rowCode: "C",
rowNumber: 3,
},
{
rowCode: "D",
rowNumber: 4,
},
{
rowCode: "E",
rowNumber: 5,
},
{
rowCode: "F",
rowNumber: 6,
},
{
rowCode: "G",
rowNumber: 7,
},
{
rowCode: "H",
rowNumber: 8,
},
{
rowCode: "I",
rowNumber: 9,
},
{
rowCode: "J",
rowNumber: 10,
},
{
rowCode: "K",
rowNumber: 11,
},
{
rowCode: "L",
rowNumber: 12,
},
{
rowCode: "M",
rowNumber: 13,
},
{
rowCode: "N",
rowNumber: 14,
},
{
rowCode: "O",
rowNumber: 15,
},
];
2.3.2 代码实现
/**
* 根据经纬度计算100万比例尺的行列号
* @param lon
* @param lat
* @return {{col: number, row: number, code: string}}
*/
static calcMapFrameNumber100 = (lon, lat) => {
let a = Math.trunc(lat / 4.0) + 1;
let b = Math.trunc(lon / 6.0) + 31;
let mateInfo = MapFrameUtils.mateData100.find(
(item) => item.rowNumber === a
);
return {
row: a,
col: b,
code: mateInfo.rowCode,
};
};
3、非100万比例尺
3.1 说明
3.1.1 2000到50万比例尺格式
3.1.2 500到1000比例尺格式
3.2 计算公式
3.3 代码
3.3.1 元数据
/**
* 100万比例尺下的行号对应的代码
*/
static mateData100 = [
{
rowCode: "A",
rowNumber: 1,
},
{
rowCode: "B",
rowNumber: 2,
},
{
rowCode: "C",
rowNumber: 3,
},
{
rowCode: "D",
rowNumber: 4,
},
{
rowCode: "E",
rowNumber: 5,
},
{
rowCode: "F",
rowNumber: 6,
},
{
rowCode: "G",
rowNumber: 7,
},
{
rowCode: "H",
rowNumber: 8,
},
{
rowCode: "I",
rowNumber: 9,
},
{
rowCode: "J",
rowNumber: 10,
},
{
rowCode: "K",
rowNumber: 11,
},
{
rowCode: "L",
rowNumber: 12,
},
{
rowCode: "M",
rowNumber: 13,
},
{
rowCode: "N",
rowNumber: 14,
},
{
rowCode: "O",
rowNumber: 15,
},
];
3.3.2 实现代码
/**
* 根据比例尺,经纬度计算地图的行列号
* @param scale
* @param lon
* @param lat
* @return {{col: number, code: *, row: number, digit: (number|*)}|null}
*/
static calcMapFrameNumberNot100 = (scale, lon, lat) => {
let mateData = MapFrameUtils.mateData.find((item) => item.scale === scale);
if (mateData) {
let cStep = ((lat % 4) / mateData.latD).toPrecision(4);
let c = Math.round(4 / mateData.latD - Math.trunc(Number(cStep)));
let dStep = ((lon % 6) / mateData.lonD).toPrecision(4);
let d = Math.trunc(Number(dStep)) + 1;
return {
row: c,
col: d,
code: mateData.code,
digit: mateData.digit,
};
} else {
return null;
}
};
4、综合代码
/**
* 采用标准:国家基本比例尺地形图分幅和编号《GB/T 13989-2012》
* 1、根据经纬度计算图幅号
* 2、根据图幅号图幅范围计算
* 3、定义图幅信息
*/
export default class MapFrameUtils {
/**
* 根据经纬度计算100万比例尺的行列号
* @param lon
* @param lat
* @return {{col: number, row: number, code: string}}
*/
static calcMapFrameNumber100 = (lon, lat) => {
let a = Math.trunc(lat / 4.0) + 1;
let b = Math.trunc(lon / 6.0) + 31;
let mateInfo = MapFrameUtils.mateData100.find(
(item) => item.rowNumber === a
);
return {
row: a,
col: b,
code: mateInfo.rowCode,
};
};
/**
* 根据比例尺,经纬度计算地图的行列号
* @param scale
* @param lon
* @param lat
* @return {{col: number, code: *, row: number, digit: (number|*)}|null}
*/
static calcMapFrameNumberNot100 = (scale, lon, lat) => {
let mateData = MapFrameUtils.mateData.find((item) => item.scale === scale);
if (mateData) {
let cStep = ((lat % 4) / mateData.latD).toPrecision(4);
let c = Math.round(4 / mateData.latD - Math.trunc(Number(cStep)));
let dStep = ((lon % 6) / mateData.lonD).toPrecision(4);
let d = Math.trunc(Number(dStep)) + 1;
return {
row: c,
col: d,
code: mateData.code,
digit: mateData.digit,
};
} else {
return null;
}
};
/**
* 根据计算出来的行列号,比例尺,计算该格网在地图商的范围
* @param frame100
* @param frameNot100
* @param scale
* @return {{minY: number, minX: number, maxY: number, maxX: number}}
*/
static calcMapFrameExtent = (frame100, frameNot100, scale) => {
let mateData = MapFrameUtils.mateData.find((item) => item.scale === scale);
let lon = (frame100.col - 31) * 6 + (frameNot100.col - 1) * mateData.lonD;
let lat =
(frame100.row - 1) * 4 +
(4 / mateData.latD - frameNot100.row) * mateData.latD;
return {
minX: lon,
minY: lat,
maxX: lon + mateData.lonD,
maxY: lat + mateData.latD,
};
};
/**
* 根据比例尺和经纬度,获取所在图幅范围的编号、行列号以及范围
* @param scale
* @param lon
* @param lat
* @return {null|{extent: {minY: number, minX: number, maxY: number, maxX: number}, col: number, code: string, row: number}}
*/
static calcMapFrameNumber = (scale, lon, lat) => {
let mapFrameNumber100 = MapFrameUtils.calcMapFrameNumber100(lon, lat);
let mapFrameNumberNot100 = MapFrameUtils.calcMapFrameNumberNot100(
scale,
lon,
lat
);
if (mapFrameNumberNot100) {
let code =
mapFrameNumber100.code +
"" +
mapFrameNumber100.col +
"" +
mapFrameNumberNot100.code +
"" +
mapFrameNumberNot100.row
.toString()
.padStart(mapFrameNumberNot100.digit, "0") +
"" +
mapFrameNumberNot100.col
.toString()
.padStart(mapFrameNumberNot100.digit, "0");
let extent = MapFrameUtils.calcMapFrameExtent(
mapFrameNumber100,
mapFrameNumberNot100,
scale
);
return {
code: code,
extent: extent,
row: mapFrameNumberNot100.row,
col: mapFrameNumberNot100.col,
};
} else {
return null;
}
};
/**
* 100万比例尺下的行号对应的代码
*/
static mateData100 = [
{
rowCode: "A",
rowNumber: 1,
},
{
rowCode: "B",
rowNumber: 2,
},
{
rowCode: "C",
rowNumber: 3,
},
{
rowCode: "D",
rowNumber: 4,
},
{
rowCode: "E",
rowNumber: 5,
},
{
rowCode: "F",
rowNumber: 6,
},
{
rowCode: "G",
rowNumber: 7,
},
{
rowCode: "H",
rowNumber: 8,
},
{
rowCode: "I",
rowNumber: 9,
},
{
rowCode: "J",
rowNumber: 10,
},
{
rowCode: "K",
rowNumber: 11,
},
{
rowCode: "L",
rowNumber: 12,
},
{
rowCode: "M",
rowNumber: 13,
},
{
rowCode: "N",
rowNumber: 14,
},
{
rowCode: "O",
rowNumber: 15,
},
];
/**
* 非100万情况下,不同比例尺的原始数据
*/
static mateData = [
{
scale: 500000,
label: "1:50万",
lonD: 3,
latD: 2,
code: "B",
digit: 3,
},
{
scale: 250000,
label: "1:25万",
lonD: 1.5,
latD: 1,
code: "C",
digit: 3,
},
{
scale: 100000,
label: "1:10万",
lonD: 0.5,
latD: 0.33333333,
code: "D",
digit: 3,
},
{
scale: 50000,
label: "1:5万",
lonD: 0.25,
latD: 0.16666667,
code: "E",
digit: 3,
},
{
scale: 25000,
label: "1:2.5万",
lonD: 0.125,
latD: 0.08333333,
code: "F",
digit: 3,
},
{
scale: 10000,
label: "1:1万",
lonD: 0.0625,
latD: 0.04166667,
code: "G",
digit: 3,
},
{
scale: 5000,
label: "1:5000",
lonD: 0.03125,
latD: 0.02083333,
code: "H",
digit: 3,
},
{
scale: 2000,
label: "1:2000",
lonD: 0.01041667,
latD: 0.006944444,
code: "I",
digit: 3,
},
{
scale: 1000,
label: "1:1000",
lonD: 0.005208333,
latD: 0.003472222,
code: "J",
digit: 4,
},
{
scale: 500,
label: "1:500",
lonD: 0.002603889,
latD: 0.001736111,
code: "K",
digit: 4,
},
];
}
5、测试结果
5.1 测试代码
MapFrameUtils.mateData.forEach((item) => {
let mapFrame = MapFrameUtils.calcMapFrameNumber(item.scale, 114.5625, 39.375);
console.log(item.scale, mapFrame);
});
5.2 测试结果
与标准中结果一致