1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include <FeaturesPlugin_Symmetry.h>
23 #include <GeomAlgoAPI_CompoundBuilder.h>
24 #include <GeomAlgoAPI_PointBuilder.h>
25 #include <GeomAlgoAPI_FaceBuilder.h>
26 #include <GeomAlgoAPI_Copy.h>
27 #include <GeomAlgoAPI_MakeShapeList.h>
29 #include <GeomAPI_Edge.h>
30 #include <GeomAPI_Face.h>
31 #include <GeomAPI_Lin.h>
32 #include <GeomAPI_Pln.h>
33 #include <GeomAPI_Trsf.h>
35 #include <ModelAPI_AttributeBoolean.h>
36 #include <ModelAPI_AttributeSelectionList.h>
37 #include <ModelAPI_AttributeString.h>
38 #include <ModelAPI_ResultBody.h>
39 #include <ModelAPI_ResultPart.h>
41 #include <FeaturesPlugin_Tools.h>
43 //=================================================================================================
44 FeaturesPlugin_Symmetry::FeaturesPlugin_Symmetry()
48 //=================================================================================================
49 void FeaturesPlugin_Symmetry::initAttributes()
51 data()->addAttribute(FeaturesPlugin_Symmetry::CREATION_METHOD(),
52 ModelAPI_AttributeString::typeId());
54 AttributeSelectionListPtr aSelection =
55 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
56 FeaturesPlugin_Symmetry::OBJECTS_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
58 data()->addAttribute(FeaturesPlugin_Symmetry::POINT_OBJECT_ID(),
59 ModelAPI_AttributeSelection::typeId());
61 data()->addAttribute(FeaturesPlugin_Symmetry::AXIS_OBJECT_ID(),
62 ModelAPI_AttributeSelection::typeId());
64 data()->addAttribute(FeaturesPlugin_Symmetry::PLANE_OBJECT_ID(),
65 ModelAPI_AttributeSelection::typeId());
67 data()->addAttribute(FeaturesPlugin_Symmetry::KEEP_ORIGINAL_RESULT(),
68 ModelAPI_AttributeBoolean::typeId());
71 //=================================================================================================
72 void FeaturesPlugin_Symmetry::execute()
74 AttributeStringPtr aMethodTypeAttr = string(FeaturesPlugin_Symmetry::CREATION_METHOD());
75 std::string aMethodType = aMethodTypeAttr->value();
77 if (aMethodType == CREATION_METHOD_BY_POINT()) {
78 performSymmetryByPoint();
81 if (aMethodType == CREATION_METHOD_BY_AXIS()) {
82 performSymmetryByAxis();
85 if (aMethodType == CREATION_METHOD_BY_PLANE()) {
86 performSymmetryByPlane();
90 //=================================================================================================
91 bool FeaturesPlugin_Symmetry::collectSourceObjects(ListOfShape& theSourceShapes,
92 std::list<ResultPtr>& theSourceResults)
94 AttributeSelectionListPtr anObjectsSelList =
95 selectionList(FeaturesPlugin_Symmetry::OBJECTS_LIST_ID());
96 if (anObjectsSelList->size() == 0) {
99 for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
100 std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
101 anObjectsSelList->value(anObjectsIndex);
102 std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
103 if (!anObject.get()) { // may be for not-activated parts
107 theSourceShapes.push_back(anObject);
108 theSourceResults.push_back(anObjectAttr->context());
113 //=================================================================================================
114 void FeaturesPlugin_Symmetry::performSymmetryByPoint()
117 ListOfShape anObjects;
118 std::list<ResultPtr> aContextes;
119 if (!collectSourceObjects(anObjects, aContextes))
123 std::shared_ptr<GeomAPI_Pnt> aPoint;
124 std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
125 selection(FeaturesPlugin_Symmetry::POINT_OBJECT_ID());
126 if (anObjRef.get() != NULL) {
127 GeomShapePtr aShape1 = anObjRef->value();
128 if (!aShape1.get()) {
129 aShape1 = anObjRef->context()->shape();
132 aPoint = GeomAlgoAPI_PointBuilder::point(aShape1);
136 // Moving each object.
137 int aResultIndex = 0;
138 std::list<ResultPtr>::iterator aContext = aContextes.begin();
139 for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
140 anObjectsIt++, aContext++) {
141 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
142 bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
146 std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
147 aTrsf->setSymmetry(aPoint);
148 ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
149 buildResult(anOrigin, aTrsf, aResultIndex);
152 std::shared_ptr<GeomAlgoAPI_Symmetry> aSymmetryAlgo(
153 new GeomAlgoAPI_Symmetry(aBaseShape, aPoint));
155 if (!aSymmetryAlgo->check()) {
156 setError(aSymmetryAlgo->getError());
160 aSymmetryAlgo->build();
162 // Checking that the algorithm worked properly.
163 if(!aSymmetryAlgo->isDone()) {
164 static const std::string aFeatureError = "Error: Symmetry algorithm failed.";
165 setError(aFeatureError);
168 if(aSymmetryAlgo->shape()->isNull()) {
169 static const std::string aShapeError = "Error: Resulting shape is Null.";
170 setError(aShapeError);
173 if(!aSymmetryAlgo->isValid()) {
174 std::string aFeatureError = "Error: Resulting shape is not valid.";
175 setError(aFeatureError);
179 buildResult(aSymmetryAlgo, aBaseShape, aResultIndex);
184 // Remove the rest results if there were produced in the previous pass.
185 removeResults(aResultIndex);
188 //=================================================================================================
189 void FeaturesPlugin_Symmetry::performSymmetryByAxis()
192 ListOfShape anObjects;
193 std::list<ResultPtr> aContextes;
194 if (!collectSourceObjects(anObjects, aContextes))
198 std::shared_ptr<GeomAPI_Ax1> anAxis;
199 std::shared_ptr<GeomAPI_Edge> anEdge;
200 std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
201 selection(FeaturesPlugin_Symmetry::AXIS_OBJECT_ID());
202 if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) {
203 anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->value()));
204 } else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
205 anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) {
206 anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->context()->shape()));
209 anAxis = std::shared_ptr<GeomAPI_Ax1>(new GeomAPI_Ax1(anEdge->line()->location(),
210 anEdge->line()->direction()));
213 // Moving each object.
214 int aResultIndex = 0;
215 std::list<ResultPtr>::iterator aContext = aContextes.begin();
216 for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
217 anObjectsIt++, aContext++) {
218 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
219 bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
223 std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
224 aTrsf->setSymmetry(anAxis);
225 ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
226 buildResult(anOrigin, aTrsf, aResultIndex);
229 std::shared_ptr<GeomAlgoAPI_Symmetry> aSymmetryAlgo(
230 new GeomAlgoAPI_Symmetry(aBaseShape, anAxis));
232 if (!aSymmetryAlgo->check()) {
233 setError(aSymmetryAlgo->getError());
237 aSymmetryAlgo->build();
239 // Checking that the algorithm worked properly.
240 if(!aSymmetryAlgo->isDone()) {
241 static const std::string aFeatureError = "Error: Symmetry algorithm failed.";
242 setError(aFeatureError);
245 if(aSymmetryAlgo->shape()->isNull()) {
246 static const std::string aShapeError = "Error: Resulting shape is Null.";
247 setError(aShapeError);
250 if(!aSymmetryAlgo->isValid()) {
251 std::string aFeatureError = "Error: Resulting shape is not valid.";
252 setError(aFeatureError);
256 buildResult(aSymmetryAlgo, aBaseShape, aResultIndex);
261 // Remove the rest results if there were produced in the previous pass.
262 removeResults(aResultIndex);
265 //=================================================================================================
266 void FeaturesPlugin_Symmetry::performSymmetryByPlane()
269 ListOfShape anObjects;
270 std::list<ResultPtr> aContextes;
271 if (!collectSourceObjects(anObjects, aContextes))
275 std::shared_ptr<GeomAPI_Ax2> aPlane;
276 std::shared_ptr<GeomAPI_Pln> aPln;
277 std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
278 selection(FeaturesPlugin_Symmetry::PLANE_OBJECT_ID());
279 if (anObjRef && anObjRef->value() && anObjRef->value()->isFace()) {
280 aPln = std::shared_ptr<GeomAPI_Face>(new GeomAPI_Face(anObjRef->value()))->getPlane();
282 else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
283 anObjRef->context()->shape() && anObjRef->context()->shape()->isFace()) {
285 std::shared_ptr<GeomAPI_Face>(new GeomAPI_Face(anObjRef->context()->shape()))->getPlane();
288 aPlane = std::shared_ptr<GeomAPI_Ax2>(new GeomAPI_Ax2(aPln->location(),
292 // Moving each object.
293 int aResultIndex = 0;
294 std::list<ResultPtr>::iterator aContext = aContextes.begin();
295 for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
296 anObjectsIt++, aContext++) {
297 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
298 bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
302 std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
303 aTrsf->setSymmetry(aPlane);
304 ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
305 buildResult(anOrigin, aTrsf, aResultIndex);
307 std::shared_ptr<GeomAlgoAPI_Symmetry> aSymmetryAlgo(
308 new GeomAlgoAPI_Symmetry(aBaseShape, aPlane));
310 if (!aSymmetryAlgo->check()) {
311 setError(aSymmetryAlgo->getError());
315 aSymmetryAlgo->build();
317 // Checking that the algorithm worked properly.
318 if(!aSymmetryAlgo->isDone()) {
319 static const std::string aFeatureError = "Error: Symmetry algorithm failed.";
320 setError(aFeatureError);
323 if(aSymmetryAlgo->shape()->isNull()) {
324 static const std::string aShapeError = "Error: Resulting shape is Null.";
325 setError(aShapeError);
328 if(!aSymmetryAlgo->isValid()) {
329 std::string aFeatureError = "Error: Resulting shape is not valid.";
330 setError(aFeatureError);
334 buildResult(aSymmetryAlgo, aBaseShape, aResultIndex);
339 // Remove the rest results if there were produced in the previous pass.
340 removeResults(aResultIndex);
343 //=================================================================================================
344 void FeaturesPlugin_Symmetry::buildResult(
345 std::shared_ptr<GeomAlgoAPI_Symmetry>& theSymmetryAlgo,
346 std::shared_ptr<GeomAPI_Shape> theBaseShape, int theResultIndex)
348 GeomAlgoAPI_MakeShapeList anAlgoList;
349 anAlgoList.appendAlgo(theSymmetryAlgo);
350 // Compose source shape and the result of symmetry.
351 GeomShapePtr aCompound;
352 if (boolean(KEEP_ORIGINAL_RESULT())->value()) {
354 // add a copy of a base shape otherwise selection of this base shape is bad (2592)
355 std::shared_ptr<GeomAlgoAPI_Copy> aCopyAlgo(new GeomAlgoAPI_Copy(theBaseShape));
356 aShapes.push_back(aCopyAlgo->shape());
357 anAlgoList.appendAlgo(aCopyAlgo);
359 aShapes.push_back(theSymmetryAlgo->shape());
360 aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
362 aCompound = theSymmetryAlgo->shape();
364 // Store and name the result.
365 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
366 aResultBody->storeModified(theBaseShape, aCompound);
367 loadNamingDS(anAlgoList, aResultBody, theBaseShape);
368 setResult(aResultBody, theResultIndex);
371 //=================================================================================================
372 void FeaturesPlugin_Symmetry::buildResult(ResultPartPtr theOriginal,
373 std::shared_ptr<GeomAPI_Trsf> theTrsf,
376 if (boolean(KEEP_ORIGINAL_RESULT())->value()) {
377 std::shared_ptr<GeomAPI_Trsf> anIdentity(new GeomAPI_Trsf());
378 ResultPartPtr aCopy = document()->copyPart(theOriginal, data(), theResultIndex);
379 aCopy->setTrsf(theOriginal, anIdentity);
380 setResult(aCopy, theResultIndex);
384 ResultPartPtr aResultPart = document()->copyPart(theOriginal, data(), theResultIndex);
385 aResultPart->setTrsf(theOriginal, theTrsf);
386 setResult(aResultPart, theResultIndex);
389 //=================================================================================================
390 void FeaturesPlugin_Symmetry::loadNamingDS(GeomAlgoAPI_MakeShapeList& theAlgo,
391 std::shared_ptr<ModelAPI_ResultBody> theResultBody,
392 std::shared_ptr<GeomAPI_Shape> theBaseShape)
395 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes = theAlgo.mapOfSubShapes();
396 std::string aReflectedName = "Symmetried";
397 FeaturesPlugin_Tools::storeModifiedShapes(theAlgo, theResultBody,
398 theBaseShape, 1, 2, 3, aReflectedName,