Salome HOME
cd6235466f679186621aa693d3d531e4f015f8e6
[modules/geom.git] / src / GEOMImpl / GEOMImpl_GlueDriver.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include <Standard_Stream.hxx>
23
24 #include <GEOMImpl_GlueDriver.hxx>
25 #include <GEOMImpl_IGlue.hxx>
26 #include <GEOMImpl_Types.hxx>
27
28 #include <GEOM_Object.hxx>
29 #include <GEOM_Function.hxx>
30
31 #include <GEOMAlgo_Gluer.hxx>
32 #include "GEOMAlgo_Gluer1.hxx"
33 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
34 #include "GEOMAlgo_CoupleOfShapes.hxx"
35 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
36
37 #include "utilities.h"
38
39 #include <TDataStd_IntegerArray.hxx>
40
41 #include <TopExp.hxx>
42 #include <TopoDS_Shape.hxx>
43 #include <TopTools_ListOfShape.hxx>
44 #include <TopTools_IndexedMapOfShape.hxx>
45 #include <TopTools_ListIteratorOfListOfShape.hxx>
46
47 #include <Standard_NullObject.hxx>
48 #include <Standard_Failure.hxx>
49
50 #define MSG_BAD_TOLERANCE "Tolerance is too big"
51 #define MSG_BAD_ARG_SHAPE "Argument shape is not a compound of hexahedral solids"
52
53 //=======================================================================
54 //function : GEOMImpl_GlueDriver
55 //purpose  :
56 //=======================================================================
57 GEOMImpl_GlueDriver::GEOMImpl_GlueDriver()
58 {
59 }
60
61 //=======================================================================
62 //function : GetID
63 //purpose  :
64 //=======================================================================
65 const Standard_GUID& GEOMImpl_GlueDriver::GetID()
66 {
67   static Standard_GUID aGlueDriver("FF1BBB63-5D14-4df2-980B-3A668264EA16");
68   return aGlueDriver;
69 }
70
71 //=======================================================================
72 //function : GlueFacesWithWarnings
73 //purpose  :
74 //=======================================================================
75 TopoDS_Shape GEOMImpl_GlueDriver::GlueFacesWithWarnings (const TopoDS_Shape& theShape,
76                                                          const Standard_Real theTolerance,
77                                                          const Standard_Boolean doKeepNonSolids,
78                                                          TCollection_AsciiString& theWarning) const
79 {
80   Standard_Integer iErr, iWrn;
81   TopoDS_Shape aRes;
82   GEOMAlgo_Gluer aGluer;
83
84   aGluer.SetShape(theShape);
85   aGluer.SetTolerance(theTolerance);
86   aGluer.SetCheckGeometry(Standard_True);
87   aGluer.SetKeepNonSolids(doKeepNonSolids);
88
89   aGluer.Perform();
90
91   iErr = aGluer.ErrorStatus();
92   if (iErr) {
93     switch (iErr) {
94     case 2:
95       Standard_Failure::Raise("No vertices found in source shape");
96       break;
97     case 3:
98     case 4:
99       Standard_Failure::Raise(MSG_BAD_TOLERANCE " or " MSG_BAD_ARG_SHAPE);
100       break;
101     case 5:
102       Standard_Failure::Raise("Source shape is Null");
103       break;
104     case 6:
105       Standard_Failure::Raise("Result shape is Null");
106       break;
107     case 100:
108       Standard_Failure::Raise(MSG_BAD_TOLERANCE);
109       break;
110     case 101:
111     case 102:
112       Standard_Failure::Raise(MSG_BAD_ARG_SHAPE);
113       break;
114     case 200:
115       Standard_Failure::Raise("Error occured during check of geometric coincidence");
116       break;
117     default:
118       {
119         // description of all errors see in GEOMAlgo_Gluer.cxx
120         TCollection_AsciiString aMsg ("Error in GEOMAlgo_Gluer with code ");
121         aMsg += TCollection_AsciiString(iErr);
122         Standard_Failure::Raise(aMsg.ToCString());
123         break;
124       }
125     }
126     return aRes;
127   }
128
129   iWrn = aGluer.WarningStatus();
130   if (iWrn) {
131     switch (iWrn) {
132     case 1:
133       {
134         Standard_Integer nbAlone = aGluer.AloneShapes();
135         theWarning = TCollection_AsciiString(nbAlone);
136         theWarning += " solid(s) can not be glued by faces";
137       }
138       break;
139     default:
140       // description of all warnings see in GEOMAlgo_Gluer.cxx
141       theWarning = "Warning in GEOMAlgo_Gluer with code ";
142       theWarning += TCollection_AsciiString(iWrn);
143       break;
144     }
145   }
146
147   aRes = aGluer.Result();
148
149   // Fill history to be used by GetInPlace functionality
150   TopTools_IndexedMapOfShape aResIndices;
151   TopExp::MapShapes(aRes, aResIndices);
152
153   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
154
155   // history for all argument shapes
156   TDF_LabelSequence aLabelSeq;
157   aFunction->GetDependency(aLabelSeq);
158   Standard_Integer nbArg = aLabelSeq.Length();
159
160   for (Standard_Integer iarg = 1; iarg <= nbArg; iarg++) {
161
162     TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
163
164     Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
165     TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
166
167     TopTools_IndexedMapOfShape anArgumentIndices;
168     TopExp::MapShapes(anArgumentShape, anArgumentIndices);
169     Standard_Integer nbArgumentEntities = anArgumentIndices.Extent();
170
171     // Find corresponding label in history
172     TDF_Label anArgumentHistoryLabel =
173       aFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_True);
174
175     for (Standard_Integer ie = 1; ie <= nbArgumentEntities; ie++) {
176       TopoDS_Shape anEntity = anArgumentIndices.FindKey(ie);
177       const TopTools_ListOfShape& aModified = aGluer.Modified(anEntity);
178       Standard_Integer nbModified = aModified.Extent();
179
180       if (nbModified > 0) {
181         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(ie, Standard_True);
182         Handle(TDataStd_IntegerArray) anAttr =
183           TDataStd_IntegerArray::Set(aWhatHistoryLabel, 1, nbModified);
184
185         TopTools_ListIteratorOfListOfShape itM (aModified);
186         for (int im = 1; itM.More(); itM.Next(), ++im) {
187           int id = aResIndices.FindIndex(itM.Value());
188           anAttr->SetValue(im, id);
189         }
190       }
191     }
192   }
193
194   return aRes;
195 }
196
197
198 //=======================================================================
199 //function : GlueFaces
200 //purpose  :
201 //=======================================================================
202 TopoDS_Shape GEOMImpl_GlueDriver::GlueFaces (const TopoDS_Shape& theShape,
203                                              const Standard_Real theTolerance,
204                                              const Standard_Boolean doKeepNonSolids)
205 {
206   Standard_Integer iErr, iWrn;
207   TopoDS_Shape aRes;
208   GEOMAlgo_Gluer aGluer;
209
210   aGluer.SetShape(theShape);
211   aGluer.SetTolerance(theTolerance);
212   aGluer.SetCheckGeometry(Standard_True);
213   aGluer.SetKeepNonSolids(doKeepNonSolids);
214
215   aGluer.Perform();
216
217   iErr = aGluer.ErrorStatus();
218   if (iErr) {
219     switch (iErr) {
220     case 2:
221       Standard_Failure::Raise("No vertices found in source shape");
222       break;
223     case 5:
224       Standard_Failure::Raise("Source shape is Null");
225       break;
226     case 6:
227       Standard_Failure::Raise("Result shape is Null");
228       break;
229     case 200:
230       Standard_Failure::Raise("Error occured during check of geometric coincidence");
231       break;
232     default:
233       {
234         // description of all errors see in GEOMAlgo_Gluer.cxx
235         TCollection_AsciiString aMsg ("Error in GEOMAlgo_Gluer with code ");
236         aMsg += TCollection_AsciiString(iErr);
237         Standard_Failure::Raise(aMsg.ToCString());
238         break;
239       }
240     }
241     return aRes;
242   }
243
244   iWrn = aGluer.WarningStatus();
245   if (iWrn) {
246     switch (iWrn) {
247     case 1:
248       MESSAGE("Some shapes can not be glued by faces");
249       break;
250     default:
251       // description of all warnings see in GEOMAlgo_Gluer.cxx
252       MESSAGE("Warning in GEOMAlgo_Gluer with code " << iWrn);
253       break;
254     }
255   }
256
257   aRes = aGluer.Result();
258
259   return aRes;
260 }
261
262
263 //=======================================================================
264 //function : GlueFacesByList
265 //purpose  :
266 //=======================================================================
267 TopoDS_Shape GEOMImpl_GlueDriver::GlueFacesByList (const TopoDS_Shape& theShape,
268                                                    const Standard_Real theTolerance,
269                                                    const Standard_Boolean doKeepNonSolids,
270                                                    const TopTools_MapOfShape& aFaces)
271 {
272   TopoDS_Shape aRes;
273
274   GEOMAlgo_Gluer1 aGluer;
275   GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
276   GEOMAlgo_CoupleOfShapes aCS;
277   GEOMAlgo_ListOfCoupleOfShapes aLCS;
278
279   aGluer.SetShape(theShape);
280   aGluer.SetTolerance(theTolerance);
281   aGluer.SetKeepNonSolids(doKeepNonSolids);
282   aGluer.Perform();
283   Standard_Integer iErr = aGluer.ErrorStatus();
284   if (iErr) return aRes;
285
286   TopTools_ListOfShape listShape;
287   const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
288   // Access to faces
289   aItCS.Initialize(aLCSG);
290   for (; aItCS.More(); aItCS.Next()) {
291     const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
292     const TopoDS_Shape& aF1 = aCSG.Shape1();
293     const TopoDS_Shape& aF2 = aCSG.Shape2();
294     if( aFaces.Contains(aF1) || aFaces.Contains(aF2) )
295       continue;
296     aCS.SetShapes(aF1,aF2);
297     aLCS.Append(aCS);
298   }
299
300   //cout<<"aLCS.Extent() = "<<aLCS.Extent()<<endl;
301   if(aLCS.Extent()>0) {
302     aGluer.SetFacesToUnglue(aLCS);
303     aGluer.UnglueFaces();
304     iErr = aGluer.ErrorStatus();
305     if (iErr) return aRes;
306   }
307
308   aRes = aGluer.Result();
309
310   return aRes;
311 }
312
313
314 //=======================================================================
315 //function : Execute
316 //purpose  :
317 //=======================================================================
318 Standard_Integer GEOMImpl_GlueDriver::Execute(TFunction_Logbook& log) const
319 {
320   if (Label().IsNull()) return 0;
321   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
322
323   GEOMImpl_IGlue aCI (aFunction);
324   Standard_Integer aType = aFunction->GetType();
325
326   TopoDS_Shape aShape;
327   TCollection_AsciiString aWrn;
328
329   Handle(GEOM_Function) aRefBase = aCI.GetBase();
330   TopoDS_Shape aShapeBase = aRefBase->GetValue();
331   if (aShapeBase.IsNull()) {
332     Standard_NullObject::Raise("Shape for gluing is null");
333   }
334
335   Standard_Real tol3d = aCI.GetTolerance();
336
337   Standard_Boolean aKeepNonSolids = aCI.GetKeepNonSolids();
338
339   if (aType == GLUE_FACES) {
340     aShape = GlueFacesWithWarnings(aShapeBase, tol3d, aKeepNonSolids, aWrn);
341   }
342   else { // aType == GLUE_FACES_BY_LIST
343     Handle(TColStd_HSequenceOfTransient) SF = aCI.GetFaces();
344     TopTools_MapOfShape aFaces;
345     int i=1;
346     for( ; i <= SF->Length(); i++) {
347       Handle(Standard_Transient) anItem = SF->Value(i);
348       if(anItem.IsNull())
349         continue;
350       Handle(GEOM_Function) aRefSh = Handle(GEOM_Function)::DownCast(anItem);
351       if(aRefSh.IsNull())
352         continue;
353       TopoDS_Shape aFace = aRefSh->GetValue();
354       if(aFace.IsNull())
355         continue;
356       if(!aFaces.Contains(aFace))
357         aFaces.Add(aFace);
358     }
359     aShape = GlueFacesByList(aShapeBase, tol3d, aKeepNonSolids, aFaces);
360   }
361
362   if (aShape.IsNull()) return 0;
363
364   aFunction->SetValue(aShape);
365
366   log.SetTouched(Label());
367
368   if (!aWrn.IsEmpty()) {
369     Standard_Failure::Raise(aWrn.ToCString());
370   }
371
372   return 1;
373 }
374
375 //=======================================================================
376 //function :  GEOMImpl_GlueDriver_Type_
377 //purpose  :
378 //=======================================================================
379 Standard_EXPORT Handle_Standard_Type& GEOMImpl_GlueDriver_Type_()
380 {
381
382   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
383   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
384   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
385   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
386   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
387   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
388
389
390   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
391   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_GlueDriver",
392                                                          sizeof(GEOMImpl_GlueDriver),
393                                                          1,
394                                                          (Standard_Address)_Ancestors,
395                                                          (Standard_Address)NULL);
396
397   return _aType;
398 }
399
400 //=======================================================================
401 //function : DownCast
402 //purpose  :
403 //=======================================================================
404 const Handle(GEOMImpl_GlueDriver) Handle(GEOMImpl_GlueDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
405 {
406   Handle(GEOMImpl_GlueDriver) _anOtherObject;
407
408   if (!AnObject.IsNull()) {
409      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_GlueDriver))) {
410        _anOtherObject = Handle(GEOMImpl_GlueDriver)((Handle(GEOMImpl_GlueDriver)&)AnObject);
411      }
412   }
413
414   return _anOtherObject ;
415 }