diff --git a/smtk/bridge/cgm/Session.cxx b/smtk/bridge/cgm/Session.cxx index ef9fb43498bf7a2ced451bfdbd536199b69baf1a..56e86bab80aeff2e4389992b1dbdfe281a3a7a2d 100644 --- a/smtk/bridge/cgm/Session.cxx +++ b/smtk/bridge/cgm/Session.cxx @@ -833,6 +833,16 @@ bool SessionAddTessellation(const EntityRef& entityref, E* cgmEnt, double chordE if (!cgmEnt || !entityref.manager() || !entityref.entity()) return false; + //calculate and store the bounding box + std::vector bBox; + bBox.push_back(cgmEnt->bounding_box().min_x()); + bBox.push_back(cgmEnt->bounding_box().max_x()); + bBox.push_back(cgmEnt->bounding_box().min_y()); + bBox.push_back(cgmEnt->bounding_box().max_y()); + bBox.push_back(cgmEnt->bounding_box().min_z()); + bBox.push_back(cgmEnt->bounding_box().max_z()); + entityref.manager()->setBoundingBox(entityref.entity(),bBox ,true); + GMem primitives; double measure = cgmEnt->measure(); double maxErr = pow(measure, 1./cgmEnt->dimension()) * chordErr; @@ -844,23 +854,25 @@ bool SessionAddTessellation(const EntityRef& entityref, E* cgmEnt, double chordE { return false; } + + // addTessellation to the manager smtk::model::Tessellation blank; - smtk::model::UUIDsToTessellations& tess(entityref.manager()->tessellations()); - smtk::model::UUIDsToTessellations::iterator it = - tess.insert(std::pair(entityref.entity(), blank)).first; - it->second.reset(); + entityref.manager()->setTessellation(entityref.entity(), blank); + + smtk::model::Tessellation *tess = const_cast(entityref.hasTessellation()); + // Now add data to the Tessellation "in situ" to avoid a copy. // First, copy point coordinates: - it->second.coords().reserve(3 * npts); + tess->coords().reserve(3 * npts); GPoint* inPts = primitives.point_list(); for (int j = 0; j < npts; ++j, ++inPts) { - it->second.addCoords(inPts->x, inPts->y, inPts->z); + tess->addCoords(inPts->x, inPts->y, inPts->z); } // Now translate the connectivity: if (cgmEnt->dimension() > 1) { - it->second.conn().reserve(connCount); + tess->conn().reserve(connCount); int* inConn = primitives.facet_list(); int ptsPerPrim = 0; for (int k = 0; k < connCount; k += (ptsPerPrim + 1), inConn += (ptsPerPrim + 1)) @@ -871,16 +883,16 @@ bool SessionAddTessellation(const EntityRef& entityref, E* cgmEnt, double chordE { case 1: // This is a vertex - it->second.addPoint(pConn[0]); + tess->addPoint(pConn[0]); break; case 2: - it->second.addLine(pConn[0], pConn[1]); + tess->addLine(pConn[0], pConn[1]); break; case 3: - it->second.addTriangle(pConn[0], pConn[1], pConn[2]); + tess->addTriangle(pConn[0], pConn[1], pConn[2]); break; case 4: - it->second.addQuad(pConn[0], pConn[1], pConn[2], pConn[3]); + tess->addQuad(pConn[0], pConn[1], pConn[2], pConn[3]); default: std::cerr << "Unknown primitive has " << ptsPerPrim << " conn entries\n"; break; @@ -889,12 +901,12 @@ bool SessionAddTessellation(const EntityRef& entityref, E* cgmEnt, double chordE } else { - it->second.conn().reserve(npts + 2); - it->second.conn().push_back(smtk::model::TESS_POLYLINE); - it->second.conn().push_back(npts); + tess->conn().reserve(npts + 2); + tess->conn().push_back(smtk::model::TESS_POLYLINE); + tess->conn().push_back(npts); for (int k = 0; k < npts; ++k) { - it->second.conn().push_back(k); + tess->conn().push_back(k); } } @@ -969,18 +981,31 @@ bool SessionAddTessellation(const EntityRef& entityref, RefVertex* cgmEnt, doubl cellConn.push_back(smtk::model::TESS_VERTEX); cellConn.push_back(0); + //calculate and store the bounding box + std::vector bBox; + bBox.push_back(cgmEnt->bounding_box().min_x()); + bBox.push_back(cgmEnt->bounding_box().max_x()); + bBox.push_back(cgmEnt->bounding_box().min_y()); + bBox.push_back(cgmEnt->bounding_box().max_y()); + bBox.push_back(cgmEnt->bounding_box().min_z()); + bBox.push_back(cgmEnt->bounding_box().max_z()); + entityref.manager()->setBoundingBox(entityref.entity(),bBox ,true); + CubitVector coords = cgmEnt->coordinates(); + + // addTessellation to the manager smtk::model::Tessellation blank; - smtk::model::UUIDsToTessellations& tess(entityref.manager()->tessellations()); - smtk::model::UUIDsToTessellations::iterator it = - tess.insert( - std::pair( - entityref.entity(), blank)).first; + entityref.manager()->setTessellation(entityref.entity(), blank); + + smtk::model::Tessellation *tess = const_cast(entityref.hasTessellation()); + + // Now add data to the Tessellation "in situ" to avoid a copy. + // Now add data to the Tessellation "in situ" to avoid a copy. // First, copy point coordinates: - it->second.coords().resize(3); - coords.get_xyz(&it->second.coords()[0]); - it->second.insertNextCell(cellConn); + tess->coords().resize(3); + coords.get_xyz(&tess->coords()[0]); + tess->insertNextCell(cellConn); return true; } diff --git a/smtk/bridge/discrete/Session.cxx b/smtk/bridge/discrete/Session.cxx index 29609d5ef6619b2469b247bbbbfaa7dc5ad52c3e..d857cd0525d8343b8787fee1d97e457fc3c2b88b 100644 --- a/smtk/bridge/discrete/Session.cxx +++ b/smtk/bridge/discrete/Session.cxx @@ -1596,7 +1596,7 @@ bool Session::addTessellation(const smtk::model::EntityRef& cellOut, vtkModelGeo std::cerr << "Warning: Triangle strips in discrete cells are unsupported. Ignoring.\n"; } if (!vertMap.empty()) - cellOut.manager()->setTessellation(cellOut.entity(), tess); + cellOut.manager()->setTessellationAndBoundingBox(cellOut.entity(), tess); smtk::mesh::CollectionPtr collection = this->manager()->meshes()->collection(cellOut.owningModel().entity()); diff --git a/smtk/bridge/discrete/testing/cxx/CMakeLists.txt b/smtk/bridge/discrete/testing/cxx/CMakeLists.txt index 9136bd2d3ebaf92c15c0f5d29be87b7e92810aac..10a545794f81c3db02680be638869e5c0dd4dc75 100644 --- a/smtk/bridge/discrete/testing/cxx/CMakeLists.txt +++ b/smtk/bridge/discrete/testing/cxx/CMakeLists.txt @@ -75,5 +75,18 @@ if(SMTK_DATA_DIR) "${SMTK_DATA_DIR}/mesh/2d/test2D.2dm" ) + add_executable(boundingBox2dmTest boundingBox2dm.cxx) + target_link_libraries(boundingBox2dmTest + smtkCore + smtkDiscreteSession + vtkSMTKOperatorsExt + vtkSMTKSourceExt + ) + add_test( + NAME boundingBox2dmTest + COMMAND + $ + "${SMTK_DATA_DIR}/mesh/2d/test2D.2dm" + ) endif() diff --git a/smtk/bridge/discrete/testing/cxx/boundingBox2dm.cxx b/smtk/bridge/discrete/testing/cxx/boundingBox2dm.cxx new file mode 100644 index 0000000000000000000000000000000000000000..395895995f093e6f401274cfca35e63ee7627852 --- /dev/null +++ b/smtk/bridge/discrete/testing/cxx/boundingBox2dm.cxx @@ -0,0 +1,112 @@ +//========================================================================= +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//========================================================================= +#include "smtk/io/ImportJSON.h" +#include "smtk/io/ModelToMesh.h" + +#include "smtk/mesh/Collection.h" +#include "smtk/mesh/Manager.h" +#include "smtk/mesh/testing/cxx/helpers.h" + +#include "smtk/model/Manager.h" +#include "smtk/model/Operator.h" +#include "smtk/model/Edge.h" +#include "smtk/model/Vertex.h" +#include "smtk/model/Group.h" + +#include "smtk/attribute/IntItem.h" +#include "smtk/attribute/FileItem.h" +#include "smtk/attribute/StringItem.h" +#include "smtk/attribute/VoidItem.h" +#include "smtk/common/UUID.h" + +#include "smtk/bridge/discrete/Session.h" + +using namespace smtk::model; + +int main(int argc, char* argv[]) +{ + // basic check info + if (argc == 1) + { + std::cout<<"Must provide input file as argument"<sessionTypeNames(); + for (StringList::iterator it = sessions.begin(); it != sessions.end(); ++it) + std::cout << " " << *it << "\n"; + std::cout << "\n"; + + // Create a new discrete session + smtk::bridge::discrete::Session::Ptr session = smtk::bridge::discrete::Session::create(); + manager->registerSession(session); + + // Identify available operators + std::cout << "Available cmb operators in discrete session\n"; + StringList opnames = session->operatorNames(); + for (StringList::iterator it = opnames.begin(); it != opnames.end(); ++it) + { + std::cout << " " << *it << "\n"; + } + std::cout << "\n"; + + // read the data + smtk::model::OperatorPtr readOp = session->op("import"); + if (!readOp) + { + std::cerr << "No import operator\n"; + return 1; + } + + // read the file + readOp->specification()->findFile("filename")->setValue(std::string(argv[1])); + std::cout << "Importing " << argv[1] << "\n"; + smtk::model::OperatorResult opresult = readOp->operate(); + if ( + opresult->findInt("outcome")->value() != + smtk::model::OPERATION_SUCCEEDED) + { + std::cerr << "Read operator failed\n"; + return 1; + } + + smtk::model::Model modelSimple2dm = opresult->findModelEntity("created")->value(); + + if (!modelSimple2dm.isValid()) + { + std::cerr << "Reading simple 2dm file failed!\n"; + return 1; + } + + // get edge/face info + EntityRefs groups = manager->entitiesMatchingFlagsAs(smtk::model::GROUP_ENTITY); + std::cout << "Before creation, group size is: " << groups.size() << endl; + EntityRefs edges = manager->entitiesMatchingFlagsAs(smtk::model::EDGE); + std::cout << "Edges inside the model is:\n"; + for (EntityRefs::iterator it = edges.begin(); it != edges.end(); ++it) + { + std::cout << " " << it->name()<< " \n"; + if (!it->hasFloatProperty(SMTK_BOUNDING_BOX_PROP)) + { + std::cerr << "edge has no bounding box!\n"; + return 1; + } + } + std::cout <setTessellation(entityref.entity(), tess); + entityref.manager()->setTessellationAndBoundingBox(entityref.entity(), tess); smtk::mesh::CollectionPtr collection = this->manager()->meshes()-> diff --git a/smtk/bridge/polygon/internal/Model.cxx b/smtk/bridge/polygon/internal/Model.cxx index 8fa31cf19fe961f8b6f91545d5d069a8b6e488c7..e0c012d8812df734d2b33219a51ed59cbb7ff875 100644 --- a/smtk/bridge/polygon/internal/Model.cxx +++ b/smtk/bridge/polygon/internal/Model.cxx @@ -1245,7 +1245,7 @@ void pmodel::addFaceTessellation(smtk::model::Face& faceRec) smtk::model::Loops outerLoops = faceRec.positiveUse().loops(); smtk::model::Tessellation blank; smtk::model::UUIDsToTessellations::iterator smtkTess = - faceRec.manager()->setTessellation(faceRec.entity(), blank); + faceRec.manager()->setTessellationAndBoundingBox(faceRec.entity(), blank); //std::cout << "Tessellate " << faceRec.name() << "\n"; for (smtk::model::Loops::iterator lit = outerLoops.begin(); lit != outerLoops.end(); ++lit) { @@ -1407,7 +1407,7 @@ void pmodel::addEdgeTessellation(smtk::model::Edge& edgeRec, internal::edge::Ptr smtk::model::Manager::Ptr mgr = edgeRec.manager(); smtk::model::Tessellation empty; UUIDsToTessellations::iterator tessIt = - mgr->setTessellation(edgeRec.entity(), empty); + mgr->setTessellationAndBoundingBox(edgeRec.entity(), empty); // Now populate the tessellation in place. PointSeq::const_iterator ptIt; diff --git a/smtk/bridge/polygon/operators/CreateFaces.cxx b/smtk/bridge/polygon/operators/CreateFaces.cxx index 07032789cb1037ee6fd4fc838f5f75aa1620f2ad..6d8bdae8169a37ecc79c56036e82638ce8686a71 100644 --- a/smtk/bridge/polygon/operators/CreateFaces.cxx +++ b/smtk/bridge/polygon/operators/CreateFaces.cxx @@ -574,7 +574,7 @@ void CreateFaces::addTessellations() std::vector >::const_iterator pit; smtk::model::Tessellation blank; smtk::model::UUIDsToTessellations::iterator smtkTess = - this->manager()->setTessellation(modelFace.entity(), blank); + this->manager()->setTessellationAndBoundingBox(modelFace.entity(), blank); double smtkPt[3]; for (pit = tess.begin(); pit != tess.end(); ++pit) { diff --git a/smtk/bridge/polygon/operators/ForceCreateFace.cxx b/smtk/bridge/polygon/operators/ForceCreateFace.cxx index 65360a28e8c5c16aa1e2f306eacf5c3c3ce96f04..55d1ecc99086e48f0c055294baa90671b96c6ccb 100644 --- a/smtk/bridge/polygon/operators/ForceCreateFace.cxx +++ b/smtk/bridge/polygon/operators/ForceCreateFace.cxx @@ -271,7 +271,7 @@ smtk::model::OperatorResult ForceCreateFace::operateInternal() std::vector >::const_iterator pit; smtk::model::Tessellation blank; smtk::model::UUIDsToTessellations::iterator smtkTess = - mgr->setTessellation(modelFaceId, blank); + mgr->setTessellationAndBoundingBox(modelFaceId, blank); double smtkPt[3]; for (pit = tess.begin(); pit != tess.end(); ++pit) { diff --git a/smtk/extension/qt/CMakeLists.txt b/smtk/extension/qt/CMakeLists.txt index 766fd196aa1eb700e1c4425ed217b06c710d5820..f8c66c7b1d5062651deb85672dcc9da78ecfa39d 100644 --- a/smtk/extension/qt/CMakeLists.txt +++ b/smtk/extension/qt/CMakeLists.txt @@ -3,6 +3,7 @@ include(${QT_USE_FILE}) # set up sources to build set(QAttrLibSrcs qtUIManager.cxx + qtSelectionManager.cxx qtAttribute.cxx qtAttributeDisplay.cxx qtAttributeItemWidgetFactory.cxx @@ -53,6 +54,7 @@ set(QAttrLibUIs set(QAttrLibMocHeaders qtUIManager.h + qtSelectionManager.h qtAttribute.h qtAttributeDisplay.h qtBaseView.h diff --git a/smtk/extension/qt/qtModelView.cxx b/smtk/extension/qt/qtModelView.cxx index 2ea2bae7535aebd7261cdb1dab08c248747c75d9..aa836a19bb6b8ce4b0b4702f28b4c5011d2bfe4d 100644 --- a/smtk/extension/qt/qtModelView.cxx +++ b/smtk/extension/qt/qtModelView.cxx @@ -382,6 +382,7 @@ void qtModelView::selectionChanged ( AUX_GEOM_ENTITY | INSTANCE_ENTITY, selproperties, false, &selmeshes); + // update selection manager emit this->selectionChanged(selentityrefs, selmeshes, selproperties); } diff --git a/smtk/extension/qt/qtSelectionManager.cxx b/smtk/extension/qt/qtSelectionManager.cxx new file mode 100644 index 0000000000000000000000000000000000000000..db681ef82612890a2930ec78f937494cae266712 --- /dev/null +++ b/smtk/extension/qt/qtSelectionManager.cxx @@ -0,0 +1,96 @@ +//========================================================================= +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//========================================================================= + +#include "smtk/extension/qt/qtSelectionManager.h" +#include "smtk/extension/qt/Exports.h" +#include "smtk/extension/qt/qtItem.h" + +#include "smtk/PublicPointerDefs.h" +#include "smtk/common/UUID.h" +#include "smtk/model/DescriptivePhrase.h" +#include "smtk/model/EntityRef.h" +#include "smtk/model/SessionRef.h" +#include "smtk/mesh/MeshSet.h" +#include "smtk/model/Session.h" + +namespace smtk +{ + namespace extension + { + qtSelectionManager::qtSelectionManager() + { + this->clearAllSelections(); + } + + void qtSelectionManager::getSelectedEntities(smtk::common::UUIDs &selEntities) + { + selEntities = this->m_selEntities; + } + + void qtSelectionManager::getSelectedMeshes(smtk::mesh::MeshSets &selMeshes) + { + selMeshes = this->m_selMeshes; + } + + void qtSelectionManager::updateSelectedItems( + const smtk::common::UUIDs &selEntities, const smtk::mesh::MeshSets &selMeshes) + { + this->clearAllSelections(); + // update entity and mesh + this->m_selEntities.insert(selEntities.begin(),selEntities.end()); + this->m_selMeshes.insert(selMeshes.begin(),selMeshes.end()); + // TBD: broacast to attribute panel + bool blocksignals = true; + emit broadcastToModelTree(this->m_selEntities,this->m_selMeshes, + blocksignals); + } + + void qtSelectionManager::updateSelectedItems(const smtk::model::EntityRefs + &selEntities, const smtk::mesh::MeshSets &selMeshes, + const smtk::model::DescriptivePhrases &DesPhrases) + + { + this->clearAllSelections(); + for (smtk::model::EntityRefs::iterator it = selEntities.begin(); + it != selEntities.end(); ++it) + { + this->m_selEntities.insert(it->entity()); + } + this->m_selMeshes.insert(selMeshes.begin(),selMeshes.end()); + this->m_desPhrases = DesPhrases; + // TBD: broacast to attribute panel + emit broadcastToRenderView(selEntities, selMeshes, DesPhrases); + + } + + void qtSelectionManager::updateSelectedItems(const smtk::common::UUIDs + &selEntities) + { + this->clearAllSelections(); + this->m_selEntities.insert(selEntities.begin(), selEntities.end()); + // broadcast to model tree and render view + bool blocksignals = false; + emit broadcastToModelTree(this->m_selEntities,this->m_selMeshes, + blocksignals); + } + + void qtSelectionManager::clearAllSelections() + { + this->m_selEntities.clear(); + this->m_selMeshes.clear(); + this->m_desPhrases.clear(); + } + + + + }; // namespace extension + +}; // namespace smtk + diff --git a/smtk/extension/qt/qtSelectionManager.h b/smtk/extension/qt/qtSelectionManager.h new file mode 100644 index 0000000000000000000000000000000000000000..4840f8e08b5c3ca97ba44d6a845c1d176e9a5406 --- /dev/null +++ b/smtk/extension/qt/qtSelectionManager.h @@ -0,0 +1,82 @@ +//========================================================================= +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//========================================================================= + +// .NAME qtSelectionManager - The selection manager for smtk +// .SECTION Description +// .SECTION See Also + +#ifndef __smtk__extension_qtSelectionManager_h +#define __smtk__extension_qtSelectionManager_h + +#include "smtk/extension/qt/Exports.h" +#include "smtk/extension/qt/qtItem.h" + +#include "smtk/PublicPointerDefs.h" +#include "smtk/common/UUID.h" +#include "smtk/model/DescriptivePhrase.h" +#include "smtk/model/EntityRef.h" +#include "smtk/model/SessionRef.h" +#include "smtk/mesh/MeshSet.h" + +namespace smtk +{ + namespace extension + { + +class SMTKQTEXT_EXPORT qtSelectionManager : public QObject +{ + Q_OBJECT + public: + qtSelectionManager(); + void getSelectedEntities(smtk::common::UUIDs &selEntities); + void getSelectedMeshes(smtk::mesh::MeshSets &selMeshes); + + signals: + // Description + // Broadcast selection to model tree + // If you do not block signal, both tree and view would be updated + void broadcastToModelTree(const smtk::common::UUIDs & + selEntities, const smtk::mesh::MeshSets &selMeshes, bool blocksignals) const; + + // Description + // Broadcast selection to render view + void broadcastToRenderView(const smtk::model::EntityRefs& + selEntities, const smtk::mesh::MeshSets &selMeshes, + const smtk::model::DescriptivePhrases &DesPhrases) const; + public slots: + + // Description + // update selected items from rendering window + void updateSelectedItems(const smtk::common::UUIDs & + selEntities, const smtk::mesh::MeshSets &selMeshes); + + // Description + // update selected items from model tree + void updateSelectedItems(const smtk::model::EntityRefs& + selEntities, const smtk::mesh::MeshSets &selMeshes, + const smtk::model::DescriptivePhrases &DesPhrases); + + // Description + // update selected items from attribute + void updateSelectedItems(const smtk::common::UUIDs & selEntities); + + protected: + void clearAllSelections(); + smtk::mesh::MeshSets m_selMeshes; + smtk::common::UUIDs m_selEntities; + smtk::model::DescriptivePhrases m_desPhrases; + +}; + + }; // namespace extension + +}; // namespace smtk + +#endif diff --git a/smtk/mesh/testing/cxx/UnitTestReclassifyEdges.cxx b/smtk/mesh/testing/cxx/UnitTestReclassifyEdges.cxx index bfb3e5ba191a21fff3fd130ace7c9d64b305c4c7..843dd2b8a438c56c96330b14e40014b1fcfafea3 100644 --- a/smtk/mesh/testing/cxx/UnitTestReclassifyEdges.cxx +++ b/smtk/mesh/testing/cxx/UnitTestReclassifyEdges.cxx @@ -114,7 +114,7 @@ void add_model_edge_and_vert(smtk::model::ManagerPtr modelManager, smtk::model::Tessellation vertTess; vertTess.addCoords(0, 2, 0); vertTess.addPoint(0); - modelManager->setTessellation(nv.entity(), vertTess); + modelManager->setTessellationAndBoundingBox(nv.entity(), vertTess); ne = modelManager->addEdge(); @@ -127,7 +127,7 @@ void add_model_edge_and_vert(smtk::model::ManagerPtr modelManager, edgeTess.addCoords(3, 0, 0); edgeTess.addLine(0, 1); edgeTess.addLine(1, 2); - modelManager->setTessellation(ne.entity(), edgeTess); + modelManager->setTessellationAndBoundingBox(ne.entity(), edgeTess); break; } diff --git a/smtk/model/EntityRef.cxx b/smtk/model/EntityRef.cxx index e021acf6b97ad7f0fff5aa9463c83e98071ff1f9..0a2309dabdcd2c4578314ba97e48953a16527c8e 100644 --- a/smtk/model/EntityRef.cxx +++ b/smtk/model/EntityRef.cxx @@ -14,12 +14,15 @@ #include "smtk/model/Entity.h" #include "smtk/model/EntityRefArrangementOps.h" #include "smtk/model/Events.h" +#include "smtk/model/Face.h" #include "smtk/model/Group.h" #include "smtk/model/Manager.h" #include "smtk/model/Model.h" #include "smtk/model/Tessellation.h" +#include "smtk/model/Volume.h" #include +#include #include @@ -445,6 +448,108 @@ EntityRefs EntityRef::boundaryEntities(int ofDimension) const return result; } +std::vector EntityRef::boundingBox() const +{ + std::vector bBox, dummy; + // initialize the BBox, following VTK's rule + for (int i = 0; i < 6; i++) + { + double tmp = (i%2 == 1) ? -DBL_MAX : DBL_MAX; + bBox.push_back(tmp); + dummy.push_back(tmp); + } + + if (this->isCellEntity()) + { + // assume that only volume do not have boundingBox as float property + if (this->hasFloatProperty(SMTK_BOUNDING_BOX_PROP)) // vertex/edge/face + { + smtk::model::FloatList currentBBox(this->floatProperty(SMTK_BOUNDING_BOX_PROP)); + bBox = this->unionBoundingBox(bBox,currentBBox); + return bBox; + } + else + { + // loop over children and set bbox + EntityRefs children = this->boundaryEntities(this->dimension()-1); + for (EntityRefs::iterator child = children.begin(); + child != children.end(); ++child) + { + if (child->hasFloatProperty(SMTK_BOUNDING_BOX_PROP)) + {bBox = this->unionBoundingBox(bBox, + child->floatProperty(SMTK_BOUNDING_BOX_PROP));} + } + return bBox; + } + } + else if(this->isModel()) + { + smtk::model::Model model = this->as(); + if (!model.isValid()) + {return bBox;} + + // loop over cells and set bbox + CellEntities cellEnts = model.cells(); + for (CellEntities::iterator cellEnt = cellEnts.begin(); cellEnt != + cellEnts.end(); ++cellEnt) + { + if(cellEnt->isValid()) + {bBox = this->unionBoundingBox(bBox, cellEnt->boundingBox());} + } + // loop over submodels and set bbox + Models submodels = model.submodels(); + for (Models::iterator subModel = submodels.begin(); subModel != submodels.end(); + ++subModel) + { + if (subModel->isValid()) + {bBox = this->unionBoundingBox(bBox, subModel->boundingBox());} + } + return bBox; + + } + else if(this->isGroup()) + { + + + if (this->hasFloatProperty(SMTK_BOUNDING_BOX_PROP)) // exodus session + { + smtk::model::FloatList currentBBox(this->floatProperty(SMTK_BOUNDING_BOX_PROP)); + bBox = this->unionBoundingBox(bBox,currentBBox); + return bBox; + } + + smtk::model::Group group = this->as(); + EntityRefs members = group.members(); + for (EntityRefs::iterator member = members.begin(); member != members.end() + ; ++member) + { + if (member->isValid()) + { + bBox = this->unionBoundingBox(bBox, member->boundingBox()); + } + } + return bBox; + } + else + { + return dummy; + } + +} + +std::vector EntityRef::unionBoundingBox(const std::vector &b1, + const std::vector &b2) const +{ + std::vector resultBBox; + resultBBox.push_back(std::min(b1[0],b2[0])); + resultBBox.push_back(std::max(b1[1],b2[1])); + resultBBox.push_back(std::min(b1[2],b2[2])); + resultBBox.push_back(std::max(b1[3],b2[3])); + resultBBox.push_back(std::min(b1[4],b2[4])); + resultBBox.push_back(std::max(b1[5],b2[5])); + return resultBBox; + +} EntityRefs EntityRef::lowerDimensionalBoundaries(int lowerDimension) { EntityRefs result; @@ -641,7 +746,7 @@ int EntityRef::setTessellation(const Tessellation* tess, int analysisMesh) { int gen; try { - mgr->setTessellation(this->m_entity, *tess, analysisMesh, &gen); + mgr->setTessellationAndBoundingBox(this->m_entity, *tess, analysisMesh, &gen); } catch (std::string& badIdMsg) { (void)badIdMsg; return -1; diff --git a/smtk/model/EntityRef.h b/smtk/model/EntityRef.h index b5802f42c26e47e69d8cb9a62236a0e631d378a4..37be5ea252b0cd47d3c6a8762984acf53d40736f 100644 --- a/smtk/model/EntityRef.h +++ b/smtk/model/EntityRef.h @@ -165,6 +165,10 @@ public: EntityRefs bordantEntities(int ofDimension = -2) const; EntityRefs boundaryEntities(int ofDimension = -2) const; + std::vector boundingBox() const; + std::vector unionBoundingBox(const std::vector &b1, + const std::vector &b2) const; + EntityRefs lowerDimensionalBoundaries(int lowerDimension); EntityRefs higherDimensionalBordants(int higherDimension); EntityRefs adjacentEntities(int ofDimension); diff --git a/smtk/model/Manager.cxx b/smtk/model/Manager.cxx index 0a27afe75b36bfb80b56243fa71927d967893155..28f89f4a8a37cc2eacb1bb3e24bb7173fb193b9c 100644 --- a/smtk/model/Manager.cxx +++ b/smtk/model/Manager.cxx @@ -34,6 +34,7 @@ #include "smtk/model/VolumeUse.h" #include "smtk/mesh/Manager.h" +#include #include #include @@ -1980,7 +1981,7 @@ EntityRefArray Manager::findEntitiesOfType(BitFlags flags, bool exactMatch) return this->entitiesMatchingFlagsAs(flags, exactMatch); } -/**\brief Set the tessellation information for a given \a cellId. +/**\brief Set the tessellation information and for a given \a cellId. * * If \a analysis is non-zero (zero is the default), then the * Tessellation is treated as an analysis mesh, not a display @@ -2034,6 +2035,101 @@ Manager::tess_iter_type Manager::setTessellation( return result; } +/**\brief Set the tessellation information and bounding box for a given \a cellId. + * + * If \a analysis is non-zero (zero is the default), then the + * Tessellation is treated as an analysis mesh, not a display + * tessellation. + * + * Note that calling this method automatically sets or increments + * the integer-valued "_tessgen" property on \a cellId. + * This property enables fast display updates when only a few + * entity tessellations have changed. + * If \a generation is a non-NULL pointer (NULL is the default), + * then the new generation number of the Tessellation is stored at + * the address provided. + */ +Manager::tess_iter_type Manager::setTessellationAndBoundingBox( + const UUID& cellId, const Tessellation& geom, int analysis, int* generation) +{ + if (cellId.isNull()) + throw std::string("Nil cell ID"); + + smtk::shared_ptr storage; + const char* genProp; + if (!analysis) + { // store as display tessellation + storage = this->m_tessellations; + genProp = SMTK_TESS_GEN_PROP; + } + else + { // store as analysis mesh + storage = this->m_analysisMesh; + genProp = SMTK_MESH_GEN_PROP; + } + + tess_iter_type result = storage->find(cellId); + if (result == storage->end()) + { + std::pair blank; + blank.first = cellId; + result = storage->insert(blank).first; + } + result->second = geom; + + // Now set or increment the generation number. + IntegerList& gen(this->integerProperty(cellId, genProp)); + if (gen.empty()) + gen.push_back(0); + else + ++gen[0]; + if (generation) + *generation = gen[0]; + + // Set/upate the bBox + this->setBoundingBox(cellId, geom.coords()); + return result; +} + +/**\brief set the bounding box of a model entity given \a entityId and \a coords. + * + * if provided bBox, we would just use the coords as bBox + * + * Returns true when a real bBox is set and false otherwise. + */ +bool Manager::setBoundingBox(const UUID &cellId, const std::vector &coords, int providedbBox) +{ + smtk::model::FloatList bBox; + if (providedbBox) + { + this->setFloatProperty(cellId, SMTK_BOUNDING_BOX_PROP, coords); + return true; + } + else // calculate boundingBox + { + if (coords.size() == 0) + {return false;} // nothing to set + // initialize the bBox + for (int i = 0; i < 6; i++) + { + double tmp = (i%2 == 1) ? -DBL_MAX : DBL_MAX; + bBox.push_back(tmp); + } + std::vector::size_type pointSize = coords.size()/3; + for (size_t i = 0; i < pointSize ; ++i) + { + bBox[0] = std::min(bBox[0], coords[3*i]); + bBox[1] = std::max(bBox[1], coords[3*i]); + bBox[2] = std::min(bBox[2], coords[3*i + 1]); + bBox[3] = std::max(bBox[3], coords[3*i + 1]); + bBox[4] = std::min(bBox[4], coords[3*i + 2]); + bBox[5] = std::max(bBox[5], coords[3*i + 2]); + } + this->setFloatProperty(cellId, SMTK_BOUNDING_BOX_PROP, bBox); + return true; + } +} + /**\brief Remove the tessellation of the given \a entityId. * * If the second argument is true, also remove the integer "generation number" diff --git a/smtk/model/Manager.h b/smtk/model/Manager.h index 87616ec639f3de71386bb20fc685a3e8b811216a..7434ec39b6ee2304812a7e8210e9c106cc5b614f 100644 --- a/smtk/model/Manager.h +++ b/smtk/model/Manager.h @@ -63,7 +63,7 @@ /**\brief The name of an integer property used to store mesh Tessellation generation numbers. * - * \sa SMTK_TESS_GEN_PROP + * \sa SMTK_MESH_GEN_PROP */ #define SMTK_MESH_GEN_PROP "_meshgen" @@ -73,6 +73,12 @@ */ #define SMTK_GEOM_STYLE_PROP "_geomstyle" +/**\brief The name of an float property used to store the bounding box of a model entity + * + * \sa SMTK_BOUNDING_BOX_PROP + */ +#define SMTK_BOUNDING_BOX_PROP "_boundingBox" + namespace smtk { namespace model { @@ -256,6 +262,16 @@ public: const Tessellation& geom, int analysis = 0, int* gen = NULL); + + tess_iter_type setTessellationAndBoundingBox( + const smtk::common::UUID& cellId, + const Tessellation& geom, + int analysis = 0, + int* gen = NULL); + // if BBox is provided, just replace corrds with BBox else we would loop through coords + // BBox format: [xmin, xmax, ymin, ymax, zmin, zmax] + bool setBoundingBox(const smtk::common::UUID& cellId, + const std::vector & coords, int providedBBox = 0); bool removeTessellation(const smtk::common::UUID& cellId, bool removeGen = false); int arrangeEntity(const smtk::common::UUID& entityId, ArrangementKind, const Arrangement& arr, int index = -1); diff --git a/smtk/model/pybind11/PybindEntityRef.h b/smtk/model/pybind11/PybindEntityRef.h index 40d3d97bd3f889492d1338c5e22bc98515d8bd20..a134cb9f207bcd86fc9fe07a6edf60274cd4f3e3 100644 --- a/smtk/model/pybind11/PybindEntityRef.h +++ b/smtk/model/pybind11/PybindEntityRef.h @@ -49,6 +49,8 @@ py::class_< smtk::model::EntityRef > pybind11_init_smtk_model_EntityRef(py::modu .def("attributes", &smtk::model::EntityRef::attributes) .def("bordantEntities", &smtk::model::EntityRef::bordantEntities, py::arg("ofDimension") = -2) .def("boundaryEntities", &smtk::model::EntityRef::boundaryEntities, py::arg("ofDimension") = -2) + .def("boundingBox", &smtk::model::EntityRef::boundingBox) + .def("unionBoundingBox", &smtk::model::EntityRef::unionBoundingBox, py::arg("b1"), py::arg("b2")) // .def("checkForArrangements", &smtk::model::EntityRef::checkForArrangements, py::arg("k"), py::arg("entry"), py::arg("arr")) .def("classname", &smtk::model::EntityRef::classname) .def("clearArrangements", &smtk::model::EntityRef::clearArrangements) diff --git a/smtk/model/pybind11/PybindManager.h b/smtk/model/pybind11/PybindManager.h index 6c7f285122b1bfa2158fbf1e3b8543a47769db52..1682a5e76580a02a7c90cbeb600e690aa16e37a5 100644 --- a/smtk/model/pybind11/PybindManager.h +++ b/smtk/model/pybind11/PybindManager.h @@ -221,7 +221,9 @@ PySharedPtrClass< smtk::model::Manager > pybind11_init_smtk_model_Manager(py::mo .def("setShell", (smtk::model::Shell (smtk::model::Manager::*)(::smtk::common::UUID const &, ::smtk::model::Shell const &)) &smtk::model::Manager::setShell, py::arg("uid"), py::arg("parent")) .def("setStringProperty", (void (smtk::model::Manager::*)(::smtk::common::UUID const &, ::std::string const &, ::smtk::model::String const &)) &smtk::model::Manager::setStringProperty, py::arg("entity"), py::arg("propName"), py::arg("propValue")) .def("setStringProperty", (void (smtk::model::Manager::*)(::smtk::common::UUID const &, ::std::string const &, ::smtk::model::StringList const &)) &smtk::model::Manager::setStringProperty, py::arg("entity"), py::arg("propName"), py::arg("propValue")) - .def("setTessellation", &smtk::model::Manager::setTessellation, py::arg("cellId"), py::arg("geom"), py::arg("analysis") = 0, py::arg("gen") = nullptr) + .def("setTessellation", &smtk::model::Manager::setTessellationAndBoundingBox, py::arg("cellId"), py::arg("geom"), py::arg("analysis") = 0, py::arg("gen") = nullptr) + .def("setTessellationAndBoundingBox", &smtk::model::Manager::setTessellationAndBoundingBox, py::arg("cellId"), py::arg("geom"), py::arg("analysis") = 0, py::arg("gen") = nullptr) + .def("setBoundingBox", &smtk::model::Manager::setBoundingBox, py::arg("cellId"), py::arg("coords"), py::arg("providedBBox") = 0) .def("setVertexUse", &smtk::model::Manager::setVertexUse, py::arg("uid"), py::arg("src"), py::arg("sense")) .def("setVolumeUse", &smtk::model::Manager::setVolumeUse, py::arg("uid"), py::arg("src")) .def_static("shortUUIDName", &smtk::model::Manager::shortUUIDName, py::arg("uid"), py::arg("entityFlags")) diff --git a/smtk/model/testing/cxx/helpers.cxx b/smtk/model/testing/cxx/helpers.cxx index 16bea09a3e11fcbcc47aef256403a7bdfc2aa74b..6a09ce74c84b88c2b442502621017117f41b23ef 100644 --- a/smtk/model/testing/cxx/helpers.cxx +++ b/smtk/model/testing/cxx/helpers.cxx @@ -114,7 +114,7 @@ UUIDArray createTet(smtk::model::ManagerPtr sm) .pushRelation(uc19) .pushRelation(uc20))->first; - sm->setTessellation(uc21, Tessellation() + sm->setTessellationAndBoundingBox(uc21, Tessellation() .addCoords(x[0][0], x[0][1], x[0][2]) .addCoords(x[1][0], x[1][1], x[1][2]) .addCoords(x[2][0], x[2][1], x[2][2]) @@ -160,7 +160,7 @@ UUIDArray createTet(smtk::model::ManagerPtr sm) // Add point coordinates for (int i = 0; i < 7; ++i) { - sm->setTessellation(uids[i],Tessellation().addCoords(x[i][0], x[i][1], x[i][2])); + sm->setTessellationAndBoundingBox(uids[i],Tessellation().addCoords(x[i][0], x[i][1], x[i][2])); } // Create vertex-uses diff --git a/smtk/typesystem.xml b/smtk/typesystem.xml index 119eed07fa062d137285810fb937717d8abbde66..7e86e08907c151999c64f3067d17acb9759dfde0 100644 --- a/smtk/typesystem.xml +++ b/smtk/typesystem.xml @@ -103,6 +103,7 @@ + @@ -1026,6 +1027,15 @@ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + smtk::model::Manager::tess_iter_type i = %CPPSELF->get()->setTessellationAndBoundingBox(%1, %2); + %RETURN_TYPE %0 = *i; + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + +