1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include <FeaturesPlugin_CompositeSketch.h>
23 #include <ModelAPI_AttributeSelectionList.h>
24 #include <ModelAPI_AttributeReference.h>
25 #include <ModelAPI_BodyBuilder.h>
26 #include <ModelAPI_ResultConstruction.h>
27 #include <ModelAPI_Session.h>
28 #include <ModelAPI_Validator.h>
30 #include <GeomAlgoAPI_CompoundBuilder.h>
31 #include <GeomAlgoAPI_Prism.h>
32 #include <GeomAlgoAPI_Revolution.h>
33 #include <GeomAlgoAPI_ShapeTools.h>
34 #include <GeomAlgoAPI_SketchBuilder.h>
36 #include <GeomAPI_PlanarEdges.h>
37 #include <GeomAPI_ShapeExplorer.h>
42 static void storeSubShape(const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
43 ResultBodyPtr theResultBody,
44 const GeomShapePtr theShape,
45 const GeomAPI_Shape::ShapeType theType,
46 const std::string& theName);
48 //=================================================================================================
49 void FeaturesPlugin_CompositeSketch::initCompositeSketchAttribtues(const int theInitFlags)
51 // Initialize sketch launcher.
52 if(theInitFlags & InitSketchLauncher) {
53 data()->addAttribute(SKETCH_ID(), ModelAPI_AttributeReference::typeId());
54 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_ID());
57 // Initialize selection list.
58 if(theInitFlags & InitBaseObjectsList) {
59 data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
63 //=================================================================================================
64 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::addFeature(std::string theID)
66 FeaturePtr aNew = document()->addFeature(theID, false);
68 data()->reference(SKETCH_ID())->setValue(aNew);
71 // Set as current also after it becomes sub to set correctly enabled for other sketch subs.
72 document()->setCurrentFeature(aNew, false);
76 //=================================================================================================
77 int FeaturesPlugin_CompositeSketch::numberOfSubs(bool forTree) const
79 ObjectPtr aObj = data()->reference(SKETCH_ID())->value();
80 return aObj.get() ? 1 : 0;
83 //=================================================================================================
84 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::subFeature(const int theIndex,
87 FeaturePtr aSubFeature;
90 std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
95 //=================================================================================================
96 int FeaturesPlugin_CompositeSketch::subFeatureId(const int theIndex) const
100 std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
102 return aFeature->data()->featureId();
109 //=================================================================================================
110 bool FeaturesPlugin_CompositeSketch::isSub(ObjectPtr theObject) const
112 bool isSubFeature = false;
113 // Check is this feature of result
114 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
115 if (aFeature.get()) {
116 ObjectPtr aSub = data()->reference(SKETCH_ID())->value();
117 isSubFeature = aSub == theObject;
122 //=================================================================================================
123 void FeaturesPlugin_CompositeSketch::removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature)
125 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
126 if(aBaseObjectsSelectionList.get() && aBaseObjectsSelectionList->size() > 0) {
127 aBaseObjectsSelectionList->clear();
130 reference(SKETCH_ID())->setValue(ObjectPtr());
133 //=================================================================================================
134 void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList,
135 const bool theIsMakeShells)
137 theBaseShapesList.clear();
139 ListOfShape aBaseFacesList;
140 std::map<ResultConstructionPtr, ListOfShape> aSketchWiresMap;
141 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
142 if(!aBaseObjectsSelectionList.get()) {
143 setError("Error: Could not get base objects selection list.");
146 if(aBaseObjectsSelectionList->size() == 0) {
147 setError("Error: Base objects list is empty.");
150 for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
151 AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
152 if(!aBaseObjectSelection.get()) {
153 setError("Error: Selected base object is empty.");
156 GeomShapePtr aBaseShape = aBaseObjectSelection->value();
157 if(aBaseShape.get() && !aBaseShape->isNull()) {
158 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
159 if(aST == GeomAPI_Shape::SOLID || aST == GeomAPI_Shape::COMPSOLID) {
160 setError("Error: Selected shapes has unsupported type.");
163 ResultConstructionPtr aConstruction =
164 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
165 if(aConstruction.get() && !aBaseShape->isEqual(aConstruction->shape()) &&
166 aST == GeomAPI_Shape::WIRE) {
167 // It is a wire on the sketch, store it to make face later.
168 aSketchWiresMap[aConstruction].push_back(aBaseShape);
171 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
172 theBaseShapesList.push_back(aBaseShape);
175 // This may be the whole sketch result selected, check and get faces.
176 ResultConstructionPtr aConstruction =
177 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
178 if(!aConstruction.get()) {
179 setError("Error: Selected sketches does not have results.");
182 int aFacesNum = aConstruction->facesNum();
184 // Probably it can be construction.
185 aBaseShape = aConstruction->shape();
186 if(aBaseShape.get() && !aBaseShape->isNull()) {
187 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
188 if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE &&
189 aST != GeomAPI_Shape::WIRE &&
190 aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
191 setError("Error: Selected shapes has unsupported type.");
194 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
195 theBaseShapesList.push_back(aBaseShape);
198 for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
199 GeomShapePtr aBaseFace = aConstruction->face(aFaceIndex);
200 if(!aBaseFace.get() || aBaseFace->isNull()) {
201 setError("Error: One of the faces on selected sketch is null.");
204 aBaseFacesList.push_back(aBaseFace);
210 // Make faces from sketch wires.
211 for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
212 anIt != aSketchWiresMap.cend(); ++anIt) {
213 const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
214 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
215 const ListOfShape& aWiresList = (*anIt).second;
217 GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
218 aSketchPlanarEdges->norm(),
221 aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
224 // Searching faces with common edges.
225 if(theIsMakeShells && aBaseFacesList.size() > 1) {
227 ListOfShape aFreeFaces;
228 GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
229 GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL,
230 aShells, aFreeFaces);
231 theBaseShapesList.insert(theBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
232 theBaseShapesList.insert(theBaseShapesList.end(), aShells.begin(), aShells.end());
234 theBaseShapesList.insert(theBaseShapesList.end(), aBaseFacesList.begin(),
235 aBaseFacesList.end());
239 //=================================================================================================
240 void FeaturesPlugin_CompositeSketch::storeResult(const GeomShapePtr theBaseShape,
241 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
244 // Create result body.
245 ResultBodyPtr aResultBody = document()->createBody(data(), theIndex);
247 // Store generated shape.
248 aResultBody->storeGenerated(theBaseShape, theMakeShape->shape());
250 // Store generated edges/faces.
251 storeGenerationHistory(aResultBody, theBaseShape, theMakeShape);
253 setResult(aResultBody, theIndex);
256 //=================================================================================================
257 void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theResultBody,
258 const GeomShapePtr theBaseShape,
259 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
261 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
262 GeomAPI_Shape::ShapeType aShapeTypeToExplode = GeomAPI_Shape::SHAPE;
264 switch(aBaseShapeType) {
265 case GeomAPI_Shape::EDGE: {
266 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
269 case GeomAPI_Shape::WIRE: {
270 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
273 case GeomAPI_Shape::FACE:
274 case GeomAPI_Shape::SHELL: {
275 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
278 case GeomAPI_Shape::COMPOUND: {
279 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
283 int aLateralIndex = 1;
284 int aBaseEdgeIndex = 1;
285 int aVertexIndex = 1;
286 int aBaseVertexIndex = 1;
288 if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX ||
289 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
290 theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::VERTEX);
292 if(aShapeTypeToExplode == GeomAPI_Shape::EDGE ||
293 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
294 theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::EDGE);
296 std::list<std::shared_ptr<GeomAlgoAPI_MakeSweep> > aSweeps; // all sweeps collected
297 std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep =
298 std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
299 if(aMakeSweep.get()) {
300 aSweeps.push_back(aMakeSweep);
302 std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeList =
303 std::dynamic_pointer_cast<GeomAlgoAPI_MakeShapeList>(theMakeShape);
304 if (aMakeList.get()) {
305 ListOfMakeShape::const_iterator anIter = aMakeList->list().cbegin();
306 for(; anIter != aMakeList->list().cend(); anIter++) {
307 std::shared_ptr<GeomAlgoAPI_MakeSweep> aSweep =
308 std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(*anIter);
310 aSweeps.push_back(aSweep);
314 std::list<std::shared_ptr<GeomAlgoAPI_MakeSweep> >::iterator aSweep = aSweeps.begin();
315 for(; aSweep != aSweeps.end(); aSweep++) {
316 // Store from shapes.
317 storeShapes(theMakeShape, theResultBody, aBaseShapeType, (*aSweep)->fromShapes(), "From_");
320 storeShapes(theMakeShape, theResultBody, aBaseShapeType, (*aSweep)->toShapes(), "To_");
324 //=================================================================================================
325 void FeaturesPlugin_CompositeSketch::storeShapes(
326 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
327 ResultBodyPtr theResultBody,
328 const GeomAPI_Shape::ShapeType theBaseShapeType,
329 const ListOfShape& theShapes,
330 const std::string theName)
332 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
333 std::string aShapeTypeStr = "Face";
334 switch(theBaseShapeType) {
335 case GeomAPI_Shape::VERTEX: {
336 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
337 aShapeTypeStr = "Vertex";
340 case GeomAPI_Shape::EDGE:
341 case GeomAPI_Shape::WIRE: {
342 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
343 aShapeTypeStr = "Edge";
346 case GeomAPI_Shape::FACE:
347 case GeomAPI_Shape::SHELL: {
348 aShapeTypeToExplore = GeomAPI_Shape::FACE;
349 aShapeTypeStr = "Face";
352 case GeomAPI_Shape::COMPOUND: {
353 aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
359 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
360 GeomShapePtr aShape = *anIt;
362 if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
363 std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
364 storeSubShape(theMakeShape, theResultBody, aShape, aShape->shapeType(), aName);
366 std::string aName = theName + aShapeTypeStr;
367 storeSubShape(theMakeShape, theResultBody, aShape, aShapeTypeToExplore, aName);
368 if (theBaseShapeType == GeomAPI_Shape::WIRE) { // issue 2289: special names also for vertices
369 aName = theName + "Vertex";
370 storeSubShape(theMakeShape, theResultBody, aShape, GeomAPI_Shape::VERTEX, aName);
377 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
378 ResultBodyPtr theResultBody,
379 const GeomShapePtr theShape,
380 const GeomAPI_Shape::ShapeType theType,
381 const std::string& theName)
383 for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
384 GeomShapePtr aSubShape = anExp.current();
385 if (!theResultBody->generated(aSubShape, theName)) {
386 // store from/to shapes as primitives and then store modification of them by the boolean
387 theResultBody->generated(aSubShape, theName, false);
388 theResultBody->loadModifiedShapes(theMakeShape, aSubShape, theType);