geopro/src/data/dto/DatasetChartDto.cpp

115 lines
6.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "dto/DatasetChartDto.hpp"
#include <cmath>
#include <QString>
#include <QtGlobal>
namespace geopro::data::dto {
using namespace geopro::core;
static double num(const QJsonValue& v, double def = 0.0) {
if (v.isDouble()) return v.toDouble();
if (v.isString()) { bool ok = false; double d = v.toString().toDouble(&ok); return ok ? d : def; }
return def;
}
Grid parseInversionGrid(const QJsonObject& data) {
const QJsonArray x = data.value("x").toArray();
const QJsonArray y = data.value("y").toArray();
const QJsonArray v = data.value("v").toArray(); // [ny][nx]
const int nx = x.size(), ny = y.size();
Grid g(nx < 1 ? 1 : nx, ny < 1 ? 1 : ny);
g.x.clear(); for (auto e : x) g.x.push_back(num(e));
g.y.clear(); for (auto e : y) g.y.push_back(num(e));
// 经纬度(每列 [nx]):供 CurtainActor 经 GeoLocalFrame 把每列摆到真实测线位置——
// 弯曲测线 → 曲面帘面(不解析则 lat/lon 空、退化成 y=0 平面。API 字段 lat/lon。
g.lat.clear(); for (auto e : data.value("lat").toArray()) g.lat.push_back(num(e));
g.lon.clear(); for (auto e : data.value("lon").toArray()) g.lon.push_back(num(e));
if (v.size() != ny) // 服务端 v 行数与 y 不符:下方越界处填 NaN记录便于排查非静默
qWarning("parseInversionGrid: v rows=%d != ny=%d (缺失行将填 NaN)", v.size(), ny);
for (int j = 0; j < ny; ++j) {
const QJsonArray row = v.at(j).toArray();
for (int i = 0; i < nx; ++i) {
const QJsonValue cell = row.at(i);
g.valueAt(i, j) = (cell.isNull() || cell.isUndefined()) ? std::nan("") : num(cell, std::nan(""));
}
}
g.vmin = num(data.value("vmin")); g.vmax = num(data.value("vmax"));
return g;
}
ScatterField parseScatterGraph(const QJsonObject& data) {
ScatterField s;
auto fill = [&](const char* key, std::vector<double>& dst) {
for (auto e : data.value(key).toArray()) dst.push_back(num(e)); };
fill("xlist", s.x); fill("ylist", s.y); fill("hlist", s.z); fill("vlist", s.v);
fill("projectXList", s.projX); fill("projectYList", s.projY);
return s;
}
ColorScale parseColorBar(const QJsonObject& data) {
ColorScale cs;
const QJsonObject props = data.value("properties").toObject();
// 整体透明度两级第二级properties.opacity缺省 1不透明
if (props.contains("opacity")) cs.setGlobalOpacity(props.value("opacity").toDouble(1.0));
const QJsonArray bar = props.value("colorBar").toArray();
for (auto e : bar) {
const QJsonArray pair = e.toArray();
if (pair.size() < 2) continue;
const double val = num(pair.at(0));
const std::string rgba = pair.at(1).toString().toStdString();
// API colorBar 颜色为混合格式hex(#RRGGBB) 与 CSS rgba(r,g,b,a),其中 a 是 01 浮点
// (实测 "rgba(0, 0, 170, 1)")。须用 Unit 标度a*255否则 a=1 被当字节 → alpha≈1 近透明。
cs.addStop(val, parseColor(rgba, AlphaScale::Unit));
}
return cs;
}
std::vector<Anomaly> parseDatasetAnomalies(const QJsonArray& arr) {
std::vector<Anomaly> out;
for (auto e : arr) {
const QJsonObject o = e.toObject();
Anomaly a;
a.id = o.value("id").toString().toStdString(); // 删除/更新/定位需要持久化 id
a.name = o.value("exceptionName").toString().toStdString();
a.typeName = o.value("exceptionTypeName").toString().toStdString();
a.exceptionTypeId = o.value("exceptionTypeId").toString().toStdString();
a.remark = o.value("remark").toString().toStdString();
a.createTime = o.value("createTime").toString().toStdString();
const int mt = o.value("exceptionMarkType").toInt(2); // 1=点 2=线 3=面 4=文字
a.markType = (mt >= 1 && mt <= 4) ? static_cast<AnomalyMarkType>(mt)
: AnomalyMarkType::Polyline; // 越界值兜底为线
const QJsonObject lg = o.value("legend").toObject();
a.lineColor = lg.value("polylineColor").toString("#000000").toStdString();
a.lineWidth = lg.value("polylineWidth").toDouble(1.0);
a.dashed = lg.value("polylineShape").toString() == "dash";
// 文字标注 customLegend详情只读展示用content/color/size/opacity。
const QJsonObject cl = o.value("customLegend").toObject();
if (!cl.isEmpty()) {
QString content = cl.value("content").toString();
if (content.isEmpty()) content = cl.value("text").toString();
a.textContent = content.toStdString();
a.textColor = cl.value("color").toString("#000000").toStdString();
a.textSize = cl.value("size").toInt(12);
a.textOpacity = cl.value("opacity").toDouble(1.0);
}
for (auto c : o.value("location").toObject().value("coordinate").toArray()) {
const QJsonObject p = c.toObject();
a.localPts.push_back(Vec2{p.value("x").toDouble(), p.value("y").toDouble()});
}
// 经纬度坐标对照原版latitudeLongitude.latLon[].{longitude,latitude})。
// 纯展示,不换算;空/缺失 → 详情坐标系下拉只给「图形坐标」(与原版 latLon.length===0 一致)。
for (auto c : o.value("latitudeLongitude").toObject().value("latLon").toArray()) {
const QJsonObject p = c.toObject();
a.lonLatPts.push_back(Vec2{p.value("longitude").toDouble(), p.value("latitude").toDouble()});
}
// 投影坐标对照原版geographicalCoordinates.coordinates[].{northCoord,eastCoord}
// 原版映射 x=northCoord、y=eastCoord
for (auto c : o.value("geographicalCoordinates").toObject().value("coordinates").toArray()) {
const QJsonObject p = c.toObject();
a.eastNorthPts.push_back(Vec2{p.value("northCoord").toDouble(), p.value("eastCoord").toDouble()});
}
out.push_back(std::move(a));
}
return out;
}
} // namespace geopro::data::dto