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