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