0025748: Parallel version of progress indicator
[occt.git] / src / IGESToBRep / IGESToBRep_Reader.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 //pdn 11.01.99 including <stdio.h> for compilation on NT
15 //#70 rln 03.03.99 syntax correction
16 // sln 11.06.2002 OCC448 : Initialize "read.onlyvisiable" parameter  to control transfering invisiable sub entities which logicaly depend on the grouping entities
17
18 #include <BRep_Builder.hxx>
19 #include <BRepLib.hxx>
20 #include <BRepTools_Modifier.hxx>
21 #include <gp_Trsf.hxx>
22 #include <IGESAppli.hxx>
23 #include <IGESAppli_Protocol.hxx>
24 #include <IGESData_FileProtocol.hxx>
25 #include <IGESData_GlobalSection.hxx>
26 #include <IGESData_IGESEntity.hxx>
27 #include <IGESData_IGESModel.hxx>
28 #include <IGESFile_Read.hxx>
29 #include <IGESSolid.hxx>
30 #include <IGESSolid_Protocol.hxx>
31 #include <IGESToBRep.hxx>
32 #include <IGESToBRep_Actor.hxx>
33 #include <IGESToBRep_CurveAndSurface.hxx>
34 #include <IGESToBRep_Reader.hxx>
35 #include <Interface_Check.hxx>
36 #include <Interface_CheckIterator.hxx>
37 #include <Interface_CheckTool.hxx>
38 #include <Interface_Macros.hxx>
39 #include <Interface_ShareFlags.hxx>
40 #include <Interface_Static.hxx>
41 #include <Message_Messenger.hxx>
42 #include <Message_Msg.hxx>
43 #include <Message_ProgressScope.hxx>
44 #include <OSD_Timer.hxx>
45 #include <ShapeAlgo.hxx>
46 #include <ShapeAlgo_AlgoContainer.hxx>
47 #include <ShapeExtend_Explorer.hxx>
48 #include <ShapeFix_ShapeTolerance.hxx>
49 #include <Standard_ErrorHandler.hxx>
50 #include <Standard_Failure.hxx>
51 #include <TopAbs.hxx>
52 #include <TopoDS_Compound.hxx>
53 #include <TopoDS_Shape.hxx>
54 #include <Transfer_IteratorOfProcessForTransient.hxx>
55 #include <Transfer_TransferOutput.hxx>
56 #include <Transfer_TransientProcess.hxx>
57 #include <TransferBRep.hxx>
58 #include <TransferBRep_ShapeBinder.hxx>
59 #include <TransferBRep_ShapeListBinder.hxx>
60 #include <XSAlgo.hxx>
61 #include <XSAlgo_AlgoContainer.hxx>
62
63 #include <stdio.h>
64 //#include <ShapeCustom.hxx>
65 #ifdef _MSC_VER
66 #include <stdlib.h>
67 #else
68 #include <errno.h>
69 #endif
70 //extern int errno;
71
72 static Handle(IGESData_FileProtocol) protocol;
73
74
75 //=======================================================================
76 //function : IGESToBRep_Reader
77 //purpose  : 
78 //=======================================================================
79     IGESToBRep_Reader::IGESToBRep_Reader ()
80 {
81   theDone = Standard_False;
82   if (protocol.IsNull()) {
83     IGESAppli::Init();  IGESSolid::Init();
84     protocol = new IGESData_FileProtocol;
85     protocol->Add(IGESAppli::Protocol());
86     protocol->Add(IGESSolid::Protocol());
87   }
88   theActor = new IGESToBRep_Actor;
89   theProc = new Transfer_TransientProcess;
90 }
91
92
93 //=======================================================================
94 //function : LoadFile
95 //purpose  : loads a Model from a file
96 //=======================================================================
97
98 Standard_Integer IGESToBRep_Reader::LoadFile (const Standard_CString filename)
99
100   if ( theProc.IsNull() )
101     theProc = new Transfer_TransientProcess;
102   Handle(Message_Messenger) TF = theProc->Messenger();
103   
104   // Message for Diagnostic file.
105   Message_Msg msg2000("IGES_2000");   
106   msg2000.Arg(filename);
107   TF->Send (msg2000, Message_Info);
108   //Message_Msg msg2001("IGES_2001");   // Date
109   Message_Msg msg2005("IGES_2005");
110   msg2005.Arg(theProc->TraceLevel());
111   TF->Send (msg2005, Message_Info);
112   /////////////////////////////////////////////////////////
113   Handle(IGESData_IGESModel) model = new IGESData_IGESModel;
114
115   OSD_Timer c; c.Reset(); c.Start();    
116   char *pfilename=(char *)filename;
117   Standard_Integer StatusFile = IGESFile_Read(pfilename,model,protocol);
118   if (StatusFile != 0) {
119     // Sending of message : IGES file opening error 
120     Message_Msg Msg2("XSTEP_2");
121     TF->Send (Msg2, Message_Info);
122     //Message_Msg Msg3("XSTEP_3");
123     //Message_Msg Msg4("XSTEP_4");
124     //Message_Msg Msg5("XSTEP_5");
125     //Message_Msg Msg6("XSTEP_6");
126     //Message_Msg Msg7("XSTEP_7");
127     // Reasons of the file opening error
128     switch(errno)
129       {
130       case 2  : // Sending of message : No such file or directory
131         {
132           Message_Msg Msg3("XSTEP_3");
133           TF->Send (Msg3, Message_Info);
134         }
135         break;
136       case 12 : // Sending of message : Not enough space
137         {
138           Message_Msg Msg4("XSTEP_4");
139           TF->Send (Msg4, Message_Info);
140         }
141         break;
142       case 13 : // Sending of message : Permission Denied
143         {
144           Message_Msg Msg5("XSTEP_5");
145           TF->Send (Msg5, Message_Info);
146         }
147         break;
148       case 24 : // Sending of message : Too many open files
149         {
150           Message_Msg Msg6("XSTEP_6");
151           TF->Send (Msg6, Message_Info);
152         }
153         break;
154       default : // Sending of message : No determined
155         {
156           Message_Msg Msg7("XSTEP_7");
157           TF->Send (Msg7, Message_Info);
158         }
159         break;
160       }
161   }  
162   
163   Message_Msg Msg8  ("XSTEP_8");
164   Message_Msg Msg25 ("XSTEP_25");
165   Message_Msg Msg26 ("XSTEP_26");
166    // Nb warning in global section.
167
168   Standard_Integer nbWarn = 0,nbFail = 0;
169   // Add the number of warning on enities :
170   Interface_CheckTool cht (model,protocol);
171   Interface_CheckIterator anIter = cht.CompleteCheckList();
172   for(anIter.Start(); anIter.More(); anIter.Next()) {
173     const Handle(Interface_Check) ach = anIter.Value();
174     nbWarn += ach->NbWarnings();
175     nbFail += ach->NbFails();
176   }
177 // Messages nbWarn and nbFail;
178   Msg25.Arg(nbFail);
179   Msg26.Arg(nbWarn);
180   TF->Send (Msg25, Message_Info);
181   TF->Send (Msg26, Message_Info);
182   
183   // Message fin de loading iGES file (elapsed time %s)
184   char t[20];
185   t[0]='\0';
186   Standard_Real second, cpu;
187   Standard_Integer minute, hour;
188   c.Show(second, minute, hour,cpu);
189   if (hour > 0)
190     Sprintf(t,"%dh:%dm:%.2fs",hour,minute,second);
191   else if (minute > 0)
192     Sprintf(t,"%dm:%.2fs",minute,second);
193   else
194     Sprintf(t,"%.2fs",second);
195   // Sending of message : End of Loading
196   Msg8.Arg(t);
197   TF->Send (Msg8, Message_Info);
198   
199   SetModel(model);
200   return StatusFile;
201 }
202
203
204 //=======================================================================
205 //function : SetModel
206 //purpose  : Specifies a Model to work on
207 //=======================================================================
208     void  IGESToBRep_Reader::SetModel (const Handle(IGESData_IGESModel)& model)
209 {
210   theModel = model;
211   theDone  = Standard_False;
212   theShapes.Clear();
213   if ( theProc.IsNull() )
214     theProc = new Transfer_TransientProcess (theModel->NbEntities());
215   else 
216     theProc->Clear();
217 }
218
219
220 //=======================================================================
221 //function : Model
222 //purpose  : returns the Model to be worked on
223 //=======================================================================
224     Handle(IGESData_IGESModel)  IGESToBRep_Reader::Model () const
225       {  return theModel;  }
226
227
228 //=======================================================================
229 //function : SetTransientProcess
230 //purpose  : Specifies a TransferProcess
231 //=======================================================================
232     void  IGESToBRep_Reader::SetTransientProcess
233   (const Handle(Transfer_TransientProcess)& TP)
234      {  theProc = TP;  }
235
236 //=======================================================================
237 //function : TransientProcess
238 //purpose  : Returns the TransferProcess
239 //=======================================================================
240     Handle(Transfer_TransientProcess)  IGESToBRep_Reader::TransientProcess () const
241      {  return theProc;  }
242
243 //=======================================================================
244 //function : Actor
245 //purpose  : returns theActor
246 //=======================================================================
247     Handle(IGESToBRep_Actor)  IGESToBRep_Reader::Actor () const
248       {  return theActor;  }
249
250
251 //=======================================================================
252 //function : Clear
253 //purpose  : Clears the result and Done status
254 //=======================================================================
255     void  IGESToBRep_Reader::Clear ()
256 {
257   theDone  = Standard_False;
258   theShapes.Clear();
259 }
260
261
262 //=======================================================================
263 //function : Check
264 //purpose  : Checks the Model
265 //=======================================================================
266     Standard_Boolean  IGESToBRep_Reader::Check
267   (const Standard_Boolean withprint) const
268 {
269   Interface_CheckTool cht (theModel,protocol);
270   Interface_CheckIterator chl = cht.CompleteCheckList();
271   if (withprint
272   && !theProc.IsNull()
273   && !theProc->Messenger().IsNull())
274   {
275     Message_Messenger::StreamBuffer aBuffer = theProc->Messenger()->SendInfo();
276     cht.Print(chl, aBuffer);
277   }
278   return chl.IsEmpty(Standard_True);
279 }
280
281
282 //=======================================================================
283 //function : IsDone
284 //purpose  : returns True if the last transfert was a success
285 //=======================================================================
286     Standard_Boolean  IGESToBRep_Reader::IsDone () const
287       {  return theDone;  }
288
289
290 //=======================================================================
291 //function : EncodeRegul
292 //purpose  : INTERNAL to encode regularity on edges
293 //=======================================================================
294
295 static Standard_Boolean  EncodeRegul (const TopoDS_Shape& sh)
296 {
297   Standard_Real tolang = Interface_Static::RVal("read.encoderegularity.angle");
298   if (sh.IsNull()) return Standard_True;
299   if (tolang <= 0) return Standard_True;
300   try {
301     OCC_CATCH_SIGNALS
302     BRepLib::EncodeRegularity (sh,tolang);
303   }
304   catch(Standard_Failure const&) {
305     return Standard_False;
306   }
307   return Standard_True;
308 }
309
310 //=======================================================================
311 //function : UpdateMap
312 //purpose  : Updates the correspondence map (Transfer_TransientProcess),
313 //           setting as translation results, the shapes received after
314 //           modification by modifier (BRepTools_Modifier)
315 //warning  : BRepTools_Modifier raises exception when it cannot find input
316 //           shape in its internal list
317 //=======================================================================
318
319 // coment as unused PTV 18.09.2000
320 // static void UpdateMap (const Handle(Transfer_TransientProcess)& map,
321 //                     const BRepTools_Modifier& modifier)
322 // {
323 //   Transfer_IteratorOfProcessForTransient iterator = map->CompleteResult(Standard_True);
324 //   for (iterator.Start(); iterator.More(); iterator.Next()) {
325 //     const Handle(Transfer_Binder) binder = iterator.Value();
326 //     try { //to avoid exception in BRepTools_Modifier
327 //       OCC_CATCH_SIGNALS
328 //       if (binder->IsKind (STANDARD_TYPE (TransferBRep_ShapeBinder))) {
329 //      DeclareAndCast(TransferBRep_ShapeBinder, shapebinder, binder);
330 //      if (shapebinder->HasResult()) {
331 //        TopoDS_Shape result = shapebinder->Result();
332 //        TopoDS_Shape modified = modifier.ModifiedShape (result);
333 //        if (shapebinder->Status() != Transfer_StatusUsed) //to avoid exception
334 //          shapebinder->SetResult (modified);
335 //      }
336 //       }
337 //       else if (binder->IsKind (STANDARD_TYPE (TransferBRep_ShapeListBinder))) {
338 //      DeclareAndCast(TransferBRep_ShapeListBinder, shapelistbinder, binder);
339 //      for (Standard_Integer i = 1; i <= shapelistbinder->NbShapes(); i++) {
340 //        TopoDS_Shape result = shapelistbinder->Shape (i);
341 //        TopoDS_Shape modified = modifier.ModifiedShape (result);
342 //        shapelistbinder->SetResult (i, modified);
343 //      }
344 //       }
345 //     }
346 //     catch(Standard_Failure) {
347 //       continue;
348 //     }
349 //   }
350 // }
351
352 //=======================================================================
353 //function : TrimTolerances
354 //purpose  : Trims tolerances of the shape according to static parameters
355 //          
356 //=======================================================================
357
358 static void TrimTolerances (const TopoDS_Shape& shape,
359                             const Standard_Real tol)
360 {
361   if( Interface_Static::IVal("read.maxprecision.mode")==1) {
362     ShapeFix_ShapeTolerance SFST;
363     SFST.LimitTolerance (shape, 0, Max(tol,Interface_Static::RVal ("read.maxprecision.val")));
364   }
365 }
366   
367 //=======================================================================
368 //function : TransferRoots
369 //purpose  : Transfers all Roots Entities
370 //=======================================================================
371 void  IGESToBRep_Reader::TransferRoots (const Standard_Boolean onlyvisible,
372                                         const Message_ProgressRange& theProgress)
373 {
374   if (theModel.IsNull() || theProc.IsNull()) return;
375
376   Handle(Message_Messenger) TF = theProc->Messenger();
377   // Declaration of messages.
378   Message_Msg msg2030("IGES_2030");
379   TF->Send (msg2030, Message_Info);
380   Message_Msg msg2065("IGES_2065");
381   OSD_Timer c; c.Reset(); c.Start();   // Initialisation du CHRONO
382   theDone = Standard_False;
383   theShapes.Clear();
384   
385   Standard_Integer level = theProc->TraceLevel();
386   theProc->SetErrorHandle(Standard_True);
387   theProc->SetRootManagement(Standard_True);
388 //  PrepareTransfer();  -> protocol, actor
389   theActor->SetModel(theModel);
390   Standard_Integer continuity = Interface_Static::IVal("read.iges.bspline.continuity");
391   theActor->SetContinuity (continuity);
392   theProc->SetModel (theModel);
393   theProc->SetActor (theActor);
394   Transfer_TransferOutput TP (theProc,theModel);
395
396   const Handle(Interface_Protocol) aProtocol = protocol; // to avoid ambiguity
397   Interface_ShareFlags SH (theModel, aProtocol);
398   Standard_Integer nb = theModel->NbEntities();
399   ShapeExtend_Explorer SBE;
400
401   
402   Standard_Integer precisionMode = Interface_Static::IVal("read.precision.mode");
403   Message_Msg msg2035("IGES_2035");
404   msg2035.Arg(precisionMode);
405   TF->Send (msg2035, Message_Info);
406   if (precisionMode==1) {
407     Message_Msg msg2040("IGES_2040");
408     msg2040.Arg(Interface_Static::RVal("read.precision.val"));//#70 rln 03.03.99
409     TF->Send (msg2040, Message_Info);
410   }
411   Message_Msg msg2045("IGES_2045");
412   msg2045.Arg(continuity);
413   TF->Send (msg2045, Message_Info);
414   Message_Msg msg2050("IGES_2050");
415   msg2050.Arg(Interface_Static::IVal("read.surfacecurve.mode"));
416   TF->Send (msg2050, Message_Info);
417
418   // sln 11.06.2002 OCC448
419   Interface_Static::SetIVal("read.iges.onlyvisible",onlyvisible);
420   
421   Message_ProgressScope PS (theProgress, "Root", nb);
422   for (Standard_Integer i = 1; i <= nb && PS.More(); i++)
423   {
424     Message_ProgressRange aRange = PS.Next();
425     Handle(IGESData_IGESEntity) ent = theModel->Entity(i);
426     if ( SH.IsShared(ent) || ! theActor->Recognize (ent) ) continue;
427     if (level > 0) {
428       Message_Msg msg2070("IGES_2070");
429       msg2070.Arg(2*i-1);
430       msg2070.Arg(ent->TypeNumber());
431       TF->Send (msg2070, Message_Info);
432     }
433     // on ajoute un traitement pour ne prendre que les entites visibles
434     if ( ! onlyvisible || ent->BlankStatus() == 0 ) {
435       TopoDS_Shape shape;
436       theDone = Standard_True;
437       try {
438         OCC_CATCH_SIGNALS
439         TP.Transfer (ent, aRange);
440         shape = TransferBRep::ShapeResult (theProc,ent);
441       } 
442       catch(Standard_Failure const&) {
443         Message_Msg msg1005("IGES_1005");
444         TF->Send (msg1005, Message_Info);
445         continue;
446       }
447       if (shape.IsNull()) {
448         Message_Msg msg2076("IGES_2076");
449         TF->Send (msg2076, Message_Info);
450       }
451       else {
452         if (SBE.ShapeType(shape,Standard_True) != TopAbs_SHAPE) {
453           if (!shape.IsNull()) {
454             EncodeRegul (shape);
455             //#74 rln 03.03.99 S4135
456             TrimTolerances (shape, theActor->UsedTolerance());
457             theShapes.Append(shape);
458           }
459         }
460       }
461     }
462   }
463   char t [20];
464   t[0]='\0';
465   Standard_Real second, cpu;
466   Standard_Integer minute, hour;
467   c.Show(second, minute, hour,cpu);
468   if (hour > 0)
469     Sprintf(t,"%dh:%dm:%.2fs",hour,minute,second);
470   else if (minute > 0)
471     Sprintf(t,"%dm:%.2fs",minute,second);
472   else
473     Sprintf(t,"%.2fs",second);
474   // Sending of message : End of Loading
475   msg2065.Arg(t);
476   TF->Send (msg2065, Message_Info);
477 }
478
479
480 //=======================================================================
481 //function : Transfer
482 //purpose  : Transfers an Entity given
483 //=======================================================================
484 Standard_Boolean  IGESToBRep_Reader::Transfer(const Standard_Integer num,
485                                               const Message_ProgressRange& theProgress)
486
487   Handle(Message_Messenger) TF = theProc->Messenger();
488   theDone = Standard_False;
489   if (theModel.IsNull()) {
490     Message_Msg msg2031("IGES_2031");
491     TF->Send (msg2031, Message_Info);
492     return Standard_False;
493   }
494   if (num <= 0 || num > theModel->NbEntities()) {
495     Message_Msg msg2032("IGES_2032");
496     msg2032.Arg(num);
497     TF->Send (msg2032, Message_Info);
498     return Standard_False;
499   }
500   // declaration of messages
501   Message_Msg msg2030("IGES_2030");
502   TF->Send (msg2030, Message_Info);
503   Message_Msg msg2065("IGES_2065");
504   OSD_Timer c; c.Reset(); c.Start();   // Initialisation du CHRONO
505   
506   Handle(IGESData_IGESEntity) ent = theModel->Entity(num);
507
508   Message_ProgressScope aPS(theProgress, "OneEnt", 2);
509
510   XSAlgo::AlgoContainer()->PrepareForTransfer();
511   IGESToBRep_CurveAndSurface CAS;
512   CAS.SetModel(theModel);
513   Standard_Real eps;
514   Standard_Integer Ival = Interface_Static::IVal("read.precision.mode");
515   Message_Msg msg2035("IGES_2035");
516   msg2035.Arg(Ival);
517   TF->Send (msg2035, Message_Info);
518   if ( Ival == 0)
519     eps = theModel->GlobalSection().Resolution();
520   else {
521     //mjm : modif du 19/12/97 pour prise en compte effective du parametre
522     eps = Interface_Static::RVal("read.precision.val");
523     Message_Msg msg2040("IGES_2040");
524     msg2040.Arg(eps);//#70 rln 03.03.99
525     TF->Send (msg2040, Message_Info);
526     
527   }
528   Ival = Interface_Static::IVal("read.iges.bspline.approxd1.mode");
529   CAS.SetModeApprox ( (Ival > 0) );
530   Message_Msg msg2045("IGES_2045");
531   Ival = Interface_Static::IVal("read.iges.bspline.continuity");
532   msg2045.Arg(Ival);
533   TF->Send (msg2045, Message_Info);
534   CAS.SetContinuity(Ival);
535   Message_Msg msg2050("IGES_2050");
536   Ival = Interface_Static::IVal("read.surfacecurve.mode");
537   msg2050.Arg(Ival);
538   TF->Send (msg2050, Message_Info);
539   CAS.SetSurfaceCurve (Ival);
540
541   if (eps > 1.E-08) CAS.SetEpsGeom(eps);
542   CAS.SetTransferProcess(theProc);
543
544   Standard_Boolean exceptionRaised = Standard_False;
545   TopoDS_Shape shape;
546   Standard_Integer nbTPitems = theProc->NbMapped();
547   {
548     try {
549       OCC_CATCH_SIGNALS
550       shape = CAS.TransferGeometry (ent, aPS.Next());
551       if (aPS.UserBreak())
552         return Standard_False;
553     } 
554     catch(Standard_Failure const&) {
555       Message_Msg msg1015("IGES_1015");
556       TF->Send (msg1015, Message_Info);
557       exceptionRaised = Standard_True;
558     }
559   }
560   if (!exceptionRaised) {
561     // fixing shape
562 //    shape = XSAlgo::AlgoContainer()->PerformFixShape ( shape, theProc, eps*CAS.GetUnitFactor(), CAS.GetMaxTol() );
563
564     Handle(Standard_Transient) info;
565     shape = XSAlgo::AlgoContainer()->ProcessShape( shape, eps*CAS.GetUnitFactor(), CAS.GetMaxTol(),
566                                                    "read.iges.resource.name", 
567                                                    "read.iges.sequence", info,
568                                                    aPS.Next() );
569     if (aPS.UserBreak())
570       return Standard_False;
571
572     XSAlgo::AlgoContainer()->MergeTransferInfo(theProc, info, nbTPitems);
573
574     ShapeExtend_Explorer SBE;
575     if (SBE.ShapeType (shape,Standard_True) != TopAbs_SHAPE) {
576       TransferBRep::SetShapeResult (theProc,ent,shape);
577       theProc->SetRoot (ent);
578       if (!shape.IsNull()) {
579         theDone = Standard_True;
580         EncodeRegul (shape);
581         //#74 rln 03.03.99 S4135
582         TrimTolerances (shape, CAS.GetMaxTol());
583         theShapes.Append(shape);
584       }
585     }
586   }
587
588   char t [20];
589   t[0]='\0';
590   Standard_Real second, cpu;
591   Standard_Integer minute, hour;
592   c.Show(second, minute, hour,cpu);
593   if (hour > 0)
594     Sprintf(t,"%dh:%dm:%.2fs",hour,minute,second);
595   else if (minute > 0)
596     Sprintf(t,"%dm:%.2fs",minute,second);
597   else
598     Sprintf(t,"%.2fs",second);
599   // Sending of message : End of Loading
600   msg2065.Arg(t);
601   TF->Send (msg2065, Message_Info);
602   return Standard_True;
603 }
604
605
606 //=======================================================================
607 //function : UsedTolerance
608 //purpose  : Returns the used tolerance (input)
609 //=======================================================================
610     Standard_Real  IGESToBRep_Reader::UsedTolerance () const
611       {  return theActor->UsedTolerance();  }
612
613 //=======================================================================
614 //function : NbShapes
615 //purpose  : Returns the count of produced Shapes
616 //=======================================================================
617     Standard_Integer  IGESToBRep_Reader::NbShapes () const
618       {  return theShapes.Length();  }
619
620
621 //=======================================================================
622 //function : Shape
623 //purpose  : Returns a Shape given its rank
624 //=======================================================================
625     TopoDS_Shape  IGESToBRep_Reader::Shape (const Standard_Integer num) const
626 {
627   TopoDS_Shape res;
628   if (num > 0 && num <= theShapes.Length()) res = theShapes.Value(num);
629   return res;
630 }
631
632
633 //=======================================================================
634 //function : OneShape
635 //purpose  : Returns a unique Shape
636 //=======================================================================
637     TopoDS_Shape  IGESToBRep_Reader::OneShape () const
638 {
639   TopoDS_Shape res;
640   Standard_Integer nb = theShapes.Length();
641   if (nb == 0) return res;
642   else if (nb == 1) return theShapes.Value(1);
643   else {
644     TopoDS_Compound C;
645     BRep_Builder B;
646     B.MakeCompound(C);
647     for (Standard_Integer i = 1; i <= nb; i ++)  B.Add (C,theShapes.Value(i));
648     return C;
649   }
650 }