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