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