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