Salome HOME
901686539335c7f790e82502a9852d5438fd7a87
[modules/shaper.git] / src / Model / Model_AttributeSelection.cpp
1 // File:        Model_AttributeSelection.h
2 // Created:     2 Oct 2014
3 // Author:      Mikhail PONIKAROV
4
5 #include "Model_AttributeSelection.h"
6 #include "Model_Application.h"
7 #include "Model_Events.h"
8 #include "Model_Data.h"
9 #include <ModelAPI_Feature.h>
10 #include <ModelAPI_ResultBody.h>
11 #include <ModelAPI_ResultConstruction.h>
12 #include <ModelAPI_CompositeFeature.h>
13 #include <GeomAPI_Shape.h>
14
15 #include <TNaming_Selector.hxx>
16 #include <TNaming_NamedShape.hxx>
17 #include <TNaming_Tool.hxx>
18 #include <TopoDS_Shape.hxx>
19 #include <TDataStd_ReferenceList.hxx>
20 #include <TopTools_MapOfShape.hxx>
21 #include <TopExp_Explorer.hxx>
22
23 using namespace std;
24
25 void Model_AttributeSelection::setValue(const ResultPtr& theContext,
26   const boost::shared_ptr<GeomAPI_Shape>& theSubShape)
27 {
28   const boost::shared_ptr<GeomAPI_Shape>& anOldShape = value();
29   bool isOldShape = 
30     (theSubShape == anOldShape || (theSubShape && anOldShape && theSubShape->isEqual(anOldShape)));
31   if (isOldShape) return; // shape is the same, so context is also unchanged
32   // update the referenced object if needed
33   bool isOldContext = theContext == myRef.value();
34   if (!isOldContext)
35     myRef.setValue(theContext);
36
37   if (theContext->groupName() == ModelAPI_ResultBody::group())
38     selectBody(theContext, theSubShape);
39   else if (theContext->groupName() == ModelAPI_ResultConstruction::group())
40     selectConstruction(theContext, theSubShape);
41
42   myIsInitialized = true;
43   owner()->data()->sendAttributeUpdated(this);
44 }
45
46 boost::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
47 {
48   boost::shared_ptr<GeomAPI_Shape> aResult;
49   if (myIsInitialized) {
50     Handle(TNaming_NamedShape) aSelection;
51     if (myRef.myRef->Label().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
52       TopoDS_Shape aSelShape = aSelection->Get();
53       aResult->setImpl(&aSelShape);
54     }
55   }
56   return aResult;
57 }
58
59 Model_AttributeSelection::Model_AttributeSelection(TDF_Label& theLabel)
60   : myRef(theLabel)
61 {
62   myIsInitialized = myRef.isInitialized();
63 }
64
65 ResultPtr Model_AttributeSelection::context() {
66   return boost::dynamic_pointer_cast<ModelAPI_Result>(myRef.value());
67 }
68
69
70 void Model_AttributeSelection::setObject(const boost::shared_ptr<ModelAPI_Object>& theObject)
71 {
72   ModelAPI_AttributeSelection::setObject(theObject);
73   myRef.setObject(theObject);
74 }
75
76 void Model_AttributeSelection::selectBody(
77     const ResultPtr& theContext, const boost::shared_ptr<GeomAPI_Shape>& theSubShape)
78 {
79   // perform the selection
80   TNaming_Selector aSel(myRef.myRef->Label());
81   TopoDS_Shape aNewShape = theSubShape ? theSubShape->impl<TopoDS_Shape>() : TopoDS_Shape();
82   TopoDS_Shape aContext;
83
84   ResultBodyPtr aBody = boost::dynamic_pointer_cast<ModelAPI_ResultBody>(myRef.value());
85   if (aBody)
86     aContext = aBody->shape()->impl<TopoDS_Shape>();
87   else {
88     ResultConstructionPtr aConstr = boost::dynamic_pointer_cast<ModelAPI_ResultConstruction>(myRef.value());
89     if (aConstr)
90       aContext = aConstr->shape()->impl<TopoDS_Shape>();
91     else
92       throw std::invalid_argument("a result with shape is expected");
93   }
94   Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aNewShape, myRef.myRef->Label());
95   TDF_Label aLab = aNS->Label();
96
97   aSel.Select(aNewShape, aContext);
98 }
99
100 #include <BRepTools.hxx>
101
102 void Model_AttributeSelection::selectConstruction(
103     const ResultPtr& theContext, const boost::shared_ptr<GeomAPI_Shape>& theSubShape)
104 {
105   FeaturePtr aContextFeature = owner()->document()->feature(theContext);
106   CompositeFeaturePtr aComposite = 
107     boost::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature);
108   if (!aComposite || aComposite->numberOfSubs() == 0) {
109     return; // saving of context is enough: result construction contains exactly the needed shape
110   }
111   boost::shared_ptr<Model_Data> aData = boost::dynamic_pointer_cast<Model_Data>(owner()->data());
112   TDF_Label aLab = aData->label();
113   // identify the reuslts of sub-object of the composite by edges
114   const TopoDS_Shape& aSubShape = theSubShape->impl<TopoDS_Shape>();
115   TopTools_MapOfShape allEdges;
116   for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) {
117     BRepTools::Write(anEdgeExp.Current(), "D:\\selected.brep");
118     allEdges.Add(anEdgeExp.Current());
119   }
120   // iterate and store the result ids of sub-elements
121   Handle(TDataStd_ReferenceList) aRefs = TDataStd_ReferenceList::Set(aLab);
122   const int aSubNum = aComposite->numberOfSubs();
123   for(int a = 0; a < aSubNum; a++) {
124     FeaturePtr aSub = aComposite->subFeature(a);
125     const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
126     std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
127     // there may be many shapes (circle and center): register if at least one is in selection
128     for(; aRes != aResults.cend(); aRes++) {
129       ResultConstructionPtr aConstr = 
130         boost::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
131       if (aConstr->shape()) {
132         const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
133         BRepTools::Write(aResShape, "D:\\sub.brep");
134         if (allEdges.Contains(aResShape)) {
135           boost::shared_ptr<Model_Data> aSubData = boost::dynamic_pointer_cast<Model_Data>(aSub->data());
136           TDF_Label aSubLab = aSubData->label();
137           aRefs->Append(aSubLab);
138         }
139       }
140     }
141   }
142 }