]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
[bos #35154][EDF](2023-T1) Edge thickness. dish/CR35154--Edge_Thickness3 76/head
authordish <dmitrii.shvydkoi@opencascade.com>
Tue, 19 Nov 2024 02:05:58 +0000 (02:05 +0000)
committerdish <dmitrii.shvydkoi@opencascade.com>
Tue, 19 Nov 2024 02:05:58 +0000 (02:05 +0000)
Add edge thickness feature. Edge thickness can be assigned to any shapes and subshapes, except vertices.
If different edge thickness values assigned both to a shape and to its subshape, subshape value overrides shape value.
Thickness data (de)serialized into xCAF and TUI.py files.

31 files changed:
src/GeomAlgoAPI/GeomAlgoAPI_STEPImportXCAF.cpp
src/GeomAlgoAPI/GeomAlgoAPI_STEPImportXCAF.h
src/Model/Model_Objects.cpp
src/Model/Model_Objects.h
src/Model/Model_ResultBody.cpp
src/Model/Model_ResultBody.h
src/Model/Model_ResultPart.cpp
src/Model/Model_ResultPart.h
src/ModelAPI/ModelAPI_Result.cpp
src/ModelAPI/ModelAPI_Result.h
src/ModelAPI/ModelAPI_ResultBody.h
src/ModelAPI/ModelAPI_ResultPart.h
src/ModelAPI/ModelAPI_Session.cpp
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModelHighAPI/ModelHighAPI_Dumper.cpp
src/ModelHighAPI/ModelHighAPI_Dumper.h
src/ModelHighAPI/ModelHighAPI_Selection.cpp
src/ModelHighAPI/ModelHighAPI_Selection.h
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Tools.cpp
src/PartSet/PartSet_Tools.h
src/SHAPERGUI/resources/LightApp.xml.in
src/XGUI/CMakeLists.txt
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_Displayer.cpp
src/XGUI/XGUI_EdgeThicknessWidget.cpp [new file with mode: 0644]
src/XGUI/XGUI_EdgeThicknessWidget.h [new file with mode: 0644]
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h
src/XGUI/XGUI_msg_fr.ts

index 30f06dbf39171336240c5baf79e21c78db58fd36..409cf7bcda255b7d80438bd6293fddefe09b929e 100644 (file)
@@ -171,6 +171,30 @@ void setColors(std::shared_ptr<ModelAPI_ResultBody> theResultBody)
   }
 }
 
