From 500f860d5c0c3a56370cea23edf1342ceca2e1dc Mon Sep 17 00:00:00 2001 From: parker Date: Sun, 10 Aug 2025 23:30:12 +0100 Subject: [PATCH] feat(geometrySpreadsheet): add index column --- src/Engine/Operator/Geometry.cpp | 50 ++++++++++++++++++- src/Engine/Operator/Geometry.h | 28 +++++++---- .../GeometrySpreadsheetMenuBar.cpp | 4 ++ .../GeometrySpreadsheetModel.cpp | 39 ++++++++++++--- .../GeometrySpreadsheetModel.h | 2 + 5 files changed, 103 insertions(+), 20 deletions(-) diff --git a/src/Engine/Operator/Geometry.cpp b/src/Engine/Operator/Geometry.cpp index a66204c..a75b0cf 100644 --- a/src/Engine/Operator/Geometry.cpp +++ b/src/Engine/Operator/Geometry.cpp @@ -3,6 +3,7 @@ #include "Engine/Operator/AttributeHandle.h" #include "Engine/Types.h" #include +#include #include #include #include @@ -33,16 +34,45 @@ geo::Geometry::Geometry(const Geometry& other): posHandlePoint_{enzo::ga::AttributeHandleVector3(getAttribByName(ga::AttrOwner::POINT, "P"))}, // other - soloPoints_{other.soloPoints_} + soloPoints_{other.soloPoints_}, + vertexPrims_{other.vertexPrims_}, + primStarts_{other.primStarts_}, + primStartsDirty_{other.primStartsDirty_.load()} { +} +enzo::geo::Geometry& enzo::geo::Geometry::operator=(const enzo::geo::Geometry& rhs) { + if (this == &rhs) return *this; + + // attributes + pointAttributes_ = deepCopyAttributes(rhs.pointAttributes_); + vertexAttributes_ = deepCopyAttributes(rhs.vertexAttributes_); + primitiveAttributes_ = deepCopyAttributes(rhs.primitiveAttributes_); + globalAttributes_ = deepCopyAttributes(rhs.globalAttributes_); + + // handles + vertexCountHandlePrim_ = enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount")); + closedHandlePrim_ = enzo::ga::AttributeHandleBool(getAttribByName(ga::AttrOwner::PRIMITIVE, "closed")); + pointOffsetHandleVert_ = enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::VERTEX, "point")); + posHandlePoint_ = enzo::ga::AttributeHandleVector3(getAttribByName(ga::AttrOwner::POINT, "P")); + + // other + soloPoints_ = rhs.soloPoints_; + vertexPrims_ = rhs.vertexPrims_; + primStarts_ = rhs.primStarts_; + + primStartsDirty_.store(rhs.primStartsDirty_.load()); + + return *this; } void geo::Geometry::addFace(std::vector pointOffsets, bool closed) { + const ga::Offset primNum = vertexCountHandlePrim_.getSize(); for(ga::Offset pointOffset : pointOffsets) { pointOffsetHandleVert_.addValue(pointOffset); + vertexPrims_.push_back(primNum); soloPoints_.erase(pointOffset); } vertexCountHandlePrim_.addValue(pointOffsets.size()); @@ -119,6 +149,11 @@ bt::Vector3 geo::Geometry::getPointPos(ga::Offset pointOffset) const return posHandlePoint_.getValue(pointOffset); } +ga::Offset geo::Geometry::getVertexPrim(ga::Offset vertexOffset) const +{ + return vertexPrims_[vertexOffset]; +} + void geo::Geometry::setPointPos(const ga::Offset offset, const bt::Vector3& pos) { posHandlePoint_.setValue(offset, pos); @@ -250,19 +285,30 @@ enzo::geo::HeMesh geo::Geometry::computeHalfEdgeMesh() ga::Offset geo::Geometry::getPrimStartVertex(ga::Offset primOffset) const { + if(primStartsDirty_.load()) + { + tbb::spin_mutex::scoped_lock lock(primStartsMutex_); //lock + if(primStartsDirty_.load()) // double check + { + computePrimStartVertices(); + } + } return primStarts_[primOffset]; } // TODO: handle this automatically -void geo::Geometry::computePrimStartVertices() +void geo::Geometry::computePrimStartVertices() const { const ga::Offset handleSize = vertexCountHandlePrim_.getSize(); + primStarts_.clear(); + primStarts_.reserve(handleSize); bt::intT primStart = 0; for(size_t i=0; i #include "Engine/Operator/AttributeHandle.h" #include +#include +#include #include @@ -27,6 +29,7 @@ class Geometry public: Geometry(); Geometry(const Geometry& other); + Geometry& operator=(const Geometry& rhs); ga::AttributeHandle addIntAttribute(ga::AttributeOwner owner, std::string name); ga::AttributeHandleBool addBoolAttribute(ga::AttributeOwner owner, std::string name); ga::AttributeHandle addVector3Attribute(ga::AttributeOwner owner, std::string name); @@ -48,18 +51,19 @@ public: void setPointPos(const ga::Offset offset, const bt::Vector3& pos); - ga::Offset getPrimStartVertex(ga::Offset primOffset) const; // returns the first vertex of the primitive - bt::Vector3 getPosFromVert(ga::Offset vertexOffset) const; - bt::Vector3 getPointPos(ga::Offset pointOffset) const; - unsigned int getPrimVertCount(ga::Offset primOffset) const; - ga::Offset getNumPrims() const; - ga::Offset getNumVerts() const; - ga::Offset getNumPoints() const; - ga::Offset getNumSoloPoints() const; + ga::Offset getPrimStartVertex(ga::Offset primOffset) const; // returns the first vertex of the primitive + bt::Vector3 getPosFromVert(ga::Offset vertexOffset) const; + bt::Vector3 getPointPos(ga::Offset pointOffset) const; + unsigned int getPrimVertCount(ga::Offset primOffset) const; + ga::Offset getVertexPrim(ga::Offset vertexOffset) const; + ga::Offset getNumPrims() const; + ga::Offset getNumVerts() const; + ga::Offset getNumPoints() const; + ga::Offset getNumSoloPoints() const; bt::boolT isClosed(ga::Offset primOffset) const; - void computePrimStartVertices(); + void computePrimStartVertices() const; private: using attribVector = std::vector>; geo::Geometry::attribVector& getAttributeStore(const ga::AttributeOwner& owner); @@ -74,7 +78,11 @@ private: std::set soloPoints_; - std::vector primStarts_; + mutable std::vector primStarts_; + mutable std::vector vertexPrims_; + + mutable std::atomic primStartsDirty_{true}; + mutable tbb::spin_mutex primStartsMutex_; // handles enzo::ga::AttributeHandleInt vertexCountHandlePrim_; diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp index fa3dd8d..24e05ab 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetMenuBar.cpp @@ -133,8 +133,12 @@ GeometrySpreadsheetMenuBar::GeometrySpreadsheetMenuBar(QWidget *parent, Qt::Wind nodeLabel_ = new QLabel(); mainLayout_->addWidget(nodeLabel_); modeSelection = new GeoSheetMenuBarModeSelection(); + mainLayout_->addStretch(); mainLayout_->addWidget(modeSelection); + const int margins = 0; + mainLayout_->setContentsMargins(margins, margins, margins, margins); + setLayout(mainLayout_); } diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp index 81654fa..94318e6 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.cpp @@ -87,7 +87,7 @@ int GeometrySpreadsheetModel::rowCount(const QModelIndex &parent) const int GeometrySpreadsheetModel::columnCount(const QModelIndex &parent) const { - int columnCount = 0; + int columnCount = attributeColumnPadding_; // first column is for indices for(auto size : attribSizes_) { columnCount += size; @@ -114,11 +114,34 @@ QVariant GeometrySpreadsheetModel::data(const QModelIndex &index, int role) cons if (role == Qt::DisplayRole) { - // std::cout << geometry_.getPointPos(index.row()).x() << "\n"; - int attributeIndex = indexFromSection(index.column()); + if(index.column()==0) + { + switch(attributeOwner_) + { + case enzo::ga::AttributeOwner::POINT: + case enzo::ga::AttributeOwner::PRIMITIVE: + { + return index.row(); + } + case enzo::ga::AttributeOwner::VERTEX: + { + const enzo::ga::Offset primOffset = geometry_.getVertexPrim(index.row()); + const enzo::ga::Offset startVert = geometry_.getPrimStartVertex(primOffset); + const enzo::ga::Offset vertexNumber = index.row()-startVert; + return QString::fromStdString(std::to_string(primOffset)+":"+std::to_string(vertexNumber)); + + } + case enzo::ga::AttributeOwner::GLOBAL: + { + return "global"; + } + + } + } + int attributeIndex = indexFromSection(index.column()-attributeColumnPadding_); if(std::shared_ptr attrib = geometry_.getAttributeByIndex(attributeOwner_, attributeIndex).lock()) { - const unsigned int valueIndex = index.column()-attributeIndex; + const unsigned int valueIndex = index.column()-attributeIndex-attributeColumnPadding_; using namespace enzo::ga; switch(attrib->getType()) @@ -167,9 +190,8 @@ int GeometrySpreadsheetModel::indexFromSection(unsigned int section) const { if(section>=sectionAttribMap_.size()) { - throw std::out_of_range("Section is out of range of sectionAttributMap_"); + throw std::out_of_range("Section is out of range of sectionAttributMap_, value: " + std::to_string(section) + " expected: <"+std::to_string(sectionAttribMap_.size())); } - IC(sectionAttribMap_); return sectionAttribMap_[section]; } @@ -182,12 +204,13 @@ QVariant GeometrySpreadsheetModel::headerData(int section, Qt::Orientation orien if (orientation == Qt::Horizontal) { - auto attributeIndex = indexFromSection(section); + if(section==0) return "Index"; + auto attributeIndex = indexFromSection(section-attributeColumnPadding_); if(auto attrib = geometry_.getAttributeByIndex(attributeOwner_, attributeIndex).lock()) { if(attribSizes_[attributeIndex]>1) { - const unsigned int valueIndex = section-attributeIndex; + const unsigned int valueIndex = section-attributeIndex-attributeColumnPadding_; std::string valueIndexString; if(attrib->getType()==enzo::ga::AttrType::vectorT) diff --git a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h index debff55..500b790 100644 --- a/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h +++ b/src/Gui/GeometrySpreadsheetPanel/GeometrySpreadsheetModel.h @@ -23,11 +23,13 @@ public: void initBuffers(); + private: enzo::nt::OpId opId_; enzo::geo::Geometry geometry_; std::vector attribSizes_; std::vector sectionAttribMap_; + const int attributeColumnPadding_ = 1; enzo::ga::AttributeOwner attributeOwner_=enzo::ga::AttributeOwner::POINT; };