From 7f609130f9985a6121879617ca8ab5bb283bf39f Mon Sep 17 00:00:00 2001 From: hypf Date: Fri, 26 Jun 2026 15:03:54 +0800 Subject: [PATCH 01/13] =?UTF-8?q?feat(app)=EF=BC=9A=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=87=A0=E4=BD=95=E6=8B=BE=E5=8F=96=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Main.qml | 12 + app/Selector.qml | 4 + app/model/QModelQuery.cpp | 4 +- app/render/CMakeLists.txt | 3 + app/render/GeometryActor.cpp | 151 ++- app/render/GeometryActor.h | 12 +- app/render/GeometryActorManager.cpp | 10 +- app/render/GeometryActorManager.h | 4 +- app/render/GeometryActorSelectOp.cpp | 39 + app/render/GeometryActorSelectOp.h | 39 + app/render/GeometrySelectManager.cpp | 98 ++ app/render/GeometrySelectManager.h | 36 + app/render/GeometrySelectorHighlight.cpp | 883 ++++++++++++++++++ app/render/GeometrySelectorHighlight.h | 137 +++ app/render/MeshActorManager.h | 2 +- app/render/QRenderWindow.cpp | 58 +- app/render/QRenderWindow.h | 3 + app/render/QRenderWindowStyle.cpp | 51 +- app/render/QRenderWindowStyle.h | 8 + app/render/SelectManager.h | 2 +- app/render/test/CMakeLists.txt | 23 + app/render/test/TestCadShapePicker.cpp | 281 ++++++ .../test/TestSolidSelectorHighlight.cpp | 2 +- core/GeometryDataVtk.h | 4 +- model/data/GeometrySubshapeIndex.cpp | 17 + 25 files changed, 1837 insertions(+), 46 deletions(-) create mode 100644 app/render/GeometryActorSelectOp.cpp create mode 100644 app/render/GeometryActorSelectOp.h create mode 100644 app/render/GeometrySelectManager.cpp create mode 100644 app/render/GeometrySelectManager.h create mode 100644 app/render/GeometrySelectorHighlight.cpp create mode 100644 app/render/GeometrySelectorHighlight.h create mode 100644 app/render/test/TestCadShapePicker.cpp diff --git a/app/Main.qml b/app/Main.qml index 8e3bcf9..3b40fc9 100644 --- a/app/Main.qml +++ b/app/Main.qml @@ -287,6 +287,18 @@ ApplicationWindow { if(selectType === "体"){ myItem.setSelectMode("Solid") } + if(selectType === "几何点"){ + myItem.setSelectMode("GeometryVertex") + } + if(selectType === "几何边"){ + myItem.setSelectMode("GeometryEdge") + } + if(selectType === "几何面"){ + myItem.setSelectMode("GeometryFace") + } + if(selectType === "几何体"){ + myItem.setSelectMode("GeometrySolid") + } } function changeEnable(){} diff --git a/app/Selector.qml b/app/Selector.qml index 9eb75c4..32bf3d5 100644 --- a/app/Selector.qml +++ b/app/Selector.qml @@ -38,6 +38,10 @@ RowLayout { ListElement{text: "面"} ListElement{text: "体"} ListElement{text: "块"} + ListElement{text: "几何点"} + ListElement{text: "几何边"} + ListElement{text: "几何面"} + ListElement{text: "几何体"} } onCurrentTextChanged: comboBoxSelectionChanged() enabled: root.cur_model >= 0 diff --git a/app/model/QModelQuery.cpp b/app/model/QModelQuery.cpp index 8f754f3..e5cdda9 100644 --- a/app/model/QModelQuery.cpp +++ b/app/model/QModelQuery.cpp @@ -114,7 +114,7 @@ std::vector QModelQuery::getGeometryVtkData(Index model_id) if (!comp || !comp->geometry || !comp->geometry->rootShape) continue; - result.push_back(GeometryDataVtk { *comp->geometry->rootShape, comp->id }); + result.push_back(GeometryDataVtk { *comp->geometry->rootShape, comp->id, &comp->geometry->index }); } return result; @@ -126,7 +126,7 @@ std::optional QModelQuery::getGeometryVtkDataByComponent(Index if (!comp || !comp->geometry || !comp->geometry->rootShape) return std::nullopt; - return GeometryDataVtk { *comp->geometry->rootShape, comp->id }; + return GeometryDataVtk { *comp->geometry->rootShape, comp->id, &comp->geometry->index }; } diff --git a/app/render/CMakeLists.txt b/app/render/CMakeLists.txt index a4e3fb9..2e45a38 100644 --- a/app/render/CMakeLists.txt +++ b/app/render/CMakeLists.txt @@ -1,9 +1,12 @@ add_library(vtkPart STATIC MeshActor.cpp MeshActorSelectOp.cpp + GeometryActorSelectOp.cpp SelectorHighlight.cpp + GeometrySelectorHighlight.cpp QRenderWindowStyle.cpp SelectManager.cpp + GeometrySelectManager.cpp GeometryActor.cpp MeshActorManager.cpp GeometryActorManager.cpp diff --git a/app/render/GeometryActor.cpp b/app/render/GeometryActor.cpp index 0644132..72b8d0b 100644 --- a/app/render/GeometryActor.cpp +++ b/app/render/GeometryActor.cpp @@ -6,11 +6,23 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include GeometryActor::GeometryActor(vtkRenderer* renderer, GeometryRenderMode render_mode) { this->renderer_ = renderer; this->render_mode_ = render_mode; + this->edge_render = false; + this->visibility_ = true; } GeometryActor::~GeometryActor() @@ -30,41 +42,122 @@ bool GeometryActor::getIsEdgeRender() void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) { - this->geometry_data_ = std::make_unique(geometry_data); - IVtkOCC_Shape::Handle aShapeImpl = new IVtkOCC_Shape(geometry_data.shape); + OccShapeHandle aShapeImpl = new IVtkOCC_Shape(geometry_data.shape); + aShapeImpl->SetId(static_cast(geometry_data.component_id)); + this->occ_shape_ = aShapeImpl; vtkSmartPointer DS = vtkSmartPointer::New(); DS->SetShape(aShapeImpl); DS->Update(); - vtkPolyData* geometry_poly_data = DS->GetOutput(); + vtkPolyData* src = DS->GetOutput(); - // 分开 polys 和 lines - vtkNew line_only; - line_only->SetPoints(geometry_poly_data->GetPoints()); - line_only->SetLines(geometry_poly_data->GetLines()); + const vtkIdType nV = src->GetNumberOfVerts(); + const vtkIdType nL = src->GetNumberOfLines(); + const vtkIdType nP = src->GetNumberOfPolys(); - vtkNew poly_only; - poly_only->SetPoints(geometry_poly_data->GetPoints()); - poly_only->SetPolys(geometry_poly_data->GetPolys()); - poly_only->GetPointData()->SetNormals(geometry_poly_data->GetPointData()->GetNormals()); + spdlog::info("[GeometryActor] loadShape component={} verts={} lines={} polys={}", + geometry_data.component_id, (int)nV, (int)nL, (int)nP); + + auto ExtractCellRangeToPolyData = [](vtkPolyData* in, vtkIdType start, vtkIdType count) -> vtkSmartPointer { + vtkNew ids; + ids->SetNumberOfComponents(1); + ids->SetNumberOfValues(count); + for (vtkIdType i = 0; i < count; ++i) + ids->SetValue(i, start + i); + + vtkNew node; + node->SetFieldType(vtkSelectionNode::CELL); + node->SetContentType(vtkSelectionNode::INDICES); + node->SetSelectionList(ids); + + vtkNew sel; + sel->AddNode(node); + + vtkNew extract; + extract->SetInputData(0, in); + extract->SetInputData(1, sel); + extract->Update(); + + vtkNew geom; + geom->SetInputConnection(extract->GetOutputPort()); + geom->Update(); + + return vtkPolyData::SafeDownCast(geom->GetOutput()); + }; + + vtkSmartPointer line_only = ExtractCellRangeToPolyData(src, 0, nV + nL); + vtkSmartPointer poly_only = ExtractCellRangeToPolyData(src, nV + nL, nP); + + if (!line_only) + line_only = vtkSmartPointer::New(); + if (!poly_only) + poly_only = vtkSmartPointer::New(); + + auto EnsureCellRgbScalars = [](vtkPolyData* pd, const unsigned char rgb[3]) -> vtkUnsignedCharArray* { + if (!pd) + return nullptr; + vtkCellData* cd = pd->GetCellData(); + if (!cd) + return nullptr; + + vtkUnsignedCharArray* colors = vtkUnsignedCharArray::SafeDownCast(cd->GetScalars()); + if (!colors || colors->GetNumberOfComponents() != 3 || colors->GetNumberOfTuples() != pd->GetNumberOfCells()) { + vtkNew c; + c->SetName("CellColors"); + c->SetNumberOfComponents(3); + c->SetNumberOfTuples(pd->GetNumberOfCells()); + colors = c.GetPointer(); + cd->SetScalars(c); + } + + for (vtkIdType i = 0; i < pd->GetNumberOfCells(); ++i) + colors->SetTypedTuple(i, rgb); + + colors->Modified(); + pd->GetCellData()->Modified(); + pd->Modified(); + return colors; + }; + + unsigned char faceBase[3] = { 200, 200, 200 }; + if (this->poly_actor_ && this->poly_actor_->GetProperty()) { + double c[3]; + this->poly_actor_->GetProperty()->GetColor(c); + faceBase[0] = (unsigned char)std::clamp((int)std::lround(c[0] * 255.0), 0, 255); + faceBase[1] = (unsigned char)std::clamp((int)std::lround(c[1] * 255.0), 0, 255); + faceBase[2] = (unsigned char)std::clamp((int)std::lround(c[2] * 255.0), 0, 255); + } + + const unsigned char lineBase[3] = { 0, 0, 0 }; + + EnsureCellRgbScalars(poly_only, faceBase); + EnsureCellRgbScalars(line_only, lineBase); - // 渲染面(带光照) vtkNew poly_mapper; poly_mapper->SetInputData(poly_only); + poly_mapper->ScalarVisibilityOn(); + poly_mapper->SetScalarModeToUseCellData(); + poly_mapper->SetColorModeToDirectScalars(); this->poly_actor_->SetMapper(poly_mapper); this->renderer_->AddActor(this->poly_actor_); - // 渲染线(无光照) vtkNew line_mapper; line_mapper->SetInputData(line_only); + line_mapper->ScalarVisibilityOn(); + line_mapper->SetScalarModeToUseCellData(); + line_mapper->SetColorModeToDirectScalars(); line_mapper->SetRelativeCoincidentTopologyLineOffsetParameters(0, -0.1); this->line_actor_->SetMapper(line_mapper); - this->line_actor_->GetProperty()->LightingOff(); // 关键:关闭光照防止线变色 - this->line_actor_->GetProperty()->SetColor(0.0, 0.0, 0.0); + this->line_actor_->GetProperty()->LightingOff(); this->line_actor_->GetProperty()->SetLineWidth(2.0); - this->line_actor_->GetProperty()->RenderLinesAsTubesOn(); // 关键:线条抗锯齿 + this->line_actor_->GetProperty()->RenderLinesAsTubesOn(); + this->line_actor_->GetProperty()->SetPointSize(6.0); + this->renderer_->AddActor(this->line_actor_); + + spdlog::info("[GeometryActor] component={} actors added, face_cells={} line_cells={}", + geometry_data.component_id, (int)poly_only->GetNumberOfCells(), (int)line_only->GetNumberOfCells()); } void GeometryActor::deleteGeometryActor() @@ -84,7 +177,6 @@ void GeometryActor::setVisibility(bool visibility) void GeometryActor::setRenderMode(GeometryRenderMode render_mode) { - // 没用 } void GeometryActor::setRenderEdge(bool is_render) @@ -92,3 +184,28 @@ void GeometryActor::setRenderEdge(bool is_render) this->edge_render = is_render; this->line_actor_->SetVisibility(is_render && this->visibility_); } + +vtkActor* GeometryActor::polyActor() noexcept +{ + return poly_actor_.GetPointer(); +} + +const vtkActor* GeometryActor::polyActor() const noexcept +{ + return poly_actor_.GetPointer(); +} + +vtkActor* GeometryActor::lineActor() noexcept +{ + return line_actor_.GetPointer(); +} + +const vtkActor* GeometryActor::lineActor() const noexcept +{ + return line_actor_.GetPointer(); +} + +const OccShapeHandle& GeometryActor::getOccShape() const +{ + return occ_shape_; +} \ No newline at end of file diff --git a/app/render/GeometryActor.h b/app/render/GeometryActor.h index 4e79a08..1403aa5 100644 --- a/app/render/GeometryActor.h +++ b/app/render/GeometryActor.h @@ -6,6 +6,10 @@ #include #include +#include +#include +typedef Handle(IVtkOCC_Shape) OccShapeHandle; + class GeometryActor { public: @@ -21,13 +25,19 @@ public: void setRenderMode(GeometryRenderMode render_mode); void setRenderEdge(bool is_render); + vtkActor* polyActor() noexcept; + const vtkActor* polyActor() const noexcept; + vtkActor* lineActor() noexcept; + const vtkActor* lineActor() const noexcept; + const OccShapeHandle& getOccShape() const; + private: void deleteGeometryActor(); GeometryRenderMode render_mode_; bool edge_render; bool visibility_; - std::unique_ptr geometry_data_; + OccShapeHandle occ_shape_; vtkNew poly_actor_; vtkNew line_actor_; diff --git a/app/render/GeometryActorManager.cpp b/app/render/GeometryActorManager.cpp index 07f8621..62be2a0 100644 --- a/app/render/GeometryActorManager.cpp +++ b/app/render/GeometryActorManager.cpp @@ -16,15 +16,13 @@ void GeometryActorManager::bindRender(vtkRenderer* renderer) this->renderer_ = renderer; } -const GeometryActor* GeometryActorManager::getGeometryActor(Index component_id) +std::shared_ptr GeometryActorManager::getComponentActor(Index component_id) const { auto it = component_actors_.find(component_id); if (it != component_actors_.end()) { - return it->second.get(); - } else { - spdlog::error("GeometryActorManager getGeometryActor error"); - return nullptr; + return it->second; } + return nullptr; } GeometryRenderMode GeometryActorManager::getGeometryRenderMode(Index component_id) @@ -64,7 +62,7 @@ void GeometryActorManager::loadGeometry(const GeometryDataVtk& geometry_data) Index component_id = geometry_data.component_id; if (!component_actors_.count(component_id)) { - component_actors_[component_id] = std::make_unique(this->renderer_, GeometryRenderMode::Face); + component_actors_[component_id] = std::make_shared(this->renderer_, GeometryRenderMode::Face); } component_actors_[component_id]->loadShape(geometry_data); diff --git a/app/render/GeometryActorManager.h b/app/render/GeometryActorManager.h index 1185512..4a3588a 100644 --- a/app/render/GeometryActorManager.h +++ b/app/render/GeometryActorManager.h @@ -15,7 +15,7 @@ public: ~GeometryActorManager(); void bindRender(vtkRenderer* renderer); - const GeometryActor* getGeometryActor(Index component_id); + std::shared_ptr getComponentActor(Index component_id) const; GeometryRenderMode getGeometryRenderMode(Index component_id); bool getIsEdgeRender(Index component_id); bool hasComponent(Index component_id) const; @@ -28,7 +28,7 @@ public: void setRenderEdge(Index component_id, bool is_render); private: - std::unordered_map> component_actors_; + std::unordered_map> component_actors_; vtkRenderer* renderer_; }; diff --git a/app/render/GeometryActorSelectOp.cpp b/app/render/GeometryActorSelectOp.cpp new file mode 100644 index 0000000..8567b66 --- /dev/null +++ b/app/render/GeometryActorSelectOp.cpp @@ -0,0 +1,39 @@ +#include "GeometryActorSelectOp.h" +#include "GeometryActor.h" + +GeometryActorSelectOpFactory::GeometryActorSelectOpFactory() = default; +GeometryActorSelectOpFactory::GeometryActorSelectOpFactory(std::weak_ptr geometry_actor) + : geometry_actor_(geometry_actor) +{ +} + +std::optional GeometryActorSelectOpFactory::lock() +{ + if (auto geometry_actor = geometry_actor_.lock()) { + return { geometry_actor }; + } + return {}; +} + +GeometryActorSelectOp::GeometryActorSelectOp(std::shared_ptr geometry_actor) + : geometry_actor_(geometry_actor) +{ + if (!geometry_actor_) { + throw std::runtime_error("GeometryActorSelectOp: geometry_actor is nullptr"); + } +} + +vtkProp& GeometryActorSelectOp::getPolyActor() +{ + return *const_cast(geometry_actor_->polyActor()); +} + +vtkProp& GeometryActorSelectOp::getLineActor() +{ + return *const_cast(geometry_actor_->lineActor()); +} + +const OccShapeHandle& GeometryActorSelectOp::getOccShape() +{ + return geometry_actor_->getOccShape(); +} diff --git a/app/render/GeometryActorSelectOp.h b/app/render/GeometryActorSelectOp.h new file mode 100644 index 0000000..e8e5f45 --- /dev/null +++ b/app/render/GeometryActorSelectOp.h @@ -0,0 +1,39 @@ +#ifndef GEOMETRY_ACTOR_SELECT_OP_H +#define GEOMETRY_ACTOR_SELECT_OP_H +#include +#include +#include + +#include +#include +typedef Handle(IVtkOCC_Shape) OccShapeHandle; + +class GeometryActorSelectOp; +class GeometryActor; + +class GeometryActorSelectOpFactory { + friend GeometryActorSelectOp; + +public: + GeometryActorSelectOpFactory(); + GeometryActorSelectOpFactory(std::weak_ptr geometry_actor); + std::optional lock(); + +private: + std::weak_ptr geometry_actor_; +}; + +class GeometryActorSelectOp { + friend GeometryActorSelectOpFactory; + +public: + GeometryActorSelectOp(std::shared_ptr geometry_actor); + + vtkProp& getPolyActor(); + vtkProp& getLineActor(); + const OccShapeHandle& getOccShape(); + +private: + std::shared_ptr geometry_actor_; +}; +#endif // GEOMETRY_ACTOR_SELECT_OP_H diff --git a/app/render/GeometrySelectManager.cpp b/app/render/GeometrySelectManager.cpp new file mode 100644 index 0000000..3d6922a --- /dev/null +++ b/app/render/GeometrySelectManager.cpp @@ -0,0 +1,98 @@ +#include "GeometrySelectManager.h" +#include "GeometryActor.h" +#include +#include +#include + +void GeometrySelectManager::bindRenderer(vtkRenderer* renderer) +{ + this->renderer_ = renderer; + picker_ = vtkSmartPointer::New(); + picker_->SetRenderer(renderer); + picker_->SetAreaSelection(false); +} + +void GeometrySelectManager::select(double posx, double posy) +{ + if (this->selector_) { + this->selector_->select(posx, posy); + } +} + +void GeometrySelectManager::setSelectActor(std::weak_ptr geom_actor, const GeometrySubshapeIndex* geom_index) +{ + this->cur_geom_actor_ = GeometryActorSelectOpFactory { geom_actor }; + this->current_geom_index_ = geom_index; + if (this->selector_) { + this->selector_->clear(); + this->selector_->setPicker(picker_); + this->selector_->setCurGeomActor(*cur_geom_actor_); + this->selector_->setGeometryIndex(current_geom_index_); + } +} + +void GeometrySelectManager::setSelectMode(SelectMode select_mode) +{ + this->clearSelection(); + this->select_mode_ = select_mode; + if (this->select_mode_ == SelectMode::Vertex) { + this->selector_ = std::make_unique(this->renderer_); + } else if (this->select_mode_ == SelectMode::Face) { + this->selector_ = std::make_unique(this->renderer_); + } else if (this->select_mode_ == SelectMode::Edge) { + this->selector_ = std::make_unique(this->renderer_); + } else if (this->select_mode_ == SelectMode::Solid) { + this->selector_ = std::make_unique(this->renderer_); + } else { + assert(this->select_mode_ == SelectMode::None); + this->selector_ = nullptr; + } + + if (this->selector_ && this->cur_geom_actor_) { + this->selector_->setPicker(picker_); + this->selector_->setCurGeomActor(*cur_geom_actor_); + this->selector_->setGeometryIndex(current_geom_index_); + } +} + +void GeometrySelectManager::clearSelection() +{ + if (this->selector_) { + this->selector_->clear(); + } + if (this->renderer_ && this->renderer_->GetRenderWindow()) + this->renderer_->GetRenderWindow()->Render(); +} + +std::unique_ptr GeometrySelectManager::getSelection() +{ + std::unique_ptr selection = std::make_unique(); + + if (this->select_mode_ == SelectMode::Vertex) { + for (const auto& id : this->selector_->get().ids) { + selection->ids.push_back(id); + } + selection->type = ElementEnum::Vertex; + } else if (this->select_mode_ == SelectMode::Face) { + for (const auto& id : this->selector_->get().ids) { + selection->ids.push_back(id); + } + selection->type = ElementEnum::Face; + } else if (this->select_mode_ == SelectMode::Edge) { + for (const auto& id : this->selector_->get().ids) { + selection->ids.push_back(id); + } + selection->type = ElementEnum::Edge; + } else if (this->select_mode_ == SelectMode::Solid) { + for (const auto& id : this->selector_->get().ids) { + selection->ids.push_back(id); + } + selection->type = ElementEnum::Solid; + } else { + if (this->selector_) + this->selector_->clear(); + return nullptr; + } + + return selection; +} diff --git a/app/render/GeometrySelectManager.h b/app/render/GeometrySelectManager.h new file mode 100644 index 0000000..c099e80 --- /dev/null +++ b/app/render/GeometrySelectManager.h @@ -0,0 +1,36 @@ +#ifndef GEOMETRY_SELECT_MANAGER_H +#define GEOMETRY_SELECT_MANAGER_H +#include "GeometrySelectorHighlight.h" +#include "GeometryActorSelectOp.h" +#include "Core.h" + +#include +#include +#include +#include +#include + +class vtkRenderer; +struct GeometrySubshapeIndex; + +class GeometrySelectManager { +public: + void bindRenderer(vtkRenderer* renderer); + void select(double posx, double posy); + + void setSelectActor(std::weak_ptr geom_actor, const GeometrySubshapeIndex* geom_index = nullptr); + void setSelectMode(SelectMode select_mode); + void clearSelection(); + std::unique_ptr getSelection(); + +private: + std::optional cur_geom_actor_ {}; + const GeometrySubshapeIndex* current_geom_index_ { nullptr }; + SelectMode select_mode_; + vtkNew selection_actor_; + vtkNew selection_mapper_; + vtkSmartPointer picker_; + vtkRenderer* renderer_; + std::unique_ptr selector_; +}; +#endif // GEOMETRY_SELECT_MANAGER_H diff --git a/app/render/GeometrySelectorHighlight.cpp b/app/render/GeometrySelectorHighlight.cpp new file mode 100644 index 0000000..5b0d00b --- /dev/null +++ b/app/render/GeometrySelectorHighlight.cpp @@ -0,0 +1,883 @@ +#include "GeometrySelectorHighlight.h" +#include "GeometryActor.h" +#include "GeometrySubshapeIndex.h" +#include "Core.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +static constexpr IVtk_SelectionMode kSelVertex = SM_Vertex; +static constexpr IVtk_SelectionMode kSelEdge = SM_Edge; +static constexpr IVtk_SelectionMode kSelFace = SM_Face; +static constexpr IVtk_SelectionMode kSelSolid = SM_Shape; + +static int toleranceForMode(const SelectMode m) +{ + if (m == SelectMode::Vertex) + return 40; + if (m == SelectMode::Edge) + return 25; + if (m == SelectMode::Solid) + return 8; + return 8; +} + +static bool firstId(const NCollection_List& list, IVtk_IdType& outId) +{ + if (list.IsEmpty()) + return false; + outId = list.First(); + return true; +} + +static std::optional mapSubshapeToGeomId(const OccShapeHandle& occShape, + const GeometrySubshapeIndex& geomIndex, + TopAbs_ShapeEnum wantType, + IVtk_IdType subId, + ElementEnum::Type& outType) +{ + if (occShape.IsNull()) + return std::nullopt; + + const TopoDS_Shape& sub = occShape->GetSubShape(subId); + if (sub.IsNull()) + return std::nullopt; + + const int ti = GeometrySubshapeIndex::typeIndex(wantType); + if (ti < 0) + return std::nullopt; + + const int localTypeId = geomIndex.type_maps[(size_t)ti].FindIndex(sub); + if (localTypeId <= 0) + return std::nullopt; + + if (wantType == TopAbs_FACE) { + GeomFaceId gid = geomIndex.faceGlobalId(localTypeId); + if (gid == kInvalidGeomFaceId) + return std::nullopt; + outType = ElementEnum::Face; + return (Index)gid; + } else if (wantType == TopAbs_EDGE) { + GeomEdgeId gid = geomIndex.edgeGlobalId(localTypeId); + if (gid == kInvalidGeomEdgeId) + return std::nullopt; + outType = ElementEnum::Edge; + return (Index)gid; + } else if (wantType == TopAbs_VERTEX) { + GeomVertexId gid = geomIndex.vertexGlobalId(localTypeId); + if (gid == kInvalidGeomVertexId) + return std::nullopt; + outType = ElementEnum::Vertex; + return (Index)gid; + } else if (wantType == TopAbs_SOLID) { + GeomSolidId gid = geomIndex.solidGlobalId(localTypeId); + if (gid == kInvalidGeomSolidId) + return std::nullopt; + outType = ElementEnum::Solid; + return (Index)gid; + } + return std::nullopt; +} + +static vtkPolyData* actorPoly(vtkActor* a) +{ + if (!a) + return nullptr; + auto* m = vtkPolyDataMapper::SafeDownCast(a->GetMapper()); + if (!m) + return nullptr; + return m->GetInput(); +} + +static vtkUnsignedCharArray* cellColors(vtkPolyData* pd) +{ + if (!pd) + return nullptr; + return vtkUnsignedCharArray::SafeDownCast(pd->GetCellData()->GetScalars()); +} + +static void readBaseRgb(vtkUnsignedCharArray* colors, unsigned char outBase[3], const unsigned char fallback[3]) +{ + outBase[0] = fallback[0]; + outBase[1] = fallback[1]; + outBase[2] = fallback[2]; + if (!colors || colors->GetNumberOfTuples() <= 0 || colors->GetNumberOfComponents() != 3) + return; + unsigned char rgb[3] { fallback[0], fallback[1], fallback[2] }; + colors->GetTypedTuple(0, rgb); + outBase[0] = rgb[0]; + outBase[1] = rgb[1]; + outBase[2] = rgb[2]; +} + +static vtkDataArray* detectSubIdArrayByValue(vtkPolyData* pd, IVtk_IdType pickedSubId, const char* tag) +{ + if (!pd) + return nullptr; + vtkCellData* cd = pd->GetCellData(); + if (!cd) + return nullptr; + + vtkDataArray* best = nullptr; + vtkIdType bestHits = 0; + const vtkIdType nCells = pd->GetNumberOfCells(); + + for (int i = 0; i < cd->GetNumberOfArrays(); ++i) { + vtkDataArray* a = cd->GetArray(i); + if (!a) + continue; + if (a->GetNumberOfComponents() != 1) + continue; + if (a->GetNumberOfTuples() != nCells) + continue; + + vtkIdType hits = 0; + for (vtkIdType c = 0; c < nCells; ++c) { + if ((IVtk_IdType)a->GetTuple1(c) == pickedSubId) + ++hits; + } + if (hits > bestHits) { + bestHits = hits; + best = a; + } + } + + if (best && bestHits > 0) { + spdlog::info("[{}] detected subId array='{}' hits={}/{} for subId={}", + tag, (best->GetName() ? best->GetName() : "(null)"), (int)bestHits, (int)nCells, (int)pickedSubId); + return best; + } + + spdlog::warn("[{}] cannot detect subId array by picked subId={}. Dump arrays:", tag, (int)pickedSubId); + for (int i = 0; i < cd->GetNumberOfArrays(); ++i) { + vtkDataArray* a = cd->GetArray(i); + if (!a) + continue; + spdlog::warn(" CellData[{}] name='{}' comps={} tuples={} type={}", + i, (a->GetName() ? a->GetName() : "(null)"), + a->GetNumberOfComponents(), (int)a->GetNumberOfTuples(), a->GetDataType()); + } + return nullptr; +} + +static void recolorBySelectedSubIds(vtkPolyData* pd, + vtkDataArray* subIdArr, + vtkUnsignedCharArray* colors, + const std::unordered_map& selected, + const unsigned char base[3]) +{ + if (!pd || !subIdArr || !colors) + return; + + const vtkIdType n = pd->GetNumberOfCells(); + for (vtkIdType c = 0; c < n; ++c) { + const IVtk_IdType sid = (IVtk_IdType)subIdArr->GetTuple1(c); + unsigned char rgb[3] { base[0], base[1], base[2] }; + if (selected.count(sid)) { + rgb[0] = 255; + rgb[1] = 0; + rgb[2] = 0; + } + colors->SetTypedTuple(c, rgb); + } + + colors->Modified(); + pd->GetCellData()->Modified(); + pd->Modified(); +} + +static void resetColorsToBase(vtkPolyData* pd, vtkUnsignedCharArray* colors, const unsigned char base[3]) +{ + if (!pd || !colors) + return; + const vtkIdType n = pd->GetNumberOfCells(); + for (vtkIdType c = 0; c < n; ++c) + colors->SetTypedTuple(c, base); + + colors->Modified(); + pd->GetCellData()->Modified(); + pd->Modified(); +} + +struct GeomTargetData { + vtkActor* polyActor = nullptr; + vtkActor* lineActor = nullptr; + OccShapeHandle occShape; + + bool valid() const { return !occShape.IsNull(); } +}; + +static GeomTargetData getTargetData(GeometryActorSelectOpFactory& factory) +{ + GeomTargetData d; + auto op = factory.lock(); + if (!op) + return d; + d.polyActor = dynamic_cast(&op->getPolyActor()); + d.lineActor = dynamic_cast(&op->getLineActor()); + d.occShape = op->getOccShape(); + return d; +} + +// ─── Face ────────────────────────────────────────────── + +GeometryFaceSelectorHighlight::GeometryFaceSelectorHighlight(vtkRenderer* renderer) + : renderer_(renderer) +{ +} + +GeometryFaceSelectorHighlight::~GeometryFaceSelectorHighlight() { clear(); } + +void GeometryFaceSelectorHighlight::clear() +{ + selections_.clear(); + face_sub_id_arr_ = nullptr; + + auto op = geom_actor_.lock(); + if (op) { + auto* polyActor = dynamic_cast(&op->getPolyActor()); + vtkPolyData* pd = actorPoly(polyActor); + vtkUnsignedCharArray* colors = cellColors(pd); + if (pd && colors) + resetColorsToBase(pd, colors, face_base_); + } +} + +GeometrySelectionVtk GeometryFaceSelectorHighlight::get() const +{ + GeometrySelectionVtk s; + s.type = ElementEnum::Face; + s.component_id = -1; + for (const auto& [subId, geomId] : selections_) { + s.ids.push_back(geomId); + } + return s; +} + +void GeometryFaceSelectorHighlight::ensureTargetInit() +{ + if (target_initialized_) + return; + auto op = geom_actor_.lock(); + if (!op) + return; + auto* polyActor = dynamic_cast(&op->getPolyActor()); + vtkPolyData* pd = actorPoly(polyActor); + vtkUnsignedCharArray* colors = cellColors(pd); + const unsigned char fallback[3] = { 200, 200, 200 }; + readBaseRgb(colors, face_base_, fallback); + if (!pd || !colors) { + spdlog::warn("Face actor has no polydata or no CellData->Scalars. " + "Need GeometryActor::loadShape to create CellColors scalars."); + } + target_initialized_ = true; +} + +void GeometryFaceSelectorHighlight::select(double posx, double posy) +{ + auto target = getTargetData(geom_actor_); + if (!target.polyActor || !target.valid() || !geom_index_) + return; + + ensureTargetInit(); + + const int n = picker_->Pick(posx, posy, 0.0, renderer_); + if (n <= 0) + return; + + IVtk_IdType shapeId = -1; + if (!firstId(picker_->GetPickedShapesIds(false), shapeId)) + return; + + IVtk_IdType subId = -1; + if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) + return; + + ElementEnum::Type elemType = ElementEnum::None; + auto geomId = mapSubshapeToGeomId(target.occShape, *geom_index_, TopAbs_FACE, subId, elemType); + if (!geomId) + return; + + auto [it, inserted] = selections_.insert_or_assign(subId, *geomId); + if (!inserted) + selections_.erase(it); + + vtkPolyData* pd = actorPoly(target.polyActor); + if (!face_sub_id_arr_ && pd) + face_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "FacePd"); + + applyHighlight(); +} + +void GeometryFaceSelectorHighlight::applyHighlight() +{ + auto target = getTargetData(geom_actor_); + vtkPolyData* pd = actorPoly(target.polyActor); + vtkUnsignedCharArray* colors = cellColors(pd); + + if (!pd || !colors || !face_sub_id_arr_) + return; + + recolorBySelectedSubIds(pd, face_sub_id_arr_, colors, selections_, face_base_); + + if (renderer_ && renderer_->GetRenderWindow()) + renderer_->GetRenderWindow()->Render(); +} + +void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) +{ + clear(); + geom_actor_ = std::move(geom_actor); + target_initialized_ = false; + configurePicker(); +} + +void GeometryFaceSelectorHighlight::setGeometryIndex(const GeometrySubshapeIndex* idx) +{ + geom_index_ = idx; +} + +void GeometryFaceSelectorHighlight::configurePicker() +{ + auto target = getTargetData(geom_actor_); + if (!target.polyActor || !target.valid()) + return; + + picker_->PickFromListOn(); + picker_->InitializePickList(); + picker_->AddPickList(target.polyActor); + + picker_->SetPixelTolerance(toleranceForMode(SelectMode::Face)); + + picker_->SetSelectionMode(target.occShape, kSelFace, false); + picker_->SetSelectionMode(target.occShape, kSelEdge, false); + picker_->SetSelectionMode(target.occShape, kSelVertex, false); + picker_->SetSelectionMode(target.occShape, kSelFace, true); + + picker_->SetSelectionMode(target.polyActor, kSelFace, true); + picker_->SetSelectionMode(target.polyActor, kSelEdge, false); + picker_->SetSelectionMode(target.polyActor, kSelVertex, false); + + if (target.lineActor) { + picker_->SetSelectionMode(target.lineActor, kSelFace, false); + picker_->SetSelectionMode(target.lineActor, kSelEdge, false); + picker_->SetSelectionMode(target.lineActor, kSelVertex, false); + } +} + +// ─── Edge ────────────────────────────────────────────── + +GeometryEdgeSelectorHighlight::GeometryEdgeSelectorHighlight(vtkRenderer* renderer) + : renderer_(renderer) +{ +} + +GeometryEdgeSelectorHighlight::~GeometryEdgeSelectorHighlight() { clear(); } + +void GeometryEdgeSelectorHighlight::clear() +{ + selections_.clear(); + line_sub_id_arr_ = nullptr; + + auto op = geom_actor_.lock(); + if (op) { + auto* lineActor = dynamic_cast(&op->getLineActor()); + vtkPolyData* pd = actorPoly(lineActor); + vtkUnsignedCharArray* colors = cellColors(pd); + if (pd && colors) + resetColorsToBase(pd, colors, line_base_); + } +} + +GeometrySelectionVtk GeometryEdgeSelectorHighlight::get() const +{ + GeometrySelectionVtk s; + s.type = ElementEnum::Edge; + s.component_id = -1; + for (const auto& [subId, geomId] : selections_) { + s.ids.push_back(geomId); + } + return s; +} + +void GeometryEdgeSelectorHighlight::ensureTargetInit() +{ + if (target_initialized_) + return; + auto op = geom_actor_.lock(); + if (!op) + return; + auto* lineActor = dynamic_cast(&op->getLineActor()); + vtkPolyData* pd = actorPoly(lineActor); + vtkUnsignedCharArray* colors = cellColors(pd); + const unsigned char fallback[3] = { 0, 0, 0 }; + readBaseRgb(colors, line_base_, fallback); + if (!pd || !colors) { + spdlog::warn("Line actor has no polydata or no CellData->Scalars. " + "Need GeometryActor::loadShape to create CellColors scalars."); + } + target_initialized_ = true; +} + +void GeometryEdgeSelectorHighlight::select(double posx, double posy) +{ + auto target = getTargetData(geom_actor_); + if (!target.lineActor || !target.valid() || !geom_index_) + return; + + ensureTargetInit(); + + const int n = picker_->Pick(posx, posy, 0.0, renderer_); + if (n <= 0) + return; + + IVtk_IdType shapeId = -1; + if (!firstId(picker_->GetPickedShapesIds(false), shapeId)) + return; + + IVtk_IdType subId = -1; + if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) + return; + + ElementEnum::Type elemType = ElementEnum::None; + auto geomId = mapSubshapeToGeomId(target.occShape, *geom_index_, TopAbs_EDGE, subId, elemType); + if (!geomId) + return; + + auto [it, inserted] = selections_.insert_or_assign(subId, *geomId); + if (!inserted) + selections_.erase(it); + + vtkPolyData* pd = actorPoly(target.lineActor); + if (!line_sub_id_arr_ && pd) + line_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "LinePd"); + + applyHighlight(); +} + +void GeometryEdgeSelectorHighlight::applyHighlight() +{ + auto target = getTargetData(geom_actor_); + vtkPolyData* pd = actorPoly(target.lineActor); + vtkUnsignedCharArray* colors = cellColors(pd); + + if (!pd || !colors || !line_sub_id_arr_) + return; + + recolorBySelectedSubIds(pd, line_sub_id_arr_, colors, selections_, line_base_); + + if (renderer_ && renderer_->GetRenderWindow()) + renderer_->GetRenderWindow()->Render(); +} + +void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) +{ + clear(); + geom_actor_ = std::move(geom_actor); + target_initialized_ = false; + configurePicker(); +} + +void GeometryEdgeSelectorHighlight::setGeometryIndex(const GeometrySubshapeIndex* idx) +{ + geom_index_ = idx; +} + +void GeometryEdgeSelectorHighlight::configurePicker() +{ + auto target = getTargetData(geom_actor_); + if (!target.lineActor || !target.valid()) + return; + + picker_->PickFromListOn(); + picker_->InitializePickList(); + picker_->AddPickList(target.lineActor); + if (target.polyActor) + picker_->AddPickList(target.polyActor); + + picker_->SetPixelTolerance(toleranceForMode(SelectMode::Edge)); + + picker_->SetSelectionMode(target.occShape, kSelFace, false); + picker_->SetSelectionMode(target.occShape, kSelEdge, false); + picker_->SetSelectionMode(target.occShape, kSelVertex, false); + picker_->SetSelectionMode(target.occShape, kSelEdge, true); + + if (target.polyActor) { + picker_->SetSelectionMode(target.polyActor, kSelFace, false); + picker_->SetSelectionMode(target.polyActor, kSelEdge, false); + picker_->SetSelectionMode(target.polyActor, kSelVertex, false); + } + + picker_->SetSelectionMode(target.lineActor, kSelEdge, true); + picker_->SetSelectionMode(target.lineActor, kSelVertex, false); + picker_->SetSelectionMode(target.lineActor, kSelFace, false); +} + +// ─── Vertex ──────────────────────────────────────────── + +GeometryVertexSelectorHighlight::GeometryVertexSelectorHighlight(vtkRenderer* renderer) + : renderer_(renderer) +{ +} + +GeometryVertexSelectorHighlight::~GeometryVertexSelectorHighlight() { clear(); } + +void GeometryVertexSelectorHighlight::clear() +{ + selections_.clear(); + line_sub_id_arr_ = nullptr; + + auto op = geom_actor_.lock(); + if (op) { + auto* lineActor = dynamic_cast(&op->getLineActor()); + vtkPolyData* pd = actorPoly(lineActor); + vtkUnsignedCharArray* colors = cellColors(pd); + if (pd && colors) + resetColorsToBase(pd, colors, line_base_); + } +} + +GeometrySelectionVtk GeometryVertexSelectorHighlight::get() const +{ + GeometrySelectionVtk s; + s.type = ElementEnum::Vertex; + s.component_id = -1; + for (const auto& [subId, geomId] : selections_) { + s.ids.push_back(geomId); + } + return s; +} + +void GeometryVertexSelectorHighlight::ensureTargetInit() +{ + if (target_initialized_) + return; + auto op = geom_actor_.lock(); + if (!op) + return; + auto* lineActor = dynamic_cast(&op->getLineActor()); + vtkPolyData* pd = actorPoly(lineActor); + vtkUnsignedCharArray* colors = cellColors(pd); + const unsigned char fallback[3] = { 0, 0, 0 }; + readBaseRgb(colors, line_base_, fallback); + if (!pd || !colors) { + spdlog::warn("Line actor has no polydata or no CellData->Scalars. " + "Need GeometryActor::loadShape to create CellColors scalars."); + } + target_initialized_ = true; +} + +void GeometryVertexSelectorHighlight::select(double posx, double posy) +{ + auto target = getTargetData(geom_actor_); + if (!target.lineActor || !target.valid() || !geom_index_) + return; + + ensureTargetInit(); + + const int n = picker_->Pick(posx, posy, 0.0, renderer_); + if (n <= 0) + return; + + IVtk_IdType shapeId = -1; + if (!firstId(picker_->GetPickedShapesIds(false), shapeId)) + return; + + IVtk_IdType subId = -1; + if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) + return; + + ElementEnum::Type elemType = ElementEnum::None; + auto geomId = mapSubshapeToGeomId(target.occShape, *geom_index_, TopAbs_VERTEX, subId, elemType); + if (!geomId) + return; + + auto [it, inserted] = selections_.insert_or_assign(subId, *geomId); + if (!inserted) + selections_.erase(it); + + vtkPolyData* pd = actorPoly(target.lineActor); + if (!line_sub_id_arr_ && pd) + line_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "LinePd"); + + applyHighlight(); +} + +void GeometryVertexSelectorHighlight::applyHighlight() +{ + auto target = getTargetData(geom_actor_); + vtkPolyData* pd = actorPoly(target.lineActor); + vtkUnsignedCharArray* colors = cellColors(pd); + + if (!pd || !colors || !line_sub_id_arr_) + return; + + recolorBySelectedSubIds(pd, line_sub_id_arr_, colors, selections_, line_base_); + + if (renderer_ && renderer_->GetRenderWindow()) + renderer_->GetRenderWindow()->Render(); +} + +void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) +{ + clear(); + geom_actor_ = std::move(geom_actor); + target_initialized_ = false; + configurePicker(); +} + +void GeometryVertexSelectorHighlight::setGeometryIndex(const GeometrySubshapeIndex* idx) +{ + geom_index_ = idx; +} + +void GeometryVertexSelectorHighlight::configurePicker() +{ + auto target = getTargetData(geom_actor_); + if (!target.lineActor || !target.valid()) + return; + + picker_->PickFromListOn(); + picker_->InitializePickList(); + picker_->AddPickList(target.lineActor); + if (target.polyActor) + picker_->AddPickList(target.polyActor); + + picker_->SetPixelTolerance(toleranceForMode(SelectMode::Vertex)); + + picker_->SetSelectionMode(target.occShape, kSelFace, false); + picker_->SetSelectionMode(target.occShape, kSelEdge, false); + picker_->SetSelectionMode(target.occShape, kSelVertex, false); + picker_->SetSelectionMode(target.occShape, kSelVertex, true); + + if (target.polyActor) { + picker_->SetSelectionMode(target.polyActor, kSelFace, false); + picker_->SetSelectionMode(target.polyActor, kSelEdge, false); + picker_->SetSelectionMode(target.polyActor, kSelVertex, false); + } + + picker_->SetSelectionMode(target.lineActor, kSelVertex, true); + picker_->SetSelectionMode(target.lineActor, kSelEdge, false); + picker_->SetSelectionMode(target.lineActor, kSelFace, false); +} + +// ─── Solid ───────────────────────────────────────────── + +GeometrySolidSelectorHighlight::GeometrySolidSelectorHighlight(vtkRenderer* renderer) + : renderer_(renderer) +{ +} + +GeometrySolidSelectorHighlight::~GeometrySolidSelectorHighlight() { clear(); } + +void GeometrySolidSelectorHighlight::clear() +{ + selections_.clear(); + highlighted_face_ids_.clear(); + face_sub_id_arr_ = nullptr; + + auto op = geom_actor_.lock(); + if (op) { + auto* polyActor = dynamic_cast(&op->getPolyActor()); + vtkPolyData* pd = actorPoly(polyActor); + vtkUnsignedCharArray* colors = cellColors(pd); + if (pd && colors) + resetColorsToBase(pd, colors, face_base_); + } +} + +GeometrySelectionVtk GeometrySolidSelectorHighlight::get() const +{ + GeometrySelectionVtk s; + s.type = ElementEnum::Solid; + s.component_id = -1; + for (const auto& [subId, geomId] : selections_) { + s.ids.push_back(geomId); + } + return s; +} + +void GeometrySolidSelectorHighlight::ensureTargetInit() +{ + if (target_initialized_) + return; + auto op = geom_actor_.lock(); + if (!op) + return; + auto* polyActor = dynamic_cast(&op->getPolyActor()); + vtkPolyData* pd = actorPoly(polyActor); + vtkUnsignedCharArray* colors = cellColors(pd); + const unsigned char fallback[3] = { 200, 200, 200 }; + readBaseRgb(colors, face_base_, fallback); + if (!pd || !colors) { + spdlog::warn("Solid actor has no polydata or no CellData->Scalars. " + "Need GeometryActor::loadShape to create CellColors scalars."); + } + target_initialized_ = true; +} + +void GeometrySolidSelectorHighlight::select(double posx, double posy) +{ + auto target = getTargetData(geom_actor_); + if (!target.polyActor || !target.valid() || !geom_index_) + return; + + ensureTargetInit(); + + const int n = picker_->Pick(posx, posy, 0.0, renderer_); + if (n <= 0) + return; + + IVtk_IdType shapeId = -1; + if (!firstId(picker_->GetPickedShapesIds(false), shapeId)) + return; + + IVtk_IdType subId = -1; + if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) + return; + + const TopoDS_Shape& pickedSub = target.occShape->GetSubShape(subId); + if (pickedSub.IsNull()) + return; + + TopoDS_Shape solidShape; + if (pickedSub.ShapeType() == TopAbs_SOLID) { + solidShape = pickedSub; + } else { + const int solidTi = GeometrySubshapeIndex::typeIndex(TopAbs_SOLID); + const int nSolids = geom_index_->type_maps[solidTi].Extent(); + for (int localId = 1; localId <= nSolids; ++localId) { + const TopoDS_Shape& solid = geom_index_->type_maps[solidTi].FindKey(localId); + for (TopExp_Explorer exp(solid, TopAbs_FACE); exp.More(); exp.Next()) { + if (exp.Current().IsSame(pickedSub)) { + solidShape = solid; + break; + } + } + if (!solidShape.IsNull()) + break; + } + if (solidShape.IsNull()) + return; + } + + const int solidTi = GeometrySubshapeIndex::typeIndex(TopAbs_SOLID); + const int localTypeId = geom_index_->type_maps[solidTi].FindIndex(solidShape); + if (localTypeId <= 0) + return; + + GeomSolidId gid = geom_index_->solidGlobalId(localTypeId); + if (gid == kInvalidGeomSolidId) + return; + + auto [it, inserted] = selections_.insert_or_assign((IVtk_IdType)gid, (Index)gid); + if (!inserted) { + selections_.erase(it); + } + + for (TopExp_Explorer expF(solidShape, TopAbs_FACE); expF.More(); expF.Next()) { + const TopoDS_Shape& face = expF.Current(); + IVtk_IdType faceSubId = target.occShape->GetSubShapeId(face); + if (faceSubId >= 0) { + if (!inserted) + highlighted_face_ids_.erase(faceSubId); + else + highlighted_face_ids_.insert(faceSubId); + } + } + + vtkPolyData* pd = actorPoly(target.polyActor); + if (!face_sub_id_arr_ && pd) + face_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "SolidPd"); + + applyHighlight(); +} + +void GeometrySolidSelectorHighlight::applyHighlight() +{ + auto target = getTargetData(geom_actor_); + vtkPolyData* pd = actorPoly(target.polyActor); + vtkUnsignedCharArray* colors = cellColors(pd); + + if (!pd || !colors || !face_sub_id_arr_) + return; + + const vtkIdType n = pd->GetNumberOfCells(); + for (vtkIdType c = 0; c < n; ++c) { + const IVtk_IdType sid = (IVtk_IdType)face_sub_id_arr_->GetTuple1(c); + unsigned char rgb[3] { face_base_[0], face_base_[1], face_base_[2] }; + if (highlighted_face_ids_.count(sid)) { + rgb[0] = 255; + rgb[1] = 0; + rgb[2] = 0; + } + colors->SetTypedTuple(c, rgb); + } + + colors->Modified(); + pd->GetCellData()->Modified(); + pd->Modified(); + + if (renderer_ && renderer_->GetRenderWindow()) + renderer_->GetRenderWindow()->Render(); +} + +void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) +{ + clear(); + geom_actor_ = std::move(geom_actor); + target_initialized_ = false; + configurePicker(); +} + +void GeometrySolidSelectorHighlight::setGeometryIndex(const GeometrySubshapeIndex* idx) +{ + geom_index_ = idx; +} + +void GeometrySolidSelectorHighlight::configurePicker() +{ + auto target = getTargetData(geom_actor_); + if (!target.polyActor || !target.valid()) { + picker_->InitializePickList(); + return; + } + + picker_->PickFromListOn(); + picker_->InitializePickList(); + picker_->AddPickList(target.polyActor); + + picker_->SetPixelTolerance(toleranceForMode(SelectMode::Solid)); + + picker_->SetSelectionMode(target.occShape, kSelFace, false); + picker_->SetSelectionMode(target.occShape, kSelEdge, false); + picker_->SetSelectionMode(target.occShape, kSelVertex, false); + picker_->SetSelectionMode(target.occShape, kSelFace, true); + + picker_->SetSelectionMode(target.polyActor, kSelFace, true); + picker_->SetSelectionMode(target.polyActor, kSelEdge, false); + picker_->SetSelectionMode(target.polyActor, kSelVertex, false); + + if (target.lineActor) { + picker_->SetSelectionMode(target.lineActor, kSelFace, false); + picker_->SetSelectionMode(target.lineActor, kSelEdge, false); + picker_->SetSelectionMode(target.lineActor, kSelVertex, false); + } +} diff --git a/app/render/GeometrySelectorHighlight.h b/app/render/GeometrySelectorHighlight.h new file mode 100644 index 0000000..1db9998 --- /dev/null +++ b/app/render/GeometrySelectorHighlight.h @@ -0,0 +1,137 @@ +#ifndef GEOMETRY_SELECTOR_HIGHLIGHT_H +#define GEOMETRY_SELECTOR_HIGHLIGHT_H +#include "GeometryActorSelectOp.h" +#include "Selection.h" + +#include +#include +#include +#include + +class vtkRenderer; +class vtkDataArray; +class IVtkTools_ShapePicker; +struct GeometrySubshapeIndex; + +using GeometrySelectionVtk = Selection; + +class GeometrySelectorHighlight { +public: + virtual ~GeometrySelectorHighlight() = default; + virtual void select(double posx, double posy) = 0; + virtual void clear() = 0; + virtual GeometrySelectionVtk get() const = 0; + virtual void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) = 0; + virtual void setGeometryIndex(const GeometrySubshapeIndex* idx) = 0; + void setPicker(vtkSmartPointer picker) { picker_ = picker; } + +protected: + virtual void configurePicker() = 0; + vtkSmartPointer picker_; +}; + +class GeometryFaceSelectorHighlight final : public GeometrySelectorHighlight { +public: + GeometryFaceSelectorHighlight(vtkRenderer* renderer); + ~GeometryFaceSelectorHighlight() override; + void clear() override; + GeometrySelectionVtk get() const override; + void select(double posx, double posy) override; + void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; + void setGeometryIndex(const GeometrySubshapeIndex* idx) override; + +private: + void applyHighlight(); + void ensureTargetInit(); + void configurePicker() override; + + vtkRenderer* renderer_; + GeometryActorSelectOpFactory geom_actor_; + const GeometrySubshapeIndex* geom_index_ { nullptr }; + + vtkSmartPointer face_sub_id_arr_; + unsigned char face_base_[3] { 200, 200, 200 }; + bool target_initialized_ { false }; + + std::unordered_map selections_; +}; + +class GeometryEdgeSelectorHighlight final : public GeometrySelectorHighlight { +public: + GeometryEdgeSelectorHighlight(vtkRenderer* renderer); + ~GeometryEdgeSelectorHighlight() override; + void clear() override; + GeometrySelectionVtk get() const override; + void select(double posx, double posy) override; + void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; + void setGeometryIndex(const GeometrySubshapeIndex* idx) override; + +private: + void applyHighlight(); + void ensureTargetInit(); + void configurePicker() override; + + vtkRenderer* renderer_; + GeometryActorSelectOpFactory geom_actor_; + const GeometrySubshapeIndex* geom_index_ { nullptr }; + + vtkSmartPointer line_sub_id_arr_; + unsigned char line_base_[3] { 0, 0, 0 }; + bool target_initialized_ { false }; + + std::unordered_map selections_; +}; + +class GeometryVertexSelectorHighlight final : public GeometrySelectorHighlight { +public: + GeometryVertexSelectorHighlight(vtkRenderer* renderer); + ~GeometryVertexSelectorHighlight() override; + void clear() override; + GeometrySelectionVtk get() const override; + void select(double posx, double posy) override; + void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; + void setGeometryIndex(const GeometrySubshapeIndex* idx) override; + +private: + void applyHighlight(); + void ensureTargetInit(); + void configurePicker() override; + + vtkRenderer* renderer_; + GeometryActorSelectOpFactory geom_actor_; + const GeometrySubshapeIndex* geom_index_ { nullptr }; + + vtkSmartPointer line_sub_id_arr_; + unsigned char line_base_[3] { 0, 0, 0 }; + bool target_initialized_ { false }; + + std::unordered_map selections_; +}; + +class GeometrySolidSelectorHighlight final : public GeometrySelectorHighlight { +public: + GeometrySolidSelectorHighlight(vtkRenderer* renderer); + ~GeometrySolidSelectorHighlight() override; + void clear() override; + GeometrySelectionVtk get() const override; + void select(double posx, double posy) override; + void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; + void setGeometryIndex(const GeometrySubshapeIndex* idx) override; + +private: + void applyHighlight(); + void ensureTargetInit(); + void configurePicker() override; + + vtkRenderer* renderer_; + GeometryActorSelectOpFactory geom_actor_; + const GeometrySubshapeIndex* geom_index_ { nullptr }; + + vtkSmartPointer face_sub_id_arr_; + unsigned char face_base_[3] { 200, 200, 200 }; + bool target_initialized_ { false }; + + std::unordered_map selections_; + std::unordered_set highlighted_face_ids_; +}; +#endif // GEOMETRY_SELECTOR_HIGHLIGHT_H diff --git a/app/render/MeshActorManager.h b/app/render/MeshActorManager.h index e9d8d64..d9ca23c 100644 --- a/app/render/MeshActorManager.h +++ b/app/render/MeshActorManager.h @@ -15,7 +15,7 @@ public: std::shared_ptr getComponentActor(Index component_id) const; void deleteComponent(Index component_id); void loadMesh(Index component_id, const MeshDataVtk& model_data, - vtkRenderer* renderer, ModelRenderMode render_mode = ModelRenderMode::Face); + vtkRenderer* renderer, ModelRenderMode render_mode = ModelRenderMode::Face); void setVisibility(Index component_id, bool visibility); void setRenderMode(Index component_id, ModelRenderMode render_mode); diff --git a/app/render/QRenderWindow.cpp b/app/render/QRenderWindow.cpp index b4ac49b..6187cbf 100644 --- a/app/render/QRenderWindow.cpp +++ b/app/render/QRenderWindow.cpp @@ -5,6 +5,7 @@ #include "QRenderWindowStyle.h" #include "QSelection.h" #include "SelectManager.h" +#include "GeometrySelectManager.h" #include "Selection.h" #include "GeometryActorManager.h" #include "GeometryDataVtk.h" @@ -21,6 +22,7 @@ QRenderWindow::QRenderWindow() connect(this, &QQuickItem::widthChanged, this, &QRenderWindow::resetCamera); connect(this, &QQuickItem::heightChanged, this, &QRenderWindow::resetCamera); selectManager_ = std::make_unique(); + geometrySelectManager_ = std::make_unique(); edge_render_ = false; } @@ -40,7 +42,9 @@ QQuickVTKItem::vtkUserData QRenderWindow::initializeVTK(vtkRenderWindow* renderW vtk->renderer_->SetGradientBackground(true); vtk->style_->SetSelectManager(this->selectManager_.get()); + vtk->style_->SetGeometrySelectManager(this->geometrySelectManager_.get()); selectManager_->bindRenderer(vtk->renderer_); + geometrySelectManager_->bindRenderer(vtk->renderer_); vtk->style_->SetDefaultRenderer(vtk->renderer_); renderWindow->GetInteractor()->SetInteractorStyle(vtk->style_); @@ -76,7 +80,7 @@ QQuickVTKItem::vtkUserData QRenderWindow::initializeVTK(vtkRenderWindow* renderW vtk->plane_widget_->SetInteractor(renderWindow->GetInteractor()); vtk->plane_widget_->SetRepresentation(rep); vtk->plane_widget_->AddObserver(vtkCommand::InteractionEvent, callback); - + return vtk; } @@ -123,7 +127,8 @@ bool QRenderWindow::event(QEvent* ev) if (!_click) return QQuickVTKItem::event(ev); - setClick(); + if (data_) + data_->style_->SetClick(); auto e = static_cast(ev); emit clicked(); return QQuickVTKItem::event(ev); @@ -147,6 +152,7 @@ void QRenderWindow::deleteModel(Index model_id) } this->selectManager_->clearSelection(); + this->geometrySelectManager_->clearSelection(); }); } @@ -164,6 +170,7 @@ void QRenderWindow::deleteComponent(Index component_id) } this->selectManager_->clearSelection(); + this->geometrySelectManager_->clearSelection(); }); } @@ -222,12 +229,12 @@ void QRenderWindow::onModelChanged(Index model_id) auto mesh_data = model_query_->getMeshDataByComponent(component_id); if (mesh_data) { vtk->mesh_actor_manager_->loadMesh(component_id, *mesh_data, vtk->renderer_, ModelRenderMode::Face); - } + } auto geometry_data = model_query_->getGeometryVtkDataByComponent(component_id); if (geometry_data) { vtk->geometry_actor_manager_->loadGeometry(*geometry_data); - } +} } }); } @@ -263,6 +270,7 @@ void QRenderWindow::setVisibility(Index model_id, bool visibility) dispatch_async([model_id, visibility, this](vtkRenderWindow* renderWindow, vtkUserData userData) -> void { Data* vtk = Data::SafeDownCast(userData); selectManager_->clearSelection(); + geometrySelectManager_->clearSelection(); auto component_ids = model_query_->getComponentIds(model_id); for (Index component_id : component_ids) { @@ -289,7 +297,12 @@ void QRenderWindow::setComponentVisibility(Index component_id, bool visibility) QSelection* QRenderWindow::selectedIDs() { - std::unique_ptr data(this->selectManager_->getSelection()); + std::unique_ptr data; + if (geom_select_mode_ != SelectMode::None) { + data = this->geometrySelectManager_->getSelection(); + } else { + data = this->selectManager_->getSelection(); + } if (!data) { return nullptr; } @@ -336,7 +349,6 @@ void QRenderWindow::setSelectComponent(Index component_id) { dispatch_async([component_id, this](vtkRenderWindow* renderWindow, vtkUserData userData) -> void { Data* vtk = Data::SafeDownCast(userData); - selectManager_->bindRenderer(vtk->renderer_); this->cur_component_id_ = component_id; this->setCurEdgeRender(this->getIsEdgeRender(*vtk, component_id)); @@ -348,6 +360,19 @@ void QRenderWindow::setSelectComponent(Index component_id) selectManager_->setSelectActor(mesh_actor); else selectManager_->setSelectActor({}); + + std::shared_ptr geometry_actor; + if (vtk->geometry_actor_manager_->hasComponent(component_id)) + geometry_actor = vtk->geometry_actor_manager_->getComponentActor(component_id); + + const GeometrySubshapeIndex* geom_index = nullptr; + if (auto geom_data = this->model_query_->getGeometryVtkDataByComponent(component_id)) + geom_index = geom_data->geometry_index; + + if (geometry_actor) + geometrySelectManager_->setSelectActor(geometry_actor, geom_index); + else + geometrySelectManager_->setSelectActor({}); }); } @@ -357,18 +382,37 @@ void QRenderWindow::setSelectMode(QString select_mode) Data* vtk = Data::SafeDownCast(userData); if (select_mode == "Vertex") { select_mode_ = SelectMode::Vertex; + geom_select_mode_ = SelectMode::None; } else if (select_mode == "Face") { select_mode_ = SelectMode::Face; + geom_select_mode_ = SelectMode::None; } else if (select_mode == "Edge") { select_mode_ = SelectMode::Edge; + geom_select_mode_ = SelectMode::None; } else if (select_mode == "Block") { select_mode_ = SelectMode::Block; + geom_select_mode_ = SelectMode::None; } else if (select_mode == "Solid") { select_mode_ = SelectMode::Solid; + geom_select_mode_ = SelectMode::None; + } else if (select_mode == "GeometryFace") { + select_mode_ = SelectMode::None; + geom_select_mode_ = SelectMode::Face; + } else if (select_mode == "GeometryEdge") { + select_mode_ = SelectMode::None; + geom_select_mode_ = SelectMode::Edge; + } else if (select_mode == "GeometryVertex") { + select_mode_ = SelectMode::None; + geom_select_mode_ = SelectMode::Vertex; + } else if (select_mode == "GeometrySolid") { + select_mode_ = SelectMode::None; + geom_select_mode_ = SelectMode::Solid; } else { select_mode_ = SelectMode::None; + geom_select_mode_ = SelectMode::None; } selectManager_->setSelectMode(select_mode_); + geometrySelectManager_->setSelectMode(geom_select_mode_); }); } @@ -376,6 +420,7 @@ void QRenderWindow::clearSelection() { dispatch_async([this](vtkRenderWindow* renderWindow, vtkUserData userData) -> void { this->selectManager_->clearSelection(); + this->geometrySelectManager_->clearSelection(); }); } @@ -385,6 +430,7 @@ void QRenderWindow::setRenderMode(Index model_id, QString render_mode) dispatch_async([model_id, render_mode, this](vtkRenderWindow* renderWindow, vtkUserData userData) -> void { Data* vtk = Data::SafeDownCast(userData); this->selectManager_->clearSelection(); + this->geometrySelectManager_->clearSelection(); auto component_ids = model_query_->getComponentIds(model_id); diff --git a/app/render/QRenderWindow.h b/app/render/QRenderWindow.h index 8937158..a25f0b9 100644 --- a/app/render/QRenderWindow.h +++ b/app/render/QRenderWindow.h @@ -27,6 +27,7 @@ class MeshActor; class SelectManager; +class GeometrySelectManager; class GeometryActorManager; class MeshActorManager; class QRenderWindowStyle; @@ -176,8 +177,10 @@ private: vtkNew _camera; std::unique_ptr selectManager_; + std::unique_ptr geometrySelectManager_; MeshActor* cur_actor_ {}; Index cur_component_id_; + SelectMode geom_select_mode_ { SelectMode::None }; std::unique_ptr _click; const Data* data_ {}; diff --git a/app/render/QRenderWindowStyle.cpp b/app/render/QRenderWindowStyle.cpp index 1230564..fa1c597 100644 --- a/app/render/QRenderWindowStyle.cpp +++ b/app/render/QRenderWindowStyle.cpp @@ -1,5 +1,6 @@ #include "QRenderWindowStyle.h" #include "SelectManager.h" +#include "GeometrySelectManager.h" #include #include @@ -15,16 +16,50 @@ void QRenderWindowStyle::SetSelectManager(SelectManager* select_manager) this->select_manager_ = select_manager; } +void QRenderWindowStyle::SetGeometrySelectManager(GeometrySelectManager* geometry_select_manager) +{ + this->geometry_select_manager_ = geometry_select_manager; +} + +void QRenderWindowStyle::OnLeftButtonDown() +{ + button_down_ = true; + trackball_started_ = false; + this->GetInteractor()->GetEventPosition(downPos_); +} + +void QRenderWindowStyle::OnMouseMove() +{ + if (button_down_ && !trackball_started_) { + int cur[2]; + this->GetInteractor()->GetEventPosition(cur); + const int dx = cur[0] - downPos_[0]; + const int dy = cur[1] - downPos_[1]; + if (dx * dx + dy * dy > 25) { + click_ = false; + trackball_started_ = true; + vtkInteractorStyleTrackballCamera::OnLeftButtonDown(); + } + } + vtkInteractorStyleTrackballCamera::OnMouseMove(); +} + void QRenderWindowStyle::OnLeftButtonUp() { - if (click_ && select_manager_) { - click_ = false; - int pos[2]; - this->GetInteractor()->GetEventPosition(pos); - select_manager_->select(pos[0], pos[1]); - } - - vtkInteractorStyleTrackballCamera::OnLeftButtonUp(); + button_down_ = false; + if (click_) { + click_ = false; + int pos[2]; + this->GetInteractor()->GetEventPosition(pos); + if (select_manager_) { + select_manager_->select(pos[0], pos[1]); + } + if (geometry_select_manager_) { + geometry_select_manager_->select(pos[0], pos[1]); + } + return; + } + vtkInteractorStyleTrackballCamera::OnLeftButtonUp(); } //vtkStandardNewMacro(MouseInteractorHighLightActor); diff --git a/app/render/QRenderWindowStyle.h b/app/render/QRenderWindowStyle.h index f844424..a2355d0 100644 --- a/app/render/QRenderWindowStyle.h +++ b/app/render/QRenderWindowStyle.h @@ -9,6 +9,7 @@ #include class SelectManager; +class GeometrySelectManager; class QRenderWindowStyle : public vtkInteractorStyleTrackballCamera { @@ -17,11 +18,18 @@ public: vtkTypeMacro(QRenderWindowStyle, vtkInteractorStyleTrackballCamera); void SetClick(); void SetSelectManager(SelectManager* select_manager); + void SetGeometrySelectManager(GeometrySelectManager* geometry_select_manager); + void OnLeftButtonDown() override; + void OnMouseMove() override; void OnLeftButtonUp() override; private: bool click_ {}; + bool trackball_started_ { false }; + bool button_down_ { false }; + int downPos_[2] { 0, 0 }; SelectManager* select_manager_{}; + GeometrySelectManager* geometry_select_manager_{}; }; diff --git a/app/render/SelectManager.h b/app/render/SelectManager.h index 09694d5..546330b 100644 --- a/app/render/SelectManager.h +++ b/app/render/SelectManager.h @@ -32,7 +32,7 @@ public: std::unique_ptr getSelection(); private: - std::optional cur_model_actor_ {}; + std::optional cur_model_actor_ {}; SelectMode select_mode_; vtkNew selection_actor_; vtkNew selection_mapper_; diff --git a/app/render/test/CMakeLists.txt b/app/render/test/CMakeLists.txt index 2786d57..57f7782 100644 --- a/app/render/test/CMakeLists.txt +++ b/app/render/test/CMakeLists.txt @@ -55,3 +55,26 @@ target_link_libraries(TestMeshData PRIVATE VTK::InteractionStyle VTK::CommonColor VTK::RenderingCore VTK::RenderingUI VTK::RenderingOpenGL2 VTK::FiltersGeometry ) vtk_module_autoinit(TARGETS TestVertexSelectorHighlight MODULES VTK::InteractionStyle VTK::CommonColor VTK::RenderingCore VTK::RenderingUI VTK::RenderingOpenGL2 VTK::FiltersGeometry) + +# TestCadShapePicker (OCCT IVtkTools_ShapePicker) +add_executable(TestCadShapePicker TestCadShapePicker.cpp) +target_link_libraries(TestCadShapePicker PRIVATE + vtkPart TestDeps + spdlog::spdlog + + VTK::InteractionStyle VTK::CommonColor + VTK::RenderingCore VTK::RenderingUI VTK::RenderingOpenGL2 + + TKIVtk + TKPrim TKBRep TKGeomBase TKMath TKernel TKTopAlgo + TKDESTEP + TKXCAF + TKVCAF + TKCAF + TKLCAF +) +vtk_module_autoinit(TARGETS TestCadShapePicker MODULES + VTK::InteractionStyle VTK::CommonColor + VTK::RenderingCore VTK::RenderingUI VTK::RenderingOpenGL2 +) +install(TARGETS TestCadShapePicker) \ No newline at end of file diff --git a/app/render/test/TestCadShapePicker.cpp b/app/render/test/TestCadShapePicker.cpp new file mode 100644 index 0000000..ba2f4ea --- /dev/null +++ b/app/render/test/TestCadShapePicker.cpp @@ -0,0 +1,281 @@ +#include "GeometryActor.h" +#include "GeometryActorManager.h" +#include "GeometrySelectManager.h" + +#include "GeometryRegistry.h" +#include "GeometrySubshapeIndex.h" +#include "Selection.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace { + +static std::optional loadStepAsSingleShape_XDE(const std::filesystem::path& path) +{ + Handle(TDocStd_Document) doc; + Handle(XCAFApp_Application)::DownCast(XCAFApp_Application::GetApplication()) + ->NewDocument("MDTV-XCAF", doc); + + STEPCAFControl_Reader reader; + IFSelect_ReturnStatus stat = reader.ReadFile(path.string().c_str()); + if (stat != IFSelect_RetDone) { + spdlog::error("Failed to read STEP file: {}", path.string()); + return std::nullopt; + } + if (!reader.Transfer(doc)) { + spdlog::error("Failed to transfer STEP file: {}", path.string()); + return std::nullopt; + } + + Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(doc->Main()); + if (shapeTool.IsNull()) { + spdlog::error("Failed to get XCAF shape tool"); + return std::nullopt; + } + + TDF_LabelSequence freeShapes; + shapeTool->GetFreeShapes(freeShapes); + if (freeShapes.Length() <= 0) { + spdlog::error("No free shapes in STEP: {}", path.string()); + return std::nullopt; + } + + BRep_Builder builder; + TopoDS_Compound comp; + builder.MakeCompound(comp); + + int added = 0; + for (Standard_Integer i = 1; i <= freeShapes.Length(); ++i) { + TopoDS_Shape s = shapeTool->GetShape(freeShapes.Value(i)); + if (s.IsNull()) + continue; + builder.Add(comp, s); + ++added; + } + + if (added == 0) { + spdlog::error("All free shapes are null in STEP: {}", path.string()); + return std::nullopt; + } + + spdlog::info("STEP loaded: {}, freeShapes={}, merged={}", path.string(), freeShapes.Length(), added); + return TopoDS_Shape(comp); +} + +class GeometrySelectInteractorStyle : public vtkInteractorStyleTrackballCamera { +public: + static GeometrySelectInteractorStyle* New(); + vtkTypeMacro(GeometrySelectInteractorStyle, vtkInteractorStyleTrackballCamera); + + void SetSelectManager(GeometrySelectManager* m) { mgr_ = m; } + + void OnLeftButtonDown() override + { + button_down_ = true; + click_ = true; + trackball_started_ = false; + this->GetInteractor()->GetEventPosition(downPos_); + } + + void OnMouseMove() override + { + if (button_down_ && click_) { + int cur[2]; + this->GetInteractor()->GetEventPosition(cur); + const int dx = cur[0] - downPos_[0]; + const int dy = cur[1] - downPos_[1]; + if (dx * dx + dy * dy > 25) { + click_ = false; + if (!trackball_started_) { + trackball_started_ = true; + vtkInteractorStyleTrackballCamera::OnLeftButtonDown(); + } + } + } + vtkInteractorStyleTrackballCamera::OnMouseMove(); + } + + void OnLeftButtonUp() override + { + button_down_ = false; + if (click_ && mgr_) { + click_ = false; + int pos[2]; + this->GetInteractor()->GetEventPosition(pos); + mgr_->select(pos[0], pos[1]); + return; + } + vtkInteractorStyleTrackballCamera::OnLeftButtonUp(); + } + + void OnKeyPress() override + { + const std::string key = this->GetInteractor()->GetKeySym() + ? this->GetInteractor()->GetKeySym() + : ""; + + if (!mgr_) { + vtkInteractorStyleTrackballCamera::OnKeyPress(); + return; + } + + if (key == "1") { + mgr_->setSelectMode(SelectMode::Vertex); + spdlog::info("[GEOMETRY] mode=Vertex"); + return; + } + if (key == "2") { + mgr_->setSelectMode(SelectMode::Edge); + spdlog::info("[GEOMETRY] mode=Edge"); + return; + } + if (key == "3") { + mgr_->setSelectMode(SelectMode::Face); + spdlog::info("[GEOMETRY] mode=Face"); + return; + } + if (key == "4") { + mgr_->setSelectMode(SelectMode::Solid); + spdlog::info("[GEOMETRY] mode=Solid"); + return; + } + if (key == "c" || key == "C") { + mgr_->clearSelection(); + spdlog::info("[GEOMETRY] clear selection"); + return; + } + + vtkInteractorStyleTrackballCamera::OnKeyPress(); + } + +private: + bool click_ = false; + bool trackball_started_ = false; + bool button_down_ = false; + int downPos_[2] { 0, 0 }; + GeometrySelectManager* mgr_ = nullptr; +}; + +vtkStandardNewMacro(GeometrySelectInteractorStyle); + +} // namespace + +int main(int argc, char** argv) +{ + std::optional stepPath; + std::string modeStr = "face"; + + if (argc >= 2) { + std::filesystem::path p = argv[1]; + if (std::filesystem::exists(p)) { + stepPath = p; + if (argc >= 3) + modeStr = argv[2]; + } else { + modeStr = argv[1]; + } + std::transform(modeStr.begin(), modeStr.end(), modeStr.begin(), + [](unsigned char c) { return (char)std::tolower(c); }); + if (modeStr != "face" && modeStr != "edge" && modeStr != "vertex" && modeStr != "solid") + modeStr = "face"; + } + + SelectMode mode = SelectMode::Face; + if (modeStr == "edge") + mode = SelectMode::Edge; + else if (modeStr == "vertex") + mode = SelectMode::Vertex; + else if (modeStr == "solid") + mode = SelectMode::Solid; + + TopoDS_Shape root; + if (stepPath) { + auto s = loadStepAsSingleShape_XDE(*stepPath); + if (!s) + return 1; + root = *s; + } else { + root = BRepPrimAPI_MakeBox(100.0, 80.0, 60.0).Shape(); + } + + GeometryRegistry reg; + GeometrySubshapeIndex cadIndex; + cadIndex.build(root, reg); + + vtkNew renderer; + renderer->SetBackground(0.2, 0.3, 0.4); + + vtkNew rw; + rw->AddRenderer(renderer); + rw->SetSize(900, 700); + + vtkNew iren; + iren->SetRenderWindow(rw); + + GeometryActorManager gmgr; + gmgr.bindRender(renderer); + + const Index component_id = 123; + GeometryDataVtk gd { root, component_id, &cadIndex }; + gmgr.loadGeometry(gd); + + auto ga = gmgr.getComponentActor(component_id); + if (!ga) { + spdlog::error("GeometryActor not found for component_id={}", component_id); + return 1; + } + + gmgr.setRenderEdge(component_id, true); + gmgr.setVisibility(component_id, true); + + GeometrySelectManager selMgr; + selMgr.bindRenderer(renderer); + + auto geomActor = gmgr.getComponentActor(component_id); + selMgr.setSelectActor(geomActor, &cadIndex); + selMgr.setSelectMode(mode); + + vtkNew style; + style->SetDefaultRenderer(renderer); + style->SetSelectManager(&selMgr); + + iren->SetInteractorStyle(style); + + renderer->ResetCamera(); + rw->Render(); + + spdlog::info("GEOMETRY selector hotkeys: [1]=Vertex [2]=Edge [3]=Face [4]=Solid [C]=Clear"); + + iren->Start(); + return 0; +} diff --git a/app/render/test/TestSolidSelectorHighlight.cpp b/app/render/test/TestSolidSelectorHighlight.cpp index d6d0c47..0712658 100644 --- a/app/render/test/TestSolidSelectorHighlight.cpp +++ b/app/render/test/TestSolidSelectorHighlight.cpp @@ -42,7 +42,7 @@ int main(int argc, char* argv[]) std::string inputFile; if (argc > 1) { inputFile = argv[1]; - std::cout << "Try load file: " << inputFile << std::endl; + spdlog::info("Try load file: {}", inputFile); } MeshData mesh; diff --git a/core/GeometryDataVtk.h b/core/GeometryDataVtk.h index 249e150..023e9e3 100644 --- a/core/GeometryDataVtk.h +++ b/core/GeometryDataVtk.h @@ -1,9 +1,11 @@ #ifndef GEOMETRY_DATA_VTK_H #define GEOMETRY_DATA_VTK_H class TopoDS_Shape; +struct GeometrySubshapeIndex; struct GeometryDataVtk { - TopoDS_Shape& shape; + const TopoDS_Shape& shape; Index component_id { -1 }; + const GeometrySubshapeIndex* geometry_index { nullptr }; }; #endif // !GEOMETRY_DATA_VTK_H diff --git a/model/data/GeometrySubshapeIndex.cpp b/model/data/GeometrySubshapeIndex.cpp index 843bb23..f3db40d 100644 --- a/model/data/GeometrySubshapeIndex.cpp +++ b/model/data/GeometrySubshapeIndex.cpp @@ -1,6 +1,8 @@ #include "GeometrySubshapeIndex.h" #include "GeometryRegistry.h" +#include + #include #include #include @@ -25,6 +27,21 @@ void GeometrySubshapeIndex::build(const TopoDS_Shape& root, GeometryRegistry& re TopExp::MapShapes(root, type, type_maps[ti]); } + { + const int nVertices = type_maps[typeIndex(TopAbs_VERTEX)].Extent(); + const int nEdges = type_maps[typeIndex(TopAbs_EDGE)].Extent(); + const int nWires = type_maps[typeIndex(TopAbs_WIRE)].Extent(); + const int nFaces = type_maps[typeIndex(TopAbs_FACE)].Extent(); + const int nShells = type_maps[typeIndex(TopAbs_SHELL)].Extent(); + const int nSolids = type_maps[typeIndex(TopAbs_SOLID)].Extent(); + const int nCompounds = type_maps[typeIndex(TopAbs_COMPOUND)].Extent(); + const int nCompSolids = type_maps[typeIndex(TopAbs_COMPSOLID)].Extent(); + + spdlog::info("[GeometryIndex] sub-shape summary:" + " Vertex={}, Edge={}, Wire={}, Face={}, Shell={}, Solid={}, CompSolid={}, Compound={}", + nVertices, nEdges, nWires, nFaces, nShells, nSolids, nCompSolids, nCompounds); + } + // 2) Vertex: localTypeId -> GeomVertexId { const int ti = typeIndex(TopAbs_VERTEX); -- Gitee From 9349643b8df05716819de35d245326c5808a55cd Mon Sep 17 00:00:00 2001 From: hypf Date: Mon, 29 Jun 2026 13:41:14 +0800 Subject: [PATCH 02/13] =?UTF-8?q?refactor(app)=EF=BC=9A=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E4=BB=A3=E7=A0=81=E9=A3=8E=E6=A0=BC=E3=80=81?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E7=AD=89=E6=93=8D=E4=BD=9C=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0picker=E6=B8=85=E7=A9=BA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/render/GeometryActor.cpp | 10 +- app/render/GeometrySelectManager.cpp | 14 ++- app/render/GeometrySelectorHighlight.cpp | 95 ++++++++++++++++--- app/render/QRenderWindowStyle.cpp | 50 +++------- app/render/QRenderWindowStyle.h | 6 -- app/render/test/CMakeLists.txt | 2 +- ...Picker.cpp => TestGeometryShapePicker.cpp} | 2 +- 7 files changed, 112 insertions(+), 67 deletions(-) rename app/render/test/{TestCadShapePicker.cpp => TestGeometryShapePicker.cpp} (98%) diff --git a/app/render/GeometryActor.cpp b/app/render/GeometryActor.cpp index 72b8d0b..1910a9f 100644 --- a/app/render/GeometryActor.cpp +++ b/app/render/GeometryActor.cpp @@ -55,7 +55,7 @@ void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) const vtkIdType nP = src->GetNumberOfPolys(); spdlog::info("[GeometryActor] loadShape component={} verts={} lines={} polys={}", - geometry_data.component_id, (int)nV, (int)nL, (int)nP); + geometry_data.component_id, static_cast(nV), static_cast(nL), static_cast(nP)); auto ExtractCellRangeToPolyData = [](vtkPolyData* in, vtkIdType start, vtkIdType count) -> vtkSmartPointer { vtkNew ids; @@ -122,9 +122,9 @@ void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) if (this->poly_actor_ && this->poly_actor_->GetProperty()) { double c[3]; this->poly_actor_->GetProperty()->GetColor(c); - faceBase[0] = (unsigned char)std::clamp((int)std::lround(c[0] * 255.0), 0, 255); - faceBase[1] = (unsigned char)std::clamp((int)std::lround(c[1] * 255.0), 0, 255); - faceBase[2] = (unsigned char)std::clamp((int)std::lround(c[2] * 255.0), 0, 255); + faceBase[0] = static_cast(std::clamp(static_cast(std::lround(c[0] * 255.0)), 0, 255)); + faceBase[1] = static_cast(std::clamp(static_cast(std::lround(c[1] * 255.0)), 0, 255)); + faceBase[2] = static_cast(std::clamp(static_cast(std::lround(c[2] * 255.0)), 0, 255)); } const unsigned char lineBase[3] = { 0, 0, 0 }; @@ -157,7 +157,7 @@ void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) this->renderer_->AddActor(this->line_actor_); spdlog::info("[GeometryActor] component={} actors added, face_cells={} line_cells={}", - geometry_data.component_id, (int)poly_only->GetNumberOfCells(), (int)line_only->GetNumberOfCells()); + geometry_data.component_id, static_cast(poly_only->GetNumberOfCells()), static_cast(line_only->GetNumberOfCells())); } void GeometryActor::deleteGeometryActor() diff --git a/app/render/GeometrySelectManager.cpp b/app/render/GeometrySelectManager.cpp index 3d6922a..dcaf64b 100644 --- a/app/render/GeometrySelectManager.cpp +++ b/app/render/GeometrySelectManager.cpp @@ -7,9 +7,11 @@ void GeometrySelectManager::bindRenderer(vtkRenderer* renderer) { this->renderer_ = renderer; - picker_ = vtkSmartPointer::New(); - picker_->SetRenderer(renderer); - picker_->SetAreaSelection(false); + if (!picker_) { + picker_ = vtkSmartPointer::New(); + picker_->SetRenderer(renderer); + picker_->SetAreaSelection(false); + } } void GeometrySelectManager::select(double posx, double posy) @@ -35,6 +37,12 @@ void GeometrySelectManager::setSelectMode(SelectMode select_mode) { this->clearSelection(); this->select_mode_ = select_mode; + + if (this->selector_) { + this->selector_->setPicker(picker_); + this->selector_->setCurGeomActor(GeometryActorSelectOpFactory {}); + } + if (this->select_mode_ == SelectMode::Vertex) { this->selector_ = std::make_unique(this->renderer_); } else if (this->select_mode_ == SelectMode::Face) { diff --git a/app/render/GeometrySelectorHighlight.cpp b/app/render/GeometrySelectorHighlight.cpp index 5b0d00b..29d8381 100644 --- a/app/render/GeometrySelectorHighlight.cpp +++ b/app/render/GeometrySelectorHighlight.cpp @@ -64,7 +64,7 @@ static std::optional mapSubshapeToGeomId(const OccShapeHandle& occShape, if (ti < 0) return std::nullopt; - const int localTypeId = geomIndex.type_maps[(size_t)ti].FindIndex(sub); + const int localTypeId = geomIndex.type_maps[static_cast(ti)].FindIndex(sub); if (localTypeId <= 0) return std::nullopt; @@ -73,25 +73,25 @@ static std::optional mapSubshapeToGeomId(const OccShapeHandle& occShape, if (gid == kInvalidGeomFaceId) return std::nullopt; outType = ElementEnum::Face; - return (Index)gid; + return gid; } else if (wantType == TopAbs_EDGE) { GeomEdgeId gid = geomIndex.edgeGlobalId(localTypeId); if (gid == kInvalidGeomEdgeId) return std::nullopt; outType = ElementEnum::Edge; - return (Index)gid; + return gid; } else if (wantType == TopAbs_VERTEX) { GeomVertexId gid = geomIndex.vertexGlobalId(localTypeId); if (gid == kInvalidGeomVertexId) return std::nullopt; outType = ElementEnum::Vertex; - return (Index)gid; + return gid; } else if (wantType == TopAbs_SOLID) { GeomSolidId gid = geomIndex.solidGlobalId(localTypeId); if (gid == kInvalidGeomSolidId) return std::nullopt; outType = ElementEnum::Solid; - return (Index)gid; + return gid; } return std::nullopt; } @@ -150,7 +150,7 @@ static vtkDataArray* detectSubIdArrayByValue(vtkPolyData* pd, IVtk_IdType picked vtkIdType hits = 0; for (vtkIdType c = 0; c < nCells; ++c) { - if ((IVtk_IdType)a->GetTuple1(c) == pickedSubId) + if (static_cast(a->GetTuple1(c)) == pickedSubId) ++hits; } if (hits > bestHits) { @@ -161,18 +161,18 @@ static vtkDataArray* detectSubIdArrayByValue(vtkPolyData* pd, IVtk_IdType picked if (best && bestHits > 0) { spdlog::info("[{}] detected subId array='{}' hits={}/{} for subId={}", - tag, (best->GetName() ? best->GetName() : "(null)"), (int)bestHits, (int)nCells, (int)pickedSubId); + tag, (best->GetName() ? best->GetName() : "(null)"), static_cast(bestHits), static_cast(nCells), pickedSubId); return best; } - spdlog::warn("[{}] cannot detect subId array by picked subId={}. Dump arrays:", tag, (int)pickedSubId); + spdlog::warn("[{}] cannot detect subId array by picked subId={}. Dump arrays:", tag, pickedSubId); for (int i = 0; i < cd->GetNumberOfArrays(); ++i) { vtkDataArray* a = cd->GetArray(i); if (!a) continue; spdlog::warn(" CellData[{}] name='{}' comps={} tuples={} type={}", i, (a->GetName() ? a->GetName() : "(null)"), - a->GetNumberOfComponents(), (int)a->GetNumberOfTuples(), a->GetDataType()); + a->GetNumberOfComponents(), static_cast(a->GetNumberOfTuples()), a->GetDataType()); } return nullptr; } @@ -188,7 +188,7 @@ static void recolorBySelectedSubIds(vtkPolyData* pd, const vtkIdType n = pd->GetNumberOfCells(); for (vtkIdType c = 0; c < n; ++c) { - const IVtk_IdType sid = (IVtk_IdType)subIdArr->GetTuple1(c); + const IVtk_IdType sid = static_cast(subIdArr->GetTuple1(c)); unsigned char rgb[3] { base[0], base[1], base[2] }; if (selected.count(sid)) { rgb[0] = 255; @@ -343,6 +343,23 @@ void GeometryFaceSelectorHighlight::applyHighlight() void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { + auto oldTarget = getTargetData(geom_actor_); + if (oldTarget.valid()) { + picker_->SetSelectionMode(oldTarget.occShape, kSelFace, false); + picker_->SetSelectionMode(oldTarget.occShape, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.occShape, kSelVertex, false); + if (oldTarget.polyActor) { + picker_->SetSelectionMode(oldTarget.polyActor, kSelFace, false); + picker_->SetSelectionMode(oldTarget.polyActor, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.polyActor, kSelVertex, false); + } + if (oldTarget.lineActor) { + picker_->SetSelectionMode(oldTarget.lineActor, kSelFace, false); + picker_->SetSelectionMode(oldTarget.lineActor, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.lineActor, kSelVertex, false); + } + picker_->InitializePickList(); + } clear(); geom_actor_ = std::move(geom_actor); target_initialized_ = false; @@ -489,6 +506,23 @@ void GeometryEdgeSelectorHighlight::applyHighlight() void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { + auto oldTarget = getTargetData(geom_actor_); + if (oldTarget.valid()) { + picker_->SetSelectionMode(oldTarget.occShape, kSelFace, false); + picker_->SetSelectionMode(oldTarget.occShape, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.occShape, kSelVertex, false); + if (oldTarget.polyActor) { + picker_->SetSelectionMode(oldTarget.polyActor, kSelFace, false); + picker_->SetSelectionMode(oldTarget.polyActor, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.polyActor, kSelVertex, false); + } + if (oldTarget.lineActor) { + picker_->SetSelectionMode(oldTarget.lineActor, kSelFace, false); + picker_->SetSelectionMode(oldTarget.lineActor, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.lineActor, kSelVertex, false); + } + picker_->InitializePickList(); + } clear(); geom_actor_ = std::move(geom_actor); target_initialized_ = false; @@ -637,6 +671,23 @@ void GeometryVertexSelectorHighlight::applyHighlight() void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { + auto oldTarget = getTargetData(geom_actor_); + if (oldTarget.valid()) { + picker_->SetSelectionMode(oldTarget.occShape, kSelFace, false); + picker_->SetSelectionMode(oldTarget.occShape, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.occShape, kSelVertex, false); + if (oldTarget.polyActor) { + picker_->SetSelectionMode(oldTarget.polyActor, kSelFace, false); + picker_->SetSelectionMode(oldTarget.polyActor, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.polyActor, kSelVertex, false); + } + if (oldTarget.lineActor) { + picker_->SetSelectionMode(oldTarget.lineActor, kSelFace, false); + picker_->SetSelectionMode(oldTarget.lineActor, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.lineActor, kSelVertex, false); + } + picker_->InitializePickList(); + } clear(); geom_actor_ = std::move(geom_actor); target_initialized_ = false; @@ -787,7 +838,7 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) if (gid == kInvalidGeomSolidId) return; - auto [it, inserted] = selections_.insert_or_assign((IVtk_IdType)gid, (Index)gid); + auto [it, inserted] = selections_.insert_or_assign(gid, gid); if (!inserted) { selections_.erase(it); } @@ -821,7 +872,7 @@ void GeometrySolidSelectorHighlight::applyHighlight() const vtkIdType n = pd->GetNumberOfCells(); for (vtkIdType c = 0; c < n; ++c) { - const IVtk_IdType sid = (IVtk_IdType)face_sub_id_arr_->GetTuple1(c); + const IVtk_IdType sid = static_cast(face_sub_id_arr_->GetTuple1(c)); unsigned char rgb[3] { face_base_[0], face_base_[1], face_base_[2] }; if (highlighted_face_ids_.count(sid)) { rgb[0] = 255; @@ -841,6 +892,23 @@ void GeometrySolidSelectorHighlight::applyHighlight() void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { + auto oldTarget = getTargetData(geom_actor_); + if (oldTarget.valid()) { + picker_->SetSelectionMode(oldTarget.occShape, kSelFace, false); + picker_->SetSelectionMode(oldTarget.occShape, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.occShape, kSelVertex, false); + if (oldTarget.polyActor) { + picker_->SetSelectionMode(oldTarget.polyActor, kSelFace, false); + picker_->SetSelectionMode(oldTarget.polyActor, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.polyActor, kSelVertex, false); + } + if (oldTarget.lineActor) { + picker_->SetSelectionMode(oldTarget.lineActor, kSelFace, false); + picker_->SetSelectionMode(oldTarget.lineActor, kSelEdge, false); + picker_->SetSelectionMode(oldTarget.lineActor, kSelVertex, false); + } + picker_->InitializePickList(); + } clear(); geom_actor_ = std::move(geom_actor); target_initialized_ = false; @@ -856,7 +924,8 @@ void GeometrySolidSelectorHighlight::configurePicker() { auto target = getTargetData(geom_actor_); if (!target.polyActor || !target.valid()) { - picker_->InitializePickList(); + if (picker_) + picker_->InitializePickList(); return; } diff --git a/app/render/QRenderWindowStyle.cpp b/app/render/QRenderWindowStyle.cpp index fa1c597..98d6c62 100644 --- a/app/render/QRenderWindowStyle.cpp +++ b/app/render/QRenderWindowStyle.cpp @@ -18,48 +18,22 @@ void QRenderWindowStyle::SetSelectManager(SelectManager* select_manager) void QRenderWindowStyle::SetGeometrySelectManager(GeometrySelectManager* geometry_select_manager) { - this->geometry_select_manager_ = geometry_select_manager; -} - -void QRenderWindowStyle::OnLeftButtonDown() -{ - button_down_ = true; - trackball_started_ = false; - this->GetInteractor()->GetEventPosition(downPos_); -} - -void QRenderWindowStyle::OnMouseMove() -{ - if (button_down_ && !trackball_started_) { - int cur[2]; - this->GetInteractor()->GetEventPosition(cur); - const int dx = cur[0] - downPos_[0]; - const int dy = cur[1] - downPos_[1]; - if (dx * dx + dy * dy > 25) { - click_ = false; - trackball_started_ = true; - vtkInteractorStyleTrackballCamera::OnLeftButtonDown(); - } - } - vtkInteractorStyleTrackballCamera::OnMouseMove(); + this->geometry_select_manager_ = geometry_select_manager; } void QRenderWindowStyle::OnLeftButtonUp() { - button_down_ = false; - if (click_) { - click_ = false; - int pos[2]; - this->GetInteractor()->GetEventPosition(pos); - if (select_manager_) { - select_manager_->select(pos[0], pos[1]); - } - if (geometry_select_manager_) { - geometry_select_manager_->select(pos[0], pos[1]); - } - return; - } - vtkInteractorStyleTrackballCamera::OnLeftButtonUp(); + if (click_) { + click_ = false; + int pos[2]; + this->GetInteractor()->GetEventPosition(pos); + if (select_manager_) + select_manager_->select(pos[0], pos[1]); + if (geometry_select_manager_) + geometry_select_manager_->select(pos[0], pos[1]); + } + + vtkInteractorStyleTrackballCamera::OnLeftButtonUp(); } //vtkStandardNewMacro(MouseInteractorHighLightActor); diff --git a/app/render/QRenderWindowStyle.h b/app/render/QRenderWindowStyle.h index a2355d0..5f1c38c 100644 --- a/app/render/QRenderWindowStyle.h +++ b/app/render/QRenderWindowStyle.h @@ -11,7 +11,6 @@ class SelectManager; class GeometrySelectManager; - class QRenderWindowStyle : public vtkInteractorStyleTrackballCamera { public: static QRenderWindowStyle* New(); @@ -19,15 +18,10 @@ public: void SetClick(); void SetSelectManager(SelectManager* select_manager); void SetGeometrySelectManager(GeometrySelectManager* geometry_select_manager); - void OnLeftButtonDown() override; - void OnMouseMove() override; void OnLeftButtonUp() override; private: bool click_ {}; - bool trackball_started_ { false }; - bool button_down_ { false }; - int downPos_[2] { 0, 0 }; SelectManager* select_manager_{}; GeometrySelectManager* geometry_select_manager_{}; diff --git a/app/render/test/CMakeLists.txt b/app/render/test/CMakeLists.txt index 57f7782..dee2756 100644 --- a/app/render/test/CMakeLists.txt +++ b/app/render/test/CMakeLists.txt @@ -57,7 +57,7 @@ target_link_libraries(TestMeshData PRIVATE vtk_module_autoinit(TARGETS TestVertexSelectorHighlight MODULES VTK::InteractionStyle VTK::CommonColor VTK::RenderingCore VTK::RenderingUI VTK::RenderingOpenGL2 VTK::FiltersGeometry) # TestCadShapePicker (OCCT IVtkTools_ShapePicker) -add_executable(TestCadShapePicker TestCadShapePicker.cpp) +add_executable(TestCadShapePicker "TestGeometryShapePicker.cpp") target_link_libraries(TestCadShapePicker PRIVATE vtkPart TestDeps spdlog::spdlog diff --git a/app/render/test/TestCadShapePicker.cpp b/app/render/test/TestGeometryShapePicker.cpp similarity index 98% rename from app/render/test/TestCadShapePicker.cpp rename to app/render/test/TestGeometryShapePicker.cpp index ba2f4ea..2775688 100644 --- a/app/render/test/TestCadShapePicker.cpp +++ b/app/render/test/TestGeometryShapePicker.cpp @@ -205,7 +205,7 @@ int main(int argc, char** argv) modeStr = argv[1]; } std::transform(modeStr.begin(), modeStr.end(), modeStr.begin(), - [](unsigned char c) { return (char)std::tolower(c); }); + [](unsigned char c) { return static_cast(std::tolower(c)); }); if (modeStr != "face" && modeStr != "edge" && modeStr != "vertex" && modeStr != "solid") modeStr = "face"; } -- Gitee From c24de12812da83965ab406c1682f583ac3d5e63b Mon Sep 17 00:00:00 2001 From: hypf Date: Mon, 29 Jun 2026 14:04:55 +0800 Subject: [PATCH 03/13] =?UTF-8?q?refactor(app)=EF=BC=9A=E5=B0=86geometrysu?= =?UTF-8?q?bshapeindex=E5=AD=98=E5=85=A5geometryactor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/render/GeometryActor.cpp | 6 +++ app/render/GeometryActor.h | 3 ++ app/render/GeometryActorSelectOp.cpp | 5 +++ app/render/GeometryActorSelectOp.h | 6 +-- app/render/GeometrySelectManager.cpp | 5 +-- app/render/GeometrySelectManager.h | 3 +- app/render/GeometrySelectorHighlight.cpp | 43 +++++++-------------- app/render/GeometrySelectorHighlight.h | 9 ----- app/render/QRenderWindow.cpp | 6 +-- app/render/test/TestGeometryShapePicker.cpp | 2 +- 10 files changed, 33 insertions(+), 55 deletions(-) diff --git a/app/render/GeometryActor.cpp b/app/render/GeometryActor.cpp index 1910a9f..2caf84b 100644 --- a/app/render/GeometryActor.cpp +++ b/app/render/GeometryActor.cpp @@ -45,6 +45,7 @@ void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) OccShapeHandle aShapeImpl = new IVtkOCC_Shape(geometry_data.shape); aShapeImpl->SetId(static_cast(geometry_data.component_id)); this->occ_shape_ = aShapeImpl; + this->geometry_index_ = geometry_data.geometry_index; vtkSmartPointer DS = vtkSmartPointer::New(); DS->SetShape(aShapeImpl); DS->Update(); @@ -208,4 +209,9 @@ const vtkActor* GeometryActor::lineActor() const noexcept const OccShapeHandle& GeometryActor::getOccShape() const { return occ_shape_; +} + +const GeometrySubshapeIndex* GeometryActor::geometryIndex() const noexcept +{ + return geometry_index_; } \ No newline at end of file diff --git a/app/render/GeometryActor.h b/app/render/GeometryActor.h index 1403aa5..cf31d6a 100644 --- a/app/render/GeometryActor.h +++ b/app/render/GeometryActor.h @@ -2,6 +2,7 @@ #define GEOMETRY_ACTOR_H #include "Core.h" #include "GeometryDataVtk.h" +#include "GeometrySubshapeIndex.h" #include #include #include @@ -30,6 +31,7 @@ public: vtkActor* lineActor() noexcept; const vtkActor* lineActor() const noexcept; const OccShapeHandle& getOccShape() const; + const GeometrySubshapeIndex* geometryIndex() const noexcept; private: void deleteGeometryActor(); @@ -38,6 +40,7 @@ private: bool edge_render; bool visibility_; OccShapeHandle occ_shape_; + const GeometrySubshapeIndex* geometry_index_; vtkNew poly_actor_; vtkNew line_actor_; diff --git a/app/render/GeometryActorSelectOp.cpp b/app/render/GeometryActorSelectOp.cpp index 8567b66..af3ebac 100644 --- a/app/render/GeometryActorSelectOp.cpp +++ b/app/render/GeometryActorSelectOp.cpp @@ -37,3 +37,8 @@ const OccShapeHandle& GeometryActorSelectOp::getOccShape() { return geometry_actor_->getOccShape(); } + +const GeometrySubshapeIndex* GeometryActorSelectOp::getGeometryIndex() +{ + return geometry_actor_->geometryIndex(); +} diff --git a/app/render/GeometryActorSelectOp.h b/app/render/GeometryActorSelectOp.h index e8e5f45..21a1957 100644 --- a/app/render/GeometryActorSelectOp.h +++ b/app/render/GeometryActorSelectOp.h @@ -4,12 +4,9 @@ #include #include -#include -#include -typedef Handle(IVtkOCC_Shape) OccShapeHandle; +#include "GeometryActor.h" class GeometryActorSelectOp; -class GeometryActor; class GeometryActorSelectOpFactory { friend GeometryActorSelectOp; @@ -32,6 +29,7 @@ public: vtkProp& getPolyActor(); vtkProp& getLineActor(); const OccShapeHandle& getOccShape(); + const GeometrySubshapeIndex* getGeometryIndex(); private: std::shared_ptr geometry_actor_; diff --git a/app/render/GeometrySelectManager.cpp b/app/render/GeometrySelectManager.cpp index dcaf64b..292ce2e 100644 --- a/app/render/GeometrySelectManager.cpp +++ b/app/render/GeometrySelectManager.cpp @@ -21,15 +21,13 @@ void GeometrySelectManager::select(double posx, double posy) } } -void GeometrySelectManager::setSelectActor(std::weak_ptr geom_actor, const GeometrySubshapeIndex* geom_index) +void GeometrySelectManager::setSelectActor(std::weak_ptr geom_actor) { this->cur_geom_actor_ = GeometryActorSelectOpFactory { geom_actor }; - this->current_geom_index_ = geom_index; if (this->selector_) { this->selector_->clear(); this->selector_->setPicker(picker_); this->selector_->setCurGeomActor(*cur_geom_actor_); - this->selector_->setGeometryIndex(current_geom_index_); } } @@ -59,7 +57,6 @@ void GeometrySelectManager::setSelectMode(SelectMode select_mode) if (this->selector_ && this->cur_geom_actor_) { this->selector_->setPicker(picker_); this->selector_->setCurGeomActor(*cur_geom_actor_); - this->selector_->setGeometryIndex(current_geom_index_); } } diff --git a/app/render/GeometrySelectManager.h b/app/render/GeometrySelectManager.h index c099e80..6b9b45d 100644 --- a/app/render/GeometrySelectManager.h +++ b/app/render/GeometrySelectManager.h @@ -18,14 +18,13 @@ public: void bindRenderer(vtkRenderer* renderer); void select(double posx, double posy); - void setSelectActor(std::weak_ptr geom_actor, const GeometrySubshapeIndex* geom_index = nullptr); + void setSelectActor(std::weak_ptr geom_actor); void setSelectMode(SelectMode select_mode); void clearSelection(); std::unique_ptr getSelection(); private: std::optional cur_geom_actor_ {}; - const GeometrySubshapeIndex* current_geom_index_ { nullptr }; SelectMode select_mode_; vtkNew selection_actor_; vtkNew selection_mapper_; diff --git a/app/render/GeometrySelectorHighlight.cpp b/app/render/GeometrySelectorHighlight.cpp index 29d8381..75f70de 100644 --- a/app/render/GeometrySelectorHighlight.cpp +++ b/app/render/GeometrySelectorHighlight.cpp @@ -220,6 +220,7 @@ struct GeomTargetData { vtkActor* polyActor = nullptr; vtkActor* lineActor = nullptr; OccShapeHandle occShape; + const GeometrySubshapeIndex* geomIndex = nullptr; bool valid() const { return !occShape.IsNull(); } }; @@ -233,6 +234,7 @@ static GeomTargetData getTargetData(GeometryActorSelectOpFactory& factory) d.polyActor = dynamic_cast(&op->getPolyActor()); d.lineActor = dynamic_cast(&op->getLineActor()); d.occShape = op->getOccShape(); + d.geomIndex = op->getGeometryIndex(); return d; } @@ -293,7 +295,7 @@ void GeometryFaceSelectorHighlight::ensureTargetInit() void GeometryFaceSelectorHighlight::select(double posx, double posy) { auto target = getTargetData(geom_actor_); - if (!target.polyActor || !target.valid() || !geom_index_) + if (!target.polyActor || !target.valid() || !target.geomIndex) return; ensureTargetInit(); @@ -311,7 +313,7 @@ void GeometryFaceSelectorHighlight::select(double posx, double posy) return; ElementEnum::Type elemType = ElementEnum::None; - auto geomId = mapSubshapeToGeomId(target.occShape, *geom_index_, TopAbs_FACE, subId, elemType); + auto geomId = mapSubshapeToGeomId(target.occShape, *target.geomIndex, TopAbs_FACE, subId, elemType); if (!geomId) return; @@ -366,10 +368,6 @@ void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory configurePicker(); } -void GeometryFaceSelectorHighlight::setGeometryIndex(const GeometrySubshapeIndex* idx) -{ - geom_index_ = idx; -} void GeometryFaceSelectorHighlight::configurePicker() { @@ -456,7 +454,7 @@ void GeometryEdgeSelectorHighlight::ensureTargetInit() void GeometryEdgeSelectorHighlight::select(double posx, double posy) { auto target = getTargetData(geom_actor_); - if (!target.lineActor || !target.valid() || !geom_index_) + if (!target.lineActor || !target.valid() || !target.geomIndex) return; ensureTargetInit(); @@ -474,7 +472,7 @@ void GeometryEdgeSelectorHighlight::select(double posx, double posy) return; ElementEnum::Type elemType = ElementEnum::None; - auto geomId = mapSubshapeToGeomId(target.occShape, *geom_index_, TopAbs_EDGE, subId, elemType); + auto geomId = mapSubshapeToGeomId(target.occShape, *target.geomIndex, TopAbs_EDGE, subId, elemType); if (!geomId) return; @@ -529,11 +527,6 @@ void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory configurePicker(); } -void GeometryEdgeSelectorHighlight::setGeometryIndex(const GeometrySubshapeIndex* idx) -{ - geom_index_ = idx; -} - void GeometryEdgeSelectorHighlight::configurePicker() { auto target = getTargetData(geom_actor_); @@ -621,7 +614,7 @@ void GeometryVertexSelectorHighlight::ensureTargetInit() void GeometryVertexSelectorHighlight::select(double posx, double posy) { auto target = getTargetData(geom_actor_); - if (!target.lineActor || !target.valid() || !geom_index_) + if (!target.lineActor || !target.valid() || !target.geomIndex) return; ensureTargetInit(); @@ -639,7 +632,7 @@ void GeometryVertexSelectorHighlight::select(double posx, double posy) return; ElementEnum::Type elemType = ElementEnum::None; - auto geomId = mapSubshapeToGeomId(target.occShape, *geom_index_, TopAbs_VERTEX, subId, elemType); + auto geomId = mapSubshapeToGeomId(target.occShape, *target.geomIndex, TopAbs_VERTEX, subId, elemType); if (!geomId) return; @@ -694,11 +687,6 @@ void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFacto configurePicker(); } -void GeometryVertexSelectorHighlight::setGeometryIndex(const GeometrySubshapeIndex* idx) -{ - geom_index_ = idx; -} - void GeometryVertexSelectorHighlight::configurePicker() { auto target = getTargetData(geom_actor_); @@ -787,7 +775,7 @@ void GeometrySolidSelectorHighlight::ensureTargetInit() void GeometrySolidSelectorHighlight::select(double posx, double posy) { auto target = getTargetData(geom_actor_); - if (!target.polyActor || !target.valid() || !geom_index_) + if (!target.polyActor || !target.valid() || !target.geomIndex) return; ensureTargetInit(); @@ -813,9 +801,9 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) solidShape = pickedSub; } else { const int solidTi = GeometrySubshapeIndex::typeIndex(TopAbs_SOLID); - const int nSolids = geom_index_->type_maps[solidTi].Extent(); + const int nSolids = target.geomIndex->type_maps[solidTi].Extent(); for (int localId = 1; localId <= nSolids; ++localId) { - const TopoDS_Shape& solid = geom_index_->type_maps[solidTi].FindKey(localId); + const TopoDS_Shape& solid = target.geomIndex->type_maps[solidTi].FindKey(localId); for (TopExp_Explorer exp(solid, TopAbs_FACE); exp.More(); exp.Next()) { if (exp.Current().IsSame(pickedSub)) { solidShape = solid; @@ -830,11 +818,11 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) } const int solidTi = GeometrySubshapeIndex::typeIndex(TopAbs_SOLID); - const int localTypeId = geom_index_->type_maps[solidTi].FindIndex(solidShape); + const int localTypeId = target.geomIndex->type_maps[solidTi].FindIndex(solidShape); if (localTypeId <= 0) return; - GeomSolidId gid = geom_index_->solidGlobalId(localTypeId); + GeomSolidId gid = target.geomIndex->solidGlobalId(localTypeId); if (gid == kInvalidGeomSolidId) return; @@ -915,11 +903,6 @@ void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactor configurePicker(); } -void GeometrySolidSelectorHighlight::setGeometryIndex(const GeometrySubshapeIndex* idx) -{ - geom_index_ = idx; -} - void GeometrySolidSelectorHighlight::configurePicker() { auto target = getTargetData(geom_actor_); diff --git a/app/render/GeometrySelectorHighlight.h b/app/render/GeometrySelectorHighlight.h index 1db9998..a65931d 100644 --- a/app/render/GeometrySelectorHighlight.h +++ b/app/render/GeometrySelectorHighlight.h @@ -22,7 +22,6 @@ public: virtual void clear() = 0; virtual GeometrySelectionVtk get() const = 0; virtual void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) = 0; - virtual void setGeometryIndex(const GeometrySubshapeIndex* idx) = 0; void setPicker(vtkSmartPointer picker) { picker_ = picker; } protected: @@ -38,7 +37,6 @@ public: GeometrySelectionVtk get() const override; void select(double posx, double posy) override; void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; - void setGeometryIndex(const GeometrySubshapeIndex* idx) override; private: void applyHighlight(); @@ -47,7 +45,6 @@ private: vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - const GeometrySubshapeIndex* geom_index_ { nullptr }; vtkSmartPointer face_sub_id_arr_; unsigned char face_base_[3] { 200, 200, 200 }; @@ -64,7 +61,6 @@ public: GeometrySelectionVtk get() const override; void select(double posx, double posy) override; void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; - void setGeometryIndex(const GeometrySubshapeIndex* idx) override; private: void applyHighlight(); @@ -73,7 +69,6 @@ private: vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - const GeometrySubshapeIndex* geom_index_ { nullptr }; vtkSmartPointer line_sub_id_arr_; unsigned char line_base_[3] { 0, 0, 0 }; @@ -90,7 +85,6 @@ public: GeometrySelectionVtk get() const override; void select(double posx, double posy) override; void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; - void setGeometryIndex(const GeometrySubshapeIndex* idx) override; private: void applyHighlight(); @@ -99,7 +93,6 @@ private: vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - const GeometrySubshapeIndex* geom_index_ { nullptr }; vtkSmartPointer line_sub_id_arr_; unsigned char line_base_[3] { 0, 0, 0 }; @@ -116,7 +109,6 @@ public: GeometrySelectionVtk get() const override; void select(double posx, double posy) override; void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; - void setGeometryIndex(const GeometrySubshapeIndex* idx) override; private: void applyHighlight(); @@ -125,7 +117,6 @@ private: vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - const GeometrySubshapeIndex* geom_index_ { nullptr }; vtkSmartPointer face_sub_id_arr_; unsigned char face_base_[3] { 200, 200, 200 }; diff --git a/app/render/QRenderWindow.cpp b/app/render/QRenderWindow.cpp index 6187cbf..aad85a2 100644 --- a/app/render/QRenderWindow.cpp +++ b/app/render/QRenderWindow.cpp @@ -365,12 +365,8 @@ void QRenderWindow::setSelectComponent(Index component_id) if (vtk->geometry_actor_manager_->hasComponent(component_id)) geometry_actor = vtk->geometry_actor_manager_->getComponentActor(component_id); - const GeometrySubshapeIndex* geom_index = nullptr; - if (auto geom_data = this->model_query_->getGeometryVtkDataByComponent(component_id)) - geom_index = geom_data->geometry_index; - if (geometry_actor) - geometrySelectManager_->setSelectActor(geometry_actor, geom_index); + geometrySelectManager_->setSelectActor(geometry_actor); else geometrySelectManager_->setSelectActor({}); }); diff --git a/app/render/test/TestGeometryShapePicker.cpp b/app/render/test/TestGeometryShapePicker.cpp index 2775688..11b1de4 100644 --- a/app/render/test/TestGeometryShapePicker.cpp +++ b/app/render/test/TestGeometryShapePicker.cpp @@ -262,7 +262,7 @@ int main(int argc, char** argv) selMgr.bindRenderer(renderer); auto geomActor = gmgr.getComponentActor(component_id); - selMgr.setSelectActor(geomActor, &cadIndex); + selMgr.setSelectActor(geomActor); selMgr.setSelectMode(mode); vtkNew style; -- Gitee From 59f9b6f4853310c7eac56bc66716f51965e03972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=85=BE=E9=9C=96=20=E7=8E=8B?= <2210178950@qq.com> Date: Wed, 1 Jul 2026 21:13:53 +0800 Subject: [PATCH 04/13] =?UTF-8?q?fix(app)=EF=BC=9A=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=BA=86=E7=9F=AD=E5=90=8D=E7=A7=B0=E5=BC=82=E5=B8=B8=E7=BC=A9?= =?UTF-8?q?=E7=95=A5=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/ObjectTree.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/ObjectTree.qml b/app/ObjectTree.qml index b5b2c27..7203308 100644 --- a/app/ObjectTree.qml +++ b/app/ObjectTree.qml @@ -44,7 +44,8 @@ Pane { clip: true flickDeceleration: 100000 boundsBehavior: Flickable.StopAtBounds - columnWidthProvider: function(column) { return treeView.width } + columnWidthProvider: function(column) { return colWidth } + property real colWidth: treeView.width property int toggleExpandRow: -1 onExpanded: (row, depth) => toggleExpandRow = row -- Gitee From d0cf82bca51e18d227af85ffc5b45f04397e510f Mon Sep 17 00:00:00 2001 From: hypf Date: Thu, 2 Jul 2026 19:40:05 +0800 Subject: [PATCH 05/13] =?UTF-8?q?fix(app)=EF=BC=9A=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=82=B9=E5=87=BB=E5=87=A0=E4=BD=95=E8=BE=B9=E4=B9=8B=E5=90=8E?= =?UTF-8?q?=E9=AB=98=E4=BA=AE=E6=9C=AA=E9=80=89=E4=B8=AD=E7=9A=84=E5=87=A0?= =?UTF-8?q?=E4=BD=95=E8=BE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/render/GeometryActor.cpp | 94 ++++++++++++++++++++++++ app/render/GeometryActor.h | 6 ++ app/render/GeometryActorSelectOp.cpp | 10 +++ app/render/GeometryActorSelectOp.h | 3 + app/render/GeometrySelectorHighlight.cpp | 39 +++++++--- 5 files changed, 143 insertions(+), 9 deletions(-) diff --git a/app/render/GeometryActor.cpp b/app/render/GeometryActor.cpp index 2caf84b..af5e0d4 100644 --- a/app/render/GeometryActor.cpp +++ b/app/render/GeometryActor.cpp @@ -16,7 +16,88 @@ #include #include +#include #include + +static vtkSmartPointer findSubIdArray(vtkPolyData* pd, const OccShapeHandle& occShape) +{ + if (!pd || occShape.IsNull()) + return nullptr; + + vtkCellData* cd = pd->GetCellData(); + if (!cd) + return nullptr; + + const vtkIdType nCells = pd->GetNumberOfCells(); + if (nCells <= 0) + return nullptr; + + vtkDataArray* best = nullptr; + vtkIdType bestValidCount = 0; + bool bestHasLineValid = false; + + for (int i = 0; i < cd->GetNumberOfArrays(); ++i) { + vtkDataArray* a = cd->GetArray(i); + if (!a) + continue; + if (a->GetNumberOfComponents() != 1) + continue; + if (a->GetNumberOfTuples() != nCells) + continue; + + const char* name = a->GetName(); + if (name) { + if (std::strcmp(name, "vtkOriginalCellIds") == 0) + continue; + if (std::strcmp(name, "vtkOriginalPointIds") == 0) + continue; + } + + vtkIdType validCount = 0; + bool hasLineValid = false; + for (vtkIdType c = 0; c < nCells; ++c) { + IVtk_IdType sid = static_cast(a->GetTuple1(c)); + if (sid > 0) { + try { + if (!occShape->GetSubShape(sid).IsNull()) { + ++validCount; + if (!hasLineValid && pd->GetCellType(c) == VTK_LINE) + hasLineValid = true; + } + } catch (...) { + } + } + } + + bool better = false; + if (!best) { + better = true; + } else if (hasLineValid && !bestHasLineValid) { + better = true; + } else if (!hasLineValid && bestHasLineValid) { + } else if (validCount > bestValidCount) { + better = true; + } + + if (better) { + bestValidCount = validCount; + bestHasLineValid = hasLineValid; + best = a; + } + } + + if (best && bestValidCount > 0) { + spdlog::info("[GeometryActor] found subId array '{}' valid={}/{} hasLine={}", + (best->GetName() ? best->GetName() : "(null)"), + static_cast(bestValidCount), static_cast(nCells), + bestHasLineValid ? "yes" : "no"); + return best; + } + + spdlog::warn("[GeometryActor] no valid subId array found in polydata with {} cells", static_cast(nCells)); + return nullptr; +} + GeometryActor::GeometryActor(vtkRenderer* renderer, GeometryRenderMode render_mode) { this->renderer_ = renderer; @@ -93,6 +174,9 @@ void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) if (!poly_only) poly_only = vtkSmartPointer::New(); + line_sub_id_array_ = findSubIdArray(line_only, occ_shape_); + poly_sub_id_array_ = findSubIdArray(poly_only, occ_shape_); + auto EnsureCellRgbScalars = [](vtkPolyData* pd, const unsigned char rgb[3]) -> vtkUnsignedCharArray* { if (!pd) return nullptr; @@ -214,4 +298,14 @@ const OccShapeHandle& GeometryActor::getOccShape() const const GeometrySubshapeIndex* GeometryActor::geometryIndex() const noexcept { return geometry_index_; +} + +const vtkDataArray* GeometryActor::lineSubIdArray() const noexcept +{ + return line_sub_id_array_.GetPointer(); +} + +const vtkDataArray* GeometryActor::polySubIdArray() const noexcept +{ + return poly_sub_id_array_.GetPointer(); } \ No newline at end of file diff --git a/app/render/GeometryActor.h b/app/render/GeometryActor.h index cf31d6a..3bbe8de 100644 --- a/app/render/GeometryActor.h +++ b/app/render/GeometryActor.h @@ -4,8 +4,10 @@ #include "GeometryDataVtk.h" #include "GeometrySubshapeIndex.h" #include +#include #include #include +#include #include #include @@ -32,6 +34,8 @@ public: const vtkActor* lineActor() const noexcept; const OccShapeHandle& getOccShape() const; const GeometrySubshapeIndex* geometryIndex() const noexcept; + const vtkDataArray* lineSubIdArray() const noexcept; + const vtkDataArray* polySubIdArray() const noexcept; private: void deleteGeometryActor(); @@ -45,6 +49,8 @@ private: vtkNew poly_actor_; vtkNew line_actor_; vtkRenderer* renderer_; + vtkSmartPointer line_sub_id_array_; + vtkSmartPointer poly_sub_id_array_; }; #endif \ No newline at end of file diff --git a/app/render/GeometryActorSelectOp.cpp b/app/render/GeometryActorSelectOp.cpp index af3ebac..8ab88ef 100644 --- a/app/render/GeometryActorSelectOp.cpp +++ b/app/render/GeometryActorSelectOp.cpp @@ -42,3 +42,13 @@ const GeometrySubshapeIndex* GeometryActorSelectOp::getGeometryIndex() { return geometry_actor_->geometryIndex(); } + +const vtkDataArray* GeometryActorSelectOp::getLineSubIdArray() const +{ + return geometry_actor_->lineSubIdArray(); +} + +const vtkDataArray* GeometryActorSelectOp::getPolySubIdArray() const +{ + return geometry_actor_->polySubIdArray(); +} diff --git a/app/render/GeometryActorSelectOp.h b/app/render/GeometryActorSelectOp.h index 21a1957..14dcf14 100644 --- a/app/render/GeometryActorSelectOp.h +++ b/app/render/GeometryActorSelectOp.h @@ -2,6 +2,7 @@ #define GEOMETRY_ACTOR_SELECT_OP_H #include #include +#include #include #include "GeometryActor.h" @@ -30,6 +31,8 @@ public: vtkProp& getLineActor(); const OccShapeHandle& getOccShape(); const GeometrySubshapeIndex* getGeometryIndex(); + const vtkDataArray* getLineSubIdArray() const; + const vtkDataArray* getPolySubIdArray() const; private: std::shared_ptr geometry_actor_; diff --git a/app/render/GeometrySelectorHighlight.cpp b/app/render/GeometrySelectorHighlight.cpp index 75f70de..09be02b 100644 --- a/app/render/GeometrySelectorHighlight.cpp +++ b/app/render/GeometrySelectorHighlight.cpp @@ -21,6 +21,7 @@ #include +#include #include static constexpr IVtk_SelectionMode kSelVertex = SM_Vertex; @@ -148,6 +149,14 @@ static vtkDataArray* detectSubIdArrayByValue(vtkPolyData* pd, IVtk_IdType picked if (a->GetNumberOfTuples() != nCells) continue; + const char* name = a->GetName(); + if (name) { + if (std::strcmp(name, "vtkOriginalCellIds") == 0) + continue; + if (std::strcmp(name, "vtkOriginalPointIds") == 0) + continue; + } + vtkIdType hits = 0; for (vtkIdType c = 0; c < nCells; ++c) { if (static_cast(a->GetTuple1(c)) == pickedSubId) @@ -221,6 +230,8 @@ struct GeomTargetData { vtkActor* lineActor = nullptr; OccShapeHandle occShape; const GeometrySubshapeIndex* geomIndex = nullptr; + const vtkDataArray* lineSubIdArr = nullptr; + const vtkDataArray* polySubIdArr = nullptr; bool valid() const { return !occShape.IsNull(); } }; @@ -235,6 +246,8 @@ static GeomTargetData getTargetData(GeometryActorSelectOpFactory& factory) d.lineActor = dynamic_cast(&op->getLineActor()); d.occShape = op->getOccShape(); d.geomIndex = op->getGeometryIndex(); + d.lineSubIdArr = op->getLineSubIdArray(); + d.polySubIdArr = op->getPolySubIdArray(); return d; } @@ -322,7 +335,9 @@ void GeometryFaceSelectorHighlight::select(double posx, double posy) selections_.erase(it); vtkPolyData* pd = actorPoly(target.polyActor); - if (!face_sub_id_arr_ && pd) + if (!face_sub_id_arr_ && target.polySubIdArr) + face_sub_id_arr_ = const_cast(target.polySubIdArr); + else if (!face_sub_id_arr_ && pd) face_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "FacePd"); applyHighlight(); @@ -354,7 +369,7 @@ void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory picker_->SetSelectionMode(oldTarget.polyActor, kSelFace, false); picker_->SetSelectionMode(oldTarget.polyActor, kSelEdge, false); picker_->SetSelectionMode(oldTarget.polyActor, kSelVertex, false); - } + } if (oldTarget.lineActor) { picker_->SetSelectionMode(oldTarget.lineActor, kSelFace, false); picker_->SetSelectionMode(oldTarget.lineActor, kSelEdge, false); @@ -394,7 +409,7 @@ void GeometryFaceSelectorHighlight::configurePicker() picker_->SetSelectionMode(target.lineActor, kSelFace, false); picker_->SetSelectionMode(target.lineActor, kSelEdge, false); picker_->SetSelectionMode(target.lineActor, kSelVertex, false); - } +} } // ─── Edge ────────────────────────────────────────────── @@ -481,7 +496,9 @@ void GeometryEdgeSelectorHighlight::select(double posx, double posy) selections_.erase(it); vtkPolyData* pd = actorPoly(target.lineActor); - if (!line_sub_id_arr_ && pd) + if (!line_sub_id_arr_ && target.lineSubIdArr) + line_sub_id_arr_ = const_cast(target.lineSubIdArr); + else if (!line_sub_id_arr_ && pd) line_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "LinePd"); applyHighlight(); @@ -518,7 +535,7 @@ void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory picker_->SetSelectionMode(oldTarget.lineActor, kSelFace, false); picker_->SetSelectionMode(oldTarget.lineActor, kSelEdge, false); picker_->SetSelectionMode(oldTarget.lineActor, kSelVertex, false); - } + } picker_->InitializePickList(); } clear(); @@ -641,7 +658,9 @@ void GeometryVertexSelectorHighlight::select(double posx, double posy) selections_.erase(it); vtkPolyData* pd = actorPoly(target.lineActor); - if (!line_sub_id_arr_ && pd) + if (!line_sub_id_arr_ && target.lineSubIdArr) + line_sub_id_arr_ = const_cast(target.lineSubIdArr); + else if (!line_sub_id_arr_ && pd) line_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "LinePd"); applyHighlight(); @@ -673,7 +692,7 @@ void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFacto picker_->SetSelectionMode(oldTarget.polyActor, kSelFace, false); picker_->SetSelectionMode(oldTarget.polyActor, kSelEdge, false); picker_->SetSelectionMode(oldTarget.polyActor, kSelVertex, false); - } + } if (oldTarget.lineActor) { picker_->SetSelectionMode(oldTarget.lineActor, kSelFace, false); picker_->SetSelectionMode(oldTarget.lineActor, kSelEdge, false); @@ -710,7 +729,7 @@ void GeometryVertexSelectorHighlight::configurePicker() picker_->SetSelectionMode(target.polyActor, kSelFace, false); picker_->SetSelectionMode(target.polyActor, kSelEdge, false); picker_->SetSelectionMode(target.polyActor, kSelVertex, false); - } +} picker_->SetSelectionMode(target.lineActor, kSelVertex, true); picker_->SetSelectionMode(target.lineActor, kSelEdge, false); @@ -843,7 +862,9 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) } vtkPolyData* pd = actorPoly(target.polyActor); - if (!face_sub_id_arr_ && pd) + if (!face_sub_id_arr_ && target.polySubIdArr) + face_sub_id_arr_ = const_cast(target.polySubIdArr); + else if (!face_sub_id_arr_ && pd) face_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "SolidPd"); applyHighlight(); -- Gitee From 3e5164eed8b8fb577a9c3deb2b27a3e0c4d49122 Mon Sep 17 00:00:00 2001 From: hypf Date: Sat, 4 Jul 2026 17:07:06 +0800 Subject: [PATCH 06/13] =?UTF-8?q?refactor(app)=EF=BC=9A=E9=AB=98=E4=BA=AE?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E4=B8=8E=E6=A8=A1=E5=9E=8B=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E8=A7=A3=E8=80=A6=EF=BC=8C=E6=9E=84=E5=BB=BA=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E9=AB=98=E4=BA=AEactor=EF=BC=88=E4=B8=8E=E7=BD=91=E6=A0=BC?= =?UTF-8?q?=E9=AB=98=E4=BA=AE=E5=AF=B9=E9=BD=90=EF=BC=89=EF=BC=9B=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E5=87=A0=E4=BD=95=E5=8F=82=E6=95=B0=E7=BA=BF=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=EF=BC=8C=E5=B9=B6=E6=A0=B9=E6=8D=AE=E8=AF=84=E5=AE=A1?= =?UTF-8?q?=E6=84=8F=E8=A7=81=E8=BF=9B=E8=A1=8C=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/render/GeometryActor.cpp | 176 +++-- app/render/GeometryActor.h | 16 + app/render/GeometryActorManager.cpp | 2 +- app/render/GeometryActorManager.h | 2 +- app/render/GeometryActorSelectOp.cpp | 30 +- app/render/GeometryActorSelectOp.h | 14 +- app/render/GeometrySelectManager.cpp | 7 +- app/render/GeometrySelectManager.h | 10 +- app/render/GeometrySelectorHighlight.cpp | 794 ++++++++--------------- app/render/GeometrySelectorHighlight.h | 35 +- app/render/QRenderWindow.cpp | 9 +- 11 files changed, 460 insertions(+), 635 deletions(-) diff --git a/app/render/GeometryActor.cpp b/app/render/GeometryActor.cpp index af5e0d4..3c77fe8 100644 --- a/app/render/GeometryActor.cpp +++ b/app/render/GeometryActor.cpp @@ -2,7 +2,7 @@ #include "Core.h" #include #include -#include +#include #include #include #include @@ -11,11 +11,8 @@ #include #include #include -#include #include -#include -#include #include #include @@ -123,6 +120,9 @@ bool GeometryActor::getIsEdgeRender() void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) { + // 全局:开一次 + vtkMapper::SetResolveCoincidentTopologyToPolygonOffset(); + OccShapeHandle aShapeImpl = new IVtkOCC_Shape(geometry_data.shape); aShapeImpl->SetId(static_cast(geometry_data.component_id)); this->occ_shape_ = aShapeImpl; @@ -177,69 +177,87 @@ void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) line_sub_id_array_ = findSubIdArray(line_only, occ_shape_); poly_sub_id_array_ = findSubIdArray(poly_only, occ_shape_); - auto EnsureCellRgbScalars = [](vtkPolyData* pd, const unsigned char rgb[3]) -> vtkUnsignedCharArray* { - if (!pd) - return nullptr; - vtkCellData* cd = pd->GetCellData(); - if (!cd) - return nullptr; - - vtkUnsignedCharArray* colors = vtkUnsignedCharArray::SafeDownCast(cd->GetScalars()); - if (!colors || colors->GetNumberOfComponents() != 3 || colors->GetNumberOfTuples() != pd->GetNumberOfCells()) { - vtkNew c; - c->SetName("CellColors"); - c->SetNumberOfComponents(3); - c->SetNumberOfTuples(pd->GetNumberOfCells()); - colors = c.GetPointer(); - cd->SetScalars(c); - } - - for (vtkIdType i = 0; i < pd->GetNumberOfCells(); ++i) - colors->SetTypedTuple(i, rgb); - - colors->Modified(); - pd->GetCellData()->Modified(); - pd->Modified(); - return colors; - }; - - unsigned char faceBase[3] = { 200, 200, 200 }; - if (this->poly_actor_ && this->poly_actor_->GetProperty()) { - double c[3]; - this->poly_actor_->GetProperty()->GetColor(c); - faceBase[0] = static_cast(std::clamp(static_cast(std::lround(c[0] * 255.0)), 0, 255)); - faceBase[1] = static_cast(std::clamp(static_cast(std::lround(c[1] * 255.0)), 0, 255)); - faceBase[2] = static_cast(std::clamp(static_cast(std::lround(c[2] * 255.0)), 0, 255)); + NCollection_Map edgeVertexIds; + for (TopExp_Explorer exp(geometry_data.shape, TopAbs_EDGE); exp.More(); exp.Next()) { + IVtk_IdType id = aShapeImpl->GetSubShapeId(exp.Current()); + if (id >= 0) edgeVertexIds.Add(id); + } + for (TopExp_Explorer exp(geometry_data.shape, TopAbs_VERTEX); exp.More(); exp.Next()) { + IVtk_IdType id = aShapeImpl->GetSubShapeId(exp.Current()); + if (id >= 0) edgeVertexIds.Add(id); } - const unsigned char lineBase[3] = { 0, 0, 0 }; - - EnsureCellRgbScalars(poly_only, faceBase); - EnsureCellRgbScalars(line_only, lineBase); + auto lineEdgeFilter = vtkSmartPointer::New(); + lineEdgeFilter->SetInputData(line_only); + lineEdgeFilter->SetDoFiltering(true); + if (line_sub_id_array_ && line_sub_id_array_->GetName()) + lineEdgeFilter->SetIdsArrayName(line_sub_id_array_->GetName()); + lineEdgeFilter->SetData(edgeVertexIds); vtkNew poly_mapper; poly_mapper->SetInputData(poly_only); - poly_mapper->ScalarVisibilityOn(); - poly_mapper->SetScalarModeToUseCellData(); - poly_mapper->SetColorModeToDirectScalars(); + poly_mapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, 0); - this->poly_actor_->SetMapper(poly_mapper); - this->renderer_->AddActor(this->poly_actor_); + poly_actor_->SetMapper(poly_mapper); + poly_actor_->GetProperty()->SetColor(200.0 / 255.0, 200.0 / 255.0, 200.0 / 255.0); + renderer_->AddActor(poly_actor_); - vtkNew line_mapper; - line_mapper->SetInputData(line_only); - line_mapper->ScalarVisibilityOn(); - line_mapper->SetScalarModeToUseCellData(); - line_mapper->SetColorModeToDirectScalars(); - line_mapper->SetRelativeCoincidentTopologyLineOffsetParameters(0, -0.1); + poly_hl_filter_ = vtkSmartPointer::New(); + poly_hl_filter_->SetInputData(poly_only); + poly_hl_filter_->SetDoFiltering(true); + if (poly_sub_id_array_ && poly_sub_id_array_->GetName()) + poly_hl_filter_->SetIdsArrayName(poly_sub_id_array_->GetName()); - this->line_actor_->SetMapper(line_mapper); - this->line_actor_->GetProperty()->LightingOff(); - this->line_actor_->GetProperty()->SetLineWidth(2.0); - this->line_actor_->GetProperty()->RenderLinesAsTubesOn(); - this->line_actor_->GetProperty()->SetPointSize(6.0); + poly_hl_mapper_ = vtkSmartPointer::New(); + poly_hl_mapper_->SetInputConnection(poly_hl_filter_->GetOutputPort()); + // 相对显示 mapper 默认值:多边形 (0,-1) + poly_hl_mapper_->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, -0.5); - this->renderer_->AddActor(this->line_actor_); + + poly_hl_actor_ = vtkSmartPointer::New(); + poly_hl_actor_->SetMapper(poly_hl_mapper_); + poly_hl_actor_->GetProperty()->SetColor(1.0, 0.0, 0.0); + poly_hl_actor_->GetProperty()->SetOpacity(1); + poly_hl_actor_->SetVisibility(false); + poly_hl_actor_->PickableOff(); + renderer_->AddActor(poly_hl_actor_); + + vtkNew line_mapper; + line_mapper->SetInputConnection(lineEdgeFilter->GetOutputPort()); + line_mapper->SetRelativeCoincidentTopologyLineOffsetParameters(0, 4); + line_mapper->SetRelativeCoincidentTopologyPointOffsetParameter(8); + + line_actor_->SetMapper(line_mapper); + line_actor_->GetProperty()->LightingOff(); + line_actor_->GetProperty()->SetLineWidth(2.0); + line_actor_->GetProperty()->RenderLinesAsTubesOn(); + line_actor_->GetProperty()->SetPointSize(6.0); + line_actor_->GetProperty()->SetColor(0.0, 0.0, 0.0); + renderer_->AddActor(line_actor_); + + line_hl_filter_ = vtkSmartPointer::New(); + line_hl_filter_->SetInputData(line_only); + line_hl_filter_->SetDoFiltering(true); + if (line_sub_id_array_ && line_sub_id_array_->GetName()) + line_hl_filter_->SetIdsArrayName(line_sub_id_array_->GetName()); + + line_hl_mapper_ = vtkSmartPointer::New(); + line_hl_mapper_->SetInputConnection(line_hl_filter_->GetOutputPort()); + // 相对显示 mapper 默认值:线 (0,-5),点 (-10) + line_hl_mapper_->SetRelativeCoincidentTopologyLineOffsetParameters(0, -1); + line_hl_mapper_->SetRelativeCoincidentTopologyPointOffsetParameter(-2); + + line_hl_actor_ = vtkSmartPointer::New(); + line_hl_actor_->SetMapper(line_hl_mapper_); + line_hl_actor_->GetProperty()->SetColor(1.0, 0.0, 0.0); + line_hl_actor_->GetProperty()->SetOpacity(0.5); + line_hl_actor_->GetProperty()->RenderLinesAsTubesOn(); + line_hl_actor_->GetProperty()->SetLineWidth(3.0); + line_hl_actor_->GetProperty()->SetPointSize(8.0); + line_hl_actor_->GetProperty()->LightingOff(); + line_hl_actor_->SetVisibility(false); + line_hl_actor_->PickableOff(); + renderer_->AddActor(line_hl_actor_); spdlog::info("[GeometryActor] component={} actors added, face_cells={} line_cells={}", geometry_data.component_id, static_cast(poly_only->GetNumberOfCells()), static_cast(line_only->GetNumberOfCells())); @@ -250,6 +268,8 @@ void GeometryActor::deleteGeometryActor() if (this->renderer_) { renderer_->RemoveActor(this->poly_actor_); renderer_->RemoveActor(this->line_actor_); + renderer_->RemoveActor(this->poly_hl_actor_); + renderer_->RemoveActor(this->line_hl_actor_); } } @@ -308,4 +328,44 @@ const vtkDataArray* GeometryActor::lineSubIdArray() const noexcept const vtkDataArray* GeometryActor::polySubIdArray() const noexcept { return poly_sub_id_array_.GetPointer(); +} + +vtkActor* GeometryActor::polyHLActor() noexcept +{ + return poly_hl_actor_.GetPointer(); +} + +const vtkActor* GeometryActor::polyHLActor() const noexcept +{ + return poly_hl_actor_.GetPointer(); +} + +vtkActor* GeometryActor::lineHLActor() noexcept +{ + return line_hl_actor_.GetPointer(); +} + +const vtkActor* GeometryActor::lineHLActor() const noexcept +{ + return line_hl_actor_.GetPointer(); +} + +IVtkTools_SubPolyDataFilter* GeometryActor::polyHLFilter() noexcept +{ + return poly_hl_filter_.GetPointer(); +} + +const IVtkTools_SubPolyDataFilter* GeometryActor::polyHLFilter() const noexcept +{ + return poly_hl_filter_.GetPointer(); +} + +IVtkTools_SubPolyDataFilter* GeometryActor::lineHLFilter() noexcept +{ + return line_hl_filter_.GetPointer(); +} + +const IVtkTools_SubPolyDataFilter* GeometryActor::lineHLFilter() const noexcept +{ + return line_hl_filter_.GetPointer(); } \ No newline at end of file diff --git a/app/render/GeometryActor.h b/app/render/GeometryActor.h index 3bbe8de..b6aacd9 100644 --- a/app/render/GeometryActor.h +++ b/app/render/GeometryActor.h @@ -11,6 +11,7 @@ #include #include +#include typedef Handle(IVtkOCC_Shape) OccShapeHandle; class GeometryActor { @@ -32,6 +33,14 @@ public: const vtkActor* polyActor() const noexcept; vtkActor* lineActor() noexcept; const vtkActor* lineActor() const noexcept; + vtkActor* polyHLActor() noexcept; + const vtkActor* polyHLActor() const noexcept; + vtkActor* lineHLActor() noexcept; + const vtkActor* lineHLActor() const noexcept; + IVtkTools_SubPolyDataFilter* polyHLFilter() noexcept; + const IVtkTools_SubPolyDataFilter* polyHLFilter() const noexcept; + IVtkTools_SubPolyDataFilter* lineHLFilter() noexcept; + const IVtkTools_SubPolyDataFilter* lineHLFilter() const noexcept; const OccShapeHandle& getOccShape() const; const GeometrySubshapeIndex* geometryIndex() const noexcept; const vtkDataArray* lineSubIdArray() const noexcept; @@ -51,6 +60,13 @@ private: vtkRenderer* renderer_; vtkSmartPointer line_sub_id_array_; vtkSmartPointer poly_sub_id_array_; + + vtkSmartPointer poly_hl_filter_; + vtkSmartPointer line_hl_filter_; + vtkSmartPointer poly_hl_mapper_; + vtkSmartPointer line_hl_mapper_; + vtkSmartPointer poly_hl_actor_; + vtkSmartPointer line_hl_actor_; }; #endif \ No newline at end of file diff --git a/app/render/GeometryActorManager.cpp b/app/render/GeometryActorManager.cpp index 62be2a0..3f20dca 100644 --- a/app/render/GeometryActorManager.cpp +++ b/app/render/GeometryActorManager.cpp @@ -16,7 +16,7 @@ void GeometryActorManager::bindRender(vtkRenderer* renderer) this->renderer_ = renderer; } -std::shared_ptr GeometryActorManager::getComponentActor(Index component_id) const +std::shared_ptr GeometryActorManager::getComponentActor(Index component_id) const { auto it = component_actors_.find(component_id); if (it != component_actors_.end()) { diff --git a/app/render/GeometryActorManager.h b/app/render/GeometryActorManager.h index 4a3588a..a01c4ad 100644 --- a/app/render/GeometryActorManager.h +++ b/app/render/GeometryActorManager.h @@ -15,7 +15,7 @@ public: ~GeometryActorManager(); void bindRender(vtkRenderer* renderer); - std::shared_ptr getComponentActor(Index component_id) const; + std::shared_ptr getComponentActor(Index component_id) const; GeometryRenderMode getGeometryRenderMode(Index component_id); bool getIsEdgeRender(Index component_id); bool hasComponent(Index component_id) const; diff --git a/app/render/GeometryActorSelectOp.cpp b/app/render/GeometryActorSelectOp.cpp index 8ab88ef..9fdbc37 100644 --- a/app/render/GeometryActorSelectOp.cpp +++ b/app/render/GeometryActorSelectOp.cpp @@ -1,8 +1,10 @@ #include "GeometryActorSelectOp.h" #include "GeometryActor.h" +#include +#include GeometryActorSelectOpFactory::GeometryActorSelectOpFactory() = default; -GeometryActorSelectOpFactory::GeometryActorSelectOpFactory(std::weak_ptr geometry_actor) +GeometryActorSelectOpFactory::GeometryActorSelectOpFactory(std::weak_ptr geometry_actor) : geometry_actor_(geometry_actor) { } @@ -15,7 +17,7 @@ std::optional GeometryActorSelectOpFactory::lock() return {}; } -GeometryActorSelectOp::GeometryActorSelectOp(std::shared_ptr geometry_actor) +GeometryActorSelectOp::GeometryActorSelectOp(std::shared_ptr geometry_actor) : geometry_actor_(geometry_actor) { if (!geometry_actor_) { @@ -25,12 +27,32 @@ GeometryActorSelectOp::GeometryActorSelectOp(std::shared_ptr(geometry_actor_->polyActor()); + return *geometry_actor_->polyActor(); } vtkProp& GeometryActorSelectOp::getLineActor() { - return *const_cast(geometry_actor_->lineActor()); + return *geometry_actor_->lineActor(); +} + +vtkActor& GeometryActorSelectOp::getPolyHLActor() +{ + return *geometry_actor_->polyHLActor(); +} + +vtkActor& GeometryActorSelectOp::getLineHLActor() +{ + return *geometry_actor_->lineHLActor(); +} + +IVtkTools_SubPolyDataFilter& GeometryActorSelectOp::getPolyHLFilter() +{ + return *geometry_actor_->polyHLFilter(); +} + +IVtkTools_SubPolyDataFilter& GeometryActorSelectOp::getLineHLFilter() +{ + return *geometry_actor_->lineHLFilter(); } const OccShapeHandle& GeometryActorSelectOp::getOccShape() diff --git a/app/render/GeometryActorSelectOp.h b/app/render/GeometryActorSelectOp.h index 14dcf14..e345831 100644 --- a/app/render/GeometryActorSelectOp.h +++ b/app/render/GeometryActorSelectOp.h @@ -8,33 +8,39 @@ #include "GeometryActor.h" class GeometryActorSelectOp; +class IVtkTools_SubPolyDataFilter; +class vtkActor; class GeometryActorSelectOpFactory { friend GeometryActorSelectOp; public: GeometryActorSelectOpFactory(); - GeometryActorSelectOpFactory(std::weak_ptr geometry_actor); + GeometryActorSelectOpFactory(std::weak_ptr geometry_actor); std::optional lock(); private: - std::weak_ptr geometry_actor_; + std::weak_ptr geometry_actor_; }; class GeometryActorSelectOp { friend GeometryActorSelectOpFactory; public: - GeometryActorSelectOp(std::shared_ptr geometry_actor); + GeometryActorSelectOp(std::shared_ptr geometry_actor); vtkProp& getPolyActor(); vtkProp& getLineActor(); + vtkActor& getPolyHLActor(); + vtkActor& getLineHLActor(); + IVtkTools_SubPolyDataFilter& getPolyHLFilter(); + IVtkTools_SubPolyDataFilter& getLineHLFilter(); const OccShapeHandle& getOccShape(); const GeometrySubshapeIndex* getGeometryIndex(); const vtkDataArray* getLineSubIdArray() const; const vtkDataArray* getPolySubIdArray() const; private: - std::shared_ptr geometry_actor_; + std::shared_ptr geometry_actor_; }; #endif // GEOMETRY_ACTOR_SELECT_OP_H diff --git a/app/render/GeometrySelectManager.cpp b/app/render/GeometrySelectManager.cpp index 292ce2e..c9c6cf9 100644 --- a/app/render/GeometrySelectManager.cpp +++ b/app/render/GeometrySelectManager.cpp @@ -21,7 +21,7 @@ void GeometrySelectManager::select(double posx, double posy) } } -void GeometrySelectManager::setSelectActor(std::weak_ptr geom_actor) +void GeometrySelectManager::setSelectActor(std::weak_ptr geom_actor) { this->cur_geom_actor_ = GeometryActorSelectOpFactory { geom_actor }; if (this->selector_) { @@ -72,6 +72,11 @@ void GeometrySelectManager::clearSelection() std::unique_ptr GeometrySelectManager::getSelection() { std::unique_ptr selection = std::make_unique(); + + if (!this->selector_) + { + return nullptr; + } if (this->select_mode_ == SelectMode::Vertex) { for (const auto& id : this->selector_->get().ids) { diff --git a/app/render/GeometrySelectManager.h b/app/render/GeometrySelectManager.h index 6b9b45d..5f4a6a2 100644 --- a/app/render/GeometrySelectManager.h +++ b/app/render/GeometrySelectManager.h @@ -18,18 +18,18 @@ public: void bindRenderer(vtkRenderer* renderer); void select(double posx, double posy); - void setSelectActor(std::weak_ptr geom_actor); + void setSelectActor(std::weak_ptr geom_actor); void setSelectMode(SelectMode select_mode); void clearSelection(); std::unique_ptr getSelection(); private: std::optional cur_geom_actor_ {}; - SelectMode select_mode_; + SelectMode select_mode_ { SelectMode::None }; vtkNew selection_actor_; vtkNew selection_mapper_; - vtkSmartPointer picker_; - vtkRenderer* renderer_; - std::unique_ptr selector_; + vtkSmartPointer picker_ {}; + vtkRenderer* renderer_ { nullptr }; + std::unique_ptr selector_ {}; }; #endif // GEOMETRY_SELECT_MANAGER_H diff --git a/app/render/GeometrySelectorHighlight.cpp b/app/render/GeometrySelectorHighlight.cpp index 09be02b..7eb3a3b 100644 --- a/app/render/GeometrySelectorHighlight.cpp +++ b/app/render/GeometrySelectorHighlight.cpp @@ -5,24 +5,15 @@ #include #include +#include #include #include #include #include #include -#include -#include -#include -#include #include #include -#include - -#include - -#include -#include static constexpr IVtk_SelectionMode kSelVertex = SM_Vertex; static constexpr IVtk_SelectionMode kSelEdge = SM_Edge; @@ -97,158 +88,14 @@ static std::optional mapSubshapeToGeomId(const OccShapeHandle& occShape, return std::nullopt; } -static vtkPolyData* actorPoly(vtkActor* a) +static void flushHighlight(IVtkTools_SubPolyDataFilter* filter, vtkActor* hlActor, bool visible, vtkRenderer* renderer) { - if (!a) - return nullptr; - auto* m = vtkPolyDataMapper::SafeDownCast(a->GetMapper()); - if (!m) - return nullptr; - return m->GetInput(); -} - -static vtkUnsignedCharArray* cellColors(vtkPolyData* pd) -{ - if (!pd) - return nullptr; - return vtkUnsignedCharArray::SafeDownCast(pd->GetCellData()->GetScalars()); -} - -static void readBaseRgb(vtkUnsignedCharArray* colors, unsigned char outBase[3], const unsigned char fallback[3]) -{ - outBase[0] = fallback[0]; - outBase[1] = fallback[1]; - outBase[2] = fallback[2]; - if (!colors || colors->GetNumberOfTuples() <= 0 || colors->GetNumberOfComponents() != 3) + if (!filter || !hlActor || !renderer) return; - unsigned char rgb[3] { fallback[0], fallback[1], fallback[2] }; - colors->GetTypedTuple(0, rgb); - outBase[0] = rgb[0]; - outBase[1] = rgb[1]; - outBase[2] = rgb[2]; -} - -static vtkDataArray* detectSubIdArrayByValue(vtkPolyData* pd, IVtk_IdType pickedSubId, const char* tag) -{ - if (!pd) - return nullptr; - vtkCellData* cd = pd->GetCellData(); - if (!cd) - return nullptr; - - vtkDataArray* best = nullptr; - vtkIdType bestHits = 0; - const vtkIdType nCells = pd->GetNumberOfCells(); - - for (int i = 0; i < cd->GetNumberOfArrays(); ++i) { - vtkDataArray* a = cd->GetArray(i); - if (!a) - continue; - if (a->GetNumberOfComponents() != 1) - continue; - if (a->GetNumberOfTuples() != nCells) - continue; - - const char* name = a->GetName(); - if (name) { - if (std::strcmp(name, "vtkOriginalCellIds") == 0) - continue; - if (std::strcmp(name, "vtkOriginalPointIds") == 0) - continue; - } - - vtkIdType hits = 0; - for (vtkIdType c = 0; c < nCells; ++c) { - if (static_cast(a->GetTuple1(c)) == pickedSubId) - ++hits; - } - if (hits > bestHits) { - bestHits = hits; - best = a; - } - } - - if (best && bestHits > 0) { - spdlog::info("[{}] detected subId array='{}' hits={}/{} for subId={}", - tag, (best->GetName() ? best->GetName() : "(null)"), static_cast(bestHits), static_cast(nCells), pickedSubId); - return best; - } - - spdlog::warn("[{}] cannot detect subId array by picked subId={}. Dump arrays:", tag, pickedSubId); - for (int i = 0; i < cd->GetNumberOfArrays(); ++i) { - vtkDataArray* a = cd->GetArray(i); - if (!a) - continue; - spdlog::warn(" CellData[{}] name='{}' comps={} tuples={} type={}", - i, (a->GetName() ? a->GetName() : "(null)"), - a->GetNumberOfComponents(), static_cast(a->GetNumberOfTuples()), a->GetDataType()); - } - return nullptr; -} - -static void recolorBySelectedSubIds(vtkPolyData* pd, - vtkDataArray* subIdArr, - vtkUnsignedCharArray* colors, - const std::unordered_map& selected, - const unsigned char base[3]) -{ - if (!pd || !subIdArr || !colors) - return; - - const vtkIdType n = pd->GetNumberOfCells(); - for (vtkIdType c = 0; c < n; ++c) { - const IVtk_IdType sid = static_cast(subIdArr->GetTuple1(c)); - unsigned char rgb[3] { base[0], base[1], base[2] }; - if (selected.count(sid)) { - rgb[0] = 255; - rgb[1] = 0; - rgb[2] = 0; - } - colors->SetTypedTuple(c, rgb); - } - - colors->Modified(); - pd->GetCellData()->Modified(); - pd->Modified(); -} - -static void resetColorsToBase(vtkPolyData* pd, vtkUnsignedCharArray* colors, const unsigned char base[3]) -{ - if (!pd || !colors) - return; - const vtkIdType n = pd->GetNumberOfCells(); - for (vtkIdType c = 0; c < n; ++c) - colors->SetTypedTuple(c, base); - - colors->Modified(); - pd->GetCellData()->Modified(); - pd->Modified(); -} - -struct GeomTargetData { - vtkActor* polyActor = nullptr; - vtkActor* lineActor = nullptr; - OccShapeHandle occShape; - const GeometrySubshapeIndex* geomIndex = nullptr; - const vtkDataArray* lineSubIdArr = nullptr; - const vtkDataArray* polySubIdArr = nullptr; - - bool valid() const { return !occShape.IsNull(); } -}; - -static GeomTargetData getTargetData(GeometryActorSelectOpFactory& factory) -{ - GeomTargetData d; - auto op = factory.lock(); - if (!op) - return d; - d.polyActor = dynamic_cast(&op->getPolyActor()); - d.lineActor = dynamic_cast(&op->getLineActor()); - d.occShape = op->getOccShape(); - d.geomIndex = op->getGeometryIndex(); - d.lineSubIdArr = op->getLineSubIdArray(); - d.polySubIdArr = op->getPolySubIdArray(); - return d; + filter->Modified(); + hlActor->SetVisibility(visible); + if (renderer->GetRenderWindow()) + renderer->GetRenderWindow()->Render(); } // ─── Face ────────────────────────────────────────────── @@ -263,16 +110,14 @@ GeometryFaceSelectorHighlight::~GeometryFaceSelectorHighlight() { clear(); } void GeometryFaceSelectorHighlight::clear() { selections_.clear(); - face_sub_id_arr_ = nullptr; - - auto op = geom_actor_.lock(); - if (op) { - auto* polyActor = dynamic_cast(&op->getPolyActor()); - vtkPolyData* pd = actorPoly(polyActor); - vtkUnsignedCharArray* colors = cellColors(pd); - if (pd && colors) - resetColorsToBase(pd, colors, face_base_); + if (filter_) { + filter_->Clear(); + filter_->Modified(); } + if (hl_actor_) + hl_actor_->SetVisibility(false); + if (renderer_ && renderer_->GetRenderWindow()) + renderer_->GetRenderWindow()->Render(); } GeometrySelectionVtk GeometryFaceSelectorHighlight::get() const @@ -280,38 +125,16 @@ GeometrySelectionVtk GeometryFaceSelectorHighlight::get() const GeometrySelectionVtk s; s.type = ElementEnum::Face; s.component_id = -1; - for (const auto& [subId, geomId] : selections_) { + for (const auto& [subId, geomId] : selections_) s.ids.push_back(geomId); - } return s; } -void GeometryFaceSelectorHighlight::ensureTargetInit() +void GeometryFaceSelectorHighlight::select(double posx, double posy) { - if (target_initialized_) - return; auto op = geom_actor_.lock(); if (!op) return; - auto* polyActor = dynamic_cast(&op->getPolyActor()); - vtkPolyData* pd = actorPoly(polyActor); - vtkUnsignedCharArray* colors = cellColors(pd); - const unsigned char fallback[3] = { 200, 200, 200 }; - readBaseRgb(colors, face_base_, fallback); - if (!pd || !colors) { - spdlog::warn("Face actor has no polydata or no CellData->Scalars. " - "Need GeometryActor::loadShape to create CellColors scalars."); - } - target_initialized_ = true; -} - -void GeometryFaceSelectorHighlight::select(double posx, double posy) -{ - auto target = getTargetData(geom_actor_); - if (!target.polyActor || !target.valid() || !target.geomIndex) - return; - - ensureTargetInit(); const int n = picker_->Pick(posx, posy, 0.0, renderer_); if (n <= 0) @@ -325,8 +148,12 @@ void GeometryFaceSelectorHighlight::select(double posx, double posy) if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) return; + const auto* geomIndex = op->getGeometryIndex(); + if (!geomIndex) + return; + ElementEnum::Type elemType = ElementEnum::None; - auto geomId = mapSubshapeToGeomId(target.occShape, *target.geomIndex, TopAbs_FACE, subId, elemType); + auto geomId = mapSubshapeToGeomId(op->getOccShape(), *geomIndex, TopAbs_FACE, subId, elemType); if (!geomId) return; @@ -334,82 +161,74 @@ void GeometryFaceSelectorHighlight::select(double posx, double posy) if (!inserted) selections_.erase(it); - vtkPolyData* pd = actorPoly(target.polyActor); - if (!face_sub_id_arr_ && target.polySubIdArr) - face_sub_id_arr_ = const_cast(target.polySubIdArr); - else if (!face_sub_id_arr_ && pd) - face_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "FacePd"); + NCollection_List ids; + for (const auto& [sid, gid] : selections_) + ids.Append(sid); - applyHighlight(); -} - -void GeometryFaceSelectorHighlight::applyHighlight() -{ - auto target = getTargetData(geom_actor_); - vtkPolyData* pd = actorPoly(target.polyActor); - vtkUnsignedCharArray* colors = cellColors(pd); - - if (!pd || !colors || !face_sub_id_arr_) - return; - - recolorBySelectedSubIds(pd, face_sub_id_arr_, colors, selections_, face_base_); - - if (renderer_ && renderer_->GetRenderWindow()) - renderer_->GetRenderWindow()->Render(); + if (filter_) + filter_->SetData(ids); + flushHighlight(filter_, hl_actor_, !ids.IsEmpty(), renderer_); } void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { - auto oldTarget = getTargetData(geom_actor_); - if (oldTarget.valid()) { - picker_->SetSelectionMode(oldTarget.occShape, kSelFace, false); - picker_->SetSelectionMode(oldTarget.occShape, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.occShape, kSelVertex, false); - if (oldTarget.polyActor) { - picker_->SetSelectionMode(oldTarget.polyActor, kSelFace, false); - picker_->SetSelectionMode(oldTarget.polyActor, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.polyActor, kSelVertex, false); - } - if (oldTarget.lineActor) { - picker_->SetSelectionMode(oldTarget.lineActor, kSelFace, false); - picker_->SetSelectionMode(oldTarget.lineActor, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.lineActor, kSelVertex, false); + { + auto oldOp = geom_actor_.lock(); + if (oldOp) { + picker_->SetSelectionMode(oldOp->getOccShape(), kSelFace, false); + picker_->SetSelectionMode(oldOp->getOccShape(), kSelEdge, false); + picker_->SetSelectionMode(oldOp->getOccShape(), kSelVertex, false); + auto& poly = dynamic_cast(oldOp->getPolyActor()); + picker_->SetSelectionMode(&poly, kSelFace, false); + picker_->SetSelectionMode(&poly, kSelEdge, false); + picker_->SetSelectionMode(&poly, kSelVertex, false); + auto& line = dynamic_cast(oldOp->getLineActor()); + picker_->SetSelectionMode(&line, kSelFace, false); + picker_->SetSelectionMode(&line, kSelEdge, false); + picker_->SetSelectionMode(&line, kSelVertex, false); + picker_->InitializePickList(); } - picker_->InitializePickList(); } + clear(); geom_actor_ = std::move(geom_actor); - target_initialized_ = false; + filter_ = nullptr; + hl_actor_ = nullptr; + + auto op = geom_actor_.lock(); + if (op) { + filter_ = &op->getPolyHLFilter(); + hl_actor_ = &op->getPolyHLActor(); + } + configurePicker(); } - void GeometryFaceSelectorHighlight::configurePicker() { - auto target = getTargetData(geom_actor_); - if (!target.polyActor || !target.valid()) + auto op = geom_actor_.lock(); + if (!op) return; picker_->PickFromListOn(); picker_->InitializePickList(); - picker_->AddPickList(target.polyActor); - + picker_->AddPickList(&dynamic_cast(op->getPolyActor())); picker_->SetPixelTolerance(toleranceForMode(SelectMode::Face)); - picker_->SetSelectionMode(target.occShape, kSelFace, false); - picker_->SetSelectionMode(target.occShape, kSelEdge, false); - picker_->SetSelectionMode(target.occShape, kSelVertex, false); - picker_->SetSelectionMode(target.occShape, kSelFace, true); + picker_->SetSelectionMode(op->getOccShape(), kSelFace, false); + picker_->SetSelectionMode(op->getOccShape(), kSelEdge, false); + picker_->SetSelectionMode(op->getOccShape(), kSelVertex, false); + picker_->SetSelectionMode(op->getOccShape(), kSelFace, true); - picker_->SetSelectionMode(target.polyActor, kSelFace, true); - picker_->SetSelectionMode(target.polyActor, kSelEdge, false); - picker_->SetSelectionMode(target.polyActor, kSelVertex, false); + auto& poly = dynamic_cast(op->getPolyActor()); + picker_->SetSelectionMode(&poly, kSelFace, true); + picker_->SetSelectionMode(&poly, kSelEdge, false); + picker_->SetSelectionMode(&poly, kSelVertex, false); - if (target.lineActor) { - picker_->SetSelectionMode(target.lineActor, kSelFace, false); - picker_->SetSelectionMode(target.lineActor, kSelEdge, false); - picker_->SetSelectionMode(target.lineActor, kSelVertex, false); -} + auto& line = dynamic_cast(op->getLineActor()); + picker_->SetSelectionMode(&line, kSelFace, false); + picker_->SetSelectionMode(&line, kSelEdge, false); + picker_->SetSelectionMode(&line, kSelVertex, false); } // ─── Edge ────────────────────────────────────────────── @@ -424,16 +243,14 @@ GeometryEdgeSelectorHighlight::~GeometryEdgeSelectorHighlight() { clear(); } void GeometryEdgeSelectorHighlight::clear() { selections_.clear(); - line_sub_id_arr_ = nullptr; - - auto op = geom_actor_.lock(); - if (op) { - auto* lineActor = dynamic_cast(&op->getLineActor()); - vtkPolyData* pd = actorPoly(lineActor); - vtkUnsignedCharArray* colors = cellColors(pd); - if (pd && colors) - resetColorsToBase(pd, colors, line_base_); + if (filter_) { + filter_->Clear(); + filter_->Modified(); } + if (hl_actor_) + hl_actor_->SetVisibility(false); + if (renderer_ && renderer_->GetRenderWindow()) + renderer_->GetRenderWindow()->Render(); } GeometrySelectionVtk GeometryEdgeSelectorHighlight::get() const @@ -441,38 +258,16 @@ GeometrySelectionVtk GeometryEdgeSelectorHighlight::get() const GeometrySelectionVtk s; s.type = ElementEnum::Edge; s.component_id = -1; - for (const auto& [subId, geomId] : selections_) { + for (const auto& [subId, geomId] : selections_) s.ids.push_back(geomId); - } return s; } -void GeometryEdgeSelectorHighlight::ensureTargetInit() +void GeometryEdgeSelectorHighlight::select(double posx, double posy) { - if (target_initialized_) - return; auto op = geom_actor_.lock(); if (!op) return; - auto* lineActor = dynamic_cast(&op->getLineActor()); - vtkPolyData* pd = actorPoly(lineActor); - vtkUnsignedCharArray* colors = cellColors(pd); - const unsigned char fallback[3] = { 0, 0, 0 }; - readBaseRgb(colors, line_base_, fallback); - if (!pd || !colors) { - spdlog::warn("Line actor has no polydata or no CellData->Scalars. " - "Need GeometryActor::loadShape to create CellColors scalars."); - } - target_initialized_ = true; -} - -void GeometryEdgeSelectorHighlight::select(double posx, double posy) -{ - auto target = getTargetData(geom_actor_); - if (!target.lineActor || !target.valid() || !target.geomIndex) - return; - - ensureTargetInit(); const int n = picker_->Pick(posx, posy, 0.0, renderer_); if (n <= 0) @@ -486,8 +281,12 @@ void GeometryEdgeSelectorHighlight::select(double posx, double posy) if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) return; + const auto* geomIndex = op->getGeometryIndex(); + if (!geomIndex) + return; + ElementEnum::Type elemType = ElementEnum::None; - auto geomId = mapSubshapeToGeomId(target.occShape, *target.geomIndex, TopAbs_EDGE, subId, elemType); + auto geomId = mapSubshapeToGeomId(op->getOccShape(), *geomIndex, TopAbs_EDGE, subId, elemType); if (!geomId) return; @@ -495,83 +294,80 @@ void GeometryEdgeSelectorHighlight::select(double posx, double posy) if (!inserted) selections_.erase(it); - vtkPolyData* pd = actorPoly(target.lineActor); - if (!line_sub_id_arr_ && target.lineSubIdArr) - line_sub_id_arr_ = const_cast(target.lineSubIdArr); - else if (!line_sub_id_arr_ && pd) - line_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "LinePd"); - - applyHighlight(); -} - -void GeometryEdgeSelectorHighlight::applyHighlight() -{ - auto target = getTargetData(geom_actor_); - vtkPolyData* pd = actorPoly(target.lineActor); - vtkUnsignedCharArray* colors = cellColors(pd); - - if (!pd || !colors || !line_sub_id_arr_) - return; - - recolorBySelectedSubIds(pd, line_sub_id_arr_, colors, selections_, line_base_); + NCollection_List ids; + for (const auto& [sid, gid] : selections_) + ids.Append(sid); - if (renderer_ && renderer_->GetRenderWindow()) - renderer_->GetRenderWindow()->Render(); + if (filter_) + filter_->SetData(ids); + flushHighlight(filter_, hl_actor_, !ids.IsEmpty(), renderer_); } void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { - auto oldTarget = getTargetData(geom_actor_); - if (oldTarget.valid()) { - picker_->SetSelectionMode(oldTarget.occShape, kSelFace, false); - picker_->SetSelectionMode(oldTarget.occShape, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.occShape, kSelVertex, false); - if (oldTarget.polyActor) { - picker_->SetSelectionMode(oldTarget.polyActor, kSelFace, false); - picker_->SetSelectionMode(oldTarget.polyActor, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.polyActor, kSelVertex, false); + { + auto oldOp = geom_actor_.lock(); + if (oldOp) { + picker_->SetSelectionMode(oldOp->getOccShape(), kSelFace, false); + picker_->SetSelectionMode(oldOp->getOccShape(), kSelEdge, false); + picker_->SetSelectionMode(oldOp->getOccShape(), kSelVertex, false); + auto& poly = dynamic_cast(oldOp->getPolyActor()); + picker_->SetSelectionMode(&poly, kSelFace, false); + picker_->SetSelectionMode(&poly, kSelEdge, false); + picker_->SetSelectionMode(&poly, kSelVertex, false); + auto& line = dynamic_cast(oldOp->getLineActor()); + picker_->SetSelectionMode(&line, kSelFace, false); + picker_->SetSelectionMode(&line, kSelEdge, false); + picker_->SetSelectionMode(&line, kSelVertex, false); + picker_->InitializePickList(); } - if (oldTarget.lineActor) { - picker_->SetSelectionMode(oldTarget.lineActor, kSelFace, false); - picker_->SetSelectionMode(oldTarget.lineActor, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.lineActor, kSelVertex, false); - } - picker_->InitializePickList(); } + clear(); geom_actor_ = std::move(geom_actor); - target_initialized_ = false; + filter_ = nullptr; + hl_actor_ = nullptr; + + auto op = geom_actor_.lock(); + if (op) { + filter_ = &op->getLineHLFilter(); + hl_actor_ = &op->getLineHLActor(); + } + configurePicker(); } void GeometryEdgeSelectorHighlight::configurePicker() { - auto target = getTargetData(geom_actor_); - if (!target.lineActor || !target.valid()) + auto op = geom_actor_.lock(); + if (!op) return; picker_->PickFromListOn(); picker_->InitializePickList(); - picker_->AddPickList(target.lineActor); - if (target.polyActor) - picker_->AddPickList(target.polyActor); - + picker_->AddPickList(&dynamic_cast(op->getLineActor())); + { + auto& poly = dynamic_cast(op->getPolyActor()); + picker_->AddPickList(&poly); + } picker_->SetPixelTolerance(toleranceForMode(SelectMode::Edge)); - picker_->SetSelectionMode(target.occShape, kSelFace, false); - picker_->SetSelectionMode(target.occShape, kSelEdge, false); - picker_->SetSelectionMode(target.occShape, kSelVertex, false); - picker_->SetSelectionMode(target.occShape, kSelEdge, true); + picker_->SetSelectionMode(op->getOccShape(), kSelFace, false); + picker_->SetSelectionMode(op->getOccShape(), kSelEdge, false); + picker_->SetSelectionMode(op->getOccShape(), kSelVertex, false); + picker_->SetSelectionMode(op->getOccShape(), kSelEdge, true); - if (target.polyActor) { - picker_->SetSelectionMode(target.polyActor, kSelFace, false); - picker_->SetSelectionMode(target.polyActor, kSelEdge, false); - picker_->SetSelectionMode(target.polyActor, kSelVertex, false); + { + auto& poly = dynamic_cast(op->getPolyActor()); + picker_->SetSelectionMode(&poly, kSelFace, false); + picker_->SetSelectionMode(&poly, kSelEdge, false); + picker_->SetSelectionMode(&poly, kSelVertex, false); } - picker_->SetSelectionMode(target.lineActor, kSelEdge, true); - picker_->SetSelectionMode(target.lineActor, kSelVertex, false); - picker_->SetSelectionMode(target.lineActor, kSelFace, false); + auto& line = dynamic_cast(op->getLineActor()); + picker_->SetSelectionMode(&line, kSelEdge, true); + picker_->SetSelectionMode(&line, kSelVertex, false); + picker_->SetSelectionMode(&line, kSelFace, false); } // ─── Vertex ──────────────────────────────────────────── @@ -586,16 +382,14 @@ GeometryVertexSelectorHighlight::~GeometryVertexSelectorHighlight() { clear(); } void GeometryVertexSelectorHighlight::clear() { selections_.clear(); - line_sub_id_arr_ = nullptr; - - auto op = geom_actor_.lock(); - if (op) { - auto* lineActor = dynamic_cast(&op->getLineActor()); - vtkPolyData* pd = actorPoly(lineActor); - vtkUnsignedCharArray* colors = cellColors(pd); - if (pd && colors) - resetColorsToBase(pd, colors, line_base_); + if (filter_) { + filter_->Clear(); + filter_->Modified(); } + if (hl_actor_) + hl_actor_->SetVisibility(false); + if (renderer_ && renderer_->GetRenderWindow()) + renderer_->GetRenderWindow()->Render(); } GeometrySelectionVtk GeometryVertexSelectorHighlight::get() const @@ -603,38 +397,16 @@ GeometrySelectionVtk GeometryVertexSelectorHighlight::get() const GeometrySelectionVtk s; s.type = ElementEnum::Vertex; s.component_id = -1; - for (const auto& [subId, geomId] : selections_) { + for (const auto& [subId, geomId] : selections_) s.ids.push_back(geomId); - } return s; } -void GeometryVertexSelectorHighlight::ensureTargetInit() +void GeometryVertexSelectorHighlight::select(double posx, double posy) { - if (target_initialized_) - return; auto op = geom_actor_.lock(); if (!op) return; - auto* lineActor = dynamic_cast(&op->getLineActor()); - vtkPolyData* pd = actorPoly(lineActor); - vtkUnsignedCharArray* colors = cellColors(pd); - const unsigned char fallback[3] = { 0, 0, 0 }; - readBaseRgb(colors, line_base_, fallback); - if (!pd || !colors) { - spdlog::warn("Line actor has no polydata or no CellData->Scalars. " - "Need GeometryActor::loadShape to create CellColors scalars."); - } - target_initialized_ = true; -} - -void GeometryVertexSelectorHighlight::select(double posx, double posy) -{ - auto target = getTargetData(geom_actor_); - if (!target.lineActor || !target.valid() || !target.geomIndex) - return; - - ensureTargetInit(); const int n = picker_->Pick(posx, posy, 0.0, renderer_); if (n <= 0) @@ -648,8 +420,12 @@ void GeometryVertexSelectorHighlight::select(double posx, double posy) if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) return; + const auto* geomIndex = op->getGeometryIndex(); + if (!geomIndex) + return; + ElementEnum::Type elemType = ElementEnum::None; - auto geomId = mapSubshapeToGeomId(target.occShape, *target.geomIndex, TopAbs_VERTEX, subId, elemType); + auto geomId = mapSubshapeToGeomId(op->getOccShape(), *geomIndex, TopAbs_VERTEX, subId, elemType); if (!geomId) return; @@ -657,83 +433,80 @@ void GeometryVertexSelectorHighlight::select(double posx, double posy) if (!inserted) selections_.erase(it); - vtkPolyData* pd = actorPoly(target.lineActor); - if (!line_sub_id_arr_ && target.lineSubIdArr) - line_sub_id_arr_ = const_cast(target.lineSubIdArr); - else if (!line_sub_id_arr_ && pd) - line_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "LinePd"); - - applyHighlight(); -} - -void GeometryVertexSelectorHighlight::applyHighlight() -{ - auto target = getTargetData(geom_actor_); - vtkPolyData* pd = actorPoly(target.lineActor); - vtkUnsignedCharArray* colors = cellColors(pd); - - if (!pd || !colors || !line_sub_id_arr_) - return; - - recolorBySelectedSubIds(pd, line_sub_id_arr_, colors, selections_, line_base_); + NCollection_List ids; + for (const auto& [sid, gid] : selections_) + ids.Append(sid); - if (renderer_ && renderer_->GetRenderWindow()) - renderer_->GetRenderWindow()->Render(); + if (filter_) + filter_->SetData(ids); + flushHighlight(filter_, hl_actor_, !ids.IsEmpty(), renderer_); } void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { - auto oldTarget = getTargetData(geom_actor_); - if (oldTarget.valid()) { - picker_->SetSelectionMode(oldTarget.occShape, kSelFace, false); - picker_->SetSelectionMode(oldTarget.occShape, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.occShape, kSelVertex, false); - if (oldTarget.polyActor) { - picker_->SetSelectionMode(oldTarget.polyActor, kSelFace, false); - picker_->SetSelectionMode(oldTarget.polyActor, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.polyActor, kSelVertex, false); - } - if (oldTarget.lineActor) { - picker_->SetSelectionMode(oldTarget.lineActor, kSelFace, false); - picker_->SetSelectionMode(oldTarget.lineActor, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.lineActor, kSelVertex, false); + { + auto oldOp = geom_actor_.lock(); + if (oldOp) { + picker_->SetSelectionMode(oldOp->getOccShape(), kSelFace, false); + picker_->SetSelectionMode(oldOp->getOccShape(), kSelEdge, false); + picker_->SetSelectionMode(oldOp->getOccShape(), kSelVertex, false); + auto& poly = dynamic_cast(oldOp->getPolyActor()); + picker_->SetSelectionMode(&poly, kSelFace, false); + picker_->SetSelectionMode(&poly, kSelEdge, false); + picker_->SetSelectionMode(&poly, kSelVertex, false); + auto& line = dynamic_cast(oldOp->getLineActor()); + picker_->SetSelectionMode(&line, kSelFace, false); + picker_->SetSelectionMode(&line, kSelEdge, false); + picker_->SetSelectionMode(&line, kSelVertex, false); + picker_->InitializePickList(); } - picker_->InitializePickList(); } + clear(); geom_actor_ = std::move(geom_actor); - target_initialized_ = false; + filter_ = nullptr; + hl_actor_ = nullptr; + + auto op = geom_actor_.lock(); + if (op) { + filter_ = &op->getLineHLFilter(); + hl_actor_ = &op->getLineHLActor(); + } + configurePicker(); } void GeometryVertexSelectorHighlight::configurePicker() { - auto target = getTargetData(geom_actor_); - if (!target.lineActor || !target.valid()) + auto op = geom_actor_.lock(); + if (!op) return; picker_->PickFromListOn(); picker_->InitializePickList(); - picker_->AddPickList(target.lineActor); - if (target.polyActor) - picker_->AddPickList(target.polyActor); - + picker_->AddPickList(&dynamic_cast(op->getLineActor())); + { + auto& poly = dynamic_cast(op->getPolyActor()); + picker_->AddPickList(&poly); + } picker_->SetPixelTolerance(toleranceForMode(SelectMode::Vertex)); - picker_->SetSelectionMode(target.occShape, kSelFace, false); - picker_->SetSelectionMode(target.occShape, kSelEdge, false); - picker_->SetSelectionMode(target.occShape, kSelVertex, false); - picker_->SetSelectionMode(target.occShape, kSelVertex, true); + picker_->SetSelectionMode(op->getOccShape(), kSelFace, false); + picker_->SetSelectionMode(op->getOccShape(), kSelEdge, false); + picker_->SetSelectionMode(op->getOccShape(), kSelVertex, false); + picker_->SetSelectionMode(op->getOccShape(), kSelVertex, true); - if (target.polyActor) { - picker_->SetSelectionMode(target.polyActor, kSelFace, false); - picker_->SetSelectionMode(target.polyActor, kSelEdge, false); - picker_->SetSelectionMode(target.polyActor, kSelVertex, false); -} + { + auto& poly = dynamic_cast(op->getPolyActor()); + picker_->SetSelectionMode(&poly, kSelFace, false); + picker_->SetSelectionMode(&poly, kSelEdge, false); + picker_->SetSelectionMode(&poly, kSelVertex, false); + } - picker_->SetSelectionMode(target.lineActor, kSelVertex, true); - picker_->SetSelectionMode(target.lineActor, kSelEdge, false); - picker_->SetSelectionMode(target.lineActor, kSelFace, false); + auto& line = dynamic_cast(op->getLineActor()); + picker_->SetSelectionMode(&line, kSelVertex, true); + picker_->SetSelectionMode(&line, kSelEdge, false); + picker_->SetSelectionMode(&line, kSelFace, false); } // ─── Solid ───────────────────────────────────────────── @@ -749,16 +522,14 @@ void GeometrySolidSelectorHighlight::clear() { selections_.clear(); highlighted_face_ids_.clear(); - face_sub_id_arr_ = nullptr; - - auto op = geom_actor_.lock(); - if (op) { - auto* polyActor = dynamic_cast(&op->getPolyActor()); - vtkPolyData* pd = actorPoly(polyActor); - vtkUnsignedCharArray* colors = cellColors(pd); - if (pd && colors) - resetColorsToBase(pd, colors, face_base_); + if (filter_) { + filter_->Clear(); + filter_->Modified(); } + if (hl_actor_) + hl_actor_->SetVisibility(false); + if (renderer_ && renderer_->GetRenderWindow()) + renderer_->GetRenderWindow()->Render(); } GeometrySelectionVtk GeometrySolidSelectorHighlight::get() const @@ -766,38 +537,16 @@ GeometrySelectionVtk GeometrySolidSelectorHighlight::get() const GeometrySelectionVtk s; s.type = ElementEnum::Solid; s.component_id = -1; - for (const auto& [subId, geomId] : selections_) { + for (const auto& [subId, geomId] : selections_) s.ids.push_back(geomId); - } return s; } -void GeometrySolidSelectorHighlight::ensureTargetInit() +void GeometrySolidSelectorHighlight::select(double posx, double posy) { - if (target_initialized_) - return; auto op = geom_actor_.lock(); if (!op) return; - auto* polyActor = dynamic_cast(&op->getPolyActor()); - vtkPolyData* pd = actorPoly(polyActor); - vtkUnsignedCharArray* colors = cellColors(pd); - const unsigned char fallback[3] = { 200, 200, 200 }; - readBaseRgb(colors, face_base_, fallback); - if (!pd || !colors) { - spdlog::warn("Solid actor has no polydata or no CellData->Scalars. " - "Need GeometryActor::loadShape to create CellColors scalars."); - } - target_initialized_ = true; -} - -void GeometrySolidSelectorHighlight::select(double posx, double posy) -{ - auto target = getTargetData(geom_actor_); - if (!target.polyActor || !target.valid() || !target.geomIndex) - return; - - ensureTargetInit(); const int n = picker_->Pick(posx, posy, 0.0, renderer_); if (n <= 0) @@ -811,18 +560,22 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) return; - const TopoDS_Shape& pickedSub = target.occShape->GetSubShape(subId); + const TopoDS_Shape& pickedSub = op->getOccShape()->GetSubShape(subId); if (pickedSub.IsNull()) return; + const auto* geomIndex = op->getGeometryIndex(); + if (!geomIndex) + return; + TopoDS_Shape solidShape; if (pickedSub.ShapeType() == TopAbs_SOLID) { solidShape = pickedSub; } else { const int solidTi = GeometrySubshapeIndex::typeIndex(TopAbs_SOLID); - const int nSolids = target.geomIndex->type_maps[solidTi].Extent(); + const int nSolids = geomIndex->type_maps[solidTi].Extent(); for (int localId = 1; localId <= nSolids; ++localId) { - const TopoDS_Shape& solid = target.geomIndex->type_maps[solidTi].FindKey(localId); + const TopoDS_Shape& solid = geomIndex->type_maps[solidTi].FindKey(localId); for (TopExp_Explorer exp(solid, TopAbs_FACE); exp.More(); exp.Next()) { if (exp.Current().IsSame(pickedSub)) { solidShape = solid; @@ -837,11 +590,11 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) } const int solidTi = GeometrySubshapeIndex::typeIndex(TopAbs_SOLID); - const int localTypeId = target.geomIndex->type_maps[solidTi].FindIndex(solidShape); + const int localTypeId = geomIndex->type_maps[solidTi].FindIndex(solidShape); if (localTypeId <= 0) return; - GeomSolidId gid = target.geomIndex->solidGlobalId(localTypeId); + GeomSolidId gid = geomIndex->solidGlobalId(localTypeId); if (gid == kInvalidGeomSolidId) return; @@ -852,7 +605,7 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) for (TopExp_Explorer expF(solidShape, TopAbs_FACE); expF.More(); expF.Next()) { const TopoDS_Shape& face = expF.Current(); - IVtk_IdType faceSubId = target.occShape->GetSubShapeId(face); + IVtk_IdType faceSubId = op->getOccShape()->GetSubShapeId(face); if (faceSubId >= 0) { if (!inserted) highlighted_face_ids_.erase(faceSubId); @@ -861,73 +614,53 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) } } - vtkPolyData* pd = actorPoly(target.polyActor); - if (!face_sub_id_arr_ && target.polySubIdArr) - face_sub_id_arr_ = const_cast(target.polySubIdArr); - else if (!face_sub_id_arr_ && pd) - face_sub_id_arr_ = detectSubIdArrayByValue(pd, subId, "SolidPd"); - - applyHighlight(); -} - -void GeometrySolidSelectorHighlight::applyHighlight() -{ - auto target = getTargetData(geom_actor_); - vtkPolyData* pd = actorPoly(target.polyActor); - vtkUnsignedCharArray* colors = cellColors(pd); - - if (!pd || !colors || !face_sub_id_arr_) - return; - - const vtkIdType n = pd->GetNumberOfCells(); - for (vtkIdType c = 0; c < n; ++c) { - const IVtk_IdType sid = static_cast(face_sub_id_arr_->GetTuple1(c)); - unsigned char rgb[3] { face_base_[0], face_base_[1], face_base_[2] }; - if (highlighted_face_ids_.count(sid)) { - rgb[0] = 255; - rgb[1] = 0; - rgb[2] = 0; - } - colors->SetTypedTuple(c, rgb); - } - - colors->Modified(); - pd->GetCellData()->Modified(); - pd->Modified(); + NCollection_List ids; + for (const auto& fid : highlighted_face_ids_) + ids.Append(fid); - if (renderer_ && renderer_->GetRenderWindow()) - renderer_->GetRenderWindow()->Render(); + if (filter_) + filter_->SetData(ids); + flushHighlight(filter_, hl_actor_, !ids.IsEmpty(), renderer_); } void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { - auto oldTarget = getTargetData(geom_actor_); - if (oldTarget.valid()) { - picker_->SetSelectionMode(oldTarget.occShape, kSelFace, false); - picker_->SetSelectionMode(oldTarget.occShape, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.occShape, kSelVertex, false); - if (oldTarget.polyActor) { - picker_->SetSelectionMode(oldTarget.polyActor, kSelFace, false); - picker_->SetSelectionMode(oldTarget.polyActor, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.polyActor, kSelVertex, false); - } - if (oldTarget.lineActor) { - picker_->SetSelectionMode(oldTarget.lineActor, kSelFace, false); - picker_->SetSelectionMode(oldTarget.lineActor, kSelEdge, false); - picker_->SetSelectionMode(oldTarget.lineActor, kSelVertex, false); + { + auto oldOp = geom_actor_.lock(); + if (oldOp) { + picker_->SetSelectionMode(oldOp->getOccShape(), kSelFace, false); + picker_->SetSelectionMode(oldOp->getOccShape(), kSelEdge, false); + picker_->SetSelectionMode(oldOp->getOccShape(), kSelVertex, false); + auto& poly = dynamic_cast(oldOp->getPolyActor()); + picker_->SetSelectionMode(&poly, kSelFace, false); + picker_->SetSelectionMode(&poly, kSelEdge, false); + picker_->SetSelectionMode(&poly, kSelVertex, false); + auto& line = dynamic_cast(oldOp->getLineActor()); + picker_->SetSelectionMode(&line, kSelFace, false); + picker_->SetSelectionMode(&line, kSelEdge, false); + picker_->SetSelectionMode(&line, kSelVertex, false); + picker_->InitializePickList(); } - picker_->InitializePickList(); } + clear(); geom_actor_ = std::move(geom_actor); - target_initialized_ = false; + filter_ = nullptr; + hl_actor_ = nullptr; + + auto op = geom_actor_.lock(); + if (op) { + filter_ = &op->getPolyHLFilter(); + hl_actor_ = &op->getPolyHLActor(); + } + configurePicker(); } void GeometrySolidSelectorHighlight::configurePicker() { - auto target = getTargetData(geom_actor_); - if (!target.polyActor || !target.valid()) { + auto op = geom_actor_.lock(); + if (!op) { if (picker_) picker_->InitializePickList(); return; @@ -935,22 +668,21 @@ void GeometrySolidSelectorHighlight::configurePicker() picker_->PickFromListOn(); picker_->InitializePickList(); - picker_->AddPickList(target.polyActor); - + picker_->AddPickList(&dynamic_cast(op->getPolyActor())); picker_->SetPixelTolerance(toleranceForMode(SelectMode::Solid)); - picker_->SetSelectionMode(target.occShape, kSelFace, false); - picker_->SetSelectionMode(target.occShape, kSelEdge, false); - picker_->SetSelectionMode(target.occShape, kSelVertex, false); - picker_->SetSelectionMode(target.occShape, kSelFace, true); + picker_->SetSelectionMode(op->getOccShape(), kSelFace, false); + picker_->SetSelectionMode(op->getOccShape(), kSelEdge, false); + picker_->SetSelectionMode(op->getOccShape(), kSelVertex, false); + picker_->SetSelectionMode(op->getOccShape(), kSelFace, true); - picker_->SetSelectionMode(target.polyActor, kSelFace, true); - picker_->SetSelectionMode(target.polyActor, kSelEdge, false); - picker_->SetSelectionMode(target.polyActor, kSelVertex, false); + auto& poly = dynamic_cast(op->getPolyActor()); + picker_->SetSelectionMode(&poly, kSelFace, true); + picker_->SetSelectionMode(&poly, kSelEdge, false); + picker_->SetSelectionMode(&poly, kSelVertex, false); - if (target.lineActor) { - picker_->SetSelectionMode(target.lineActor, kSelFace, false); - picker_->SetSelectionMode(target.lineActor, kSelEdge, false); - picker_->SetSelectionMode(target.lineActor, kSelVertex, false); - } + auto& line = dynamic_cast(op->getLineActor()); + picker_->SetSelectionMode(&line, kSelFace, false); + picker_->SetSelectionMode(&line, kSelEdge, false); + picker_->SetSelectionMode(&line, kSelVertex, false); } diff --git a/app/render/GeometrySelectorHighlight.h b/app/render/GeometrySelectorHighlight.h index a65931d..af58c6e 100644 --- a/app/render/GeometrySelectorHighlight.h +++ b/app/render/GeometrySelectorHighlight.h @@ -9,7 +9,8 @@ #include class vtkRenderer; -class vtkDataArray; +class vtkActor; +class IVtkTools_SubPolyDataFilter; class IVtkTools_ShapePicker; struct GeometrySubshapeIndex; @@ -39,16 +40,12 @@ public: void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; private: - void applyHighlight(); - void ensureTargetInit(); void configurePicker() override; vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - - vtkSmartPointer face_sub_id_arr_; - unsigned char face_base_[3] { 200, 200, 200 }; - bool target_initialized_ { false }; + IVtkTools_SubPolyDataFilter* filter_ { nullptr }; + vtkActor* hl_actor_ { nullptr }; std::unordered_map selections_; }; @@ -63,16 +60,12 @@ public: void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; private: - void applyHighlight(); - void ensureTargetInit(); void configurePicker() override; vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - - vtkSmartPointer line_sub_id_arr_; - unsigned char line_base_[3] { 0, 0, 0 }; - bool target_initialized_ { false }; + IVtkTools_SubPolyDataFilter* filter_ { nullptr }; + vtkActor* hl_actor_ { nullptr }; std::unordered_map selections_; }; @@ -87,16 +80,12 @@ public: void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; private: - void applyHighlight(); - void ensureTargetInit(); void configurePicker() override; vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - - vtkSmartPointer line_sub_id_arr_; - unsigned char line_base_[3] { 0, 0, 0 }; - bool target_initialized_ { false }; + IVtkTools_SubPolyDataFilter* filter_ { nullptr }; + vtkActor* hl_actor_ { nullptr }; std::unordered_map selections_; }; @@ -111,16 +100,12 @@ public: void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; private: - void applyHighlight(); - void ensureTargetInit(); void configurePicker() override; vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - - vtkSmartPointer face_sub_id_arr_; - unsigned char face_base_[3] { 200, 200, 200 }; - bool target_initialized_ { false }; + IVtkTools_SubPolyDataFilter* filter_ { nullptr }; + vtkActor* hl_actor_ { nullptr }; std::unordered_map selections_; std::unordered_set highlighted_face_ids_; diff --git a/app/render/QRenderWindow.cpp b/app/render/QRenderWindow.cpp index 32d93fb..934d3ff 100644 --- a/app/render/QRenderWindow.cpp +++ b/app/render/QRenderWindow.cpp @@ -80,7 +80,7 @@ QQuickVTKItem::vtkUserData QRenderWindow::initializeVTK(vtkRenderWindow* renderW vtk->plane_widget_->SetInteractor(renderWindow->GetInteractor()); vtk->plane_widget_->SetRepresentation(rep); vtk->plane_widget_->AddObserver(vtkCommand::InteractionEvent, callback); - + return vtk; } @@ -229,12 +229,12 @@ void QRenderWindow::onModelChanged(Index model_id) auto mesh_data = model_query_->getMeshDataByComponent(component_id); if (mesh_data) { vtk->mesh_actor_manager_->loadMesh(component_id, *mesh_data, vtk->renderer_, ModelRenderMode::Face); - } + } auto geometry_data = model_query_->getGeometryVtkDataByComponent(component_id); if (geometry_data) { vtk->geometry_actor_manager_->loadGeometry(*geometry_data); -} + } } }); } @@ -361,7 +361,7 @@ void QRenderWindow::setSelectComponent(Index component_id) else selectManager_->setSelectActor({}); - std::shared_ptr geometry_actor; + std::shared_ptr geometry_actor; if (vtk->geometry_actor_manager_->hasComponent(component_id)) geometry_actor = vtk->geometry_actor_manager_->getComponentActor(component_id); @@ -375,7 +375,6 @@ void QRenderWindow::setSelectComponent(Index component_id) void QRenderWindow::setSelectMode(QString select_mode) { dispatch_async([select_mode, this](vtkRenderWindow* renderWindow, vtkUserData userData) -> void { - Data* vtk = Data::SafeDownCast(userData); if (select_mode == "Vertex") { select_mode_ = SelectMode::Vertex; geom_select_mode_ = SelectMode::None; -- Gitee From f9798c1b039c4443807590a74386434989ffeca2 Mon Sep 17 00:00:00 2001 From: hypf Date: Wed, 8 Jul 2026 11:56:37 +0800 Subject: [PATCH 07/13] =?UTF-8?q?fix(app)=EF=BC=9A=E5=9C=A8=20loadShape()?= =?UTF-8?q?=20=E5=BC=80=E5=A4=B4=EF=BC=8C=E7=A7=BB=E9=99=A4=E6=97=A7?= =?UTF-8?q?=E9=AB=98=E4=BA=AE=20actor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/render/GeometryActor.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/render/GeometryActor.cpp b/app/render/GeometryActor.cpp index 3c77fe8..cf8bcc4 100644 --- a/app/render/GeometryActor.cpp +++ b/app/render/GeometryActor.cpp @@ -120,6 +120,22 @@ bool GeometryActor::getIsEdgeRender() void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) { + // 清理上一次的高亮管线 + if (renderer_) { + if (poly_hl_actor_) { + renderer_->RemoveActor(poly_hl_actor_); + poly_hl_actor_ = nullptr; + } + if (line_hl_actor_) { + renderer_->RemoveActor(line_hl_actor_); + line_hl_actor_ = nullptr; + } + } + poly_hl_filter_ = nullptr; + poly_hl_mapper_ = nullptr; + line_hl_filter_ = nullptr; + line_hl_mapper_ = nullptr; + // 全局:开一次 vtkMapper::SetResolveCoincidentTopologyToPolygonOffset(); -- Gitee From 965cfbc46685bf20f98a8148fe782f9eb7511f7d Mon Sep 17 00:00:00 2001 From: hypf Date: Thu, 9 Jul 2026 15:41:44 +0800 Subject: [PATCH 08/13] =?UTF-8?q?refactor(app)=EF=BC=9A=E5=B0=86geometryse?= =?UTF-8?q?lectmanager=E5=92=8Cmeshselectmanager=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E7=94=B1selectmanager=E5=AF=B9=E5=A4=96?= =?UTF-8?q?=E6=9A=B4=E9=9C=B2=E7=BB=9F=E4=B8=80=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/render/CMakeLists.txt | 1 + app/render/MeshActorManager.cpp | 2 +- app/render/MeshActorManager.h | 2 +- app/render/MeshActorSelectOp.cpp | 4 +- app/render/MeshActorSelectOp.h | 8 +- app/render/MeshSelectManager.cpp | 98 +++++++++++++++ app/render/MeshSelectManager.h | 31 +++++ app/render/QRenderWindow.cpp | 58 +-------- app/render/QRenderWindow.h | 4 - app/render/QRenderWindowStyle.cpp | 202 ------------------------------ app/render/QRenderWindowStyle.h | 98 +-------------- app/render/SelectManager.cpp | 129 +++++++++---------- app/render/SelectManager.h | 52 ++++---- 13 files changed, 225 insertions(+), 464 deletions(-) create mode 100644 app/render/MeshSelectManager.cpp create mode 100644 app/render/MeshSelectManager.h diff --git a/app/render/CMakeLists.txt b/app/render/CMakeLists.txt index 2e45a38..cbd58ac 100644 --- a/app/render/CMakeLists.txt +++ b/app/render/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(vtkPart STATIC QRenderWindowStyle.cpp SelectManager.cpp GeometrySelectManager.cpp + MeshSelectManager.cpp GeometryActor.cpp MeshActorManager.cpp GeometryActorManager.cpp diff --git a/app/render/MeshActorManager.cpp b/app/render/MeshActorManager.cpp index 3b992a9..946a904 100644 --- a/app/render/MeshActorManager.cpp +++ b/app/render/MeshActorManager.cpp @@ -11,7 +11,7 @@ MeshActorManager::MeshActorManager(vtkPoints* global_points) { } -std::shared_ptr MeshActorManager::getComponentActor(Index component_id) const +std::shared_ptr MeshActorManager::getComponentActor(Index component_id) const { if (this->component_actors_.count(component_id)) return this->component_actors_.at(component_id); diff --git a/app/render/MeshActorManager.h b/app/render/MeshActorManager.h index d9ca23c..690c42e 100644 --- a/app/render/MeshActorManager.h +++ b/app/render/MeshActorManager.h @@ -12,7 +12,7 @@ public: explicit MeshActorManager(vtkPoints* global_points); void bindRender(vtkRenderer* renderer); bool hasComponent(Index component_id) const; - std::shared_ptr getComponentActor(Index component_id) const; + std::shared_ptr getComponentActor(Index component_id) const; void deleteComponent(Index component_id); void loadMesh(Index component_id, const MeshDataVtk& model_data, vtkRenderer* renderer, ModelRenderMode render_mode = ModelRenderMode::Face); diff --git a/app/render/MeshActorSelectOp.cpp b/app/render/MeshActorSelectOp.cpp index e2a935f..ef55948 100644 --- a/app/render/MeshActorSelectOp.cpp +++ b/app/render/MeshActorSelectOp.cpp @@ -8,7 +8,7 @@ #include MeshActorSelectOpFactory::MeshActorSelectOpFactory() = default; -MeshActorSelectOpFactory::MeshActorSelectOpFactory(std::weak_ptr mesh_actor) +MeshActorSelectOpFactory::MeshActorSelectOpFactory(std::weak_ptr mesh_actor) : mesh_actor_(mesh_actor) { } @@ -21,7 +21,7 @@ std::optional MeshActorSelectOpFactory::lock() return {}; } -MeshActorSelectOp::MeshActorSelectOp(std::shared_ptr mesh_actor) +MeshActorSelectOp::MeshActorSelectOp(std::shared_ptr mesh_actor) : mesh_actor_(mesh_actor) { if (!mesh_actor_) { diff --git a/app/render/MeshActorSelectOp.h b/app/render/MeshActorSelectOp.h index 6e85372..26eef70 100644 --- a/app/render/MeshActorSelectOp.h +++ b/app/render/MeshActorSelectOp.h @@ -18,7 +18,7 @@ class MeshActorSelectOpFactory { public: MeshActorSelectOpFactory(); - MeshActorSelectOpFactory(std::weak_ptr mesh_actor); + MeshActorSelectOpFactory(std::weak_ptr mesh_actor); /** * @brief 获取操作对象 * @return 如果MeshActor还存在,返回MeshActorSelectOp对象,否则返回std::nullopt @@ -26,7 +26,7 @@ public: std::optional lock(); private: - std::weak_ptr mesh_actor_; + std::weak_ptr mesh_actor_; }; /** @@ -36,7 +36,7 @@ class MeshActorSelectOp { friend MeshActorSelectOpFactory; public: - MeshActorSelectOp(std::shared_ptr mesh_actor); + MeshActorSelectOp(std::shared_ptr mesh_actor); vtkProp& getSolidActor(); vtkProp& getFaceActor(); @@ -65,6 +65,6 @@ public: vtkSmartPointer extractEdge(std::vector>& ids); private: - std::shared_ptr mesh_actor_; // 非空 + std::shared_ptr mesh_actor_; // 非空 }; #endif // MESH_ACTOR_SELECT_OP_H \ No newline at end of file diff --git a/app/render/MeshSelectManager.cpp b/app/render/MeshSelectManager.cpp new file mode 100644 index 0000000..6bfcecf --- /dev/null +++ b/app/render/MeshSelectManager.cpp @@ -0,0 +1,98 @@ +#include "MeshSelectManager.h" +#include "MeshActor.h" +#include "Selection.h" +#include "SelectorHighlight.h" +#include +#include +#include +#include + +void MeshSelectManager::bindRenderer(vtkRenderer* renderer) +{ + this->renderer_ = renderer; +} + +void MeshSelectManager::select(double posx, double posy) +{ + if (this->selector_) { + assert(this->select_mode_ != SelectMode::None); + this->selector_->select(posx, posy); + } +} + +void MeshSelectManager::setSelectActor(std::weak_ptr model_actor_) +{ + this->cur_model_actor_ = MeshActorSelectOpFactory { model_actor_ }; + if (this->selector_) { + this->selector_->clear(); + this->selector_->setCurModelActor(*cur_model_actor_); + } +} + +void MeshSelectManager::setSelectMode(SelectMode select_mode) +{ + this->select_mode_ = select_mode; + if (this->select_mode_ == SelectMode::Vertex) { + this->selector_ = std::make_unique(this->renderer_); + } else if (this->select_mode_ == SelectMode::Face) { + this->selector_ = std::make_unique(this->renderer_); + } else if (this->select_mode_ == SelectMode::Block) { + this->selector_ = std::make_unique(this->renderer_); + } else if (this->select_mode_ == SelectMode::Edge) { + this->selector_ = std::make_unique(this->renderer_); + } else if (this->select_mode_ == SelectMode::Solid) { + this->selector_ = std::make_unique(this->renderer_); + } else { + assert(this->select_mode_ == SelectMode::None); + this->selector_ = nullptr; + } + + if (this->selector_ && this->cur_model_actor_) { + this->selector_->setCurModelActor(*cur_model_actor_); + } +} + +void MeshSelectManager::clearSelection() +{ + if (this->selector_) { + this->selector_->clear(); + } +} + +std::unique_ptr MeshSelectManager::getSelection() +{ + std::unique_ptr selection = std::make_unique(); + + if (this->select_mode_ == SelectMode::Vertex) { + for (const auto& id : this->selector_->get().ids) { + selection->ids.push_back(id); + } + selection->type = ElementEnum::Vertex; + } else if (this->select_mode_ == SelectMode::Face) { + for (const auto& id : this->selector_->get().ids) { + selection->ids.push_back(id); + } + selection->type = ElementEnum::Face; + } else if (this->select_mode_ == SelectMode::Block) { + for (const auto& id : this->selector_->get().ids) { + selection->ids.push_back(id); + } + selection->type = ElementEnum::Block; + }else if (this->select_mode_ == SelectMode::Solid) { + for (const auto& id : this->selector_->get().ids) { + selection->ids.push_back(id); + } + selection->type = ElementEnum::Solid; + } else if (this->select_mode_ == SelectMode::Edge) { + for (const auto& id : this->selector_->get().ids) { + selection->ids.push_back(id); + } + selection->type = ElementEnum::Edge; + } else { + if (this->selector_) + this->selector_->clear(); + return nullptr; + } + + return selection; +} diff --git a/app/render/MeshSelectManager.h b/app/render/MeshSelectManager.h new file mode 100644 index 0000000..ccf17a2 --- /dev/null +++ b/app/render/MeshSelectManager.h @@ -0,0 +1,31 @@ +#ifndef MESH_SELECT_MANAGER_H +#define MESH_SELECT_MANAGER_H +#include "Selection.h" +#include "SelectorHighlight.h" +#include "MeshActorSelectOp.h" +#include "Core.h" + +#include +#include +#include +#include + +class MeshSelectManager { + +public: + void bindRenderer(vtkRenderer* renderer); + void select(double posx, double posy); + void setSelectActor(std::weak_ptr model_actor_); + void setSelectMode(SelectMode select_mode); + void clearSelection(); + std::unique_ptr getSelection(); + +private: + std::optional cur_model_actor_ {}; + SelectMode select_mode_; + vtkNew selection_actor_; + vtkNew selection_mapper_; + vtkRenderer* renderer_; + std::unique_ptr selector_; +}; +#endif diff --git a/app/render/QRenderWindow.cpp b/app/render/QRenderWindow.cpp index 934d3ff..83db30f 100644 --- a/app/render/QRenderWindow.cpp +++ b/app/render/QRenderWindow.cpp @@ -5,7 +5,6 @@ #include "QRenderWindowStyle.h" #include "QSelection.h" #include "SelectManager.h" -#include "GeometrySelectManager.h" #include "Selection.h" #include "GeometryActorManager.h" #include "GeometryDataVtk.h" @@ -22,7 +21,6 @@ QRenderWindow::QRenderWindow() connect(this, &QQuickItem::widthChanged, this, &QRenderWindow::resetCamera); connect(this, &QQuickItem::heightChanged, this, &QRenderWindow::resetCamera); selectManager_ = std::make_unique(); - geometrySelectManager_ = std::make_unique(); edge_render_ = false; } @@ -42,9 +40,7 @@ QQuickVTKItem::vtkUserData QRenderWindow::initializeVTK(vtkRenderWindow* renderW vtk->renderer_->SetGradientBackground(true); vtk->style_->SetSelectManager(this->selectManager_.get()); - vtk->style_->SetGeometrySelectManager(this->geometrySelectManager_.get()); selectManager_->bindRenderer(vtk->renderer_); - geometrySelectManager_->bindRenderer(vtk->renderer_); vtk->style_->SetDefaultRenderer(vtk->renderer_); renderWindow->GetInteractor()->SetInteractorStyle(vtk->style_); @@ -152,7 +148,6 @@ void QRenderWindow::deleteModel(Index model_id) } this->selectManager_->clearSelection(); - this->geometrySelectManager_->clearSelection(); }); } @@ -170,7 +165,6 @@ void QRenderWindow::deleteComponent(Index component_id) } this->selectManager_->clearSelection(); - this->geometrySelectManager_->clearSelection(); }); } @@ -270,7 +264,6 @@ void QRenderWindow::setVisibility(Index model_id, bool visibility) dispatch_async([model_id, visibility, this](vtkRenderWindow* renderWindow, vtkUserData userData) -> void { Data* vtk = Data::SafeDownCast(userData); selectManager_->clearSelection(); - geometrySelectManager_->clearSelection(); auto component_ids = model_query_->getComponentIds(model_id); for (Index component_id : component_ids) { @@ -297,12 +290,7 @@ void QRenderWindow::setComponentVisibility(Index component_id, bool visibility) QSelection* QRenderWindow::selectedIDs() { - std::unique_ptr data; - if (geom_select_mode_ != SelectMode::None) { - data = this->geometrySelectManager_->getSelection(); - } else { - data = this->selectManager_->getSelection(); - } + std::unique_ptr data = this->selectManager_->getSelection(); if (!data) { return nullptr; } @@ -352,62 +340,30 @@ void QRenderWindow::setSelectComponent(Index component_id) this->cur_component_id_ = component_id; this->setCurEdgeRender(this->getIsEdgeRender(*vtk, component_id)); - std::shared_ptr mesh_actor; + std::shared_ptr mesh_actor; if (vtk->mesh_actor_manager_->hasComponent(component_id)) mesh_actor = vtk->mesh_actor_manager_->getComponentActor(component_id); if (mesh_actor) selectManager_->setSelectActor(mesh_actor); else - selectManager_->setSelectActor({}); + selectManager_->setSelectActor(std::weak_ptr {}); std::shared_ptr geometry_actor; if (vtk->geometry_actor_manager_->hasComponent(component_id)) geometry_actor = vtk->geometry_actor_manager_->getComponentActor(component_id); if (geometry_actor) - geometrySelectManager_->setSelectActor(geometry_actor); + selectManager_->setSelectActor(geometry_actor); else - geometrySelectManager_->setSelectActor({}); + selectManager_->setSelectActor(std::weak_ptr {}); }); } void QRenderWindow::setSelectMode(QString select_mode) { dispatch_async([select_mode, this](vtkRenderWindow* renderWindow, vtkUserData userData) -> void { - if (select_mode == "Vertex") { - select_mode_ = SelectMode::Vertex; - geom_select_mode_ = SelectMode::None; - } else if (select_mode == "Face") { - select_mode_ = SelectMode::Face; - geom_select_mode_ = SelectMode::None; - } else if (select_mode == "Edge") { - select_mode_ = SelectMode::Edge; - geom_select_mode_ = SelectMode::None; - } else if (select_mode == "Block") { - select_mode_ = SelectMode::Block; - geom_select_mode_ = SelectMode::None; - } else if (select_mode == "Solid") { - select_mode_ = SelectMode::Solid; - geom_select_mode_ = SelectMode::None; - } else if (select_mode == "GeometryFace") { - select_mode_ = SelectMode::None; - geom_select_mode_ = SelectMode::Face; - } else if (select_mode == "GeometryEdge") { - select_mode_ = SelectMode::None; - geom_select_mode_ = SelectMode::Edge; - } else if (select_mode == "GeometryVertex") { - select_mode_ = SelectMode::None; - geom_select_mode_ = SelectMode::Vertex; - } else if (select_mode == "GeometrySolid") { - select_mode_ = SelectMode::None; - geom_select_mode_ = SelectMode::Solid; - } else { - select_mode_ = SelectMode::None; - geom_select_mode_ = SelectMode::None; - } - selectManager_->setSelectMode(select_mode_); - geometrySelectManager_->setSelectMode(geom_select_mode_); + selectManager_->setSelectMode(select_mode.toStdString()); }); } @@ -415,7 +371,6 @@ void QRenderWindow::clearSelection() { dispatch_async([this](vtkRenderWindow* renderWindow, vtkUserData userData) -> void { this->selectManager_->clearSelection(); - this->geometrySelectManager_->clearSelection(); }); } @@ -425,7 +380,6 @@ void QRenderWindow::setRenderMode(Index model_id, QString render_mode) dispatch_async([model_id, render_mode, this](vtkRenderWindow* renderWindow, vtkUserData userData) -> void { Data* vtk = Data::SafeDownCast(userData); this->selectManager_->clearSelection(); - this->geometrySelectManager_->clearSelection(); auto component_ids = model_query_->getComponentIds(model_id); diff --git a/app/render/QRenderWindow.h b/app/render/QRenderWindow.h index a25f0b9..ee5ba19 100644 --- a/app/render/QRenderWindow.h +++ b/app/render/QRenderWindow.h @@ -27,7 +27,6 @@ class MeshActor; class SelectManager; -class GeometrySelectManager; class GeometryActorManager; class MeshActorManager; class QRenderWindowStyle; @@ -172,15 +171,12 @@ signals: private: bool edge_render_ {}; ModelRenderMode renderMode_ {}; - SelectMode select_mode_ {}; vtkNew _camera; std::unique_ptr selectManager_; - std::unique_ptr geometrySelectManager_; MeshActor* cur_actor_ {}; Index cur_component_id_; - SelectMode geom_select_mode_ { SelectMode::None }; std::unique_ptr _click; const Data* data_ {}; diff --git a/app/render/QRenderWindowStyle.cpp b/app/render/QRenderWindowStyle.cpp index 98d6c62..68a486f 100644 --- a/app/render/QRenderWindowStyle.cpp +++ b/app/render/QRenderWindowStyle.cpp @@ -1,6 +1,5 @@ #include "QRenderWindowStyle.h" #include "SelectManager.h" -#include "GeometrySelectManager.h" #include #include @@ -16,11 +15,6 @@ void QRenderWindowStyle::SetSelectManager(SelectManager* select_manager) this->select_manager_ = select_manager; } -void QRenderWindowStyle::SetGeometrySelectManager(GeometrySelectManager* geometry_select_manager) -{ - this->geometry_select_manager_ = geometry_select_manager; -} - void QRenderWindowStyle::OnLeftButtonUp() { if (click_) { @@ -29,203 +23,7 @@ void QRenderWindowStyle::OnLeftButtonUp() this->GetInteractor()->GetEventPosition(pos); if (select_manager_) select_manager_->select(pos[0], pos[1]); - if (geometry_select_manager_) - geometry_select_manager_->select(pos[0], pos[1]); } vtkInteractorStyleTrackballCamera::OnLeftButtonUp(); } - -//vtkStandardNewMacro(MouseInteractorHighLightActor); -//void MouseInteractorHighLightActor::OnLeftButtonUp() -//{ -// if (selector_ != nullptr && click_) -// { -// click_ = false; -// int pos[2]; -// this->GetInteractor()->GetEventPosition(pos); -// OnSelect(pos[0], pos[1]); -// } -// vtkInteractorStyleTrackballCamera::OnLeftButtonUp(); -//} -// -//void MouseInteractorHighLightActor::OnSelect(double posx, double posy) -//{ -// selector_->select(posx, posy); -//} -// -// -// -//void MouseInteractorHighLightActor::SetClick() -//{ -// click_ = true; -//} -// -//void MouseInteractorHighLightActor::ClearSelections() -//{ -// selector_->clear(); -//} -// -//std::unique_ptr MouseInteractorHighLightActor::GetSelectedIDs(const std::unordered_map>& mActors, SelectMode mode) -//{ -// auto actors = selector_->get(); -// std::unique_ptr selection = std::make_unique(); -// //std::vector ids; -// vtkPropAssembly* assembly_ = selector_->getAssembly(); -// MeshActor* modelactor_; -// -// for (const auto& pair : mActors) -// { -// modelactor_= pair.second.get()->getModelActor(assembly_); -// -// if (modelactor_ != NULL) -// { -// selection->model_name = pair.first; -// break; -// } -// } -// -// -// int (MeshActor::*actor_id)(vtkActor*) {}; -// if (mode == SelectMode::Group) -// { -// actor_id = &MeshActor::group_actor_id; -// selection->type = Element::Type::Group; -// } else if (mode == SelectMode::Block) { -// actor_id = &MeshActor::block_actor_id; -// selection->type = Element::Type::Block; -// } else { -// assert(false); -// } -// -// for (vtkActor* actor : actors) -// { -// selection->ids.push_back((modelactor_->*actor_id)(actor)); -// } -// return selection; -//} -//std::unique_ptr MouseInteractorHighLightFace::GetSelectedIDs(const std::unordered_map>& mActors, SelectMode mode) -//{ -// auto actors = selector_->get(); -// std::unique_ptr selection = std::make_unique(); -// //std::vector face_ids; -// vtkPropAssembly* assembly_ = selector_->getAssembly(); -// MeshActor* modelactor_; -// for (const auto& pair : mActors) -// { -// modelactor_ = pair.second.get()->getModelActor(assembly_); -// -// if (modelactor_ != NULL) -// { -// selection->model_name = pair.first; -// break; -// } -// } -// if (actors) -// { -// selection->ids.reserve(2); -// -// int patch_id = modelactor_->patch_actor_id(actors->patch_actor); -// selection->ids.push_back(modelactor_->patch_global_fid(patch_id,actors->local_id)); -// selection->type = Element::Type::Face; -// } -// -// return selection; -//} -//std::unique_ptr MouseInteractorHighLightEdge::GetSelectedIDs(const std::unordered_map>& mActors, SelectMode mode) -//{ -// auto actors = selector_->get(); -// std::unique_ptr selection=std::make_unique(); -// //std::vector point_ids; -// vtkPropAssembly* assembly_ = selector_->getAssembly(); -// MeshActor* modelactor_; -// for (const auto& pair : mActors) -// { -// modelactor_ = pair.second.get()->getModelActor(assembly_); -// -// if (modelactor_ != NULL) -// { -// selection->model_name = pair.first; -// break; -// } -// } -// if (actors) -// { -// selection->ids.reserve(3); -// -// int patch_id = modelactor_->patch_actor_id(actors->actor); -// selection->ids.push_back(modelactor_->patch_global_vid(patch_id,actors->v_local_id[0])); -// selection->ids.push_back(modelactor_->patch_global_vid(patch_id, actors->v_local_id[1])); -// selection->type = Element::Type::Edge; -// } -// -// return selection; -//} -// -//void MouseInteractorHighLightActor::SetSelector(std::unique_ptr selector) -//{ -// selector_ = std::move(selector); -//} -// -// -//vtkStandardNewMacro(MouseInteractorHighLightFace); -//void MouseInteractorHighLightFace::OnLeftButtonUp() -//{ -// if (selector_ != nullptr && click_) -// { -// click_ = false; -// int pos[2]; -// this->GetInteractor()->GetEventPosition(pos); -// selector_->select(pos[0], pos[1]); -// } -// vtkInteractorStyleTrackballCamera::OnLeftButtonUp(); -//} -// -// -// -//void MouseInteractorHighLightFace::SetClick() -//{ -// click_ = true; -//} -// -//void MouseInteractorHighLightFace::ClearSelections() -//{ -// selector_->clear(); -//} -// -//void MouseInteractorHighLightFace::SetSelector(std::unique_ptr selector) -//{ -// selector_ = std::move(selector); -//} -// -//vtkStandardNewMacro(MouseInteractorHighLightEdge); -//void MouseInteractorHighLightEdge::OnLeftButtonUp() -//{ -// if (selector_ != nullptr && click_) -// { -// click_ = false; -// int pos[2]; -// this->GetInteractor()->GetEventPosition(pos); -// selector_->select(pos[0], pos[1]); -// } -// vtkInteractorStyleTrackballCamera::OnLeftButtonUp(); -//} -// -// -//void MouseInteractorHighLightEdge::SetClick() -//{ -// click_ = true; -//} -// -//void MouseInteractorHighLightEdge::ClearSelections() -//{ -// selector_->clear(); -//} -// -// -//void MouseInteractorHighLightEdge::SetSelector(std::unique_ptr selector) -//{ -// selector_ = std::move(selector); -//} - - diff --git a/app/render/QRenderWindowStyle.h b/app/render/QRenderWindowStyle.h index 5f1c38c..6d1bf63 100644 --- a/app/render/QRenderWindowStyle.h +++ b/app/render/QRenderWindowStyle.h @@ -9,7 +9,6 @@ #include class SelectManager; -class GeometrySelectManager; class QRenderWindowStyle : public vtkInteractorStyleTrackballCamera { public: @@ -17,105 +16,10 @@ public: vtkTypeMacro(QRenderWindowStyle, vtkInteractorStyleTrackballCamera); void SetClick(); void SetSelectManager(SelectManager* select_manager); - void SetGeometrySelectManager(GeometrySelectManager* geometry_select_manager); void OnLeftButtonUp() override; private: bool click_ {}; SelectManager* select_manager_{}; - GeometrySelectManager* geometry_select_manager_{}; - }; - -//class MouseInteractorHighLightActor : public vtkInteractorStyleWithClick { -//public: -// static MouseInteractorHighLightActor* New(); -// vtkTypeMacro(MouseInteractorHighLightActor, -// vtkInteractorStyleTrackballCamera); -// -// virtual ~MouseInteractorHighLightActor() { } -// void OnLeftButtonUp() override; -// /* -// * @brief 调用select -// -// -// */ -// void OnSelect(double posx, double posy); -// -// void SetClick() override; -// void ClearSelections() override; -// /* -// * @brief 获取选中的Selection -// * -// * 判断选中的对象所属的模型,将全局ID转化为ModelActor中的局部ID,并存入Selection -// * @param[in] mActors 所有模型与模型名的映射 -// * @param[in] mode 当前的选择模式 -// -// */ -// std::unique_ptr GetSelectedIDs(const std::unordered_map>& mActors, SelectMode mode) override; -// -// void SetSelector(std::unique_ptr selector); -// -//private: -// bool click_ {}; -// std::unique_ptr selector_; -//}; -// -//class MouseInteractorHighLightFace : public vtkInteractorStyleWithClick { -//public: -// static MouseInteractorHighLightFace* New(); -// vtkTypeMacro(MouseInteractorHighLightFace, -// vtkInteractorStyleTrackballCamera); -// -// virtual ~MouseInteractorHighLightFace() { } -// virtual void OnLeftButtonUp() override; -// -// -// void SetClick() override; -// void ClearSelections() override; -// void SetSelector(std::unique_ptr selector); -// /* -// * @brief 获取选中的Selection -// * -// * 判断选中的对象所属的模型,将全局ID转化为ModelActor中的局部ID,并存入Selection -// * @param[in] mActors 所有模型与模型名的映射 -// * @param[in] mode 当前的选择模式 -// -// */ -// std::unique_ptr GetSelectedIDs(const std::unordered_map>& mActors, SelectMode mode) override; -// -//private: -// -// bool click_ {}; -// std::unique_ptr selector_; -//}; -// -//class MouseInteractorHighLightEdge : public vtkInteractorStyleWithClick { -//public: -// static MouseInteractorHighLightEdge* New(); -// vtkTypeMacro(MouseInteractorHighLightEdge, -// vtkInteractorStyleTrackballCamera); -// -// virtual ~MouseInteractorHighLightEdge() { } -// virtual void OnLeftButtonUp() override; -// -// -// -// void SetClick() override; -// void ClearSelections() override; -// void SetSelector(std::unique_ptr selector); -// /* -// * @brief 获取选中的Selection -// * -// * 判断选中的对象所属的模型,将全局ID转化为ModelActor中的局部ID,并存入Selection -// * @param[in] mActors 所有模型与模型名的映射 -// * @param[in] mode 当前的选择模式 -// -// */ -// std::unique_ptr GetSelectedIDs(const std::unordered_map>& mActors, SelectMode mode) override; -//private: -// -// bool click_ {}; -// std::unique_ptr selector_; -//}; -#endif // STYLE_H +#endif // Q_RENDER_WINDOW_STYLE_H diff --git a/app/render/SelectManager.cpp b/app/render/SelectManager.cpp index b2b4ab5..676de55 100644 --- a/app/render/SelectManager.cpp +++ b/app/render/SelectManager.cpp @@ -1,98 +1,85 @@ #include "SelectManager.h" +#include "MeshSelectManager.h" +#include "GeometrySelectManager.h" +#include "GeometryActor.h" #include "MeshActor.h" -#include "Selection.h" -#include "SelectorHighlight.h" -#include -#include -#include -#include + +SelectManager::SelectManager() + : mesh_(std::make_unique()) + , geom_(std::make_unique()) +{ +} + +SelectManager::~SelectManager() = default; void SelectManager::bindRenderer(vtkRenderer* renderer) { - this->renderer_ = renderer; + mesh_->bindRenderer(renderer); + geom_->bindRenderer(renderer); } void SelectManager::select(double posx, double posy) { - if (this->selector_) { - assert(this->select_mode_ != SelectMode::None); - this->selector_->select(posx, posy); - } + mesh_->select(posx, posy); + geom_->select(posx, posy); } -void SelectManager::setSelectActor(std::weak_ptr model_actor_) +void SelectManager::setSelectActor(std::weak_ptr mesh_actor) { - this->cur_model_actor_ = MeshActorSelectOpFactory { model_actor_ }; - if (this->selector_) { - this->selector_->clear(); - this->selector_->setCurModelActor(*cur_model_actor_); - } + mesh_->setSelectActor(mesh_actor); } -void SelectManager::setSelectMode(SelectMode select_mode) +void SelectManager::setSelectActor(std::weak_ptr geom_actor) { - this->select_mode_ = select_mode; - if (this->select_mode_ == SelectMode::Vertex) { - this->selector_ = std::make_unique(this->renderer_); - } else if (this->select_mode_ == SelectMode::Face) { - this->selector_ = std::make_unique(this->renderer_); - } else if (this->select_mode_ == SelectMode::Block) { - this->selector_ = std::make_unique(this->renderer_); - } else if (this->select_mode_ == SelectMode::Edge) { - this->selector_ = std::make_unique(this->renderer_); - } else if (this->select_mode_ == SelectMode::Solid) { - this->selector_ = std::make_unique(this->renderer_); - } else { - assert(this->select_mode_ == SelectMode::None); - this->selector_ = nullptr; - } + geom_->setSelectActor(geom_actor); +} - if (this->selector_ && this->cur_model_actor_) { - this->selector_->setCurModelActor(*cur_model_actor_); +void SelectManager::setSelectMode(const std::string& select_mode) +{ + if (select_mode == "Vertex") { + mesh_->setSelectMode(SelectMode::Vertex); + geom_->setSelectMode(SelectMode::None); + } else if (select_mode == "Face") { + mesh_->setSelectMode(SelectMode::Face); + geom_->setSelectMode(SelectMode::None); + } else if (select_mode == "Edge") { + mesh_->setSelectMode(SelectMode::Edge); + geom_->setSelectMode(SelectMode::None); + } else if (select_mode == "Block") { + mesh_->setSelectMode(SelectMode::Block); + geom_->setSelectMode(SelectMode::None); + } else if (select_mode == "Solid") { + mesh_->setSelectMode(SelectMode::Solid); + geom_->setSelectMode(SelectMode::None); + } else if (select_mode == "GeometryFace") { + mesh_->setSelectMode(SelectMode::None); + geom_->setSelectMode(SelectMode::Face); + } else if (select_mode == "GeometryEdge") { + mesh_->setSelectMode(SelectMode::None); + geom_->setSelectMode(SelectMode::Edge); + } else if (select_mode == "GeometryVertex") { + mesh_->setSelectMode(SelectMode::None); + geom_->setSelectMode(SelectMode::Vertex); + } else if (select_mode == "GeometrySolid") { + mesh_->setSelectMode(SelectMode::None); + geom_->setSelectMode(SelectMode::Solid); + } else { + mesh_->setSelectMode(SelectMode::None); + geom_->setSelectMode(SelectMode::None); } } void SelectManager::clearSelection() { - if (this->selector_) { - this->selector_->clear(); - } + mesh_->clearSelection(); + geom_->clearSelection(); } std::unique_ptr SelectManager::getSelection() { - std::unique_ptr selection = std::make_unique(); - - if (this->select_mode_ == SelectMode::Vertex) { - for (const auto& id : this->selector_->get().ids) { - selection->ids.push_back(id); - } - selection->type = ElementEnum::Vertex; - } else if (this->select_mode_ == SelectMode::Face) { - for (const auto& id : this->selector_->get().ids) { - selection->ids.push_back(id); - } - selection->type = ElementEnum::Face; - } else if (this->select_mode_ == SelectMode::Block) { - for (const auto& id : this->selector_->get().ids) { - selection->ids.push_back(id); - } - selection->type = ElementEnum::Block; - }else if (this->select_mode_ == SelectMode::Solid) { - for (const auto& id : this->selector_->get().ids) { - selection->ids.push_back(id); - } - selection->type = ElementEnum::Solid; - } else if (this->select_mode_ == SelectMode::Edge) { - for (const auto& id : this->selector_->get().ids) { - selection->ids.push_back(id); - } - selection->type = ElementEnum::Edge; - } else { - if (this->selector_) - this->selector_->clear(); - return nullptr; + auto geom_selection = geom_->getSelection(); + if (geom_selection) { + return geom_selection; } - - return selection; + return mesh_->getSelection(); } diff --git a/app/render/SelectManager.h b/app/render/SelectManager.h index 546330b..84b4880 100644 --- a/app/render/SelectManager.h +++ b/app/render/SelectManager.h @@ -1,42 +1,34 @@ #ifndef SELECT_MANAGER_H #define SELECT_MANAGER_H -#include "Selection.h" -#include "SelectorHighlight.h" -#include "MeshActorSelectOp.h" #include "Core.h" +#include "Selection.h" -#include -#include -#include -#include +#include +#include -class SelectManager { +class vtkRenderer; +class MeshActor; +class GeometryActor; +class MeshSelectManager; +class GeometrySelectManager; +class SelectManager { public: - void bindRenderer(vtkRenderer* renderer); - /** - * @brief 传入renderer - * - * @param posx - * @param posy - */ - void select(double posx, double posy); + SelectManager(); + ~SelectManager(); + + void bindRenderer(vtkRenderer* renderer); + void select(double posx, double posy); + + void setSelectActor(std::weak_ptr mesh_actor); + void setSelectActor(std::weak_ptr geom_actor); - void setSelectActor(std::weak_ptr model_actor_); - /** - * @brief 传入选择模型 - * @param select_mode - */ - void setSelectMode(SelectMode select_mode); - void clearSelection(); - std::unique_ptr getSelection(); + void setSelectMode(const std::string& select_mode); + void clearSelection(); + std::unique_ptr getSelection(); private: - std::optional cur_model_actor_ {}; - SelectMode select_mode_; - vtkNew selection_actor_; - vtkNew selection_mapper_; - vtkRenderer* renderer_; - std::unique_ptr selector_; + std::unique_ptr mesh_; + std::unique_ptr geom_; }; #endif \ No newline at end of file -- Gitee From e4befe14a6f525e2f085487cbf16b2e4be973127 Mon Sep 17 00:00:00 2001 From: hypf Date: Fri, 10 Jul 2026 19:39:13 +0800 Subject: [PATCH 09/13] =?UTF-8?q?refactor(app)=EF=BC=9A=E6=8A=8Ageometryse?= =?UTF-8?q?lector=E9=87=8C=E7=9A=84=E9=87=8D=E5=A4=8D=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=8F=90=E5=88=B0op=E9=87=8C=EF=BC=8C=E5=B9=B6=E5=A3=B0?= =?UTF-8?q?=E6=98=8Eop=E4=B8=BAgeometryactor=E7=9A=84=E5=8F=8B=E5=85=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/render/GeometryActor.cpp | 80 ----- app/render/GeometryActor.h | 20 +- app/render/GeometryActorSelectOp.cpp | 274 ++++++++++++-- app/render/GeometryActorSelectOp.h | 35 +- app/render/GeometrySelectorHighlight.cpp | 431 ++--------------------- app/render/GeometrySelectorHighlight.h | 9 - 6 files changed, 306 insertions(+), 543 deletions(-) diff --git a/app/render/GeometryActor.cpp b/app/render/GeometryActor.cpp index cf8bcc4..c75570b 100644 --- a/app/render/GeometryActor.cpp +++ b/app/render/GeometryActor.cpp @@ -304,84 +304,4 @@ void GeometryActor::setRenderEdge(bool is_render) { this->edge_render = is_render; this->line_actor_->SetVisibility(is_render && this->visibility_); -} - -vtkActor* GeometryActor::polyActor() noexcept -{ - return poly_actor_.GetPointer(); -} - -const vtkActor* GeometryActor::polyActor() const noexcept -{ - return poly_actor_.GetPointer(); -} - -vtkActor* GeometryActor::lineActor() noexcept -{ - return line_actor_.GetPointer(); -} - -const vtkActor* GeometryActor::lineActor() const noexcept -{ - return line_actor_.GetPointer(); -} - -const OccShapeHandle& GeometryActor::getOccShape() const -{ - return occ_shape_; -} - -const GeometrySubshapeIndex* GeometryActor::geometryIndex() const noexcept -{ - return geometry_index_; -} - -const vtkDataArray* GeometryActor::lineSubIdArray() const noexcept -{ - return line_sub_id_array_.GetPointer(); -} - -const vtkDataArray* GeometryActor::polySubIdArray() const noexcept -{ - return poly_sub_id_array_.GetPointer(); -} - -vtkActor* GeometryActor::polyHLActor() noexcept -{ - return poly_hl_actor_.GetPointer(); -} - -const vtkActor* GeometryActor::polyHLActor() const noexcept -{ - return poly_hl_actor_.GetPointer(); -} - -vtkActor* GeometryActor::lineHLActor() noexcept -{ - return line_hl_actor_.GetPointer(); -} - -const vtkActor* GeometryActor::lineHLActor() const noexcept -{ - return line_hl_actor_.GetPointer(); -} - -IVtkTools_SubPolyDataFilter* GeometryActor::polyHLFilter() noexcept -{ - return poly_hl_filter_.GetPointer(); -} - -const IVtkTools_SubPolyDataFilter* GeometryActor::polyHLFilter() const noexcept -{ - return poly_hl_filter_.GetPointer(); -} - -IVtkTools_SubPolyDataFilter* GeometryActor::lineHLFilter() noexcept -{ - return line_hl_filter_.GetPointer(); -} - -const IVtkTools_SubPolyDataFilter* GeometryActor::lineHLFilter() const noexcept -{ - return line_hl_filter_.GetPointer(); } \ No newline at end of file diff --git a/app/render/GeometryActor.h b/app/render/GeometryActor.h index b6aacd9..dda9d92 100644 --- a/app/render/GeometryActor.h +++ b/app/render/GeometryActor.h @@ -14,7 +14,10 @@ #include typedef Handle(IVtkOCC_Shape) OccShapeHandle; +class GeometryActorSelectOp; + class GeometryActor { + friend GeometryActorSelectOp; public: GeometryActor(vtkRenderer* renderer, GeometryRenderMode render_mode); @@ -29,23 +32,6 @@ public: void setRenderMode(GeometryRenderMode render_mode); void setRenderEdge(bool is_render); - vtkActor* polyActor() noexcept; - const vtkActor* polyActor() const noexcept; - vtkActor* lineActor() noexcept; - const vtkActor* lineActor() const noexcept; - vtkActor* polyHLActor() noexcept; - const vtkActor* polyHLActor() const noexcept; - vtkActor* lineHLActor() noexcept; - const vtkActor* lineHLActor() const noexcept; - IVtkTools_SubPolyDataFilter* polyHLFilter() noexcept; - const IVtkTools_SubPolyDataFilter* polyHLFilter() const noexcept; - IVtkTools_SubPolyDataFilter* lineHLFilter() noexcept; - const IVtkTools_SubPolyDataFilter* lineHLFilter() const noexcept; - const OccShapeHandle& getOccShape() const; - const GeometrySubshapeIndex* geometryIndex() const noexcept; - const vtkDataArray* lineSubIdArray() const noexcept; - const vtkDataArray* polySubIdArray() const noexcept; - private: void deleteGeometryActor(); diff --git a/app/render/GeometryActorSelectOp.cpp b/app/render/GeometryActorSelectOp.cpp index 9fdbc37..6c0f90c 100644 --- a/app/render/GeometryActorSelectOp.cpp +++ b/app/render/GeometryActorSelectOp.cpp @@ -1,7 +1,90 @@ #include "GeometryActorSelectOp.h" #include "GeometryActor.h" +#include "GeometrySubshapeIndex.h" +#include "Selection.h" +#include "Core.h" + #include +#include +#include #include +#include +#include +#include +#include +#include + +static constexpr IVtk_SelectionMode kSelVertex = SM_Vertex; +static constexpr IVtk_SelectionMode kSelEdge = SM_Edge; +static constexpr IVtk_SelectionMode kSelFace = SM_Face; + +static int toleranceForMode(const SelectMode m) +{ + if (m == SelectMode::Vertex) + return 40; + if (m == SelectMode::Edge) + return 25; + if (m == SelectMode::Solid) + return 8; + return 8; +} + +static bool firstId(const NCollection_List& list, IVtk_IdType& outId) +{ + if (list.IsEmpty()) + return false; + outId = list.First(); + return true; +} + +static std::optional mapSubshapeToGeomId(const OccShapeHandle& occShape, + const GeometrySubshapeIndex& geomIndex, + TopAbs_ShapeEnum wantType, + IVtk_IdType subId, + ElementEnum::Type& outType) +{ + if (occShape.IsNull()) + return std::nullopt; + + const TopoDS_Shape& sub = occShape->GetSubShape(subId); + if (sub.IsNull()) + return std::nullopt; + + const int ti = GeometrySubshapeIndex::typeIndex(wantType); + if (ti < 0) + return std::nullopt; + + const int localTypeId = geomIndex.type_maps[static_cast(ti)].FindIndex(sub); + if (localTypeId <= 0) + return std::nullopt; + + if (wantType == TopAbs_FACE) { + GeomFaceId gid = geomIndex.faceGlobalId(localTypeId); + if (gid == kInvalidGeomFaceId) + return std::nullopt; + outType = ElementEnum::Face; + return gid; + } else if (wantType == TopAbs_EDGE) { + GeomEdgeId gid = geomIndex.edgeGlobalId(localTypeId); + if (gid == kInvalidGeomEdgeId) + return std::nullopt; + outType = ElementEnum::Edge; + return gid; + } else if (wantType == TopAbs_VERTEX) { + GeomVertexId gid = geomIndex.vertexGlobalId(localTypeId); + if (gid == kInvalidGeomVertexId) + return std::nullopt; + outType = ElementEnum::Vertex; + return gid; + } else if (wantType == TopAbs_SOLID) { + GeomSolidId gid = geomIndex.solidGlobalId(localTypeId); + if (gid == kInvalidGeomSolidId) + return std::nullopt; + outType = ElementEnum::Solid; + return gid; + } + return std::nullopt; +} GeometryActorSelectOpFactory::GeometryActorSelectOpFactory() = default; GeometryActorSelectOpFactory::GeometryActorSelectOpFactory(std::weak_ptr geometry_actor) @@ -25,52 +108,187 @@ GeometryActorSelectOp::GeometryActorSelectOp(std::shared_ptr geom } } -vtkProp& GeometryActorSelectOp::getPolyActor() +void GeometryActorSelectOp::disablePickerModes(IVtkTools_ShapePicker* picker) { - return *geometry_actor_->polyActor(); -} + if (!picker) + return; -vtkProp& GeometryActorSelectOp::getLineActor() -{ - return *geometry_actor_->lineActor(); -} + const OccShapeHandle& occ = geometry_actor_->occ_shape_; + vtkActor* poly = geometry_actor_->poly_actor_.GetPointer(); + vtkActor* line = geometry_actor_->line_actor_.GetPointer(); -vtkActor& GeometryActorSelectOp::getPolyHLActor() -{ - return *geometry_actor_->polyHLActor(); + picker->SetSelectionMode(occ, kSelFace, false); + picker->SetSelectionMode(occ, kSelEdge, false); + picker->SetSelectionMode(occ, kSelVertex, false); + picker->SetSelectionMode(poly, kSelFace, false); + picker->SetSelectionMode(poly, kSelEdge, false); + picker->SetSelectionMode(poly, kSelVertex, false); + picker->SetSelectionMode(line, kSelFace, false); + picker->SetSelectionMode(line, kSelEdge, false); + picker->SetSelectionMode(line, kSelVertex, false); + picker->InitializePickList(); } -vtkActor& GeometryActorSelectOp::getLineHLActor() +void GeometryActorSelectOp::configurePicker(IVtkTools_ShapePicker* picker, SelectMode mode) { - return *geometry_actor_->lineHLActor(); -} + if (!picker) + return; -IVtkTools_SubPolyDataFilter& GeometryActorSelectOp::getPolyHLFilter() -{ - return *geometry_actor_->polyHLFilter(); -} + const OccShapeHandle& occ = geometry_actor_->occ_shape_; + vtkActor* poly = geometry_actor_->poly_actor_.GetPointer(); + vtkActor* line = geometry_actor_->line_actor_.GetPointer(); -IVtkTools_SubPolyDataFilter& GeometryActorSelectOp::getLineHLFilter() -{ - return *geometry_actor_->lineHLFilter(); + const bool useLine = (mode == SelectMode::Edge || mode == SelectMode::Vertex); + + picker->PickFromListOn(); + picker->InitializePickList(); + picker->AddPickList(useLine ? line : poly); + if (useLine) + picker->AddPickList(poly); + picker->SetPixelTolerance(toleranceForMode(mode)); + + picker->SetSelectionMode(occ, kSelFace, false); + picker->SetSelectionMode(occ, kSelEdge, false); + picker->SetSelectionMode(occ, kSelVertex, false); + picker->SetSelectionMode(poly, kSelFace, false); + picker->SetSelectionMode(poly, kSelEdge, false); + picker->SetSelectionMode(poly, kSelVertex, false); + picker->SetSelectionMode(line, kSelFace, false); + picker->SetSelectionMode(line, kSelEdge, false); + picker->SetSelectionMode(line, kSelVertex, false); + + switch (mode) { + case SelectMode::Face: + case SelectMode::Solid: + picker->SetSelectionMode(occ, kSelFace, true); + picker->SetSelectionMode(poly, kSelFace, true); + break; + case SelectMode::Edge: + picker->SetSelectionMode(occ, kSelEdge, true); + picker->SetSelectionMode(line, kSelEdge, true); + break; + case SelectMode::Vertex: + picker->SetSelectionMode(occ, kSelVertex, true); + picker->SetSelectionMode(line, kSelVertex, true); + break; + default: + break; + } } -const OccShapeHandle& GeometryActorSelectOp::getOccShape() +std::optional GeometryActorSelectOp::pickSubshape(IVtkTools_ShapePicker* picker, vtkRenderer* renderer, + double posx, double posy, SelectMode mode, IVtk_IdType& out_sub_id) { - return geometry_actor_->getOccShape(); + if (!picker) + return std::nullopt; + + TopAbs_ShapeEnum wantType; + if (mode == SelectMode::Face) + wantType = TopAbs_FACE; + else if (mode == SelectMode::Edge) + wantType = TopAbs_EDGE; + else if (mode == SelectMode::Vertex) + wantType = TopAbs_VERTEX; + else + return std::nullopt; + + const int n = picker->Pick(posx, posy, 0.0, renderer); + if (n <= 0) + return std::nullopt; + + IVtk_IdType shapeId = -1; + if (!firstId(picker->GetPickedShapesIds(false), shapeId)) + return std::nullopt; + + out_sub_id = -1; + if (!firstId(picker->GetPickedSubShapesIds(shapeId, false), out_sub_id)) + return std::nullopt; + + const GeometrySubshapeIndex* geomIndex = geometry_actor_->geometry_index_; + if (!geomIndex) + return std::nullopt; + + ElementEnum::Type elemType = ElementEnum::None; + return mapSubshapeToGeomId(geometry_actor_->occ_shape_, *geomIndex, wantType, out_sub_id, elemType); } -const GeometrySubshapeIndex* GeometryActorSelectOp::getGeometryIndex() +bool GeometryActorSelectOp::pickSolid(IVtkTools_ShapePicker* picker, vtkRenderer* renderer, double posx, double posy, + GeomSolidId& out_solid_id, std::vector& out_face_sub_ids) { - return geometry_actor_->geometryIndex(); + if (!picker) + return false; + + const int n = picker->Pick(posx, posy, 0.0, renderer); + if (n <= 0) + return false; + + IVtk_IdType shapeId = -1; + if (!firstId(picker->GetPickedShapesIds(false), shapeId)) + return false; + + IVtk_IdType subId = -1; + if (!firstId(picker->GetPickedSubShapesIds(shapeId, false), subId)) + return false; + + const OccShapeHandle& occ = geometry_actor_->occ_shape_; + const TopoDS_Shape& pickedSub = occ->GetSubShape(subId); + if (pickedSub.IsNull()) + return false; + + const GeometrySubshapeIndex* geomIndex = geometry_actor_->geometry_index_; + if (!geomIndex) + return false; + + const int solidTi = GeometrySubshapeIndex::typeIndex(TopAbs_SOLID); + + TopoDS_Shape solidShape; + if (pickedSub.ShapeType() == TopAbs_SOLID) { + solidShape = pickedSub; + } else { + const int nSolids = geomIndex->type_maps[solidTi].Extent(); + for (int localId = 1; localId <= nSolids; ++localId) { + const TopoDS_Shape& solid = geomIndex->type_maps[solidTi].FindKey(localId); + for (TopExp_Explorer exp(solid, TopAbs_FACE); exp.More(); exp.Next()) { + if (exp.Current().IsSame(pickedSub)) { + solidShape = solid; + break; + } + } + if (!solidShape.IsNull()) + break; + } + if (solidShape.IsNull()) + return false; + } + + const int localTypeId = geomIndex->type_maps[solidTi].FindIndex(solidShape); + if (localTypeId <= 0) + return false; + + GeomSolidId gid = geomIndex->solidGlobalId(localTypeId); + if (gid == kInvalidGeomSolidId) + return false; + + out_solid_id = gid; + out_face_sub_ids.clear(); + for (TopExp_Explorer expF(solidShape, TopAbs_FACE); expF.More(); expF.Next()) { + IVtk_IdType faceSubId = occ->GetSubShapeId(expF.Current()); + if (faceSubId >= 0) + out_face_sub_ids.push_back(faceSubId); + } + return true; } -const vtkDataArray* GeometryActorSelectOp::getLineSubIdArray() const +IVtkTools_SubPolyDataFilter* GeometryActorSelectOp::highlightFilter(SelectMode mode) { - return geometry_actor_->lineSubIdArray(); + if (mode == SelectMode::Edge || mode == SelectMode::Vertex) + return geometry_actor_->line_hl_filter_.GetPointer(); + return geometry_actor_->poly_hl_filter_.GetPointer(); } -const vtkDataArray* GeometryActorSelectOp::getPolySubIdArray() const +vtkActor* GeometryActorSelectOp::highlightActor(SelectMode mode) { - return geometry_actor_->polySubIdArray(); + if (mode == SelectMode::Edge || mode == SelectMode::Vertex) + return geometry_actor_->line_hl_actor_.GetPointer(); + return geometry_actor_->poly_hl_actor_.GetPointer(); } diff --git a/app/render/GeometryActorSelectOp.h b/app/render/GeometryActorSelectOp.h index e345831..5311fa2 100644 --- a/app/render/GeometryActorSelectOp.h +++ b/app/render/GeometryActorSelectOp.h @@ -2,14 +2,18 @@ #define GEOMETRY_ACTOR_SELECT_OP_H #include #include -#include -#include +#include +#include + +#include "Core.h" #include "GeometryActor.h" class GeometryActorSelectOp; class IVtkTools_SubPolyDataFilter; +class IVtkTools_ShapePicker; class vtkActor; +class vtkRenderer; class GeometryActorSelectOpFactory { friend GeometryActorSelectOp; @@ -29,16 +33,23 @@ class GeometryActorSelectOp { public: GeometryActorSelectOp(std::shared_ptr geometry_actor); - vtkProp& getPolyActor(); - vtkProp& getLineActor(); - vtkActor& getPolyHLActor(); - vtkActor& getLineHLActor(); - IVtkTools_SubPolyDataFilter& getPolyHLFilter(); - IVtkTools_SubPolyDataFilter& getLineHLFilter(); - const OccShapeHandle& getOccShape(); - const GeometrySubshapeIndex* getGeometryIndex(); - const vtkDataArray* getLineSubIdArray() const; - const vtkDataArray* getPolySubIdArray() const; + // 重置该 actor 在 picker 上的所有 selection mode,并清空拾取列表 + void disablePickerModes(IVtkTools_ShapePicker* picker); + + // 按选择模式配置 picker:拾取列表 / 容差 / 启用的 selection mode + void configurePicker(IVtkTools_ShapePicker* picker, SelectMode mode); + + // 面/边/点拾取:命中则返回几何全局 id,并通过 out_sub_id 输出 OCC 子形状 id + std::optional pickSubshape(IVtkTools_ShapePicker* picker, vtkRenderer* renderer, + double posx, double posy, SelectMode mode, IVtk_IdType& out_sub_id); + + // 体拾取:命中则输出体全局 id 及该体所有面的子形状 id + bool pickSolid(IVtkTools_ShapePicker* picker, vtkRenderer* renderer, double posx, double posy, + GeomSolidId& out_solid_id, std::vector& out_face_sub_ids); + + // 按选择模式返回对应的高亮管线(面/体用 poly,边/点用 line) + IVtkTools_SubPolyDataFilter* highlightFilter(SelectMode mode); + vtkActor* highlightActor(SelectMode mode); private: std::shared_ptr geometry_actor_; diff --git a/app/render/GeometrySelectorHighlight.cpp b/app/render/GeometrySelectorHighlight.cpp index 7eb3a3b..7680070 100644 --- a/app/render/GeometrySelectorHighlight.cpp +++ b/app/render/GeometrySelectorHighlight.cpp @@ -1,93 +1,15 @@ #include "GeometrySelectorHighlight.h" -#include "GeometryActor.h" -#include "GeometrySubshapeIndex.h" +#include "GeometryActorSelectOp.h" #include "Core.h" -#include #include #include #include -#include -#include -#include - +#include #include #include #include -static constexpr IVtk_SelectionMode kSelVertex = SM_Vertex; -static constexpr IVtk_SelectionMode kSelEdge = SM_Edge; -static constexpr IVtk_SelectionMode kSelFace = SM_Face; -static constexpr IVtk_SelectionMode kSelSolid = SM_Shape; - -static int toleranceForMode(const SelectMode m) -{ - if (m == SelectMode::Vertex) - return 40; - if (m == SelectMode::Edge) - return 25; - if (m == SelectMode::Solid) - return 8; - return 8; -} - -static bool firstId(const NCollection_List& list, IVtk_IdType& outId) -{ - if (list.IsEmpty()) - return false; - outId = list.First(); - return true; -} - -static std::optional mapSubshapeToGeomId(const OccShapeHandle& occShape, - const GeometrySubshapeIndex& geomIndex, - TopAbs_ShapeEnum wantType, - IVtk_IdType subId, - ElementEnum::Type& outType) -{ - if (occShape.IsNull()) - return std::nullopt; - - const TopoDS_Shape& sub = occShape->GetSubShape(subId); - if (sub.IsNull()) - return std::nullopt; - - const int ti = GeometrySubshapeIndex::typeIndex(wantType); - if (ti < 0) - return std::nullopt; - - const int localTypeId = geomIndex.type_maps[static_cast(ti)].FindIndex(sub); - if (localTypeId <= 0) - return std::nullopt; - - if (wantType == TopAbs_FACE) { - GeomFaceId gid = geomIndex.faceGlobalId(localTypeId); - if (gid == kInvalidGeomFaceId) - return std::nullopt; - outType = ElementEnum::Face; - return gid; - } else if (wantType == TopAbs_EDGE) { - GeomEdgeId gid = geomIndex.edgeGlobalId(localTypeId); - if (gid == kInvalidGeomEdgeId) - return std::nullopt; - outType = ElementEnum::Edge; - return gid; - } else if (wantType == TopAbs_VERTEX) { - GeomVertexId gid = geomIndex.vertexGlobalId(localTypeId); - if (gid == kInvalidGeomVertexId) - return std::nullopt; - outType = ElementEnum::Vertex; - return gid; - } else if (wantType == TopAbs_SOLID) { - GeomSolidId gid = geomIndex.solidGlobalId(localTypeId); - if (gid == kInvalidGeomSolidId) - return std::nullopt; - outType = ElementEnum::Solid; - return gid; - } - return std::nullopt; -} - static void flushHighlight(IVtkTools_SubPolyDataFilter* filter, vtkActor* hlActor, bool visible, vtkRenderer* renderer) { if (!filter || !hlActor || !renderer) @@ -136,24 +58,8 @@ void GeometryFaceSelectorHighlight::select(double posx, double posy) if (!op) return; - const int n = picker_->Pick(posx, posy, 0.0, renderer_); - if (n <= 0) - return; - - IVtk_IdType shapeId = -1; - if (!firstId(picker_->GetPickedShapesIds(false), shapeId)) - return; - IVtk_IdType subId = -1; - if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) - return; - - const auto* geomIndex = op->getGeometryIndex(); - if (!geomIndex) - return; - - ElementEnum::Type elemType = ElementEnum::None; - auto geomId = mapSubshapeToGeomId(op->getOccShape(), *geomIndex, TopAbs_FACE, subId, elemType); + auto geomId = op->pickSubshape(picker_, renderer_, posx, posy, SelectMode::Face, subId); if (!geomId) return; @@ -172,23 +78,8 @@ void GeometryFaceSelectorHighlight::select(double posx, double posy) void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { - { - auto oldOp = geom_actor_.lock(); - if (oldOp) { - picker_->SetSelectionMode(oldOp->getOccShape(), kSelFace, false); - picker_->SetSelectionMode(oldOp->getOccShape(), kSelEdge, false); - picker_->SetSelectionMode(oldOp->getOccShape(), kSelVertex, false); - auto& poly = dynamic_cast(oldOp->getPolyActor()); - picker_->SetSelectionMode(&poly, kSelFace, false); - picker_->SetSelectionMode(&poly, kSelEdge, false); - picker_->SetSelectionMode(&poly, kSelVertex, false); - auto& line = dynamic_cast(oldOp->getLineActor()); - picker_->SetSelectionMode(&line, kSelFace, false); - picker_->SetSelectionMode(&line, kSelEdge, false); - picker_->SetSelectionMode(&line, kSelVertex, false); - picker_->InitializePickList(); - } - } + if (auto oldOp = geom_actor_.lock()) + oldOp->disablePickerModes(picker_); clear(); geom_actor_ = std::move(geom_actor); @@ -197,38 +88,10 @@ void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory auto op = geom_actor_.lock(); if (op) { - filter_ = &op->getPolyHLFilter(); - hl_actor_ = &op->getPolyHLActor(); + filter_ = op->highlightFilter(SelectMode::Face); + hl_actor_ = op->highlightActor(SelectMode::Face); + op->configurePicker(picker_, SelectMode::Face); } - - configurePicker(); -} - -void GeometryFaceSelectorHighlight::configurePicker() -{ - auto op = geom_actor_.lock(); - if (!op) - return; - - picker_->PickFromListOn(); - picker_->InitializePickList(); - picker_->AddPickList(&dynamic_cast(op->getPolyActor())); - picker_->SetPixelTolerance(toleranceForMode(SelectMode::Face)); - - picker_->SetSelectionMode(op->getOccShape(), kSelFace, false); - picker_->SetSelectionMode(op->getOccShape(), kSelEdge, false); - picker_->SetSelectionMode(op->getOccShape(), kSelVertex, false); - picker_->SetSelectionMode(op->getOccShape(), kSelFace, true); - - auto& poly = dynamic_cast(op->getPolyActor()); - picker_->SetSelectionMode(&poly, kSelFace, true); - picker_->SetSelectionMode(&poly, kSelEdge, false); - picker_->SetSelectionMode(&poly, kSelVertex, false); - - auto& line = dynamic_cast(op->getLineActor()); - picker_->SetSelectionMode(&line, kSelFace, false); - picker_->SetSelectionMode(&line, kSelEdge, false); - picker_->SetSelectionMode(&line, kSelVertex, false); } // ─── Edge ────────────────────────────────────────────── @@ -269,24 +132,8 @@ void GeometryEdgeSelectorHighlight::select(double posx, double posy) if (!op) return; - const int n = picker_->Pick(posx, posy, 0.0, renderer_); - if (n <= 0) - return; - - IVtk_IdType shapeId = -1; - if (!firstId(picker_->GetPickedShapesIds(false), shapeId)) - return; - IVtk_IdType subId = -1; - if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) - return; - - const auto* geomIndex = op->getGeometryIndex(); - if (!geomIndex) - return; - - ElementEnum::Type elemType = ElementEnum::None; - auto geomId = mapSubshapeToGeomId(op->getOccShape(), *geomIndex, TopAbs_EDGE, subId, elemType); + auto geomId = op->pickSubshape(picker_, renderer_, posx, posy, SelectMode::Edge, subId); if (!geomId) return; @@ -305,23 +152,8 @@ void GeometryEdgeSelectorHighlight::select(double posx, double posy) void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { - { - auto oldOp = geom_actor_.lock(); - if (oldOp) { - picker_->SetSelectionMode(oldOp->getOccShape(), kSelFace, false); - picker_->SetSelectionMode(oldOp->getOccShape(), kSelEdge, false); - picker_->SetSelectionMode(oldOp->getOccShape(), kSelVertex, false); - auto& poly = dynamic_cast(oldOp->getPolyActor()); - picker_->SetSelectionMode(&poly, kSelFace, false); - picker_->SetSelectionMode(&poly, kSelEdge, false); - picker_->SetSelectionMode(&poly, kSelVertex, false); - auto& line = dynamic_cast(oldOp->getLineActor()); - picker_->SetSelectionMode(&line, kSelFace, false); - picker_->SetSelectionMode(&line, kSelEdge, false); - picker_->SetSelectionMode(&line, kSelVertex, false); - picker_->InitializePickList(); - } - } + if (auto oldOp = geom_actor_.lock()) + oldOp->disablePickerModes(picker_); clear(); geom_actor_ = std::move(geom_actor); @@ -330,44 +162,10 @@ void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory auto op = geom_actor_.lock(); if (op) { - filter_ = &op->getLineHLFilter(); - hl_actor_ = &op->getLineHLActor(); + filter_ = op->highlightFilter(SelectMode::Edge); + hl_actor_ = op->highlightActor(SelectMode::Edge); + op->configurePicker(picker_, SelectMode::Edge); } - - configurePicker(); -} - -void GeometryEdgeSelectorHighlight::configurePicker() -{ - auto op = geom_actor_.lock(); - if (!op) - return; - - picker_->PickFromListOn(); - picker_->InitializePickList(); - picker_->AddPickList(&dynamic_cast(op->getLineActor())); - { - auto& poly = dynamic_cast(op->getPolyActor()); - picker_->AddPickList(&poly); - } - picker_->SetPixelTolerance(toleranceForMode(SelectMode::Edge)); - - picker_->SetSelectionMode(op->getOccShape(), kSelFace, false); - picker_->SetSelectionMode(op->getOccShape(), kSelEdge, false); - picker_->SetSelectionMode(op->getOccShape(), kSelVertex, false); - picker_->SetSelectionMode(op->getOccShape(), kSelEdge, true); - - { - auto& poly = dynamic_cast(op->getPolyActor()); - picker_->SetSelectionMode(&poly, kSelFace, false); - picker_->SetSelectionMode(&poly, kSelEdge, false); - picker_->SetSelectionMode(&poly, kSelVertex, false); - } - - auto& line = dynamic_cast(op->getLineActor()); - picker_->SetSelectionMode(&line, kSelEdge, true); - picker_->SetSelectionMode(&line, kSelVertex, false); - picker_->SetSelectionMode(&line, kSelFace, false); } // ─── Vertex ──────────────────────────────────────────── @@ -408,24 +206,8 @@ void GeometryVertexSelectorHighlight::select(double posx, double posy) if (!op) return; - const int n = picker_->Pick(posx, posy, 0.0, renderer_); - if (n <= 0) - return; - - IVtk_IdType shapeId = -1; - if (!firstId(picker_->GetPickedShapesIds(false), shapeId)) - return; - IVtk_IdType subId = -1; - if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) - return; - - const auto* geomIndex = op->getGeometryIndex(); - if (!geomIndex) - return; - - ElementEnum::Type elemType = ElementEnum::None; - auto geomId = mapSubshapeToGeomId(op->getOccShape(), *geomIndex, TopAbs_VERTEX, subId, elemType); + auto geomId = op->pickSubshape(picker_, renderer_, posx, posy, SelectMode::Vertex, subId); if (!geomId) return; @@ -444,23 +226,8 @@ void GeometryVertexSelectorHighlight::select(double posx, double posy) void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { - { - auto oldOp = geom_actor_.lock(); - if (oldOp) { - picker_->SetSelectionMode(oldOp->getOccShape(), kSelFace, false); - picker_->SetSelectionMode(oldOp->getOccShape(), kSelEdge, false); - picker_->SetSelectionMode(oldOp->getOccShape(), kSelVertex, false); - auto& poly = dynamic_cast(oldOp->getPolyActor()); - picker_->SetSelectionMode(&poly, kSelFace, false); - picker_->SetSelectionMode(&poly, kSelEdge, false); - picker_->SetSelectionMode(&poly, kSelVertex, false); - auto& line = dynamic_cast(oldOp->getLineActor()); - picker_->SetSelectionMode(&line, kSelFace, false); - picker_->SetSelectionMode(&line, kSelEdge, false); - picker_->SetSelectionMode(&line, kSelVertex, false); - picker_->InitializePickList(); - } - } + if (auto oldOp = geom_actor_.lock()) + oldOp->disablePickerModes(picker_); clear(); geom_actor_ = std::move(geom_actor); @@ -469,44 +236,10 @@ void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFacto auto op = geom_actor_.lock(); if (op) { - filter_ = &op->getLineHLFilter(); - hl_actor_ = &op->getLineHLActor(); - } - - configurePicker(); -} - -void GeometryVertexSelectorHighlight::configurePicker() -{ - auto op = geom_actor_.lock(); - if (!op) - return; - - picker_->PickFromListOn(); - picker_->InitializePickList(); - picker_->AddPickList(&dynamic_cast(op->getLineActor())); - { - auto& poly = dynamic_cast(op->getPolyActor()); - picker_->AddPickList(&poly); - } - picker_->SetPixelTolerance(toleranceForMode(SelectMode::Vertex)); - - picker_->SetSelectionMode(op->getOccShape(), kSelFace, false); - picker_->SetSelectionMode(op->getOccShape(), kSelEdge, false); - picker_->SetSelectionMode(op->getOccShape(), kSelVertex, false); - picker_->SetSelectionMode(op->getOccShape(), kSelVertex, true); - - { - auto& poly = dynamic_cast(op->getPolyActor()); - picker_->SetSelectionMode(&poly, kSelFace, false); - picker_->SetSelectionMode(&poly, kSelEdge, false); - picker_->SetSelectionMode(&poly, kSelVertex, false); + filter_ = op->highlightFilter(SelectMode::Vertex); + hl_actor_ = op->highlightActor(SelectMode::Vertex); + op->configurePicker(picker_, SelectMode::Vertex); } - - auto& line = dynamic_cast(op->getLineActor()); - picker_->SetSelectionMode(&line, kSelVertex, true); - picker_->SetSelectionMode(&line, kSelEdge, false); - picker_->SetSelectionMode(&line, kSelFace, false); } // ─── Solid ───────────────────────────────────────────── @@ -548,70 +281,20 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) if (!op) return; - const int n = picker_->Pick(posx, posy, 0.0, renderer_); - if (n <= 0) - return; - - IVtk_IdType shapeId = -1; - if (!firstId(picker_->GetPickedShapesIds(false), shapeId)) - return; - - IVtk_IdType subId = -1; - if (!firstId(picker_->GetPickedSubShapesIds(shapeId, false), subId)) - return; - - const TopoDS_Shape& pickedSub = op->getOccShape()->GetSubShape(subId); - if (pickedSub.IsNull()) - return; - - const auto* geomIndex = op->getGeometryIndex(); - if (!geomIndex) - return; - - TopoDS_Shape solidShape; - if (pickedSub.ShapeType() == TopAbs_SOLID) { - solidShape = pickedSub; - } else { - const int solidTi = GeometrySubshapeIndex::typeIndex(TopAbs_SOLID); - const int nSolids = geomIndex->type_maps[solidTi].Extent(); - for (int localId = 1; localId <= nSolids; ++localId) { - const TopoDS_Shape& solid = geomIndex->type_maps[solidTi].FindKey(localId); - for (TopExp_Explorer exp(solid, TopAbs_FACE); exp.More(); exp.Next()) { - if (exp.Current().IsSame(pickedSub)) { - solidShape = solid; - break; - } - } - if (!solidShape.IsNull()) - break; - } - if (solidShape.IsNull()) - return; - } - - const int solidTi = GeometrySubshapeIndex::typeIndex(TopAbs_SOLID); - const int localTypeId = geomIndex->type_maps[solidTi].FindIndex(solidShape); - if (localTypeId <= 0) - return; - - GeomSolidId gid = geomIndex->solidGlobalId(localTypeId); - if (gid == kInvalidGeomSolidId) + GeomSolidId gid = kInvalidGeomSolidId; + std::vector faceSubIds; + if (!op->pickSolid(picker_, renderer_, posx, posy, gid, faceSubIds)) return; auto [it, inserted] = selections_.insert_or_assign(gid, gid); - if (!inserted) { + if (!inserted) selections_.erase(it); - } - for (TopExp_Explorer expF(solidShape, TopAbs_FACE); expF.More(); expF.Next()) { - const TopoDS_Shape& face = expF.Current(); - IVtk_IdType faceSubId = op->getOccShape()->GetSubShapeId(face); - if (faceSubId >= 0) { - if (!inserted) - highlighted_face_ids_.erase(faceSubId); - else - highlighted_face_ids_.insert(faceSubId); - } + for (IVtk_IdType faceSubId : faceSubIds) { + if (!inserted) + highlighted_face_ids_.erase(faceSubId); + else + highlighted_face_ids_.insert(faceSubId); } NCollection_List ids; @@ -625,23 +308,8 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) { - { - auto oldOp = geom_actor_.lock(); - if (oldOp) { - picker_->SetSelectionMode(oldOp->getOccShape(), kSelFace, false); - picker_->SetSelectionMode(oldOp->getOccShape(), kSelEdge, false); - picker_->SetSelectionMode(oldOp->getOccShape(), kSelVertex, false); - auto& poly = dynamic_cast(oldOp->getPolyActor()); - picker_->SetSelectionMode(&poly, kSelFace, false); - picker_->SetSelectionMode(&poly, kSelEdge, false); - picker_->SetSelectionMode(&poly, kSelVertex, false); - auto& line = dynamic_cast(oldOp->getLineActor()); - picker_->SetSelectionMode(&line, kSelFace, false); - picker_->SetSelectionMode(&line, kSelEdge, false); - picker_->SetSelectionMode(&line, kSelVertex, false); - picker_->InitializePickList(); - } - } + if (auto oldOp = geom_actor_.lock()) + oldOp->disablePickerModes(picker_); clear(); geom_actor_ = std::move(geom_actor); @@ -650,39 +318,8 @@ void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactor auto op = geom_actor_.lock(); if (op) { - filter_ = &op->getPolyHLFilter(); - hl_actor_ = &op->getPolyHLActor(); + filter_ = op->highlightFilter(SelectMode::Solid); + hl_actor_ = op->highlightActor(SelectMode::Solid); + op->configurePicker(picker_, SelectMode::Solid); } - - configurePicker(); -} - -void GeometrySolidSelectorHighlight::configurePicker() -{ - auto op = geom_actor_.lock(); - if (!op) { - if (picker_) - picker_->InitializePickList(); - return; - } - - picker_->PickFromListOn(); - picker_->InitializePickList(); - picker_->AddPickList(&dynamic_cast(op->getPolyActor())); - picker_->SetPixelTolerance(toleranceForMode(SelectMode::Solid)); - - picker_->SetSelectionMode(op->getOccShape(), kSelFace, false); - picker_->SetSelectionMode(op->getOccShape(), kSelEdge, false); - picker_->SetSelectionMode(op->getOccShape(), kSelVertex, false); - picker_->SetSelectionMode(op->getOccShape(), kSelFace, true); - - auto& poly = dynamic_cast(op->getPolyActor()); - picker_->SetSelectionMode(&poly, kSelFace, true); - picker_->SetSelectionMode(&poly, kSelEdge, false); - picker_->SetSelectionMode(&poly, kSelVertex, false); - - auto& line = dynamic_cast(op->getLineActor()); - picker_->SetSelectionMode(&line, kSelFace, false); - picker_->SetSelectionMode(&line, kSelEdge, false); - picker_->SetSelectionMode(&line, kSelVertex, false); } diff --git a/app/render/GeometrySelectorHighlight.h b/app/render/GeometrySelectorHighlight.h index af58c6e..32a5de2 100644 --- a/app/render/GeometrySelectorHighlight.h +++ b/app/render/GeometrySelectorHighlight.h @@ -26,7 +26,6 @@ public: void setPicker(vtkSmartPointer picker) { picker_ = picker; } protected: - virtual void configurePicker() = 0; vtkSmartPointer picker_; }; @@ -40,8 +39,6 @@ public: void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; private: - void configurePicker() override; - vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; IVtkTools_SubPolyDataFilter* filter_ { nullptr }; @@ -60,8 +57,6 @@ public: void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; private: - void configurePicker() override; - vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; IVtkTools_SubPolyDataFilter* filter_ { nullptr }; @@ -80,8 +75,6 @@ public: void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; private: - void configurePicker() override; - vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; IVtkTools_SubPolyDataFilter* filter_ { nullptr }; @@ -100,8 +93,6 @@ public: void setCurGeomActor(GeometryActorSelectOpFactory geom_actor) override; private: - void configurePicker() override; - vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; IVtkTools_SubPolyDataFilter* filter_ { nullptr }; -- Gitee From b520da07fadcf0323d1c9faa258bd60a75eccf85 Mon Sep 17 00:00:00 2001 From: hypf Date: Fri, 10 Jul 2026 20:09:48 +0800 Subject: [PATCH 10/13] =?UTF-8?q?refactor(app)=EF=BC=9A=E5=B0=86=E9=AB=98?= =?UTF-8?q?=E4=BA=AE=E7=AE=A1=E7=BA=BF=E4=BB=8EGeometryActor=E7=A7=BB?= =?UTF-8?q?=E5=87=BA=EF=BC=8C=E7=94=B1Op=E6=9E=84=E9=80=A0=E5=B9=B6?= =?UTF-8?q?=E5=AD=98=E5=9C=A8Selector=E9=87=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/render/GeometryActor.cpp | 65 +---------- app/render/GeometryActor.h | 9 +- app/render/GeometryActorSelectOp.cpp | 55 +++++++-- app/render/GeometryActorSelectOp.h | 20 ++-- app/render/GeometrySelectorHighlight.cpp | 137 ++++++++++++++--------- app/render/GeometrySelectorHighlight.h | 12 +- 6 files changed, 151 insertions(+), 147 deletions(-) diff --git a/app/render/GeometryActor.cpp b/app/render/GeometryActor.cpp index c75570b..3242d54 100644 --- a/app/render/GeometryActor.cpp +++ b/app/render/GeometryActor.cpp @@ -120,22 +120,6 @@ bool GeometryActor::getIsEdgeRender() void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) { - // 清理上一次的高亮管线 - if (renderer_) { - if (poly_hl_actor_) { - renderer_->RemoveActor(poly_hl_actor_); - poly_hl_actor_ = nullptr; - } - if (line_hl_actor_) { - renderer_->RemoveActor(line_hl_actor_); - line_hl_actor_ = nullptr; - } - } - poly_hl_filter_ = nullptr; - poly_hl_mapper_ = nullptr; - line_hl_filter_ = nullptr; - line_hl_mapper_ = nullptr; - // 全局:开一次 vtkMapper::SetResolveCoincidentTopologyToPolygonOffset(); @@ -190,6 +174,9 @@ void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) if (!poly_only) poly_only = vtkSmartPointer::New(); + this->line_only_ = line_only; + this->poly_only_ = poly_only; + line_sub_id_array_ = findSubIdArray(line_only, occ_shape_); poly_sub_id_array_ = findSubIdArray(poly_only, occ_shape_); @@ -218,26 +205,6 @@ void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) poly_actor_->GetProperty()->SetColor(200.0 / 255.0, 200.0 / 255.0, 200.0 / 255.0); renderer_->AddActor(poly_actor_); - poly_hl_filter_ = vtkSmartPointer::New(); - poly_hl_filter_->SetInputData(poly_only); - poly_hl_filter_->SetDoFiltering(true); - if (poly_sub_id_array_ && poly_sub_id_array_->GetName()) - poly_hl_filter_->SetIdsArrayName(poly_sub_id_array_->GetName()); - - poly_hl_mapper_ = vtkSmartPointer::New(); - poly_hl_mapper_->SetInputConnection(poly_hl_filter_->GetOutputPort()); - // 相对显示 mapper 默认值:多边形 (0,-1) - poly_hl_mapper_->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, -0.5); - - - poly_hl_actor_ = vtkSmartPointer::New(); - poly_hl_actor_->SetMapper(poly_hl_mapper_); - poly_hl_actor_->GetProperty()->SetColor(1.0, 0.0, 0.0); - poly_hl_actor_->GetProperty()->SetOpacity(1); - poly_hl_actor_->SetVisibility(false); - poly_hl_actor_->PickableOff(); - renderer_->AddActor(poly_hl_actor_); - vtkNew line_mapper; line_mapper->SetInputConnection(lineEdgeFilter->GetOutputPort()); line_mapper->SetRelativeCoincidentTopologyLineOffsetParameters(0, 4); @@ -251,30 +218,6 @@ void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) line_actor_->GetProperty()->SetColor(0.0, 0.0, 0.0); renderer_->AddActor(line_actor_); - line_hl_filter_ = vtkSmartPointer::New(); - line_hl_filter_->SetInputData(line_only); - line_hl_filter_->SetDoFiltering(true); - if (line_sub_id_array_ && line_sub_id_array_->GetName()) - line_hl_filter_->SetIdsArrayName(line_sub_id_array_->GetName()); - - line_hl_mapper_ = vtkSmartPointer::New(); - line_hl_mapper_->SetInputConnection(line_hl_filter_->GetOutputPort()); - // 相对显示 mapper 默认值:线 (0,-5),点 (-10) - line_hl_mapper_->SetRelativeCoincidentTopologyLineOffsetParameters(0, -1); - line_hl_mapper_->SetRelativeCoincidentTopologyPointOffsetParameter(-2); - - line_hl_actor_ = vtkSmartPointer::New(); - line_hl_actor_->SetMapper(line_hl_mapper_); - line_hl_actor_->GetProperty()->SetColor(1.0, 0.0, 0.0); - line_hl_actor_->GetProperty()->SetOpacity(0.5); - line_hl_actor_->GetProperty()->RenderLinesAsTubesOn(); - line_hl_actor_->GetProperty()->SetLineWidth(3.0); - line_hl_actor_->GetProperty()->SetPointSize(8.0); - line_hl_actor_->GetProperty()->LightingOff(); - line_hl_actor_->SetVisibility(false); - line_hl_actor_->PickableOff(); - renderer_->AddActor(line_hl_actor_); - spdlog::info("[GeometryActor] component={} actors added, face_cells={} line_cells={}", geometry_data.component_id, static_cast(poly_only->GetNumberOfCells()), static_cast(line_only->GetNumberOfCells())); } @@ -284,8 +227,6 @@ void GeometryActor::deleteGeometryActor() if (this->renderer_) { renderer_->RemoveActor(this->poly_actor_); renderer_->RemoveActor(this->line_actor_); - renderer_->RemoveActor(this->poly_hl_actor_); - renderer_->RemoveActor(this->line_hl_actor_); } } diff --git a/app/render/GeometryActor.h b/app/render/GeometryActor.h index dda9d92..193472f 100644 --- a/app/render/GeometryActor.h +++ b/app/render/GeometryActor.h @@ -15,6 +15,7 @@ typedef Handle(IVtkOCC_Shape) OccShapeHandle; class GeometryActorSelectOp; +class vtkPolyData; class GeometryActor { friend GeometryActorSelectOp; @@ -47,12 +48,8 @@ private: vtkSmartPointer line_sub_id_array_; vtkSmartPointer poly_sub_id_array_; - vtkSmartPointer poly_hl_filter_; - vtkSmartPointer line_hl_filter_; - vtkSmartPointer poly_hl_mapper_; - vtkSmartPointer line_hl_mapper_; - vtkSmartPointer poly_hl_actor_; - vtkSmartPointer line_hl_actor_; + vtkSmartPointer poly_only_; + vtkSmartPointer line_only_; }; #endif \ No newline at end of file diff --git a/app/render/GeometryActorSelectOp.cpp b/app/render/GeometryActorSelectOp.cpp index 6c0f90c..c95cd5d 100644 --- a/app/render/GeometryActorSelectOp.cpp +++ b/app/render/GeometryActorSelectOp.cpp @@ -5,6 +5,10 @@ #include "Core.h" #include +#include +#include +#include +#include #include #include #include @@ -279,16 +283,47 @@ bool GeometryActorSelectOp::pickSolid(IVtkTools_ShapePicker* picker, vtkRenderer return true; } -IVtkTools_SubPolyDataFilter* GeometryActorSelectOp::highlightFilter(SelectMode mode) +GeometryHighlightPipeline GeometryActorSelectOp::buildHighlight(SelectMode mode) { - if (mode == SelectMode::Edge || mode == SelectMode::Vertex) - return geometry_actor_->line_hl_filter_.GetPointer(); - return geometry_actor_->poly_hl_filter_.GetPointer(); -} + GeometryHighlightPipeline hl; -vtkActor* GeometryActorSelectOp::highlightActor(SelectMode mode) -{ - if (mode == SelectMode::Edge || mode == SelectMode::Vertex) - return geometry_actor_->line_hl_actor_.GetPointer(); - return geometry_actor_->poly_hl_actor_.GetPointer(); + const bool useLine = (mode == SelectMode::Edge || mode == SelectMode::Vertex); + vtkPolyData* source = useLine ? geometry_actor_->line_only_.GetPointer() + : geometry_actor_->poly_only_.GetPointer(); + vtkDataArray* idArray = useLine ? geometry_actor_->line_sub_id_array_.GetPointer() + : geometry_actor_->poly_sub_id_array_.GetPointer(); + if (!source) + return hl; + + hl.filter = vtkSmartPointer::New(); + hl.filter->SetInputData(source); + hl.filter->SetDoFiltering(true); + if (idArray && idArray->GetName()) + hl.filter->SetIdsArrayName(idArray->GetName()); + + hl.mapper = vtkSmartPointer::New(); + hl.mapper->SetInputConnection(hl.filter->GetOutputPort()); + + hl.actor = vtkSmartPointer::New(); + hl.actor->SetMapper(hl.mapper); + hl.actor->GetProperty()->SetColor(1.0, 0.0, 0.0); + hl.actor->SetVisibility(false); + hl.actor->PickableOff(); + + if (useLine) { + // 相对显示 mapper 默认值:线 (0,-5),点 (-10) + hl.mapper->SetRelativeCoincidentTopologyLineOffsetParameters(0, -1); + hl.mapper->SetRelativeCoincidentTopologyPointOffsetParameter(-2); + hl.actor->GetProperty()->SetOpacity(0.5); + hl.actor->GetProperty()->RenderLinesAsTubesOn(); + hl.actor->GetProperty()->SetLineWidth(3.0); + hl.actor->GetProperty()->SetPointSize(8.0); + hl.actor->GetProperty()->LightingOff(); + } else { + // 相对显示 mapper 默认值:多边形 (0,-1) + hl.mapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, -0.5); + hl.actor->GetProperty()->SetOpacity(1); + } + + return hl; } diff --git a/app/render/GeometryActorSelectOp.h b/app/render/GeometryActorSelectOp.h index 5311fa2..8353f0d 100644 --- a/app/render/GeometryActorSelectOp.h +++ b/app/render/GeometryActorSelectOp.h @@ -4,17 +4,25 @@ #include #include +#include +#include +#include +#include #include #include "Core.h" #include "GeometryActor.h" class GeometryActorSelectOp; -class IVtkTools_SubPolyDataFilter; class IVtkTools_ShapePicker; -class vtkActor; class vtkRenderer; +struct GeometryHighlightPipeline { + vtkSmartPointer filter; + vtkSmartPointer mapper; + vtkSmartPointer actor; +}; + class GeometryActorSelectOpFactory { friend GeometryActorSelectOp; @@ -33,23 +41,17 @@ class GeometryActorSelectOp { public: GeometryActorSelectOp(std::shared_ptr geometry_actor); - // 重置该 actor 在 picker 上的所有 selection mode,并清空拾取列表 void disablePickerModes(IVtkTools_ShapePicker* picker); - // 按选择模式配置 picker:拾取列表 / 容差 / 启用的 selection mode void configurePicker(IVtkTools_ShapePicker* picker, SelectMode mode); - // 面/边/点拾取:命中则返回几何全局 id,并通过 out_sub_id 输出 OCC 子形状 id std::optional pickSubshape(IVtkTools_ShapePicker* picker, vtkRenderer* renderer, double posx, double posy, SelectMode mode, IVtk_IdType& out_sub_id); - // 体拾取:命中则输出体全局 id 及该体所有面的子形状 id bool pickSolid(IVtkTools_ShapePicker* picker, vtkRenderer* renderer, double posx, double posy, GeomSolidId& out_solid_id, std::vector& out_face_sub_ids); - // 按选择模式返回对应的高亮管线(面/体用 poly,边/点用 line) - IVtkTools_SubPolyDataFilter* highlightFilter(SelectMode mode); - vtkActor* highlightActor(SelectMode mode); + GeometryHighlightPipeline buildHighlight(SelectMode mode); private: std::shared_ptr geometry_actor_; diff --git a/app/render/GeometrySelectorHighlight.cpp b/app/render/GeometrySelectorHighlight.cpp index 7680070..79a3630 100644 --- a/app/render/GeometrySelectorHighlight.cpp +++ b/app/render/GeometrySelectorHighlight.cpp @@ -20,6 +20,15 @@ static void flushHighlight(IVtkTools_SubPolyDataFilter* filter, vtkActor* hlActo renderer->GetRenderWindow()->Render(); } +static void removeHighlightActor(GeometryHighlightPipeline& hl, vtkRenderer* renderer) +{ + if (hl.actor && renderer) { + renderer->RemoveActor(hl.actor); + if (renderer->GetRenderWindow()) + renderer->GetRenderWindow()->Render(); + } +} + // ─── Face ────────────────────────────────────────────── GeometryFaceSelectorHighlight::GeometryFaceSelectorHighlight(vtkRenderer* renderer) @@ -27,17 +36,21 @@ GeometryFaceSelectorHighlight::GeometryFaceSelectorHighlight(vtkRenderer* render { } -GeometryFaceSelectorHighlight::~GeometryFaceSelectorHighlight() { clear(); } +GeometryFaceSelectorHighlight::~GeometryFaceSelectorHighlight() +{ + clear(); + removeHighlightActor(hl_, renderer_); +} void GeometryFaceSelectorHighlight::clear() { selections_.clear(); - if (filter_) { - filter_->Clear(); - filter_->Modified(); + if (hl_.filter) { + hl_.filter->Clear(); + hl_.filter->Modified(); } - if (hl_actor_) - hl_actor_->SetVisibility(false); + if (hl_.actor) + hl_.actor->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -71,9 +84,9 @@ void GeometryFaceSelectorHighlight::select(double posx, double posy) for (const auto& [sid, gid] : selections_) ids.Append(sid); - if (filter_) - filter_->SetData(ids); - flushHighlight(filter_, hl_actor_, !ids.IsEmpty(), renderer_); + if (hl_.filter) + hl_.filter->SetData(ids); + flushHighlight(hl_.filter, hl_.actor, !ids.IsEmpty(), renderer_); } void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) @@ -82,14 +95,16 @@ void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory oldOp->disablePickerModes(picker_); clear(); + removeHighlightActor(hl_, renderer_); + hl_ = {}; + geom_actor_ = std::move(geom_actor); - filter_ = nullptr; - hl_actor_ = nullptr; auto op = geom_actor_.lock(); if (op) { - filter_ = op->highlightFilter(SelectMode::Face); - hl_actor_ = op->highlightActor(SelectMode::Face); + hl_ = op->buildHighlight(SelectMode::Face); + if (renderer_ && hl_.actor) + renderer_->AddActor(hl_.actor); op->configurePicker(picker_, SelectMode::Face); } } @@ -101,17 +116,21 @@ GeometryEdgeSelectorHighlight::GeometryEdgeSelectorHighlight(vtkRenderer* render { } -GeometryEdgeSelectorHighlight::~GeometryEdgeSelectorHighlight() { clear(); } +GeometryEdgeSelectorHighlight::~GeometryEdgeSelectorHighlight() +{ + clear(); + removeHighlightActor(hl_, renderer_); +} void GeometryEdgeSelectorHighlight::clear() { selections_.clear(); - if (filter_) { - filter_->Clear(); - filter_->Modified(); + if (hl_.filter) { + hl_.filter->Clear(); + hl_.filter->Modified(); } - if (hl_actor_) - hl_actor_->SetVisibility(false); + if (hl_.actor) + hl_.actor->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -145,9 +164,9 @@ void GeometryEdgeSelectorHighlight::select(double posx, double posy) for (const auto& [sid, gid] : selections_) ids.Append(sid); - if (filter_) - filter_->SetData(ids); - flushHighlight(filter_, hl_actor_, !ids.IsEmpty(), renderer_); + if (hl_.filter) + hl_.filter->SetData(ids); + flushHighlight(hl_.filter, hl_.actor, !ids.IsEmpty(), renderer_); } void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) @@ -156,14 +175,16 @@ void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory oldOp->disablePickerModes(picker_); clear(); + removeHighlightActor(hl_, renderer_); + hl_ = {}; + geom_actor_ = std::move(geom_actor); - filter_ = nullptr; - hl_actor_ = nullptr; auto op = geom_actor_.lock(); if (op) { - filter_ = op->highlightFilter(SelectMode::Edge); - hl_actor_ = op->highlightActor(SelectMode::Edge); + hl_ = op->buildHighlight(SelectMode::Edge); + if (renderer_ && hl_.actor) + renderer_->AddActor(hl_.actor); op->configurePicker(picker_, SelectMode::Edge); } } @@ -175,17 +196,21 @@ GeometryVertexSelectorHighlight::GeometryVertexSelectorHighlight(vtkRenderer* re { } -GeometryVertexSelectorHighlight::~GeometryVertexSelectorHighlight() { clear(); } +GeometryVertexSelectorHighlight::~GeometryVertexSelectorHighlight() +{ + clear(); + removeHighlightActor(hl_, renderer_); +} void GeometryVertexSelectorHighlight::clear() { selections_.clear(); - if (filter_) { - filter_->Clear(); - filter_->Modified(); + if (hl_.filter) { + hl_.filter->Clear(); + hl_.filter->Modified(); } - if (hl_actor_) - hl_actor_->SetVisibility(false); + if (hl_.actor) + hl_.actor->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -219,9 +244,9 @@ void GeometryVertexSelectorHighlight::select(double posx, double posy) for (const auto& [sid, gid] : selections_) ids.Append(sid); - if (filter_) - filter_->SetData(ids); - flushHighlight(filter_, hl_actor_, !ids.IsEmpty(), renderer_); + if (hl_.filter) + hl_.filter->SetData(ids); + flushHighlight(hl_.filter, hl_.actor, !ids.IsEmpty(), renderer_); } void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) @@ -230,14 +255,16 @@ void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFacto oldOp->disablePickerModes(picker_); clear(); + removeHighlightActor(hl_, renderer_); + hl_ = {}; + geom_actor_ = std::move(geom_actor); - filter_ = nullptr; - hl_actor_ = nullptr; auto op = geom_actor_.lock(); if (op) { - filter_ = op->highlightFilter(SelectMode::Vertex); - hl_actor_ = op->highlightActor(SelectMode::Vertex); + hl_ = op->buildHighlight(SelectMode::Vertex); + if (renderer_ && hl_.actor) + renderer_->AddActor(hl_.actor); op->configurePicker(picker_, SelectMode::Vertex); } } @@ -249,18 +276,22 @@ GeometrySolidSelectorHighlight::GeometrySolidSelectorHighlight(vtkRenderer* rend { } -GeometrySolidSelectorHighlight::~GeometrySolidSelectorHighlight() { clear(); } +GeometrySolidSelectorHighlight::~GeometrySolidSelectorHighlight() +{ + clear(); + removeHighlightActor(hl_, renderer_); +} void GeometrySolidSelectorHighlight::clear() { selections_.clear(); highlighted_face_ids_.clear(); - if (filter_) { - filter_->Clear(); - filter_->Modified(); + if (hl_.filter) { + hl_.filter->Clear(); + hl_.filter->Modified(); } - if (hl_actor_) - hl_actor_->SetVisibility(false); + if (hl_.actor) + hl_.actor->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -301,9 +332,9 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) for (const auto& fid : highlighted_face_ids_) ids.Append(fid); - if (filter_) - filter_->SetData(ids); - flushHighlight(filter_, hl_actor_, !ids.IsEmpty(), renderer_); + if (hl_.filter) + hl_.filter->SetData(ids); + flushHighlight(hl_.filter, hl_.actor, !ids.IsEmpty(), renderer_); } void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) @@ -312,14 +343,16 @@ void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactor oldOp->disablePickerModes(picker_); clear(); + removeHighlightActor(hl_, renderer_); + hl_ = {}; + geom_actor_ = std::move(geom_actor); - filter_ = nullptr; - hl_actor_ = nullptr; auto op = geom_actor_.lock(); if (op) { - filter_ = op->highlightFilter(SelectMode::Solid); - hl_actor_ = op->highlightActor(SelectMode::Solid); + hl_ = op->buildHighlight(SelectMode::Solid); + if (renderer_ && hl_.actor) + renderer_->AddActor(hl_.actor); op->configurePicker(picker_, SelectMode::Solid); } } diff --git a/app/render/GeometrySelectorHighlight.h b/app/render/GeometrySelectorHighlight.h index 32a5de2..3d491da 100644 --- a/app/render/GeometrySelectorHighlight.h +++ b/app/render/GeometrySelectorHighlight.h @@ -41,8 +41,7 @@ public: private: vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - IVtkTools_SubPolyDataFilter* filter_ { nullptr }; - vtkActor* hl_actor_ { nullptr }; + GeometryHighlightPipeline hl_; std::unordered_map selections_; }; @@ -59,8 +58,7 @@ public: private: vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - IVtkTools_SubPolyDataFilter* filter_ { nullptr }; - vtkActor* hl_actor_ { nullptr }; + GeometryHighlightPipeline hl_; std::unordered_map selections_; }; @@ -77,8 +75,7 @@ public: private: vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - IVtkTools_SubPolyDataFilter* filter_ { nullptr }; - vtkActor* hl_actor_ { nullptr }; + GeometryHighlightPipeline hl_; std::unordered_map selections_; }; @@ -95,8 +92,7 @@ public: private: vtkRenderer* renderer_; GeometryActorSelectOpFactory geom_actor_; - IVtkTools_SubPolyDataFilter* filter_ { nullptr }; - vtkActor* hl_actor_ { nullptr }; + GeometryHighlightPipeline hl_; std::unordered_map selections_; std::unordered_set highlighted_face_ids_; -- Gitee From 7867d89b3deee1d13b8ed4279a0402c03443c2d8 Mon Sep 17 00:00:00 2001 From: hypf Date: Fri, 10 Jul 2026 20:48:19 +0800 Subject: [PATCH 11/13] =?UTF-8?q?refactor(app)=EF=BC=9A=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E5=87=A0=E4=BD=95=20SelectMode=20/=20ElementEnum=20=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=EF=BC=8C=E5=B9=B6=E5=B0=86SetClick=20=E6=94=B9?= =?UTF-8?q?=E5=9B=9E=20setClick()=EF=BC=88=E7=BA=BF=E7=A8=8B=E5=AE=89?= =?UTF-8?q?=E5=85=A8=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/render/GeometrySelectManager.cpp | 25 ++++++++--------- app/render/MeshSelectManager.cpp | 1 - app/render/QRenderWindow.cpp | 3 +- app/render/SelectManager.cpp | 41 +++++++++++----------------- core/Core.h | 6 +++- core/Selection.h | 6 +++- 6 files changed, 39 insertions(+), 43 deletions(-) diff --git a/app/render/GeometrySelectManager.cpp b/app/render/GeometrySelectManager.cpp index c9c6cf9..a31fd70 100644 --- a/app/render/GeometrySelectManager.cpp +++ b/app/render/GeometrySelectManager.cpp @@ -41,16 +41,15 @@ void GeometrySelectManager::setSelectMode(SelectMode select_mode) this->selector_->setCurGeomActor(GeometryActorSelectOpFactory {}); } - if (this->select_mode_ == SelectMode::Vertex) { + if (this->select_mode_ == SelectMode::GeometryVertex) { this->selector_ = std::make_unique(this->renderer_); - } else if (this->select_mode_ == SelectMode::Face) { + } else if (this->select_mode_ == SelectMode::GeometryFace) { this->selector_ = std::make_unique(this->renderer_); - } else if (this->select_mode_ == SelectMode::Edge) { + } else if (this->select_mode_ == SelectMode::GeometryEdge) { this->selector_ = std::make_unique(this->renderer_); - } else if (this->select_mode_ == SelectMode::Solid) { + } else if (this->select_mode_ == SelectMode::GeometrySolid) { this->selector_ = std::make_unique(this->renderer_); } else { - assert(this->select_mode_ == SelectMode::None); this->selector_ = nullptr; } @@ -78,26 +77,26 @@ std::unique_ptr GeometrySelectManager::getSelection() return nullptr; } - if (this->select_mode_ == SelectMode::Vertex) { + if (this->select_mode_ == SelectMode::GeometryVertex) { for (const auto& id : this->selector_->get().ids) { selection->ids.push_back(id); } - selection->type = ElementEnum::Vertex; - } else if (this->select_mode_ == SelectMode::Face) { + selection->type = ElementEnum::GeometryVertex; + } else if (this->select_mode_ == SelectMode::GeometryFace) { for (const auto& id : this->selector_->get().ids) { selection->ids.push_back(id); } - selection->type = ElementEnum::Face; - } else if (this->select_mode_ == SelectMode::Edge) { + selection->type = ElementEnum::GeometryFace; + } else if (this->select_mode_ == SelectMode::GeometryEdge) { for (const auto& id : this->selector_->get().ids) { selection->ids.push_back(id); } - selection->type = ElementEnum::Edge; - } else if (this->select_mode_ == SelectMode::Solid) { + selection->type = ElementEnum::GeometryEdge; + } else if (this->select_mode_ == SelectMode::GeometrySolid) { for (const auto& id : this->selector_->get().ids) { selection->ids.push_back(id); } - selection->type = ElementEnum::Solid; + selection->type = ElementEnum::GeometrySolid; } else { if (this->selector_) this->selector_->clear(); diff --git a/app/render/MeshSelectManager.cpp b/app/render/MeshSelectManager.cpp index 6bfcecf..37d2aa8 100644 --- a/app/render/MeshSelectManager.cpp +++ b/app/render/MeshSelectManager.cpp @@ -43,7 +43,6 @@ void MeshSelectManager::setSelectMode(SelectMode select_mode) } else if (this->select_mode_ == SelectMode::Solid) { this->selector_ = std::make_unique(this->renderer_); } else { - assert(this->select_mode_ == SelectMode::None); this->selector_ = nullptr; } diff --git a/app/render/QRenderWindow.cpp b/app/render/QRenderWindow.cpp index 83db30f..cca2965 100644 --- a/app/render/QRenderWindow.cpp +++ b/app/render/QRenderWindow.cpp @@ -123,8 +123,7 @@ bool QRenderWindow::event(QEvent* ev) if (!_click) return QQuickVTKItem::event(ev); - if (data_) - data_->style_->SetClick(); + setClick(); auto e = static_cast(ev); emit clicked(); return QQuickVTKItem::event(ev); diff --git a/app/render/SelectManager.cpp b/app/render/SelectManager.cpp index 676de55..a1f2db2 100644 --- a/app/render/SelectManager.cpp +++ b/app/render/SelectManager.cpp @@ -36,37 +36,29 @@ void SelectManager::setSelectActor(std::weak_ptr geom_actor) void SelectManager::setSelectMode(const std::string& select_mode) { + SelectMode mode = SelectMode::None; if (select_mode == "Vertex") { - mesh_->setSelectMode(SelectMode::Vertex); - geom_->setSelectMode(SelectMode::None); + mode = SelectMode::Vertex; } else if (select_mode == "Face") { - mesh_->setSelectMode(SelectMode::Face); - geom_->setSelectMode(SelectMode::None); + mode = SelectMode::Face; } else if (select_mode == "Edge") { - mesh_->setSelectMode(SelectMode::Edge); - geom_->setSelectMode(SelectMode::None); + mode = SelectMode::Edge; } else if (select_mode == "Block") { - mesh_->setSelectMode(SelectMode::Block); - geom_->setSelectMode(SelectMode::None); + mode = SelectMode::Block; } else if (select_mode == "Solid") { - mesh_->setSelectMode(SelectMode::Solid); - geom_->setSelectMode(SelectMode::None); - } else if (select_mode == "GeometryFace") { - mesh_->setSelectMode(SelectMode::None); - geom_->setSelectMode(SelectMode::Face); - } else if (select_mode == "GeometryEdge") { - mesh_->setSelectMode(SelectMode::None); - geom_->setSelectMode(SelectMode::Edge); + mode = SelectMode::Solid; } else if (select_mode == "GeometryVertex") { - mesh_->setSelectMode(SelectMode::None); - geom_->setSelectMode(SelectMode::Vertex); + mode = SelectMode::GeometryVertex; + } else if (select_mode == "GeometryEdge") { + mode = SelectMode::GeometryEdge; + } else if (select_mode == "GeometryFace") { + mode = SelectMode::GeometryFace; } else if (select_mode == "GeometrySolid") { - mesh_->setSelectMode(SelectMode::None); - geom_->setSelectMode(SelectMode::Solid); - } else { - mesh_->setSelectMode(SelectMode::None); - geom_->setSelectMode(SelectMode::None); + mode = SelectMode::GeometrySolid; } + + mesh_->setSelectMode(mode); + geom_->setSelectMode(mode); } void SelectManager::clearSelection() @@ -77,8 +69,7 @@ void SelectManager::clearSelection() std::unique_ptr SelectManager::getSelection() { - auto geom_selection = geom_->getSelection(); - if (geom_selection) { + if (auto geom_selection = geom_->getSelection()) { return geom_selection; } return mesh_->getSelection(); diff --git a/core/Core.h b/core/Core.h index 8328c25..45aa21a 100644 --- a/core/Core.h +++ b/core/Core.h @@ -23,7 +23,11 @@ enum class SelectMode { Face, Edge, Solid, - Block + Block, + GeometryVertex, + GeometryEdge, + GeometryFace, + GeometrySolid }; /** diff --git a/core/Selection.h b/core/Selection.h index 1d19aef..ae6a674 100644 --- a/core/Selection.h +++ b/core/Selection.h @@ -13,7 +13,11 @@ public: Edge, Vertex, Block, - Group + Group, + GeometrySolid, + GeometryFace, + GeometryEdge, + GeometryVertex }; }; -- Gitee From 47071f9f76cf44d41700aec604061c9359568c93 Mon Sep 17 00:00:00 2001 From: hypf Date: Sat, 11 Jul 2026 13:51:55 +0800 Subject: [PATCH 12/13] =?UTF-8?q?refactor(app)=EF=BC=9A=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=85=B1=E7=94=A8=E5=90=8C=E4=B8=80=E4=B8=AA?= =?UTF-8?q?vtkActor=E5=81=9A=E9=80=89=E6=8B=A9=E5=8F=AF=E8=A7=86=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/render/EdgeSelectorHighlight.cpp | 26 +++-- app/render/FaceSelectorHighlight.cpp | 34 +++--- app/render/GeometryActor.cpp | 3 - app/render/GeometryActorSelectOp.cpp | 12 -- app/render/GeometryActorSelectOp.h | 1 - app/render/GeometrySelectManager.cpp | 11 +- app/render/GeometrySelectManager.h | 3 +- app/render/GeometrySelectorHighlight.cpp | 109 ++++++++++-------- app/render/GeometrySelectorHighlight.h | 12 +- app/render/MeshSelectManager.cpp | 11 +- app/render/MeshSelectManager.h | 3 +- app/render/SelectManager.cpp | 20 +++- app/render/SelectManager.h | 5 + app/render/SelectorHighlight.h | 18 +-- app/render/SolidSelectorHighlight.cpp | 34 ++++-- app/render/VertexSelectorHighlight.cpp | 30 +++-- app/render/test/TestEdgeSelectorHighlight.cpp | 6 +- app/render/test/TestFaceSelectorHighlight.cpp | 6 +- app/render/test/TestGeometryShapePicker.cpp | 21 ++-- .../test/TestSolidSelectorHighlight.cpp | 5 +- .../test/TestVertexSelectorHighlight.cpp | 6 +- 21 files changed, 225 insertions(+), 151 deletions(-) diff --git a/app/render/EdgeSelectorHighlight.cpp b/app/render/EdgeSelectorHighlight.cpp index 7ad885e..10babc3 100644 --- a/app/render/EdgeSelectorHighlight.cpp +++ b/app/render/EdgeSelectorHighlight.cpp @@ -53,28 +53,34 @@ bool _is_selected(std::array v_local_id, const std::optionalselected_actor_ = vtkSmartPointer::New(); + this->highlight_actor_ = highlight_actor; this->renderer_ = renderer; selected_mapper_->SetInputData(vtkPolyData::New()); - selected_actor_->SetMapper(selected_mapper_); - selected_actor_->GetProperty()->SetColor(MeshActor::colors->GetColor3d("red").GetData()); - selected_actor_->GetProperty()->SetLineWidth(5); - renderer_->AddActor(selected_actor_); + if (highlight_actor_) { + highlight_actor_->SetMapper(selected_mapper_); + vtkNew prop; + prop->SetColor(MeshActor::colors->GetColor3d("red").GetData()); + prop->SetLineWidth(5); + highlight_actor_->SetProperty(prop); + highlight_actor_->SetVisibility(false); + } } -EdgeSelectorHighlight::~EdgeSelectorHighlight() -{ - renderer_->RemoveActor(selected_actor_); +EdgeSelectorHighlight::~EdgeSelectorHighlight() +{ + clear(); } void EdgeSelectorHighlight::clear() { _cancel_highlight(selected_mapper_); selections_.clear(); + if (highlight_actor_) + highlight_actor_->SetVisibility(false); } SelectionVtk EdgeSelectorHighlight::get() @@ -136,6 +142,8 @@ void EdgeSelectorHighlight::select(double posx, double posy) auto edge_poly_data = model_actor->extractEdge(selections_); // 设置PolyData到mapper selected_mapper_->SetInputData(edge_poly_data); + if (highlight_actor_) + highlight_actor_->SetVisibility(!selections_.empty()); } else { // 没选到 clear(); diff --git a/app/render/FaceSelectorHighlight.cpp b/app/render/FaceSelectorHighlight.cpp index f21e230..62a05cb 100644 --- a/app/render/FaceSelectorHighlight.cpp +++ b/app/render/FaceSelectorHighlight.cpp @@ -25,25 +25,29 @@ std::vector::const_iterator _find_selected(vtkIdType new_face_id, con } } -FaceSelectorHighlight::FaceSelectorHighlight(vtkRenderer* renderer) +FaceSelectorHighlight::FaceSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor) { - this->selected_actor_ = vtkSmartPointer::New(); + this->highlight_actor_ = highlight_actor; this->renderer_ = renderer; selected_mapper_->SetInputData(vtkPolyData::New()); - selected_actor_->SetMapper(selected_mapper_); - selected_actor_->GetProperty()->SetColor(1.0, 0.0, 0.0); // 红色高亮 - selected_actor_->GetProperty()->SetLineWidth(2.0); - selected_actor_->GetProperty()->EdgeVisibilityOn(); - selected_actor_->GetProperty()->SetEdgeColor(1.0, 0.0, 0.0); - selected_actor_->PickableOff(); // 防止自己被选中 - - renderer_->AddActor(selected_actor_); + selected_mapper_->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, -0.5); + + if (highlight_actor_) { + highlight_actor_->SetMapper(selected_mapper_); + vtkNew prop; + prop->SetColor(1.0, 0.0, 0.0); // 红色高亮 + prop->SetLineWidth(2.0); + prop->EdgeVisibilityOn(); + prop->SetEdgeColor(1.0, 0.0, 0.0); + highlight_actor_->SetProperty(prop); + highlight_actor_->SetVisibility(false); + } } -FaceSelectorHighlight::~FaceSelectorHighlight() -{ - renderer_->RemoveActor(selected_actor_); +FaceSelectorHighlight::~FaceSelectorHighlight() +{ + clear(); } SelectionVtk FaceSelectorHighlight::get() @@ -62,6 +66,8 @@ void FaceSelectorHighlight::clear() { _cancel_highlight(selected_mapper_); selections_.clear(); + if (highlight_actor_) + highlight_actor_->SetVisibility(false); } void FaceSelectorHighlight::select(double posx, double posy) @@ -106,6 +112,8 @@ void FaceSelectorHighlight::select(double posx, double posy) highlight_poly->SetPolys(cell_array); // 设置面单元 selected_mapper_->SetInputData(highlight_poly); // 触发高亮演员更新渲染 + if (highlight_actor_) + highlight_actor_->SetVisibility(!selections_.empty()); } else { // 没选到 clear(); diff --git a/app/render/GeometryActor.cpp b/app/render/GeometryActor.cpp index 3242d54..1abad75 100644 --- a/app/render/GeometryActor.cpp +++ b/app/render/GeometryActor.cpp @@ -120,9 +120,6 @@ bool GeometryActor::getIsEdgeRender() void GeometryActor::loadShape(const GeometryDataVtk& geometry_data) { - // 全局:开一次 - vtkMapper::SetResolveCoincidentTopologyToPolygonOffset(); - OccShapeHandle aShapeImpl = new IVtkOCC_Shape(geometry_data.shape); aShapeImpl->SetId(static_cast(geometry_data.component_id)); this->occ_shape_ = aShapeImpl; diff --git a/app/render/GeometryActorSelectOp.cpp b/app/render/GeometryActorSelectOp.cpp index c95cd5d..e223e4a 100644 --- a/app/render/GeometryActorSelectOp.cpp +++ b/app/render/GeometryActorSelectOp.cpp @@ -304,25 +304,13 @@ GeometryHighlightPipeline GeometryActorSelectOp::buildHighlight(SelectMode mode) hl.mapper = vtkSmartPointer::New(); hl.mapper->SetInputConnection(hl.filter->GetOutputPort()); - hl.actor = vtkSmartPointer::New(); - hl.actor->SetMapper(hl.mapper); - hl.actor->GetProperty()->SetColor(1.0, 0.0, 0.0); - hl.actor->SetVisibility(false); - hl.actor->PickableOff(); - if (useLine) { // 相对显示 mapper 默认值:线 (0,-5),点 (-10) hl.mapper->SetRelativeCoincidentTopologyLineOffsetParameters(0, -1); hl.mapper->SetRelativeCoincidentTopologyPointOffsetParameter(-2); - hl.actor->GetProperty()->SetOpacity(0.5); - hl.actor->GetProperty()->RenderLinesAsTubesOn(); - hl.actor->GetProperty()->SetLineWidth(3.0); - hl.actor->GetProperty()->SetPointSize(8.0); - hl.actor->GetProperty()->LightingOff(); } else { // 相对显示 mapper 默认值:多边形 (0,-1) hl.mapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, -0.5); - hl.actor->GetProperty()->SetOpacity(1); } return hl; diff --git a/app/render/GeometryActorSelectOp.h b/app/render/GeometryActorSelectOp.h index 8353f0d..b204b99 100644 --- a/app/render/GeometryActorSelectOp.h +++ b/app/render/GeometryActorSelectOp.h @@ -20,7 +20,6 @@ class vtkRenderer; struct GeometryHighlightPipeline { vtkSmartPointer filter; vtkSmartPointer mapper; - vtkSmartPointer actor; }; class GeometryActorSelectOpFactory { diff --git a/app/render/GeometrySelectManager.cpp b/app/render/GeometrySelectManager.cpp index a31fd70..a7d13e0 100644 --- a/app/render/GeometrySelectManager.cpp +++ b/app/render/GeometrySelectManager.cpp @@ -4,9 +4,10 @@ #include #include -void GeometrySelectManager::bindRenderer(vtkRenderer* renderer) +void GeometrySelectManager::bindRenderer(vtkRenderer* renderer, vtkActor* highlight_actor) { this->renderer_ = renderer; + this->highlight_actor_ = highlight_actor; if (!picker_) { picker_ = vtkSmartPointer::New(); picker_->SetRenderer(renderer); @@ -42,13 +43,13 @@ void GeometrySelectManager::setSelectMode(SelectMode select_mode) } if (this->select_mode_ == SelectMode::GeometryVertex) { - this->selector_ = std::make_unique(this->renderer_); + this->selector_ = std::make_unique(this->renderer_, this->highlight_actor_); } else if (this->select_mode_ == SelectMode::GeometryFace) { - this->selector_ = std::make_unique(this->renderer_); + this->selector_ = std::make_unique(this->renderer_, this->highlight_actor_); } else if (this->select_mode_ == SelectMode::GeometryEdge) { - this->selector_ = std::make_unique(this->renderer_); + this->selector_ = std::make_unique(this->renderer_, this->highlight_actor_); } else if (this->select_mode_ == SelectMode::GeometrySolid) { - this->selector_ = std::make_unique(this->renderer_); + this->selector_ = std::make_unique(this->renderer_, this->highlight_actor_); } else { this->selector_ = nullptr; } diff --git a/app/render/GeometrySelectManager.h b/app/render/GeometrySelectManager.h index 5f4a6a2..f18a80a 100644 --- a/app/render/GeometrySelectManager.h +++ b/app/render/GeometrySelectManager.h @@ -15,7 +15,7 @@ struct GeometrySubshapeIndex; class GeometrySelectManager { public: - void bindRenderer(vtkRenderer* renderer); + void bindRenderer(vtkRenderer* renderer, vtkActor* highlight_actor); void select(double posx, double posy); void setSelectActor(std::weak_ptr geom_actor); @@ -30,6 +30,7 @@ private: vtkNew selection_mapper_; vtkSmartPointer picker_ {}; vtkRenderer* renderer_ { nullptr }; + vtkActor* highlight_actor_ { nullptr }; std::unique_ptr selector_ {}; }; #endif // GEOMETRY_SELECT_MANAGER_H diff --git a/app/render/GeometrySelectorHighlight.cpp b/app/render/GeometrySelectorHighlight.cpp index 79a3630..d67eb04 100644 --- a/app/render/GeometrySelectorHighlight.cpp +++ b/app/render/GeometrySelectorHighlight.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -20,26 +21,40 @@ static void flushHighlight(IVtkTools_SubPolyDataFilter* filter, vtkActor* hlActo renderer->GetRenderWindow()->Render(); } -static void removeHighlightActor(GeometryHighlightPipeline& hl, vtkRenderer* renderer) +// 把共享高亮 actor 挂到当前 selector 的 mapper 上,并按模式套用完整样式(避免残留上一模式属性) +static void mountHighlight(vtkActor* actor, const GeometryHighlightPipeline& hl, SelectMode mode) { - if (hl.actor && renderer) { - renderer->RemoveActor(hl.actor); - if (renderer->GetRenderWindow()) - renderer->GetRenderWindow()->Render(); + if (!actor || !hl.mapper) + return; + + actor->SetMapper(hl.mapper); + + vtkNew prop; + prop->SetColor(1.0, 0.0, 0.0); + if (mode == SelectMode::Edge || mode == SelectMode::Vertex) { + prop->SetOpacity(0.5); + prop->RenderLinesAsTubesOn(); + prop->SetLineWidth(3.0); + prop->SetPointSize(8.0); + prop->LightingOff(); + } else { + prop->SetOpacity(1.0); } + actor->SetProperty(prop); + actor->SetVisibility(false); } // ─── Face ────────────────────────────────────────────── -GeometryFaceSelectorHighlight::GeometryFaceSelectorHighlight(vtkRenderer* renderer) +GeometryFaceSelectorHighlight::GeometryFaceSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor) : renderer_(renderer) + , highlight_actor_(highlight_actor) { } -GeometryFaceSelectorHighlight::~GeometryFaceSelectorHighlight() -{ - clear(); - removeHighlightActor(hl_, renderer_); +GeometryFaceSelectorHighlight::~GeometryFaceSelectorHighlight() +{ + clear(); } void GeometryFaceSelectorHighlight::clear() @@ -49,8 +64,8 @@ void GeometryFaceSelectorHighlight::clear() hl_.filter->Clear(); hl_.filter->Modified(); } - if (hl_.actor) - hl_.actor->SetVisibility(false); + if (highlight_actor_) + highlight_actor_->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -58,7 +73,7 @@ void GeometryFaceSelectorHighlight::clear() GeometrySelectionVtk GeometryFaceSelectorHighlight::get() const { GeometrySelectionVtk s; - s.type = ElementEnum::Face; + s.type = ElementEnum::GeometryFace; s.component_id = -1; for (const auto& [subId, geomId] : selections_) s.ids.push_back(geomId); @@ -86,7 +101,7 @@ void GeometryFaceSelectorHighlight::select(double posx, double posy) if (hl_.filter) hl_.filter->SetData(ids); - flushHighlight(hl_.filter, hl_.actor, !ids.IsEmpty(), renderer_); + flushHighlight(hl_.filter, highlight_actor_, !ids.IsEmpty(), renderer_); } void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) @@ -95,7 +110,6 @@ void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory oldOp->disablePickerModes(picker_); clear(); - removeHighlightActor(hl_, renderer_); hl_ = {}; geom_actor_ = std::move(geom_actor); @@ -103,23 +117,22 @@ void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory auto op = geom_actor_.lock(); if (op) { hl_ = op->buildHighlight(SelectMode::Face); - if (renderer_ && hl_.actor) - renderer_->AddActor(hl_.actor); + mountHighlight(highlight_actor_, hl_, SelectMode::Face); op->configurePicker(picker_, SelectMode::Face); } } // ─── Edge ────────────────────────────────────────────── -GeometryEdgeSelectorHighlight::GeometryEdgeSelectorHighlight(vtkRenderer* renderer) +GeometryEdgeSelectorHighlight::GeometryEdgeSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor) : renderer_(renderer) + , highlight_actor_(highlight_actor) { } -GeometryEdgeSelectorHighlight::~GeometryEdgeSelectorHighlight() -{ +GeometryEdgeSelectorHighlight::~GeometryEdgeSelectorHighlight() +{ clear(); - removeHighlightActor(hl_, renderer_); } void GeometryEdgeSelectorHighlight::clear() @@ -129,8 +142,8 @@ void GeometryEdgeSelectorHighlight::clear() hl_.filter->Clear(); hl_.filter->Modified(); } - if (hl_.actor) - hl_.actor->SetVisibility(false); + if (highlight_actor_) + highlight_actor_->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -138,7 +151,7 @@ void GeometryEdgeSelectorHighlight::clear() GeometrySelectionVtk GeometryEdgeSelectorHighlight::get() const { GeometrySelectionVtk s; - s.type = ElementEnum::Edge; + s.type = ElementEnum::GeometryEdge; s.component_id = -1; for (const auto& [subId, geomId] : selections_) s.ids.push_back(geomId); @@ -166,7 +179,7 @@ void GeometryEdgeSelectorHighlight::select(double posx, double posy) if (hl_.filter) hl_.filter->SetData(ids); - flushHighlight(hl_.filter, hl_.actor, !ids.IsEmpty(), renderer_); + flushHighlight(hl_.filter, highlight_actor_, !ids.IsEmpty(), renderer_); } void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) @@ -175,7 +188,6 @@ void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory oldOp->disablePickerModes(picker_); clear(); - removeHighlightActor(hl_, renderer_); hl_ = {}; geom_actor_ = std::move(geom_actor); @@ -183,23 +195,22 @@ void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory auto op = geom_actor_.lock(); if (op) { hl_ = op->buildHighlight(SelectMode::Edge); - if (renderer_ && hl_.actor) - renderer_->AddActor(hl_.actor); + mountHighlight(highlight_actor_, hl_, SelectMode::Edge); op->configurePicker(picker_, SelectMode::Edge); } } // ─── Vertex ──────────────────────────────────────────── -GeometryVertexSelectorHighlight::GeometryVertexSelectorHighlight(vtkRenderer* renderer) +GeometryVertexSelectorHighlight::GeometryVertexSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor) : renderer_(renderer) + , highlight_actor_(highlight_actor) { } -GeometryVertexSelectorHighlight::~GeometryVertexSelectorHighlight() -{ +GeometryVertexSelectorHighlight::~GeometryVertexSelectorHighlight() +{ clear(); - removeHighlightActor(hl_, renderer_); } void GeometryVertexSelectorHighlight::clear() @@ -209,8 +220,8 @@ void GeometryVertexSelectorHighlight::clear() hl_.filter->Clear(); hl_.filter->Modified(); } - if (hl_.actor) - hl_.actor->SetVisibility(false); + if (highlight_actor_) + highlight_actor_->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -218,7 +229,7 @@ void GeometryVertexSelectorHighlight::clear() GeometrySelectionVtk GeometryVertexSelectorHighlight::get() const { GeometrySelectionVtk s; - s.type = ElementEnum::Vertex; + s.type = ElementEnum::GeometryVertex; s.component_id = -1; for (const auto& [subId, geomId] : selections_) s.ids.push_back(geomId); @@ -246,7 +257,7 @@ void GeometryVertexSelectorHighlight::select(double posx, double posy) if (hl_.filter) hl_.filter->SetData(ids); - flushHighlight(hl_.filter, hl_.actor, !ids.IsEmpty(), renderer_); + flushHighlight(hl_.filter, highlight_actor_, !ids.IsEmpty(), renderer_); } void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) @@ -255,7 +266,6 @@ void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFacto oldOp->disablePickerModes(picker_); clear(); - removeHighlightActor(hl_, renderer_); hl_ = {}; geom_actor_ = std::move(geom_actor); @@ -263,23 +273,22 @@ void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFacto auto op = geom_actor_.lock(); if (op) { hl_ = op->buildHighlight(SelectMode::Vertex); - if (renderer_ && hl_.actor) - renderer_->AddActor(hl_.actor); + mountHighlight(highlight_actor_, hl_, SelectMode::Vertex); op->configurePicker(picker_, SelectMode::Vertex); } } // ─── Solid ───────────────────────────────────────────── -GeometrySolidSelectorHighlight::GeometrySolidSelectorHighlight(vtkRenderer* renderer) +GeometrySolidSelectorHighlight::GeometrySolidSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor) : renderer_(renderer) + , highlight_actor_(highlight_actor) { } -GeometrySolidSelectorHighlight::~GeometrySolidSelectorHighlight() -{ - clear(); - removeHighlightActor(hl_, renderer_); +GeometrySolidSelectorHighlight::~GeometrySolidSelectorHighlight() +{ + clear(); } void GeometrySolidSelectorHighlight::clear() @@ -290,8 +299,8 @@ void GeometrySolidSelectorHighlight::clear() hl_.filter->Clear(); hl_.filter->Modified(); } - if (hl_.actor) - hl_.actor->SetVisibility(false); + if (highlight_actor_) + highlight_actor_->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -299,7 +308,7 @@ void GeometrySolidSelectorHighlight::clear() GeometrySelectionVtk GeometrySolidSelectorHighlight::get() const { GeometrySelectionVtk s; - s.type = ElementEnum::Solid; + s.type = ElementEnum::GeometrySolid; s.component_id = -1; for (const auto& [subId, geomId] : selections_) s.ids.push_back(geomId); @@ -334,7 +343,7 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) if (hl_.filter) hl_.filter->SetData(ids); - flushHighlight(hl_.filter, hl_.actor, !ids.IsEmpty(), renderer_); + flushHighlight(hl_.filter, highlight_actor_, !ids.IsEmpty(), renderer_); } void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) @@ -343,7 +352,6 @@ void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactor oldOp->disablePickerModes(picker_); clear(); - removeHighlightActor(hl_, renderer_); hl_ = {}; geom_actor_ = std::move(geom_actor); @@ -351,8 +359,7 @@ void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactor auto op = geom_actor_.lock(); if (op) { hl_ = op->buildHighlight(SelectMode::Solid); - if (renderer_ && hl_.actor) - renderer_->AddActor(hl_.actor); + mountHighlight(highlight_actor_, hl_, SelectMode::Solid); op->configurePicker(picker_, SelectMode::Solid); } } diff --git a/app/render/GeometrySelectorHighlight.h b/app/render/GeometrySelectorHighlight.h index 3d491da..ba0c86a 100644 --- a/app/render/GeometrySelectorHighlight.h +++ b/app/render/GeometrySelectorHighlight.h @@ -31,7 +31,7 @@ protected: class GeometryFaceSelectorHighlight final : public GeometrySelectorHighlight { public: - GeometryFaceSelectorHighlight(vtkRenderer* renderer); + GeometryFaceSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor); ~GeometryFaceSelectorHighlight() override; void clear() override; GeometrySelectionVtk get() const override; @@ -40,6 +40,7 @@ public: private: vtkRenderer* renderer_; + vtkActor* highlight_actor_ {}; GeometryActorSelectOpFactory geom_actor_; GeometryHighlightPipeline hl_; @@ -48,7 +49,7 @@ private: class GeometryEdgeSelectorHighlight final : public GeometrySelectorHighlight { public: - GeometryEdgeSelectorHighlight(vtkRenderer* renderer); + GeometryEdgeSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor); ~GeometryEdgeSelectorHighlight() override; void clear() override; GeometrySelectionVtk get() const override; @@ -57,6 +58,7 @@ public: private: vtkRenderer* renderer_; + vtkActor* highlight_actor_ {}; GeometryActorSelectOpFactory geom_actor_; GeometryHighlightPipeline hl_; @@ -65,7 +67,7 @@ private: class GeometryVertexSelectorHighlight final : public GeometrySelectorHighlight { public: - GeometryVertexSelectorHighlight(vtkRenderer* renderer); + GeometryVertexSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor); ~GeometryVertexSelectorHighlight() override; void clear() override; GeometrySelectionVtk get() const override; @@ -74,6 +76,7 @@ public: private: vtkRenderer* renderer_; + vtkActor* highlight_actor_ {}; GeometryActorSelectOpFactory geom_actor_; GeometryHighlightPipeline hl_; @@ -82,7 +85,7 @@ private: class GeometrySolidSelectorHighlight final : public GeometrySelectorHighlight { public: - GeometrySolidSelectorHighlight(vtkRenderer* renderer); + GeometrySolidSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor); ~GeometrySolidSelectorHighlight() override; void clear() override; GeometrySelectionVtk get() const override; @@ -91,6 +94,7 @@ public: private: vtkRenderer* renderer_; + vtkActor* highlight_actor_ {}; GeometryActorSelectOpFactory geom_actor_; GeometryHighlightPipeline hl_; diff --git a/app/render/MeshSelectManager.cpp b/app/render/MeshSelectManager.cpp index 37d2aa8..99ed50c 100644 --- a/app/render/MeshSelectManager.cpp +++ b/app/render/MeshSelectManager.cpp @@ -7,9 +7,10 @@ #include #include -void MeshSelectManager::bindRenderer(vtkRenderer* renderer) +void MeshSelectManager::bindRenderer(vtkRenderer* renderer, vtkActor* highlight_actor) { this->renderer_ = renderer; + this->highlight_actor_ = highlight_actor; } void MeshSelectManager::select(double posx, double posy) @@ -33,15 +34,15 @@ void MeshSelectManager::setSelectMode(SelectMode select_mode) { this->select_mode_ = select_mode; if (this->select_mode_ == SelectMode::Vertex) { - this->selector_ = std::make_unique(this->renderer_); + this->selector_ = std::make_unique(this->renderer_, this->highlight_actor_); } else if (this->select_mode_ == SelectMode::Face) { - this->selector_ = std::make_unique(this->renderer_); + this->selector_ = std::make_unique(this->renderer_, this->highlight_actor_); } else if (this->select_mode_ == SelectMode::Block) { this->selector_ = std::make_unique(this->renderer_); } else if (this->select_mode_ == SelectMode::Edge) { - this->selector_ = std::make_unique(this->renderer_); + this->selector_ = std::make_unique(this->renderer_, this->highlight_actor_); } else if (this->select_mode_ == SelectMode::Solid) { - this->selector_ = std::make_unique(this->renderer_); + this->selector_ = std::make_unique(this->renderer_, this->highlight_actor_); } else { this->selector_ = nullptr; } diff --git a/app/render/MeshSelectManager.h b/app/render/MeshSelectManager.h index ccf17a2..3682aff 100644 --- a/app/render/MeshSelectManager.h +++ b/app/render/MeshSelectManager.h @@ -13,7 +13,7 @@ class MeshSelectManager { public: - void bindRenderer(vtkRenderer* renderer); + void bindRenderer(vtkRenderer* renderer, vtkActor* highlight_actor); void select(double posx, double posy); void setSelectActor(std::weak_ptr model_actor_); void setSelectMode(SelectMode select_mode); @@ -26,6 +26,7 @@ private: vtkNew selection_actor_; vtkNew selection_mapper_; vtkRenderer* renderer_; + vtkActor* highlight_actor_ {}; std::unique_ptr selector_; }; #endif diff --git a/app/render/SelectManager.cpp b/app/render/SelectManager.cpp index a1f2db2..6ba9014 100644 --- a/app/render/SelectManager.cpp +++ b/app/render/SelectManager.cpp @@ -4,18 +4,30 @@ #include "GeometryActor.h" #include "MeshActor.h" +#include +#include +#include + SelectManager::SelectManager() : mesh_(std::make_unique()) , geom_(std::make_unique()) { + // 共享 actor 始终持有一个空 mapper(None 或未激活时的兜底,避免空 mapper / 残留旧数据) + vtkNew empty; + empty_mapper_->SetInputData(empty); + highlight_actor_->SetMapper(empty_mapper_); + highlight_actor_->PickableOff(); + highlight_actor_->SetVisibility(false); } SelectManager::~SelectManager() = default; void SelectManager::bindRenderer(vtkRenderer* renderer) { - mesh_->bindRenderer(renderer); - geom_->bindRenderer(renderer); + if (renderer) + renderer->AddActor(highlight_actor_); + mesh_->bindRenderer(renderer, highlight_actor_); + geom_->bindRenderer(renderer, highlight_actor_); } void SelectManager::select(double posx, double posy) @@ -36,6 +48,10 @@ void SelectManager::setSelectActor(std::weak_ptr geom_actor) void SelectManager::setSelectMode(const std::string& select_mode) { + // 复位共享 actor:隐藏并挂回空 mapper;随后由激活的 selector 挂上自己的 mapper(None 则保持空) + highlight_actor_->SetVisibility(false); + highlight_actor_->SetMapper(empty_mapper_); + SelectMode mode = SelectMode::None; if (select_mode == "Vertex") { mode = SelectMode::Vertex; diff --git a/app/render/SelectManager.h b/app/render/SelectManager.h index 84b4880..00b5e9d 100644 --- a/app/render/SelectManager.h +++ b/app/render/SelectManager.h @@ -5,6 +5,9 @@ #include #include +#include +#include +#include class vtkRenderer; class MeshActor; @@ -30,5 +33,7 @@ public: private: std::unique_ptr mesh_; std::unique_ptr geom_; + vtkNew highlight_actor_; + vtkNew empty_mapper_; }; #endif \ No newline at end of file diff --git a/app/render/SelectorHighlight.h b/app/render/SelectorHighlight.h index 420dbfa..6e895bd 100644 --- a/app/render/SelectorHighlight.h +++ b/app/render/SelectorHighlight.h @@ -93,7 +93,7 @@ public: // int local_id; //}; //! @brief 将actor绑定到renderer,mapper绑定到actor - FaceSelectorHighlight(vtkRenderer* renderer); + FaceSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor); //! @brief 将actor从renderer中删除 ~FaceSelectorHighlight() override; //! @brief 返回当前选择的面 @@ -109,7 +109,7 @@ private: vtkRenderer* renderer_; std::vector selections_; vtkNew selected_mapper_; - vtkSmartPointer selected_actor_; + vtkActor* highlight_actor_ {}; vtkNew collection_; MeshActorSelectOpFactory model_actor_; }; @@ -117,7 +117,7 @@ private: class EdgeSelectorHighlight : public SelectorHighlight { public: //! @brief 将actor绑定到renderer,mapper绑定到actor - EdgeSelectorHighlight(vtkRenderer* renderer); + EdgeSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor); //! @brief 将actor从renderer中删除 ~EdgeSelectorHighlight() override; //! @brief 获取当前选择的边 @@ -138,7 +138,7 @@ private: vtkRenderer* renderer_; std::vector> selections_; vtkNew selected_mapper_; - vtkSmartPointer selected_actor_; + vtkActor* highlight_actor_ {}; vtkNew collection_; MeshActorSelectOpFactory model_actor_; }; @@ -146,7 +146,7 @@ private: class SolidSelectorHighlight : public SelectorHighlight { public: //! @brief 将actor绑定到renderer,mapper绑定到actor - SolidSelectorHighlight(vtkRenderer* renderer); + SolidSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor); //! @brief 将actor从renderer中删除 ~SolidSelectorHighlight() override; //! @brief 返回当前选择的体 @@ -160,7 +160,8 @@ public: private: vtkRenderer* renderer_; - vtkNew highlight_actor_; + vtkActor* highlight_actor_ {}; + vtkSmartPointer mapper_; MeshActorSelectOpFactory model_actor_; //> 当前操作的模型,可能为空 vtkNew selected_ids_; //> 存储选中的体id,绑定到了mapper,用于触发高亮体cell修改 }; @@ -171,7 +172,7 @@ private: class VertexSelectorHighlight : public SelectorHighlight { public: //! @brief 将actor绑定到renderer,mapper绑定到actor - VertexSelectorHighlight(vtkRenderer* renderer); + VertexSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor); //! @brief 将actor从renderer中删除 ~VertexSelectorHighlight() override; //! @brief 返回当前选择的点集 @@ -185,7 +186,8 @@ public: private: vtkRenderer* renderer_; - vtkNew highlight_actor_; + vtkActor* highlight_actor_ {}; + vtkSmartPointer mapper_; MeshActorSelectOpFactory model_actor_; //> 当前操作的模型,可能为空 vtkNew selected_ids_; //> 存储选中的点id,绑定到了mapper,用于触发高亮顶点修改 }; diff --git a/app/render/SolidSelectorHighlight.cpp b/app/render/SolidSelectorHighlight.cpp index 248851d..74fb54a 100644 --- a/app/render/SolidSelectorHighlight.cpp +++ b/app/render/SolidSelectorHighlight.cpp @@ -32,30 +32,34 @@ vtkIdType _is_selected(vtkIdType new_solid, const vtkIdTypeArray& selected_ids_) } } -SolidSelectorHighlight::SolidSelectorHighlight(vtkRenderer* renderer) +SolidSelectorHighlight::SolidSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor) : renderer_(renderer) + , highlight_actor_(highlight_actor) { this->selected_ids_->SetName("vtkOriginalCellIds"); this->selected_ids_->SetNumberOfComponents(1); this->selected_ids_->SetNumberOfValues(0); vtkNew dummy; - vtkNew mapper; - mapper->SetInputData(dummy); + this->mapper_ = vtkSmartPointer::New(); + this->mapper_->SetInputData(dummy); + this->mapper_->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, -0.5); - this->highlight_actor_->SetMapper(mapper); - this->highlight_actor_->GetProperty()->SetColor(1.0, 1.0, 0.0); // 黄色高亮 - this->highlight_actor_->GetProperty()->EdgeVisibilityOn(); - this->highlight_actor_->GetProperty()->SetEdgeColor(1.0, 0.0, 0.0); // 红色边框 - this->highlight_actor_->GetProperty()->SetLineWidth(2.0); - - renderer_->AddActor(this->highlight_actor_); + if (highlight_actor_) { + highlight_actor_->SetMapper(mapper_); + vtkNew prop; + prop->SetColor(1.0, 1.0, 0.0); // 黄色高亮 + prop->EdgeVisibilityOn(); + prop->SetEdgeColor(1.0, 0.0, 0.0); // 红色边框 + prop->SetLineWidth(2.0); + highlight_actor_->SetProperty(prop); + highlight_actor_->SetVisibility(false); + } } SolidSelectorHighlight::~SolidSelectorHighlight() { clear(); - renderer_->RemoveActor(this->highlight_actor_); } SelectionVtk SolidSelectorHighlight::get() @@ -71,6 +75,8 @@ SelectionVtk SolidSelectorHighlight::get() void SolidSelectorHighlight::clear() { _cancel_highlight(this->selected_ids_); + if (highlight_actor_) + highlight_actor_->SetVisibility(false); } void SolidSelectorHighlight::select(double posx, double posy) @@ -116,6 +122,8 @@ void SolidSelectorHighlight::select(double posx, double posy) spdlog::debug("SolidSelectorHighlight::select: point {} selected.", selected_solid_id); } this->selected_ids_->Modified(); // 触发highlight_actor_更新 + if (highlight_actor_) + highlight_actor_->SetVisibility(selected_ids_->GetNumberOfValues() > 0); } void SolidSelectorHighlight::setCurModelActor(MeshActorSelectOpFactory model_actor) @@ -123,6 +131,8 @@ void SolidSelectorHighlight::setCurModelActor(MeshActorSelectOpFactory model_act this->model_actor_ = model_actor; if (auto model_actor = this->model_actor_.lock()) { vtkSmartPointer extract_selection = model_actor->extractSolid(selected_ids_); - this->highlight_actor_->GetMapper()->SetInputConnection(extract_selection->GetOutputPort()); + this->mapper_->SetInputConnection(extract_selection->GetOutputPort()); } + if (highlight_actor_) + highlight_actor_->SetVisibility(selected_ids_->GetNumberOfValues() > 0); } \ No newline at end of file diff --git a/app/render/VertexSelectorHighlight.cpp b/app/render/VertexSelectorHighlight.cpp index bc19b2e..959583c 100644 --- a/app/render/VertexSelectorHighlight.cpp +++ b/app/render/VertexSelectorHighlight.cpp @@ -25,28 +25,30 @@ vtkIdType _is_selected(vtkIdType new_vertex, const vtkIdTypeArray& selected_ids_ } } -VertexSelectorHighlight::VertexSelectorHighlight(vtkRenderer* renderer) +VertexSelectorHighlight::VertexSelectorHighlight(vtkRenderer* renderer, vtkActor* highlight_actor) : renderer_(renderer) + , highlight_actor_(highlight_actor) { vtkNew dummy; - vtkNew mapper; - mapper->SetInputData(dummy); + this->mapper_ = vtkSmartPointer::New(); + this->mapper_->SetInputData(dummy); - this->highlight_actor_->SetMapper(mapper); - this->highlight_actor_->GetProperty()->SetColor(1.0, 0.0, 0.0); // 红色高亮 - this->highlight_actor_->GetProperty()->SetPointSize(6.0); - this->highlight_actor_->PickableOff(); // 防止自己被选中 + if (highlight_actor_) { + highlight_actor_->SetMapper(mapper_); + vtkNew prop; + prop->SetColor(1.0, 0.0, 0.0); // 红色高亮 + prop->SetPointSize(6.0); + highlight_actor_->SetProperty(prop); + highlight_actor_->SetVisibility(false); + } this->selected_ids_->SetNumberOfTuples(1); this->selected_ids_->SetNumberOfValues(0); - - this->renderer_->AddActor(this->highlight_actor_); } VertexSelectorHighlight::~VertexSelectorHighlight() { clear(); - this->renderer_->RemoveActor(this->highlight_actor_); } SelectionVtk VertexSelectorHighlight::get() @@ -62,6 +64,8 @@ SelectionVtk VertexSelectorHighlight::get() void VertexSelectorHighlight::clear() { _cancel_highlight(this->selected_ids_); + if (highlight_actor_) + highlight_actor_->SetVisibility(false); } void VertexSelectorHighlight::select(double posx, double posy) @@ -110,6 +114,8 @@ void VertexSelectorHighlight::select(double posx, double posy) spdlog::debug("VertexSelectorHighlight::select: point {} selected.", selected_vertex_id); } selected_ids_->Modified(); // 通知 VTK 数据已更改,进行刷新 + if (highlight_actor_) + highlight_actor_->SetVisibility(selected_ids_->GetNumberOfValues() > 0); } void VertexSelectorHighlight::setCurModelActor(MeshActorSelectOpFactory model_actor) @@ -117,6 +123,8 @@ void VertexSelectorHighlight::setCurModelActor(MeshActorSelectOpFactory model_ac this->model_actor_ = model_actor; if (auto model_actor = this->model_actor_.lock()) { auto extract_selection = model_actor->extractVertex(this->selected_ids_); - this->highlight_actor_->GetMapper()->SetInputConnection(extract_selection->GetOutputPort()); + this->mapper_->SetInputConnection(extract_selection->GetOutputPort()); } + if (highlight_actor_) + highlight_actor_->SetVisibility(selected_ids_->GetNumberOfValues() > 0); } diff --git a/app/render/test/TestEdgeSelectorHighlight.cpp b/app/render/test/TestEdgeSelectorHighlight.cpp index 4c13f66..7adc29c 100644 --- a/app/render/test/TestEdgeSelectorHighlight.cpp +++ b/app/render/test/TestEdgeSelectorHighlight.cpp @@ -2,6 +2,7 @@ #include "SelectorHighlight.h" #include +#include #include #include #include @@ -76,7 +77,10 @@ int main(int argc, char* argv[]) meshActor->loadModelData(test_mesh_data); // 集成 EdgeSelectorHighlight - EdgeSelectorHighlight selector(renderer); + vtkNew highlightActor; + highlightActor->PickableOff(); + renderer->AddActor(highlightActor); + EdgeSelectorHighlight selector(renderer, highlightActor); selector.setCurModelActor(MeshActorSelectOpFactory(meshActor)); style->SetSelectorHighlight(&selector); diff --git a/app/render/test/TestFaceSelectorHighlight.cpp b/app/render/test/TestFaceSelectorHighlight.cpp index d9e8a8b..0b2ea08 100644 --- a/app/render/test/TestFaceSelectorHighlight.cpp +++ b/app/render/test/TestFaceSelectorHighlight.cpp @@ -2,6 +2,7 @@ #include "SelectorHighlight.h" #include +#include #include #include #include @@ -76,7 +77,10 @@ int main(int argc, char* argv[]) meshActor->loadModelData(test_mesh_data); // 集成 FaceSelectorHighlight - FaceSelectorHighlight selector(renderer); + vtkNew highlightActor; + highlightActor->PickableOff(); + renderer->AddActor(highlightActor); + FaceSelectorHighlight selector(renderer, highlightActor); selector.setCurModelActor(MeshActorSelectOpFactory(meshActor)); style->SetSelectorHighlight(&selector); diff --git a/app/render/test/TestGeometryShapePicker.cpp b/app/render/test/TestGeometryShapePicker.cpp index 11b1de4..b45c9d9 100644 --- a/app/render/test/TestGeometryShapePicker.cpp +++ b/app/render/test/TestGeometryShapePicker.cpp @@ -150,22 +150,22 @@ public: } if (key == "1") { - mgr_->setSelectMode(SelectMode::Vertex); + mgr_->setSelectMode(SelectMode::GeometryVertex); spdlog::info("[GEOMETRY] mode=Vertex"); return; } if (key == "2") { - mgr_->setSelectMode(SelectMode::Edge); + mgr_->setSelectMode(SelectMode::GeometryEdge); spdlog::info("[GEOMETRY] mode=Edge"); return; } if (key == "3") { - mgr_->setSelectMode(SelectMode::Face); + mgr_->setSelectMode(SelectMode::GeometryFace); spdlog::info("[GEOMETRY] mode=Face"); return; } if (key == "4") { - mgr_->setSelectMode(SelectMode::Solid); + mgr_->setSelectMode(SelectMode::GeometrySolid); spdlog::info("[GEOMETRY] mode=Solid"); return; } @@ -210,13 +210,13 @@ int main(int argc, char** argv) modeStr = "face"; } - SelectMode mode = SelectMode::Face; + SelectMode mode = SelectMode::GeometryFace; if (modeStr == "edge") - mode = SelectMode::Edge; + mode = SelectMode::GeometryEdge; else if (modeStr == "vertex") - mode = SelectMode::Vertex; + mode = SelectMode::GeometryVertex; else if (modeStr == "solid") - mode = SelectMode::Solid; + mode = SelectMode::GeometrySolid; TopoDS_Shape root; if (stepPath) { @@ -259,7 +259,10 @@ int main(int argc, char** argv) gmgr.setVisibility(component_id, true); GeometrySelectManager selMgr; - selMgr.bindRenderer(renderer); + vtkNew highlightActor; + highlightActor->PickableOff(); + renderer->AddActor(highlightActor); + selMgr.bindRenderer(renderer, highlightActor); auto geomActor = gmgr.getComponentActor(component_id); selMgr.setSelectActor(geomActor); diff --git a/app/render/test/TestSolidSelectorHighlight.cpp b/app/render/test/TestSolidSelectorHighlight.cpp index 0712658..f0f3c88 100644 --- a/app/render/test/TestSolidSelectorHighlight.cpp +++ b/app/render/test/TestSolidSelectorHighlight.cpp @@ -75,7 +75,10 @@ int main(int argc, char* argv[]) meshActor->loadModelData(test_mesh_data); // 体元高亮选择器 - SolidSelectorHighlight selector(renderer); + vtkNew highlightActor; + highlightActor->PickableOff(); + renderer->AddActor(highlightActor); + SolidSelectorHighlight selector(renderer, highlightActor); selector.setCurModelActor(MeshActorSelectOpFactory(meshActor)); style->SetSelectorHighlight(&selector); diff --git a/app/render/test/TestVertexSelectorHighlight.cpp b/app/render/test/TestVertexSelectorHighlight.cpp index 84cd3f8..e1b547e 100644 --- a/app/render/test/TestVertexSelectorHighlight.cpp +++ b/app/render/test/TestVertexSelectorHighlight.cpp @@ -2,6 +2,7 @@ #include "SelectorHighlight.h" #include #include +#include #include #include #include @@ -64,7 +65,10 @@ int main(int argc, char* argv[]) meshActor->loadModelData(test_mesh_data); // 集成 VertexSelectorHighlight - VertexSelectorHighlight selector(renderer); + vtkNew highlightActor; + highlightActor->PickableOff(); + renderer->AddActor(highlightActor); + VertexSelectorHighlight selector(renderer, highlightActor); selector.setCurModelActor(MeshActorSelectOpFactory(meshActor)); style->SetSelectorHighlight(&selector); -- Gitee From 0d544cacbef262d4571b98536c10c4895b2f177b Mon Sep 17 00:00:00 2001 From: hypf Date: Sat, 11 Jul 2026 16:42:33 +0800 Subject: [PATCH 13/13] =?UTF-8?q?refactor(app)=EF=BC=9A=E4=BF=9D=E6=8C=81?= =?UTF-8?q?=E9=AB=98=E4=BA=AEactor=E5=8F=AF=E8=A7=81=E6=80=A7=E5=A7=8B?= =?UTF-8?q?=E7=BB=88=E4=B8=BAtrue=EF=BC=8C=E5=8F=AA=E6=A0=B9=E6=8D=AE?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=9D=A5=E6=8E=A7=E5=88=B6=E9=AB=98=E4=BA=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/render/EdgeSelectorHighlight.cpp | 5 ----- app/render/FaceSelectorHighlight.cpp | 5 ----- app/render/GeometryActorSelectOp.cpp | 2 +- app/render/GeometrySelectorHighlight.cpp | 22 ++++++---------------- app/render/SelectManager.cpp | 4 +--- app/render/SolidSelectorHighlight.cpp | 7 ------- app/render/VertexSelectorHighlight.cpp | 7 ------- 7 files changed, 8 insertions(+), 44 deletions(-) diff --git a/app/render/EdgeSelectorHighlight.cpp b/app/render/EdgeSelectorHighlight.cpp index 10babc3..5e69144 100644 --- a/app/render/EdgeSelectorHighlight.cpp +++ b/app/render/EdgeSelectorHighlight.cpp @@ -66,7 +66,6 @@ EdgeSelectorHighlight::EdgeSelectorHighlight(vtkRenderer* renderer, vtkActor* hi prop->SetColor(MeshActor::colors->GetColor3d("red").GetData()); prop->SetLineWidth(5); highlight_actor_->SetProperty(prop); - highlight_actor_->SetVisibility(false); } } @@ -79,8 +78,6 @@ void EdgeSelectorHighlight::clear() { _cancel_highlight(selected_mapper_); selections_.clear(); - if (highlight_actor_) - highlight_actor_->SetVisibility(false); } SelectionVtk EdgeSelectorHighlight::get() @@ -142,8 +139,6 @@ void EdgeSelectorHighlight::select(double posx, double posy) auto edge_poly_data = model_actor->extractEdge(selections_); // 设置PolyData到mapper selected_mapper_->SetInputData(edge_poly_data); - if (highlight_actor_) - highlight_actor_->SetVisibility(!selections_.empty()); } else { // 没选到 clear(); diff --git a/app/render/FaceSelectorHighlight.cpp b/app/render/FaceSelectorHighlight.cpp index 62a05cb..c7c04a3 100644 --- a/app/render/FaceSelectorHighlight.cpp +++ b/app/render/FaceSelectorHighlight.cpp @@ -41,7 +41,6 @@ FaceSelectorHighlight::FaceSelectorHighlight(vtkRenderer* renderer, vtkActor* hi prop->EdgeVisibilityOn(); prop->SetEdgeColor(1.0, 0.0, 0.0); highlight_actor_->SetProperty(prop); - highlight_actor_->SetVisibility(false); } } @@ -66,8 +65,6 @@ void FaceSelectorHighlight::clear() { _cancel_highlight(selected_mapper_); selections_.clear(); - if (highlight_actor_) - highlight_actor_->SetVisibility(false); } void FaceSelectorHighlight::select(double posx, double posy) @@ -112,8 +109,6 @@ void FaceSelectorHighlight::select(double posx, double posy) highlight_poly->SetPolys(cell_array); // 设置面单元 selected_mapper_->SetInputData(highlight_poly); // 触发高亮演员更新渲染 - if (highlight_actor_) - highlight_actor_->SetVisibility(!selections_.empty()); } else { // 没选到 clear(); diff --git a/app/render/GeometryActorSelectOp.cpp b/app/render/GeometryActorSelectOp.cpp index e223e4a..42b6185 100644 --- a/app/render/GeometryActorSelectOp.cpp +++ b/app/render/GeometryActorSelectOp.cpp @@ -310,7 +310,7 @@ GeometryHighlightPipeline GeometryActorSelectOp::buildHighlight(SelectMode mode) hl.mapper->SetRelativeCoincidentTopologyPointOffsetParameter(-2); } else { // 相对显示 mapper 默认值:多边形 (0,-1) - hl.mapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, -0.5); + hl.mapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, -5); } return hl; diff --git a/app/render/GeometrySelectorHighlight.cpp b/app/render/GeometrySelectorHighlight.cpp index d67eb04..107cc56 100644 --- a/app/render/GeometrySelectorHighlight.cpp +++ b/app/render/GeometrySelectorHighlight.cpp @@ -11,12 +11,11 @@ #include #include -static void flushHighlight(IVtkTools_SubPolyDataFilter* filter, vtkActor* hlActor, bool visible, vtkRenderer* renderer) +static void flushHighlight(IVtkTools_SubPolyDataFilter* filter, vtkRenderer* renderer) { - if (!filter || !hlActor || !renderer) + if (!filter || !renderer) return; filter->Modified(); - hlActor->SetVisibility(visible); if (renderer->GetRenderWindow()) renderer->GetRenderWindow()->Render(); } @@ -41,7 +40,6 @@ static void mountHighlight(vtkActor* actor, const GeometryHighlightPipeline& hl, prop->SetOpacity(1.0); } actor->SetProperty(prop); - actor->SetVisibility(false); } // ─── Face ────────────────────────────────────────────── @@ -64,8 +62,6 @@ void GeometryFaceSelectorHighlight::clear() hl_.filter->Clear(); hl_.filter->Modified(); } - if (highlight_actor_) - highlight_actor_->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -101,7 +97,7 @@ void GeometryFaceSelectorHighlight::select(double posx, double posy) if (hl_.filter) hl_.filter->SetData(ids); - flushHighlight(hl_.filter, highlight_actor_, !ids.IsEmpty(), renderer_); + flushHighlight(hl_.filter, renderer_); } void GeometryFaceSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) @@ -142,8 +138,6 @@ void GeometryEdgeSelectorHighlight::clear() hl_.filter->Clear(); hl_.filter->Modified(); } - if (highlight_actor_) - highlight_actor_->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -179,7 +173,7 @@ void GeometryEdgeSelectorHighlight::select(double posx, double posy) if (hl_.filter) hl_.filter->SetData(ids); - flushHighlight(hl_.filter, highlight_actor_, !ids.IsEmpty(), renderer_); + flushHighlight(hl_.filter, renderer_); } void GeometryEdgeSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) @@ -220,8 +214,6 @@ void GeometryVertexSelectorHighlight::clear() hl_.filter->Clear(); hl_.filter->Modified(); } - if (highlight_actor_) - highlight_actor_->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -257,7 +249,7 @@ void GeometryVertexSelectorHighlight::select(double posx, double posy) if (hl_.filter) hl_.filter->SetData(ids); - flushHighlight(hl_.filter, highlight_actor_, !ids.IsEmpty(), renderer_); + flushHighlight(hl_.filter, renderer_); } void GeometryVertexSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) @@ -299,8 +291,6 @@ void GeometrySolidSelectorHighlight::clear() hl_.filter->Clear(); hl_.filter->Modified(); } - if (highlight_actor_) - highlight_actor_->SetVisibility(false); if (renderer_ && renderer_->GetRenderWindow()) renderer_->GetRenderWindow()->Render(); } @@ -343,7 +333,7 @@ void GeometrySolidSelectorHighlight::select(double posx, double posy) if (hl_.filter) hl_.filter->SetData(ids); - flushHighlight(hl_.filter, highlight_actor_, !ids.IsEmpty(), renderer_); + flushHighlight(hl_.filter, renderer_); } void GeometrySolidSelectorHighlight::setCurGeomActor(GeometryActorSelectOpFactory geom_actor) diff --git a/app/render/SelectManager.cpp b/app/render/SelectManager.cpp index 6ba9014..6820cf8 100644 --- a/app/render/SelectManager.cpp +++ b/app/render/SelectManager.cpp @@ -17,7 +17,7 @@ SelectManager::SelectManager() empty_mapper_->SetInputData(empty); highlight_actor_->SetMapper(empty_mapper_); highlight_actor_->PickableOff(); - highlight_actor_->SetVisibility(false); + highlight_actor_->SetVisibility(true); } SelectManager::~SelectManager() = default; @@ -48,8 +48,6 @@ void SelectManager::setSelectActor(std::weak_ptr geom_actor) void SelectManager::setSelectMode(const std::string& select_mode) { - // 复位共享 actor:隐藏并挂回空 mapper;随后由激活的 selector 挂上自己的 mapper(None 则保持空) - highlight_actor_->SetVisibility(false); highlight_actor_->SetMapper(empty_mapper_); SelectMode mode = SelectMode::None; diff --git a/app/render/SolidSelectorHighlight.cpp b/app/render/SolidSelectorHighlight.cpp index 74fb54a..cc54248 100644 --- a/app/render/SolidSelectorHighlight.cpp +++ b/app/render/SolidSelectorHighlight.cpp @@ -53,7 +53,6 @@ SolidSelectorHighlight::SolidSelectorHighlight(vtkRenderer* renderer, vtkActor* prop->SetEdgeColor(1.0, 0.0, 0.0); // 红色边框 prop->SetLineWidth(2.0); highlight_actor_->SetProperty(prop); - highlight_actor_->SetVisibility(false); } } @@ -75,8 +74,6 @@ SelectionVtk SolidSelectorHighlight::get() void SolidSelectorHighlight::clear() { _cancel_highlight(this->selected_ids_); - if (highlight_actor_) - highlight_actor_->SetVisibility(false); } void SolidSelectorHighlight::select(double posx, double posy) @@ -122,8 +119,6 @@ void SolidSelectorHighlight::select(double posx, double posy) spdlog::debug("SolidSelectorHighlight::select: point {} selected.", selected_solid_id); } this->selected_ids_->Modified(); // 触发highlight_actor_更新 - if (highlight_actor_) - highlight_actor_->SetVisibility(selected_ids_->GetNumberOfValues() > 0); } void SolidSelectorHighlight::setCurModelActor(MeshActorSelectOpFactory model_actor) @@ -133,6 +128,4 @@ void SolidSelectorHighlight::setCurModelActor(MeshActorSelectOpFactory model_act vtkSmartPointer extract_selection = model_actor->extractSolid(selected_ids_); this->mapper_->SetInputConnection(extract_selection->GetOutputPort()); } - if (highlight_actor_) - highlight_actor_->SetVisibility(selected_ids_->GetNumberOfValues() > 0); } \ No newline at end of file diff --git a/app/render/VertexSelectorHighlight.cpp b/app/render/VertexSelectorHighlight.cpp index 959583c..332db0f 100644 --- a/app/render/VertexSelectorHighlight.cpp +++ b/app/render/VertexSelectorHighlight.cpp @@ -39,7 +39,6 @@ VertexSelectorHighlight::VertexSelectorHighlight(vtkRenderer* renderer, vtkActor prop->SetColor(1.0, 0.0, 0.0); // 红色高亮 prop->SetPointSize(6.0); highlight_actor_->SetProperty(prop); - highlight_actor_->SetVisibility(false); } this->selected_ids_->SetNumberOfTuples(1); @@ -64,8 +63,6 @@ SelectionVtk VertexSelectorHighlight::get() void VertexSelectorHighlight::clear() { _cancel_highlight(this->selected_ids_); - if (highlight_actor_) - highlight_actor_->SetVisibility(false); } void VertexSelectorHighlight::select(double posx, double posy) @@ -114,8 +111,6 @@ void VertexSelectorHighlight::select(double posx, double posy) spdlog::debug("VertexSelectorHighlight::select: point {} selected.", selected_vertex_id); } selected_ids_->Modified(); // 通知 VTK 数据已更改,进行刷新 - if (highlight_actor_) - highlight_actor_->SetVisibility(selected_ids_->GetNumberOfValues() > 0); } void VertexSelectorHighlight::setCurModelActor(MeshActorSelectOpFactory model_actor) @@ -125,6 +120,4 @@ void VertexSelectorHighlight::setCurModelActor(MeshActorSelectOpFactory model_ac auto extract_selection = model_actor->extractVertex(this->selected_ids_); this->mapper_->SetInputConnection(extract_selection->GetOutputPort()); } - if (highlight_actor_) - highlight_actor_->SetVisibility(selected_ids_->GetNumberOfValues() > 0); } -- Gitee