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(ResultBodyPtr theResultBody,
43 const GeomShapePtr theShape,
44 const GeomAPI_Shape::ShapeType theType,
45 const std::string& theName);
47 //=================================================================================================
48 void FeaturesPlugin_CompositeSketch::initCompositeSketchAttribtues(const int theInitFlags)
50 // Initialize sketch launcher.
51 if(theInitFlags & InitSketchLauncher) {
52 data()->addAttribute(SKETCH_ID(), ModelAPI_AttributeReference::typeId());
53 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_ID());
56 // Initialize selection list.
57 if(theInitFlags & InitBaseObjectsList) {
58 data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
62 //=================================================================================================
63 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::addFeature(std::string theID)
65 FeaturePtr aNew = document()->addFeature(theID, false);
67 data()->reference(SKETCH_ID())->setValue(aNew);
70 // Set as current also after it becomes sub to set correctly enabled for other sketch subs.
71 document()->setCurrentFeature(aNew, false);
75 //=================================================================================================
76 int FeaturesPlugin_CompositeSketch::numberOfSubs(bool forTree) const
78 ObjectPtr aObj = data()->reference(SKETCH_ID())->value();
79 return aObj.get() ? 1 : 0;
82 //=================================================================================================
83 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::subFeature(const int theIndex,
87 return std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
90 return std::shared_ptr<ModelAPI_Feature>();
93 //=================================================================================================
94 int FeaturesPlugin_CompositeSketch::subFeatureId(const int theIndex) const
98 std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
100 return aFeature->data()->featureId();
107 //=================================================================================================
108 bool FeaturesPlugin_CompositeSketch::isSub(ObjectPtr theObject) const
110 // Check is this feature of result
111 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
112 if(!aFeature.get()) {
116 ObjectPtr aSub = data()->reference(SKETCH_ID())->value();
117 return aSub == theObject;
120 //=================================================================================================
121 void FeaturesPlugin_CompositeSketch::removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature)
123 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
124 if(aBaseObjectsSelectionList.get() && aBaseObjectsSelectionList->size() > 0) {
125 aBaseObjectsSelectionList->clear();
128 reference(SKETCH_ID())->setValue(ObjectPtr());
131 //=================================================================================================
132 void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList,
133 const bool theIsMakeShells)
135 theBaseShapesList.clear();
137 ListOfShape aBaseFacesList;
138 std::map<ResultConstructionPtr, ListOfShape> aSketchWiresMap;
139 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
140 if(!aBaseObjectsSelectionList.get()) {
141 setError("Error: Could not get base objects selection list.");
144 if(aBaseObjectsSelectionList->size() == 0) {
145 setError("Error: Base objects list is empty.");
148 for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
149 AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
150 if(!aBaseObjectSelection.get()) {
151 setError("Error: Selected base object is empty.");
154 GeomShapePtr aBaseShape = aBaseObjectSelection->value();
155 if(aBaseShape.get() && !aBaseShape->isNull()) {
156 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
157 if(aST == GeomAPI_Shape::SOLID || aST == GeomAPI_Shape::COMPSOLID) {
158 setError("Error: Selected shapes has unsupported type.");
161 ResultConstructionPtr aConstruction =
162 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
163 if(aConstruction.get() && !aBaseShape->isEqual(aConstruction->shape()) &&
164 aST == GeomAPI_Shape::WIRE) {
165 // It is a wire on the sketch, store it to make face later.
166 aSketchWiresMap[aConstruction].push_back(aBaseShape);
169 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
170 theBaseShapesList.push_back(aBaseShape);
173 // This may be the whole sketch result selected, check and get faces.
174 ResultConstructionPtr aConstruction =
175 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
176 if(!aConstruction.get()) {
177 setError("Error: Selected sketches does not have results.");
180 int aFacesNum = aConstruction->facesNum();
182 // Probably it can be construction.
183 aBaseShape = aConstruction->shape();
184 if(aBaseShape.get() && !aBaseShape->isNull()) {
185 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
186 if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE &&
187 aST != GeomAPI_Shape::WIRE &&
188 aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
189 setError("Error: Selected shapes has unsupported type.");
192 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
193 theBaseShapesList.push_back(aBaseShape);
196 for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
197 GeomShapePtr aBaseFace = aConstruction->face(aFaceIndex);
198 if(!aBaseFace.get() || aBaseFace->isNull()) {
199 setError("Error: One of the faces on selected sketch is null.");
202 aBaseFacesList.push_back(aBaseFace);
208 // Make faces from sketch wires.
209 for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
210 anIt != aSketchWiresMap.cend(); ++anIt) {
211 const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
212 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
213 const ListOfShape& aWiresList = (*anIt).second;
215 GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
216 aSketchPlanarEdges->norm(),
219 aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
222 // Searching faces with common edges.
223 if(theIsMakeShells && aBaseFacesList.size() > 1) {
225 ListOfShape aFreeFaces;
226 GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
227 GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL,
228 aShells, aFreeFaces);
229 theBaseShapesList.insert(theBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
230 theBaseShapesList.insert(theBaseShapesList.end(), aShells.begin(), aShells.end());
232 theBaseShapesList.insert(theBaseShapesList.end(), aBaseFacesList.begin(),
233 aBaseFacesList.end());
237 //=================================================================================================
238 bool FeaturesPlugin_CompositeSketch::isMakeShapeValid(
239 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
241 // Check that algo is done.
242 if(!theMakeShape->isDone()) {
243 setError("Error: " + getKind() + " algorithm failed.");
247 // Check if shape is not null.
248 if(!theMakeShape->shape().get() || theMakeShape->shape()->isNull()) {
249 setError("Error: Resulting shape is null.");
253 // Check that resulting shape is valid.
254 if(!theMakeShape->isValid()) {
255 setError("Error: Resulting shape is not valid.");
262 //=================================================================================================
263 void FeaturesPlugin_CompositeSketch::storeResult(const GeomShapePtr theBaseShape,
264 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
267 // Create result body.
268 ResultBodyPtr aResultBody = document()->createBody(data(), theIndex);
270 // Store generated shape.
271 aResultBody->storeGenerated(theBaseShape, theMakeShape->shape());
273 // Store generated edges/faces.
274 storeGenerationHistory(aResultBody, theBaseShape, theMakeShape);
276 setResult(aResultBody, theIndex);
279 //=================================================================================================
280 void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theResultBody,
281 const GeomShapePtr theBaseShape,
282 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
284 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
285 GeomAPI_Shape::ShapeType aShapeTypeToExplode = GeomAPI_Shape::SHAPE;
287 switch(aBaseShapeType) {
288 case GeomAPI_Shape::EDGE: {
289 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
292 case GeomAPI_Shape::WIRE: {
293 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
296 case GeomAPI_Shape::FACE:
297 case GeomAPI_Shape::SHELL: {
298 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
301 case GeomAPI_Shape::COMPOUND: {
302 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
306 int aLateralIndex = 1;
307 int aBaseEdgeIndex = 1;
308 int aVertexIndex = 1;
309 int aBaseVertexIndex = 1;
311 if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX ||
312 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
313 theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::VERTEX);
315 if(aShapeTypeToExplode == GeomAPI_Shape::EDGE ||
316 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
317 theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::EDGE);
320 std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep =
321 std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
322 if(aMakeSweep.get()) {
323 // Store from shapes.
324 storeShapes(theResultBody, aBaseShapeType, aMakeSweep->fromShapes(), "From_");
327 storeShapes(theResultBody, aBaseShapeType, aMakeSweep->toShapes(), "To_");
331 //=================================================================================================
332 void FeaturesPlugin_CompositeSketch::storeShapes(ResultBodyPtr theResultBody,
333 const GeomAPI_Shape::ShapeType theBaseShapeType,
334 const ListOfShape& theShapes,
335 const std::string theName)
337 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
338 std::string aShapeTypeStr = "Face";
339 switch(theBaseShapeType) {
340 case GeomAPI_Shape::VERTEX: {
341 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
342 aShapeTypeStr = "Vertex";
345 case GeomAPI_Shape::EDGE:
346 case GeomAPI_Shape::WIRE: {
347 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
348 aShapeTypeStr = "Edge";
351 case GeomAPI_Shape::FACE:
352 case GeomAPI_Shape::SHELL: {
353 aShapeTypeToExplore = GeomAPI_Shape::FACE;
354 aShapeTypeStr = "Face";
357 case GeomAPI_Shape::COMPOUND: {
358 aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
364 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
365 GeomShapePtr aShape = *anIt;
367 if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
368 std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
369 storeSubShape(theResultBody, aShape, aShape->shapeType(), aName);
371 std::string aName = theName + aShapeTypeStr;
372 storeSubShape(theResultBody, aShape, aShapeTypeToExplore, aName);
373 if (theBaseShapeType == GeomAPI_Shape::WIRE) { // issue 2289: special names also for vertices
374 aName = theName + "Vertex";
375 storeSubShape(theResultBody, aShape, GeomAPI_Shape::VERTEX, aName);
381 void storeSubShape(ResultBodyPtr theResultBody,
382 const GeomShapePtr theShape,
383 const GeomAPI_Shape::ShapeType theType,
384 const std::string& theName)
386 for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
387 GeomShapePtr aSubShape = anExp.current();
388 theResultBody->generated(aSubShape, theName);