]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Dump with geometrical selection
authorazv <azv@opencascade.com>
Fri, 17 Aug 2018 11:59:37 +0000 (14:59 +0300)
committerazv <azv@opencascade.com>
Thu, 30 Aug 2018 08:39:19 +0000 (11:39 +0300)
Fix the selection of the "older" shape: if there are several shapes in the history, which satisfy the selected point criteria, but the selected one is not the last one.

src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelectionList.cpp
src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp
src/ModelGeomAlgo/ModelGeomAlgo_Shape.h
src/ModelHighAPI/CMakeLists.txt
src/ModelHighAPI/ModelHighAPI_Dumper.cpp
src/ModelHighAPI/ModelHighAPI_Tools.cpp

index 31bc8a0cf190506bd87e8920bf56c4fcb9958d2a..787cc116f1e5157935113c841030387f421f56da 100644 (file)
@@ -36,9 +36,9 @@
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
+#include <ModelGeomAlgo_Shape.h>
 #include <Events_InfoMessage.h>
 #include <GeomAPI_Edge.h>
-#include <GeomAPI_PlanarEdges.h>
 #include <GeomAPI_Pnt.h>
 #include <GeomAPI_Vertex.h>
 #include <GeomAlgoAPI_CompoundBuilder.h>
@@ -1067,43 +1067,35 @@ void Model_AttributeSelection::selectSubShape(
   reset();
 }
 
-
-// Check the point is within shape's bounding box
-static bool isPointWithinBB(const GeomPointPtr& thePoint, const GeomShapePtr& theShape)
-{
-  double aXMin, aXMax, aYMin, aYMax, aZMin, aZMax;
-  theShape->computeSize(aXMin, aYMin, aZMin, aXMax, aYMax, aZMax);
-  return thePoint->x() >= aXMin - Precision::Confusion() &&
-         thePoint->x() <= aXMax + Precision::Confusion() &&
-         thePoint->y() >= aYMin - Precision::Confusion() &&
-         thePoint->y() <= aYMax + Precision::Confusion() &&
-         thePoint->z() >= aZMin - Precision::Confusion() &&
-         thePoint->z() <= aZMax + Precision::Confusion();
-}
-
-// Select sub-shape of the given type, which contains the given point
-static GeomShapePtr findSubShape(const GeomShapePtr& theShape,
-                                 const GeomAPI_Shape::ShapeType& theType,
-                                 const GeomPointPtr& thePoint)
-{
-  std::list<GeomShapePtr> aSubs = theShape->subShapes(theType);
-  for (std::list<GeomShapePtr>::const_iterator aSubIt = aSubs.begin();
-    aSubIt != aSubs.end(); ++aSubIt) {
-    if ((*aSubIt)->middlePoint()->distance(thePoint) < Precision::Confusion())
-      return *aSubIt;
-  }
-
-  // not found
-  return GeomShapePtr();
-}
-
 void Model_AttributeSelection::selectSubShape(const std::string& theType,
                                               const GeomPointPtr& thePoint)
 {
   if (theType.empty() || !thePoint)
     return;
 
+  int aSelectionIndex = 0;
   GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::shapeTypeByStr(theType);
+  if (aType == GeomAPI_Shape::SHAPE) {
+    // possibly, the string consists of the type and the index,
+    // thus, try to separate them
+    size_t aUndersporePos = theType.find_first_of('_');
+    if (aUndersporePos != std::string::npos)
+      aType = GeomAPI_Shape::shapeTypeByStr(theType.substr(0, aUndersporePos));
+
+    if (aType != GeomAPI_Shape::SHAPE) {
+      for (std::string::const_iterator aChar = theType.begin() + aUndersporePos + 1;
+           aChar != theType.end(); ++aChar) {
+        if (std::isdigit(*aChar))
+          aSelectionIndex = aSelectionIndex * 10 + (*aChar - '0');
+        else {
+          aSelectionIndex = 1;
+          break;
+        }
+      }
+      aSelectionIndex -= 1;
+    }
+  }
+  ResultPtr aFoundResult;
   GeomShapePtr aFoundSubShape;
 
   // collect features from PartSet and the current part
@@ -1131,50 +1123,13 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType,
     if (isSubOfComposite)
       continue;
 
-    // process results of the current feature
-    const std::list<ResultPtr>& aResults = (*anIt)->results();
-    for (std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
-         aResIt != aResults.end(); ++aResIt) {
-      GeomShapePtr aCurShape = (*aResIt)->shape();
-      // first of all, check the point is within bounding box of the result
-      if (!aCurShape || !isPointWithinBB(thePoint, aCurShape))
-        continue;
-      // now, process all sub-shapes of the given type and check their inner points,
-      // but skip the case the selected type is COMPOUND and the shape is a list of sketch edges
-      // (it will be processed later)
-      std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
-          std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aCurShape);
-      if (aType != GeomAPI_Shape::COMPOUND || !aSketchEdges)
-        aFoundSubShape = findSubShape(aCurShape, aType, thePoint);
-      if (aFoundSubShape) {
-        setValue(*aResIt, aFoundSubShape);
-        return;
-      }
-
-      // special case for ResultConstruction if the FACE is selected
-      ResultConstructionPtr aResConstr =
-          std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIt);
-      if (aResConstr && aType >= GeomAPI_Shape::FACE) {
-        int aNbFaces = aResConstr->facesNum();
-        for (int aFaceInd = 0; aFaceInd < aNbFaces; ++aFaceInd) {
-          GeomFacePtr aCurFace = aResConstr->face(aFaceInd);
-          // check the point is within bounding box of the face
-          if (!isPointWithinBB(thePoint, aCurFace))
-            continue;
-          aFoundSubShape = findSubShape(aCurFace, aType, thePoint);
-          if (aFoundSubShape) {
-            setValue(*aResIt, aFoundSubShape);
-            return;
-          }
-        }
-      }
-
-      // next special case: the full sketch is selected
-      // the selection type is a COMPOUND
-      if (aSketchEdges &&
-          aSketchEdges->middlePoint()->distance(thePoint) < Precision::Confusion()) {
-        // select whole result
-        setValue(*aResIt, GeomShapePtr());
+    // process results of the current feature to find appropriate sub-shape
+    if (ModelGeomAlgo_Shape::findSubshapeByPoint(*anIt, thePoint, aType,
+                                                 aFoundResult, aFoundSubShape)) {
+      if (aSelectionIndex > 0)
+        --aSelectionIndex; // skip this shape, because one of the previous is selected
+      else {
+        setValue(aFoundResult, aFoundSubShape);
         return;
       }
     }
index c7e852221b97f19e24806334046fffb993baa8b5..7575ca2f91bb0237a965e3d38927b3fb5dc1f96b 100644 (file)
@@ -110,6 +110,8 @@ void Model_AttributeSelectionList::append(const GeomPointPtr& thePoint, const st
   aNewAttr->setID(id());
   mySize->Set(aNewTag);
   aNewAttr->selectSubShape(theType, thePoint);
+  if (selectionType().empty())
+    setSelectionType(aNewAttr->value()->shapeTypeStr());
   owner()->data()->sendAttributeUpdated(this);
 }
 
index f93dd9e48c77e706ac7e54085ca0869e6bdf7a20..ca7809b3906a09014590f8416afec48dec5d93d5 100644 (file)
 
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Result.h>
+#include <ModelAPI_ResultConstruction.h>
+
+#include <GeomAPI_PlanarEdges.h>
+#include <GeomAPI_Pnt.h>
 
 
 #ifdef WIN32
@@ -46,4 +50,95 @@ namespace ModelGeomAlgo_Shape
         theShapeResults.insert(aResult);
     }
   }
