0030593: Modeling Algorithms - ShapeUpgrade_ShapeDivide::Perform() throws Standard_No...
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_ShapeDivide.cxx
1 // Created on: 1999-04-27
2 // Created by: Pavel DURANDIN
3 // Copyright (c) 1999-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 //    abv 16.06.99 returning ReShape context; processing shared subshapes in compounds
18 //    sln 29.11.01 Bug21: in method Perform(..) nullify location of compound's faces only if mode myConsiderLocation is on
19
20 #include <BRep_Builder.hxx>
21 #include <Message_Msg.hxx>
22 #include <Precision.hxx>
23 #include <ShapeBuild_ReShape.hxx>
24 #include <ShapeExtend.hxx>
25 #include <ShapeExtend_BasicMsgRegistrator.hxx>
26 #include <ShapeUpgrade_FaceDivide.hxx>
27 #include <ShapeUpgrade_ShapeDivide.hxx>
28 #include <ShapeUpgrade_WireDivide.hxx>
29 #include <Standard_ErrorHandler.hxx>
30 #include <Standard_Failure.hxx>
31 #include <TopExp.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <TopoDS.hxx>
34 #include <TopoDS_Compound.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS_Iterator.hxx>
37 #include <TopoDS_Shape.hxx>
38 #include <TopoDS_Vertex.hxx>
39 #include <TopoDS_Wire.hxx>
40
41 //=======================================================================
42 //function : ShapeUpgrade_ShapeDivide
43 //purpose  : 
44 //=======================================================================
45 ShapeUpgrade_ShapeDivide::ShapeUpgrade_ShapeDivide() : myStatus(0)
46 {
47   myPrecision = myMinTol = Precision::Confusion();
48   myMaxTol = 1; //Precision::Infinite() ?? pdn
49   mySplitFaceTool = new ShapeUpgrade_FaceDivide;
50   myContext = new ShapeBuild_ReShape;
51   //myMsgReg = new ShapeExtend_BasicMsgRegistrator;
52   mySegmentMode = Standard_True;
53   myEdgeMode = 2;
54 }
55
56 //=======================================================================
57 //function : ShapeUpgrade_ShapeDivide
58 //purpose  : 
59 //=======================================================================
60
61 ShapeUpgrade_ShapeDivide::ShapeUpgrade_ShapeDivide(const TopoDS_Shape &S) : myStatus(0)
62 {
63   myPrecision = myMinTol = Precision::Confusion();
64   myMaxTol = 1; //Precision::Infinite() ?? pdn
65   mySplitFaceTool = new ShapeUpgrade_FaceDivide;
66   myContext = new ShapeBuild_ReShape;
67   mySegmentMode = Standard_True;
68   myEdgeMode = 2;
69   Init(S);
70 }
71
72 //=======================================================================
73 //function : Init
74 //purpose  : 
75 //=======================================================================
76
77 void ShapeUpgrade_ShapeDivide::Init(const TopoDS_Shape &S)
78 {
79   myShape = S;
80 }
81
82 //=======================================================================
83 //function : ~ShapeUpgrade_ShapeDivide
84 //purpose  : 
85 //=======================================================================
86
87 ShapeUpgrade_ShapeDivide::~ShapeUpgrade_ShapeDivide()
88 {}
89
90
91 //=======================================================================
92 //function : SetPrecision
93 //purpose  : 
94 //=======================================================================
95
96 void ShapeUpgrade_ShapeDivide::SetPrecision (const Standard_Real Prec)
97 {
98   myPrecision = Prec;
99 }
100
101 //=======================================================================
102 //function : SetMaxTolerance
103 //purpose  : 
104 //=======================================================================
105
106 void ShapeUpgrade_ShapeDivide::SetMaxTolerance (const Standard_Real maxtol)
107 {
108   myMaxTol = maxtol;
109 }
110
111
112 //=======================================================================
113 //function : SetMinTolerance
114 //purpose  : 
115 //=======================================================================
116
117 void ShapeUpgrade_ShapeDivide::SetMinTolerance (const Standard_Real mintol)
118 {
119   myMinTol = mintol;
120 }
121
122
123 //=======================================================================
124 //function : SetSurfaceSegmentMode
125 //purpose  : 
126 //=======================================================================
127
128 void ShapeUpgrade_ShapeDivide::SetSurfaceSegmentMode(const Standard_Boolean Segment)
129 {
130   mySegmentMode = Segment;
131 }
132 //=======================================================================
133 //function : Perform
134 //purpose  : 
135 //=======================================================================
136
137 Standard_Boolean ShapeUpgrade_ShapeDivide::Perform(const Standard_Boolean newContext)
138 {
139   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
140   if(myShape.IsNull()) {
141     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
142     return Standard_False;
143   }
144   
145   if ( newContext || myContext.IsNull() ) 
146     myContext = new ShapeBuild_ReShape;
147
148   // Process COMPOUNDs separately in order to handle sharing in assemblies
149   // NOTE: not optimized: subshape can be processed twice (second time - no modif)
150   if ( myShape.ShapeType() == TopAbs_COMPOUND ) {
151     Standard_Integer locStatus = myStatus;
152     TopoDS_Compound C;
153     BRep_Builder B;
154     B.MakeCompound ( C );
155     TopoDS_Shape savShape = myShape;
156     for ( TopoDS_Iterator it(savShape,Standard_False); it.More(); it.Next() ) {
157       TopoDS_Shape shape = it.Value();
158       TopLoc_Location L = shape.Location();
159       if(myContext->ModeConsiderLocation()) {
160         TopLoc_Location nullLoc;
161         shape.Location ( nullLoc );
162       }
163       myShape = myContext->Apply ( shape );
164       Perform ( Standard_False );
165      if(myContext->ModeConsiderLocation()) 
166         myResult.Location ( L );
167       myResult.Orientation(TopAbs::Compose(myResult.Orientation(),savShape.Orientation()));
168       B.Add ( C, myResult );
169       locStatus |= myStatus;
170     }
171     
172     myShape = savShape;
173     myStatus = locStatus;
174     if ( Status ( ShapeExtend_DONE ) ) {
175       myResult = myContext->Apply ( C, TopAbs_SHAPE );
176       myContext->Replace ( myShape, myResult );
177       return Standard_True;
178     }
179     myResult = myShape;
180     return Standard_False;
181   }
182
183   // Process FACEs
184   Handle(ShapeUpgrade_FaceDivide) SplitFace = GetSplitFaceTool();
185   if ( ! SplitFace.IsNull() ) {
186     SplitFace->SetPrecision( myPrecision );
187     SplitFace->SetMaxTolerance(myMaxTol);
188     SplitFace->SetSurfaceSegmentMode(mySegmentMode);
189     Handle(ShapeUpgrade_WireDivide) SplitWire = SplitFace->GetWireDivideTool();
190     if ( ! SplitWire.IsNull() ) {
191       SplitWire->SetMinTolerance(myMinTol);
192       SplitWire->SetEdgeMode(myEdgeMode);
193     }
194     Message_Msg doneMsg = GetFaceMsg();
195
196     for (TopExp_Explorer exp (myShape,TopAbs_FACE); exp.More(); exp.Next())
197     {
198       TopoDS_Shape tmpF = exp.Current().Oriented ( TopAbs_FORWARD );
199       TopoDS_Face F = TopoDS::Face (tmpF); // protection against INTERNAL shapes: cts20105a.rle
200       TopoDS_Shape sh = myContext->Apply ( F, TopAbs_SHAPE );
201       for (TopExp_Explorer exp2 (sh,TopAbs_FACE); exp2.More(); exp2.Next())
202       {
203         try
204         {
205           OCC_CATCH_SIGNALS
206           for (; exp2.More(); exp2.Next())
207           {
208             TopoDS_Face face = TopoDS::Face (exp2.Current());
209             SplitFace->Init(face);
210             SplitFace->SetContext(myContext);
211             SplitFace->Perform();
212             if (SplitFace->Status (ShapeExtend_FAIL))
213             {
214               myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
215             }
216             if (SplitFace->Status (ShapeExtend_DONE))
217             {
218               myContext->Replace (face, SplitFace->Result());
219               SendMsg (face, doneMsg, Message_Info);
220               if (SplitFace->Status (ShapeExtend_DONE1))
221               {
222                 myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
223               }
224               if (SplitFace->Status (ShapeExtend_DONE2))
225               {
226                 myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
227               }
228             }
229           }
230         }
231         catch (Standard_Failure const& anException)
232         {
233         #ifdef OCCT_DEBUG
234           std::cout << "\nError: Exception in ShapeUpgrade_FaceDivide::Perform(): ";
235           anException.Print (std::cout); std::cout << std::endl;
236         #endif
237           (void )anException;
238           myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
239         }
240
241         if (!exp2.More())
242         {
243           break;
244         }
245       }
246     }
247   }
248   
249   // Process free WIREs
250   Handle(ShapeUpgrade_WireDivide) SplitWire = SplitFace->GetWireDivideTool();
251   if ( ! SplitWire.IsNull() ) {
252     SplitWire->SetFace (TopoDS_Face());
253     SplitWire->SetPrecision( myPrecision );
254     SplitWire->SetMaxTolerance(myMaxTol);
255     SplitWire->SetMinTolerance(myMinTol);
256     SplitWire->SetEdgeMode(myEdgeMode);
257     Message_Msg doneMsg = GetWireMsg();
258
259     TopExp_Explorer exp;//svv Jan 10 2000 : porting on DEC
260     for (exp.Init (myShape, TopAbs_WIRE, TopAbs_FACE); exp.More(); exp.Next()) {
261 //smh#8
262       TopoDS_Shape tmpW = exp.Current().Oriented ( TopAbs_FORWARD );
263       TopoDS_Wire W = TopoDS::Wire (tmpW );   // protection against INTERNAL shapes
264       TopoDS_Shape sh = myContext->Apply ( W, TopAbs_SHAPE );
265       for (TopExp_Explorer exp2 (sh,TopAbs_WIRE); exp2.More(); exp2.Next()) {
266         TopoDS_Wire wire = TopoDS::Wire ( exp2.Current() );
267         SplitWire->Load (wire);
268         SplitWire->SetContext(myContext);
269         SplitWire->Perform();
270         if(SplitWire->Status(ShapeExtend_FAIL)) {
271           myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
272         }
273         if(SplitWire->Status(ShapeExtend_DONE)) {
274           myContext->Replace(wire,SplitWire->Wire());
275           SendMsg( wire, doneMsg, Message_Info );
276           myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
277         }
278       }
279     }
280   
281     // Process free EDGEs
282     Message_Msg edgeDoneMsg = GetEdgeMsg();
283     for (exp.Init (myShape, TopAbs_EDGE, TopAbs_WIRE); exp.More(); exp.Next()) {
284 //smh#8
285       TopoDS_Shape tmpE = exp.Current().Oriented ( TopAbs_FORWARD );
286       TopoDS_Edge E = TopoDS::Edge (tmpE );                                       // protection against INTERNAL shapes
287       TopoDS_Vertex V1,V2;
288       TopExp::Vertices(E,V2,V1);
289       if( V1.IsNull() && V2.IsNull() ) continue; // skl 27.10.2004 for OCC5624
290       TopoDS_Shape sh = myContext->Apply ( E, TopAbs_SHAPE );
291       for (TopExp_Explorer exp2 (sh,TopAbs_EDGE); exp2.More(); exp2.Next()) {
292         TopoDS_Edge edge = TopoDS::Edge ( exp2.Current() );
293         SplitWire->Load (edge);
294         SplitWire->SetContext(myContext);
295         SplitWire->Perform();
296         if(SplitWire->Status(ShapeExtend_FAIL)) {
297           myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
298         }
299         if(SplitWire->Status(ShapeExtend_DONE)) {
300           myContext->Replace(edge,SplitWire->Wire());
301           SendMsg( edge, edgeDoneMsg, Message_Info );
302           myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
303         }
304       }
305     }
306   }
307   myResult = myContext->Apply ( myShape, TopAbs_SHAPE );
308   return ! myResult.IsSame ( myShape );
309 }
310
311 //=======================================================================
312 //function : Result
313 //purpose  : 
314 //=======================================================================
315
316 TopoDS_Shape ShapeUpgrade_ShapeDivide::Result() const
317 {
318   return myResult;
319 }
320
321 //=======================================================================
322 //function : GetContext
323 //purpose  : 
324 //=======================================================================
325
326 Handle(ShapeBuild_ReShape) ShapeUpgrade_ShapeDivide::GetContext() const
327 {
328   //if ( myContext.IsNull() ) myContext = new ShapeBuild_ReShape;
329   return myContext;
330 }
331
332 //=======================================================================
333 //function : SetContext
334 //purpose  : 
335 //=======================================================================
336
337 void ShapeUpgrade_ShapeDivide::SetContext (const Handle(ShapeBuild_ReShape) &context)
338 {
339   myContext = context;
340 }
341
342 //=======================================================================
343 //function : SetSplitFaceTool
344 //purpose  : 
345 //=======================================================================
346
347 void ShapeUpgrade_ShapeDivide::SetSplitFaceTool(const Handle(ShapeUpgrade_FaceDivide)& splitFaceTool)
348 {
349   mySplitFaceTool = splitFaceTool;
350 }
351
352 //=======================================================================
353 //function : GetSplitFaceTool
354 //purpose  : 
355 //=======================================================================
356
357 Handle(ShapeUpgrade_FaceDivide) ShapeUpgrade_ShapeDivide::GetSplitFaceTool () const
358 {
359   return mySplitFaceTool;
360 }
361
362 //=======================================================================
363 //function : Status
364 //purpose  : 
365 //=======================================================================
366
367 Standard_Boolean ShapeUpgrade_ShapeDivide::Status (const ShapeExtend_Status status) const
368 {
369   return ShapeExtend::DecodeStatus ( myStatus, status );
370 }
371
372 //=======================================================================
373 //function : SetEdgeMode
374 //purpose  : 
375 //=======================================================================
376
377  void ShapeUpgrade_ShapeDivide::SetEdgeMode(const Standard_Integer aEdgeMode) 
378 {
379   myEdgeMode = aEdgeMode;
380 }
381
382 //=======================================================================
383 //function : SetMsgRegistrator
384 //purpose  : 
385 //=======================================================================
386
387 void ShapeUpgrade_ShapeDivide::SetMsgRegistrator(const Handle(ShapeExtend_BasicMsgRegistrator)& msgreg) 
388 {
389   myMsgReg = msgreg;
390 }
391
392 //=======================================================================
393 //function : MsgRegistrator
394 //purpose  : 
395 //=======================================================================
396
397 Handle(ShapeExtend_BasicMsgRegistrator) ShapeUpgrade_ShapeDivide::MsgRegistrator() const
398 {
399   return myMsgReg;
400 }
401
402 //=======================================================================
403 //function : SendMsg
404 //purpose  :
405 //=======================================================================
406
407 void ShapeUpgrade_ShapeDivide::SendMsg(const TopoDS_Shape& shape,
408                                        const Message_Msg& message,
409                                        const Message_Gravity gravity) const
410 {
411   if ( !myMsgReg.IsNull() )
412     myMsgReg->Send (shape, message, gravity);
413 }
414
415 Message_Msg ShapeUpgrade_ShapeDivide::GetFaceMsg() const
416 {
417   return "ShapeDivide.FaceDivide.MSG0";
418 }
419 Message_Msg ShapeUpgrade_ShapeDivide::GetWireMsg() const
420 {
421   return "ShapeDivide.WireDivide.MSG0";
422 }
423 Message_Msg ShapeUpgrade_ShapeDivide::GetEdgeMsg() const
424 {
425   return "ShapeDivide.EdgeDivide.MSG0";
426 }