Salome HOME
fb830f62a93c560936ea680037cedf990524b733
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Sewing.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 <FeaturesPlugin_Sewing.h>
21
22 #include <GeomAlgoAPI_Sewing.h>
23 #include <GeomAlgoAPI_Tools.h>
24
25 #include <GeomAPI_Shape.h>
26
27 #include <ModelAPI_AttributeBoolean.h>
28 #include <ModelAPI_AttributeDouble.h>
29 #include <ModelAPI_AttributeSelectionList.h>
30 #include <ModelAPI_ResultBody.h>
31
32
33
34 //=================================================================================================
35 FeaturesPlugin_Sewing::FeaturesPlugin_Sewing()
36 {
37 }
38
39 //=================================================================================================
40 void FeaturesPlugin_Sewing::initAttributes()
41 {
42   data()->addAttribute(OBJECTS_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
43   data()->addAttribute(ALLOW_NON_MANIFOLD_ID(), ModelAPI_AttributeBoolean::typeId());
44   data()->addAttribute(TOLERANCE_ID(), ModelAPI_AttributeDouble::typeId());
45   data()->addAttribute(ALWAYS_CREATE_RESULT_ID(), ModelAPI_AttributeBoolean::typeId());
46 }
47
48 //=================================================================================================
49 void FeaturesPlugin_Sewing::execute()
50 {
51   // Collect all base shapes
52   ListOfShape aShapes;
53   getOriginalShapes(OBJECTS_LIST_ID(), aShapes);
54
55   // Get all other feature arguments
56   bool isAllowNonManifold = boolean(FeaturesPlugin_Sewing::ALLOW_NON_MANIFOLD_ID())->value();
57   bool isAlwaysCreateResult = boolean(FeaturesPlugin_Sewing::ALWAYS_CREATE_RESULT_ID())->value();
58   double aTolerance = real(FeaturesPlugin_Sewing::TOLERANCE_ID())->value();
59
60   std::shared_ptr<GeomAlgoAPI_Sewing> aSewingAlgo(new GeomAlgoAPI_Sewing(aShapes, isAllowNonManifold, aTolerance));
61
62   std::string anError;
63   if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aSewingAlgo, getKind(), anError))
64   {
65     setError(anError);
66     return;
67   }
68     
69   // Store result.
70   GeomShapePtr aResult = aSewingAlgo->shape();
71
72   if (!isSewn(aShapes, aResult) && !isAlwaysCreateResult)
73   {
74     static const std::string anError = "Error: No faces were sewn.";
75     setError(anError);
76     return;
77   }
78
79   int anIndex = 0;
80   ResultBodyPtr aResultBody = document()->createBody(data(), anIndex);
81   aResultBody->storeModified(aShapes, aResult, aSewingAlgo);
82
83   setResult(aResultBody, anIndex);
84 }
85
86 //=================================================================================================
87 void FeaturesPlugin_Sewing::getOriginalShapes(const std::string& theAttributeName,
88                                               ListOfShape&       theShapes)
89 {
90   // Collect all selections into a single list of shapes
91   AttributeSelectionListPtr aSelectionList = selectionList(theAttributeName);
92   for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex)
93   {
94     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
95     GeomShapePtr aShape = aSelection->value();
96     GeomShapePtr aContext = aSelection->context()->shape();
97     if (!aShape.get())
98     {
99       aShape = aContext;
100     }
101     theShapes.push_back(aShape);
102   }
103 }
104
105 //=================================================================================================
106 bool FeaturesPlugin_Sewing::isSewn(const ListOfShape& theInputs,
107                                    const GeomShapePtr theResult)
108 {
109   // Consider the list of input shapes the same as the result, if
110   //  * both arguments have the same number of shells
111   //  * the total number of faces in these shells did NOT change.
112   int nbInputShells = 0, nbInputFaces = 0;
113   for (ListOfShape::const_iterator anIt = theInputs.cbegin();
114        anIt != theInputs.cend();
115        ++anIt)
116   {
117     GeomShapePtr aShape = *anIt;
118     if (aShape.get())
119     {
120       if (aShape->isShell()) nbInputShells++;
121       nbInputFaces += aShape->subShapes(GeomAPI_Shape::FACE, true).size();
122     }
123   }
124
125   int nbResultShells = 0, nbResultFaces = 0;
126   if (theResult->isCompound())
127   {
128     ListOfShape shells = theResult->subShapes(GeomAPI_Shape::SHELL, true);
129     nbResultShells = shells.size();
130     for (ListOfShape::const_iterator anIt = shells.cbegin();
131         anIt != shells.cend();
132         ++anIt)
133     {
134       GeomShapePtr aShape = *anIt;
135       if (aShape.get() && aShape->isShell())
136       {
137         nbInputFaces += aShape->subShapes(GeomAPI_Shape::FACE, true).size();
138       }
139     }
140   }
141   else if (theResult->isShell())
142   {
143     nbResultShells = 1;
144     nbResultFaces = theResult->subShapes(GeomAPI_Shape::FACE, true).size();
145   }
146
147   return ((nbInputShells == 0 && nbResultShells > 0) || (nbResultShells < nbInputShells) || (nbResultShells == nbInputShells && nbResultFaces > nbInputFaces));
148 }