threejs使用球体制作地球模型时没找到合适的贴图,那么就自己下载地图切片制作吧,记录下过程。
初始化设置
下载QGis
QGis下载地址
QGis 设置为中文
QGis > Preferences > General > User interface translation > OK
设置完成重启QGis
添加天地图XYZ切片服务
-
注册天地图用户前往控制台申请访问密钥tk
2. 创建应用
应用名称和应用类型可以随意填写,但是要注意的是应用类型 。使用不同客户端会限制访问,例如 申请应用选择的是服务端,在浏览器端使用改 key 访问就会访问失败
- QGis中添加天地图服务
- 天地图访问Api 地址
-
天地图切片服务访问地址
3857是指球面墨卡托投影,4326是指经纬度投影。tk为创建应用时生成的key。-
地址规则如下:
t0.tianditu.gov.cn/[图层服务访问前缀]/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=[图层类型]&STYLE=default&TILEMATRIXSET=[切片规则]&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=填写成应用的key
图层服务访问前缀:
图层类型+切片规则:
let [图层类型,切片规则] = 图层服务访问前缀.split("_");
// 矢量底图 http://t0.tianditu.gov.cn/vec_c/wmts let [LAYER,TILEMATRIXSET]"vec_c".split("_"); // 图层类型 LAYER = vec // 切片规则 TILEMATRIXSET = c -
常用服务地址
- 天地图影像图3857 :
http://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=填写成应用的key - 天地图影像图3857注记:
http://t0.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=填写成应用的key - 天地图矢量图3857:
http://t0.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=填写成应用的key - 天地图矢量图3857注记:
http://t0.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=填写成应用的key - 天地图影像图4326:
http://t0.tianditu.gov.cn/img_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=填写成应用的key - 天地图影像图4326注记:
http://t0.tianditu.gov.cn/cia_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=填写成应用的key - 天地图矢量图4326:
http://t0.tianditu.gov.cn/vec_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=填写成应用的key - 天地图矢量图注记4326:
http://t0.tianditu.gov.cn/cva_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=填写成应用的key
- 天地图影像图3857 :
-
-
QGis 新建XYZ切片服务链接
-
切片服务预览
-
注意事项
- 当图层服务添加进去发现看不了图层,尝试切换下天地图服务的tk
安装 QTiles 切片下载插件
插件 > 管理并安装插件 > 搜索QTiles > 安装
下载切片
打开QTiles插件下载
切片下载设置
-
Tileset name 配置输出名称
-
Output 配置输出目录
-
Extent 设置切片下载边界
-
Zoom 设置切片下载层级
-
Parameters 参数默认就好
注意事项
- 切片下载前先将天地图切片服务加入图层预览
- 下载的图层不对,检查下 Extent 边界设置
- 设置层级过大会非常耗时
- 下载的规则是 z/x/y,层级/列/行
合并切片
基于Node.js + jimp 简单实现某个层级下的切片合并
const { readdirSync, statSync, readFileSync } = require('fs');
const { join, basename, extname } = require('path');
const Jimp = require('jimp');
// 合并某个层级下的图片
const folderPath = 'Mapnik22/5/';
// 要忽略的文件夹/文件名
const excludedNames = ['.DS_Store'];
function getFilesAndFolders(filePath) {
const items = readdirSync(filePath);
return items
.filter(item => !excludedNames.includes(item))
.map(item => {
const itemPath = join(filePath, item);
return {
path: itemPath,
isFile: statSync(itemPath).isFile()
};
})
.sort((a, b) => {
if (a.isFile && b.isFile) {
return (
basename(a.path, extname(a.path)) - basename(b.path, extname(b.path))
);
}
if (!a.isFile && !b.isFile) {
return basename(a.path) - basename(b.path);
}
return 0;
});
}
const imageGroups = [];
const folders = getFilesAndFolders(folderPath);
folders.forEach((folderInfo, index) => {
if (!folderInfo.isFile) {
const imagesInFolder = [];
getFilesAndFolders(folderInfo.path).forEach(fileInfo => {
if (fileInfo.isFile) {
imagesInFolder.push(fileInfo.path);
}
});
imageGroups[index] = imagesInFolder;
}
});
Promise.all(
imageGroups.map(col => Promise.all(col.map(path => Jimp.read(path))))
)
.then(cols => {
// 计算合并图片的宽度
const width = cols.reduce(
(acc, col) => acc + Math.max(...col.map(image => image.bitmap.width)),
0
);
// 计算合并图片的高度
const height = Math.max(
...cols.map(col =>
col.reduce((acc, image) => acc + image.bitmap.height, 0)
)
);
// 创建一个新的 Jimp 对象
const mergedImage = new Jimp(width, height);
// 合并图片
let x = 0;
cols.forEach((col, index) => {
let y = 0;
col.forEach((image, row) => {
mergedImage.composite(image, x, y);
y += image.bitmap.height;
console.log(`第${index}列,第${row}行,${imageGroups[index][row]}`);
});
x += Math.max(...col.map(image => image.bitmap.width));
});
// 保存合并后的图片
return mergedImage.writeAsync('output.png');
})
.then(() => {
console.log('图片合并完成');
})
.catch(err => {
console.error('图片合并失败:', err);
});