feat(data): DatasetChartDto 解析 inversion网格/散点/colorBar/异常
This commit is contained in:
parent
00c42f7a8d
commit
e1bbf39d6d
|
|
@ -4,6 +4,7 @@ add_library(geopro_data STATIC
|
|||
parse/SampleParsers.cpp
|
||||
repo/LocalSampleRepository.cpp
|
||||
dto/NavDto.cpp
|
||||
dto/DatasetChartDto.cpp
|
||||
api/ApiProjectRepository.cpp)
|
||||
target_include_directories(geopro_data PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(geopro_data PUBLIC geopro_core geopro_net Qt6::Core PRIVATE nlohmann_json::nlohmann_json)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
#include "dto/DatasetChartDto.hpp"
|
||||
#include <cmath>
|
||||
#include <QString>
|
||||
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));
|
||||
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 QJsonArray bar = data.value("properties").toObject().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();
|
||||
cs.addStop(val, parseColor(rgba, AlphaScale::Bit255));
|
||||
}
|
||||
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.name = o.value("exceptionName").toString().toStdString();
|
||||
a.typeName = o.value("exceptionTypeName").toString().toStdString();
|
||||
a.markType = static_cast<AnomalyMarkType>(o.value("exceptionMarkType").toInt(2));
|
||||
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";
|
||||
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()});
|
||||
}
|
||||
out.push_back(std::move(a));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
} // namespace geopro::data::dto
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include "model/Field.hpp"
|
||||
#include "model/ColorScale.hpp"
|
||||
#include "model/Anomaly.hpp"
|
||||
namespace geopro::data::dto {
|
||||
|
||||
// inversion/rows 的 data{ x,y,v[ny][nx],z,elevation,vmin,vmax } → Grid(v 缺省/非数→NaN)。
|
||||
geopro::core::Grid parseInversionGrid(const QJsonObject& data);
|
||||
// getErtRawDataScatterGraph 的 data{ xlist,ylist,hlist,vlist,projectXList,projectYList } → ScatterField。
|
||||
geopro::core::ScatterField parseScatterGraph(const QJsonObject& data);
|
||||
// colorGradation/getDetail 的 data.properties.colorBar [[值,"rgba()"],…] → ColorScale。
|
||||
geopro::core::ColorScale parseColorBar(const QJsonObject& data);
|
||||
// queryException 的 data 数组 → Anomaly[](location.coordinate / legend)。
|
||||
std::vector<geopro::core::Anomaly> parseDatasetAnomalies(const QJsonArray& arr);
|
||||
|
||||
} // namespace geopro::data::dto
|
||||
|
|
@ -37,6 +37,7 @@ target_link_libraries(geopro_tests PRIVATE geopro_core)
|
|||
target_sources(geopro_tests PRIVATE data/test_parsers.cpp)
|
||||
target_sources(geopro_tests PRIVATE data/test_local_repo.cpp)
|
||||
target_sources(geopro_tests PRIVATE data/test_nav_dto.cpp)
|
||||
target_sources(geopro_tests PRIVATE data/test_dataset_chart_dto.cpp)
|
||||
target_link_libraries(geopro_tests PRIVATE geopro_data)
|
||||
|
||||
# net 层:RSA 加密器。测试需直接用 OpenSSL 生成/解密密钥,故显式 find_package
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include "dto/DatasetChartDto.hpp"
|
||||
using namespace geopro::data::dto;
|
||||
|
||||
static QJsonObject obj(const char* json) {
|
||||
return QJsonDocument::fromJson(json).object();
|
||||
}
|
||||
|
||||
TEST(DatasetChartDto, ParsesInversionGrid) {
|
||||
auto d = obj(R"({"x":[0,1],"y":[0,1,2],"v":[[1,2],[3,4],[5,6]],"vmin":1,"vmax":6})");
|
||||
auto g = parseInversionGrid(d);
|
||||
EXPECT_EQ(g.nx(), 2); EXPECT_EQ(g.ny(), 3);
|
||||
EXPECT_DOUBLE_EQ(g.valueAt(1, 2), 6.0);
|
||||
EXPECT_DOUBLE_EQ(g.vmax, 6.0);
|
||||
}
|
||||
TEST(DatasetChartDto, ParsesColorBar) {
|
||||
// Use "json" delimiter to avoid raw-string termination by ")" inside rgba()
|
||||
const char* colorBarJson = "{\"properties\":{\"colorBar\":[[\"10\",\"rgba(0,0,255,255)\"],[\"20\",\"rgba(255,0,0,255)\"]]}}";
|
||||
auto d = obj(colorBarJson);
|
||||
auto cs = parseColorBar(d);
|
||||
auto stops = cs.stopValues();
|
||||
ASSERT_EQ(stops.size(), 2u);
|
||||
EXPECT_DOUBLE_EQ(stops[0], 10.0);
|
||||
auto c = cs.colorAt(12.0); // [10,20) -> blue
|
||||
EXPECT_GT(c.b, c.r);
|
||||
}
|
||||
TEST(DatasetChartDto, ParsesAnomalyPolyline) {
|
||||
auto arr = QJsonDocument::fromJson(
|
||||
R"([{"exceptionName":"A1","exceptionTypeName":"AnomalyZone","exceptionMarkType":2,
|
||||
"legend":{"polylineColor":"#0D0101","polylineWidth":4,"polylineShape":"dash"},
|
||||
"location":{"coordinate":[{"x":1,"y":2},{"x":3,"y":4}]}}])").array();
|
||||
auto v = parseDatasetAnomalies(arr);
|
||||
ASSERT_EQ(v.size(), 1u);
|
||||
EXPECT_EQ(v[0].name, "A1");
|
||||
EXPECT_EQ(static_cast<int>(v[0].markType), 2);
|
||||
ASSERT_EQ(v[0].localPts.size(), 2u);
|
||||
EXPECT_DOUBLE_EQ(v[0].localPts[1].x, 3.0);
|
||||
EXPECT_TRUE(v[0].dashed);
|
||||
}
|
||||
Loading…
Reference in New Issue