+void setEdgeThicknessValues(std::shared_ptr<ModelAPI_ResultBody> theResultBody)
+{
+  TopoDS_Shape aShape = theResultBody->shape()->impl<TopoDS_Shape>();
+  TopExp_Explorer anExp(aShape, TopAbs_SOLID); // TODO Should it be everything, except VERTEX?
+  while (anExp.More()) {
+    auto aSolid = anExp.Current();
+
+    std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
+    aGeomShape->setImpl(new TopoDS_Shape(aSolid));
+    auto aName = theResultBody->findShapeName(aGeomShape);
+
+    if (!aName.empty()) {
+      auto aColor = theResultBody->findShapeColor(aName); // TODO
+
+      if (!aColor.empty())
+        theResultBody->setSubShapeColor(theResultBody, aGeomShape, { 128, 222, 2 }); // TODO
+      else
+        theResultBody->setSubShapeColor(theResultBody, aGeomShape, { 255, 0, 0 }); // TODO
+
+    }
+    anExp.Next();
+  }
+}
+
 //=============================================================================
 std::shared_ptr<GeomAPI_Shape> setGeom(const Handle(XCAFDoc_ShapeTool) &theShapeTool,
                                        const TDF_Label& /*theLabel*/,
index d8674a6966c0cfba6fe4588e371bc1e7e00f2fc7..b4c57a7f923e7483f8830e194448fda14ab2d84b 100644 (file)
@@ -34,4 +34,7 @@ std::shared_ptr<GeomAPI_Shape>  readAttributes(STEPCAFControl_Reader &theReader,
                                  std::string& theError);
 
 GEOMALGOAPI_EXPORT void setColors(std::shared_ptr<ModelAPI_ResultBody> theResultBody);
+
+GEOMALGOAPI_EXPORT void setEdgeThicknessValues(std::shared_ptr<ModelAPI_ResultBody> theResultBody);
+
 #endif /* GEOMALGOAPI_STEPIMPORTXCAF_H_ */
index d7d6190d5a5ba5f30fc17d73b58d04b37fd23191..9675b4c3d398a1c5ec289a47cc89336710beb31d 100644 (file)
@@ -54,6 +54,7 @@
 #include <TDF_LabelMap.hxx>
 #include <TDF_CopyLabel.hxx>
 #include <TDF_ListIteratorOfLabelList.hxx>
+#include <Standard_GUID.hxx>
 
 // relocate to other file
 #include <TNaming_Builder.hxx>
@@ -112,6 +113,8 @@ static const int TAG_RESULT_SHAPES = 2;  ///< where the shapes are located
 /// 0:1:2:N:2:K:1 - data of the K result of the feature N
 /// 0:1:2:N:2:K:2:M:1 - data of the M shape of the K result of the feature N
 
+/*static*/ const Standard_GUID Model_Objects::GUID_EDGE_THICKNESS = Standard_GUID("9b31b32b-aaba-37c7-b8f0-58b793d81dd9");
+
 Model_Objects::Model_Objects(TDF_Label theMainLab) : myMain(theMainLab)
 {
 }
@@ -814,6 +817,17 @@ void Model_Objects::setAttribute(const Handle(TDF_Attribute)& theAttribute,
     static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
     ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
   }
+  else if (theAttribute->ID() == Model_Objects::GUID_EDGE_THICKNESS) {
+    Handle(TDataStd_Integer) aThicknessAttr;
+    Handle(TDataStd_Integer) anAttr = Handle(TDataStd_Integer)::DownCast(theAttribute);
+
+    if (anAttributeLabel.FindAttribute(Model_Objects::GUID_EDGE_THICKNESS, aThicknessAttr))
+      anAttributeLabel.ForgetAttribute(Model_Objects::GUID_EDGE_THICKNESS);
+
+    anAttributeLabel.AddAttribute(anAttr);
+    static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+    ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
+  }
 }
 
 Handle(TDF_Attribute) Model_Objects::getAttribute(const Standard_GUID& theID,
@@ -823,21 +837,80 @@ Handle(TDF_Attribute) Model_Objects::getAttribute(const Standard_GUID& theID,
   ResultBodyPtr aMain = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
   aMain = ModelAPI_Tools::mainBody(aMain);
 
-  int anIndex = index(theResult, theShape);
-  Handle(TDataStd_IntegerArray) anColor;
+  const int anIndex = index(theResult, theShape);
+  if (anIndex == -1)
+    return opencascade::handle<TDF_Attribute>(nullptr);
+
+  TDF_Label aResultLabel;
+  if (aMain.get())
+    aResultLabel = resultLabel(theResult->data(), index(aMain));
+  else
+    aResultLabel = resultLabel(theResult->data(), index(theResult));
+
+  TDF_Label anAttributeLabel = subShapeLabel(aResultLabel, anIndex).FindChild(TAG_FEATURE_ARGUMENTS);
 
-  if (anIndex != -1)
+  Handle(TDF_Attribute) anAttr;
+  anAttributeLabel.FindAttribute(theID, anAttr);
+  return anAttr;
+}
+
+void Model_Objects::getSubShapesWithEdgeThickness(
+  const std::shared_ptr<ModelAPI_Result> theResult,
+  std::map<std::shared_ptr<GeomAPI_Shape>, int>& oShapes
+) const {
+  ResultBodyPtr aMainBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
+  aMainBody = ModelAPI_Tools::mainBody(aMainBody);
+  TDF_Label aShapesLabel;
+  if (aMainBody.get())
+    aShapesLabel = shapesFromResult(resultLabel(theResult->data(), index(aMainBody)));
+  else
+    aShapesLabel = shapesFromResult(resultLabel(theResult->data(), index(theResult)));
+
+  for (TDF_ChildIterator aChilds(aShapesLabel); aChilds.More(); aChilds.Next())
   {
-    TDF_Label aResultLabel;
-    if (aMain.get())
-      aResultLabel = resultLabel(theResult->data(), index(aMain));
-    else
-      aResultLabel = resultLabel(theResult->data(), index(theResult));
+    TDF_Label aCurSubShape = aChilds.Value();
+    Handle(TNaming_NamedShape) aNamedShape;
+    aCurSubShape.FindAttribute(TNaming_NamedShape::GetID(), aNamedShape);
+    if (aNamedShape.IsNull())
+      continue;
+
+    std::shared_ptr<GeomAPI_Shape> aSub(new GeomAPI_Shape);
+    aSub->setImpl(new TopoDS_Shape(aNamedShape->Get()));
+
+    Handle(TDataStd_Integer) aEdgeThicknessAttr;
+    aCurSubShape.FindChild(TAG_FEATURE_ARGUMENTS).FindAttribute(Model_Objects::GUID_EDGE_THICKNESS, aEdgeThicknessAttr);
+    if (aEdgeThicknessAttr.IsNull())
+      continue;
+
+    oShapes[aSub] = aEdgeThicknessAttr->Get();
+  }
+}
+
+void Model_Objects::removeSubShapeEdgeThickness(const std::shared_ptr<ModelAPI_Result> theResult) const
+{
+  ResultBodyPtr aMainBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
+  aMainBody = ModelAPI_Tools::mainBody(aMainBody);
+
+  TDF_Label aShapesLabel;
+  if (aMainBody.get())
+    aShapesLabel = shapesFromResult(resultLabel(theResult->data(), index(aMainBody)));
+  else
+  {
+    ResultPartPtr aResPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(theResult);
+    if (!aResPart.get())
+      return;
+    aShapesLabel = shapesFromResult(resultLabel(theResult->data(), index(aResPart)));
+  }
+  for (TDF_ChildIterator aChilds(aShapesLabel); aChilds.More(); aChilds.Next())
+  {
+    TDF_Label aCurSubShape = aChilds.Value();
+    Handle(TNaming_NamedShape) aNamedShape;
+    aCurSubShape.FindAttribute(TNaming_NamedShape::GetID(), aNamedShape);
+    if (aNamedShape.IsNull())
+      continue;
 
-    TDF_Label anAttributeLabel = subShapeLabel(aResultLabel, anIndex).FindChild(TAG_FEATURE_ARGUMENTS);
-    anAttributeLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anColor);
+    aCurSubShape.FindChild(TAG_FEATURE_ARGUMENTS).ForgetAttribute(Model_Objects::GUID_EDGE_THICKNESS);
   }
-  return anColor;
 }
 
 void Model_Objects::getColoredShapes(const std::shared_ptr<ModelAPI_Result> theResult,
index 364a3dddd3e66f6d7209a5b9334728c478667ca6..f3e0c511d3d6e239cffb928fc1cfe1f18c8c08a0 100644 (file)
 
 extern int kUNDEFINED_FEATURE_INDEX;
 
+
+class Standard_GUID;
+
+
 /**\class Model_Objects
  * \ingroup DataModel
  * \brief Manager of objects of the document. Normally one this class corresponds to
@@ -45,6 +49,8 @@ extern int kUNDEFINED_FEATURE_INDEX;
 class Model_Objects
 {
  public:
+  static const Standard_GUID GUID_EDGE_THICKNESS;
+
   //! Registers the feature in the data structure
   //! \param theFeature feature that must be added to the data structure
   //! \param theAfterThis the feature will be added after this feature;
@@ -199,6 +205,13 @@ class Model_Objects
     std::shared_ptr<ModelAPI_Result> theResult,
     std::shared_ptr<GeomAPI_Shape> theShape);
 
+  void getSubShapesWithEdgeThickness(
+    const std::shared_ptr<ModelAPI_Result> theResult,
+    std::map<std::shared_ptr<GeomAPI_Shape>, int>& oShapes
+  ) const;
+
+  void removeSubShapeEdgeThickness(const std::shared_ptr<ModelAPI_Result> theResult) const;
+
   //! Get colored shapes from result
   void getColoredShapes(const std::shared_ptr<ModelAPI_Result> theResult,
     std::map<std::shared_ptr<GeomAPI_Shape>, std::vector<int>>& theColoredShapes);
index 6dc5538ef5046103f857671c1b94c66f44f3bfe2..1956b7696888dc343f4c7f675d0c6199c6df8c5c 100644 (file)
@@ -39,6 +39,7 @@
 #include <TopExp_Explorer.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TDataStd_UAttribute.hxx>
+#include <TDataStd_Integer.hxx>
 #include <TDataStd_IntegerArray.hxx>
 #include <TNaming_Tool.hxx>
 #include <TDF_Reference.hxx>
@@ -255,6 +256,56 @@ void Model_ResultBody::updateConcealment()
   }
 }
 
+void Model_ResultBody::setSubShapeEdgeThickness(
+  const std::shared_ptr<ModelAPI_Result> theResult,
+  const std::shared_ptr<GeomAPI_Shape> theSubShape,
+  int theEdgeThickness
+)
+{
+  TopoDS_Shape aShape = shape()->impl<TopoDS_Shape>();
+  TopoDS_Shape aSubShape = theSubShape->impl<TopoDS_Shape>();
+  if (!shape()->isSubShape(theSubShape))
+    return;
+
+  Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
+  document()->storeShape(data(), theResult, theSubShape);
+
+  Handle(TDataStd_Integer) aThickness = new TDataStd_Integer();
+  aThickness->SetID(Model_Objects::GUID_EDGE_THICKNESS);
+  aThickness->Set(theEdgeThickness);
+  anObjects->setAttribute(aThickness, theResult, theSubShape);
+}
+
+int Model_ResultBody::getSubShapeEdgeThickness(const std::shared_ptr<ModelAPI_Result> theResult, const std::shared_ptr<GeomAPI_Shape> theSubShape) const
+{
+  TopoDS_Shape aShape = shape()->impl<TopoDS_Shape>();
+  TopoDS_Shape aSubShape = theSubShape->impl<TopoDS_Shape>();
+  if (!shape()->isSubShape(theSubShape))
+    return -1;
+
+  Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
+  auto anAttr = Handle(TDataStd_Integer)::DownCast(anObjects->getAttribute(Model_Objects::GUID_EDGE_THICKNESS, theResult, theSubShape));
+  if (anAttr.IsNull())
+    return -1;
+
+  return anAttr->Get();
+}
+
+void Model_ResultBody::getSubShapesWithEdgeThickness(
+  const std::shared_ptr<ModelAPI_Result> theResult,
+  std::map<std::shared_ptr<GeomAPI_Shape>, int>& oShapes
+) const
+{
+  Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
+  anObjects->getSubShapesWithEdgeThickness(theResult, oShapes);
+}
+
+void Model_ResultBody::removeSubShapeEdgeThickness(const std::shared_ptr<ModelAPI_Result> theResult)
+{
+  Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
+  anObjects->removeSubShapeEdgeThickness(theResult);
+}
+
 void Model_ResultBody::addShapeColor( const std::wstring& theName,std::vector<int>& color)
 {
   if (myColorsShape.find(theName) == myColorsShape.end())
index 3f5727e5d6af28f5dcd4cede7a1dd96265ed6989..7ff38f672d7c5fa1dfa2d9314e1ac66ee8d4f8e2 100644 (file)
@@ -139,6 +139,21 @@ protected:
   /// Checks the state of children and parents to send events of creation/erase when needed
   void updateConcealment();
 
+  void setSubShapeEdgeThickness(
+    const std::shared_ptr<ModelAPI_Result> theResult,
+    const std::shared_ptr<GeomAPI_Shape> theSubShape,
+    int theEdgeThickness
+  );
+
+  int getSubShapeEdgeThickness(const std::shared_ptr<ModelAPI_Result> theResult, const std::shared_ptr<GeomAPI_Shape> theSubShape) const;
+
+  void getSubShapesWithEdgeThickness(
+    const std::shared_ptr<ModelAPI_Result> theResult,
+    std::map<std::shared_ptr<GeomAPI_Shape>, int>& oSubShapes
+  ) const;
+
+  void removeSubShapeEdgeThickness(const std::shared_ptr<ModelAPI_Result> theResult);
+
   /// Adds to theOldForSub only old shapes that where used for theSub creation
   void computeOldForSub(const GeomShapePtr& theSub,
     const std::list<GeomShapePtr>& theAllOlds, std::list<GeomShapePtr>& theOldForSub);
index 5f46da1783162885fdcd4b2fc8e8cde178c99d68..45470ce48dd22d72e9f5b334d0e766bb459aff07 100644 (file)
@@ -26,6 +26,7 @@
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_ResultBody.h>
+#include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_AttributeIntArray.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeReference.h>
@@ -45,6 +46,7 @@
 #include <TNaming_Tool.hxx>
 #include <TNaming_NamedShape.hxx>
 #include <TDataStd_Name.hxx>
+#include <TDataStd_Integer.hxx>
 #include <TDataStd_IntegerArray.hxx>
 #include <TopoDS_Compound.hxx>
 #include <BRep_Builder.hxx>
@@ -61,6 +63,7 @@ void Model_ResultPart::initAttributes()
   AttributeDocRefPtr aDocRef = std::dynamic_pointer_cast<ModelAPI_AttributeDocRef>(
     data()->addAttribute(DOC_REF(), ModelAPI_AttributeDocRef::typeId()));
   data()->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::typeId());
+  data()->addAttribute(EDGE_THICKNESS_ID(), ModelAPI_AttributeInteger::typeId());
   data()->addAttribute(BASE_REF_ID(), ModelAPI_AttributeReference::typeId());
   data()->addAttribute(DEFLECTION_ID(), ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(TRANSPARENCY_ID(), ModelAPI_AttributeDouble::typeId());
@@ -439,6 +442,49 @@ std::shared_ptr<GeomAPI_Shape> Model_ResultPart::shapeInPart(
   return aResult;
 }
 
+void Model_ResultPart::setSubShapeEdgeThickness(const std::shared_ptr<GeomAPI_Shape>& theSubShape, int theThickness)
+{
+  TopoDS_Shape aShape = shape()->impl<TopoDS_Shape>();
+  TopoDS_Shape aSubShape = theSubShape->impl<TopoDS_Shape>();
+  if (!shape()->isSubShape(theSubShape))
+    return;
+
+  Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
+
+  document()->storeShape(data(), original(), theSubShape);
+  Handle(TDataStd_Integer) aThickness = new TDataStd_Integer();
+  aThickness->SetID(Model_Objects::GUID_EDGE_THICKNESS);
+  aThickness->Set(theThickness);
+  anObjects->setAttribute(aThickness, original(), theSubShape);
+}
+
+int Model_ResultPart::getSubShapeEdgeThickness(const std::shared_ptr<GeomAPI_Shape>& theSubShape) const
+{
+  TopoDS_Shape aShape = shape()->impl<TopoDS_Shape>();
+  TopoDS_Shape aSubShape = theSubShape->impl<TopoDS_Shape>();
+  if (!shape()->isSubShape(theSubShape))
+    return -1;
+
+  Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
+  Handle(TDataStd_Integer) anAttr = Handle(TDataStd_Integer)::DownCast(anObjects->getAttribute(Model_Objects::GUID_EDGE_THICKNESS, original(), theSubShape));
+  if (anAttr.IsNull())
+    return -1;
+
+  return anAttr->Get();
+}
+
+void Model_ResultPart::getSubShapesWithEdgeThickness(std::map<std::shared_ptr<GeomAPI_Shape>, int>& oShapes)
+{
+  Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
+  anObjects->getSubShapesWithEdgeThickness(original(), oShapes);
+}
+
+void Model_ResultPart::removeSubShapeEdgeThickness()
+{
+  Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
+  anObjects->removeSubShapeEdgeThickness(original());
+}
+
 void Model_ResultPart::setSubShapeColor(const std::shared_ptr<GeomAPI_Shape>& theShape,
   const std::vector<int>& theColor)
 {
index 2ba7d9ac9c427efadcc0c51e2878203edf67fe75..43074b2e1f9d2a16bc873d8d1a3a5c65115f4f3e 100644 (file)
@@ -78,7 +78,17 @@ class Model_ResultPart : public ModelAPI_ResultPart
   MODEL_EXPORT virtual bool updateInPart(const int theIndex);
   /// Returns the shape by the name in the part
   MODEL_EXPORT virtual std::shared_ptr<GeomAPI_Shape> shapeInPart(
-    const std::wstring& theName, const std::string& theType, int& theIndex);  /// Set color on subshape
+    const std::wstring& theName, const std::string& theType, int& theIndex);
+
+  MODEL_EXPORT virtual void setSubShapeEdgeThickness(const std::shared_ptr<GeomAPI_Shape>& theSubShape, int theThickness);
+
+  MODEL_EXPORT virtual int getSubShapeEdgeThickness(const std::shared_ptr<GeomAPI_Shape>& theSubShape) const;
+
+  MODEL_EXPORT virtual void getSubShapesWithEdgeThickness(std::map<std::shared_ptr<GeomAPI_Shape>, int>& oSubShapes);
+
+  MODEL_EXPORT virtual void removeSubShapeEdgeThickness();
+
+  /// Set color on subshape
   MODEL_EXPORT virtual void setSubShapeColor(const std::shared_ptr<GeomAPI_Shape>& theShape,
     const std::vector<int>& theColor);
 
index 2c3bdc9f9acaebbc921fc95b367c14249921db77..fcdd6cfcb922722fb5e165edd965e754519ddc7a 100644 (file)
@@ -21,6 +21,7 @@
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Attribute.h>
+#include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_AttributeIntArray.h>
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeBoolean.h>
@@ -44,6 +45,7 @@ void ModelAPI_Result::initAttributes()
   // append the color attribute. It is empty, the attribute will be filled by a request
   DataPtr aData = data();
   aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::typeId())->setIsArgument(false);
+  aData->addAttribute(EDGE_THICKNESS_ID(), ModelAPI_AttributeInteger::typeId());
   aData->addAttribute(DEFLECTION_ID(), ModelAPI_AttributeDouble::typeId())->setIsArgument(false);
   aData->addAttribute(TRANSPARENCY_ID(), ModelAPI_AttributeDouble::typeId())->setIsArgument(false);
   aData->addAttribute(ISO_LINES_ID(), ModelAPI_AttributeIntArray::typeId())->setIsArgument(false);
index e82ea2f355d123eb0f36f26dd450ecac3567a876..31a64ae4ca2e6b61879691c29a02cee28693e5e9 100644 (file)
@@ -49,6 +49,14 @@ class ModelAPI_Result : public ModelAPI_Object
     return MY_COLOR_ID;
   }
 
+  /// Reference to the edge thickness of the result.
+  /// The integer value is used. The value is in [1, 5] range
+  inline static const std::string& EDGE_THICKNESS_ID()
+  {
+    static const std::string MY_EDGE_THICKNESS_ID("Edge_Thickness");
+    return MY_EDGE_THICKNESS_ID;
+  }
+
   /// Reference to the deflection of the result.
   /// The double value is used. The value is in [0, 1] range
   inline static const std::string& DEFLECTION_ID()
@@ -122,7 +130,7 @@ class ModelAPI_Result : public ModelAPI_Object
   MODELAPI_EXPORT virtual ~ModelAPI_Result();
 
   /// Returns the shape-result produced by this feature (or null if no shapes)
-  MODELAPI_EXPORT virtual std::shared_ptr<GeomAPI_Shape> shape(); 
+  MODELAPI_EXPORT virtual std::shared_ptr<GeomAPI_Shape> shape();
 
   /// Returns all the vertices of this result
   MODELAPI_EXPORT virtual ListOfShape
index 3d1df1837f3b07432c66cd51183530fdf9c2d8e3..64fb56d683df05866f14cd3a97c77e45843c3d8b 100644 (file)
@@ -196,6 +196,24 @@ public:
   MODELAPI_EXPORT virtual std::wstring addShapeName
                               (std::shared_ptr<GeomAPI_Shape>, const std::wstring& theName) = 0;
 
+  MODELAPI_EXPORT virtual void setSubShapeEdgeThickness(
+    const std::shared_ptr<ModelAPI_Result> theResult,
+    const std::shared_ptr<GeomAPI_Shape> theSubShape,
+    int theEdgeThickness
+  ) = 0;
+
+  MODELAPI_EXPORT virtual int getSubShapeEdgeThickness(
+    const std::shared_ptr<ModelAPI_Result> theResult,
+    const std::shared_ptr<GeomAPI_Shape> theSubShape
+  ) const = 0;
+
+  MODELAPI_EXPORT virtual void getSubShapesWithEdgeThickness(
+    const std::shared_ptr<ModelAPI_Result> theResult,
+    std::map<std::shared_ptr<GeomAPI_Shape>, int>& oSubShapes
+  ) const = 0;
+
+  MODELAPI_EXPORT virtual void removeSubShapeEdgeThickness(const std::shared_ptr<ModelAPI_Result> theResult) = 0;
+
   /// Add color for shape Name read shape in step file
   MODELAPI_EXPORT virtual void addShapeColor
                               (const std::wstring& theName, std::vector<int>& theColor) = 0;
index 8dcd857237e356a8258db949f65668f854d1e303..d3adf16eab79cd8da223f3e0b4ff555fd3132c99 100644 (file)
@@ -89,6 +89,15 @@ class ModelAPI_ResultPart : public ModelAPI_Result
   /// Returns the shape by the name in the part
   virtual std::shared_ptr<GeomAPI_Shape> shapeInPart(
     const std::wstring& theName, const std::string& theType, int& theIndex) = 0;
+
+  virtual void setSubShapeEdgeThickness(const std::shared_ptr<GeomAPI_Shape>& theSubShape, int theThickness) = 0;
+
+  virtual int getSubShapeEdgeThickness(const std::shared_ptr<GeomAPI_Shape>& theSubShape) const = 0;
+
+  virtual void getSubShapesWithEdgeThickness(std::map<std::shared_ptr<GeomAPI_Shape>, int>& oSubShapes) = 0;
+
+  virtual void removeSubShapeEdgeThickness() = 0;
+
   /// Set color on subshape
   virtual void setSubShapeColor(const std::shared_ptr<GeomAPI_Shape>& theShape,
     const std::vector<int>& theColor) = 0;
index d00c9e50f66e1c0de7ef2d9e1b7244d0dc9c19bc..e9ed94a8095b78fc1e19e68d714cbe616faaf641 100644 (file)
@@ -83,6 +83,9 @@ std::shared_ptr<ModelAPI_Session> ModelAPI_Session::get()
     Config_PropManager::registerProp("Visualization", "shaper_default_transparency",
       "Default transparency (%)", Config_Prop::IntSpin, "0", "0", "100");
 
+    Config_PropManager::registerProp("Visualization", "shaper_default_edge_thickness",
+      "Default edge thickness (pt)", Config_Prop::IntSpin, "3", "1", "5");
+
   }
   return MY_MANAGER;
 }
index f7d7a5699e59fa4d59a0fdd80d052f57be6ca933..57915dc1f702984a705d1dd1b6d0561047ef2fdc 100644 (file)
@@ -21,6 +21,7 @@
 #include <ModelAPI_AttributeDocRef.h>
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeImage.h>
+#include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_AttributeIntArray.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_CompositeFeature.h>
@@ -1124,6 +1125,134 @@ void setColor(ResultPtr theResult, GeomShapePtr theShape, const std::vector<int>
 }
 
 
+//**************************************************************
+int getEdgeThickness(const std::shared_ptr<ModelAPI_Result>& theResult)
+{
+  int aThickness = -1;
+  if (theResult && theResult->data()->attribute(ModelAPI_Result::EDGE_THICKNESS_ID())) {
+    AttributeIntegerPtr aIntAttr = theResult->data()->integer(ModelAPI_Result::EDGE_THICKNESS_ID());
+    if (aIntAttr && aIntAttr->isInitialized())
+      aThickness = aIntAttr->value();
+  }
+  return aThickness;
+}
+
+int getSubShapeEdgeThickness(const std::shared_ptr<ModelAPI_Result> theResult, const std::shared_ptr<GeomAPI_Shape> theSubShape)
+{
+  if (!theResult || theSubShape->isNull())
+    return -1;
+
+  if (!theResult->shape()->isSubShape(theSubShape))
+    return -1;
+
+  auto resultBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
+  if (resultBody) {
+    resultBody = mainBody(resultBody);
+    return resultBody->getSubShapeEdgeThickness(theResult, theSubShape);
+  }
+  else {
+    const auto resultPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(theResult);
+    if (!resultPart)
+      return -1;
+
+    return resultPart->getSubShapeEdgeThickness(theSubShape);
+  }
+}
+
+void getSubShapesWithEdgeThickness(
+  const std::shared_ptr<ModelAPI_Result> theResult,
+  std::map<std::shared_ptr<GeomAPI_Shape>, int>& oShapes,
+  bool theGetSubResults
+) {
+  if (!theResult)
+    return;
+
+  const auto resultBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
+  if (resultBody) {
+    ResultBodyPtr mainBody = ModelAPI_Tools::mainBody(resultBody);
+    if (!mainBody)
+      return;
+
+    if (theGetSubResults) {
+      std::list<ResultPtr> subResults;
+      allSubs(resultBody, subResults);
+      for (auto itSubRes = subResults.begin(); itSubRes != subResults.end(); ++itSubRes) {
+        mainBody->getSubShapesWithEdgeThickness(*itSubRes, oShapes);
+      }
+    }
+
+    mainBody->getSubShapesWithEdgeThickness(theResult, oShapes);
+  }
+  else {
+    const auto resultPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(theResult);
+    if (!resultPart)
+      return;
+
+    resultPart->getSubShapesWithEdgeThickness(oShapes);
+  }
+}
+
+void removeSubShapeEdgeThickness(const std::shared_ptr<ModelAPI_Result> theResult)
+{
+  if (!theResult)
+    return;
+
+  auto resultBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
+  if (resultBody) {
+    resultBody = mainBody(resultBody);
+    resultBody->removeSubShapeEdgeThickness(theResult);
+  }
+  else {
+    auto resultPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(theResult);
+    if (!resultPart)
+      return;
+
+    resultPart->removeSubShapeEdgeThickness();
+  }
+}
+
+void setEdgeThickness(std::shared_ptr<ModelAPI_Result> theResult, int theEdgeThickness)
+{
+  if (!theResult)
+    return;
+
+  const AttributeIntegerPtr anAttribute = theResult->data()->integer(ModelAPI_Result::EDGE_THICKNESS_ID());
+  if (anAttribute) {
+    anAttribute->setValue(theEdgeThickness);
+    removeSubShapeEdgeThickness(theResult);
+  }
+}
+
+void setSubShapeEdgeThickness(
+  std::shared_ptr<ModelAPI_Result> theResult,
+  std::shared_ptr<GeomAPI_Shape> theSubShape,
+  int theEdgeThickness
+) {
+  if (!theResult || theSubShape->isNull())
+    return;
+
+  if (!theResult->shape()->isSubShape(theSubShape))
+    return;
+
+  auto resultBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
+  if (resultBody) {
+    resultBody = mainBody(resultBody);
+    resultBody->setSubShapeEdgeThickness(theResult, theSubShape, theEdgeThickness);
+  }
+  else {
+    const auto resultPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(theResult);
+    if (!resultPart)
+      return;
+
+    resultPart->setSubShapeEdgeThickness(theSubShape, theEdgeThickness);
+  }
+
+  static const Events_ID EVENT = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  ModelAPI_EventCreator::get()->sendUpdated(theResult, EVENT);
+}
+
+
+//**************************************************************
 void getColor(const std::shared_ptr<ModelAPI_Result>& theResult, std::vector<int>& theColor)
 {
   theColor.clear();
index dcb62e0d3b894cdfec8e3929e1180289159ca1b4..d67e4d0f1297d77d4c94b1c210e78ca332819fab 100644 (file)
@@ -276,6 +276,32 @@ MODELAPI_EXPORT double getDeflection(const std::shared_ptr<ModelAPI_Result>& the
 MODELAPI_EXPORT void setDeflection(std::shared_ptr<ModelAPI_Result> theResult,
   const double theDeflection);
 
+/*! \returns -1, if edge thickness is not defined. */
+MODELAPI_EXPORT int getEdgeThickness(const std::shared_ptr<ModelAPI_Result>& theResult);
+
+/*! \returns -1, if edge thickness is not defined. */
+MODELAPI_EXPORT int getSubShapeEdgeThickness(const std::shared_ptr<ModelAPI_Result> theResult, const std::shared_ptr<GeomAPI_Shape> theSubShape);
+
+/*! \returns theResult subshapes with defined edge thickness.
+* \param theSubResults - true, to include subshapes of subresults. */
+MODELAPI_EXPORT void getSubShapesWithEdgeThickness(
+  const std::shared_ptr<ModelAPI_Result> theResult,
+  std::map<std::shared_ptr<GeomAPI_Shape>,int>& oShapes,
+  bool theGetSubResults = false
+);
+
+/*! \brief Removes edge thickness data of result subshapes. */
+MODELAPI_EXPORT void removeSubShapeEdgeThickness(const std::shared_ptr<ModelAPI_Result> theResult);
+
+MODELAPI_EXPORT void setEdgeThickness(std::shared_ptr<ModelAPI_Result> theResult, int theEdgeThickness);
+
+/*! \param theShape belongs to theResult. */
+MODELAPI_EXPORT void setSubShapeEdgeThickness(
+  std::shared_ptr<ModelAPI_Result> theResult,
+  std::shared_ptr<GeomAPI_Shape> theSubShape,
+  int theEdgeThickness
+);
+
 /*! Returns current color of the current result
 * \param[in] theResult a result object
 * \param[out] theColor a color values if it is defined
index f7cd5b96cd23a30ec077ce5dfe4ed2887e2abbdf..308821fd22b5fe5d6a49c1a75038efb3bea887e5 100644 (file)
@@ -940,6 +940,30 @@ void ModelHighAPI_Dumper::dumpEntitySetName()
       anEntityNames.myUserName.clear();
       anEntityNames.myIsDefault = true;
     }
+
+    // Set result edge thickness.
+    if (isEdgeThicknessDefined(*aResIt)) {
+      AttributeIntegerPtr attrThickness = (*aResIt)->data()->integer(ModelAPI_Result::EDGE_THICKNESS_ID());
+      if (attrThickness && attrThickness->isInitialized()) {
+        *this << *aResIt;
+        *myDumpStorage << ".setEdgeThickness(" << attrThickness->value() << ")\n";
+      }
+    }
+    // Set subresult edge thickness.
+    std::map<GeomShapePtr, int> aShapesWithEdgeThickness;
+    ModelAPI_Tools::getSubShapesWithEdgeThickness(*aResIt, aShapesWithEdgeThickness, true /*theGetSubResults*/);
+
+    if ((isParentResult(*aResIt)) && !aShapesWithEdgeThickness.empty()) {
+      for (const auto& shapeAndThickness : aShapesWithEdgeThickness) {
+        const GeomShapePtr& aShape = shapeAndThickness.first;
+
+        *this << *aResIt;
+        *myDumpStorage << ".setEdgeThickness(model.selection(\"" << aShape->shapeTypeStr() << "\", \""
+          << Locale::Convert::toString((*aResIt)->data()->name(aShape)) << "\"), "
+          << shapeAndThickness.second << ")\n";
+      }
+    }
+
     // set result color
     if (!isDefaultColor(*aResIt)) {
       AttributeIntArrayPtr aColor = (*aResIt)->data()->intArray(ModelAPI_Result::COLOR_ID());
@@ -1044,6 +1068,13 @@ static bool isSketchSub(const FeaturePtr& theFeature)
   return anOwner && anOwner->getKind() == SKETCH;
 }
 
