Salome HOME
Unit test for moving group after BuildPlugin_Face feature
[modules/shaper.git] / src / BuildPlugin / BuildPlugin_Face.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 "BuildPlugin_Face.h"
22
23 #include <ModelAPI_AttributeSelectionList.h>
24 #include <ModelAPI_ResultBody.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     // keep selected faces "as is"
76     if (aShape->shapeType() == GeomAPI_Shape::FACE) {
77       anOriginalFaces.push_back(aShape);
78       continue;
79     }
80
81     for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
82       GeomShapePtr anEdge = anExp.current();
83       anEdges.push_back(anEdge);
84     }
85
86     // check whether the context is a sketch, in this case store its normal for further needs
87     std::shared_ptr<GeomAPI_PlanarEdges> aSketch =
88         std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aContext);
89     if (aSketch)
90       aListOfNormals.push_back(aSketch->norm());
91   }
92
93   // Build faces by edges.
94   ListOfShape aFaces;
95   GeomMakeShapePtr aFaceBuilder;
96   if (!anEdges.empty())
97     buildFacesByEdges(anEdges, aListOfNormals, aFaces, aFaceBuilder);
98   int aNbFacesFromEdges = (int)aFaces.size();
99
100   // Add faces selected by user.
101   aFaces.insert(aFaces.end(), anOriginalFaces.begin(), anOriginalFaces.end());
102
103   // Store result.
104   int anIndex = 0;
105   for(ListOfShape::const_iterator anIt = aFaces.cbegin(); anIt != aFaces.cend(); ++anIt) {
106     std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList);
107     if (anIndex < aNbFacesFromEdges)
108       aMakeShapeList->appendAlgo(aFaceBuilder);
109
110     GeomShapePtr aShape = *anIt;
111     GeomMakeShapePtr aCopy(new GeomAlgoAPI_Copy(aShape));
112     aMakeShapeList->appendAlgo(aCopy);
113
114     ListOfShape aBaseShapes;
115     if (anIndex < aNbFacesFromEdges)
116       aBaseShapes = anEdges;
117     else
118       aBaseShapes.push_back(aShape);
119     storeResult(aMakeShapeList, aBaseShapes, aContexts, aCopy->shape(), anIndex++);
120   }
121
122   removeResults(anIndex);
123 }
124
125 void BuildPlugin_Face::buildFacesByEdges(
126     const ListOfShape& theEdges,
127     const std::list< std::shared_ptr<GeomAPI_Dir> >& theNormals,
128     ListOfShape& theFaces,
129     std::shared_ptr<GeomAlgoAPI_MakeShape>& theBuilderAlgo) const
130 {
131   // Get plane.
132   std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(theEdges);
133   std::shared_ptr<GeomAPI_Dir> aNormal = aPln->direction();
134   bool isReverse = !theNormals.empty();
135   std::list< std::shared_ptr<GeomAPI_Dir> >::const_iterator aNormIt = theNormals.begin();
136   for (; aNormIt != theNormals.end() && isReverse; ++aNormIt)
137     if ((*aNormIt)->dot(aNormal) > 1.e-7)
138       isReverse = false;
139   if (isReverse) {
140     aNormal->reverse();
141     aPln = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(aPln->location(), aNormal));
142   }
143
144   // Get faces.
145   std::shared_ptr<GeomAlgoAPI_SketchBuilder> aSketchBuilder(
146       new GeomAlgoAPI_SketchBuilder(aPln, theEdges));
147   theFaces = aSketchBuilder->faces();
148   theBuilderAlgo = aSketchBuilder;
149
150   // Get wires from faces.
151   ListOfShape aWires;
152   for(ListOfShape::const_iterator anIt = theFaces.cbegin(); anIt != theFaces.cend(); ++anIt)
153     aWires.push_back(GeomAlgoAPI_ShapeTools::getFaceOuterWire(*anIt));
154
155   // Make faces with holes.
156   theFaces.clear();
157   GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aPln->location(), aPln->direction(),
158                                              aWires, theFaces);
159 }