]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #3087: Show remaining DoFs highlight not all features
authorazv <azv@opencascade.com>
Tue, 26 Nov 2019 16:03:03 +0000 (19:03 +0300)
committerazv <azv@opencascade.com>
Tue, 26 Nov 2019 16:03:28 +0000 (19:03 +0300)
Find all parameters coincident to the returned by PlaneGCS.

src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/Test/Test3087_1.py [new file with mode: 0644]
src/SketchPlugin/Test/Test3087_2.py [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp

index 199149f69c9cc6a6aa44669f8bd5eae722717892..c660b7aeb3ffad83dbcdf0577fd387857bb26390 100644 (file)
@@ -203,6 +203,8 @@ ADD_UNIT_TESTS(
   Test2860.py
   Test2894.py
   Test3019.py
+  Test3087_1.py
+  Test3087_2.py
   TestArcBehavior.py
   TestChangeSketchPlane1.py
   TestChangeSketchPlane2.py
diff --git a/src/SketchPlugin/Test/Test3087_1.py b/src/SketchPlugin/Test/Test3087_1.py
new file mode 100644 (file)
index 0000000..92a0fe4
--- /dev/null
@@ -0,0 +1,63 @@
+# Copyright (C) 2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+from EventsAPI import *
+from ModelAPI import *
+
+class FreeShapesListener(EventsAPI.Events_Listener):
+    def __init__(self):
+        Events_Listener.__init__(self)
+        # register as a listener
+        Events_Loop.loop().registerListener(self, Events_Loop.eventByName("DoFObjects"))
+        self.myEventProcessed = False
+
+    def __del__(self):
+        Events_Loop.loop().removeListener(self)
+
+    def processEvent(self, theMessage):
+        message = messageToUpdatedMessage(theMessage)
+        objs = message.objects()
+        assert(len(objs) == 3)
+        self.myEventProcessed = True
+
+
+if __name__ == "__main__":
+    # create the listener
+    listener = FreeShapesListener()
+
+    model.begin()
+    partSet = model.moduleDocument()
+    Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+    SketchLine_1 = Sketch_1.addLine(10, 10, -10, 10)
+    SketchLine_2 = Sketch_1.addLine(-10, 10, -10, -10)
+    SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+    SketchLine_3 = Sketch_1.addLine(-10, -10, 10, -10)
+    SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+    SketchConstraintRigid_1 = Sketch_1.setFixed(SketchLine_1.startPoint())
+    SketchConstraintRigid_2 = Sketch_1.setFixed(SketchLine_3.endPoint())
+    model.end()
+
+    # send message to find the free shapes in the sketch
+    event = Events_Loop.eventByName("GetDoFObjects")
+    ModelAPI_EventCreator.get().sendUpdated(Sketch_1.feature(), event);
+    Events_Loop.loop().flush(event);
+
+    assert(listener.myEventProcessed)
diff --git a/src/SketchPlugin/Test/Test3087_2.py b/src/SketchPlugin/Test/Test3087_2.py
new file mode 100644 (file)
index 0000000..4fb18ea
--- /dev/null
@@ -0,0 +1,66 @@
+# Copyright (C) 2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+from EventsAPI import *
+from ModelAPI import *
+
+class FreeShapesListener(EventsAPI.Events_Listener):
+    def __init__(self):
+        Events_Listener.__init__(self)
+        # register as a listener
+        Events_Loop.loop().registerListener(self, Events_Loop.eventByName("DoFObjects"))
+        self.myEventProcessed = False
+
+    def __del__(self):
+        Events_Loop.loop().removeListener(self)
+
+    def processEvent(self, theMessage):
+        message = messageToUpdatedMessage(theMessage)
+        objs = message.objects()
+        assert(len(objs) == 4)
+        self.myEventProcessed = True
+
+
+if __name__ == "__main__":
+    # create the listener
+    listener = FreeShapesListener()
+
+    model.begin()
+    partSet = model.moduleDocument()
+    Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+    SketchLine_1 = Sketch_1.addLine(10, 10, -10, 10)
+    SketchLine_2 = Sketch_1.addLine(-10, 10, -10, -10)
+    SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+    SketchLine_3 = Sketch_1.addLine(-10, -10, 10, -10)
+    SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+    SketchConstraintRigid_1 = Sketch_1.setFixed(SketchLine_1.startPoint())
+    SketchConstraintRigid_2 = Sketch_1.setFixed(SketchLine_3.endPoint())
+    SketchCircle_1 = Sketch_1.addCircle(-10, 10, 10)
+    SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchCircle_1.center())
+    SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 10)
+    model.end()
+
+    # send message to find the free shapes in the sketch
+    event = Events_Loop.eventByName("GetDoFObjects")
+    ModelAPI_EventCreator.get().sendUpdated(Sketch_1.feature(), event);
+    Events_Loop.loop().flush(event);
+
+    assert(listener.myEventProcessed)
index 30b12ec7b20b962c9249f8da229c66e1dad2675a..716022c9865700605a7f480187bc1fff6dfc4e76 100644 (file)
@@ -243,10 +243,10 @@ void PlaneGCSSolver_Solver::diagnose(const GCS::Algorithm& theAlgo)
   myDiagnoseBeforeSolve = false;
 }
 