+bool ModelHighAPI_Dumper::hasShapeWithEdgeThickness(const ResultPtr& theResult, bool theGetSubResults = false) const
+{
+  std::map<GeomShapePtr, int> aShapes;
+  ModelAPI_Tools::getSubShapesWithEdgeThickness(theResult, aShapes, theGetSubResults);
+  return !aShapes.empty();
+}
+
 bool ModelHighAPI_Dumper::hasColoredShape(const ResultPtr& theResult, bool theGetSubResults) const
 {
   std::map<GeomShapePtr, std::vector<int>> aColoredShapes;
@@ -1062,6 +1093,23 @@ bool ModelHighAPI_Dumper::isParentResult(const ResultPtr& theResult) const
   return false;
 }
 
+bool ModelHighAPI_Dumper::isEdgeThicknessDefined(const ResultPtr& theResult) const
+{
+  const auto anAttribute = theResult->data()->integer(ModelAPI_Result::EDGE_THICKNESS_ID());
+  if (!anAttribute || !anAttribute->isInitialized())
+    return false;
+
+  // Do not dump edge thickness, if theResult belongs to sketch entity.
+  const auto aResConstr = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theResult);
+  if (aResConstr) {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(theResult->data()->owner());
+    if (isSketchSub(aFeature))
+      return false;
+  }
+
+  return true;
+}
+
 bool ModelHighAPI_Dumper::isDefaultColor(const ResultPtr& theResult) const
 {
   AttributeIntArrayPtr aColor = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
@@ -1367,20 +1415,20 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FeaturePtr& theEntity
 
   if (!myNames[theEntity].myIsDumped) {
     bool isUserDefinedName = !myNames[theEntity].myIsDefault;
-    // store results if they have user-defined names or colors
-    std::list<ResultPtr> aResultsWithNameOrColor;
+    // Store results if they have user-defined names, colors or edge thickness.
+    std::list<ResultPtr> aResultsWithNonDefaultAttr;
     std::list<ResultPtr> allRes;
     ModelAPI_Tools::allResults(theEntity, allRes);
-    for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
-      if(!myNames[*aRes].myIsDefault || !isDefaultColor(*aRes) ||
-         !isDefaultDeflection(*aRes) || !isDefaultTransparency(*aRes) ||
-        (isParentResult(*aRes) && hasColoredShape(*aRes, true)))
-        aResultsWithNameOrColor.push_back(*aRes);
+    for (const auto& aRes : allRes) {
+      if (!myNames[aRes].myIsDefault || !isDefaultColor(aRes) || isEdgeThicknessDefined(aRes) ||
+         !isDefaultDeflection(aRes) || !isDefaultTransparency(aRes) ||
+        (isParentResult(aRes) && (hasColoredShape(aRes, true) || hasShapeWithEdgeThickness(aRes, true))))
+        aResultsWithNonDefaultAttr.push_back(aRes);
     }
+
     // store just dumped entity to stack
     if (myEntitiesStack.empty() || myEntitiesStack.top().myEntity != theEntity)
-      myEntitiesStack.push(
-          LastDumpedEntity(theEntity, isUserDefinedName, aResultsWithNameOrColor));
+      myEntitiesStack.push(LastDumpedEntity(theEntity, isUserDefinedName, aResultsWithNonDefaultAttr));
   }
 
   // remove entity from the list of not dumped items
index 3c85b9ac10af3d1048eaabe47356239353338c94..3b5fee985ed37cae4b52785d248d8163e957f5ee 100644 (file)
@@ -403,12 +403,17 @@ private:
   /// Stores names of results for the given feature
   void saveResultNames(const FeaturePtr& theFeature);
 
+  bool hasShapeWithEdgeThickness(const ResultPtr& theResult, bool theGetSubResults = false) const;
+
   /// Check the result feature has colored shape
   bool hasColoredShape(const ResultPtr& theResult, bool theGetSubResults = false) const;
 
   /// Check the result is parent result int the feature
   bool isParentResult(const ResultPtr& theResult) const;
 
+  /// Check the result feature has edge thickness attribute
+  bool isEdgeThicknessDefined(const ResultPtr& theResult) const;
+
   /// Check the result feature has default color
   bool isDefaultColor(const ResultPtr& theResult) const;
 
index e2d07d5f37e1c56625ff5df1dfa9307cdcae17a6..751caab71d33705929e5c50e0779262397aa6946 100644 (file)
@@ -20,6 +20,7 @@
 #include "ModelHighAPI_Selection.h"
 
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_AttributeIntArray.h>
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_AttributeSelectionList.h>
@@ -210,6 +211,44 @@ std::wstring ModelHighAPI_Selection::name() const
   return std::wstring();
 }
 
