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