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