-void PlaneGCSSolver_Solver::getFreeParameters(GCS::VEC_pD& theFreeParams)
+void PlaneGCSSolver_Solver::getFreeParameters(GCS::SET_pD& theFreeParams)
 {
   if (myConstraints.empty())
-    theFreeParams = myParameters;
+    theFreeParams.insert(myParameters.begin(), myParameters.end());
   else {
     GCS::VEC_pD aParametersCopy = myParameters;
     ConstraintMap aConstraintCopy = myConstraints;
@@ -263,10 +263,77 @@ void PlaneGCSSolver_Solver::getFreeParameters(GCS::VEC_pD& theFreeParams)
     GCS::QRAlgorithm aQRAlgo = myEquationSystem->qrAlgorithm;
     myEquationSystem->qrAlgorithm = GCS::EigenDenseQR;
     diagnose();
-    myEquationSystem->getDependentParams(theFreeParams);
+    GCS::VEC_pD aFreeParams;
+    myEquationSystem->getDependentParams(aFreeParams);
+    theFreeParams.insert(aFreeParams.begin(), aFreeParams.end());
     // revert QR decomposition algorithm
     myEquationSystem->qrAlgorithm = aQRAlgo;
   }
+
+  if (theFreeParams.empty())
+    return;
+
+  // find all equal parameters too
+  struct EqualParameters
+  {
+    typedef std::map<double*, std::list<GCS::SET_pD>::iterator> MapParamGroup;
+
+    std::list<GCS::SET_pD> myEqualParams;
+    MapParamGroup myGroups;
+
+    void add(double* theParam1, double* theParam2)
+    {
+      MapParamGroup::iterator aFound1 = myGroups.find(theParam1);
+      MapParamGroup::iterator aFound2 = myGroups.find(theParam2);
+
+      if (aFound1 == myGroups.end()) {
+        if (aFound2 == myGroups.end()) {
+          // create new group
+          myEqualParams.push_back(GCS::SET_pD());
+          std::list<GCS::SET_pD>::iterator aGroup = --myEqualParams.end();
+          aGroup->insert(theParam1);
+          aGroup->insert(theParam2);
+          myGroups[theParam1] = aGroup;
+          myGroups[theParam2] = aGroup;
+        }
+        else {
+          // add first parameter to the second group
+          aFound2->second->insert(theParam1);
+          myGroups[theParam1] = aFound2->second;
+        }
+      }
+      else {
+        if (aFound2 == myGroups.end()) {
+          // add second parameter to the first group
+          aFound1->second->insert(theParam2);
+          myGroups[theParam2] = aFound1->second;
+        }
+        else if (aFound1 != aFound2) {
+          // merge two groups
+          GCS::SET_pD aCopy = *(aFound2->second);
+          myEqualParams.erase(aFound2->second);
+          for (GCS::SET_pD::iterator anIt = aCopy.begin(); anIt != aCopy.end(); ++anIt)
+            myGroups[*anIt] = aFound1->second;
+          aFound1->second->insert(aCopy.begin(), aCopy.end());
+        }
+      }
+    }
+  } anEqualParams;
+
+  for (ConstraintMap::iterator anIt = myConstraints.begin(); anIt != myConstraints.end(); ++anIt)
+    for (std::list<GCSConstraintPtr>::iterator aCIt = anIt->second.begin();
+         aCIt != anIt->second.end(); ++aCIt) {
+      if ((*aCIt)->getTypeId() == GCS::Equal)
+        anEqualParams.add((*aCIt)->params()[0], (*aCIt)->params()[1]);
+    }
+
+  GCS::SET_pD aFreeParamsCopy = theFreeParams;
+  for (GCS::SET_pD::iterator anIt = aFreeParamsCopy.begin();
+       anIt != aFreeParamsCopy.end(); ++anIt) {
+    EqualParameters::MapParamGroup::iterator aFound = anEqualParams.myGroups.find(*anIt);
+    if (aFound != anEqualParams.myGroups.end())
+      theFreeParams.insert(aFound->second->begin(), aFound->second->end());
+  }
 }
 
 void PlaneGCSSolver_Solver::addFictiveConstraintIfNecessary()
index 290136b25cec55f58eaacc0864ababe7afa8dbc1..96c198dbb0fb85d2969485ae8c2381c520a310d6 100644 (file)
@@ -80,7 +80,7 @@ public:
   void diagnose(const GCS::Algorithm& theAlgo = GCS::DogLeg);
 
   /// \brief Return the list of modifiable parameters
-  void getFreeParameters(GCS::VEC_pD& theFreeParams);
+  void getFreeParameters(GCS::SET_pD& theFreeParams);
 
   /// \brief Degrees of freedom
   int dof();
index 833e1535284015a86aaa0d9d9d4f9c9aad0b528c..a5788f23a82f8e37224d769a52f4c91cf07bc89e 100644 (file)
@@ -658,25 +658,20 @@ PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Storage::checkDegeneratedGeome
 
 void PlaneGCSSolver_Storage::getUnderconstrainedGeometry(std::set<ObjectPtr>& theFeatures) const
 {
-  std::vector<double*> aFreeParams;
+  std::set<double*> aFreeParams;
   mySketchSolver->getFreeParameters(aFreeParams);
   if (aFreeParams.empty())
     return;
 
-  std::map<double*, FeaturePtr> aParamOfFeatures;
   for (std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
        aFIt != myFeatureMap.end(); ++aFIt) {
     if (!aFIt->second)
       continue;
     GCS::SET_pD aParams = PlaneGCSSolver_Tools::parameters(aFIt->second);
     for (GCS::SET_pD::iterator aPIt = aParams.begin(); aPIt != aParams.end(); ++aPIt)
-      aParamOfFeatures[*aPIt] = aFIt->first;
-  }
-
-  for (std::vector<double*>::iterator anIt = aFreeParams.begin();
-       anIt != aFreeParams.end(); ++anIt) {
-    std::map<double*, FeaturePtr>::iterator aFound = aParamOfFeatures.find(*anIt);
-    if (aFound != aParamOfFeatures.end())
-      theFeatures.insert(aFound->second);
+      if (aFreeParams.find(*aPIt) != aFreeParams.end()) {
+        theFeatures.insert(aFIt->first);
+        break;
+      }
   }
 }