+
+  // Check the point is within shape's bounding box
+  static bool isPointWithinBB(const GeomPointPtr& thePoint,
+                              const GeomShapePtr& theShape,
+                              const double theTolerance)
+  {
+    double aXMin, aXMax, aYMin, aYMax, aZMin, aZMax;
+    theShape->computeSize(aXMin, aYMin, aZMin, aXMax, aYMax, aZMax);
+    return thePoint->x() >= aXMin - theTolerance && thePoint->x() <= aXMax + theTolerance &&
+           thePoint->y() >= aYMin - theTolerance && thePoint->y() <= aYMax + theTolerance &&
+           thePoint->z() >= aZMin - theTolerance && thePoint->z() <= aZMax + theTolerance;
+  }
+
+  // Select sub-shape of the given type, which contains the given point
+  static GeomShapePtr findSubShape(const GeomShapePtr& theShape,
+                                   const GeomAPI_Shape::ShapeType& theType,
+                                   const GeomPointPtr& thePoint,
+                                   const double theTolerance)
+  {
+    std::list<GeomShapePtr> aSubs = theShape->subShapes(theType);
+    for (std::list<GeomShapePtr>::const_iterator aSubIt = aSubs.begin();
+      aSubIt != aSubs.end(); ++aSubIt) {
+      if ((*aSubIt)->middlePoint()->distance(thePoint) < theTolerance)
+        return *aSubIt;
+    }
+
+    // not found
+    return GeomShapePtr();
+  }
+
+  bool findSubshapeByPoint(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                           const std::shared_ptr<GeomAPI_Pnt>& thePoint,
+                           const GeomAPI_Shape::ShapeType& theShapeType,
+                           std::shared_ptr<ModelAPI_Result>& theResult,
+                           std::shared_ptr<GeomAPI_Shape>& theSubshape)
+  {
+    static const double TOLERANCE = 1.e-7;
+
+    theResult = ResultPtr();
+    const std::list<ResultPtr>& aResults = theFeature->results();
+    for (std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
+         aResIt != aResults.end(); ++aResIt) {
+      GeomShapePtr aCurShape = (*aResIt)->shape();
+      // first of all, check the point is within bounding box of the result
+      if (!aCurShape || !isPointWithinBB(thePoint, aCurShape, TOLERANCE))
+        continue;
+      // now, process all sub-shapes of the given type and check their inner points,
+      // but skip the case the selected type is COMPOUND and the shape is a list of sketch edges
+      // (it will be processed later)
+      std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
+          std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aCurShape);
+      if (theShapeType != GeomAPI_Shape::COMPOUND || !aSketchEdges)
+        theSubshape = findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
+      if (theSubshape) {
+        theResult = *aResIt;
+        break;
+      }
+
+      // special case for ResultConstruction if the FACE is selected
+      ResultConstructionPtr aResConstr =
+          std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIt);
+      if (aResConstr && theShapeType >= GeomAPI_Shape::FACE) {
+        int aNbFaces = aResConstr->facesNum();
+        for (int aFaceInd = 0; aFaceInd < aNbFaces; ++aFaceInd) {
+          GeomFacePtr aCurFace = aResConstr->face(aFaceInd);
+          // check the point is within bounding box of the face
+          if (!isPointWithinBB(thePoint, aCurFace, TOLERANCE))
+            continue;
+          theSubshape = findSubShape(aCurFace, theShapeType, thePoint, TOLERANCE);
+          if (theSubshape) {
+            theResult = *aResIt;
+            break;
+          }
+        }
+      }
+      if (theResult)
+        break;
+
+      // next special case: the full sketch is selected
+      // the selection type is a COMPOUND
+      if (aSketchEdges &&
+          aSketchEdges->middlePoint()->distance(thePoint) < TOLERANCE) {
+        // select whole result
+        theResult = *aResIt;
+        theSubshape = GeomShapePtr();
+        break;
+      }
+    }
+
+    return (bool)theResult;
+  }
 } // namespace ModelGeomAlgo_Shape
