三维频谱marker
This commit is contained in:
@@ -9,10 +9,12 @@
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <numbers>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -800,7 +802,22 @@ void Datoviz_Visual_Backend::create_scene(
|
||||
throw std::runtime_error("failed to enable Datoviz item queries");
|
||||
wants_item_interaction = true;
|
||||
}
|
||||
visuals_.push_back({registration.identity, family, visual, 0});
|
||||
DvzText* coordinate_text{};
|
||||
if (family == Visual_Family::marker) {
|
||||
coordinate_text = dvz_text(panel_, 0);
|
||||
DvzTextPlacement placement = dvz_text_placement();
|
||||
placement.mode = DVZ_TEXT_PLACEMENT_DATA;
|
||||
placement.anchor = DVZ_SCENE_ANCHOR_DATA;
|
||||
placement.depth_test = false;
|
||||
DvzTextStyle style = dvz_text_style();
|
||||
style.renderer = DVZ_TEXT_RENDERER_MSDF_ATLAS;
|
||||
style.size_px = 12.0F;
|
||||
if (coordinate_text == nullptr ||
|
||||
dvz_text_set_placement(coordinate_text, &placement) != DVZ_OK ||
|
||||
dvz_text_set_style(coordinate_text, &style) != DVZ_OK)
|
||||
throw std::runtime_error("failed to create Datoviz marker coordinate labels");
|
||||
}
|
||||
visuals_.push_back({registration.identity, family, visual, coordinate_text, 0});
|
||||
}
|
||||
if (wants_item_interaction) {
|
||||
item_interaction_ = dvz_item_interaction(panel_, nullptr);
|
||||
@@ -1096,6 +1113,41 @@ void Datoviz_Visual_Backend::apply_visual(
|
||||
if (point.revision == target.applied_revision) return;
|
||||
const auto& data = *point.data;
|
||||
auto* visual = target.visual;
|
||||
if (target.coordinate_text != nullptr) {
|
||||
std::vector<std::string> strings;
|
||||
std::vector<DvzTextItem> items;
|
||||
if (point.visible) {
|
||||
strings.reserve(data.positions.size());
|
||||
items.reserve(data.positions.size());
|
||||
for (std::size_t index = 0; index < data.positions.size(); ++index) {
|
||||
if (index >= data.coordinate_label_visibility.size() ||
|
||||
!data.coordinate_label_visibility[index]) continue;
|
||||
const auto& source = data.positions[index];
|
||||
const auto& matrix = point.transform.values;
|
||||
const float x = matrix[0] * source[0] + matrix[1] * source[1] + matrix[2] * source[2] + matrix[3];
|
||||
const float y = matrix[4] * source[0] + matrix[5] * source[1] + matrix[6] * source[2] + matrix[7];
|
||||
const float z = matrix[8] * source[0] + matrix[9] * source[1] + matrix[10] * source[2] + matrix[11];
|
||||
std::ostringstream stream;
|
||||
stream << std::fixed << std::setprecision(3)
|
||||
<< "X " << x << " Y " << y << " Z " << z;
|
||||
strings.push_back(std::move(stream).str());
|
||||
DvzTextItem item{};
|
||||
item.struct_size = sizeof(DvzTextItem);
|
||||
item.position[0] = x; item.position[1] = y; item.position[2] = z;
|
||||
item.offset[0] = 10.0F; item.offset[1] = -10.0F;
|
||||
item.anchor[0] = 0.0F; item.anchor[1] = 1.0F;
|
||||
item.size_px = 12.0F;
|
||||
item.color = {235, 244, 255, 255};
|
||||
items.push_back(item);
|
||||
}
|
||||
}
|
||||
for (std::size_t index = 0; index < items.size(); ++index)
|
||||
items[index].string = strings[index].c_str();
|
||||
if (dvz_text_set_items(target.coordinate_text,
|
||||
items.empty() ? nullptr : items.data(),
|
||||
static_cast<std::uint32_t>(items.size())) != DVZ_OK)
|
||||
throw std::runtime_error("failed to upload Datoviz marker coordinate labels");
|
||||
}
|
||||
{
|
||||
mat4 transform{};
|
||||
for (std::size_t row = 0; row < 4; ++row)
|
||||
|
||||
@@ -56,6 +56,7 @@ private:
|
||||
Visual_Identity identity{}; /* Scene 注册的稳定身份。 */
|
||||
Visual_Family family{Visual_Family::point}; /* 原生 Visual 的确定 family。 */
|
||||
DvzVisual* visual{}; /* 由 Datoviz Scene 拥有。 */
|
||||
DvzText* coordinate_text{}; /* Marker 的数据坐标 XYZ 标注。 */
|
||||
std::uint64_t applied_revision{}; /* 此 Visual 已上传的 Prepare 版本。 */
|
||||
};
|
||||
void require_domain() const;
|
||||
|
||||
@@ -10,6 +10,7 @@ struct Prepared_Visual_Data {
|
||||
std::vector<std::array<float, 2>> sigma{}; /* Splat 椭圆标准差字段。 */
|
||||
std::vector<float> angles{}; /* Splat、Marker 旋转角字段。 */
|
||||
std::vector<std::uint32_t> shapes{}; /* Marker 形状字段。 */
|
||||
std::vector<std::uint8_t> coordinate_label_visibility{}; /* Marker XYZ 标签逐项开关。 */
|
||||
std::vector<std::array<float, 3>> secondary_positions{}; /* 线段终点或向量字段。 */
|
||||
std::vector<std::array<float, 3>> normals{}; /* Primitive、Mesh 法线字段。 */
|
||||
std::vector<std::array<float, 2>> extents{}; /* Image、Labels 尺寸字段。 */
|
||||
|
||||
@@ -26,6 +26,7 @@ struct Marker {
|
||||
Pixel_Distance diameter_px{12.0F}; /* 标记直径,单位为像素;必须为正数。 */
|
||||
Coordinate_3D angle{}; /* 标记旋转角,单位为弧度。 */
|
||||
Marker_Shape shape{Marker_Shape::disc}; /* 标记图形。 */
|
||||
bool coordinate_label_visible{false}; /* 是否显示由此 Marker 实际位置派生的 XYZ 标签。 */
|
||||
bool operator==(const Marker&) const = default;
|
||||
};
|
||||
struct Sphere {
|
||||
|
||||
@@ -9,7 +9,7 @@ inline void Splat_Spec::prepare(const std::vector<Item>& items, Prepared_Visual_
|
||||
inline bool Pixel_Spec::valid(const Item& item) noexcept { return finite(item.position) && finite(item.size_px) && item.size_px > 0.0F; }
|
||||
inline void Pixel_Spec::prepare(const std::vector<Item>& items, Prepared_Visual_Data& output) { reserve_common(output, items.size()); for (const auto& item : items) { output.positions.push_back({item.position.x, item.position.y, item.position.z}); output.colors.push_back(channels(item.color)); output.sizes.push_back(item.size_px); } }
|
||||
inline bool Marker_Spec::valid(const Item& item) noexcept { return finite(item.position) && finite(item.diameter_px) && item.diameter_px > 0.0F && finite(item.angle); }
|
||||
inline void Marker_Spec::prepare(const std::vector<Item>& items, Prepared_Visual_Data& output) { reserve_common(output, items.size()); output.angles.reserve(items.size()); output.shapes.reserve(items.size()); for (const auto& item : items) { output.positions.push_back({item.position.x, item.position.y, item.position.z}); output.colors.push_back(channels(item.color)); output.sizes.push_back(item.diameter_px); output.angles.push_back(item.angle); output.shapes.push_back(static_cast<std::uint32_t>(item.shape)); } }
|
||||
inline void Marker_Spec::prepare(const std::vector<Item>& items, Prepared_Visual_Data& output) { reserve_common(output, items.size()); output.angles.reserve(items.size()); output.shapes.reserve(items.size()); output.coordinate_label_visibility.reserve(items.size()); for (const auto& item : items) { output.positions.push_back({item.position.x, item.position.y, item.position.z}); output.colors.push_back(channels(item.color)); output.sizes.push_back(item.diameter_px); output.angles.push_back(item.angle); output.shapes.push_back(static_cast<std::uint32_t>(item.shape)); output.coordinate_label_visibility.push_back(item.coordinate_label_visible); } }
|
||||
inline bool Sphere_Spec::valid(const Item& item) noexcept { return finite(item.center) && finite(item.radius) && item.radius > 0.0F; }
|
||||
inline void Sphere_Spec::prepare(const std::vector<Item>& items, Prepared_Visual_Data& output) { reserve_common(output, items.size()); for (const auto& item : items) { output.positions.push_back({item.center.x, item.center.y, item.center.z}); output.colors.push_back(channels(item.color)); output.sizes.push_back(item.radius); } }
|
||||
inline bool Segment_Spec::valid(const Item& item) noexcept { return finite(item.start) && finite(item.end) && finite(item.width_px) && item.width_px > 0.0F; }
|
||||
|
||||
Reference in New Issue
Block a user