0026500: Add the possibility to save only part of shapes from XCAF document in IGES...
[occt.git] / src / IGESCAFControl / IGESCAFControl_Writer.cxx
1 // Created on: 2000-08-17
2 // Created by: Andrey BETENEV
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <IGESCAFControl.hxx>
17 #include <IGESCAFControl_Writer.hxx>
18 #include <IGESData_IGESEntity.hxx>
19 #include <IGESData_IGESModel.hxx>
20 #include <IGESData_NameEntity.hxx>
21 #include <IGESGraph_Color.hxx>
22 #include <IGESGraph_DefinitionLevel.hxx>
23 #include <IGESSolid_Face.hxx>
24 #include <NCollection_DataMap.hxx>
25 #include <Standard_Transient.hxx>
26 #include <TCollection_AsciiString.hxx>
27 #include <TCollection_HAsciiString.hxx>
28 #include <TColStd_HSequenceOfExtendedString.hxx>
29 #include <TDataStd_Name.hxx>
30 #include <TDF_ChildIterator.hxx>
31 #include <TDF_Label.hxx>
32 #include <TDF_LabelSequence.hxx>
33 #include <TDocStd_Document.hxx>
34 #include <TopAbs.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <TopoDS.hxx>
37 #include <TopoDS_Face.hxx>
38 #include <TopoDS_Iterator.hxx>
39 #include <TopoDS_Shape.hxx>
40 #include <TopTools_SequenceOfShape.hxx>
41 #include <Transfer_FinderProcess.hxx>
42 #include <Transfer_TransientListBinder.hxx>
43 #include <TransferBRep.hxx>
44 #include <TransferBRep_ShapeMapper.hxx>
45 #include <XCAFDoc_ColorTool.hxx>
46 #include <XCAFDoc_DocumentTool.hxx>
47 #include <XCAFDoc_LayerTool.hxx>
48 #include <XCAFDoc_ShapeTool.hxx>
49 #include <XCAFPrs.hxx>
50 #include <XCAFPrs_Style.hxx>
51 #include <XSControl_WorkSession.hxx>
52
53 namespace
54 {
55   typedef NCollection_DataMap<TopoDS_Shape, TCollection_ExtendedString> DataMapOfShapeNames;
56
57   void  CollectShapeNames (const TDF_Label& theLabel,
58                            const TopLoc_Location& theLocation,
59                            const Handle(TDataStd_Name)& thePrevName,
60                            DataMapOfShapeNames& theMapOfShapeNames)
61   {
62     Standard_Boolean hasReferredShape = Standard_False;
63     Standard_Boolean hasComponents    = Standard_False;
64     TDF_Label aReferredLabel;
65
66     Handle(TDataStd_Name) aName;
67     theLabel.FindAttribute (TDataStd_Name::GetID(), aName);
68
69     if ( XCAFDoc_ShapeTool::GetReferredShape ( theLabel, aReferredLabel ) )
70     {
71       TopLoc_Location aSubLocation = theLocation.Multiplied ( XCAFDoc_ShapeTool::GetLocation ( theLabel ) );
72       CollectShapeNames (aReferredLabel, aSubLocation, aName, theMapOfShapeNames);
73       hasReferredShape = Standard_True;
74     }
75
76     TDF_LabelSequence aSeq;
77     if (XCAFDoc_ShapeTool::GetComponents (theLabel, aSeq))
78     {
79       for (Standard_Integer anIter = 1; anIter <= aSeq.Length(); anIter++)
80       {
81         CollectShapeNames (aSeq.Value (anIter), theLocation, aName, theMapOfShapeNames );
82       }
83       hasComponents = Standard_True;
84     }
85
86     aSeq.Clear();
87     if (XCAFDoc_ShapeTool::GetSubShapes (theLabel, aSeq))
88     {
89       for (Standard_Integer anIter = 1; anIter <= aSeq.Length(); anIter++)
90       {
91         TopoDS_Shape aShape;
92         if (!XCAFDoc_ShapeTool::GetShape (aSeq.Value (anIter), aShape)) continue;
93         if (!aSeq.Value (anIter).FindAttribute (TDataStd_Name::GetID(), aName)) continue;
94         theMapOfShapeNames.Bind (aShape, aName->Get());
95       }
96     }
97
98     if (!hasReferredShape && !hasComponents)
99     {
100       TopoDS_Shape aShape;
101       if (!XCAFDoc_ShapeTool::GetShape (theLabel, aShape)) return;
102       aShape.Move (theLocation);
103       theMapOfShapeNames.Bind (aShape, thePrevName->Get());
104     }
105   }
106 }
107
108 //=======================================================================
109 //function : IGESCAFControl_Writer
110 //purpose  : 
111 //=======================================================================
112
113 IGESCAFControl_Writer::IGESCAFControl_Writer () :
114        myColorMode( Standard_True ),
115        myNameMode ( Standard_True ),
116        myLayerMode( Standard_True )
117 {
118 }
119
120 //=======================================================================
121 //function : IGESCAFControl_Writer
122 //purpose  : 
123 //=======================================================================
124
125 IGESCAFControl_Writer::IGESCAFControl_Writer (const Handle(XSControl_WorkSession)& WS,
126                                               const Standard_Boolean /*scratch*/ )
127 {
128   // this code does things in a wrong way, it should be vice-versa
129   WS->SetModel ( Model() );
130   WS->SetMapWriter ( TransferProcess() );
131   myColorMode = Standard_True;
132   myNameMode = Standard_True;
133   myLayerMode = Standard_True;
134   
135 //  SetWS (WS,scratch); // this should be the only required command here
136 }
137
138 //=======================================================================
139 //function : Transfer
140 //purpose  : 
141 //=======================================================================
142
143 Standard_Boolean IGESCAFControl_Writer::Transfer (const Handle(TDocStd_Document) &doc)
144 {  
145   // translate free top-level shapes of the DECAF document
146   Handle(XCAFDoc_ShapeTool) STool = XCAFDoc_DocumentTool::ShapeTool( doc->Main() );
147   if ( STool.IsNull() ) return Standard_False;
148
149   TDF_LabelSequence labels;
150   STool->GetFreeShapes ( labels );
151   return Transfer (labels);
152 }  
153
154 //=======================================================================
155 //function : Transfer
156 //purpose  : 
157 //=======================================================================
158
159 Standard_Boolean IGESCAFControl_Writer::Transfer (const TDF_Label& label)
160 {
161   TDF_LabelSequence labels;
162   labels.Append( label );
163   return Transfer( labels );
164 }
165
166 //=======================================================================
167 //function : Transfer
168 //purpose  : 
169 //=======================================================================
170
171 Standard_Boolean IGESCAFControl_Writer::Transfer (const TDF_LabelSequence& labels)
172 {  
173   if ( labels.Length() <=0 ) return Standard_False;
174   for ( Standard_Integer i=1; i <= labels.Length(); i++ ) {
175     TopoDS_Shape shape = XCAFDoc_ShapeTool::GetShape ( labels.Value(i) );
176     if ( ! shape.IsNull() ) 
177       AddShape ( shape );
178 //      IGESControl_Writer::Transfer ( shape );
179   }
180   
181   // write colors
182   if ( GetColorMode() )
183     WriteAttributes ( labels );
184
185   // write layers
186   if ( GetLayerMode() )
187     WriteLayers ( labels );
188   
189   // write names
190   if ( GetNameMode() )
191     WriteNames( labels );
192   
193   // refresh graph
194 //  WS()->ComputeGraph ( Standard_True );
195   ComputeModel();
196   
197   return Standard_True;
198 }
199
200 //=======================================================================
201 //function : Perform
202 //purpose  : 
203 //=======================================================================
204
205 Standard_Boolean IGESCAFControl_Writer::Perform (const Handle(TDocStd_Document) &doc,
206                                                  const Standard_CString filename)
207 {
208   if ( ! Transfer ( doc ) ) return Standard_False;
209   return Write ( filename ) == IFSelect_RetDone;
210 }
211   
212 //=======================================================================
213 //function : Perform
214 //purpose  : 
215 //=======================================================================
216
217 Standard_Boolean IGESCAFControl_Writer::Perform (const Handle(TDocStd_Document) &doc,
218                                                  const TCollection_AsciiString &filename)
219 {
220   if ( ! Transfer ( doc ) ) return Standard_False;
221   return Write ( filename.ToCString() ) == IFSelect_RetDone;
222 }
223   
224 //=======================================================================
225 //function : WriteAttributes
226 //purpose  : 
227 //=======================================================================
228
229 Standard_Boolean IGESCAFControl_Writer::WriteAttributes (const TDF_LabelSequence& labels) 
230 {
231   // Iterate on labels
232   if ( labels.Length() <=0 ) return Standard_False;
233   for ( Standard_Integer i=1; i <= labels.Length(); i++ ) {
234     TDF_Label L = labels.Value(i);
235
236     // collect color settings
237     XCAFPrs_DataMapOfShapeStyle settings;
238     TopLoc_Location loc;
239     XCAFPrs::CollectStyleSettings ( L, loc, settings );
240     if ( settings.Extent() <=0 ) continue;
241     
242     // get a target shape and try to find corresponding context
243     // (all the colors set under that label will be put into that context)
244     TopoDS_Shape S;
245     if ( ! XCAFDoc_ShapeTool::GetShape ( L, S ) ) continue;
246         
247     // iterate on subshapes and create IGES styles 
248     XCAFPrs_DataMapOfStyleTransient colors;
249     TopTools_MapOfShape Map;
250     const XCAFPrs_Style inherit;
251     MakeColors ( S, settings, colors, Map, inherit );
252   }
253   
254   return Standard_True;
255 }
256
257 //=======================================================================
258 //function : MakeColors
259 //purpose  : 
260 //=======================================================================
261
262 void IGESCAFControl_Writer::MakeColors (const TopoDS_Shape &S, 
263                                         const XCAFPrs_DataMapOfShapeStyle &settings,
264                                         XCAFPrs_DataMapOfStyleTransient &colors,
265                                         TopTools_MapOfShape &Map,
266                                         const XCAFPrs_Style &inherit) 
267 {
268   // skip already processed shapes
269   if ( ! Map.Add ( S ) ) return;
270   
271   // check if shape has its own style (or inherits from ancestor)
272   XCAFPrs_Style style = inherit;
273   if ( settings.IsBound(S) ) {
274     XCAFPrs_Style own = settings.Find(S);
275     if ( own.IsSetColorCurv() ) style.SetColorCurv ( own.GetColorCurv() );
276     if ( own.IsSetColorSurf() ) style.SetColorSurf ( own.GetColorSurf() );
277   }
278   
279   // analyze whether current entity should get a color 
280   Standard_Boolean hasColor = Standard_False;
281   Quantity_Color col;
282   if ( S.ShapeType() == TopAbs_FACE  || S.ShapeType() == TopAbs_SOLID) {
283     if ( style.IsSetColorSurf() ) {
284       hasColor = Standard_True;
285       col = style.GetColorSurf();
286     }
287   }
288   else if ( S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE ) {
289     if ( style.IsSetColorCurv() ) {
290       hasColor = Standard_True;
291       col = style.GetColorCurv();
292     }
293   }
294   
295   // if color has to be assigned, try to do this
296   if ( hasColor ) {
297     Handle(IGESGraph_Color) colent;
298     Standard_Integer rank = IGESCAFControl::EncodeColor ( col );
299     if ( ! rank ) {
300       XCAFPrs_Style c; // style used as key in the map
301       c.SetColorSurf ( col );
302       if ( colors.IsBound ( c ) ) {
303         colent = Handle(IGESGraph_Color)::DownCast ( colors.Find(c) );
304       }
305       else {
306         Handle(TCollection_HAsciiString) str = 
307           new TCollection_HAsciiString ( col.StringName ( col.Name() ) );
308         colent = new IGESGraph_Color;
309         colent->Init ( col.Red() * 100., col.Green() * 100., col.Blue() * 100., str );
310         AddEntity ( colent );
311         colors.Bind ( c, colent );
312       }
313     }
314     Handle(Transfer_FinderProcess) FP = TransferProcess();
315     Handle(IGESData_IGESEntity) ent;
316     Handle(TransferBRep_ShapeMapper) mapper = TransferBRep::ShapeMapper ( FP, S );
317     if ( FP->FindTypedTransient ( mapper, STANDARD_TYPE(IGESData_IGESEntity), ent ) ) {
318       ent->InitColor ( colent, rank );
319       Handle(IGESSolid_Face) ent_f = Handle(IGESSolid_Face)::DownCast(ent);
320       if (!ent_f.IsNull())
321       {
322         if (!ent_f->Surface().IsNull())
323           ent_f->Surface()->InitColor ( colent, rank );
324       }
325     }
326     else {
327       // may be S was splited during shape process
328       Handle(Transfer_Binder) bnd = FP->Find ( mapper );
329       if ( ! bnd.IsNull() ) {
330         Handle(Transfer_TransientListBinder) TransientListBinder =
331           //Handle(Transfer_TransientListBinder)::DownCast( bnd->Next(Standard_True) );
332           Handle(Transfer_TransientListBinder)::DownCast( bnd );
333         Standard_Integer i=0, nb=0;
334         if (! TransientListBinder.IsNull() ) {
335           nb = TransientListBinder->NbTransients();
336           for (i=1; i<=nb; i++) {
337             Handle(Standard_Transient) t = TransientListBinder->Transient(i);
338             ent = Handle(IGESData_IGESEntity)::DownCast(t);
339             if (!ent.IsNull())
340       {
341         ent->InitColor ( colent, rank );
342         Handle(IGESSolid_Face) ent_f = Handle(IGESSolid_Face)::DownCast(ent);
343         if (!ent_f.IsNull())
344         {
345           if (!ent_f->Surface().IsNull())
346             ent_f->Surface()->InitColor ( colent, rank );
347         }
348       }
349           }
350         }
351         /* // alternative: consider recursive mapping S -> compound -> entities
352         else {
353           TopoDS_Shape comp = TransferBRep::ShapeResult(bnd);
354           if ( ! comp.IsNull() && comp.ShapeType() < S.ShapeType() ) 
355             for ( TopoDS_Iterator it(comp); it.More(); it.Next() ) {
356               MakeColors ( it.Value(), settings, colors, Map, style );
357             }
358         }
359         */
360       }
361     }
362   }
363
364   // iterate on subshapes (except vertices :)
365   if ( S.ShapeType() == TopAbs_EDGE ) return;
366   for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
367     MakeColors ( it.Value(), settings, colors, Map, style );
368   }
369 }
370
371
372 static void AttachLayer (const Handle(Transfer_FinderProcess) &FP,
373                          const Handle(XCAFDoc_LayerTool)& LTool,
374                          const TopoDS_Shape& aSh,
375                          const Standard_Integer localIntName)
376 {
377
378   TopTools_SequenceOfShape shseq;
379   if ( aSh.ShapeType() == TopAbs_COMPOUND ) {
380     TopoDS_Iterator aShIt(aSh);
381     for ( ; aShIt.More(); aShIt.Next() ) {
382       TopoDS_Shape newSh = aShIt.Value();
383       Handle(TColStd_HSequenceOfExtendedString) shLayers = new TColStd_HSequenceOfExtendedString;
384       if (! LTool->GetLayers( newSh, shLayers) || newSh.ShapeType() == TopAbs_COMPOUND )
385         AttachLayer(FP, LTool, newSh, localIntName);
386     }
387     return;
388   } else if ( aSh.ShapeType() == TopAbs_SOLID || aSh.ShapeType() == TopAbs_SHELL ) {
389     for (TopExp_Explorer exp(aSh,TopAbs_FACE) ; exp.More(); exp.Next()) {
390       TopoDS_Face entSh = TopoDS::Face (exp.Current());
391       shseq.Append(entSh);
392     }
393   } else {
394     shseq.Append(aSh);
395   }
396   
397   for (Standard_Integer i = 1; i <= shseq.Length(); i++ ) {
398     TopoDS_Shape localShape = shseq.Value(i);
399     Handle(IGESData_IGESEntity) Igesent;
400     Handle(TransferBRep_ShapeMapper) mapper = TransferBRep::ShapeMapper ( FP, localShape );
401     if ( FP->FindTypedTransient ( mapper, STANDARD_TYPE(IGESData_IGESEntity), Igesent ) ) {
402       Igesent->InitLevel( 0, localIntName );
403     }
404 #ifdef OCCT_DEBUG
405     else cout << "Warning: Can't find entity for shape in mapper" << endl;
406 #endif
407   }
408 }
409
410
411 static void MakeLayers (const Handle(Transfer_FinderProcess) &FP, 
412                         const Handle(XCAFDoc_ShapeTool)& STool,
413                         const Handle(XCAFDoc_LayerTool)& LTool,
414                         const TDF_LabelSequence& aShapeLabels,
415                         const Standard_Integer localIntName) 
416 {
417   for ( Standard_Integer j = 1; j <= aShapeLabels.Length(); j++ ) {
418     TDF_Label aShapeLabel = aShapeLabels.Value(j);
419     TopoDS_Shape aSh;
420     if ( ! STool->GetShape ( aShapeLabel, aSh ) ) continue;
421     AttachLayer (FP, LTool, aSh, localIntName);
422   }
423 }
424
425
426
427 //=======================================================================
428 //function : WriteLayers
429 //purpose  : 
430 //=======================================================================
431
432 Standard_Boolean IGESCAFControl_Writer::WriteLayers (const TDF_LabelSequence& labels) 
433 {
434   if ( labels.Length() <=0 ) return Standard_False;
435   Handle(XCAFDoc_ShapeTool) STool = XCAFDoc_DocumentTool::ShapeTool( labels(1) );
436   if ( STool.IsNull() ) return Standard_False;
437   Handle(XCAFDoc_LayerTool) LTool = XCAFDoc_DocumentTool::LayerTool( labels(1) );
438   if ( LTool.IsNull() ) return Standard_False;
439   
440   Standard_Integer globalIntName = 0;
441   TDF_LabelSequence aLayerLabels;
442   LTool->GetLayerLabels( aLayerLabels );
443   
444   Handle(Transfer_FinderProcess) FP = TransferProcess();
445   for ( Standard_Integer i = 1; i <= aLayerLabels.Length(); i++ ){
446     TDF_Label aOneLayerL = aLayerLabels.Value(i);
447     if ( aOneLayerL.IsNull() ) continue;
448     TCollection_ExtendedString localName;
449     LTool->GetLayer(aOneLayerL, localName);
450     Standard_Integer localIntName = 0;
451     TCollection_AsciiString asciiName(localName,'?');
452     if (asciiName.IsIntegerValue() ) {
453       localIntName = asciiName.IntegerValue();
454       if (globalIntName < localIntName) globalIntName = localIntName;
455       
456       TDF_LabelSequence aShapeLabels;
457       LTool->GetShapesOfLayer( aOneLayerL, aShapeLabels );
458       if ( aShapeLabels.Length() <= 0 ) continue;
459       MakeLayers(FP, STool, LTool, aShapeLabels, localIntName);
460     }
461   }
462   
463   for ( Standard_Integer i1 = 1; i1 <= aLayerLabels.Length(); i1++ ) {
464     TDF_Label aOneLayerL = aLayerLabels.Value(i1);
465     if ( aOneLayerL.IsNull() ) continue;
466     TCollection_ExtendedString localName; 
467     LTool->GetLayer(aOneLayerL, localName);
468     Standard_Integer localIntName = 0;
469     TCollection_AsciiString asciiName(localName,'?');
470     if (asciiName.IsIntegerValue() ) continue;
471     TDF_LabelSequence aShapeLabels;
472     LTool->GetShapesOfLayer( aOneLayerL, aShapeLabels );
473     if ( aShapeLabels.Length() <= 0 ) continue;
474     localIntName = ++globalIntName;
475     MakeLayers (FP, STool, LTool, aShapeLabels, localIntName);
476   }
477   
478   return Standard_True;
479 }
480
481
482 //=======================================================================
483 //function : WriteNames
484 //purpose  : 
485 //=======================================================================
486
487 Standard_Boolean IGESCAFControl_Writer::WriteNames (const TDF_LabelSequence& theLabels)
488 {
489   if (theLabels.Length() <= 0) return Standard_False;
490
491   DataMapOfShapeNames aMapOfShapeNames;
492
493   for (Standard_Integer anIter = 1; anIter <= theLabels.Length(); anIter++ )
494   {
495     TDF_Label aLabel = theLabels.Value (anIter);
496
497     TopoDS_Shape aShape;
498     Handle(TDataStd_Name) aName;
499     if (!XCAFDoc_ShapeTool::GetShape (aLabel, aShape)) continue;
500     if (!aLabel.FindAttribute (TDataStd_Name::GetID(), aName)) continue;
501
502     aMapOfShapeNames.Bind (aShape, aName->Get());
503
504     // Collect names for subshapes
505     TopLoc_Location aLocation;
506     CollectShapeNames (aLabel, aLocation, aName, aMapOfShapeNames);
507   }
508
509   for (DataMapOfShapeNames::Iterator anIter (aMapOfShapeNames);
510        anIter.More(); anIter.Next())
511   {
512     const TopoDS_Shape& aShape = anIter.Key();
513     const TCollection_ExtendedString& aName = anIter.Value();
514
515     Handle(Transfer_FinderProcess) aFinderProcess = TransferProcess();
516     Handle(IGESData_IGESEntity) anIGESEntity;
517     Handle(TransferBRep_ShapeMapper) aShapeMapper = TransferBRep::ShapeMapper (aFinderProcess, aShape);
518
519     if (aFinderProcess->FindTypedTransient (aShapeMapper, STANDARD_TYPE(IGESData_IGESEntity), anIGESEntity))
520     {
521       Handle(TCollection_HAsciiString) anAsciiName = new TCollection_HAsciiString ("        ");
522       Standard_Integer aNameLength = 8 - aName.Length();
523       if (aNameLength < 0) aNameLength = 0;
524       for (Standard_Integer aCharPos = 1; aNameLength < 8; aCharPos++, aNameLength++)
525       {
526         anAsciiName->SetValue (aNameLength+1, IsAnAscii (aName.Value (aCharPos)) ? (Standard_Character )aName.Value (aCharPos) : '?');
527       }
528       anIGESEntity->SetLabel (anAsciiName);
529     }
530   }
531
532   return Standard_True;
533 }
534
535 //=======================================================================
536 //function : SetColorMode
537 //purpose  : 
538 //=======================================================================
539
540 void IGESCAFControl_Writer::SetColorMode (const Standard_Boolean colormode)
541 {
542   myColorMode = colormode;
543 }
544
545 //=======================================================================
546 //function : GetColorMode
547 //purpose  : 
548 //=======================================================================
549
550 Standard_Boolean IGESCAFControl_Writer::GetColorMode () const
551 {
552   return myColorMode;
553 }
554
555 //=======================================================================
556 //function : SetNameMode
557 //purpose  : 
558 //=======================================================================
559
560 void IGESCAFControl_Writer::SetNameMode (const Standard_Boolean namemode)
561 {
562   myNameMode = namemode;
563 }
564
565 //=======================================================================
566 //function : GetNameMode
567 //purpose  : 
568 //=======================================================================
569
570 Standard_Boolean IGESCAFControl_Writer::GetNameMode () const
571 {
572   return myNameMode;
573 }
574
575 //=======================================================================
576 //function : SetLayerMode
577 //purpose  : 
578 //=======================================================================
579
580 void IGESCAFControl_Writer::SetLayerMode (const Standard_Boolean layermode)
581 {
582   myLayerMode = layermode;
583 }
584
585 //=======================================================================
586 //function : GetLayerMode
587 //purpose  : 
588 //=======================================================================
589
590 Standard_Boolean IGESCAFControl_Writer::GetLayerMode () const
591 {
592   return myLayerMode;
593 }