中国建设网站中天建设平分数,网站建设方案包括,网站建设模板购买,wordpress 免费cms主题背景介绍
前两天研究GeoServer发布存储在PostGIS中栅格数据#xff0c;最终目的是想在PostGIS中存储金字塔瓦片#xff0c;用GeoServer发布#xff0c;但是最后经过研究不改GeoServer源码的情况下#xff0c;好像只支持将大图tif存在PostGIS数据库中进行发布#xff0c;金…背景介绍
前两天研究GeoServer发布存储在PostGIS中栅格数据最终目的是想在PostGIS中存储金字塔瓦片用GeoServer发布但是最后经过研究不改GeoServer源码的情况下好像只支持将大图tif存在PostGIS数据库中进行发布金字塔存入数据库后由于PostGIS的raster类型只存了瓦片的scale没有存类似层级的东西导致发布后所有的金字塔层级一起显示了没有层级控制导致了很多影像叠加到一起了后来又想到在数据库新增一个level字段然后使用sld来进行控制显示最后发现sld读不到字段表这个路径也就放弃了也许是我没弄对有大佬点拨一下的话万分感谢。
今天灵感来了自己弄着玩想到直接把瓦片的编号以及原始数据存到数据库然后写个网络接口按照xyz数据源的格式请求接口里查询数据库返回一张image给客户端是不是就相当于一个xyz的瓦片服务器了最终经过测试是可行的先上两张效果图。
QGIS加载效果 水经微图加载效果 下面就说一下实现的具体流程
数据准备
数据是wgs84的瓦片xyz都是从0开始从左上角开始逆时针编号以下是瓦片本地存储示例 组织结构最外层为z值第二层为x值图片名称为y值。
数据库表示例 然后使用Qt将瓦片读入并写入数据库相关代码如下
#pragma once#include QString
#include QSqlDatabaseclass CImageUploader
{
public:CImageUploader();~CImageUploader();void Init();void CreateTable();void UploadTileImage(const QString strTileDir);private:QSqlDatabase m_db;
};
#include ImageUploader.h
#include QDir
#include QFile
#include QDebug
#include QFileInfo
#include QSqlQuery
#include QSqlError
#include QByteArray
#include QBufferQString strHostName 192.168.1.7;
QString strDatabaseName Tile;
QString strUserName postgres;
QString strPassword root;
QString strPort 4321;CImageUploader::CImageUploader()
{Init();CreateTable();
}CImageUploader::~CImageUploader()
{}void CImageUploader::Init()
{m_db QSqlDatabase::addDatabase(QPSQL);m_db.setHostName(strHostName);m_db.setDatabaseName(strDatabaseName);m_db.setUserName(strUserName);m_db.setPassword(strPassword);m_db.setPort(strPort.toInt());if (!m_db.open()){qDebug() Failed to open database connection! m_db.lastError().text();}
}void CImageUploader::CreateTable()
{// 使用 IF NOT EXISTS 判断表是否存在QString strCreateTableQuery QString(R(CREATE TABLE IF NOT EXISTS Tile (id SERIAL PRIMARY KEY,x BIGINT NOT NULL,y BIGINT NOT NULL,z INT NOT NULL,data BYTEA NOT NULL);));QSqlQuery query(m_db);if (!query.exec(strCreateTableQuery)){qDebug() Exec failed: query.lastError().text().toLocal8Bit();}
}void CImageUploader::UploadTileImage(const QString strTileDir)
{QDir zDir(strTileDir);if (!zDir.exists()) {qDebug() Directory does not exist: strTileDir;return;}// 遍历 z 值文件夹QStringList zFolders zDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);foreach(const QString zFolder, zFolders) {bool zOk;int z zFolder.toInt(zOk);if (!zOk) {qDebug() Invalid z folder: zFolder;continue;}QDir xDir(zDir.filePath(zFolder));// 遍历 x 值文件夹QStringList xFolders xDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);foreach(const QString xFolder, xFolders) {bool xOk;qint64 x xFolder.toLongLong(xOk);if (!xOk) {qDebug() Invalid x folder: xFolder;continue;}QDir yDir(xDir.filePath(xFolder));// 遍历 y 值的图片文件QStringList imageFiles yDir.entryList(QDir::Files);foreach(const QString imageFile, imageFiles) {QString yValueStr QFileInfo(imageFile).baseName();bool yOk;qint64 y yValueStr.toLongLong(yOk);if (!yOk) {qDebug() Invalid y file name: imageFile;continue;}QString imagePath yDir.filePath(imageFile);QFile file(imagePath);if (!file.open(QIODevice::ReadOnly)) {qDebug() Failed to open image file: imagePath;continue;}QByteArray imageData file.readAll();file.close();// 上传图片数据到数据库QSqlQuery query(m_db);query.prepare(INSERT INTO Tile (x, y, z, data) VALUES (:x, :y, :z, :data));query.bindValue(:x, x);query.bindValue(:y, y);query.bindValue(:z, z);query.bindValue(:data, imageData);if (!query.exec()) {qDebug() Failed to upload tile image: query.lastError().text();}else {qDebug() Successfully uploaded tile image: z z , x x , y y;}}}}
}
#include QCoreApplication
#include ImageUploader.hint main(int argc, char *argv[])
{QCoreApplication a(argc, argv);CImageUploader imageUploader;imageUploader.UploadTileImage(QString::fromLocal8Bit(R(H:\data)));return a.exec();
}
服务实现
数据写入数据库后只需要弄一个http接口了我这里使用的是Node.js直连PostGIS数据库然后根据请求去查数据库对应的image值然后返回给客户端Node代码如下
const express require(express);
const { Pool } require(pg);
const app express();
const port 3000;// 配置PostgreSQL连接池
const pool new Pool({user: postgres,host: 192.168.1.7,database: Tile,password: root,port: 4321,
});// XYZ瓦片接口
app.get(/tiles/:z/:x/:y, async (req, res) {let { z, x, y } req.params;// 提取数字部分的 y 值去除文件扩展名y y.split(.)[0];try {// 确保 z, x, y 是有效的数字const zInt parseInt(z, 10);const xInt parseInt(x, 10);const yInt parseInt(y, 10);if (isNaN(zInt) || isNaN(xInt) || isNaN(yInt)) {return res.status(400).send(Invalid tile coordinates);}// 查询数据库获取瓦片数据const queryText SELECT data FROM Tile WHERE z $1 AND x $2 AND y $3;const result await pool.query(queryText, [zInt -1, xInt, yInt]);if (result.rows.length 0) {const tileData result.rows[0].data;res.setHeader(Content-Type, image/jpeg); // 确保设置正确的图片格式res.send(tileData);} else {res.status(404).send(Tile not found);}} catch (err) {console.error(Error fetching tile:, err);res.status(500).send(Internal Server Error);}
});// 启动服务器
app.listen(port, () {console.log(Tile server is running at http://localhost:${port});
});安装依赖
npm init -y
npm install express pg启动
node server.js然后就可以在浏览器请求测试(图片格式后缀其实没影响加不加都可)
http://localhost:3000/tiles/{z}/{x}/{y}.jpg例如
localhost:3000/tiles/1/0/0.jpg 效果如下 然后就是QGIS加载测试在XYZ Tiles新建链接输入名称和网址网址直接输入http://localhost:3000/tiles/{z}/{x}/{y}.jpg即可,Node做了z-1处理图块分辨率可以不管也可以设为256*256如下 在水经微图里点击在线地图自定义在弹出的页面中输入前面所说的网址即可如下 最后给两张放大的效果图(数据只有6级)
QGIS: 水经微图 分享到此结束。