index cb0f7e24377cc18e59f0e763232b829f008f94d6..e2fa4a1753a1e4992cc21cfbebf469752ac7e4e2 100644 (file)
@@ -39,6 +39,21 @@ namespace ModelGeomAlgo_Shape {
                               const std::shared_ptr<ModelAPI_Feature>& theFeature,
                               const GeomAPI_Shape::ShapeType& theType,
                               std::set<std::shared_ptr<ModelAPI_Result> >& theShapeResults);
+
+  /// Searches a sub-shape in the results of the given features,
+  /// which contains the given point.
+  /// \param[in]  theFeature    feature, which results are being processed
+  /// \param[in]  thePoint      selected point which identifies the shape
+  /// \param[in]  theShapeType  type of the selected shape
+  /// \param[out] theResult     applicable result
+  /// \param[out] theSubshape   sub-shape of the found result
+  /// \return \c true if the result and its applicable sub-shape are found
+  MODELGEOMALGO_EXPORT bool findSubshapeByPoint(
+                              const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const std::shared_ptr<GeomAPI_Pnt>& thePoint,
+                              const GeomAPI_Shape::ShapeType& theShapeType,
+                              std::shared_ptr<ModelAPI_Result>& theResult,
+                              std::shared_ptr<GeomAPI_Shape>& theSubshape);
 }
 
 #endif
index 3af378807a6cbb0ded53e04347e00f7acba4c834..8f0607feb14e491a229afb4f629a3fe99c28b14f 100644 (file)
@@ -57,6 +57,7 @@ SET(PROJECT_LIBRARIES
   GeomDataAPI
   GeomAlgoAPI
   ModelAPI
+  ModelGeomAlgo
 )
 
 ADD_DEFINITIONS(-DMODELHIGHAPI_EXPORTS -DWNT)
@@ -84,6 +85,7 @@ INCLUDE_DIRECTORIES(
   ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
   ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
   ${PROJECT_SOURCE_DIR}/src/ModelAPI
+  ${PROJECT_SOURCE_DIR}/src/ModelGeomAlgo
   ${PROJECT_SOURCE_DIR}/src/PartSetPlugin
   ${OpenCASCADE_INCLUDE_DIR}
 )
index 4e8152652e97d431f321e6357aff20f00a3c1de8..1cbee858ccde9c64986d022ac75321d186033e1d 100644 (file)
@@ -53,6 +53,8 @@
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_Tools.h>
 
+#include <ModelGeomAlgo_Shape.h>
+
 #include <PartSetPlugin_Part.h>
 
 #include <OSD_OpenFile.hxx>
@@ -935,6 +937,46 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
   return *this;
 }
 
