fix(vtk): 地形不出根因-看小测区LOD选z16-18>DEM上限15致fetchTerrain静默退出;改取祖先DEM瓦片按经纬采样+诊断日志
This commit is contained in:
parent
67f767d787
commit
33e9949623
|
|
@ -114,6 +114,7 @@ void TileBasemap::show(Kind kind) {
|
|||
inFlight_.clear();
|
||||
terrainInFlight_.clear();
|
||||
desired_.clear();
|
||||
terrainProbed_ = false;
|
||||
kind_ = kind;
|
||||
if (kind == Hidden) {
|
||||
if (rw_) rw_->Render();
|
||||
|
|
@ -280,18 +281,26 @@ void TileBasemap::placeTile(long long key, int z, int x, int y, const QImage& im
|
|||
}
|
||||
|
||||
void TileBasemap::fetchTerrain(int z, int x, int y, long long key) {
|
||||
if (z > kDemMaxZoom) return; // 高层级无 DEM → 维持平面
|
||||
if (terrainInFlight_.count(key)) return;
|
||||
// Terrarium 数据约到 z15;更高层级取覆盖本块的祖先 DEM 瓦片,按经纬采样其子区域。
|
||||
const int dz = std::min(z, kDemMaxZoom);
|
||||
const int shift = z - dz;
|
||||
const int dx = x >> shift, dy = y >> shift;
|
||||
if (!terrainProbed_) {
|
||||
terrainProbed_ = true;
|
||||
qInfo() << "[basemap] 首次拉DEM 卫星z=" << z << " → DEMz=" << dz << "(" << dx << "," << dy
|
||||
<< ")";
|
||||
}
|
||||
// 必须 https:该 S3 桶对纯 http 返回 403(实测)。
|
||||
const QString url =
|
||||
QStringLiteral("https://s3.amazonaws.com/elevation-tiles-prod/terrarium/%1/%2/%3.png")
|
||||
.arg(z)
|
||||
.arg(x)
|
||||
.arg(y);
|
||||
.arg(dz)
|
||||
.arg(dx)
|
||||
.arg(dy);
|
||||
const int gen = generation_;
|
||||
terrainInFlight_.insert(key);
|
||||
QNetworkReply* reply = nam_.get(QNetworkRequest(QUrl(url)));
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply, key, z, x, y, gen]() {
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply, key, z, x, y, dz, dx, dy, gen]() {
|
||||
reply->deleteLater();
|
||||
terrainInFlight_.erase(key);
|
||||
if (gen != generation_ || kind_ != Satellite) return;
|
||||
|
|
@ -305,11 +314,12 @@ void TileBasemap::fetchTerrain(int z, int x, int y, long long key) {
|
|||
qWarning() << "[basemap] DEM 解码失败" << reply->url().toString();
|
||||
return;
|
||||
}
|
||||
applyTerrain(key, z, x, y, dem);
|
||||
applyTerrain(key, z, x, y, dz, dx, dy, dem);
|
||||
});
|
||||
}
|
||||
|
||||
void TileBasemap::applyTerrain(long long key, int z, int x, int y, const QImage& dem) {
|
||||
void TileBasemap::applyTerrain(long long key, int sz, int sx, int sy, int dz, int dx, int dy,
|
||||
const QImage& dem) {
|
||||
auto it = placed_.find(key);
|
||||
if (it == placed_.end()) return;
|
||||
vtkSmartPointer<vtkTexture> tex = it->second->GetTexture(); // 复用已贴卫星纹理
|
||||
|
|
@ -317,24 +327,35 @@ void TileBasemap::applyTerrain(long long key, int z, int x, int y, const QImage&
|
|||
if (!haveBaseline_) { // 基准高程取首块中心 → 地形整体绕 z=0 起伏
|
||||
baseline_ = demElev(dem, 0.5, 0.5);
|
||||
haveBaseline_ = true;
|
||||
double mn = 1e30, mx = -1e30;
|
||||
for (int yy = 0; yy < dem.height(); yy += 16)
|
||||
for (int xx = 0; xx < dem.width(); xx += 16) {
|
||||
const double e = demElev(dem, xx / double(dem.width() - 1),
|
||||
yy / double(dem.height() - 1));
|
||||
mn = std::min(mn, e);
|
||||
mx = std::max(mx, e);
|
||||
}
|
||||
auto warped = buildWarped(z, x, y, tex, dem);
|
||||
qInfo() << "[basemap] 地形启用 baseline=" << baseline_ << "m 首块高程范围[" << mn << ","
|
||||
<< mx << "]m 起伏=" << (mx - mn) << "m";
|
||||
}
|
||||
auto warped = buildWarped(sz, sx, sy, dz, dx, dy, tex, dem);
|
||||
scene_.renderer()->RemoveViewProp(it->second);
|
||||
scene_.addActor(warped);
|
||||
it->second = warped;
|
||||
if (rw_) rw_->Render();
|
||||
}
|
||||
|
||||
vtkSmartPointer<vtkActor> TileBasemap::buildWarped(int z, int x, int y,
|
||||
vtkSmartPointer<vtkActor> TileBasemap::buildWarped(int sz, int sx, int sy, int dz, int dx, int dy,
|
||||
vtkSmartPointer<vtkTexture> tex,
|
||||
const QImage& dem) {
|
||||
const geopro::render::LonLatBox b = geopro::render::tileBounds(z, x, y);
|
||||
const auto sw = frame_->toLocal(b.south, b.west);
|
||||
const auto se = frame_->toLocal(b.south, b.east);
|
||||
const auto nw = frame_->toLocal(b.north, b.west);
|
||||
const double base = kGroundZ + (z - kMinZoom) * kZEps;
|
||||
const geopro::render::LonLatBox sb = geopro::render::tileBounds(sz, sx, sy); // 卫星块(几何)
|
||||
const geopro::render::LonLatBox db = geopro::render::tileBounds(dz, dx, dy); // DEM 块(采样)
|
||||
const auto sw = frame_->toLocal(sb.south, sb.west);
|
||||
const auto se = frame_->toLocal(sb.south, sb.east);
|
||||
const auto nw = frame_->toLocal(sb.north, sb.west);
|
||||
const double base = kGroundZ + (sz - kMinZoom) * kZEps;
|
||||
|
||||
// PlaneSource(等距圆柱下平面插值即正确 x/y) + 自动 tcoord;再按高程位移每点 Z。
|
||||
// PlaneSource(等距圆柱下平面插值即正确 x/y) + 自动 tcoord;再按各点真实经纬采 DEM 位移 Z。
|
||||
vtkNew<vtkPlaneSource> plane;
|
||||
plane->SetOrigin(sw.x, sw.y, base);
|
||||
plane->SetPoint1(se.x, se.y, base);
|
||||
|
|
@ -346,11 +367,16 @@ vtkSmartPointer<vtkActor> TileBasemap::buildWarped(int z, int x, int y,
|
|||
warped->DeepCopy(plane->GetOutput());
|
||||
vtkDataArray* tc = warped->GetPointData()->GetTCoords();
|
||||
vtkPoints* pts = warped->GetPoints();
|
||||
const double sLonSpan = sb.east - sb.west, sLatSpan = sb.north - sb.south;
|
||||
const double dLonSpan = db.east - db.west, dLatSpan = db.north - db.south;
|
||||
const vtkIdType n = pts->GetNumberOfPoints();
|
||||
for (vtkIdType id = 0; id < n; ++id) {
|
||||
double t[2];
|
||||
tc->GetTuple(id, t);
|
||||
const double fx = t[0], fy = 1.0 - t[1]; // tcoord v: 南0北1 → fy: 北0南1(对齐 DEM 顶行=北)
|
||||
tc->GetTuple(id, t); // u:西0东1, v:南0北1
|
||||
const double lon = sb.west + t[0] * sLonSpan;
|
||||
const double lat = sb.south + t[1] * sLatSpan;
|
||||
const double fx = (lon - db.west) / dLonSpan; // DEM 块内列比例
|
||||
const double fy = (db.north - lat) / dLatSpan; // DEM 顶行=北 → fy
|
||||
const double elev = demElev(dem, fx, fy);
|
||||
double p[3];
|
||||
pts->GetPoint(id, p);
|
||||
|
|
|
|||
|
|
@ -42,9 +42,11 @@ private:
|
|||
bool computeView(double& centerLat, double& centerLon, int& zoom) const;
|
||||
void fetchTile(int z, int x, int y, long long key);
|
||||
void placeTile(long long key, int z, int x, int y, const QImage& img);
|
||||
void fetchTerrain(int z, int x, int y, long long key); // 拉对应 DEM 瓦片(卫星模式)
|
||||
void applyTerrain(long long key, int z, int x, int y, const QImage& dem); // 平面块换起伏块
|
||||
vtkSmartPointer<vtkActor> buildWarped(int z, int x, int y, vtkSmartPointer<vtkTexture> tex,
|
||||
void fetchTerrain(int z, int x, int y, long long key); // 拉覆盖该瓦片的 DEM(z>15 取祖先块)
|
||||
void applyTerrain(long long key, int sz, int sx, int sy, int dz, int dx, int dy,
|
||||
const QImage& dem); // 平面块换起伏块
|
||||
vtkSmartPointer<vtkActor> buildWarped(int sz, int sx, int sy, int dz, int dx, int dy,
|
||||
vtkSmartPointer<vtkTexture> tex,
|
||||
const QImage& dem); // DEM 位移网格 + 卫星贴图
|
||||
static void onInteractionEnd(vtkObject*, unsigned long, void* clientData, void*);
|
||||
|
||||
|
|
@ -60,6 +62,7 @@ private:
|
|||
std::set<long long> terrainInFlight_; // DEM 瓦片在途请求
|
||||
double baseline_ = 0.0; // 基准高程(首块中心),地形绕 z=0 起伏
|
||||
bool haveBaseline_ = false;
|
||||
bool terrainProbed_ = false; // 首次 fetchTerrain 打一行诊断日志
|
||||
vtkSmartPointer<vtkInteractorObserver> styleObs_; // 持引用保证回调期有效
|
||||
vtkSmartPointer<vtkCallbackCommand> observer_;
|
||||
bool refreshing_ = false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue