0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / ShapeProcess / ShapeProcess_ShapeContext.cxx
CommitLineData
b311480e 1// Created on: 2000-08-22
2// Created by: Andrey BETENEV
973c2be1 3// Copyright (c) 2000-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
7fd59977 16
7fd59977 17#include <BRep_Builder.hxx>
42cf5bc1 18#include <BRepTools_Modifier.hxx>
7fd59977 19#include <Message_ListIteratorOfListOfMsg.hxx>
42cf5bc1 20#include <Message_ListOfMsg.hxx>
21#include <Message_Messenger.hxx>
22#include <Message_Msg.hxx>
23#include <ShapeBuild_ReShape.hxx>
7fd59977 24#include <ShapeExtend_DataMapOfShapeListOfMsg.hxx>
42cf5bc1 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>
7fd59977 32
92efcf78 33IMPLEMENT_STANDARD_RTTIEXT(ShapeProcess_ShapeContext,ShapeProcess_Context)
34
7fd59977 35//=======================================================================
36//function : ShapeProcess_ShapeContext
37//purpose :
38//=======================================================================
7fd59977 39ShapeProcess_ShapeContext::ShapeProcess_ShapeContext (const Standard_CString file,
40 const Standard_CString seq)
2bc6f715 41 : ShapeProcess_Context ( file, seq ), myUntil(TopAbs_FACE),
42 myNonManifold(Standard_False)
7fd59977 43{
44}
45
46//=======================================================================
47//function : ShapeProcess_ShapeContext
48//purpose :
49//=======================================================================
50
51ShapeProcess_ShapeContext::ShapeProcess_ShapeContext (const TopoDS_Shape &S,
52 const Standard_CString file,
53 const Standard_CString seq)
2bc6f715 54 : ShapeProcess_Context ( file, seq ), myUntil(TopAbs_FACE),
55 myNonManifold(Standard_False)
7fd59977 56{
57 Init ( S );
58}
59
60//=======================================================================
61//function : Init
62//purpose :
63//=======================================================================
64
65void 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
78const TopoDS_Shape &ShapeProcess_ShapeContext::Shape () const
79{
80 return myShape;
81}
82
83//=======================================================================
84//function : Result
85//purpose :
86//=======================================================================
87
88const TopoDS_Shape &ShapeProcess_ShapeContext::Result () const
89{
90 return myResult;
91}
92
93//=======================================================================
94//function : Map
95//purpose :
96//=======================================================================
97
98const TopTools_DataMapOfShapeShape &ShapeProcess_ShapeContext::Map () const
99{
100 return myMap;
101}
102
103//=======================================================================
104//function : Messages
105//purpose :
106//=======================================================================
107
108Handle(ShapeExtend_MsgRegistrator) &ShapeProcess_ShapeContext::Messages ()
109{
110 return myMsg;
111}
112
113//=======================================================================
114//function : Messages
115//purpose :
116//=======================================================================
117
118const Handle(ShapeExtend_MsgRegistrator) &ShapeProcess_ShapeContext::Messages () const
119{
120 return myMsg;
121}
122
123//=======================================================================
124//function : SetDetalisation
125//purpose :
126//=======================================================================
127
128void ShapeProcess_ShapeContext::SetDetalisation (const TopAbs_ShapeEnum level)
129{
130 myUntil = level;
131}
132
133//=======================================================================
134//function : GetDetalisation
135//purpose :
136//=======================================================================
137
138TopAbs_ShapeEnum ShapeProcess_ShapeContext::GetDetalisation () const
139{
140 return myUntil;
141}
142
143//=======================================================================
144//function : SetResult
145//purpose :
146//=======================================================================
147
148void 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/*
0797d9d3 160#ifdef OCCT_DEBUG
7fd59977 161static void DumpMap (const TopTools_DataMapOfShapeShape &map)
162{
163 cout << "----" << endl;
164 cout << "Map:" << endl;
165 for (TopTools_DataMapIteratorOfDataMapOfShapeShape It (map); It.More(); It.Next()) {
166 TopoDS_Shape S0 = It.Key(), S = It.Value();
167 cout << S0.TShape()->DynamicType()->Name() << "\t" << *(void**)&S0.TShape() <<
168 " \t-> " << S.TShape()->DynamicType()->Name() << "\t" << *(void**)&S.TShape() << endl;
169 }
170 cout << "----" << endl;
171}
172#endif
173*/
174
175static void RecModif (const TopoDS_Shape &S,
176 const TopTools_DataMapOfShapeShape &repl,
da2db6a7 177 const Handle(ShapeExtend_MsgRegistrator) &msg,
7fd59977 178 TopTools_DataMapOfShapeShape &map,
da2db6a7 179 Handle(ShapeExtend_MsgRegistrator) &myMsg,
7fd59977 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 }
ab860031 219 if ( modif )
220 {
da72a17c 221 if (result.ShapeType() == TopAbs_WIRE || result.ShapeType() == TopAbs_SHELL)
222 result.Closed (BRep_Tool::IsClosed (result));
ab860031 223 res = result;
224 }
7fd59977 225 }
226
227 if ( res != r ) map.Bind ( S.Located(aNullLoc), res );
228 }
229
da2db6a7 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
7fd59977 247 if ( until == TopAbs_SHAPE || S.ShapeType() >= until ) return;
248
249 for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
da2db6a7 250 RecModif ( it.Value(), repl, msg, map, myMsg, until );
7fd59977 251 }
252}
253
da2db6a7 254void ShapeProcess_ShapeContext::RecordModification (const TopTools_DataMapOfShapeShape &repl,
255 const Handle(ShapeExtend_MsgRegistrator)& msg)
7fd59977 256{
257 if ( repl.Extent() <=0 ) return;
da2db6a7 258 RecModif ( myShape, repl, msg, myMap, myMsg, myUntil );
7fd59977 259 if ( myMap.IsBound(myShape) ) myResult = myMap.Find ( myShape );
0797d9d3 260#ifdef OCCT_DEBUG
7fd59977 261// cout << "Modifier: " << endl; DumpMap (myMap);
262#endif
263}
264
265//=======================================================================
266//function : RecordModification
267//purpose :
268//=======================================================================
269
270static 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();
da2db6a7 304 if ( msgmap.IsBound( S ))
305 next = S;
7fd59977 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
da2db6a7 320 for ( TopoDS_Iterator it(S,Standard_False/*,Standard_False*/); it.More(); it.Next() ) {
7fd59977 321 RecModif ( it.Value(), repl, msg, map, myMsg, until );
322 }
323}
324
325void 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 }
0797d9d3 335#ifdef OCCT_DEBUG
7fd59977 336// cout << "ReShape: " << endl; DumpMap (myMap);
337#endif
338}
339
340//=======================================================================
341//function : RecordModification
342//purpose :
343//=======================================================================
344
345void 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
356void 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
368static 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
385void ShapeProcess_ShapeContext::RecordModification (const TopoDS_Shape &S,
da2db6a7 386 const BRepTools_Modifier &repl,
387 const Handle(ShapeExtend_MsgRegistrator)& msg)
7fd59977 388{
389 TopTools_DataMapOfShapeShape map;
390 ExplodeModifier ( S, repl, map, myUntil );
da2db6a7 391 RecordModification ( map, msg );
7fd59977 392}
393
394//=======================================================================
395//function : GetContinuity
396//purpose :
397//=======================================================================
398
399Standard_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
425GeomAbs_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
437void 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)
eafb234b 446 {
7fd59977 447 if (valueshape.IsNull()) FN++;
448 else if (valueshape.ShapeType() == TopAbs_SHELL) FS++;
449 else FF++;
eafb234b 450 }
7fd59977 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}