+static int possibleSelectionsByPoint(const GeomPointPtr& thePoint,
+                                     const GeomAPI_Shape::ShapeType& theType,
+                                     const FeaturePtr& theStartFeature,
+                                     const FeaturePtr& theEndFeature)
+{
+  DocumentPtr aDoc1 = theStartFeature->document();
+  DocumentPtr aDoc2 = theEndFeature->document();
+
+  std::list<FeaturePtr> aFeatures = aDoc1->allFeatures();
+  if (aDoc1 != aDoc2) {
+    std::list<FeaturePtr> anAdditionalFeatures = aDoc2->allFeatures();
+    aFeatures.insert(aFeatures.end(), anAdditionalFeatures.begin(), anAdditionalFeatures.end());
+  }
+
+  CompositeFeaturePtr aLastCompositeFeature;
+
+  std::list<FeaturePtr>::const_iterator aFIt = aFeatures.begin();
+  while (aFIt != aFeatures.end() && *aFIt != theStartFeature) {
+    CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFIt);
+    if (aCompFeat)
+      aLastCompositeFeature = aCompFeat;
+    ++aFIt;
+  }
+
+  ResultPtr aResult;
+  GeomShapePtr aSubshape;
+  int aNbPossibleSelections = 0;
+  for (; aFIt != aFeatures.end() && *aFIt != theEndFeature; ++aFIt) {
+    if (aLastCompositeFeature && aLastCompositeFeature->isSub(*aFIt))
+      continue;
+    CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFIt);
+    if (aCompFeat)
+      aLastCompositeFeature = aCompFeat;
+
+    if (ModelGeomAlgo_Shape::findSubshapeByPoint(*aFIt, thePoint, theType, aResult, aSubshape))
+      ++aNbPossibleSelections;
+  }
+  return aNbPossibleSelections;
+}
+
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     const std::shared_ptr<ModelAPI_AttributeSelection>& theAttrSelect)
 {
@@ -957,20 +999,37 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
 
   // how to dump selection: construction features are dumped by name always
   bool isDumpByGeom = myGeometricalSelection;
+  FeaturePtr aSelectedFeature;
   if (isDumpByGeom) {
     ResultPtr aRes = theAttrSelect->context();
     if (aRes) {
-      FeaturePtr aFeat = ModelAPI_Feature::feature(aRes->data()->owner());
-      if (aFeat)
-        isDumpByGeom = aFeat->isInHistory();
+      aSelectedFeature = ModelAPI_Feature::feature(aRes->data()->owner());
+      if (aSelectedFeature)
+        isDumpByGeom = aSelectedFeature->isInHistory();
     }
   }
 
-  myDumpBuffer << "\"" << aShape->shapeTypeStr() << "\", ";
-  if (isDumpByGeom)
-    *this << aShape->middlePoint();
+  myDumpBuffer << "\"" << aShape->shapeTypeStr();
+  if (isDumpByGeom) {
+    GeomPointPtr aMiddlePoint = aShape->middlePoint();
+    // calculate number of features, which could be selected by the same point
+    FeaturePtr anOwner = ModelAPI_Feature::feature(theAttrSelect->owner());
+    int aNbPossibleSelections =
+        possibleSelectionsByPoint(aMiddlePoint, aShape->shapeType(), aSelectedFeature, anOwner);
+
+    // produce the index if the number of applicable features is greater than 1
+    std::string anIndex;
+    if (aNbPossibleSelections > 1) {
+      std::ostringstream anOutput;
+      anOutput << "_" << aNbPossibleSelections;
+      anIndex = anOutput.str();
+    }
+
+    myDumpBuffer << anIndex << "\", ";
+    *this << aMiddlePoint;
+  }
   else
-    myDumpBuffer << "\"" << theAttrSelect->namingName() << "\"";
+    myDumpBuffer << "\", \"" << theAttrSelect->namingName() << "\"";
   myDumpBuffer << ")";
   return *this;
 }
index 996e176764f2b7d97fa2d78b077f05e562123c41..87146a7a7fe6e2954fe8be60f1bc8e1787a7afb6 100644 (file)
@@ -194,9 +194,11 @@ void fillAttribute(const std::list<ModelHighAPI_Selection> & theValue,
   theAttribute->clear();
 
   if(!theValue.empty()) {
-    std::string aSelectionType;
     const ModelHighAPI_Selection& aSelection = theValue.front();
-    theAttribute->setSelectionType(aSelection.shapeType());
+    std::string aSelectionType = aSelection.shapeType();
+    GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::shapeTypeByStr(aSelectionType);
+    if (aType != GeomAPI_Shape::SHAPE || aSelectionType == "SHAPE")
+      theAttribute->setSelectionType(aSelectionType);
   }
 
   for (auto it = theValue.begin(); it != theValue.end(); ++it)