+void ModelHighAPI_Selection::setEdgeThickness(int theValue)
+{
+  if (myVariantType != VT_ResultSubShapePair || !myResultSubShapePair.first.get())
+    return;
+
+  const auto attr = myResultSubShapePair.first->data()->integer(ModelAPI_Result::EDGE_THICKNESS_ID());
+  attr->setValue(theValue);
+}
+
+void ModelHighAPI_Selection::setEdgeThickness(const ModelHighAPI_Selection& theShape, int theValue)
+{
+  if (myVariantType != VT_ResultSubShapePair || !myResultSubShapePair.first.get())
+    return;
+
+  std::shared_ptr<GeomAPI_Shape> aShape = myResultSubShapePair.second;
+  ResultBodyPtr aResBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(myResultSubShapePair.first);
+
+  ResultPtr aRes;
+  AttributeSelectionPtr aSelAttr;
+  if (aResBody.get())
+  {
+    aSelAttr = aResBody->selection();
+    theShape.fillAttribute(aSelAttr);
+  }
+  else
+  {
+    std::wstring aSubShapeName = theShape.myTypeSubShapeNamePair.second;
+    aSubShapeName = changePartName(theShape, aSubShapeName);
+    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(myResultSubShapePair.first);
+    aSelAttr = aPart->selection();
+    aSelAttr->selectSubShape(myTypeSubShapeNamePair.first, aSubShapeName);
+  }
+  aRes = aSelAttr->context();
+  aShape = aSelAttr->value();
+  if (aRes.get() && aShape.get() && !aShape->isNull())
+    ModelAPI_Tools::setSubShapeEdgeThickness(aRes, aShape, theValue);
+}
+
 void ModelHighAPI_Selection::setColor(int theRed, int theGreen, int theBlue, bool random)
 {
   if (myVariantType != VT_ResultSubShapePair || !myResultSubShapePair.first.get())
index bffa214aa6286d7b5ca1b48e8ee9859cddd9d551..9c98dc80480f37d2c323e181a4a1a9f5060bb203 100644 (file)
@@ -132,6 +132,14 @@ public:
   MODELHIGHAPI_EXPORT
   std::wstring name() const;
 
+  /// Change edge thickness of result
+  MODELHIGHAPI_EXPORT
+  void setEdgeThickness(int theValue);
+
+  /// Change edge thickness of subshape.
+  MODELHIGHAPI_EXPORT
+  void setEdgeThickness(const ModelHighAPI_Selection& theShape, int theValue);
+
   /// Change result's color
   MODELHIGHAPI_EXPORT
   void setColor(int theRed = 0, int theGreen = 0, int theBlue = 0, bool random = false);
index 825d5a2548b98fbd4a25338cb7797e9070bffe51..9836754a36274d5779698e83c5afed40bae6460b 100644 (file)
@@ -273,13 +273,12 @@ PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
   Config_PropManager::registerProp("Visualization", "axis_arrow_size",
     "Trihedron arrows constant size", Config_Prop::IntSpin, "10");
 
+  Config_PropManager::registerProp("Visualization", "result_subshape_with_edge_thickness",
+    "Set edge thickness of subshape of result", Config_Prop::Boolean, "true");
+
   Config_PropManager::registerProp("Visualization", "color_subshape_result",
     "Set color on subshape of result", Config_Prop::Boolean, "true");
 
-  Config_PropManager::registerProp("Shortcuts", "add_parameter_shortcut",
-    "Add parameter in parameters manager dialog",
-    Config_Prop::Shortcut, "Ctrl+A");
-
   Config_PropManager::registerProp("Windows", "use_hide_faces_panel",
     "Use HideFaces panel in operations", Config_Prop::Boolean, "false");
 }
