]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Fix for the issue 1526: optimization of isConnectedTopology calls
authormpv <mpv@opencascade.com>
Mon, 30 May 2016 07:32:51 +0000 (10:32 +0300)
committermpv <mpv@opencascade.com>
Mon, 30 May 2016 07:32:51 +0000 (10:32 +0300)
src/GeomAPI/GeomAPI_Shape.cpp
src/Model/Model_ResultBody.cpp
src/Model/Model_ResultBody.h
src/ModelAPI/ModelAPI_ResultBody.cpp
src/ModelAPI/ModelAPI_ResultBody.h
src/PartSet/PartSet_IconFactory.cpp

index 0ee2a087c67a17b2d790f8e8b4df1b12d5a89255..43627a1dd56a1281fadcec7db90295ec647be12c 100644 (file)
@@ -131,15 +131,21 @@ bool GeomAPI_Shape::isConnectedTopology() const
     NCollection_List<TopoDS_Shape> aNew; // very new connected to new connected
     NCollection_List<TopoDS_Shape>::Iterator aNotIter(aNotConnected);
     while(aNotIter.More()) {
+      // optimization to avoid TopExp_Explorer double-cycle, collect all vertices in the list first
+      NCollection_List<TopoDS_Shape> aNotVertices;
+      for(TopExp_Explorer anExp1(aNotIter.Value(), TopAbs_VERTEX); anExp1.More(); anExp1.Next()) {
+        aNotVertices.Append(anExp1.Current());
+      }
+
       bool aConnected =  false;
       NCollection_List<TopoDS_Shape>::Iterator aNewIter(aNewConnected);
       for(; !aConnected && aNewIter.More(); aNewIter.Next()) {
         // checking topological connecion of aNotIter and aNewIter (if shapes are connected, vertices are connected for sure)
-        TopExp_Explorer anExp1(aNotIter.Value(), TopAbs_VERTEX);
-        for(; !aConnected && anExp1.More(); anExp1.Next()) {
-          TopExp_Explorer anExp2(aNewIter.Value(), TopAbs_VERTEX);
-          for(; anExp2.More(); anExp2.Next()) {
-            if (anExp1.Current().IsSame(anExp2.Current())) {
+        TopExp_Explorer anExp2(aNewIter.Value(), TopAbs_VERTEX);
+        for(; !aConnected && anExp2.More(); anExp2.Next()) {
+          NCollection_List<TopoDS_Shape>::Iterator aNotIter(aNotVertices);
+          for(; aNotIter.More(); aNotIter.Next()) {
+            if (aNotIter.Value().IsSame(anExp2.Current())) {
               aConnected = true;
               break;
             }
index 5fb26d84309209720f6c8689237aa89c7e4aa759..714d984e8e49e631abd123e79fa6304c49354d61 100644 (file)
@@ -19,6 +19,7 @@ Model_ResultBody::Model_ResultBody()
 {
   myBuilder = new Model_BodyBuilder(this);
   myWasConcealed = false;
+  myConnect = ConnectionNotComputed;
 }
 
 void Model_ResultBody::initAttributes()
index bbb23da35ed80a810fa26396569f16852fe75baf..be5ac8e1dba9c7eae478450aacd1654c94559e0f 100644 (file)
@@ -32,6 +32,7 @@ class Model_ResultBody : public ModelAPI_ResultBody
   /// Flag that stores the previous state of "concealed": if it is changed,
   /// The event is used to redisplay the body.
   bool myWasConcealed;
+
 public:
   /// Request for initialization of data model of the result: adding all attributes
   virtual void initAttributes();
index 6792f18bc335dd0bdc7c07b89e9aad0468e7a60e..bdf9947d2f93324f8e75c1c3bfd55a2bd343739b 100644 (file)
@@ -12,6 +12,7 @@
 ModelAPI_ResultBody::ModelAPI_ResultBody()
 : myBuilder(0)
 {
+  myConnect = ConnectionNotComputed;
 }
 
 ModelAPI_ResultBody::~ModelAPI_ResultBody()
@@ -29,6 +30,7 @@ void ModelAPI_ResultBody::store(const std::shared_ptr<GeomAPI_Shape>& theShape,
                                 const bool theIsStoreSameShapes)
 {
   myBuilder->store(theShape, theIsStoreSameShapes);
+  myConnect = ConnectionNotComputed;
 
   static Events_Loop* aLoop = Events_Loop::loop();
   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
@@ -40,6 +42,7 @@ void ModelAPI_ResultBody::storeGenerated(const std::shared_ptr<GeomAPI_Shape>& t
                                  const std::shared_ptr<GeomAPI_Shape>& theToShape)
 {
   myBuilder->storeGenerated(theFromShape, theToShape);
+  myConnect = ConnectionNotComputed;
 
   static Events_Loop* aLoop = Events_Loop::loop();
   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
@@ -52,6 +55,7 @@ void ModelAPI_ResultBody::storeModified(const std::shared_ptr<GeomAPI_Shape>& th
                             const int theDecomposeSolidsTag)
 {
   myBuilder->storeModified(theOldShape, theNewShape, theDecomposeSolidsTag);
+  myConnect = ConnectionNotComputed;
 
   static Events_Loop* aLoop = Events_Loop::loop();
   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
@@ -62,6 +66,7 @@ void ModelAPI_ResultBody::storeModified(const std::shared_ptr<GeomAPI_Shape>& th
 void ModelAPI_ResultBody::storeWithoutNaming(const std::shared_ptr<GeomAPI_Shape>& theShape)
 {
   myBuilder->storeWithoutNaming(theShape);
+  myConnect = ConnectionNotComputed;
 
   static Events_Loop* aLoop = Events_Loop::loop();
   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
@@ -142,3 +147,11 @@ void ModelAPI_ResultBody::loadDisconnectedVertexes(std::shared_ptr<GeomAPI_Shape
 {
   myBuilder->loadDisconnectedVertexes(theShape, theName, theTag);
 }
+
+bool ModelAPI_ResultBody::isConnectedTopology()
+{
+  if (myConnect == ConnectionNotComputed) {
+    myConnect = shape()->isConnectedTopology() ? IsConnected : IsNotConnected;
+  }
+  return myConnect == IsConnected;
+}
index ad5846e0f10a84927141a7b1f729b954c35d2bad..119978c6f5a896a0cc24f2c2259f6344be9f1471 100644 (file)
@@ -44,6 +44,15 @@ public:
     return RESULT_BODY_COLOR;
   }
 
+  /// Iternal enumeration for storage the information of connected topology flag
+  enum ConnectedTopologyFlag {
+    ConnectionNotComputed, ///< not yet computed
+    IsConnected,           ///< the topology is connected
+    IsNotConnected         ///< the topology is connected
+  };
+  /// Keeps (not persistently) the connected topology flag
+  ConnectedTopologyFlag myConnect;
+
   /// \brief Stores the shape (called by the execution method).
   /// param[in] theShape shape to store.
   /// param[in] theIsStoreSameShapes if false stores reference to the same shape if it is already in document.
@@ -118,6 +127,10 @@ public:
   // is equal to the given shape
   MODELAPI_EXPORT virtual bool isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape) = 0;
 
+  /// Returns true is the topology is connected. Cashes this information for the current shape,
+  /// so it is more effective to use this method than directly GeomAPI_Shape.
+  MODELAPI_EXPORT virtual bool isConnectedTopology();
+
 protected:
   /// Default constructor accessible only from Model_Objects
   MODELAPI_EXPORT ModelAPI_ResultBody();
index 2beae8cc10aeb6646be0bc8fb87daefded454a96..1636a6ca234bf5c34ce2b8c8edeb4c3c7de0cea9 100644 (file)
@@ -79,8 +79,12 @@ QIcon PartSet_IconFactory::getIcon(ObjectPtr theObj)
     GeomShapePtr aShape = aResult->shape();
     if(aShape.get()) {
       switch(aShape->shapeType()) {
-        case GeomAPI_Shape::COMPOUND:  return aShape->isConnectedTopology() ?
-                QIcon(":pictures/compoundofsolids.png") : QIcon(":pictures/compound.png");
+        case GeomAPI_Shape::COMPOUND: {
+          ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
+          if (aBody.get() && aBody->isConnectedTopology())
+            return QIcon(":pictures/compoundofsolids.png");
+          return QIcon(":pictures/compound.png");
+        }
         case GeomAPI_Shape::COMPSOLID: return QIcon(":pictures/compsolid.png");
         case GeomAPI_Shape::SOLID:     return QIcon(":pictures/solid.png");
         case GeomAPI_Shape::SHELL:     return QIcon(":pictures/shell.png");