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