Salome HOME
3a718e5b10fa5431404289e54d0591e94f3b3a0b
[modules/shaper.git] / src / BuildPlugin / BuildPlugin_Edge.cpp
1 // Copyright (C) 2014-2023  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_Edge.h"
21
22 #include <ModelAPI_AttributeBoolean.h>
23 #include <ModelAPI_AttributeSelectionList.h>
24 #include <ModelAPI_AttributeString.h>
25 #include <ModelAPI_ResultBody.h>
26 #include <ModelAPI_Session.h>
27 #include <ModelAPI_Validator.h>
28
29 #include <GeomAlgoAPI_CompoundBuilder.h>
30 #include <GeomAlgoAPI_Copy.h>
31 #include <GeomAlgoAPI_EdgeBuilder.h>
32 #include <GeomAlgoAPI_MakeShapeList.h>
33 #include <GeomAlgoAPI_Partition.h>
34 #include <GeomAlgoAPI_Tools.h>
35
36 #include <GeomAPI_Edge.h>
37 #include <GeomAPI_ShapeExplorer.h>
38 #include <GeomAPI_Vertex.h>
39
40 static bool getShape(const AttributeSelectionPtr theAttribute,
41                      GeomShapePtr& theShape,
42                      std::string& theError)
43 {
44   theShape = theAttribute->value();
45   if (!theShape.get()) {
46     ResultPtr aContext = theAttribute->context();
47     if (!aContext.get()) {
48       theError = "Error: Attribute has empty context.";
49       return false;
50     }
51     theShape = aContext->shape();
52   }
53   return true;
54 }
55
56 //=================================================================================================
57 BuildPlugin_Edge::BuildPlugin_Edge()
58 {
59 }
60
61 //=================================================================================================
62 void BuildPlugin_Edge::initAttributes()
63 {
64   data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
65
66   data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
67   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CREATION_METHOD());
68
69   data()->addAttribute(FIRST_POINT(), ModelAPI_AttributeSelection::typeId());
70   data()->addAttribute(SECOND_POINT(), ModelAPI_AttributeSelection::typeId());
71
72   data()->addAttribute(INTERSECT_ID(), ModelAPI_AttributeBoolean::typeId());
73   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), INTERSECT_ID());
74 }
75
76 //=================================================================================================
77 void BuildPlugin_Edge::execute()
78 {
79   AttributeStringPtr aCreationMethod = string(CREATION_METHOD());
80   if (aCreationMethod && aCreationMethod->isInitialized() &&
81       aCreationMethod->value() == CREATION_BY_POINTS())
82     edgeByPoints();
83   else
84     edgesBySegments();
85 }
86
87 //=================================================================================================
88 void BuildPlugin_Edge::edgesBySegments()
89 {
90   string(CREATION_METHOD())->setValue(CREATION_BY_SEGMENTS());
91
92   // Get base objects list.
93   AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
94   if(!aSelectionList.get()) {
95     setError("Error: Could not get selection list.");
96     return;
97   }
98   if(aSelectionList->size() == 0) {
99     setError("Error: Empty selection list.");
100     return;
101   }
102
103   // Collect base shapes.
104   ListOfShape aListOfShapes;
105   std::string aError;
106   for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
107     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
108     GeomShapePtr aShape;
109     if (!getShape(aSelection, aShape, aError)) {
110       setError(aError);
111       return;
112     }
113     if(!aShape.get()) {
114       setError("Error: Empty shape selected.");
115       return;
116     }
117     aListOfShapes.push_back(aShape);
118   }
119
120   AttributeBooleanPtr isIntersect = boolean(INTERSECT_ID());
121
122   GeomShapePtr aResult;
123   std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo;
124   if (isIntersect->isInitialized() && isIntersect->value()) {
125     aPartitionAlgo.reset(new GeomAlgoAPI_Partition(aListOfShapes, ListOfShape()));
126
127     std::string anError;
128     if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) {
129       setError(anError);
130       return;
131     }
132
133     aResult = aPartitionAlgo->shape();
134   }
135   else
136     aResult = GeomAlgoAPI_CompoundBuilder::compound(aListOfShapes);
137
138   int aResultIndex = 0;
139
140   // Explode on edges
141   std::set<GeomShapePtr, GeomAPI_Shape::Comparator> aProcessed;
142   for (GeomAPI_ShapeExplorer anExp(aResult, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
143     GeomShapePtr anEdge = anExp.current();
144     if (aProcessed.find(anEdge) != aProcessed.end())
145       continue; // vertex is already processed
146     aProcessed.insert(anEdge);
147
148     std::shared_ptr<GeomAlgoAPI_Copy> aCopyAlgo(new GeomAlgoAPI_Copy(anEdge));
149
150     std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList);
151     if (aPartitionAlgo)
152       aMakeShapeList->appendAlgo(aPartitionAlgo);
153     aMakeShapeList->appendAlgo(aCopyAlgo);
154
155     // Store result.
156     ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
157     aResultBody->storeModified(aListOfShapes, aCopyAlgo->shape(), aMakeShapeList);
158     aResultBody->loadModifiedShapes(aMakeShapeList, anEdge, GeomAPI_Shape::VERTEX);
159     setResult(aResultBody, aResultIndex);
160     ++aResultIndex;
161   }
162
163   removeResults(aResultIndex);
164 }
165
166 void BuildPlugin_Edge::edgeByPoints()
167 {
168   // Get base points.
169   AttributeSelectionPtr aFirstPointAttr = selection(FIRST_POINT());
170   AttributeSelectionPtr aSecondPointAttr = selection(SECOND_POINT());
171   if (!aFirstPointAttr.get() || !aSecondPointAttr.get()) {
172     setError("Error: Not enough points selected.");
173     return;
174   }
175
176   std::string aError;
177   GeomShapePtr aFirstShape, aSecondShape;
178   if (!getShape(aFirstPointAttr, aFirstShape, aError) ||
179       !getShape(aSecondPointAttr, aSecondShape, aError)) {
180     setError(aError);
181     return;
182   }
183   if (!aFirstShape.get() || !aSecondShape.get()) {
184     setError("Error: Empty shape selected.");
185     return;
186   }
187
188   if (!aFirstShape->isVertex() || !aSecondShape->isVertex()) {
189     setError("Error: Selected shape has wrong type. Only vertices acceptable.");
190     return;
191   }
192
193   int aResultIndex = 0;
194
195   GeomEdgePtr anEdge = GeomAlgoAPI_EdgeBuilder::line(aFirstShape->vertex()->point(),
196                                                      aSecondShape->vertex()->point());
197   if (!anEdge.get()) {
198     setError("Error: Algorithm failed.");
199     return;
200   }
201
202   // Store result.
203   ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
204   aResultBody->store(anEdge);
205   // History of vertices
206   GeomAPI_ShapeExplorer anExp(anEdge, GeomAPI_Shape::VERTEX);
207   GeomShapePtr aStartVertex = anExp.current();
208   anExp.next();
209   GeomShapePtr anEndVertex = anExp.current();
210   aResultBody->modified(aFirstShape, aStartVertex);
211   aResultBody->modified(aSecondShape, anEndVertex);
212
213   setResult(aResultBody, aResultIndex++);
214   removeResults(aResultIndex);
215 }