0023948: Wrong intersection between a surface of revolution and a plane.
[occt.git] / src / ShapeProcess / ShapeProcess_ShapeContext.cxx
1 // Created on: 2000-08-22
2 // Created by: Andrey BETENEV
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <ShapeProcess_ShapeContext.ixx>
17
18 #include <TCollection_AsciiString.hxx>
19 #include <TopoDS_Iterator.hxx>
20 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
21 #include <BRep_Builder.hxx>
22
23 #include <Message_Msg.hxx>
24 #include <Message_Messenger.hxx>
25 #include <Message_ListOfMsg.hxx>
26 #include <Message_ListIteratorOfListOfMsg.hxx>
27 #include <ShapeExtend_MsgRegistrator.hxx>
28 #include <ShapeExtend_DataMapOfShapeListOfMsg.hxx>
29
30 //=======================================================================
31 //function : ShapeProcess_ShapeContext
32 //purpose  : 
33 //=======================================================================
34
35 ShapeProcess_ShapeContext::ShapeProcess_ShapeContext (const Standard_CString file,
36                                                       const Standard_CString seq) 
37      : ShapeProcess_Context ( file, seq ), myUntil(TopAbs_FACE)
38 {
39 }
40
41 //=======================================================================
42 //function : ShapeProcess_ShapeContext
43 //purpose  : 
44 //=======================================================================
45
46 ShapeProcess_ShapeContext::ShapeProcess_ShapeContext (const TopoDS_Shape &S,
47                                                       const Standard_CString file,
48                                                       const Standard_CString seq) 
49      : ShapeProcess_Context ( file, seq ), myUntil(TopAbs_FACE)
50 {
51   Init ( S );
52 }
53
54 //=======================================================================
55 //function : Init
56 //purpose  : 
57 //=======================================================================
58
59 void ShapeProcess_ShapeContext::Init (const TopoDS_Shape &S)
60 {
61   myMap.Clear();
62   myMsg = new ShapeExtend_MsgRegistrator;
63   myShape = S;
64   myResult = myShape;//.Nullify();
65 }
66
67 //=======================================================================
68 //function : Shape
69 //purpose  : 
70 //=======================================================================
71
72 const TopoDS_Shape &ShapeProcess_ShapeContext::Shape () const
73 {
74   return myShape;
75 }
76
77 //=======================================================================
78 //function : Result
79 //purpose  : 
80 //=======================================================================
81
82 const TopoDS_Shape &ShapeProcess_ShapeContext::Result () const
83 {
84   return myResult;
85 }
86
87 //=======================================================================
88 //function : Map
89 //purpose  : 
90 //=======================================================================
91
92 const TopTools_DataMapOfShapeShape &ShapeProcess_ShapeContext::Map () const
93 {
94   return myMap;
95 }
96
97 //=======================================================================
98 //function : Messages
99 //purpose  : 
100 //=======================================================================
101
102 Handle(ShapeExtend_MsgRegistrator) &ShapeProcess_ShapeContext::Messages () 
103 {
104   return myMsg;
105 }
106
107 //=======================================================================
108 //function : Messages
109 //purpose  : 
110 //=======================================================================
111
112 const Handle(ShapeExtend_MsgRegistrator) &ShapeProcess_ShapeContext::Messages () const
113 {
114   return myMsg;
115 }
116
117 //=======================================================================
118 //function : SetDetalisation
119 //purpose  : 
120 //=======================================================================
121
122 void ShapeProcess_ShapeContext::SetDetalisation (const TopAbs_ShapeEnum level)
123 {
124   myUntil = level;
125 }
126
127 //=======================================================================
128 //function : GetDetalisation
129 //purpose  : 
130 //=======================================================================
131
132 TopAbs_ShapeEnum ShapeProcess_ShapeContext::GetDetalisation () const
133 {
134   return myUntil;
135 }
136        
137 //=======================================================================
138 //function : SetResult
139 //purpose  : 
140 //=======================================================================
141
142 void ShapeProcess_ShapeContext::SetResult (const TopoDS_Shape &res) 
143 {
144   myResult = res;
145   myMap.Bind ( myShape, myResult );
146 }
147
148 //=======================================================================
149 //function : RecordModification
150 //purpose  : 
151 //=======================================================================
152
153 /*
154 #ifdef DEB
155 static void DumpMap (const TopTools_DataMapOfShapeShape &map)
156 {
157   cout << "----" << endl;
158   cout << "Map:" << endl;
159   for (TopTools_DataMapIteratorOfDataMapOfShapeShape It (map); It.More(); It.Next()) {
160     TopoDS_Shape S0 = It.Key(), S = It.Value();
161     cout << S0.TShape()->DynamicType()->Name() << "\t" << *(void**)&S0.TShape() << 
162       "     \t->    " << S.TShape()->DynamicType()->Name() << "\t" << *(void**)&S.TShape() << endl;
163   }
164   cout << "----" << endl;
165 }            
166 #endif
167 */
168
169 static void RecModif (const TopoDS_Shape &S, 
170                       const TopTools_DataMapOfShapeShape &repl,
171                       TopTools_DataMapOfShapeShape &map,
172                       const TopAbs_ShapeEnum until)
173 {
174   TopoDS_Shape r = S;
175   //gka  -modification to keep history for shape with location (OCC21617)
176   TopLoc_Location aShLoc = S.Location();
177   TopLoc_Location aNullLoc;
178   r.Location(aNullLoc);
179
180   if ( map.IsBound ( r ) ) 
181     r = map.Find ( r );
182   if ( ! r.IsNull() ) {
183     TopoDS_Shape res = r;
184     
185     if ( repl.IsBound ( r.Located(aShLoc) ) ) {
186       res = repl.Find (  r.Located(aShLoc) );
187       // it is supposed that map is created for r having FORWARD orientation
188       // hence, if it is reversed, result should be reversed too
189       // INTERNAL or EXTERNAL orientations are not allowed
190       if ( r.Orientation() != TopAbs_FORWARD ) 
191         res.Reverse();
192      
193     }
194     // Treat special case: if S was split, r will be a compound of
195     // resulting shapes, each to be checked separately
196     // It is supposed that repl does not contain such splitting
197     else if ( r.ShapeType() < S.ShapeType() ) {
198       TopoDS_Shape result = r.EmptyCopied();
199       result.Orientation(TopAbs_FORWARD); // protect against INTERNAL or EXTERNAL shapes
200       Standard_Boolean modif = Standard_False;
201       BRep_Builder B;
202       for ( TopoDS_Iterator it(r,Standard_False); it.More(); it.Next() ) {
203         TopoDS_Shape sh = it.Value();
204         if ( repl.IsBound(sh) ) {
205           TopoDS_Shape newsh = repl.Find(sh);
206           if ( ! newsh.IsNull() ) B.Add ( result, newsh );
207           modif = Standard_True;
208         }
209         else B.Add ( result, sh );
210       }
211       if ( modif ) res = result;
212     }
213     
214     if ( res != r ) map.Bind ( S.Located(aNullLoc), res );
215   }
216   
217   if ( until == TopAbs_SHAPE || S.ShapeType() >= until ) return;
218
219   for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
220     RecModif ( it.Value(), repl, map, until );
221   }
222 }
223
224 void ShapeProcess_ShapeContext::RecordModification (const TopTools_DataMapOfShapeShape &repl)
225 {
226   if ( repl.Extent() <=0 ) return;
227   RecModif ( myShape, repl, myMap, myUntil );
228   if ( myMap.IsBound(myShape) ) myResult = myMap.Find ( myShape );
229 #ifdef DEB
230 //  cout << "Modifier: " << endl; DumpMap (myMap);
231 #endif
232 }
233
234 //=======================================================================
235 //function : RecordModification
236 //purpose  : 
237 //=======================================================================
238
239 static void RecModif (const TopoDS_Shape &S, 
240                       const Handle(ShapeBuild_ReShape) &repl,
241                       const Handle(ShapeExtend_MsgRegistrator) &msg,
242                       TopTools_DataMapOfShapeShape &map,
243                       Handle(ShapeExtend_MsgRegistrator) &myMsg,
244                       const TopAbs_ShapeEnum until)
245 {
246   if(S.IsNull())
247     return;
248   //gka  -modification to keep history for shape with location (OCC21617)
249   TopLoc_Location aNullLoc;
250   TopoDS_Shape aS = S.Located(aNullLoc);
251   TopoDS_Shape r = aS;
252  
253   if ( map.IsBound ( r ) ) 
254     r = map.Find ( r );
255   if ( ! r.IsNull() ) {
256     TopoDS_Shape res;
257     if ( repl->Status (r, res, Standard_True ) && res != r ) 
258       map.Bind ( aS, res );
259     
260     // Treat special case: if S was split, r will be a compound of
261     // resulting shapes, recursive procedure should be applied
262     else if ( r.ShapeType() < S.ShapeType() ) {
263       res = repl->Apply ( r, (TopAbs_ShapeEnum)((Standard_Integer)S.ShapeType()+1) );
264       if ( res != r ) map.Bind ( aS, res );
265     }
266   }
267
268   // update messages (messages must be taken from each level in the substitution map)
269   if ( ! r.IsNull() && ! myMsg.IsNull() && 
270        ! msg.IsNull() && msg->MapShape().Extent() >0 ) {
271     TopoDS_Shape cur, next = r;
272     const ShapeExtend_DataMapOfShapeListOfMsg& msgmap = msg->MapShape();
273     do {
274       cur = next;
275       if (msgmap.IsBound (cur)) {
276         const Message_ListOfMsg &msglist = msgmap.Find (cur);
277         for (Message_ListIteratorOfListOfMsg iter (msglist); iter.More(); iter.Next()) {
278           myMsg->Send ( S, iter.Value(), Message_Warning );
279         }
280       }
281       next = repl->Value (cur);
282     } while ( ! next.IsNull() && cur != next);
283   }
284
285   if ( until == TopAbs_SHAPE || S.ShapeType() >= until ) return;
286   
287   for ( TopoDS_Iterator it(S,Standard_False,Standard_False); it.More(); it.Next() ) {
288     RecModif ( it.Value(), repl, msg, map, myMsg, until );
289   }
290 }
291
292 void ShapeProcess_ShapeContext::RecordModification (const Handle(ShapeBuild_ReShape) &repl,
293                                                     const Handle(ShapeExtend_MsgRegistrator) &msg)
294 {
295   
296   RecModif ( myShape, repl, msg, myMap, myMsg, myUntil );
297   if ( myMap.IsBound(myShape) ) 
298   {
299     myResult = myMap.Find ( myShape );
300     myResult.Location(myShape.Location());
301   }
302 #ifdef DEB
303 //  cout << "ReShape: " << endl; DumpMap (myMap);
304 #endif
305 }
306
307 //=======================================================================
308 //function : RecordModification
309 //purpose  : 
310 //=======================================================================
311
312 void ShapeProcess_ShapeContext::RecordModification (const Handle(ShapeBuild_ReShape) &repl)
313 {
314   Handle(ShapeExtend_MsgRegistrator) msg;
315   RecordModification ( repl, msg );
316 }
317
318 //=======================================================================
319 //function : AddMessage
320 //purpose  : 
321 //=======================================================================
322
323 void ShapeProcess_ShapeContext::AddMessage (const TopoDS_Shape &S,
324                                             const Message_Msg &msg,
325                                             const Message_Gravity grv) 
326 {
327   if ( ! myMsg.IsNull() ) myMsg->Send ( S, msg, grv );
328 }
329
330 //=======================================================================
331 //function : RecordModification
332 //purpose  : 
333 //=======================================================================
334
335 static void ExplodeModifier (const TopoDS_Shape &S, 
336                              const BRepTools_Modifier &repl,
337                              TopTools_DataMapOfShapeShape &map,
338                              const TopAbs_ShapeEnum until)
339 {
340   TopoDS_Shape res = repl.ModifiedShape ( S );
341   
342   if ( res != S ) 
343   {
344    map.Bind ( S, res );
345  }
346   if ( until == TopAbs_SHAPE || S.ShapeType() >= until ) return;
347   for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
348     ExplodeModifier ( it.Value(), repl, map, until );
349   }
350 }
351
352 void ShapeProcess_ShapeContext::RecordModification (const TopoDS_Shape &S, 
353                                                     const BRepTools_Modifier &repl)
354 {
355   TopTools_DataMapOfShapeShape map;
356   ExplodeModifier ( S, repl, map, myUntil );
357   RecordModification ( map );
358 }
359
360 //=======================================================================
361 //function : GetContinuity
362 //purpose  : 
363 //=======================================================================
364
365 Standard_Boolean ShapeProcess_ShapeContext::GetContinuity (const Standard_CString param,
366                                                            GeomAbs_Shape &cont) const
367 {
368   TCollection_AsciiString str;
369   if ( ! GetString ( param, str ) ) return Standard_False;
370   
371   str.LeftAdjust();
372   str.RightAdjust();
373   str.UpperCase();
374   
375   if      ( str.IsEqual ( "C0" ) ) cont = GeomAbs_C0;
376   else if ( str.IsEqual ( "G1" ) ) cont = GeomAbs_G1;
377   else if ( str.IsEqual ( "C1" ) ) cont = GeomAbs_C1;
378   else if ( str.IsEqual ( "G2" ) ) cont = GeomAbs_G2;
379   else if ( str.IsEqual ( "C2" ) ) cont = GeomAbs_C2;
380   else if ( str.IsEqual ( "C3" ) ) cont = GeomAbs_C3;
381   else if ( str.IsEqual ( "CN" ) ) cont = GeomAbs_CN;
382   else return Standard_False;
383   return Standard_True;
384 }
385
386 //=======================================================================
387 //function : ContinuityVal
388 //purpose  : 
389 //=======================================================================
390
391 GeomAbs_Shape ShapeProcess_ShapeContext::ContinuityVal (const Standard_CString param,
392                                                         const GeomAbs_Shape def) const
393 {
394   GeomAbs_Shape val;
395   return GetContinuity ( param, val ) ? val : def;
396 }
397
398 //=======================================================================
399 //function : PrintStatistics
400 //purpose  : 
401 //=======================================================================
402
403 void ShapeProcess_ShapeContext::PrintStatistics () const
404 {
405   Standard_Integer SS = 0, SN = 0, FF = 0, FS = 0, FN = 0;
406   for (TopTools_DataMapIteratorOfDataMapOfShapeShape It (myMap); It.More(); It.Next()) {
407     TopoDS_Shape keyshape = It.Key(), valueshape = It.Value();
408     if (keyshape.ShapeType() == TopAbs_SHELL)
409       if (valueshape.IsNull()) SN++;
410       else SS++;
411     else if (keyshape.ShapeType() == TopAbs_FACE)
412     {
413       if (valueshape.IsNull()) FN++;
414       else if (valueshape.ShapeType() == TopAbs_SHELL) FS++;
415       else FF++;
416     }
417   }
418   
419   // mapping
420   Message_Msg EPMSG100 ("PrResult.Print.MSG100"); //Mapping:
421   Messenger()->Send (EPMSG100, Message_Info);
422   Message_Msg TPMSG50 ("PrResult.Print.MSG50"); //  Shells:
423   Messenger()->Send (TPMSG50, Message_Info);
424   Message_Msg EPMSG110 ("PrResult.Print.MSG110"); //    Result is Shell                 : %d
425   EPMSG110.Arg (SS);
426   Messenger()->Send (EPMSG110, Message_Info);
427   Message_Msg EPMSG150 ("PrResult.Print.MSG150"); //    No Result                       : %d
428   EPMSG150.Arg (SN);
429   Messenger()->Send (EPMSG150.Get(), Message_Info);
430   
431   TCollection_AsciiString tmp110 (EPMSG110.Original()), tmp150  (EPMSG150.Original());
432   EPMSG110.Set (tmp110.ToCString());
433   EPMSG150.Set (tmp150.ToCString());
434
435   Message_Msg TPMSG55 ("PrResult.Print.MSG55"); //  Faces:
436   Messenger()->Send (TPMSG55, Message_Info);
437   Message_Msg EPMSG115 ("PrResult.Print.MSG115"); //    Result is Face                  : %d
438   EPMSG115.Arg (FF);
439   Messenger()->Send (EPMSG115, Message_Info);
440   EPMSG110.Arg (FS);
441   Messenger()->Send (EPMSG110, Message_Info);
442   EPMSG150.Arg (FN);
443   Messenger()->Send (EPMSG150, Message_Info);
444   
445   // preparation ratio
446   Standard_Real SPR = 1, FPR = 1;
447   Standard_Integer STotalR = SS, FTotalR  = FF + FS;
448   Standard_Integer NbS = STotalR + SN, NbF = FTotalR + FN;
449   if (NbS > 0) SPR = 1. * (NbS - SN) / NbS;
450   if (NbF > 0) FPR = 1. * (NbF - FN) / NbF;
451   Message_Msg PMSG200 ("PrResult.Print.MSG200"); //Preparation ratio:
452   Messenger()->Send (PMSG200, Message_Info);
453   Message_Msg PMSG205 ("PrResult.Print.MSG205"); //  Shells: %d per cent
454   PMSG205.Arg ((Standard_Integer) (100. * SPR));
455   Messenger()->Send (PMSG205, Message_Info);
456   Message_Msg PMSG210 ("PrResult.Print.MSG210"); //  Faces : %d per cent
457   PMSG210.Arg ((Standard_Integer) (100. * FPR));
458   Messenger()->Send (PMSG210, Message_Info);
459 }