Salome HOME
Issue #1834: Fix length of lines
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Partition.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        FeaturesPlugin_Partition.cpp
4 // Created:     31 Jul 2015
5 // Author:      Natalia ERMOLAEVA
6
7 #include "FeaturesPlugin_Partition.h"
8
9 #include <ModelAPI_Data.h>
10 #include <ModelAPI_Document.h>
11 #include <ModelAPI_AttributeBoolean.h>
12 #include <ModelAPI_AttributeReference.h>
13 #include <ModelAPI_AttributeInteger.h>
14 #include <ModelAPI_BodyBuilder.h>
15 #include <ModelAPI_ResultBody.h>
16 #include <ModelAPI_AttributeSelectionList.h>
17 #include <ModelAPI_Session.h>
18 #include <ModelAPI_Validator.h>
19
20 #include <GeomAlgoAPI_CompoundBuilder.h>
21 #include <GeomAlgoAPI_Partition.h>
22 #include <GeomAlgoAPI_MakeShapeCustom.h>
23 #include <GeomAlgoAPI_MakeShapeList.h>
24 #include <GeomAlgoAPI_ShapeTools.h>
25
26 #include <GeomAPI_Face.h>
27 #include <GeomAPI_ShapeExplorer.h>
28 #include <GeomAPI_ShapeIterator.h>
29
30 #include <iostream>
31 #include <sstream>
32
33 static GeomShapePtr findBase(const GeomShapePtr theObjectShape,
34                              const GeomShapePtr theResultShape,
35                              const GeomAPI_Shape::ShapeType theShapeType,
36                              const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape);
37
38 //=================================================================================================
39 FeaturesPlugin_Partition::FeaturesPlugin_Partition()
40 {
41 }
42
43 //=================================================================================================
44 void FeaturesPlugin_Partition::initAttributes()
45 {
46   data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
47 }
48
49 //=================================================================================================
50 void FeaturesPlugin_Partition::execute()
51 {
52   ListOfShape anObjects, aPlanes;
53
54   // Getting objects.
55   AttributeSelectionListPtr anObjectsSelList = selectionList(BASE_OBJECTS_ID());
56   for(int anIndex = 0; anIndex < anObjectsSelList->size(); ++anIndex) {
57     AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anIndex);
58     GeomShapePtr anObject = anObjectAttr->value();
59     if(!anObject.get()) {
60       // It could be a construction plane.
61       ResultPtr aContext = anObjectAttr->context();
62       aPlanes.push_back(anObjectAttr->context()->shape());
63     } else {
64       anObjects.push_back(anObject);
65     }
66   }
67
68   if(anObjects.empty()) {
69     static const std::string aFeatureError = "Error: No objects for partition.";
70     setError(aFeatureError);
71     return;
72   }
73
74   std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
75     GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0);
76
77   // Resize planes.
78   ListOfShape aTools;
79   std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
80   for(ListOfShape::const_iterator anIt = aPlanes.cbegin(); anIt != aPlanes.cend(); ++anIt) {
81     GeomShapePtr aPlane = *anIt;
82     GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
83     std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(new GeomAlgoAPI_MakeShapeCustom);
84     aMkShCustom->addModified(aPlane, aTool);
85     aMakeShapeList->appendAlgo(aMkShCustom);
86     aTools.push_back(aTool);
87   }
88
89   // Create single result.
90   std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo(
91     new GeomAlgoAPI_Partition(anObjects, aTools));
92
93   // Checking that the algorithm worked properly.
94   if (!aPartitionAlgo->isDone()) {
95     static const std::string aFeatureError = "Error: Partition algorithm failed.";
96     setError(aFeatureError);
97     return;
98   }
99   if (aPartitionAlgo->shape()->isNull()) {
100     static const std::string aShapeError = "Error: Resulting shape is Null.";
101     setError(aShapeError);
102     return;
103   }
104   if (!aPartitionAlgo->isValid()) {
105     std::string aFeatureError = "Error: Resulting shape is not valid.";
106     setError(aFeatureError);
107     return;
108   }
109   aMakeShapeList->appendAlgo(aPartitionAlgo);
110   GeomShapePtr aResultShape = aPartitionAlgo->shape();
111
112   int aResultIndex = 0;
113   if(aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
114     for(GeomAPI_ShapeIterator anIt(aResultShape); anIt.more(); anIt.next()) {
115       storeResult(anObjects, aPlanes, anIt.current(), aMakeShapeList, aResultIndex);
116       ++aResultIndex;
117     }
118   } else {
119     storeResult(anObjects, aPlanes, aResultShape, aMakeShapeList, aResultIndex);
120     ++aResultIndex;
121   }
122
123   // Remove the rest results if there were produced in the previous pass.
124   removeResults(aResultIndex);
125 }
126
127 //=================================================================================================
128 void FeaturesPlugin_Partition::storeResult(
129   ListOfShape& theObjects, ListOfShape& thePlanes,
130   const GeomShapePtr theResultShape,
131   const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
132   const int theIndex)
133 {
134   // Find base. The most complicated is the real modified object (#1799 if box is partitioned by 
135   // two planes the box is the base, not planes, independently on the order in the list).
136   GeomShapePtr aBaseShape;
137   for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) {
138     GeomShapePtr anObjectShape = *anIt;
139     GeomShapePtr aCandidate =
140       findBase(anObjectShape, theResultShape, GeomAPI_Shape::VERTEX, theMakeShape);
141     if(!aCandidate.get()) {
142       aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::EDGE, theMakeShape);
143     }
144     if (!aCandidate.get())
145       aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::FACE, theMakeShape);
146
147     if(aCandidate.get()) {
148       if (!aBaseShape.get() || aBaseShape->shapeType() > aCandidate->shapeType()) {
149         aBaseShape = aCandidate;
150       }
151     }
152   }
153
154   // Create result body.
155   ResultBodyPtr aResultBody = document()->createBody(data(), theIndex);
156
157   // Store modified shape.
158   if(!aBaseShape.get() || aBaseShape->isEqual(theResultShape)) {
159     aResultBody->store(theResultShape);
160     setResult(aResultBody, theIndex);
161     return;
162   }
163
164   const int aDelTag = 1;
165   /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
166   const int aSubTag = 2; 
167   int aModTag = aSubTag + 10000;
168   const std::string aModName = "Modified";
169
170   aResultBody->storeModified(aBaseShape, theResultShape, aSubTag);
171
172   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
173   theObjects.insert(theObjects.end(), thePlanes.begin(), thePlanes.end());
174   int anIndex = 1;
175   for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) {
176     GeomShapePtr aShape = *anIt;
177     std::string aModEdgeName = aModName + "_Edge_" + std::to_string((long long)anIndex);
178     std::string aModFaceName = aModName + "_Face_" + std::to_string((long long)anIndex++);
179     aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::EDGE,
180                                              aModTag, aModEdgeName, *aMapOfSubShapes.get(), true);
181     aModTag += 10000;
182     aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE,
183                                              aModTag, aModFaceName, *aMapOfSubShapes.get(), true);
184     aModTag += 10000;
185     aResultBody->loadDeletedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::EDGE, aDelTag);
186     aResultBody->loadDeletedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE, aDelTag);
187   }
188
189   setResult(aResultBody, theIndex);
190 }
191
192
193 //=================================================================================================
194 GeomShapePtr findBase(const GeomShapePtr theObjectShape,
195                       const GeomShapePtr theResultShape,
196                       const GeomAPI_Shape::ShapeType theShapeType,
197                       const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
198 {
199   GeomShapePtr aBaseShape;
200   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
201   for(GeomAPI_ShapeExplorer anObjectSubShapesExp(theObjectShape, theShapeType);
202       anObjectSubShapesExp.more();
203       anObjectSubShapesExp.next()) {
204     GeomShapePtr anObjectSubShape = anObjectSubShapesExp.current();
205     ListOfShape aModifiedShapes;
206     theMakeShape->modified(anObjectSubShape, aModifiedShapes);
207     for(ListOfShape::const_iterator 
208         aModIt = aModifiedShapes.cbegin(); aModIt != aModifiedShapes.cend(); ++aModIt) {
209       GeomShapePtr aModShape = *aModIt;
210       if(aMapOfSubShapes->isBound(aModShape)) {
211         aModShape = aMapOfSubShapes->find(aModShape);
212       }
213       if(theResultShape->isSubShape(aModShape)) {
214         aBaseShape = theObjectShape;
215         break;
216       }
217     }
218     if(aBaseShape.get()) {
219       break;
220     }
221   }
222
223   return aBaseShape;
224 }