0025418: Debug output to be limited to OCC development environment
[occt.git] / src / XSAlgo / XSAlgo_AlgoContainer.cxx
1 // Created on: 2000-01-19
2 // Created by: data exchange team
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 <XSAlgo_AlgoContainer.ixx>
17
18 #include <Standard_ErrorHandler.hxx>
19 #include <Standard_Failure.hxx>
20
21 #include <Message_ListOfMsg.hxx>
22 #include <Message_ListIteratorOfListOfMsg.hxx>
23
24 #include <gp_Pnt.hxx>
25 #include <gp_Pnt2d.hxx>
26 #include <Geom_Curve.hxx>
27 #include <Geom_Surface.hxx>
28 #include <Geom2d_Curve.hxx>
29 #include <TopoDS.hxx>
30 #include <TopoDS_Vertex.hxx>
31 #include <TopoDS_Iterator.hxx>
32 #include <TopExp.hxx>
33 #include <BRep_Tool.hxx>
34 #include <BRep_Builder.hxx>
35 #include <BRepBuilderAPI_MakeEdge.hxx>
36 #include <TopTools_DataMapOfShapeShape.hxx>
37 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
38
39 #include <ShapeProcess.hxx>
40 #include <ShapeProcess_ShapeContext.hxx>
41 #include <ShapeAlgo.hxx>
42 #include <ShapeAlgo_AlgoContainer.hxx>
43 #include <ShapeAlgo_ToolContainer.hxx>
44 #include <ShapeBuild_ReShape.hxx>
45 #include <ShapeExtend_DataMapOfShapeListOfMsg.hxx>
46 #include <ShapeExtend_MsgRegistrator.hxx>
47 #include <ShapeFix_Shape.hxx>
48 #include <ShapeBuild_Edge.hxx>
49 #include <ShapeAnalysis_Edge.hxx>
50 #include <ShapeFix_Edge.hxx>
51 #include <UnitsMethods.hxx>
52 #include <ShapeCustom.hxx>
53
54 #include <TransferBRep.hxx>
55 #include <TransferBRep_ShapeMapper.hxx>
56 #include <TransferBRep_ShapeBinder.hxx>
57 #include <Transfer_TransientListBinder.hxx>
58 #include <Resource_Manager.hxx>
59 #include <Interface_Static.hxx>
60 #include <Message_Msg.hxx>
61
62 //=======================================================================
63 //function : XSAlgo_AlgoContainer
64 //purpose  : 
65 //=======================================================================
66
67 XSAlgo_AlgoContainer::XSAlgo_AlgoContainer()
68 {
69   myTC = new XSAlgo_ToolContainer;
70 }
71
72 //=======================================================================
73 //function : PrepareForTransfer
74 //purpose  : 
75 //=======================================================================
76
77 void XSAlgo_AlgoContainer::PrepareForTransfer() const
78 {
79   UnitsMethods::SetCasCadeLengthUnit ( Interface_Static::IVal("xstep.cascade.unit") );
80 }
81
82 //=======================================================================
83 //function : ProcessShape
84 //purpose  : 
85 //=======================================================================
86
87 TopoDS_Shape XSAlgo_AlgoContainer::ProcessShape (const TopoDS_Shape& shape,
88                                                  const Standard_Real Prec,
89                                                  const Standard_Real maxTol,
90                                                  const Standard_CString prscfile,
91                                                  const Standard_CString pseq,
92                                                  Handle(Standard_Transient)& info,
93                                                  const Handle(Message_ProgressIndicator)& progress) const
94 {
95   if ( shape.IsNull() ) return shape;
96   
97   Handle(ShapeProcess_ShapeContext) context = Handle(ShapeProcess_ShapeContext)::DownCast(info);
98   if ( context.IsNull() )
99   {
100     Standard_CString rscfile = Interface_Static::CVal(prscfile);
101     if (!rscfile)
102       rscfile = prscfile;
103     context = new ShapeProcess_ShapeContext(shape, rscfile);
104     context->SetDetalisation(TopAbs_EDGE);
105     if ( !progress.IsNull() )
106       context->SetProgress(progress);
107   }
108   info = context;
109   
110   Standard_CString seq = Interface_Static::CVal ( pseq );
111   if ( ! seq ) seq = pseq;
112   
113   // if resource file is not loaded or does not define <seq>.exec.op, 
114   // do default fixes
115   Handle(Resource_Manager) rsc = context->ResourceManager();
116   TCollection_AsciiString str ( seq );
117   str += ".exec.op";
118   if ( ! rsc->Find ( str.ToCString() ) ) {
119 #ifdef OCCT_DEBUG
120     {
121       static Standard_Integer time = 0;
122       if ( ! time )
123         cout << "Warning: XSAlgo_AlgoContainer::ProcessShape(): Sequence " << str.ToCString() << 
124                 " is not defined in " << prscfile << " resource; do default processing" << endl;
125       time++;
126     }
127 #endif
128     // if FromSTEP or FromIGES, do default ShapeFix
129     if ( ! strncmp ( pseq, "read.", 5 ) ) {
130       try {
131         OCC_CATCH_SIGNALS
132         Handle(ShapeExtend_MsgRegistrator) msg = new ShapeExtend_MsgRegistrator;
133         Handle(ShapeFix_Shape) sfs = ShapeAlgo::AlgoContainer()->ToolContainer()->FixShape();
134         sfs->Init ( shape );
135         sfs->SetMsgRegistrator ( msg );
136         sfs->SetPrecision ( Prec );
137         sfs->SetMaxTolerance ( maxTol );
138         sfs->FixFaceTool()->FixWireTool()->FixSameParameterMode() = Standard_False;
139         sfs->FixSolidTool()->CreateOpenSolidMode() = Standard_False;
140         sfs->Perform(progress);
141
142         TopoDS_Shape S = sfs->Shape();
143         if ( ! S.IsNull() && S != shape ) {
144           context->RecordModification ( sfs->Context(), msg );
145           context->SetResult ( S );
146         }
147       }
148       catch (Standard_Failure) {
149 #ifdef OCCT_DEBUG
150         cout << "Error: XSAlgo_AlgoContainer::ProcessShape(): Exception in ShapeFix::Shape" << endl;
151         Standard_Failure::Caught()->Print(cout); cout << endl;
152 #endif
153       }  
154       return context->Result();
155     }
156     // if ToSTEP or ToIGES, define sequence of DirectFaces
157     else if ( ! strcmp ( pseq, "write.step.sequence" ) ) {
158       rsc->SetResource ( str.ToCString(), "DirectFaces" );
159     }
160     else if ( ! strcmp ( pseq, "write.iges.sequence" ) ) {
161       rsc->SetResource ( str.ToCString(), "DirectFaces" );
162     }
163   }
164   
165   // Define runtime tolerances and do Shape Processing 
166   rsc->SetResource ( "Runtime.Tolerance", Prec );
167   rsc->SetResource ( "Runtime.MaxTolerance", maxTol );
168
169   if ( !ShapeProcess::Perform(context, seq) )
170     return TopoDS_Shape(); // Null shape
171
172   return context->Result();
173 }
174                                                   
175 //=======================================================================
176 //function : PerformFixShape
177 //purpose  : 
178 //=======================================================================
179
180 /*
181 TopoDS_Shape XSAlgo_AlgoContainer::PerformFixShape(const TopoDS_Shape& S,
182                                                       const Handle(Transfer_TransientProcess)& TP,
183                                                       const Standard_Real Prec,
184                                                       const Standard_Real MaxTol) const
185 {
186   if ( S.IsNull() ) return S;
187   
188   TopoDS_Shape shape = S;
189   // fixing shape
190   try {
191     OCC_CATCH_SIGNALS
192     Handle(ShapeFix_Shape) sfs = ShapeAlgo::AlgoContainer()->ToolContainer()->FixShape();
193     sfs->Init ( S );
194     sfs->SetMsgRegistrator ( new ShapeExtend_MsgRegistrator );
195     sfs->SetPrecision ( Prec );
196     sfs->SetMaxTolerance ( MaxTol );
197     sfs->FixFaceTool()->FixWireTool()->FixSameParameterMode() = Standard_False;
198     sfs->Perform();
199
200     shape = sfs->Shape();
201     
202     // to be removed when messages come
203     if ( shape == S || shape.IsNull() ) return S;
204     
205     // update map to reflect the substitutions
206     Handle(ShapeBuild_ReShape) context = sfs->Context();
207     const ShapeExtend_DataMapOfShapeListOfMsg& msgmap = 
208       Handle(ShapeExtend_MsgRegistrator)::DownCast (sfs->MsgRegistrator())->MapShape();
209     for ( Standard_Integer i=1; i <= TP->NbMapped(); i++ ) {
210       Handle(Transfer_Binder) bnd = TP->MapItem ( i );
211       Handle(TransferBRep_ShapeBinder) sb = Handle(TransferBRep_ShapeBinder)::DownCast ( bnd );
212       if ( sb.IsNull() || sb->Result().IsNull() ) continue;
213       
214       TopoDS_Shape orig = sb->Result();
215       
216       // update messages (messages must be taken from each level in the substitution map)
217       TopoDS_Shape cur, next = orig;
218       do {
219         cur = next;
220         Message_ListOfMsg msglist;
221         if (msgmap.IsBound (cur)) {
222           msglist = msgmap.Find (cur);
223           for (Message_ListIteratorOfListOfMsg iter (msglist); iter.More(); iter.Next()) {
224             const Message_Msg& msg = iter.Value();
225             sb->AddWarning (msg.Value(), msg.Original());
226           }
227         }
228         next = context->Value (cur);
229       } while (cur != next);
230
231       // update shapes
232       TopoDS_Shape res;
233       if ( ! context->Status ( orig, res, Standard_True ) ) continue;
234
235       sb->SetResult ( res );
236     }
237   }
238   catch (Standard_Failure) {
239 #ifdef OCCT_DEBUG
240     cout << "Error: XSAlgo_AlgoContainer::PerformFixShape(): Exception in ShapeFix::Shape" << endl;
241 #endif
242   }   
243   return shape;
244 }
245 */
246
247 // ============================================================================
248 // Method  : MakeEdgeOnCurve
249 // Purpose : for CheckPCurve
250 // ============================================================================
251
252 static TopoDS_Edge MakeEdgeOnCurve(const TopoDS_Edge edge)
253 {
254   TopoDS_Edge result;
255   //BRep_Builder B; // B not used - see below (skl)
256   Handle(Geom_Curve) C3d;
257   ShapeAnalysis_Edge sae;
258   Standard_Real cf, cl;
259   if (!sae.Curve3d (edge, C3d, cf, cl, Standard_False )) 
260     return result;
261   gp_Pnt PV1 = C3d->Value(cf);
262   gp_Pnt PV2 = C3d->Value(cl);
263   BRepBuilderAPI_MakeEdge mkEdge(C3d, PV1, PV2, cf, cl);
264 //:S4136  Standard_Real tol = BRep_Tool::Tolerance (edge);
265   ShapeBuild_Edge SBE;          //skl 10.07.2001
266   SBE.SetRange3d(mkEdge,cf,cl); //skl 10.07.2001
267   result = mkEdge.Edge();
268 //:S4136  B.UpdateEdge(result,tol);
269   return result;
270 }
271
272 //=======================================================================
273 //function : CheckPCurve
274 //purpose  : 
275 //=======================================================================
276
277 Standard_Boolean XSAlgo_AlgoContainer::CheckPCurve (const TopoDS_Edge& E,
278                                                     const TopoDS_Face& face,
279                                                     const Standard_Real preci,
280                                                     const Standard_Boolean isSeam) const
281 {
282   Standard_Real w1, w2;  
283   Handle(Geom2d_Curve) thePC;
284   ShapeAnalysis_Edge sae;
285   if ( ! sae.PCurve (E, face, thePC, w1, w2, Standard_False ) ) {
286     return Standard_False;
287   }
288
289   // Check for pcurve longer than surface
290   Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
291   Standard_Real UF,UL,VF,VL;
292   surf->Bounds (UF,UL,VF,VL);
293   gp_Pnt2d PUV1, PUV2;
294   PUV1 = thePC->Value(w1);
295   PUV2 = thePC->Value(w2);
296   //    Multi-periodique ? mieux vaut jeter (attention aux valeurs infinies)
297   Standard_Real DU = Abs (PUV1.X() - PUV2.X());
298   Standard_Real DV = Abs (PUV1.Y() - PUV2.Y());
299   if ( DU/8. > (UL/6. - UF/6.) || DV/8. > (VL/6. - VF/6.) ) {
300     ShapeBuild_Edge().RemovePCurve(E,face);
301 #ifdef OCCT_DEBUG
302     cout<<"Removing pcuve periodic"<<endl;
303 #endif      
304     return Standard_False;
305   }
306
307   // Second Check : 2D and 3D consistency (if the Pcurve has not been 
308   //                dropped)
309   //  On verifie aussi qu on ne s enroule pas trop ...
310   //  ex. : UVV en DEGRES sur une surface en RADIANS, recalee = 57 tours !
311
312   Handle(Geom_Curve) C3d;
313   Standard_Real cf1, cl1;
314   sae.Curve3d (E, C3d, cf1, cl1, Standard_False );
315
316   gp_Pnt P1 = surf->Value(PUV1.X(), PUV1.Y());
317   gp_Pnt P2 = surf->Value(PUV2.X(), PUV2.Y());
318   TopoDS_Vertex V1 = TopExp::FirstVertex(E);
319   TopoDS_Vertex V2 = TopExp::LastVertex(E);
320   gp_Pnt PV1 = ( C3d.IsNull() ? BRep_Tool::Pnt(V1) : C3d->Value(cf1) );
321   gp_Pnt PV2 = ( C3d.IsNull() ? BRep_Tool::Pnt(V2) : C3d->Value(cl1) );
322   Standard_Real Dist11 = PV1.Distance(P1), Dist22 = PV2.Distance(P2);
323     
324   if (!((Dist11 <= preci) && (Dist22 <= preci))) {
325     ShapeBuild_Edge().RemovePCurve(E,face);
326 #ifdef OCCT_DEBUG
327     cout<<"Removing pcurve points"<<endl;
328 #endif      
329     return Standard_False;
330   }
331
332   //
333   // pdn checking deviation between pcurve and 3D curve
334   //
335   
336   // Make temporary edge for analysis
337   if ( C3d.IsNull() ) return Standard_False;
338   TopoDS_Edge edge = MakeEdgeOnCurve(E);
339   
340   // fill it with pcurve(s)
341   BRep_Builder B;
342   Handle(Geom2d_Curve) seamPC;
343   if ( isSeam ) {
344     Standard_Real f, l;
345     TopoDS_Shape REdge = E.Reversed() ;
346     if ( ! sae.PCurve ( TopoDS::Edge ( REdge ), 
347                         face, seamPC, f, l, Standard_False ) ||
348          seamPC == thePC ) 
349       seamPC = Handle(Geom2d_Curve)::DownCast ( thePC->Copy() );
350     B.UpdateEdge ( edge, thePC, seamPC, face, 0.);
351   }
352   else B.UpdateEdge ( edge, thePC, face, 0.);
353   B.Range(edge,face,w1,w2);
354   B.SameRange(edge, Standard_False );
355   //:S4136
356   Standard_Integer SPmode = Interface_Static::IVal("read.stdsameparameter.mode");
357   if ( SPmode ) 
358     B.SameParameter (edge, Standard_False );
359
360   // call FixSP to see what it will do
361   Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
362   sfe->FixSameParameter(edge);
363   Standard_Real tol = BRep_Tool::Tolerance (edge);
364   //    Standard_Real tolV1 = BRep_Tool::Tolerance(TopExp::FirstVertex(edge));
365   //    Standard_Real tolV2 = BRep_Tool::Tolerance(TopExp::LastVertex(edge));                          
366   Standard_Boolean sr = BRep_Tool::SameRange ( edge );
367   Standard_Boolean sp = BRep_Tool::SameParameter ( edge );
368   
369   // if result is not nice, try to call projection and take the best
370   if ( tol > Min ( 1., 2.*preci ) || ! sr ) {
371     //pdn trying to recompute pcurve 
372     TopoDS_Edge edgePr = MakeEdgeOnCurve(E);
373     sfe->FixAddPCurve(edgePr, face, isSeam, preci);
374     sfe->FixSameParameter(edgePr);
375     Standard_Real tolPr = BRep_Tool::Tolerance (edgePr);
376     //pdn choose the best pcurve
377     if ( tolPr < tol || ! sr ) {
378       //        tolV1 = BRep_Tool::Tolerance(TopExp::FirstVertex(edgePr));
379       //        tolV2 = BRep_Tool::Tolerance(TopExp::LastVertex(edgePr));
380       sr = BRep_Tool::SameRange ( edgePr );
381       sp = BRep_Tool::SameParameter ( edgePr );
382       tol = tolPr;
383       edge = edgePr;
384     }
385   }
386   
387   // get corrected pcurve from the temporary edge, and put to original
388   sae.PCurve ( edge, face, thePC, w1, w2, Standard_False );
389   if ( isSeam ) {
390     Standard_Real f, l;
391     TopoDS_Shape REdge = edge.Reversed();
392     sae.PCurve ( TopoDS::Edge ( REdge ), face, seamPC, f, l, Standard_False );
393     if ( E.Orientation() == TopAbs_REVERSED ) //:abv 14.11.01: coneEl.sat loop
394       B.UpdateEdge ( E, seamPC, thePC, face, tol );
395     else 
396       B.UpdateEdge ( E, thePC, seamPC, face, tol );
397   }
398   else B.UpdateEdge ( E, thePC, face, tol );
399
400   B.UpdateVertex(V1,tol);
401   B.UpdateVertex(V2,tol);
402   B.Range(E,face, w1, w2);
403   if(BRep_Tool::SameRange(E))
404     B.SameRange( E, sr );
405   if(BRep_Tool::SameParameter(E))
406     B.SameParameter ( E, sp );
407   
408   return Standard_True;
409 }
410
411 //=======================================================================
412 //function : MergeTransferInfo
413 //purpose  : 
414 //=======================================================================
415
416 void XSAlgo_AlgoContainer::MergeTransferInfo(const Handle(Transfer_TransientProcess)& TP,
417                                                 const Handle(Standard_Transient) &info,
418                                                 const Standard_Integer startTPitem) const
419 {
420   Handle(ShapeProcess_ShapeContext) context = Handle(ShapeProcess_ShapeContext)::DownCast ( info );
421   if ( context.IsNull() ) return;
422
423   const TopTools_DataMapOfShapeShape &map = context->Map();
424   Handle(ShapeExtend_MsgRegistrator) msg = context->Messages();
425   if ( map.Extent() <=0 && ( msg.IsNull() || msg->MapShape().Extent() <=0 ) )
426     return;
427
428   Standard_Integer i = ( startTPitem >0 ? startTPitem : 1 );
429   for ( ; i <= TP->NbMapped(); i++ ) {
430     Handle(Transfer_Binder) bnd = TP->MapItem ( i );
431     Handle(TransferBRep_ShapeBinder) sb = Handle(TransferBRep_ShapeBinder)::DownCast ( bnd );
432     if ( sb.IsNull() || sb->Result().IsNull() ) continue;
433       
434     TopoDS_Shape orig = sb->Result();
435     if ( map.IsBound ( orig ) ) sb->SetResult ( map.Find ( orig ) );
436     else if ( !orig.Location().IsIdentity() )
437     {
438       TopLoc_Location aNullLoc;
439       TopoDS_Shape atmpSh = orig.Located(aNullLoc);
440       if ( map.IsBound ( atmpSh ) ) sb->SetResult ( map.Find ( atmpSh ) );
441     }
442       
443     // update messages
444     if ( ! msg.IsNull() ) {
445       const ShapeExtend_DataMapOfShapeListOfMsg& msgmap = msg->MapShape();
446       if ( msgmap.IsBound (orig) ) {
447         const Message_ListOfMsg &msglist = msgmap.Find (orig);
448         for (Message_ListIteratorOfListOfMsg iter (msglist); iter.More(); iter.Next()) {
449           const Message_Msg& mess = iter.Value();
450           sb->AddWarning (TCollection_AsciiString(mess.Value()).ToCString(),
451                           TCollection_AsciiString(mess.Original()).ToCString());
452         }
453       }
454     }
455   }
456 }
457
458 //=======================================================================
459 //function : MergeTransferInfo
460 //purpose  : 
461 //=======================================================================
462
463 void XSAlgo_AlgoContainer::MergeTransferInfo(const Handle(Transfer_FinderProcess)& FP,
464                                                 const Handle(Standard_Transient) &info) const
465 {
466   Handle(ShapeProcess_ShapeContext) context = Handle(ShapeProcess_ShapeContext)::DownCast ( info );
467   if ( context.IsNull() ) return;
468
469   const TopTools_DataMapOfShapeShape &map = context->Map();
470   TopTools_DataMapIteratorOfDataMapOfShapeShape ShapeShapeIterator(map);
471   Handle(ShapeExtend_MsgRegistrator) msg = context->Messages();
472
473   for ( ; ShapeShapeIterator.More(); ShapeShapeIterator.Next() ) {
474
475     TopoDS_Shape orig = ShapeShapeIterator.Key(), res = ShapeShapeIterator.Value();
476     Handle(TransferBRep_ShapeMapper) resMapper = TransferBRep::ShapeMapper ( FP, res );
477     Handle(Transfer_Binder) resBinder = FP->Find ( resMapper );
478     
479     if (resBinder.IsNull()) {
480       resBinder = new TransferBRep_ShapeBinder(res);
481       //if <orig> shape was splitted, put entities corresponding to new shapes
482       // into Transfer_TransientListBinder.
483       if ( orig.ShapeType() > res.ShapeType() ) {
484         TopoDS_Shape sub;
485         Handle(Transfer_TransientListBinder) TransientListBinder = new Transfer_TransientListBinder;
486         for (TopoDS_Iterator it(res); it.More(); it.Next()) {
487           Handle(Transfer_Finder) subMapper = TransferBRep::ShapeMapper ( FP, it.Value());
488           if (subMapper.IsNull()) continue;
489
490           Handle(Standard_Transient) tr = FP->FindTransient ( subMapper );
491           if (tr.IsNull()) continue;
492           TransientListBinder->AddResult(tr);
493           sub = it.Value();
494         }
495         if ( TransientListBinder->NbTransients() == 1 ) resBinder = new TransferBRep_ShapeBinder(sub);
496         else if ( TransientListBinder->NbTransients() > 1 ) {
497           resBinder->AddResult(TransientListBinder);
498 //        resBinder->SetNext(TransientListBinder, Standard_True);
499 #ifdef OCCT_DEBUG
500           cout<<"Info: TransientListBinder created for splitted shape"<<endl;
501         } 
502         else {
503           cout<<"Warning: XSAlgo_AlgoContainer::MergeTransferInfo() "
504             <<"No results were found for splitted shape. "<<endl;
505           //<<"Transfer_FinderProcess->NbMapped() = "<<FP->NbMapped()<<endl;
506 #endif    
507         }
508       }
509     }
510     
511     Handle(TransferBRep_ShapeMapper) origMapper= TransferBRep::ShapeMapper ( FP, orig);
512     Handle(Transfer_Binder) origBinder = FP->Find ( origMapper );
513     if ( origBinder.IsNull() ) {
514       FP->Bind(origMapper, resBinder);
515     }
516     else {
517       origBinder->AddResult ( resBinder );
518     }
519     
520     // update messages
521     if ( ! msg.IsNull() ) {
522       const ShapeExtend_DataMapOfShapeListOfMsg& msgmap = msg->MapShape();
523       if ( msgmap.IsBound (orig) ) {
524         const Message_ListOfMsg &msglist = msgmap.Find (orig);
525         for (Message_ListIteratorOfListOfMsg iter (msglist); iter.More(); iter.Next()) {
526           const Message_Msg& mess = iter.Value();
527           resBinder->AddWarning (TCollection_AsciiString(mess.Value()).ToCString(),
528                                  TCollection_AsciiString(mess.Original()).ToCString());
529         }
530       }
531     }
532   }
533 }