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