Salome HOME
e557498945a3add650f18bbbd6c4fa805341670b
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Intersection.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "FeaturesPlugin_Intersection.h"
22
23 #include <ModelAPI_Data.h>
24 #include <ModelAPI_Document.h>
25 #include <ModelAPI_BodyBuilder.h>
26 #include <ModelAPI_ResultBody.h>
27 #include <ModelAPI_AttributeSelectionList.h>
28
29 #include <GeomAlgoAPI_Intersection.h>
30 #include <GeomAPI_ShapeExplorer.h>
31
32 #include <sstream>
33
34 //=================================================================================================
35 FeaturesPlugin_Intersection::FeaturesPlugin_Intersection()
36 {
37 }
38
39 //=================================================================================================
40 void FeaturesPlugin_Intersection::initAttributes()
41 {
42   data()->addAttribute(FeaturesPlugin_Intersection::OBJECT_LIST_ID(),
43                        ModelAPI_AttributeSelectionList::typeId());
44   data()->addAttribute(FeaturesPlugin_Intersection::TOOL_LIST_ID(),
45                        ModelAPI_AttributeSelectionList::typeId());
46 }
47
48 //=================================================================================================
49 void FeaturesPlugin_Intersection::execute()
50 {
51   ListOfShape anObjects, aTools;
52
53   // Getting objects.
54   AttributeSelectionListPtr anObjectsSelList =
55     selectionList(FeaturesPlugin_Intersection::OBJECT_LIST_ID());
56   for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
57     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
58       anObjectsSelList->value(anObjectsIndex);
59     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
60     if (!anObject.get()) {
61       return;
62     }
63     anObjects.push_back(anObject);
64   }
65
66   // Getting tools.
67   AttributeSelectionListPtr aToolsSelList =
68     selectionList(FeaturesPlugin_Intersection::TOOL_LIST_ID());
69   for (int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
70     std::shared_ptr<ModelAPI_AttributeSelection> aToolAttr = aToolsSelList->value(aToolsIndex);
71     std::shared_ptr<GeomAPI_Shape> aTool = aToolAttr->value();
72     if (!aTool.get()) {
73       return;
74     }
75     aTools.push_back(aTool);
76   }
77
78   if(anObjects.empty() || aTools.empty()) {
79     setError("Error: Objects or tools are empty.");
80     return;
81   }
82
83   int aResultIndex = 0;
84
85   // Create result for each object.
86   for (ListOfShape::iterator
87        anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) {
88     std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
89     ListOfShape aListWithObject; aListWithObject.push_back(anObject);
90     GeomAlgoAPI_Intersection anIntersectionAlgo(aListWithObject, aTools);
91
92     // Checking that the algorithm worked properly.
93     if (!anIntersectionAlgo.isDone()) {
94       static const std::string aFeatureError = "Error: Intersection algorithm failed.";
95       setError(aFeatureError);
96       return;
97     }
98     if (anIntersectionAlgo.shape()->isNull()) {
99       static const std::string aShapeError = "Error: Resulting shape is Null.";
100       setError(aShapeError);
101       return;
102     }
103     if (!anIntersectionAlgo.isValid()) {
104       std::string aFeatureError = "Error: Resulting shape is not valid.";
105       setError(aFeatureError);
106       return;
107     }
108
109     std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
110     loadNamingDS(aResultBody, anObject, aTools, anIntersectionAlgo);
111     setResult(aResultBody, aResultIndex);
112     aResultIndex++;
113   }
114
115   // remove the rest results if there were produced in the previous pass
116   removeResults(aResultIndex);
117 }
118
119 //=================================================================================================
120 void FeaturesPlugin_Intersection::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
121                                                const std::shared_ptr<GeomAPI_Shape> theBaseShape,
122                                                const ListOfShape& theTools,
123                                                GeomAlgoAPI_MakeShape& theMakeShape)
124 {
125   std::shared_ptr<GeomAPI_Shape> aResultShape = theMakeShape.shape();
126   theResultBody->storeModified(theBaseShape, aResultShape);
127
128   const int aDeletedVertexTag = 1;
129   const int aDeletedEdgeTag   = 2;
130   const int aDeletedFaceTag   = 3;
131
132   theResultBody->loadDeletedShapes(&theMakeShape,
133                                    theBaseShape,
134                                    GeomAPI_Shape::VERTEX,
135                                    aDeletedVertexTag);
136   theResultBody->loadDeletedShapes(&theMakeShape,
137                                    theBaseShape,
138                                    GeomAPI_Shape::EDGE,
139                                    aDeletedEdgeTag);
140   theResultBody->loadDeletedShapes(&theMakeShape,
141                                    theBaseShape,
142                                    GeomAPI_Shape::FACE,
143                                    aDeletedFaceTag);
144
145   ListOfShape aShapes = theTools;
146   aShapes.push_back(theBaseShape);
147   GeomAPI_DataMapOfShapeShape aShapesMap; // Map to store {result_shape, original_shape}
148   const int aShapeTypesNb = 2;
149   const GeomAPI_Shape::ShapeType aShapeTypes[aShapeTypesNb] =
150     {GeomAPI_Shape::VERTEX, GeomAPI_Shape::EDGE};
151   for(ListOfShape::const_iterator anIt = aShapes.cbegin(); anIt != aShapes.cend(); ++anIt) {
152     const GeomShapePtr aShape = *anIt;
153     for(int anIndex = 0; anIndex < aShapeTypesNb; ++anIndex) {
154       for(GeomAPI_ShapeExplorer anOrigShapeExp(aShape, aShapeTypes[anIndex]);
155           anOrigShapeExp.more();
156           anOrigShapeExp.next()) {
157         ListOfShape aHistory;
158         const GeomShapePtr aSubShape = anOrigShapeExp.current();
159         theMakeShape.modified(aSubShape, aHistory);
160         for(ListOfShape::const_iterator aHistoryIt = aHistory.cbegin();
161             aHistoryIt != aHistory.cend();
162             ++aHistoryIt) {
163           aShapesMap.bind(*aHistoryIt, aSubShape);
164         }
165       }
166     }
167   }
168
169   int aModifiedVertexIndex(1),
170       aGeneratedVertexIndex(1),
171       aModifiedEdgeIndex(1),
172       aGeneratedEdgeIndex(1);
173   int aTag = 4;
174   GeomAPI_DataMapOfShapeShape aStoredShapes;
175   for(int anIndex = 0; anIndex < aShapeTypesNb; ++anIndex) {
176     for(GeomAPI_ShapeExplorer aShapeExp(aResultShape, aShapeTypes[anIndex]);
177         aShapeExp.more();
178         aShapeExp.next()) {
179       const GeomShapePtr aSubShape = aShapeExp.current();
180       if(aStoredShapes.isBound(aSubShape)) {
181         continue;
182       }
183       if(aShapesMap.isBound(aSubShape)) {
184         theResultBody->modified(aShapesMap.find(aSubShape),
185           aSubShape,
186           std::string("Modified_")
187             + (anIndex == 0 ? "Vertex_" : "Edge_")
188             + std::to_string((long long)(anIndex == 0 ? aModifiedVertexIndex++
189                                                       : aModifiedEdgeIndex++)),
190           aTag++);
191       } else {
192         theResultBody->generated(aSubShape,
193           std::string("Generated_")
194             + (anIndex == 0 ? "Vertex_" : "Edge_")
195             + std::to_string((long long)(anIndex == 0 ? aGeneratedVertexIndex++
196                                                       : aGeneratedEdgeIndex++)),
197           aTag++);
198       }
199       aStoredShapes.bind(aSubShape, aSubShape);
200     }
201   }
202 }