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