Salome HOME
updated copyright message
[modules/shaper.git] / src / BuildPlugin / BuildPlugin_Face.cpp
1 // Copyright (C) 2014-2023  CEA, EDF
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 email : webmaster.salome@opencascade.com
18 //
19
20 #include "BuildPlugin_Face.h"
21
22 #include <ModelAPI_AttributeSelectionList.h>
23 #include <ModelAPI_ResultBody.h>
24 #include <ModelAPI_ResultConstruction.h>
25
26 #include <GeomAPI_Edge.h>
27 #include <GeomAPI_PlanarEdges.h>
28 #include <GeomAPI_Pln.h>
29 #include <GeomAPI_ShapeExplorer.h>
30
31 #include <GeomAlgoAPI_MakeShapeList.h>
32 #include <GeomAlgoAPI_ShapeTools.h>
33 #include <GeomAlgoAPI_SketchBuilder.h>
34 #include <GeomAlgoAPI_Copy.h>
35
36 //=================================================================================================
37 BuildPlugin_Face::BuildPlugin_Face()
38 {
39 }
40
41 //=================================================================================================
42 void BuildPlugin_Face::initAttributes()
43 {
44   data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
45 }
46
47 //=================================================================================================
48 void BuildPlugin_Face::execute()
49 {
50   // Get base objects list.
51   AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
52   if(!aSelectionList.get()) {
53     setError("Error: Could not get selection list.");
54     return;
55   }
56   if(aSelectionList->size() == 0) {
57     setError("Error: Empty selection list.");
58     return;
59   }
60
61   // Collect base shapes.
62   ListOfShape anEdges;
63   ListOfShape anOriginalFaces;
64   ListOfShape aContexts;
65   getOriginalShapesAndContexts(BASE_OBJECTS_ID(), anOriginalFaces, aContexts);
66   anOriginalFaces.clear();
67   std::list< std::shared_ptr<GeomAPI_Dir> > aListOfNormals;
68   for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
69     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
70     GeomShapePtr aShape = aSelection->value();
71     GeomShapePtr aContext = aSelection->context()->shape();
72     if(!aShape.get()) {
73       aShape = aContext;
74     }
75     if (aShape->shapeType() == GeomAPI_Shape::FACE) {
76       // keep selected faces "as is"
77       anOriginalFaces.push_back(aShape);
78       continue;
79     }
80     else if (!aSelection->value() && aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
81       // collect faces from the sketch
82       ResultConstructionPtr aSketch =
83           std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSelection->context());
84       if (aSketch && aSketch->facesNum() > 0) {
85         for (int i = 0; i < aSketch->facesNum(); ++i)
86           anOriginalFaces.push_back(aSketch->face(i));
87         continue;
88       }
89     }
90
91     for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
92       GeomShapePtr anEdge = anExp.current();
93       anEdges.push_back(anEdge);
94     }
95
96     // check whether the context is a sketch, in this case store its normal for further needs
97     std::shared_ptr<GeomAPI_PlanarEdges> aSketch =
98         std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aContext);
99     if (aSketch)
100       aListOfNormals.push_back(aSketch->norm());
101   }
102
103   // Build faces by edges.
104   ListOfShape aFaces;
105   GeomMakeShapePtr aFaceBuilder;
106   if (!anEdges.empty())
107     buildFacesByEdges(anEdges, aListOfNormals, aFaces, aFaceBuilder);
108   int aNbFacesFromEdges = (int)aFaces.size();
109
110   // Add faces selected by user.
111   aFaces.insert(aFaces.end(), anOriginalFaces.begin(), anOriginalFaces.end());
112
113   // Store result.
114   int anIndex = 0;
115   for(ListOfShape::const_iterator anIt = aFaces.cbegin(); anIt != aFaces.cend(); ++anIt) {
116     std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList);
117     if (anIndex < aNbFacesFromEdges)
118       aMakeShapeList->appendAlgo(aFaceBuilder);
119
120     GeomShapePtr aShape = *anIt;
121     GeomMakeShapePtr aCopy(new GeomAlgoAPI_Copy(aShape));
122     aMakeShapeList->appendAlgo(aCopy);
123
124     ListOfShape aBaseShapes;
125     if (anIndex < aNbFacesFromEdges)
126       aBaseShapes = anEdges;
127     else
128       aBaseShapes.push_back(aShape);
129     storeResult(aMakeShapeList, aBaseShapes, aContexts, aCopy->shape(), anIndex++);
130   }
131
132   removeResults(anIndex);
133 }
134
135 void BuildPlugin_Face::buildFacesByEdges(
136     const ListOfShape& theEdges,
137     const std::list< std::shared_ptr<GeomAPI_Dir> >& theNormals,
138     ListOfShape& theFaces,
139     std::shared_ptr<GeomAlgoAPI_MakeShape>& theBuilderAlgo) const
140 {
141   // Get plane.
142   std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(theEdges);
143   std::shared_ptr<GeomAPI_Dir> aNormal = aPln->direction();
144   bool isReverse = !theNormals.empty();
145   std::list< std::shared_ptr<GeomAPI_Dir> >::const_iterator aNormIt = theNormals.begin();
146   for (; aNormIt != theNormals.end() && isReverse; ++aNormIt)
147     if ((*aNormIt)->dot(aNormal) > 1.e-7)
148       isReverse = false;
149   if (isReverse) {
150     aNormal->reverse();
151     aPln = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(aPln->location(), aNormal));
152   }
153
154   // Get faces.
155   std::shared_ptr<GeomAlgoAPI_SketchBuilder> aSketchBuilder(
156       new GeomAlgoAPI_SketchBuilder(aPln, theEdges));
157   theFaces = aSketchBuilder->faces();
158   theBuilderAlgo = aSketchBuilder;
159
160   // Get wires from faces.
161   ListOfShape aWires;
162   for(ListOfShape::const_iterator anIt = theFaces.cbegin(); anIt != theFaces.cend(); ++anIt)
163     aWires.push_back(GeomAlgoAPI_ShapeTools::getFaceOuterWire(*anIt));
164
165   // Make faces with holes.
166   theFaces.clear();
167   GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aPln->location(), aPln->direction(),
168                                              aWires, theFaces);
169 }