index fd71ff50bbf7480c8eeda1ac1cf2d31f8b43564b..d5dbd95c4859c913c4a87b7c046c45bf19b456b5 100644 (file)
@@ -853,6 +853,12 @@ void PartSet_Tools::getFirstAndLastIndexInFolder(const ObjectPtr& theFolder,
 }
 
 
+int PartSet_Tools::getDefaultEdgeThickness()
+{
+  return Config_PropManager::integer("Visualization", "shaper_default_edge_thickness");
+}
+
+
 void PartSet_Tools::getDefaultColor(ObjectPtr theObject, const bool isEmptyColorValid,
   std::vector<int>& theColor)
 {
index f8ae5dba73f6ea7c68e53e44cb793ae20c6a3ba0..d3a3c8761dfd9b6b9bd40237c6b90f0018fd034b 100644 (file)
@@ -313,6 +313,10 @@ public:
   static void getFirstAndLastIndexInFolder(const ObjectPtr& theFolder,
     int& theFirst, int& theLast);
 
+  /**
+  * Returns user-defined default edge thickness value
+  */
+  static int getDefaultEdgeThickness();
 
   /**
   * Returns default color value for the given object
index 06636c0fb0ff98d0067cd999add67d94f911da3c..f6873c91740d4639ff9432cddb93923767745e3a 100644 (file)
@@ -52,6 +52,7 @@
     <parameter name="scalar_bar_nb_intervals" value="20" />
     <parameter name="scalar_bar_text_color" value="#000000" />
     <parameter name="shaper_default_transparency" value="0"/>
+    <parameter name="shaper_default_edge_thickness" value="3"/>
     <parameter name="group_names_display" value="true" />
     <parameter name="group_names_font" value="Times-bold" />
     <parameter name="group_names_size" value="12" />
index dd690533ec0779ab317de4850a475a3edb703344..136034ef5aee0282a9378afcc08ea6b39065d786 100644 (file)
@@ -39,6 +39,7 @@ SET(PROJECT_HEADERS
     XGUI_DataModel.h
     XGUI_DeflectionDialog.h
     XGUI_Displayer.h
+    XGUI_EdgeThicknessWidget.h
     XGUI_ErrorDialog.h
     XGUI_ErrorMgr.h
     XGUI_FacesPanel.h
@@ -76,6 +77,7 @@ SET(PROJECT_MOC_HEADERS
     XGUI_DataModel.h
     XGUI_DeflectionDialog.h
     XGUI_Displayer.h
+    XGUI_EdgeThicknessWidget.h
     XGUI_ErrorDialog.h
     XGUI_ErrorMgr.h
     XGUI_FacesPanel.h
@@ -106,6 +108,7 @@ SET(PROJECT_SOURCES
     XGUI_DataModel.cpp
     XGUI_DeflectionDialog.cpp
     XGUI_Displayer.cpp
+    XGUI_EdgeThicknessWidget.cpp
     XGUI_ErrorDialog.cpp
     XGUI_ErrorMgr.cpp
     XGUI_FacesPanel.cpp
index 5b43656584e52835956c83072522196be2309908..cddc7578ee39f96d62a8c6ed109e1d68ad58bdbf 100644 (file)
@@ -133,6 +133,9 @@ void XGUI_ContextMenuMgr::createActions()
                                            tr("Transparency..."), aDesktop);
   addAction("TRANSPARENCY_CMD", anAction);
 
+  anAction = ModuleBase_Tools::createAction(QIcon(), tr("Edge Thickness..."), aDesktop);
+  addAction("EDGE_THICKNESS_CMD", anAction);
+
   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/eye_pencil.png"),
                                                   tr("Show"), aDesktop);
   addAction("SHOW_CMD", anAction);
@@ -553,6 +556,7 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
   action("COLOR_CMD")->setEnabled(myWorkshop->canChangeProperty("COLOR_CMD"));
   action("DEFLECTION_CMD")->setEnabled(myWorkshop->canChangeProperty("DEFLECTION_CMD"));
   action("TRANSPARENCY_CMD")->setEnabled(myWorkshop->canChangeProperty("TRANSPARENCY_CMD"));
+  action("EDGE_THICKNESS_CMD")->setEnabled(myWorkshop->canChangeProperty("EDGE_THICKNESS_CMD"));
   action("AUTOCOLOR_CMD")->setEnabled(myWorkshop->canChangeProperty("AUTOCOLOR_CMD"));
 
   #ifdef _DEBUG
@@ -684,6 +688,9 @@ void XGUI_ContextMenuMgr::updateViewerMenu()
   if (myWorkshop->canChangeProperty("TRANSPARENCY_CMD"))
     action("TRANSPARENCY_CMD")->setEnabled(true);
 
+  if (myWorkshop->canChangeProperty("EDGE_THICKNESS_CMD"))
+    action("EDGE_THICKNESS_CMD")->setEnabled(true);
+
   action("DELETE_CMD")->setEnabled(true);
 }
 
@@ -717,6 +724,7 @@ void XGUI_ContextMenuMgr::buildObjBrowserMenu()
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
   aList.append(action("TRANSPARENCY_CMD"));
+  aList.append(action("EDGE_THICKNESS_CMD"));
   aList.append(action("SHOW_FEATURE_CMD"));
   aList.append(mySeparator2);
   aList.append(action("DELETE_CMD"));
@@ -738,6 +746,7 @@ void XGUI_ContextMenuMgr::buildObjBrowserMenu()
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
   aList.append(action("TRANSPARENCY_CMD"));
+  aList.append(action("EDGE_THICKNESS_CMD"));
   aList.append(action("SHOW_ISOLINES_CMD"));
   aList.append(action("ISOLINES_CMD"));
   aList.append(action("SHOW_FEATURE_CMD"));
@@ -768,6 +777,7 @@ void XGUI_ContextMenuMgr::buildObjBrowserMenu()
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
   aList.append(action("TRANSPARENCY_CMD"));
+  aList.append(action("EDGE_THICKNESS_CMD"));
   aList.append(action("SHOW_ISOLINES_CMD"));
   aList.append(action("ISOLINES_CMD"));
   aList.append(action("SHOW_FEATURE_CMD"));
@@ -827,6 +837,7 @@ void XGUI_ContextMenuMgr::buildViewerMenu()
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
   aList.append(action("TRANSPARENCY_CMD"));
+  aList.append(action("EDGE_THICKNESS_CMD"));
   aList.append(mySeparator3);
   aList.append(action("SET_VIEW_NORMAL_CMD"));
   aList.append(action("SET_VIEW_INVERTEDNORMAL_CMD"));
@@ -846,6 +857,7 @@ void XGUI_ContextMenuMgr::buildViewerMenu()
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
   aList.append(action("TRANSPARENCY_CMD"));
+  aList.append(action("EDGE_THICKNESS_CMD"));
   aList.append(action("SHOW_ISOLINES_CMD"));
   aList.append(action("ISOLINES_CMD"));
   aList.append(mySeparator3);
@@ -869,6 +881,7 @@ void XGUI_ContextMenuMgr::buildViewerMenu()
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
   aList.append(action("TRANSPARENCY_CMD"));
+  aList.append(action("EDGE_THICKNESS_CMD"));
   aList.append(action("SHOW_ISOLINES_CMD"));
   aList.append(action("ISOLINES_CMD"));
   aList.append(mySeparator3);
@@ -925,6 +938,7 @@ void XGUI_ContextMenuMgr::addObjBrowserMenu(QMenu* theMenu) const
       anActions.append(action("COLOR_CMD"));
       anActions.append(action("DEFLECTION_CMD"));
       anActions.append(action("TRANSPARENCY_CMD"));
+      anActions.append(action("EDGE_THICKNESS_CMD"));
       anActions.append(action("SHOW_ISOLINES_CMD"));
       anActions.append(action("ISOLINES_CMD"));
       anActions.append(action("CLEAN_HISTORY_CMD"));
@@ -978,6 +992,7 @@ void XGUI_ContextMenuMgr::addViewerMenu(QMenu* theMenu) const
     anActions.append(action("COLOR_CMD"));
     anActions.append(action("DEFLECTION_CMD"));
     anActions.append(action("TRANSPARENCY_CMD"));
+    anActions.append(action("EDGE_THICKNESS_CMD"));
     anActions.append(mySeparator1);
     anActions.append(action("SHOW_ONLY_CMD"));
     anActions.append(action("HIDE_CMD"));
index 96386fe08ac36ba8233e83e9daac10c67b959912..2bd55d6e731235424143d00eed8e7723f4724a06 100644 (file)
 #pragma warning(disable: 4702)
 #endif
 
+#define EDGE_THICKNESS_DBG
+#ifdef EDGE_THICKNESS_DBG
+  #include <iostream>
+#endif /*EDGE_THICKNESS_DBG*/
+
 /// defines the local context mouse selection sensitivity
 const int MOUSE_SENSITIVITY_IN_PIXEL = 10;
 
@@ -248,7 +253,7 @@ bool XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS,
 
     // bos#40617: Apply clipping planes
     // Retrieve the clipping plane from the OCCT Presentation Manager directly,
-    // as they are stored in the ViewModel of the OCCViewer in GUI, where we 
+    // as they are stored in the ViewModel of the OCCViewer in GUI, where we
     // don't have access to.
     Handle(ViewerData_AISShape) aShape = Handle(ViewerData_AISShape)::DownCast (anAISIO);
     if (!aShape.IsNull() && aShape->IsClippable()) {
@@ -279,6 +284,7 @@ bool XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS,
       //       appear "behind" the Groups.
       aContext->SetDisplayPriority(anAISIO, FRONT_DISPLAY_PRIORITY);
     }
+
     #ifdef TINSPECTOR
     if (getCallBack()) getCallBack()->Display(anAISIO);
     #endif
@@ -374,7 +380,113 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
 
   if (!aAISIO.IsNull()) {
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
-    if (aResult.get()) {
+    if (aResult) {
+      #ifdef EDGE_THICKNESS_DBG
+      std::cout << "XGUI_Displayer::redisplay. theObject is ModelAPI_Result and has AIS_InteractiveObject." << std::endl;
+      #endif /*EDGE_THICKNESS_DBG*/
+
+      { // Set edge thickness
+        // Set edge thickness to subshapes of result
+        std::map<GeomShapePtr, int> aShapes;
+        ModelAPI_Tools::getSubShapesWithEdgeThickness(aResult, aShapes);
+
+        #ifdef EDGE_THICKNESS_DBG
+        for (const auto& shapeAndThickness : aShapes) {
+          std::cout << "Edge thickness of subshape at \"" << shapeAndThickness.first.get() << "\" is " <<  shapeAndThickness.second << std::endl;
+        }
+        #endif /*EDGE_THICKNESS_DBG*/
+
+        // Displayer overlays presentations of edge shapes with edges of face presentations.
+        // Edges of face presentations are overlaid by edges of solid presentations.
+        // Etc...
+        //
+        // This snippet is circumvention of the behaviour.
+        // Thickness is only assigned to presentations of edge subshapes of a shape.
+        // If a subshape has non-default thickness value, the value overrides thickness value of the parental shape.
+        std::map<GeomShapePtr, int> edges;
+        std::map<GeomShapePtr, int> wires;
+        std::map<GeomShapePtr, int> faces;
+        std::map<GeomShapePtr, int> shells;
+        std::map<GeomShapePtr, int> solids;
+        std::map<GeomShapePtr, int> compsolids;
+        std::map<GeomShapePtr, int> compounds;
+
+        for (auto itShapes = aShapes.begin(); itShapes != aShapes.end();) {
+          const auto& shape = itShapes->first;
+          const auto& thickness = itShapes->second;
+          const auto shapeType = shape->shapeType();
+
+          if (shapeType > GeomAPI_Shape::ShapeType::EDGE) {
+            // Do nothing.
+          }
+          else if (shapeType == GeomAPI_Shape::ShapeType::EDGE)
+            edges.emplace(shape, thickness);
+          else if (shapeType == GeomAPI_Shape::ShapeType::WIRE)
+            wires.emplace(shape, thickness);
+          else if (shapeType == GeomAPI_Shape::ShapeType::FACE)
+            faces.emplace(shape, thickness);
+          else if (shapeType == GeomAPI_Shape::ShapeType::SHELL)
+            shells.emplace(shape, thickness);
+          else if (shapeType == GeomAPI_Shape::ShapeType::SOLID)
+            solids.emplace(shape, thickness);
+          else if (shapeType == GeomAPI_Shape::ShapeType::COMPSOLID)
+            compsolids.emplace(shape, thickness);
+          else if (shapeType == GeomAPI_Shape::ShapeType::COMPOUND)
+            compounds.emplace(shape, thickness);
+
+          itShapes = aShapes.erase(itShapes);
+        }
+
+        std::map<GeomShapePtr, int> mapResultShapeThickness;
+        {
+          const int resultThickness = ModelAPI_Tools::getEdgeThickness(aResult);
+          if (resultThickness > 0) {
+            mapResultShapeThickness.emplace(aResult->shape(), resultThickness);
+            #ifdef EDGE_THICKNESS_DBG
+            std::cout << "Result edge thickness: " <<  resultThickness << std::endl;
+            #endif /*EDGE_THICKNESS_DBG*/
+          }
+        }
+
+        #ifdef EDGE_THICKNESS_DBG
+        std::cout << std::endl;
+        #endif /*EDGE_THICKNESS_DBG*/
+
+        const std::list<std::map<GeomShapePtr, int>*> thicknessMaps = {&wires, &faces, &shells, &solids, &compsolids, &compounds, &mapResultShapeThickness};
+        for (const auto pThicknessMap : thicknessMaps) {
+          const std::map<GeomShapePtr, int>& thicknessMap = *pThicknessMap;
+          for (const auto& shapeAndThickness : thicknessMap) {
+            const GeomShapePtr& shape = shapeAndThickness.first;
+            const int thickness = shapeAndThickness.second;
+
+            const std::list<GeomShapePtr> shapeEdges = shape->subShapes(GeomAPI_Shape::ShapeType::EDGE, true /*theOnlyUnique*/);
+            for (const auto& shapeEdge : shapeEdges) {
+              if (edges.find(shapeEdge) == edges.end())
+                edges.emplace(shapeEdge, thickness);
+            }
+          }
+        }
+
+        Handle(AIS_ColoredShape) aResShape = Handle(AIS_ColoredShape)::DownCast(aAISIO);
+        Handle(ModuleBase_ResultPrs) aResPrsShape = Handle(ModuleBase_ResultPrs)::DownCast(aResShape);
+        if (!aResPrsShape.IsNull()) {
+          for (const auto& edgeAndTickness : edges) {
+            const GeomShapePtr& edge = edgeAndTickness.first;
+            const int thickness = edgeAndTickness.second;
+
+            if (aAISObj->getShape()->isSubShape(edge)) {
+              aResPrsShape->SetCustomWidth(edge->impl<TopoDS_Shape>(), thickness);
+              aResPrsShape->SetCustomColor(edge->impl<TopoDS_Shape>(), Quantity_Color(Quantity_NameOfColor::Quantity_NOC_BLACK));
+            }
+            else {
+              #ifdef EDGE_THICKNESS_DBG
+              std::cout << "Edge at \"" << edge.get() << "\" is not a subshape of result !" << std::endl;
+              #endif /*EDGE_THICKNESS_DBG*/
+            }
+          }
+        }
+      }
+
       // Set color
       std::vector<int> aColor;
       ModelAPI_Tools::getColor(aResult, aColor);
@@ -406,7 +518,8 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
       }
       else
       {
-        aResShape->ClearCustomAspects();
+        // Edge thickness is also custom aspect. Don't remove aspects just because colors aren't assigned.
+        // aResShape->ClearCustomAspects();
       }
       // Set deflection
       double aDeflection = ModelAPI_Tools::getDeflection(aResult);
diff --git a/src/XGUI/XGUI_EdgeThicknessWidget.cpp b/src/XGUI/XGUI_EdgeThicknessWidget.cpp
new file mode 100644 (file)
index 0000000..7fb5e7d
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright (C) 2014-2023  CEA, EDF
+//
+// 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
+//
+
+#include "XGUI_EdgeThicknessWidget.h"
+
+
+#include <QHBoxLayout>
+#include <SalomeApp_IntSpinBox.h>
+
+
+XGUI_EdgeThicknessWidget::XGUI_EdgeThicknessWidget(QWidget* theParent)
+  : QWidget(theParent)
+{
+  auto aLayout = new QHBoxLayout(this);
+  aLayout->setContentsMargins(0, 0, 0, 0);
+
+  mySpinBox = new SalomeApp_IntSpinBox();
+  mySpinBox->setRange(1, 5);
+  mySpinBox->setDefaultValue(1);
+  mySpinBox->setSingleStep(1);
+  mySpinBox->setObjectName("EdgeThicknessSpinBox");
+  mySpinBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+  mySpinBox->setValue(1);
+  aLayout->addWidget(mySpinBox, 0, Qt::AlignCenter);
+
+  connect(mySpinBox, SIGNAL(valueChanged(int)), this, SIGNAL(thicknessValueChanged(int)));
+}
+
+void XGUI_EdgeThicknessWidget::setValue(int theValue)
+{
+  bool isSpinBoxBlocked = mySpinBox->blockSignals(true);
+  mySpinBox->setValue(theValue);
+  mySpinBox->blockSignals(isSpinBoxBlocked);
+}
+
+int XGUI_EdgeThicknessWidget::getValue() const
+{
+  return mySpinBox->value();
+}
\ No newline at end of file
diff --git a/src/XGUI/XGUI_EdgeThicknessWidget.h b/src/XGUI/XGUI_EdgeThicknessWidget.h
new file mode 100644 (file)
index 0000000..c72ae36
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (C) 2014-2023  CEA, EDF
+//
+// 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
+//
+
+#ifndef XGUI_EdgeThicknessWidget_H
+#define XGUI_EdgeThicknessWidget_H
+
+#include "XGUI.h"
+#include <QWidget>
+
+class SalomeApp_IntSpinBox;
+
+/**
+* \ingroup GUI
+* A class of a widget to chose edge thickness. Range of values is Natural:[0; 5].
+*/
+class XGUI_EdgeThicknessWidget : public QWidget
+{
+  Q_OBJECT
+
+public:
+/// Constructor
+  /// \param theParent a parent widget for the dialog
+  /// \param theLabelText if not empty, the information label will be shown in the widget
+  XGUI_EXPORT XGUI_EdgeThicknessWidget(QWidget* theParent);
+  XGUI_EXPORT ~XGUI_EdgeThicknessWidget() = default;
+
+  /// Initializes the dialog with the given value.
+  /// \param theValue edge thickness value
+  void setValue(int theValue);
+
+  /// Returns the current edge thickness value.
+  /// \return value
+  int getValue() const;
+
+signals:
+  void thicknessValueChanged(int);
+
+private:
+ SalomeApp_IntSpinBox* mySpinBox;
+};
+
+#endif // XGUI_EdgeThicknessWidget_H
\ No newline at end of file
index 3d128ef705d71bb6b258d006a69a78f404a00e54..f2edff5f9b9305fa5eca784ee5dff547ae70e2b4 100644 (file)
@@ -25,6 +25,7 @@
 #include "XGUI_MenuMgr.h"
 #include "XGUI_ColorDialog.h"
 #include "XGUI_DeflectionDialog.h"
+#include "XGUI_EdgeThicknessWidget.h"
 #include "XGUI_TransparencyWidget.h"
 #include "XGUI_ContextMenuMgr.h"
 #include "XGUI_Displayer.h"
@@ -1794,6 +1795,8 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
     moveObjects(theId == "MOVE_SPLIT_CMD");
   else if (theId == "RECOVER_CMD")
     recoverFeature();
+  else if (theId == "EDGE_THICKNESS_CMD")
+    changeEdgeThickness(aSelectedObjects);
   else if (theId == "COLOR_CMD")
     changeColor(aSelectedObjects);
   else if (theId == "AUTOCOLOR_CMD")
@@ -2517,9 +2520,11 @@ bool XGUI_Workshop::canBeShaded(const ObjectPtr& theObject) const
 bool XGUI_Workshop::canChangeProperty(const QString& theActionName) const
 {
   if (theActionName == "COLOR_CMD" ||
+      theActionName == "EDGE_THICKNESS_CMD" ||
       theActionName == "DEFLECTION_CMD" ||
       theActionName == "TRANSPARENCY_CMD") {
     QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
+    // List of std::shared_ptr<ModelAPI_Object>
 
     std::set<std::string> aTypes;
     aTypes.insert(ModelAPI_ResultGroup::group());
@@ -2527,6 +2532,34 @@ bool XGUI_Workshop::canChangeProperty(const QString& theActionName) const
     aTypes.insert(ModelAPI_ResultBody::group());
     aTypes.insert(ModelAPI_ResultPart::group());
 
+    /* TODO Get shape type correctly.
+    if (theActionName == "COLOR_CMD") {
+      // Do not show Color dialog in context menus if nothing face-containing is selected.
+      bool isFaceContainingShapeSelected = false;
+      for (const auto& object : anObjects) {
+        if (object->shape().ShapeType() <= TopAbs_ShapeEnum::TopAbs_FACE) {
+          isFaceContainingShapeSelected = true;
+          break;
+        }
+      }
+
+      if (!isFaceContainingShapeSelected)
+        return false;
+    }
+    else if (theActionName == "EDGE_THICKNESS_CMD") {
+      // Do not show Edge Thickness dialog in context menus if nothing edge-containing is selected.
+      bool isEdgeContainingShapeSelected = false;
+      for (const auto& object : anObjects) {
+        if (object->shape().ShapeType() <= TopAbs_ShapeEnum::TopAbs_EDGE) {
+          isEdgeContainingShapeSelected = true;
+          break;
+        }
+      }
+
+      if (!isEdgeContainingShapeSelected)
+        return false;
+    }*/
+
     return hasResults(anObjects, aTypes);
   }
   if (theActionName == "AUTOCOLOR_CMD") {
@@ -2564,6 +2597,117 @@ void getDefaultColor(ObjectPtr theObject, const bool isEmptyColorValid,
   }
 }
 
+
+//**************************************************************
+/// Returns user-defined default edge thickness.
+int getDefaultEdgeThickness()
+{
+  return Config_PropManager::integer("Visualization", "shaper_default_edge_thickness");
+}
+
+
+
+//**************************************************************
+void XGUI_Workshop::changeEdgeThickness(const QMap<ResultPtr, QList<GeomShapePtr>>& theSelectedObjects)
+{
+  int thickness = -1;
+  // 1. find current edge thickness of the object. This is an edge thickness of AIS presentation.
+  // The objects are iterated until a first valid thickness is found.
+  QList<ModuleBase_ViewerPrsPtr> aValues = mySelector->selection()->getSelected(ModuleBase_ISelection::Viewer);
+  const bool aEdgeThicknessOfSubShapesEnabled = Config_PropManager::boolean("Visualization", "result_subshape_with_edge_thickness");
+  foreach(ResultPtr aResult, theSelectedObjects.keys())
+  {
+    if (!aResult)
+      continue;
+
+    foreach(GeomShapePtr aShape, theSelectedObjects[aResult]) {
+      if (aResult->shape()->impl<TopoDS_Shape>().IsEqual(aShape->impl<TopoDS_Shape>()) || !aEdgeThicknessOfSubShapesEnabled)
+        thickness = ModelAPI_Tools::getEdgeThickness(aResult);
+      else if (!aShape->isNull()) {
+        thickness = ModelAPI_Tools::getSubShapeEdgeThickness(aResult, aShape);
+        if (thickness <= 0)
+          thickness = ModelAPI_Tools::getEdgeThickness(aResult);
+      }
+
+      if (thickness <= 0) {
+        AISObjectPtr anAISObj = myDisplayer->getAISObject(aResult);
+        if (anAISObj) {
+          thickness = getDefaultEdgeThickness();
+          const double aAISThickness = anAISObj->width();
+          if (aAISThickness >= 1)
+            thickness = int(aAISThickness);
+        }
+      }
+
+      if (thickness <= 0)
+        thickness = getDefaultEdgeThickness();
+
+      if (thickness > 0 || !aEdgeThicknessOfSubShapesEnabled)
+        break;
+    }
+
+    if (thickness > 0)
+      break;
+  }
+
+  if (thickness <= 0)
+    return;
+
+  if (!abortAllOperations())
+    return;
+
+  // 2. show the dialog to change the value
+  const auto dialog = new XGUI_PropertyDialog(desktop());
+  dialog->setWindowTitle(tr("Edge Thickness"));
+  const XGUI_EdgeThicknessWidget* edgeThicknessWidget = new XGUI_EdgeThicknessWidget(dialog);
+  dialog->setContent(edgeThicknessWidget);
+  edgeThicknessWidget->setValue(thickness);
+  if (dialog->exec() != QDialog::Accepted)
+    return;
+
+  // bool isSetToShape = dialog->isSetOnSubShape();
+  const bool isSetToShape = true;
+
+  // 3. abort the previous operation and start a new one
+  SessionPtr aMgr = ModelAPI_Session::get();
+  QString aDescription = contextMenuMgr()->action("EDGE_THICKNESS_CMD")->text();
+
+  aMgr->startOperation(aDescription.toStdString());
+
+  // 4. set the value to all results and subshapes from result (if subshape of result were selected).
+  const int newThickness = edgeThicknessWidget->getValue();
+  foreach(ResultPtr aResult, theSelectedObjects.keys()) {
+    if (!aResult)
+      continue;
+
+    ResultBodyPtr aBodyResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
+    foreach(GeomShapePtr aShape, theSelectedObjects[aResult]) {
+      if (aResult->shape()->impl<TopoDS_Shape>().IsEqual(aShape->impl<TopoDS_Shape>()) || !aEdgeThicknessOfSubShapesEnabled || !isSetToShape) {
+        if (aResult.get() != NULL) {
+          // change edge thickness for all sub-solids
+          std::list<ResultPtr> allRes;
+          ModelAPI_Tools::allSubs(aBodyResult, allRes);
+          for (std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
+            ModelAPI_Tools::setEdgeThickness(*aRes, newThickness);
+          }
+          ModelAPI_Tools::setEdgeThickness(aResult, newThickness);
+        }
+        if (!aEdgeThicknessOfSubShapesEnabled)
+          break;
+      }
+      else if (!aShape->isNull()) {
+        ModelAPI_Tools::setSubShapeEdgeThickness(aResult, aShape, newThickness);
+      }
+    }
+  }
+
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+  aMgr->finishOperation();
+  updateCommandStatus();
+  myViewerProxy->update();
+}
+
+
 //**************************************************************
 void XGUI_Workshop::changeColor(const QMap<ResultPtr, QList<GeomShapePtr>>& theSelectedObjects)
 {
index e3d949a7e6955639acbba2a75841ae4c65f02db3..7d013bdb5391fe7a2d7d8a6c3fc1551d5d93faa9 100644 (file)
@@ -201,6 +201,11 @@ Q_OBJECT
   /// \return boolean value
   bool canChangeProperty(const QString& theActionName) const;
 
+  /// Change edge thickness of the results if it is possible.
+  /// The operation is available for construction, body and group results.
+  /// \param theObjects refers to selected objects.
+  void changeEdgeThickness(const QMap<ResultPtr, QList<GeomShapePtr>>& theObjects);
+
   /// Change color of the selected objects (result and subshape of result) if it is possible
   /// The operation is available for subshape of result, construction, body and group results
   /// theSelectedObjects a list of selected objects
index 9d89050d2aa3121ffd3d50b36e79987094369d23..643f74d70f01a6e08ac0e8995224711ad9ecfa45 100644 (file)
         <source>Transparency...</source>
         <translation>Transparence...</translation>
     </message>
+    <message>
+        <source>Edge Thickness...</source>
+        <translation>Epaisseur Des Aretes...</translation>
+    </message>
     <message>
         <source>Show</source>
         <translation>Voir</translation>