3d8c29d670b88bd184b2aaeac6e91092df5f5230
[occt.git] / src / STEPControl / STEPControl_ActorWrite.cxx
1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
2 //
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
7 //
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10 //
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
17
18 //:k8 abv 6 Jan 99: unique names for PRODUCTs
19 //:k9 abv 6 Jan 99: TR10: eliminating duplicated APPLICATION_CONTEXT entities
20 //abv,gka 05.04.99: S4136: change parameters and update units
21 // PTV    22.08.2002 OCC609 transfer solo vertices into step file.
22 // PTV    16.09.2002 OCC725 transfer compound of vertices into one geometrical curve set.
23 #include <STEPControl_ActorWrite.ixx>
24 #include <STEPControl_StepModelType.hxx>
25
26 //  Transfer
27 #include <Transfer_SimpleBinderOfTransient.hxx>
28 #include <gp_Ax2.hxx>
29 #include <GeomToStep_MakeAxis2Placement3d.hxx>
30 #include <StepGeom_Axis2Placement3d.hxx>
31
32 #include <STEPConstruct_Part.hxx>
33 #include <STEPConstruct_Assembly.hxx>
34 #include <STEPConstruct_ContextTool.hxx>
35 #include <STEPConstruct_UnitContext.hxx>
36
37 //  TransferShape
38 #include <TopoDSToStep.hxx>
39 #include <TopoDSToStep_Builder.hxx>
40 #include <TopoDSToStep_FacetedTool.hxx>
41 #include <TopoDSToStep_Tool.hxx>
42 #include <TopoDSToStep_MakeManifoldSolidBrep.hxx>
43 #include <TopoDSToStep_MakeBrepWithVoids.hxx>
44 #include <TopoDSToStep_MakeFacetedBrep.hxx>
45 #include <TopoDSToStep_MakeFacetedBrepAndBrepWithVoids.hxx>
46 #include <TopoDSToStep_MakeGeometricCurveSet.hxx>
47 #include <TopoDSToStep_MakeShellBasedSurfaceModel.hxx>
48
49 #include <TopoDS.hxx>
50 #include <TopoDS_Shape.hxx>
51 #include <TopoDS_Solid.hxx>
52 #include <Geom_Surface.hxx>
53 #include <Geom_Plane.hxx>
54 #include <Geom_Curve.hxx>
55 #include <Geom_Line.hxx>
56
57 #include <StepShape_ShapeDefinitionRepresentation.hxx>
58 #include <StepShape_FacetedBrepAndBrepWithVoids.hxx>
59 #include <StepShape_FacetedBrep.hxx>
60 #include <StepShape_GeometricCurveSet.hxx>
61 #include <StepShape_ShellBasedSurfaceModel.hxx>
62 #include <StepShape_ManifoldSolidBrep.hxx>
63 #include <StepShape_BrepWithVoids.hxx>
64 #include <StepRepr_HArray1OfRepresentationItem.hxx>
65 #include <StepBasic_HArray1OfProduct.hxx>
66 #include <StepRepr_GlobalUnitAssignedContext.hxx>
67 #include <StepShape_AdvancedBrepShapeRepresentation.hxx>
68 #include <StepShape_FacetedBrepShapeRepresentation.hxx>
69 #include <StepShape_TopologicalRepresentationItem.hxx>
70 #include <StepShape_ManifoldSurfaceShapeRepresentation.hxx>
71 #include <StepShape_GeometricallyBoundedWireframeShapeRepresentation.hxx>
72 #include <StepBasic_ApplicationProtocolDefinition.hxx>
73 #include <StepRepr_PropertyDefinition.hxx>
74
75 #include <TopExp_Explorer.hxx>
76 #include <TColStd_HSequenceOfTransient.hxx>
77 #include <TCollection_HAsciiString.hxx>
78
79 #include <Transfer_TransientProcess.hxx>
80 #include <Transfer_Binder.hxx>
81 #include <Transfer_Finder.hxx>
82 #include <Transfer_FinderProcess.hxx>
83 #include <TransferBRep_ShapeMapper.hxx>
84 #include <TransferBRep.hxx>
85 #include <OSD_Timer.hxx>
86
87 #include <ShapeExtend_Explorer.hxx>  
88 #include <ShapeAnalysis_ShapeTolerance.hxx>
89 #include <Interface_MSG.hxx>
90 #include <Interface_Static.hxx>
91
92 #include <Interface_Macros.hxx>
93 #include <TopTools_HSequenceOfShape.hxx>
94
95 #include <BRep_Tool.hxx>
96 #include <TopoDS_Iterator.hxx> //:d6
97 #include <UnitsMethods.hxx>
98 #include <STEPConstruct_AP203Context.hxx>
99 #include <BRepTools_Modifier.hxx>
100
101 #include <XSAlgo.hxx>
102 #include <XSAlgo_AlgoContainer.hxx>
103 #include <StepRepr_ShapeRepresentationRelationship.hxx>
104 #include <Transfer_SequenceOfBinder.hxx>
105
106 #include <TopoDSToStep_MakeStepVertex.hxx>
107 #include <StepShape_VertexPoint.hxx>
108 #include <MoniTool_DataMapOfShapeTransient.hxx>
109 #include <StepShape_HArray1OfGeometricSetSelect.hxx>
110 #include <StepShape_GeometricSetSelect.hxx>
111 #include <TopoDS_Compound.hxx>
112 #include <BRep_Builder.hxx>
113
114 // Non-manifold topology processing (ssv; 10.11.2010)
115 #include <StepShape_NonManifoldSurfaceShapeRepresentation.hxx>
116 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
117 #include <TopTools_ListOfShape.hxx>
118 #include <TopExp.hxx>
119 #include <TopTools_MapOfShape.hxx>
120 #include <TopTools_ListIteratorOfListOfShape.hxx>
121
122 // ============================================================================
123 // Function: DumpWhatIs   
124 // Purpose: Use it in DEB mode to dump your shapes
125 // ============================================================================
126
127 static void DumpWhatIs(const TopoDS_Shape& S) {
128
129   TopTools_MapOfShape aMapOfShape;
130   aMapOfShape.Add(S);
131   TopTools_ListOfShape aListOfShape;
132   aListOfShape.Append(S);
133   TopTools_ListIteratorOfListOfShape itL(aListOfShape);
134   Standard_Integer nbSolids = 0,
135                    nbShells = 0,
136                    nbOpenShells = 0,
137                    nbFaces = 0, 
138                    nbWires = 0, 
139                    nbEdges = 0, 
140                    nbVertexes = 0;
141
142   for( ; itL.More(); itL.Next() ) {
143     TopoDS_Iterator it( itL.Value() );
144     for ( ; it.More(); it.Next() ) {
145       TopoDS_Shape aSubShape = it.Value();
146       if ( !aMapOfShape.Add(aSubShape) )
147         continue;
148       aListOfShape.Append(aSubShape);
149       if (aSubShape.ShapeType() == TopAbs_SOLID)
150         nbSolids++;
151       if (aSubShape.ShapeType() == TopAbs_SHELL) {
152         if ( !aSubShape.Closed() )
153           nbOpenShells++;
154         nbShells++;
155       }
156       if (aSubShape.ShapeType() == TopAbs_FACE)
157         nbFaces++;
158       if (aSubShape.ShapeType() == TopAbs_WIRE)
159         nbWires++;
160       if (aSubShape.ShapeType() == TopAbs_EDGE)
161         nbEdges++;
162       if (aSubShape.ShapeType() == TopAbs_VERTEX)
163         nbVertexes++;
164     }
165   }
166   #ifdef DEB
167   cout << "//What is?// NB SOLIDS: " << nbSolids << endl;
168   cout << "//What is?// NB SHELLS: " << nbShells << endl;
169   cout << "//What is?//    OPEN SHELLS: " << nbOpenShells << endl;
170   cout << "//What is?//    CLOSED SHELLS: " << nbShells - nbOpenShells << endl;
171   cout << "//What is?// NB FACES: " << nbFaces << endl;
172   cout << "//What is?// NB WIRES: " << nbWires << endl;
173   cout << "//What is?// NB EDGES: " << nbEdges << endl;
174   cout << "//What is?// NB VERTEXES: " << nbVertexes << endl;
175   #endif
176 }
177
178 //=======================================================================
179 // Function : IsManifoldShape
180 // Purpose  : Used to define whether the passed shape has manifold
181 //            topology or not
182 //=======================================================================
183
184 static Standard_Boolean IsManifoldShape(const TopoDS_Shape& theShape) {
185
186    Standard_Boolean aResult = Standard_True;
187
188   // Do not check nested Compounds
189   TopoDS_Compound aDirectShapes;
190   BRep_Builder aBrepBuilder;
191   aBrepBuilder.MakeCompound(aDirectShapes);
192
193   TopoDS_Iterator anIt(theShape);
194   for ( ; anIt.More(); anIt.Next() ) {
195     TopoDS_Shape aDirectChild = anIt.Value();
196     if (aDirectChild.ShapeType() != TopAbs_COMPOUND)
197       aBrepBuilder.Add(aDirectShapes, aDirectChild);
198   }  
199
200   #ifdef DEB
201   DumpWhatIs(aDirectShapes);
202   #endif
203
204   TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
205   TopExp::MapShapesAndAncestors(aDirectShapes, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
206
207   Standard_Integer aNbEdges = aMapEdgeFaces.Extent();
208   #ifdef DEB
209   cout << "Checking whether the topology passed is manifold..." << endl;
210   #endif
211
212   // Check topology
213   for (Standard_Integer i = 1; i <= aNbEdges; i++) {
214     TopoDS_Edge aCurrentEdge = TopoDS::Edge( aMapEdgeFaces.FindKey(i) );
215     if ( !BRep_Tool::Degenerated(aCurrentEdge) ) { 
216       Standard_Integer aNbAncestors = aMapEdgeFaces.FindFromIndex(i).Extent();
217       if (aNbAncestors > 2) {
218         aResult = Standard_False;
219         break;
220       }
221     }
222   }
223
224   #ifdef DEB
225   cout << "Check result: "
226        << (aResult ? "TRUE" : "FALSE") << endl;
227   #endif
228
229   return aResult;
230 }
231
232 /* this is a start of a comment! */ 
233 #ifdef DEB
234 void DumpBinder (const Handle(Transfer_Binder) &binder)
235 {
236   Handle(Transfer_Binder) bbb = binder;
237   while ( ! bbb.IsNull() ) {
238     Handle(Transfer_SimpleBinderOfTransient) bx = 
239       Handle(Transfer_SimpleBinderOfTransient)::DownCast ( bbb );
240     cout << (void*)&bx;
241     if ( ! bx.IsNull() ) {
242       cout << "--> " << bx->ResultTypeName() << " " << *(void**)&bx->Result() << endl;
243     }
244     else cout << "--> ???" << endl;
245     bbb = bbb->NextResult();
246   }
247   cout << endl;
248 }
249 #endif
250 /* this is a end of a comment */
251   
252 //=======================================================================
253 //function : STEPControl_ActorWrite
254 //purpose  : 
255 //=======================================================================
256
257 STEPControl_ActorWrite::STEPControl_ActorWrite ()
258 : mygroup (0) , mytoler (-1.)
259 {  
260   SetMode(STEPControl_ShellBasedSurfaceModel);  
261 }
262
263 //=======================================================================
264 //method: getNMSSRForGroup
265 //purpose: allows to get NMSSR (NON_MANIFOLD_SURFACE_SHAPE_REPRESENTATION)
266 //         STEP's entity for the group of shells (!) passed
267 //=======================================================================
268
269 Handle(StepShape_NonManifoldSurfaceShapeRepresentation) STEPControl_ActorWrite::getNMSSRForGroup(const Handle(TopTools_HSequenceOfShape)& shapeGroup,
270                                                                                                  const Handle(Transfer_FinderProcess)& FP, 
271                                                                                                  Standard_Boolean& isNMSSRCreated) const
272 {
273   Handle(StepShape_NonManifoldSurfaceShapeRepresentation) aResult;
274
275   if ( !shapeGroup.IsNull() ) {
276     for (Standard_Integer i = 1; i <= shapeGroup->Length(); i++) {
277       TopoDS_Shape aCurrentShape = shapeGroup->Value(i);
278       Handle(TransferBRep_ShapeMapper) mapper = TransferBRep::ShapeMapper(FP, aCurrentShape);
279       if ( FP->FindTypedTransient(mapper, STANDARD_TYPE(StepShape_NonManifoldSurfaceShapeRepresentation), aResult) )
280         break;
281     }
282   }
283
284   if ( aResult.IsNull() ) {
285     #ifdef DEB
286     cout << "\nNew NMSSR created" << endl;
287     #endif
288     aResult = new StepShape_NonManifoldSurfaceShapeRepresentation;
289     isNMSSRCreated = Standard_True;
290   } else {
291     #ifdef DEB
292     cout << "\nExisting NMSSR is used" << endl;
293     #endif
294     isNMSSRCreated = Standard_False;
295   }
296
297   return aResult;
298 }
299
300
301 //=======================================================================
302 //function : SetMode
303 //purpose  : 
304 //=======================================================================
305
306 void STEPControl_ActorWrite::SetMode (const STEPControl_StepModelType M)
307 {
308   switch (M) {
309   case STEPControl_AsIs : ModeTrans() = 0; break;
310   case STEPControl_ManifoldSolidBrep : ModeTrans() = 3; break;
311   case STEPControl_BrepWithVoids :     ModeTrans() = 5; break;
312   case STEPControl_FacetedBrep :       ModeTrans() = 1; break;
313   case STEPControl_FacetedBrepAndBrepWithVoids : ModeTrans() = 6; break;
314   case STEPControl_ShellBasedSurfaceModel :      ModeTrans() = 2;
315   case STEPControl_GeometricCurveSet :           ModeTrans() = 4;
316   case STEPControl_Hybrid : ModeTrans() = 0; break;  // PAS IMPLEMENTE !!
317     default: break;
318   }
319 }
320
321 //=======================================================================
322 //function : Mode
323 //purpose  : 
324 //=======================================================================
325
326 STEPControl_StepModelType STEPControl_ActorWrite::Mode () const
327 {
328   switch (themodetrans) {
329   case 0 : return STEPControl_AsIs;
330   case 1 : return STEPControl_FacetedBrep;
331   case 2 : return STEPControl_ShellBasedSurfaceModel;
332   case 3 : return STEPControl_ManifoldSolidBrep;
333   case 4 : return STEPControl_GeometricCurveSet;
334   case 5 : return STEPControl_BrepWithVoids;
335   case 6 : return STEPControl_FacetedBrepAndBrepWithVoids;
336     default : break;
337   }
338   return STEPControl_AsIs;
339 }
340
341 //=======================================================================
342 //function : SetGroupMode
343 //purpose  : 
344 //=======================================================================
345
346 void STEPControl_ActorWrite::SetGroupMode (const Standard_Integer mode)
347 {  
348   if (mode >= 0) mygroup = mode;  
349 }
350
351 //=======================================================================
352 //function : GroupMode
353 //purpose  : 
354 //=======================================================================
355
356 Standard_Integer STEPControl_ActorWrite::GroupMode () const
357 {  
358   return mygroup;  
359 }
360
361 //=======================================================================
362 //function : SetTolerance
363 //purpose  : 
364 //=======================================================================
365
366 void STEPControl_ActorWrite::SetTolerance (const Standard_Real Tol)
367 {  
368   mytoler = Tol;  
369 }
370
371 //=======================================================================
372 //function : Recognize
373 //  ATTENTION, Recognize doit s aligner sur ce que Transfer sait faire
374 //purpose  : 
375 //=======================================================================
376
377 Standard_Boolean  STEPControl_ActorWrite::Recognize (const Handle(Transfer_Finder)& start)
378 {
379   STEPControl_StepModelType mymode = Mode();
380   Handle(TransferBRep_ShapeMapper) mapper = Handle(TransferBRep_ShapeMapper)::DownCast(start);
381   if (mapper.IsNull()) return Standard_False;
382   if (mymode == STEPControl_AsIs) return Standard_True;
383
384   Standard_Boolean yasolid = Standard_False, yashell = Standard_False,
385                    yaface  = Standard_False;
386
387   TopoDS_Shape theShape, aShape;
388 //  theShape = TopoDSToStep::DirectFaces(mapper->Value());
389   theShape = mapper->Value();  // pour une reconnaissance c est bien assez
390
391   if (theShape.ShapeType() == TopAbs_COMPOUND) {
392     
393     TopExp_Explorer SolidExp, ShellExp, FaceExp;
394     
395     for (SolidExp.Init(theShape, TopAbs_SOLID);
396          SolidExp.More();SolidExp.Next()) yasolid = Standard_True;
397     for (ShellExp.Init(theShape, TopAbs_SHELL, TopAbs_SOLID);
398          ShellExp.More();ShellExp.Next()) yashell = Standard_True;
399     for (FaceExp.Init(theShape, TopAbs_FACE, TopAbs_SHELL);
400          FaceExp.More();FaceExp.Next())   yaface  = Standard_True;
401   }
402   else if (theShape.ShapeType() == TopAbs_SOLID) yasolid = Standard_True;
403   else if (theShape.ShapeType() == TopAbs_SHELL) yashell = Standard_True;
404   else if (theShape.ShapeType() == TopAbs_FACE)  yaface  = Standard_True;
405   else if (mymode != STEPControl_GeometricCurveSet) return Standard_False;
406 //  pour wireframe ?
407
408 //  Faceted : il est OBLIGATOIRE d avoir des surfaces support Plane et des
409 //   courbes 3D Line (pcurves ignorees)
410
411   if (mymode == STEPControl_FacetedBrep || mymode == STEPControl_FacetedBrepAndBrepWithVoids) {
412     for (TopExp_Explorer ffac(theShape,TopAbs_FACE); ffac.More(); ffac.Next()) {
413       const TopoDS_Face& F = TopoDS::Face (ffac.Current());
414       TopLoc_Location locbid;
415       Handle(Geom_Surface) surf = BRep_Tool::Surface (F,locbid);
416       if (surf.IsNull() || !surf->IsKind(STANDARD_TYPE(Geom_Plane)) ) return Standard_False;
417     }
418     for (TopExp_Explorer fedg(theShape,TopAbs_EDGE); fedg.More(); fedg.Next()) {
419       const TopoDS_Edge& E = TopoDS::Edge (fedg.Current());
420       TopLoc_Location locbid;  Standard_Real first,last;
421       Handle(Geom_Curve) curv = BRep_Tool::Curve (E,locbid,first,last);
422       if (curv.IsNull() || !curv->IsKind(STANDARD_TYPE(Geom_Line)) ) return Standard_False;
423     }
424   }
425
426   switch (mymode) {
427     case STEPControl_ManifoldSolidBrep: return (yasolid || yashell);
428     case STEPControl_BrepWithVoids:
429     case STEPControl_FacetedBrep:
430     case STEPControl_FacetedBrepAndBrepWithVoids:       return yasolid;
431     case STEPControl_ShellBasedSurfaceModel:
432                                         return (yasolid || yashell || yaface);
433     case STEPControl_GeometricCurveSet:  return Standard_True;  // tout OK
434     default : break;
435   }
436   return Standard_False;
437 }
438
439
440 //  ########    MAKE PRODUCT DATA + CONTEXT    ########
441
442 //=======================================================================
443 //function : Transfer
444 //purpose  : 
445 //=======================================================================
446
447 Handle(Transfer_Binder) STEPControl_ActorWrite::Transfer (const Handle(Transfer_Finder)& start,
448                                                           const Handle(Transfer_FinderProcess)& FP)
449 {
450   XSAlgo::AlgoContainer()->PrepareForTransfer();
451     
452   Handle(TransferBRep_ShapeMapper) mapper = Handle(TransferBRep_ShapeMapper)::DownCast(start);
453
454   if (mapper.IsNull()) return NullResult();
455   TopoDS_Shape shape = mapper->Value();
456
457   // init context
458   Handle(StepData_StepModel) model = Handle(StepData_StepModel)::DownCast ( FP->Model() );
459   if ( ! model.IsNull() ) myContext.SetModel ( model ); //: abv 04.11.00: take APD from model
460   myContext.AddAPD ( Standard_False ); // update APD
461   myContext.SetLevel ( 1 ); // set assembly level to 1 (to ensure)
462   
463   //:S4136: init UnitsMethods to reset angle unit factors (see TopoDSToStep)
464   Standard_Real lFactor = UnitsMethods::GetLengthFactorValue ( Interface_Static::IVal ( "write.step.unit" ) );
465   lFactor /= UnitsMethods::GetCasCadeLengthUnit();
466   Standard_Integer anglemode = Interface_Static::IVal("step.angleunit.mode");
467   UnitsMethods::InitializeFactors ( lFactor, ( anglemode <= 1 ? 1. : M_PI/180. ), 1. );
468
469   // create SDR
470   STEPConstruct_Part SDRTool;
471   SDRTool.MakeSDR ( 0, myContext.GetProductName(), myContext.GetAPD()->Application() );
472   Handle(StepShape_ShapeDefinitionRepresentation) sdr = SDRTool.SDRValue();
473   // transfer shape
474
475   Handle(Transfer_Binder) resbind = TransferShape (mapper,sdr,FP);
476
477 //  Handle(StepShape_ShapeRepresentation) resultat;
478 //  FP->GetTypedTransient (resbind,STANDARD_TYPE(StepShape_ShapeRepresentation),resultat);
479 //  sdr->SetUsedRepresentation (resultat);
480
481   // create binder with all root entities produced from shape
482   Handle(TColStd_HSequenceOfTransient) roots = myContext.GetRootsForPart ( SDRTool );
483   Handle(Transfer_Binder) resprod = TransientResult ( myContext.GetAPD() );
484   for ( Standard_Integer i=1; i <= roots->Length(); i++ ) 
485     resprod->AddResult ( TransientResult ( roots->Value(i) ) );
486   resprod->AddResult(resbind);
487
488   // bind and exit
489   //FP->Bind (mapper,resprod);
490   myContext.NextIndex();
491   return resprod;
492 }
493
494 //==========================================
495
496 static Standard_Real UsedTolerance (const Standard_Real mytoler, 
497                                     const TopoDS_Shape& theShape)
498 {
499
500   //    COMPUTING 3D TOLERANCE
501   //    Either from Session, or Computed (Least,Average, or Greatest)
502   //    Then given to TopoDSToStep_Tool
503
504   Standard_Real Tol = mytoler;
505   Standard_Integer tolmod = Interface_Static::IVal("write.precision.mode");
506   if (Tol <= 0 && tolmod == 2) Tol =
507     Interface_Static::RVal("write.precision.val");
508   if (Tol <= 0) {
509     ShapeAnalysis_ShapeTolerance stu;
510     Tol = stu.Tolerance (theShape,tolmod);
511     //  Par defaut, on prend une tolerance moyenne, on elimine les aberrations
512     Tol = Interface_MSG::Intervalled (Tol * 1.5);  // arrondi a 1 2 5 ...
513   }
514   if (Tol == 0) Tol = 1.e-07;  // minimum ...
515
516   return Tol;
517 }
518
519 //=======================================================================
520 //function : IsAssembly
521 //purpose  : 
522 //=======================================================================
523 // if GroupMode is >1 downgrades all compounds having single subshape to that 
524 // subshape
525
526 Standard_Boolean STEPControl_ActorWrite::IsAssembly (TopoDS_Shape &S) const
527 {
528   if ( ! GroupMode() || S.ShapeType() != TopAbs_COMPOUND ) return Standard_False;
529   // PTV 16.09.2002  OCC725 for storing compound of vertices
530   if (S.ShapeType() == TopAbs_COMPOUND ) {
531     Standard_Boolean IsOnlyVertices = Standard_True;
532     TopoDS_Iterator anItr( S );
533     for ( ; anItr.More(); anItr.Next() ) {
534       if ( anItr.Value().ShapeType() != TopAbs_VERTEX ) {
535         IsOnlyVertices = Standard_False;
536         break;
537       }
538     }
539     if ( IsOnlyVertices )
540       return Standard_False;
541   }
542   if ( GroupMode() ==1 ) return Standard_True;
543   TopoDS_Iterator it ( S );
544   if ( ! it.More() ) return Standard_False;
545   TopoDS_Shape shape = it.Value();
546   it.Next();
547   if ( it.More() ) return Standard_True;
548   S = shape;
549   return IsAssembly ( S );
550 }
551
552 //=======================================================================
553 //function : TransferShape
554 //purpose  : 
555 //=======================================================================
556
557 /*
558 static void UpdateMap (const TopoDS_Shape &shape, 
559                        BRepTools_Modifier &M1, 
560                        BRepTools_Modifier &M2, 
561                        const Handle(Transfer_FinderProcess) &FinderProcess)
562 {
563   TopoDS_Shape S = M1.ModifiedShape ( shape );
564   S = M2.ModifiedShape ( S );
565   if ( S == shape ) return;
566
567   Handle(TransferBRep_ShapeMapper) mapper = TransferBRep::ShapeMapper ( FinderProcess, S );
568   Handle(Transfer_Binder) binder = FinderProcess->Find ( mapper );
569   if ( ! binder.IsNull() ) {
570     mapper = TransferBRep::ShapeMapper ( FinderProcess, shape );
571     FinderProcess->Bind ( mapper, binder );
572   }
573   
574   for ( TopoDS_Iterator it(shape); it.More(); it.Next() ) 
575     UpdateMap ( it.Value(), M1, M2, FinderProcess );
576 }
577 */
578
579 // PTV 16.09.2002 added for transfering vertices.
580 static Standard_Boolean transferVertex (const Handle(Transfer_FinderProcess)& FP,
581                                         Handle(StepShape_HArray1OfGeometricSetSelect)& aGSS,
582                                         const TopoDS_Shape& aShVrtx,
583                                         const Standard_Integer theNum)
584 {
585   Standard_Boolean IsDone = Standard_False;
586   MoniTool_DataMapOfShapeTransient aMap;
587   TopoDSToStep_Tool    aTool(aMap, Standard_True);
588   TopoDSToStep_MakeStepVertex aMkVrtx ( TopoDS::Vertex(aShVrtx), aTool, FP );
589   
590   if (!aMkVrtx.IsDone())
591     return IsDone;
592   
593   Handle(StepShape_VertexPoint) aVP = 
594     Handle(StepShape_VertexPoint)::DownCast(aTool.Find(aShVrtx));
595   if (aVP.IsNull())
596     return IsDone;
597     
598   StepShape_GeometricSetSelect select;
599   select.SetValue(aVP->VertexGeometry());
600   // add current result
601   aGSS->SetValue( theNum, select );
602   IsDone = Standard_True;
603   return IsDone;
604 }
605
606      
607 Handle(Transfer_Binder) STEPControl_ActorWrite::TransferShape (const Handle(Transfer_Finder)& start,
608                                                                const Handle(StepShape_ShapeDefinitionRepresentation)& SDR0,
609                                                                const Handle(Transfer_FinderProcess)& FP,
610                                                                const Handle(TopTools_HSequenceOfShape)& shapeGroup,
611                                                                const Standard_Boolean isManifold)
612 {
613   STEPControl_StepModelType mymode = Mode();
614   Handle(TransferBRep_ShapeMapper) mapper = Handle(TransferBRep_ShapeMapper)::DownCast(start);
615   Handle(Transfer_Binder) binder;
616
617   // Indicates whether to use an exising NMSSR to write items to (ss; 13.11.2010)
618   Standard_Boolean useExistingNMSSR = Standard_False;
619
620   if (mapper.IsNull()) return binder;
621   TopoDS_Shape theShape = mapper->Value();
622
623   if (theShape.IsNull()) return binder;
624
625   // INDIVIDUAL SHAPE ALREADY TRANSFERRED : RETURN IT !
626   binder = FP->Find(start);
627   if (!binder.IsNull()) {  if (!binder->HasResult()) binder.Nullify();  }
628   if (!binder.IsNull()) { 
629     //:abv 20.05.02: writing box & face from it (shared) in one compound 
630     // as assembly - while face already translated, it should be 
631     // re-translated to break sharing
632 #ifdef DEB
633     cout << "Warning: STEPControl_ActorWrite::TransferShape(): shape already translated" << endl;
634 #endif
635 //    return binder;
636   }
637
638   // MODE ASSEMBLY : if Compound, (sub-)assembly
639   if ( IsAssembly(theShape) )
640     return TransferCompound(start, SDR0, FP);
641
642   // [BEGIN] Separate manifold topology from non-manifold in group mode 0 (ssv; 18.11.2010)
643   Standard_Boolean isNMMode = Interface_Static::IVal("write.step.nonmanifold");
644   Handle(Transfer_Binder) aNMBinder;
645   if (isNMMode && !GroupMode() && theShape.ShapeType() == TopAbs_COMPOUND) {
646     TopoDS_Compound aNMCompound;
647     TopoDS_Compound aManifoldCompound;
648     BRep_Builder brepBuilder;
649
650     // Create empty Compounds
651     brepBuilder.MakeCompound(aManifoldCompound);
652     brepBuilder.MakeCompound(aNMCompound);
653
654     // Indicates whether there is only non-manifold topology detected 
655     // (there is no manifold topology found in the Compound passed)
656     Standard_Boolean isOnlyNonManifold = Standard_False;
657     
658     // Find a Compound containing non-manifold topology.
659     // NOTE: only one such Compound must exist in the entire Compound passed
660     if ( !IsManifoldShape(theShape) ) {
661       aNMCompound = TopoDS::Compound(theShape);
662       isOnlyNonManifold = Standard_True;
663     }
664     else {
665       TopTools_ListOfShape aListOfShapes;
666       TopTools_ListOfShape aListOfManifoldShapes;
667       aListOfShapes.Append(theShape);
668
669       TopTools_ListIteratorOfListOfShape itL(aListOfShapes);
670       for ( ; itL.More(); itL.Next() ) {
671         TopoDS_Shape aParentShape = itL.Value();
672         TopoDS_Iterator it(aParentShape);
673         for ( ; it.More(); it.Next() ) {
674           TopoDS_Shape aSubShape = it.Value();
675           if (aSubShape.ShapeType() == TopAbs_COMPOUND && !IsManifoldShape(aSubShape) )
676             aNMCompound = TopoDS::Compound(aSubShape);
677           else if (aSubShape.ShapeType() == TopAbs_COMPOUND)
678             aListOfShapes.Append(aSubShape);
679           else 
680             aListOfManifoldShapes.Append(aSubShape);
681         }
682       }
683             
684       // Group manifold topology together.
685       // NOTE: there is no sense that initial Compound structure was lost as
686       //       group mode is set to 0 (no Assemblies are mapped)
687       for ( itL.Initialize(aListOfManifoldShapes); itL.More(); itL.Next() ) {
688         TopoDS_Shape aCurrentManiShape = itL.Value();
689         brepBuilder.Add(aManifoldCompound, aCurrentManiShape);
690       }
691
692     }
693
694     // Process only manifold topology in the current TransferShape invocation.
695     // Invoke TransferShape for non-manifold topology separately (see below)
696     theShape = aManifoldCompound;
697     
698     // List of items to transfer
699     Handle(TopTools_HSequenceOfShape) RepItemSeq = new TopTools_HSequenceOfShape();
700     // Non-manifold group to pass into TransferShape with each shape from RepItemSeq
701     Handle(TopTools_HSequenceOfShape) NonManifoldGroup = new TopTools_HSequenceOfShape();
702
703     // Transfer Solids to closed Shells. Prepare RepItemSeq & NonManifoldGroup
704     for ( TopoDS_Iterator iter(aNMCompound); iter.More(); iter.Next() ) {
705       TopoDS_Shape aSubShape = iter.Value();
706       if (aSubShape.ShapeType() == TopAbs_SOLID) {
707         for ( TopoDS_Iterator aSubIter(aSubShape); aSubIter.More(); aSubIter.Next() ) {
708           TopoDS_Shell aSubShell = TopoDS::Shell( aSubIter.Value() );
709           aSubShell.Closed(Standard_True);
710           RepItemSeq->Append(aSubShell);
711           NonManifoldGroup->Append(aSubShell);
712         }
713       }
714       else if (!isManifold && (aSubShape.ShapeType() == TopAbs_SHELL) ) {
715         RepItemSeq->Append(aSubShape);
716         NonManifoldGroup->Append(aSubShape);
717       } 
718       else
719         RepItemSeq->Append( iter.Value() );
720     }
721
722     Standard_Integer aNMItemsNb = RepItemSeq->Length();
723      
724     // In case of pure manifold topology do nothing; theShape is processed as usual (see below)
725     if (aNMItemsNb > 0) {
726
727       // Prepare SDR for non-manifold group. This SDR will be linked to NMSSR by means
728       // of TransferShape invocation. SDR is not created if there is no any manifold
729       // topology in the passed Compound. If topology is pure non-manifold, SDR0 (passed)
730       // is used
731       Handle(StepShape_ShapeDefinitionRepresentation) sdr;
732       if (isOnlyNonManifold)
733         sdr = SDR0;
734       else {
735         STEPConstruct_Part SDRTool;
736         SDRTool.MakeSDR( 0, myContext.GetProductName(), myContext.GetAPD()->Application() );
737         sdr = SDRTool.SDRValue();
738       }
739
740       aNMBinder = TransientResult(sdr);
741     
742       // Complete SDR with shape representations.
743       // NOTE: aNMBinder is connected now with this SDR. It will be added to the resulting
744       //       binder in the end of this invocation of TransferShape
745       for (Standard_Integer i = 1; i <= aNMItemsNb; i++) {
746         Handle(TransferBRep_ShapeMapper) mapper = TransferBRep::ShapeMapper( FP, RepItemSeq->Value(i) );
747         TransferShape(mapper, sdr, FP, NonManifoldGroup, Standard_False);
748       }
749
750       // Nothing else needed for pure non-manifold topology, return
751       if (isOnlyNonManifold)
752         return aNMBinder;
753    
754     }
755
756   }
757   // [END] Separate manifold topology from non-manifold in group mode 0 (ssv; 18.11.2010)
758
759   // create a list of items to translate
760   Handle(TopTools_HSequenceOfShape) RepItemSeq = new TopTools_HSequenceOfShape();
761   
762   // PTV 16.09.2002 OCC725 separate shape from solo vertices.
763   if (theShape.ShapeType() == TopAbs_COMPOUND) {
764     Standard_Integer countVrtx = 0;
765     Standard_Integer countSh = 0;
766     TopoDS_Compound aNewShape, aCompOfVrtx;
767     BRep_Builder aB;
768     aB.MakeCompound(aNewShape);
769     aB.MakeCompound(aCompOfVrtx);
770     TopoDS_Iterator anCompIt(theShape);
771     for (; anCompIt.More(); anCompIt.Next()) {
772       TopoDS_Shape aCurSh = anCompIt.Value();
773       if (aCurSh.ShapeType() != TopAbs_VERTEX) {
774         aB.Add(aNewShape, aCurSh);
775         countSh++;
776       }
777       else {
778         aB.Add(aCompOfVrtx, aCurSh);
779         countVrtx++;
780       }
781     }
782     // replace the shapes
783     if (countSh)
784       theShape = aNewShape;
785     if (countVrtx)
786       RepItemSeq->Append(aCompOfVrtx);
787   } 
788   else if (theShape.ShapeType() == TopAbs_VERTEX)
789     RepItemSeq->Append(theShape); // to translate one vertex
790   
791
792   if (theShape.ShapeType() == TopAbs_COMPOUND) {
793     TopExp_Explorer SolidExp, ShellExp, FaceExp;
794     if (mymode != STEPControl_GeometricCurveSet) {
795       for (SolidExp.Init(theShape, TopAbs_SOLID);
796            SolidExp.More();SolidExp.Next()) {
797         RepItemSeq->Append(TopoDS::Solid(SolidExp.Current()));
798       }
799       for (ShellExp.Init(theShape, TopAbs_SHELL, TopAbs_SOLID);
800            ShellExp.More();ShellExp.Next()) {
801         RepItemSeq->Append(TopoDS::Shell(ShellExp.Current()));
802       }
803       
804       for (FaceExp.Init(theShape, TopAbs_FACE, TopAbs_SHELL);
805            FaceExp.More();FaceExp.Next()) {
806         RepItemSeq->Append(TopoDS::Face(FaceExp.Current()));
807       }
808     }
809     else {
810       RepItemSeq->Append(theShape); //:j1
811     }
812     if(mymode == STEPControl_AsIs) {
813       TopExp_Explorer WireExp, EdgeExp;
814       for (WireExp.Init(theShape, TopAbs_WIRE, TopAbs_FACE);
815            WireExp.More();WireExp.Next()) 
816         RepItemSeq->Append(TopoDS::Wire(WireExp.Current()));
817       for (EdgeExp.Init(theShape, TopAbs_EDGE, TopAbs_WIRE);
818            EdgeExp.More();EdgeExp.Next()) 
819         RepItemSeq->Append(TopoDS::Edge(EdgeExp.Current()));
820     }
821     
822   }
823   else if (theShape.ShapeType() == TopAbs_SOLID) {
824     RepItemSeq->Append(TopoDS::Solid(theShape));
825   }
826   else if (theShape.ShapeType() == TopAbs_SHELL) {
827     RepItemSeq->Append(TopoDS::Shell(theShape));
828   }
829   else if (theShape.ShapeType() == TopAbs_FACE) {
830     RepItemSeq->Append(TopoDS::Face(theShape));
831   }
832   else if (mymode != STEPControl_GeometricCurveSet && mymode != STEPControl_AsIs) {
833     FP->AddFail(start,"The Shape is not a SOLID, nor a SHELL, nor a FACE");
834     return binder;
835   }
836   else RepItemSeq->Append (theShape);
837
838   //    COMPUTING 3D TOLERANCE
839   //    Either from Session, or Computed (Least,Average, or Greatest)
840   //    Then given to TopoDSToStep_Tool
841   Standard_Real Tol = UsedTolerance (mytoler,theShape);
842   
843   // Create a STEP-Entity for each TopoDS_Shape  
844   // according to the current StepModelMode
845   
846   Standard_Integer nbs = RepItemSeq->Length();
847   Handle(TColStd_HSequenceOfTransient) ItemSeq = 
848     new TColStd_HSequenceOfTransient();
849
850 //ptv 10.11.00: allow to write empty Compound:  if (GroupMode() >0)
851   ItemSeq->Append (myContext.GetDefaultAxis());
852   STEPControl_StepModelType trmode = mymode;
853   for (Standard_Integer i = 1; i <= nbs; i++) {
854     TopoDS_Shape xShape = RepItemSeq->Value(i);
855  
856     if(mymode == STEPControl_AsIs) {
857       switch(xShape.ShapeType()) {
858         case TopAbs_SOLID :  trmode = STEPControl_ManifoldSolidBrep;break;
859         case TopAbs_SHELL :  trmode = STEPControl_ShellBasedSurfaceModel; break;
860         case TopAbs_FACE : trmode = STEPControl_ShellBasedSurfaceModel;break;
861         default : trmode =STEPControl_GeometricCurveSet; break;
862       }
863     }
864     //:abv 24Jan99 CAX-IF TRJ3: expanded Shape Processing
865 //    TopoDS_Shape aShape = xShape;
866     // eliminate conical surfaces with negative semiangles
867 //    Handle(TopoDSToStep_ConicalSurfModif) CSM = new TopoDSToStep_ConicalSurfModif();
868 //    BRepTools_Modifier CSMT(aShape,CSM);
869 //    if ( CSMT.IsDone() ) aShape = CSMT.ModifiedShape ( aShape );
870 //    // eliminate indirect elementary surfaces
871 //    Handle(TopoDSToStep_DirectModification) DM = new TopoDSToStep_DirectModification();
872 //    BRepTools_Modifier DMT(aShape,DM);
873 //    if ( DMT.IsDone() ) aShape = DMT.ModifiedShape ( aShape );
874 ////    aShape = TopoDSToStep::DirectFaces(xShape);
875     Handle(Standard_Transient) info;
876     Standard_Real maxTol = Interface_Static::RVal("read.maxprecision.val");
877
878     // Fix only manifold shapes, do nothing with non-manifold topology as it is processed separately (ssv; 13.11.2010)
879     TopoDS_Shape aShape;
880     if (isManifold)
881       aShape = XSAlgo::AlgoContainer()->ProcessShape(xShape, Tol, maxTol, 
882                                                     "write.step.resource.name", 
883                                                     "write.step.sequence", info,
884                                                     FP->GetProgress() );
885     else
886       aShape = xShape;
887     
888     // create a STEP entity corresponding to shape
889     Handle(StepGeom_GeometricRepresentationItem) item;
890     switch (trmode)
891       {
892       case STEPControl_ManifoldSolidBrep:
893         {
894           if (aShape.ShapeType() == TopAbs_SOLID) {
895             TopoDS_Solid aSolid = TopoDS::Solid(aShape);
896
897             //:d6 abv 13 Mar 98: if solid has more than 1 shell, 
898             // try to treat it as solid with voids
899             Standard_Integer nbShells = 0;
900             for ( TopoDS_Iterator It ( aSolid ); It.More(); It.Next() ) 
901               if (It.Value().ShapeType() == TopAbs_SHELL) nbShells++;
902             if ( nbShells >1 ) {
903               TopoDSToStep_MakeBrepWithVoids MkBRepWithVoids(aSolid,FP);
904               MkBRepWithVoids.Tolerance() = Tol;
905               if (MkBRepWithVoids.IsDone()) {
906                 item = MkBRepWithVoids.Value();
907               }
908               else nbShells = 1; //smth went wrong; let it will be just Manifold
909             }
910             if ( nbShells ==1 ) {
911
912               TopoDSToStep_MakeManifoldSolidBrep MkManifoldSolidBrep(aSolid,FP);
913               MkManifoldSolidBrep.Tolerance() = Tol;
914               if (MkManifoldSolidBrep.IsDone()) {
915                 item = MkManifoldSolidBrep.Value();
916               }
917             }
918           }
919           else if (aShape.ShapeType() == TopAbs_SHELL) {
920             TopoDS_Shell aShell = TopoDS::Shell(aShape);
921             TopoDSToStep_MakeManifoldSolidBrep MkManifoldSolidBrep(aShell,FP);
922             MkManifoldSolidBrep.Tolerance() = Tol;
923             if (MkManifoldSolidBrep.IsDone()) {
924               item = MkManifoldSolidBrep.Value();
925             }
926           }
927           break;
928         }
929       case STEPControl_BrepWithVoids:
930         {
931           if (aShape.ShapeType() == TopAbs_SOLID) {
932             TopoDS_Solid aSolid = TopoDS::Solid(aShape);
933             TopoDSToStep_MakeBrepWithVoids MkBRepWithVoids(aSolid,FP);
934             MkBRepWithVoids.Tolerance() = Tol;
935             if (MkBRepWithVoids.IsDone()) {
936               item = MkBRepWithVoids.Value();
937             }
938           }
939           break;
940         }
941       case STEPControl_FacetedBrep:
942         {
943           TopoDSToStep_FacetedError facErr = TopoDSToStep_FacetedTool::CheckTopoDSShape(aShape);
944           if (facErr != TopoDSToStep_FacetedDone) {
945             FP->AddFail(start,"Error in Faceted Shape from TopoDS");
946             if (facErr == TopoDSToStep_SurfaceNotPlane) {
947               FP->AddFail(start,"-- The TopoDS_Face is not plane");
948             }
949             else if (facErr == TopoDSToStep_PCurveNotLinear) {
950               FP->AddFail(start,"-- The Face contains non linear PCurves");
951             }
952             return binder;
953           }
954           if (aShape.ShapeType() == TopAbs_SOLID) {
955             TopoDS_Solid aSolid = TopoDS::Solid(aShape);
956             TopoDSToStep_MakeFacetedBrep MkFacetedBrep(aSolid,FP);
957             MkFacetedBrep.Tolerance() = Tol;
958             if (MkFacetedBrep.IsDone()) {
959               item = MkFacetedBrep.Value();
960             }
961           }
962           break;
963         }
964       case STEPControl_FacetedBrepAndBrepWithVoids:
965         {
966           TopoDSToStep_FacetedError facErr = TopoDSToStep_FacetedTool::CheckTopoDSShape(aShape);
967           if (facErr != TopoDSToStep_FacetedDone) {
968             FP->AddFail(start,"Error in Faceted Shape from TopoDS");
969             if (facErr == TopoDSToStep_SurfaceNotPlane) {
970               FP->AddFail(start,"-- The TopoDS_Face is not plane");
971             }
972             else if (facErr == TopoDSToStep_PCurveNotLinear) {
973               FP->AddFail(start,"-- The Face contains non linear PCurves");
974             }
975             return binder;
976           }
977           if (aShape.ShapeType() == TopAbs_SOLID) {
978             TopoDS_Solid aSolid = TopoDS::Solid(aShape);
979             TopoDSToStep_MakeFacetedBrepAndBrepWithVoids 
980               MkFacetedBrepAndBrepWithVoids(aSolid,FP);
981             MkFacetedBrepAndBrepWithVoids.Tolerance() = Tol;
982             if (MkFacetedBrepAndBrepWithVoids.IsDone()) {
983               item = MkFacetedBrepAndBrepWithVoids.Value();
984             }
985           }
986           break;
987         }
988       case STEPControl_ShellBasedSurfaceModel:
989         {
990           if (aShape.ShapeType() == TopAbs_SOLID) {
991             TopoDS_Solid aSolid = TopoDS::Solid(aShape);
992             TopoDSToStep_MakeShellBasedSurfaceModel
993               MkShellBasedSurfaceModel(aSolid, FP);
994             MkShellBasedSurfaceModel.Tolerance() = Tol;
995             if (MkShellBasedSurfaceModel.IsDone()) {
996               item = MkShellBasedSurfaceModel.Value();
997             }
998           }
999           else if (aShape.ShapeType() == TopAbs_SHELL) {
1000             TopoDS_Shell aShell = TopoDS::Shell(aShape);
1001             // Non-manifold topology is stored via NMSSR containing series of SBSM (ssv; 13.11.2010)
1002             TopoDSToStep_MakeShellBasedSurfaceModel MkShellBasedSurfaceModel(aShell, FP);
1003             MkShellBasedSurfaceModel.Tolerance() = Tol;
1004             if (MkShellBasedSurfaceModel.IsDone()) {
1005               item = MkShellBasedSurfaceModel.Value();
1006             }
1007           }
1008           else if (aShape.ShapeType() == TopAbs_FACE) {
1009             TopoDS_Face aFace = TopoDS::Face(aShape);
1010             TopoDSToStep_MakeShellBasedSurfaceModel
1011               MkShellBasedSurfaceModel(aFace, FP);
1012             MkShellBasedSurfaceModel.Tolerance() = Tol;
1013             if (MkShellBasedSurfaceModel.IsDone()) {
1014               item = MkShellBasedSurfaceModel.Value();
1015             }
1016           }
1017           break;
1018         }
1019       case STEPControl_GeometricCurveSet:
1020         {
1021           TopoDSToStep_MakeGeometricCurveSet MkGeometricCurveSet(aShape,FP);
1022           MkGeometricCurveSet.Tolerance() = Tol;
1023           if (MkGeometricCurveSet.IsDone()) {
1024             item = MkGeometricCurveSet.Value();
1025           }
1026           // PTV 22.08.2002 OCC609 ------------------------- begin --------------------
1027           // modified by PTV 16.09.2002 OCC725
1028           else if (aShape.ShapeType() == TopAbs_COMPOUND || 
1029                    aShape.ShapeType() == TopAbs_VERTEX) {
1030             // it is compund with solo vertices.
1031             Standard_Integer aNbVrtx = 0;
1032             Standard_Integer curNb = 0;
1033             TopExp_Explorer anExp (aShape, TopAbs_VERTEX);
1034             for ( ; anExp.More(); anExp.Next() ) {
1035               if ( anExp.Current().ShapeType() != TopAbs_VERTEX )
1036                 continue;
1037               aNbVrtx++;
1038             }
1039             if ( aNbVrtx ) {
1040               // create new geometric curve set for all vertices
1041               Handle(StepShape_HArray1OfGeometricSetSelect) aGSS =
1042                 new StepShape_HArray1OfGeometricSetSelect(1,aNbVrtx);
1043               Handle(TCollection_HAsciiString) empty = new TCollection_HAsciiString("");
1044               Handle(StepShape_GeometricCurveSet) aGCSet =
1045                 new StepShape_GeometricCurveSet;
1046               aGCSet->SetName(empty);
1047               // iterates on compound with vertices and trances each vertex
1048               for ( anExp.ReInit() ; anExp.More(); anExp.Next() ) {
1049                 TopoDS_Shape aVertex = anExp.Current();
1050                 if ( aVertex.ShapeType() != TopAbs_VERTEX )
1051                   continue;
1052                 curNb++;
1053                 transferVertex (FP, aGSS, aVertex, curNb);
1054               } // end of iteration on compound with vertices.
1055               aGCSet->SetElements(aGSS);
1056               item = aGCSet;
1057             } // end of check that number of vertices is not null
1058           }
1059           // PTV 22.08.2002 OCC609-------------------------  end  --------------------
1060           break;
1061         }
1062       default: break;
1063       }
1064     if ( item.IsNull() ) continue;
1065
1066     // add resulting item to the FP
1067     ItemSeq->Append(item);
1068     Handle(TransferBRep_ShapeMapper) submapper;
1069     if ( xShape.IsSame ( mapper->Value() ) ) 
1070       submapper = Handle(TransferBRep_ShapeMapper)::DownCast ( start );
1071     if ( submapper.IsNull() ) submapper = TransferBRep::ShapeMapper (FP,xShape);
1072     Handle(Transfer_Binder) subbind = FP->Find ( submapper );
1073     if ( subbind.IsNull() ) {
1074       subbind = TransientResult ( item );
1075       FP->Bind ( submapper, subbind );
1076     }
1077     else subbind->AddResult ( TransientResult ( item ) );
1078
1079     //:abv 24Jan99 CAX-IF TRJ3: Update FinderProcess map to take into account shape processing
1080 //    UpdateMap ( xShape, CSMT, DMT, FP );
1081     XSAlgo::AlgoContainer()->MergeTransferInfo(FP, info);
1082   }
1083   
1084   // - Make Shape Representation 
1085   Standard_Integer nCc1 = ItemSeq->Length();
1086   if (nCc1 < 1) {
1087     FP->AddFail(start,"The Shape has not the appropriate type");
1088     return binder;
1089   }
1090   Handle(StepShape_ShapeRepresentation) shapeRep;
1091   if ( theShape.ShapeType() == TopAbs_SHAPE ) { // for external references
1092     shapeRep = new StepShape_ShapeRepresentation;
1093   }
1094   else {
1095     switch (mymode) {
1096     case STEPControl_ManifoldSolidBrep:
1097       shapeRep = new StepShape_AdvancedBrepShapeRepresentation;
1098       break;
1099     case STEPControl_FacetedBrep:
1100       shapeRep = new StepShape_FacetedBrepShapeRepresentation;
1101       break;
1102     // NOTE: STEPControl_AsIs mode is normally used to transfer non-manifold topology.
1103     //       However, as ShellBasedSurfaceModel is used in non-manifold processing
1104     //       internally, STEPControl_ShellBasedSurfaceModel is also adjusted to
1105     //       be able to work with non-manifold cases
1106     case STEPControl_ShellBasedSurfaceModel:
1107       if (isManifold)
1108         shapeRep = new StepShape_ManifoldSurfaceShapeRepresentation;
1109       else {
1110         Standard_Boolean isNewNMSSRCreated;
1111         shapeRep = this->getNMSSRForGroup(shapeGroup, FP, isNewNMSSRCreated);
1112         useExistingNMSSR = !isNewNMSSRCreated;
1113       }
1114       break;
1115     case STEPControl_GeometricCurveSet:
1116       shapeRep = new StepShape_GeometricallyBoundedWireframeShapeRepresentation;
1117       break;
1118     case STEPControl_AsIs :
1119     {
1120       if(nbs == 1) {
1121         if(trmode == STEPControl_ManifoldSolidBrep)
1122           shapeRep = new StepShape_AdvancedBrepShapeRepresentation;
1123         else if(trmode == STEPControl_ShellBasedSurfaceModel)
1124           // Process non-manifold topology separately (ssv; 13.11.2010)
1125           if (isManifold)
1126             shapeRep = new StepShape_ManifoldSurfaceShapeRepresentation;
1127           else {
1128             Standard_Boolean isNewNMSSRCreated;
1129             shapeRep = this->getNMSSRForGroup(shapeGroup, FP, isNewNMSSRCreated);
1130             useExistingNMSSR = !isNewNMSSRCreated;
1131           }
1132         else if(trmode == STEPControl_GeometricCurveSet)
1133           shapeRep = new StepShape_GeometricallyBoundedWireframeShapeRepresentation;
1134         else if(trmode ==STEPControl_FacetedBrep)
1135           shapeRep = new StepShape_FacetedBrepShapeRepresentation; 
1136       }
1137       else shapeRep = new StepShape_ShapeRepresentation;
1138     }
1139       break;
1140     default: break;
1141     }
1142   }
1143   if(shapeRep.IsNull()) {
1144     Handle(Transfer_Binder) resb;
1145     return resb;
1146   }
1147     
1148   Handle(StepRepr_HArray1OfRepresentationItem) items =
1149     new StepRepr_HArray1OfRepresentationItem(1,nCc1);
1150
1151   for (Standard_Integer rep = 1; rep <= nCc1; rep++) {
1152     Handle(StepRepr_RepresentationItem) repit = 
1153       GetCasted(StepRepr_RepresentationItem, ItemSeq->Value(rep));
1154     items->SetValue(rep,repit);
1155   }
1156   Standard_Integer ap = Interface_Static::IVal("write.step.schema");
1157   Transfer_SequenceOfBinder aSeqBindRelation;
1158   if(ap == 3 && nbs > 1) {
1159     Standard_Integer j = 1;
1160     if(items->Value(j)->IsKind(STANDARD_TYPE(StepGeom_Axis2Placement3d))) {
1161       Handle(StepRepr_HArray1OfRepresentationItem) axis =
1162         new StepRepr_HArray1OfRepresentationItem(1,1);
1163       axis->SetValue(1,items->Value(j++));
1164       shapeRep->SetItems(axis);
1165     }
1166     for (; j <= items->Length(); j++) {
1167       
1168       Handle(StepShape_ShapeRepresentation) ShapeRepr1;
1169       if(items->Value(j)->IsKind(STANDARD_TYPE(StepShape_ManifoldSolidBrep)))
1170          ShapeRepr1 = new StepShape_AdvancedBrepShapeRepresentation;
1171       else if(items->Value(j)->IsKind(STANDARD_TYPE(StepShape_ShellBasedSurfaceModel))) 
1172         ShapeRepr1 = new StepShape_ManifoldSurfaceShapeRepresentation;
1173       else if(items->Value(j)->IsKind(STANDARD_TYPE(StepShape_GeometricCurveSet)))
1174         ShapeRepr1 = new StepShape_GeometricallyBoundedWireframeShapeRepresentation;
1175       else if (items->Value(j)->IsKind(STANDARD_TYPE(StepShape_FacetedBrep)))
1176         ShapeRepr1 = new StepShape_FacetedBrepShapeRepresentation;
1177       else ShapeRepr1 = new StepShape_ShapeRepresentation;
1178       
1179       Handle(StepRepr_HArray1OfRepresentationItem) repr1 = new StepRepr_HArray1OfRepresentationItem(1,2);
1180       repr1->SetValue(1,myContext.GetDefaultAxis());
1181       repr1->SetValue(2,items->Value(j));
1182       ShapeRepr1->SetItems(repr1);
1183       STEPConstruct_UnitContext mk1;
1184       mk1.Init(Tol);
1185       ShapeRepr1->SetContextOfItems(mk1.Value());  // la tolerance, voir au debut
1186       ShapeRepr1->SetName (new TCollection_HAsciiString(""));
1187       
1188       Handle(StepRepr_ShapeRepresentationRelationship) aShapeRel = new StepRepr_ShapeRepresentationRelationship;
1189       Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString("");
1190       Handle(TCollection_HAsciiString) aDescr = new TCollection_HAsciiString("");
1191       aShapeRel->SetName(aName);
1192       aShapeRel->SetDescription(aDescr);
1193       aShapeRel->SetRep2(shapeRep);
1194       aShapeRel->SetRep1(ShapeRepr1);
1195       
1196       aSeqBindRelation.Append(TransientResult (aShapeRel));
1197     }
1198   }
1199   else {
1200     if (!useExistingNMSSR)
1201       shapeRep->SetItems(items);
1202     else {
1203       // Add new representation item to the NMSSR's existing collection (ssv; 13.11.2010)
1204       Handle(StepRepr_HArray1OfRepresentationItem) oldItems = shapeRep->Items();
1205       Handle(StepRepr_HArray1OfRepresentationItem) newItems = 
1206         new StepRepr_HArray1OfRepresentationItem(1, oldItems->Length() + 1);
1207       Standard_Integer el = 1;
1208       for (Standard_Integer i = 1; i <= oldItems->Length(); i++)
1209         newItems->SetValue( el++, oldItems->Value(i) );
1210       newItems->SetValue( el, items->Value( items->Length() ) );
1211       shapeRep->SetItems(newItems);
1212     }
1213   }
1214
1215   // init representation
1216   STEPConstruct_UnitContext mk;
1217   mk.Init(Tol);
1218   shapeRep->SetContextOfItems(mk.Value());  // la tolerance, voir au debut
1219   shapeRep->SetName (new TCollection_HAsciiString(""));
1220
1221   // Create SDR (only once for non-manifold group)
1222   if (!useExistingNMSSR) {
1223     SDR0->SetUsedRepresentation (shapeRep);
1224     // create binder for SR and attach to it binder for RepItem (if exists)
1225     Handle(Transfer_Binder) resbind = TransientResult(shapeRep);
1226     binder = FP->Find(start);
1227     if ( ! binder.IsNull() ) {
1228       resbind->AddResult ( binder );
1229       FP->Rebind(start,resbind);
1230       //binder->AddResult ( resbind );
1231       //resbind = binder;
1232     }
1233     for(Standard_Integer k = 1; k <= aSeqBindRelation.Length(); k++)
1234       resbind->AddResult(aSeqBindRelation.Value(k));
1235
1236     // Add SDR for non-manifold topology in group mode 0 (ssv; 18.11.2010)
1237     if ( !aNMBinder.IsNull() )
1238       resbind->AddResult(aNMBinder);
1239
1240     return resbind;
1241   } else return FP->Find(start);
1242
1243 }
1244
1245 //=======================================================================
1246 //function : TransferCompound
1247 //    ####    TRANSFER COMPOUND AS (SUB-)ASSEMBLY
1248 //purpose  : 
1249 //=======================================================================
1250
1251 Handle(Transfer_Binder) STEPControl_ActorWrite::TransferCompound (const Handle(Transfer_Finder)& start,
1252                                                                   const Handle(StepShape_ShapeDefinitionRepresentation)& SDR0,
1253                                                                   const Handle(Transfer_FinderProcess)& FP)
1254 {
1255   Handle(TransferBRep_ShapeMapper) mapper = Handle(TransferBRep_ShapeMapper)::DownCast(start);
1256   Handle(Transfer_Binder) binder;
1257   if (mapper.IsNull()) return binder;
1258   TopoDS_Shape theShape = mapper->Value();
1259
1260   // Inspect non-manifold topology case (ssv; 10.11.2010)
1261   Standard_Boolean isNMMode = Interface_Static::IVal("write.step.nonmanifold");
1262   Standard_Boolean isManifold;
1263   if (isNMMode)
1264     isManifold = IsManifoldShape(theShape);
1265   else
1266     isManifold = Standard_True;
1267
1268   // get a sequence of components (subshapes)
1269   Handle(TopTools_HSequenceOfShape) RepItemSeq = new TopTools_HSequenceOfShape();
1270   // Prepare a collection for non-manifold group of shapes
1271   Handle(TopTools_HSequenceOfShape) NonManifoldGroup = new TopTools_HSequenceOfShape();
1272   // PTV OCC725 17.09.2002 -- begin --
1273   Standard_Integer nbFreeVrtx = 0;
1274   TopoDS_Compound aCompOfVrtx;
1275   BRep_Builder aB;
1276   aB.MakeCompound(aCompOfVrtx);
1277  
1278   #ifdef DEB
1279   if (!isManifold)
1280     cout << "Exploding Solids to Shells if any..." << endl;
1281   #endif
1282
1283   for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
1284     TopoDS_Shape aSubShape = iter.Value();
1285     if (aSubShape.ShapeType() != TopAbs_VERTEX) {
1286
1287       // Store non-manifold topology as shells (ssv; 10.11.2010)
1288       if (!isManifold && aSubShape.ShapeType() == TopAbs_SOLID) {
1289         for ( TopoDS_Iterator aSubIter(aSubShape); aSubIter.More(); aSubIter.Next() ) {
1290           TopoDS_Shell aSubShell = TopoDS::Shell( aSubIter.Value() );
1291           aSubShell.Closed(Standard_True);
1292           RepItemSeq->Append(aSubShell);
1293           NonManifoldGroup->Append(aSubShell);
1294         }
1295       } 
1296       else if (!isManifold && (aSubShape.ShapeType() == TopAbs_SHELL) ) {
1297         RepItemSeq->Append(aSubShape);
1298         NonManifoldGroup->Append(aSubShape);
1299       }
1300       else
1301         RepItemSeq->Append(aSubShape);
1302
1303       continue;
1304     }
1305     aB.Add(aCompOfVrtx, iter.Value());
1306     nbFreeVrtx++;
1307   }
1308   if (nbFreeVrtx)
1309     RepItemSeq->Append (aCompOfVrtx);
1310
1311   // PTV OCC725 17.09.2002 -- end --
1312   
1313   // Constitution : liste d axes, le premier est l origine, les suivants : 1
1314   // par sous-item
1315   Handle(StepShape_ShapeRepresentation) shapeRep =
1316     Handle(StepShape_ShapeRepresentation)::DownCast(SDR0->UsedRepresentation());
1317   if ( shapeRep.IsNull() ) {
1318     shapeRep = new StepShape_ShapeRepresentation;
1319     SDR0->SetUsedRepresentation(shapeRep);  // to be used by MakeItem
1320   }
1321   binder = TransientResult(SDR0); // set SDR as first item in order to be found first (but not SDR of subshape!)
1322   binder->AddResult ( TransientResult(shapeRep) );
1323
1324   // translate components
1325   Standard_Integer i, nbs = RepItemSeq->Length();
1326   Handle(TColStd_HSequenceOfTransient) ItemSeq = new TColStd_HSequenceOfTransient();
1327   ItemSeq->Append (myContext.GetDefaultAxis());
1328   myContext.NextLevel();
1329   for ( i = 1; i <= nbs; i ++) {
1330     Handle(TransferBRep_ShapeMapper) subs = TransferBRep::ShapeMapper (FP,RepItemSeq->Value(i));
1331     Handle(StepGeom_Axis2Placement3d) AX1;
1332     
1333     Handle(Transfer_Binder) bnd = TransferSubShape(subs, SDR0, AX1, FP, NonManifoldGroup, isManifold);
1334
1335     if (!AX1.IsNull()) ItemSeq->Append (AX1);
1336     // copy binders so as to have all roots in upper binder, but do not conflict
1337     while ( !bnd.IsNull() ) {
1338       Handle(Transfer_SimpleBinderOfTransient) bx = 
1339         Handle(Transfer_SimpleBinderOfTransient)::DownCast(bnd);
1340       if ( !bx.IsNull() )
1341         // Single SDR is created for a non-manifold group (ssv: 12.11.2010)
1342         if (!isManifold && i > 1)
1343           break;
1344         else
1345           binder->AddResult( TransientResult( bx->Result() ) );
1346       bnd = bnd->NextResult();
1347     }
1348   }
1349   myContext.PrevLevel();
1350
1351   Standard_Integer nsub = ItemSeq->Length();
1352   Handle(StepRepr_HArray1OfRepresentationItem) items =
1353     new StepRepr_HArray1OfRepresentationItem(1,nsub);
1354
1355   // initialize representation
1356   for (Standard_Integer rep = 1; rep <= nsub; rep++)
1357     items->SetValue(rep,GetCasted(StepRepr_RepresentationItem, ItemSeq->Value(rep)));
1358   shapeRep->SetItems(items);
1359   Standard_Real Tol = UsedTolerance (mytoler,theShape);
1360   STEPConstruct_UnitContext mk;
1361   mk.Init(Tol);
1362   shapeRep->SetContextOfItems(mk.Value());  // la tolerance, voir au debut
1363   shapeRep->SetName (new TCollection_HAsciiString(""));
1364
1365   // set it to SDR
1366 //  SDR0->SetUsedRepresentation (shapeRep);
1367
1368   return binder;
1369 }
1370
1371 //=======================================================================
1372 //function : TransferSubShape
1373 //purpose  : 
1374 //=======================================================================
1375
1376 Handle(Transfer_Binder)  STEPControl_ActorWrite::TransferSubShape (const Handle(Transfer_Finder)& start,
1377                                                                    const Handle(StepShape_ShapeDefinitionRepresentation)& SDR0,
1378                                                                    Handle(StepGeom_Axis2Placement3d)& AX1,
1379                                                                    const Handle(Transfer_FinderProcess)& FP,
1380                                                                    const Handle(TopTools_HSequenceOfShape)& shapeGroup,
1381                                                                    const Standard_Boolean isManifold)
1382 {
1383   Handle(TransferBRep_ShapeMapper) mapper = Handle(TransferBRep_ShapeMapper)::DownCast(start);
1384   if (mapper.IsNull()) return NullResult();
1385   TopoDS_Shape shape = mapper->Value();
1386
1387   //   SHAPE EN POSITION VENANT D UN ASSEMBLAGE
1388   //   Il faut alors distinguer la transformation de la shape meme
1389   //   laquelle est consideree a l origine, puis transferee
1390   //   A part, un item decrivant une occurence en position est cree
1391   //   SINON, la shape est prise et transferee telle quelle
1392   TopoDS_Shape sh0 = shape;
1393   gp_Trsf aLoc;
1394   if ( GroupMode() >0) {
1395     TopLoc_Location shloc = shape.Location();
1396     aLoc = shloc.Transformation();
1397     TopLoc_Location shident;
1398     sh0.Location (shident);
1399     mapper = TransferBRep::ShapeMapper(FP,sh0);
1400     mapper->SameAttributes (start);
1401   }
1402
1403   Handle(Transfer_Binder) resbind = FP->Find(mapper);
1404   Handle(StepShape_ShapeDefinitionRepresentation) sdr;
1405 //  Handle(StepShape_ShapeRepresentation) resultat;
1406   STEPConstruct_Part SDRTool;  
1407
1408   // Already SDR and SR available : take them as are
1409   Standard_Boolean iasdr = FP->GetTypedTransient
1410     (resbind,STANDARD_TYPE(StepShape_ShapeDefinitionRepresentation),sdr);
1411   if ( iasdr ) SDRTool.ReadSDR ( sdr ); 
1412   else { 
1413     SDRTool.MakeSDR ( 0, myContext.GetProductName(), myContext.GetAPD()->Application() );
1414     sdr = SDRTool.SDRValue();
1415   }
1416 //  resultat = GetCasted(StepShape_ShapeRepresentation,sdr->UsedRepresentation());
1417
1418   // if shape itself not yet translated, do it now
1419   //:abv 20.05.02: see comment in TransferShape(): added "! iasdr ||"
1420   Handle(Transfer_Binder) resprod = TransientResult(sdr);  //KA - OCC7141(skl 10.11.2004)
1421   if ( ! iasdr || resbind.IsNull() ) {
1422     resbind = TransferShape(mapper, sdr, FP, shapeGroup, isManifold);
1423     Handle(Transfer_Binder) oldbind = FP->Find ( mapper );
1424     if ( ! oldbind.IsNull() && !resbind.IsNull()) resbind->AddResult ( oldbind );
1425     FP->Bind (mapper,resbind);
1426     resprod=resbind; //KA - OCC7141(skl 10.11.2004)
1427   }
1428
1429   // A new resbind may have been produced
1430 //  DeclareAndCast(Transfer_SimpleBinderOfTransient,restrans,resbind);
1431 //  if (restrans.IsNull()) return resbind;
1432 //  FP->GetTypedTransient (resbind,STANDARD_TYPE(StepShape_ShapeRepresentation),resultat);
1433 //  sdr->SetUsedRepresentation(resultat);  // to be used by MakeItem
1434
1435   // make location for assembly placement
1436   GeomToStep_MakeAxis2Placement3d mkax (aLoc);
1437   Handle(StepGeom_Axis2Placement3d) AxLoc = mkax.Value();
1438   AX1 = AxLoc;
1439
1440   // create assembly structures (CDSR, NAUO etc.)
1441   STEPConstruct_Assembly mkitem;
1442   mkitem.Init (sdr,SDR0,myContext.GetDefaultAxis(),AxLoc);
1443   mkitem.MakeRelationship ();
1444   Handle(TColStd_HSequenceOfTransient) roots = myContext.GetRootsForAssemblyLink ( mkitem );
1445
1446   // add roots corresponding to assembly and product structures to binder
1447   //Handle(Transfer_Binder) resprod = resbind; //KA - OCC7141(skl 10.11.2004)
1448   //KA: we need only the current subshape in resprod, since the binder is copied
1449   //    in Transfershape which calls Transfersubshape   [ OCC7141(skl 10.11.2004) ]
1450   if ( ! iasdr ) {
1451     resprod->AddResult ( TransientResult ( SDRTool.SDRValue() ) );
1452     resbind->AddResult ( TransientResult ( SDRTool.SDRValue() ) ); //KA - OCC7141(skl 10.11.2004)
1453     roots->Append ( myContext.GetRootsForPart ( SDRTool ) );
1454   }
1455   for ( Standard_Integer i=1; i <= roots->Length(); i++ ) {
1456     resprod->AddResult ( TransientResult ( roots->Value(i) ) );
1457     resbind->AddResult ( TransientResult ( roots->Value(i) ) );  //KA - OCC7141(skl 10.11.2004)
1458   }
1459   myContext.NextIndex();
1460
1461   //FP->Bind (mapper,resprod); //KA - OCC7141(skl 10.11.2004)
1462
1463   // abv 16.10.00: bind CDSR (et al) to located shape in order to be able to track instances
1464   if ( mapper != start ) {
1465     Handle(Transfer_Binder) bnd = FP->Find ( start );
1466     for ( Standard_Integer j=1; j <= roots->Length(); j++ ) 
1467       if ( bnd.IsNull() ) bnd = TransientResult ( roots->Value(j) );
1468       else bnd->AddResult ( TransientResult ( roots->Value(j) ) );
1469     FP->Bind ( start, bnd );
1470   }
1471   
1472   return resprod;
1473 }