1 // Created on: 2000-08-17
2 // Created by: Andrey BETENEV
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <IGESCAFControl.hxx>
17 #include <IGESCAFControl_Writer.hxx>
18 #include <IGESData_IGESModel.hxx>
19 #include <IGESGraph_Color.hxx>
20 #include <IGESGraph_DefinitionLevel.hxx>
21 #include <IGESSolid_Face.hxx>
22 #include <IGESBasic_Name.hxx>
23 #include <Message_ProgressScope.hxx>
24 #include <NCollection_DataMap.hxx>
25 #include <Standard_Transient.hxx>
26 #include <TCollection_AsciiString.hxx>
27 #include <TCollection_HAsciiString.hxx>
28 #include <TCollection_HExtendedString.hxx>
29 #include <TDataStd_Name.hxx>
30 #include <TDF_Label.hxx>
31 #include <TDF_LabelSequence.hxx>
32 #include <TDocStd_Document.hxx>
33 #include <TopExp_Explorer.hxx>
35 #include <TopoDS_Face.hxx>
36 #include <TopoDS_Iterator.hxx>
37 #include <TopoDS_Shape.hxx>
38 #include <Transfer_TransientListBinder.hxx>
39 #include <TransferBRep.hxx>
40 #include <TransferBRep_ShapeMapper.hxx>
41 #include <XCAFDoc_DocumentTool.hxx>
42 #include <XCAFDoc_LayerTool.hxx>
43 #include <XCAFDoc_LengthUnit.hxx>
44 #include <XCAFDoc_ShapeTool.hxx>
45 #include <XCAFPrs.hxx>
46 #include <XCAFPrs_Style.hxx>
48 #include <XSAlgo_AlgoContainer.hxx>
49 #include <XSControl_WorkSession.hxx>
50 #include <UnitsMethods.hxx>
54 typedef NCollection_DataMap<TopoDS_Shape, TCollection_ExtendedString> DataMapOfShapeNames;
56 void CollectShapeNames (const TDF_Label& theLabel,
57 const TopLoc_Location& theLocation,
58 const Handle(TDataStd_Name)& thePrevName,
59 DataMapOfShapeNames& theMapOfShapeNames)
61 Standard_Boolean hasReferredShape = Standard_False;
62 Standard_Boolean hasComponents = Standard_False;
63 TDF_Label aReferredLabel;
65 Handle(TDataStd_Name) aName;
66 theLabel.FindAttribute (TDataStd_Name::GetID(), aName);
68 if ( XCAFDoc_ShapeTool::GetReferredShape ( theLabel, aReferredLabel ) )
70 TopLoc_Location aSubLocation = theLocation.Multiplied ( XCAFDoc_ShapeTool::GetLocation ( theLabel ) );
71 CollectShapeNames (aReferredLabel, aSubLocation, aName, theMapOfShapeNames);
72 hasReferredShape = Standard_True;
75 TDF_LabelSequence aSeq;
76 if (XCAFDoc_ShapeTool::GetComponents (theLabel, aSeq))
78 for (Standard_Integer anIter = 1; anIter <= aSeq.Length(); anIter++)
80 CollectShapeNames (aSeq.Value (anIter), theLocation, aName, theMapOfShapeNames );
82 hasComponents = Standard_True;
86 if (XCAFDoc_ShapeTool::GetSubShapes (theLabel, aSeq))
88 for (Standard_Integer anIter = 1; anIter <= aSeq.Length(); anIter++)
91 if (!XCAFDoc_ShapeTool::GetShape (aSeq.Value (anIter), aShape)) continue;
92 if (!aSeq.Value (anIter).FindAttribute (TDataStd_Name::GetID(), aName)) continue;
93 theMapOfShapeNames.Bind (aShape, aName->Get());
97 if (!hasReferredShape && !hasComponents && !thePrevName.IsNull())
100 if (!XCAFDoc_ShapeTool::GetShape (theLabel, aShape)) return;
101 aShape.Move (theLocation, Standard_False);
102 theMapOfShapeNames.Bind (aShape, thePrevName->Get());
107 //=======================================================================
108 //function : IGESCAFControl_Writer
110 //=======================================================================
112 IGESCAFControl_Writer::IGESCAFControl_Writer () :
113 myColorMode( Standard_True ),
114 myNameMode ( Standard_True ),
115 myLayerMode( Standard_True )
119 //=======================================================================
120 //function : IGESCAFControl_Writer
122 //=======================================================================
124 IGESCAFControl_Writer::IGESCAFControl_Writer (const Handle(XSControl_WorkSession)& WS,
125 const Standard_Boolean /*scratch*/ )
127 // this code does things in a wrong way, it should be vice-versa
128 WS->SetModel ( Model() );
129 WS->SetMapWriter ( TransferProcess() );
130 myColorMode = Standard_True;
131 myNameMode = Standard_True;
132 myLayerMode = Standard_True;
134 // SetWS (WS,scratch); // this should be the only required command here
137 //=======================================================================
138 //function : Transfer
140 //=======================================================================
142 Standard_Boolean IGESCAFControl_Writer::Transfer (const Handle(TDocStd_Document) &doc,
143 const Message_ProgressRange& theProgress)
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;
149 TDF_LabelSequence labels;
150 STool->GetFreeShapes ( labels );
151 return Transfer (labels, theProgress);
154 //=======================================================================
155 //function : Transfer
157 //=======================================================================
159 Standard_Boolean IGESCAFControl_Writer::Transfer (const TDF_Label& label,
160 const Message_ProgressRange& theProgress)
162 TDF_LabelSequence labels;
163 labels.Append( label );
164 return Transfer( labels, theProgress );
167 //=======================================================================
168 //function : Transfer
170 //=======================================================================
172 Standard_Boolean IGESCAFControl_Writer::Transfer (const TDF_LabelSequence& labels,
173 const Message_ProgressRange& theProgress)
175 if ( labels.Length() <=0 ) return Standard_False;
176 prepareUnit(labels.First()); // set local length unit to the model
177 Message_ProgressScope aPS(theProgress, "Labels", labels.Length());
178 for ( Standard_Integer i=1; i <= labels.Length() && aPS.More(); i++ )
180 TopoDS_Shape shape = XCAFDoc_ShapeTool::GetShape ( labels.Value(i) );
181 if ( ! shape.IsNull() )
182 AddShape (shape, aPS.Next());
183 // IGESControl_Writer::Transfer ( shape );
187 if ( GetColorMode() )
188 WriteAttributes ( labels );
191 if ( GetLayerMode() )
192 WriteLayers ( labels );
196 WriteNames( labels );
199 // WS()->ComputeGraph ( Standard_True );
202 return Standard_True;
205 //=======================================================================
208 //=======================================================================
210 Standard_Boolean IGESCAFControl_Writer::Perform (const Handle(TDocStd_Document) &doc,
211 const Standard_CString filename,
212 const Message_ProgressRange& theProgress)
214 if ( ! Transfer ( doc, theProgress ) ) return Standard_False;
215 return Write ( filename ) == IFSelect_RetDone;
218 //=======================================================================
221 //=======================================================================
223 Standard_Boolean IGESCAFControl_Writer::Perform (const Handle(TDocStd_Document) &doc,
224 const TCollection_AsciiString &filename,
225 const Message_ProgressRange& theProgress)
227 if ( ! Transfer ( doc, theProgress ) ) return Standard_False;
228 return Write ( filename.ToCString() ) == IFSelect_RetDone;
231 //=======================================================================
232 //function : WriteAttributes
234 //=======================================================================
236 Standard_Boolean IGESCAFControl_Writer::WriteAttributes (const TDF_LabelSequence& labels)
239 if ( labels.Length() <=0 ) return Standard_False;
240 for ( Standard_Integer i=1; i <= labels.Length(); i++ ) {
241 TDF_Label L = labels.Value(i);
243 // collect color settings
244 XCAFPrs_IndexedDataMapOfShapeStyle settings;
246 XCAFPrs::CollectStyleSettings ( L, loc, settings );
247 if ( settings.Extent() <=0 ) continue;
249 // get a target shape and try to find corresponding context
250 // (all the colors set under that label will be put into that context)
252 if ( ! XCAFDoc_ShapeTool::GetShape ( L, S ) ) continue;
254 // iterate on subshapes and create IGES styles
255 XCAFPrs_DataMapOfStyleTransient colors;
256 TopTools_MapOfShape Map;
257 const XCAFPrs_Style inherit;
258 MakeColors ( S, settings, colors, Map, inherit );
261 return Standard_True;
264 //=======================================================================
265 //function : MakeColors
267 //=======================================================================
269 void IGESCAFControl_Writer::MakeColors (const TopoDS_Shape &S,
270 const XCAFPrs_IndexedDataMapOfShapeStyle &settings,
271 XCAFPrs_DataMapOfStyleTransient &colors,
272 TopTools_MapOfShape &Map,
273 const XCAFPrs_Style &inherit)
275 // skip already processed shapes
276 if ( ! Map.Add ( S ) ) return;
278 // check if shape has its own style (or inherits from ancestor)
279 XCAFPrs_Style style = inherit;
280 if ( settings.Contains(S) ) {
281 const XCAFPrs_Style& own = settings.FindFromKey(S);
282 if ( own.IsSetColorCurv() ) style.SetColorCurv ( own.GetColorCurv() );
283 if ( own.IsSetColorSurf() ) style.SetColorSurf ( own.GetColorSurf() );
284 style.SetMaterial (own.Material());
287 // analyze whether current entity should get a color
288 Standard_Boolean hasColor = Standard_False;
290 if ( S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SOLID) {
291 if ( style.IsSetColorSurf() ) {
292 hasColor = Standard_True;
293 col = style.GetColorSurf();
295 else if (!style.Material().IsNull()
296 && !style.Material()->IsEmpty())
298 hasColor = Standard_True;
299 col = style.Material()->BaseColor().GetRGB();
302 else if ( S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE ) {
303 if ( style.IsSetColorCurv() ) {
304 hasColor = Standard_True;
305 col = style.GetColorCurv();
309 // if color has to be assigned, try to do this
311 Handle(IGESGraph_Color) colent;
312 Standard_Integer rank = IGESCAFControl::EncodeColor ( col );
314 XCAFPrs_Style c; // style used as key in the map
315 c.SetColorSurf ( col );
316 if ( colors.IsBound ( c ) ) {
317 colent = Handle(IGESGraph_Color)::DownCast ( colors.Find(c) );
320 Handle(TCollection_HAsciiString) str =
321 new TCollection_HAsciiString ( col.StringName ( col.Name() ) );
322 colent = new IGESGraph_Color;
323 NCollection_Vec3<Standard_Real> aColor_sRGB;
324 col.Values (aColor_sRGB.r(), aColor_sRGB.g(), aColor_sRGB.b(), Quantity_TOC_sRGB);
325 colent->Init ( aColor_sRGB.r() * 100., aColor_sRGB.g() * 100., aColor_sRGB.b() * 100., str );
326 AddEntity ( colent );
327 colors.Bind ( c, colent );
330 Handle(Transfer_FinderProcess) FP = TransferProcess();
331 Handle(IGESData_IGESEntity) ent;
332 Handle(TransferBRep_ShapeMapper) mapper = TransferBRep::ShapeMapper ( FP, S );
333 Handle(TransferBRep_ShapeMapper) aNoLocMapper = TransferBRep::ShapeMapper(FP, S.Located(TopLoc_Location()));
334 if ( FP->FindTypedTransient ( mapper, STANDARD_TYPE(IGESData_IGESEntity), ent ) ||
335 FP->FindTypedTransient(aNoLocMapper, STANDARD_TYPE(IGESData_IGESEntity), ent)) {
336 ent->InitColor ( colent, rank );
337 Handle(IGESSolid_Face) ent_f = Handle(IGESSolid_Face)::DownCast(ent);
340 if (!ent_f->Surface().IsNull())
341 ent_f->Surface()->InitColor ( colent, rank );
345 // may be S was splited during shape process
346 Handle(Transfer_Binder) bnd = FP->Find ( mapper );
347 if ( ! bnd.IsNull() ) {
348 Handle(Transfer_TransientListBinder) TransientListBinder =
349 //Handle(Transfer_TransientListBinder)::DownCast( bnd->Next(Standard_True) );
350 Handle(Transfer_TransientListBinder)::DownCast( bnd );
351 Standard_Integer i=0, nb=0;
352 if (! TransientListBinder.IsNull() ) {
353 nb = TransientListBinder->NbTransients();
354 for (i=1; i<=nb; i++) {
355 Handle(Standard_Transient) t = TransientListBinder->Transient(i);
356 ent = Handle(IGESData_IGESEntity)::DownCast(t);
359 ent->InitColor ( colent, rank );
360 Handle(IGESSolid_Face) ent_f = Handle(IGESSolid_Face)::DownCast(ent);
363 if (!ent_f->Surface().IsNull())
364 ent_f->Surface()->InitColor ( colent, rank );
369 /* // alternative: consider recursive mapping S -> compound -> entities
371 TopoDS_Shape comp = TransferBRep::ShapeResult(bnd);
372 if ( ! comp.IsNull() && comp.ShapeType() < S.ShapeType() )
373 for ( TopoDS_Iterator it(comp); it.More(); it.Next() ) {
374 MakeColors ( it.Value(), settings, colors, Map, style );
382 // iterate on subshapes (except vertices :)
383 if ( S.ShapeType() == TopAbs_EDGE ) return;
384 for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
385 MakeColors ( it.Value(), settings, colors, Map, style );
390 static void AttachLayer (const Handle(Transfer_FinderProcess) &FP,
391 const Handle(XCAFDoc_LayerTool)& LTool,
392 const TopoDS_Shape& aSh,
393 const Standard_Integer localIntName)
396 TopTools_SequenceOfShape shseq;
397 if ( aSh.ShapeType() == TopAbs_COMPOUND ) {
398 TopoDS_Iterator aShIt(aSh);
399 for ( ; aShIt.More(); aShIt.Next() ) {
400 const TopoDS_Shape& newSh = aShIt.Value();
401 Handle(TColStd_HSequenceOfExtendedString) shLayers = new TColStd_HSequenceOfExtendedString;
402 if (! LTool->GetLayers( newSh, shLayers) || newSh.ShapeType() == TopAbs_COMPOUND )
403 AttachLayer(FP, LTool, newSh, localIntName);
406 } else if ( aSh.ShapeType() == TopAbs_SOLID || aSh.ShapeType() == TopAbs_SHELL ) {
407 for (TopExp_Explorer exp(aSh,TopAbs_FACE) ; exp.More(); exp.Next()) {
408 TopoDS_Face entSh = TopoDS::Face (exp.Current());
415 for (Standard_Integer i = 1; i <= shseq.Length(); i++ ) {
416 const TopoDS_Shape& localShape = shseq.Value(i);
417 Handle(IGESData_IGESEntity) Igesent;
418 Handle(TransferBRep_ShapeMapper) mapper = TransferBRep::ShapeMapper ( FP, localShape );
419 if ( FP->FindTypedTransient ( mapper, STANDARD_TYPE(IGESData_IGESEntity), Igesent ) ) {
420 Igesent->InitLevel( 0, localIntName );
423 else std::cout << "Warning: Can't find entity for shape in mapper" << std::endl;
429 static void MakeLayers (const Handle(Transfer_FinderProcess) &FP,
430 const Handle(XCAFDoc_ShapeTool)& STool,
431 const Handle(XCAFDoc_LayerTool)& LTool,
432 const TDF_LabelSequence& aShapeLabels,
433 const Standard_Integer localIntName)
435 for ( Standard_Integer j = 1; j <= aShapeLabels.Length(); j++ ) {
436 TDF_Label aShapeLabel = aShapeLabels.Value(j);
438 if ( ! STool->GetShape ( aShapeLabel, aSh ) ) continue;
439 AttachLayer (FP, LTool, aSh, localIntName);
445 //=======================================================================
446 //function : WriteLayers
448 //=======================================================================
450 Standard_Boolean IGESCAFControl_Writer::WriteLayers (const TDF_LabelSequence& labels)
452 if ( labels.Length() <=0 ) return Standard_False;
453 Handle(XCAFDoc_ShapeTool) STool = XCAFDoc_DocumentTool::ShapeTool( labels(1) );
454 if ( STool.IsNull() ) return Standard_False;
455 Handle(XCAFDoc_LayerTool) LTool = XCAFDoc_DocumentTool::LayerTool( labels(1) );
456 if ( LTool.IsNull() ) return Standard_False;
458 Standard_Integer globalIntName = 0;
459 TDF_LabelSequence aLayerLabels;
460 LTool->GetLayerLabels( aLayerLabels );
462 Handle(Transfer_FinderProcess) FP = TransferProcess();
463 for ( Standard_Integer i = 1; i <= aLayerLabels.Length(); i++ ){
464 TDF_Label aOneLayerL = aLayerLabels.Value(i);
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() ) {
471 localIntName = asciiName.IntegerValue();
472 if (globalIntName < localIntName) globalIntName = localIntName;
474 TDF_LabelSequence aShapeLabels;
475 LTool->GetShapesOfLayer( aOneLayerL, aShapeLabels );
476 if ( aShapeLabels.Length() <= 0 ) continue;
477 MakeLayers(FP, STool, LTool, aShapeLabels, localIntName);
481 for ( Standard_Integer i1 = 1; i1 <= aLayerLabels.Length(); i1++ ) {
482 TDF_Label aOneLayerL = aLayerLabels.Value(i1);
483 if ( aOneLayerL.IsNull() ) continue;
484 TCollection_ExtendedString localName;
485 LTool->GetLayer(aOneLayerL, localName);
486 Standard_Integer localIntName = 0;
487 TCollection_AsciiString asciiName(localName,'?');
488 if (asciiName.IsIntegerValue() ) continue;
489 TDF_LabelSequence aShapeLabels;
490 LTool->GetShapesOfLayer( aOneLayerL, aShapeLabels );
491 if ( aShapeLabels.Length() <= 0 ) continue;
492 localIntName = ++globalIntName;
493 MakeLayers (FP, STool, LTool, aShapeLabels, localIntName);
496 return Standard_True;
500 //=======================================================================
501 //function : WriteNames
503 //=======================================================================
505 Standard_Boolean IGESCAFControl_Writer::WriteNames (const TDF_LabelSequence& theLabels)
507 if (theLabels.Length() <= 0) return Standard_False;
509 DataMapOfShapeNames aMapOfShapeNames;
511 for (Standard_Integer anIter = 1; anIter <= theLabels.Length(); anIter++ )
513 TDF_Label aLabel = theLabels.Value (anIter);
516 Handle(TDataStd_Name) aName;
517 if (!XCAFDoc_ShapeTool::GetShape (aLabel, aShape)) continue;
518 if (!aLabel.FindAttribute (TDataStd_Name::GetID(), aName)) continue;
520 aMapOfShapeNames.Bind (aShape, aName->Get());
522 // Collect names for subshapes
523 TopLoc_Location aLocation;
524 CollectShapeNames (aLabel, aLocation, aName, aMapOfShapeNames);
527 for (DataMapOfShapeNames::Iterator anIter (aMapOfShapeNames);
528 anIter.More(); anIter.Next())
530 const TopoDS_Shape& aShape = anIter.Key();
531 const TCollection_ExtendedString& aName = anIter.Value();
533 Handle(Transfer_FinderProcess) aFinderProcess = TransferProcess();
534 Handle(IGESData_IGESEntity) anIGESEntity;
535 Handle(TransferBRep_ShapeMapper) aShapeMapper = TransferBRep::ShapeMapper (aFinderProcess, aShape);
537 if (aFinderProcess->FindTypedTransient (aShapeMapper, STANDARD_TYPE(IGESData_IGESEntity), anIGESEntity))
539 Handle(TCollection_HAsciiString) anAsciiName = new TCollection_HAsciiString (" ");
540 Standard_Integer aNameLength = 8 - aName.Length();
541 if (aNameLength < 0) aNameLength = 0;
542 for (Standard_Integer aCharPos = 1; aNameLength < 8; aCharPos++, aNameLength++)
544 anAsciiName->SetValue (aNameLength+1, IsAnAscii (aName.Value (aCharPos)) ? (Standard_Character )aName.Value (aCharPos) : '?');
546 anIGESEntity->SetLabel (anAsciiName);
548 // Set long IGES name using 406 form 15 entity
549 Handle(IGESBasic_Name) aLongNameEntity = new IGESBasic_Name;
550 Handle(TCollection_HExtendedString) aTmpStr = new TCollection_HExtendedString(aName);
551 aLongNameEntity->Init(1, new TCollection_HAsciiString(aTmpStr, '_'));
553 anIGESEntity->AddProperty(aLongNameEntity);
554 AddEntity(aLongNameEntity);
558 return Standard_True;
561 //=======================================================================
562 //function : prepareUnit
564 //=======================================================================
565 void IGESCAFControl_Writer::prepareUnit(const TDF_Label& theLabel)
567 Handle(XCAFDoc_LengthUnit) aLengthAttr;
568 if (!theLabel.IsNull() &&
569 theLabel.Root().FindAttribute(XCAFDoc_LengthUnit::GetID(), aLengthAttr))
571 Model()->ChangeGlobalSection().SetCascadeUnit(aLengthAttr->GetUnitValue() * 1000);
575 XSAlgo::AlgoContainer()->PrepareForTransfer(); // update unit info
576 Model()->ChangeGlobalSection().SetCascadeUnit(UnitsMethods::GetCasCadeLengthUnit());
580 //=======================================================================
581 //function : SetColorMode
583 //=======================================================================
585 void IGESCAFControl_Writer::SetColorMode (const Standard_Boolean colormode)
587 myColorMode = colormode;
590 //=======================================================================
591 //function : GetColorMode
593 //=======================================================================
595 Standard_Boolean IGESCAFControl_Writer::GetColorMode () const
600 //=======================================================================
601 //function : SetNameMode
603 //=======================================================================
605 void IGESCAFControl_Writer::SetNameMode (const Standard_Boolean namemode)
607 myNameMode = namemode;
610 //=======================================================================
611 //function : GetNameMode
613 //=======================================================================
615 Standard_Boolean IGESCAFControl_Writer::GetNameMode () const
620 //=======================================================================
621 //function : SetLayerMode
623 //=======================================================================
625 void IGESCAFControl_Writer::SetLayerMode (const Standard_Boolean layermode)
627 myLayerMode = layermode;
630 //=======================================================================
631 //function : GetLayerMode
633 //=======================================================================
635 Standard_Boolean IGESCAFControl_Writer::GetLayerMode () const