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