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