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>
27 #include <GeomAPI_Edge.h>
28 #include <GeomAPI_Face.h>
29 #include <GeomAPI_Lin.h>
30 #include <GeomAPI_Pln.h>
31 #include <GeomAPI_Trsf.h>
33 #include <ModelAPI_AttributeBoolean.h>
34 #include <ModelAPI_AttributeSelectionList.h>
35 #include <ModelAPI_AttributeString.h>
36 #include <ModelAPI_ResultBody.h>
37 #include <ModelAPI_ResultPart.h>
39 #include <FeaturesPlugin_Tools.h>
41 //=================================================================================================
42 FeaturesPlugin_Symmetry::FeaturesPlugin_Symmetry()
46 //=================================================================================================
47 void FeaturesPlugin_Symmetry::initAttributes()
49 data()->addAttribute(FeaturesPlugin_Symmetry::CREATION_METHOD(),
50 ModelAPI_AttributeString::typeId());
52 AttributeSelectionListPtr aSelection =
53 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
54 FeaturesPlugin_Symmetry::OBJECTS_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
56 data()->addAttribute(FeaturesPlugin_Symmetry::POINT_OBJECT_ID(),
57 ModelAPI_AttributeSelection::typeId());
59 data()->addAttribute(FeaturesPlugin_Symmetry::AXIS_OBJECT_ID(),
60 ModelAPI_AttributeSelection::typeId());
62 data()->addAttribute(FeaturesPlugin_Symmetry::PLANE_OBJECT_ID(),
63 ModelAPI_AttributeSelection::typeId());
65 data()->addAttribute(FeaturesPlugin_Symmetry::KEEP_ORIGINAL_RESULT(),
66 ModelAPI_AttributeBoolean::typeId());
69 //=================================================================================================
70 void FeaturesPlugin_Symmetry::execute()
72 AttributeStringPtr aMethodTypeAttr = string(FeaturesPlugin_Symmetry::CREATION_METHOD());
73 std::string aMethodType = aMethodTypeAttr->value();
75 if (aMethodType == CREATION_METHOD_BY_POINT()) {
76 performSymmetryByPoint();
79 if (aMethodType == CREATION_METHOD_BY_AXIS()) {
80 performSymmetryByAxis();
83 if (aMethodType == CREATION_METHOD_BY_PLANE()) {
84 performSymmetryByPlane();
88 //=================================================================================================
89 bool FeaturesPlugin_Symmetry::collectSourceObjects(ListOfShape& theSourceShapes,
90 std::list<ResultPtr>& theSourceResults)
92 AttributeSelectionListPtr anObjectsSelList =
93 selectionList(FeaturesPlugin_Symmetry::OBJECTS_LIST_ID());
94 if (anObjectsSelList->size() == 0) {
97 for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
98 std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
99 anObjectsSelList->value(anObjectsIndex);
100 std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
101 if (!anObject.get()) { // may be for not-activated parts
105 theSourceShapes.push_back(anObject);
106 theSourceResults.push_back(anObjectAttr->context());
111 //=================================================================================================
112 void FeaturesPlugin_Symmetry::performSymmetryByPoint()
115 ListOfShape anObjects;
116 std::list<ResultPtr> aContextes;
117 if (!collectSourceObjects(anObjects, aContextes))
121 std::shared_ptr<GeomAPI_Pnt> aPoint;
122 std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
123 selection(FeaturesPlugin_Symmetry::POINT_OBJECT_ID());
124 if (anObjRef.get() != NULL) {
125 GeomShapePtr aShape1 = anObjRef->value();
126 if (!aShape1.get()) {
127 aShape1 = anObjRef->context()->shape();
130 aPoint = GeomAlgoAPI_PointBuilder::point(aShape1);
134 // Moving each object.
135 int aResultIndex = 0;
136 std::list<ResultPtr>::iterator aContext = aContextes.begin();
137 for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
138 anObjectsIt++, aContext++) {
139 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
140 bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group();
144 std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
145 aTrsf->setSymmetry(aPoint);
146 ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
147 buildResult(anOrigin, aTrsf, aResultIndex);
150 GeomAlgoAPI_Symmetry aSymmetryAlgo(aBaseShape, aPoint);
152 if (!aSymmetryAlgo.check()) {
153 setError(aSymmetryAlgo.getError());
157 aSymmetryAlgo.build();
159 // Checking that the algorithm worked properly.
160 if(!aSymmetryAlgo.isDone()) {
161 static const std::string aFeatureError = "Error: Symmetry algorithm failed.";
162 setError(aFeatureError);
165 if(aSymmetryAlgo.shape()->isNull()) {
166 static const std::string aShapeError = "Error: Resulting shape is Null.";
167 setError(aShapeError);
170 if(!aSymmetryAlgo.isValid()) {
171 std::string aFeatureError = "Error: Resulting shape is not valid.";
172 setError(aFeatureError);
176 buildResult(aSymmetryAlgo, aBaseShape, aResultIndex);
181 // Remove the rest results if there were produced in the previous pass.
182 removeResults(aResultIndex);
185 //=================================================================================================
186 void FeaturesPlugin_Symmetry::performSymmetryByAxis()
189 ListOfShape anObjects;
190 std::list<ResultPtr> aContextes;
191 if (!collectSourceObjects(anObjects, aContextes))
195 std::shared_ptr<GeomAPI_Ax1> anAxis;
196 std::shared_ptr<GeomAPI_Edge> anEdge;
197 std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
198 selection(FeaturesPlugin_Symmetry::AXIS_OBJECT_ID());
199 if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) {
200 anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->value()));
201 } else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
202 anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) {
203 anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->context()->shape()));
206 anAxis = std::shared_ptr<GeomAPI_Ax1>(new GeomAPI_Ax1(anEdge->line()->location(),
207 anEdge->line()->direction()));
210 // Moving each object.
211 int aResultIndex = 0;
212 std::list<ResultPtr>::iterator aContext = aContextes.begin();
213 for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
214 anObjectsIt++, aContext++) {
215 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
216 bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group();
220 std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
221 aTrsf->setSymmetry(anAxis);
222 ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
223 buildResult(anOrigin, aTrsf, aResultIndex);
226 GeomAlgoAPI_Symmetry aSymmetryAlgo(aBaseShape, anAxis);
228 if (!aSymmetryAlgo.check()) {
229 setError(aSymmetryAlgo.getError());
233 aSymmetryAlgo.build();
235 // Checking that the algorithm worked properly.
236 if(!aSymmetryAlgo.isDone()) {
237 static const std::string aFeatureError = "Error: Symmetry algorithm failed.";
238 setError(aFeatureError);
241 if(aSymmetryAlgo.shape()->isNull()) {
242 static const std::string aShapeError = "Error: Resulting shape is Null.";
243 setError(aShapeError);
246 if(!aSymmetryAlgo.isValid()) {
247 std::string aFeatureError = "Error: Resulting shape is not valid.";
248 setError(aFeatureError);
252 buildResult(aSymmetryAlgo, aBaseShape, aResultIndex);
257 // Remove the rest results if there were produced in the previous pass.
258 removeResults(aResultIndex);
261 //=================================================================================================
262 void FeaturesPlugin_Symmetry::performSymmetryByPlane()
265 ListOfShape anObjects;
266 std::list<ResultPtr> aContextes;
267 if (!collectSourceObjects(anObjects, aContextes))
271 std::shared_ptr<GeomAPI_Ax2> aPlane;
272 std::shared_ptr<GeomAPI_Pln> aPln;
273 std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
274 selection(FeaturesPlugin_Symmetry::PLANE_OBJECT_ID());
275 if (anObjRef && anObjRef->value() && anObjRef->value()->isFace()) {
276 aPln = std::shared_ptr<GeomAPI_Face>(new GeomAPI_Face(anObjRef->value()))->getPlane();
278 else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
279 anObjRef->context()->shape() && anObjRef->context()->shape()->isFace()) {
281 std::shared_ptr<GeomAPI_Face>(new GeomAPI_Face(anObjRef->context()->shape()))->getPlane();
284 aPlane = std::shared_ptr<GeomAPI_Ax2>(new GeomAPI_Ax2(aPln->location(),
288 // Moving each object.
289 int aResultIndex = 0;
290 std::list<ResultPtr>::iterator aContext = aContextes.begin();
291 for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
292 anObjectsIt++, aContext++) {
293 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
294 bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group();
298 std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
299 aTrsf->setSymmetry(aPlane);
300 ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
301 buildResult(anOrigin, aTrsf, aResultIndex);
303 GeomAlgoAPI_Symmetry aSymmetryAlgo(aBaseShape, aPlane);
305 if (!aSymmetryAlgo.check()) {
306 setError(aSymmetryAlgo.getError());
310 aSymmetryAlgo.build();
312 // Checking that the algorithm worked properly.
313 if(!aSymmetryAlgo.isDone()) {
314 static const std::string aFeatureError = "Error: Symmetry algorithm failed.";
315 setError(aFeatureError);
318 if(aSymmetryAlgo.shape()->isNull()) {
319 static const std::string aShapeError = "Error: Resulting shape is Null.";
320 setError(aShapeError);
323 if(!aSymmetryAlgo.isValid()) {
324 std::string aFeatureError = "Error: Resulting shape is not valid.";
325 setError(aFeatureError);
329 buildResult(aSymmetryAlgo, aBaseShape, aResultIndex);
334 // Remove the rest results if there were produced in the previous pass.
335 removeResults(aResultIndex);
338 //=================================================================================================
339 void FeaturesPlugin_Symmetry::buildResult(GeomAlgoAPI_Symmetry& theSymmetryAlgo,
340 std::shared_ptr<GeomAPI_Shape> theBaseShape,
343 // Compose source shape and the result of symmetry.
344 GeomShapePtr aCompound;
345 if (boolean(KEEP_ORIGINAL_RESULT())->value()) {
347 aShapes.push_back(theBaseShape);
348 aShapes.push_back(theSymmetryAlgo.shape());
349 aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
351 aCompound = theSymmetryAlgo.shape();
353 // Store and name the result.
354 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
355 aResultBody->storeModified(theBaseShape, aCompound);
356 loadNamingDS(theSymmetryAlgo, aResultBody, theBaseShape);
357 setResult(aResultBody, theResultIndex);
360 //=================================================================================================
361 void FeaturesPlugin_Symmetry::buildResult(ResultPartPtr theOriginal,
362 std::shared_ptr<GeomAPI_Trsf> theTrsf,
365 if (boolean(KEEP_ORIGINAL_RESULT())->value()) {
366 std::shared_ptr<GeomAPI_Trsf> anIdentity(new GeomAPI_Trsf());
367 ResultPartPtr aCopy = document()->copyPart(theOriginal, data(), theResultIndex);
368 aCopy->setTrsf(theOriginal, anIdentity);
369 setResult(aCopy, theResultIndex);
373 ResultPartPtr aResultPart = document()->copyPart(theOriginal, data(), theResultIndex);
374 aResultPart->setTrsf(theOriginal, theTrsf);
375 setResult(aResultPart, theResultIndex);
378 //=================================================================================================
379 void FeaturesPlugin_Symmetry::loadNamingDS(GeomAlgoAPI_Symmetry& theSymmetryAlgo,
380 std::shared_ptr<ModelAPI_ResultBody> theResultBody,
381 std::shared_ptr<GeomAPI_Shape> theBaseShape)
384 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes = theSymmetryAlgo.mapOfSubShapes();
385 std::string aReflectedName = "Symmetried";
386 FeaturesPlugin_Tools::storeModifiedShapes(theSymmetryAlgo, theResultBody,
387 theBaseShape, 1, 2, 3, aReflectedName,