1 // Copyright (C) 2014-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #include "STEPPlugin_ImportDriver.hxx"
22 #include "STEPPlugin_IImport.hxx"
25 #include <utilities.h>
26 #include <Basics_Utils.hxx>
29 #include "GEOM_Function.hxx"
30 #include "GEOMImpl_Types.hxx"
33 #include <TDF_ChildIDIterator.hxx>
34 #include <TDF_Label.hxx>
35 #include <TDataStd_Name.hxx>
36 #include <TDataStd_Comment.hxx>
37 #include <TNaming_Builder.hxx>
38 #include <TNaming_NamedShape.hxx>
39 #include <Interface_EntityIterator.hxx>
40 #include <Interface_Graph.hxx>
41 #include <Interface_InterfaceModel.hxx>
42 #include <Interface_Static.hxx>
43 #include <STEPControl_Reader.hxx>
44 #include <StepBasic_Product.hxx>
45 #include <StepBasic_ProductDefinition.hxx>
46 #include <StepBasic_ProductDefinitionFormation.hxx>
47 #include <StepGeom_GeometricRepresentationItem.hxx>
48 #include <StepShape_TopologicalRepresentationItem.hxx>
49 #include <StepRepr_DescriptiveRepresentationItem.hxx>
50 #include <StepRepr_ProductDefinitionShape.hxx>
51 #include <StepRepr_PropertyDefinitionRepresentation.hxx>
52 #include <StepRepr_Representation.hxx>
53 #include <TransferBRep.hxx>
54 #include <Transfer_TransientProcess.hxx>
55 #include <XSControl_TransferReader.hxx>
56 #include <XSControl_WorkSession.hxx>
57 #include <BRep_Builder.hxx>
59 #include <TopExp_Explorer.hxx>
60 #include <TopTools_IndexedMapOfShape.hxx>
61 #include <TopoDS_Compound.hxx>
62 #include <TopoDS_Iterator.hxx>
63 #include <TColStd_SequenceOfAsciiString.hxx>
65 #include <StdFail_NotDone.hxx>
66 #include <Standard_Failure.hxx>
67 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
69 //=============================================================================
73 //=============================================================================
75 TopoDS_Shape GetShape(const Handle(Standard_Transient) &theEnti,
76 const Handle(Transfer_TransientProcess) &theTP)
79 Handle(Transfer_Binder) aBinder = theTP->Find(theEnti);
81 if (aBinder.IsNull()) {
85 aResult = TransferBRep::ShapeResult(aBinder);
90 //=============================================================================
94 //=============================================================================
96 TDF_Label GetLabel(const Handle(Standard_Transient) &theEnti,
97 const TDF_Label &theShapeLabel,
98 const TopoDS_Shape &aShape)
103 (STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
104 // check all named shapes using iterator
105 TDF_ChildIDIterator anIt
106 (theShapeLabel, TDataStd_Name::GetID(), Standard_True);
108 for (; anIt.More(); anIt.Next()) {
109 Handle(TDataStd_Name) nameAttr =
110 Handle(TDataStd_Name)::DownCast(anIt.Value());
112 if (nameAttr.IsNull()) {
116 TDF_Label aLab = nameAttr->Label();
117 Handle(TNaming_NamedShape) shAttr;
119 if (aLab.FindAttribute(TNaming_NamedShape::GetID(), shAttr) &&
120 shAttr->Get().IsEqual(aShape)) {
126 // create label and set shape
127 if (aResult.IsNull()) {
130 aResult = aTag.NewChild(theShapeLabel);
132 TNaming_Builder tnBuild (aResult);
134 tnBuild.Generated(aShape);
140 //=============================================================================
144 //=============================================================================
146 void StoreName( const Handle(Standard_Transient) &theEnti,
147 const TopTools_IndexedMapOfShape &theIndices,
148 const Handle(Transfer_TransientProcess) &theTP,
149 const TDF_Label &theShapeLabel)
151 Handle(TCollection_HAsciiString) aName;
153 if (theEnti->IsKind(STANDARD_TYPE(StepShape_TopologicalRepresentationItem)) ||
154 theEnti->IsKind(STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
155 aName = Handle(StepRepr_RepresentationItem)::DownCast(theEnti)->Name();
157 Handle(StepBasic_ProductDefinition) PD =
158 Handle(StepBasic_ProductDefinition)::DownCast(theEnti);
160 if (PD.IsNull() == Standard_False) {
161 Handle(StepBasic_Product) Prod = PD->Formation()->OfProduct();
162 aName = Prod->Name();
166 bool isValidName = false;
168 if (aName.IsNull() == Standard_False) {
171 if (aName->UsefullLength() < 1) {
173 } else if (aName->UsefullLength() == 4 &&
174 toupper (aName->Value(1)) == 'N' &&
175 toupper (aName->Value(2)) == 'O' &&
176 toupper (aName->Value(3)) == 'N' &&
177 toupper (aName->Value(4)) == 'E') {
181 // special check to pass names like "Open CASCADE STEP translator 6.3 1"
182 TCollection_AsciiString aSkipName ("Open CASCADE STEP translator");
184 if (aName->Length() >= aSkipName.Length()) {
185 if (aName->String().SubString
186 (1, aSkipName.Length()).IsEqual(aSkipName)) {
194 TCollection_ExtendedString aNameExt (aName->ToCString());
197 TopoDS_Shape S = GetShape(theEnti, theTP);
203 // as PRODUCT can be included in the main shape
204 // several times, we look here for all iclusions.
205 Standard_Integer isub, nbSubs = theIndices.Extent();
207 for (isub = 1; isub <= nbSubs; isub++) {
208 TopoDS_Shape aSub = theIndices.FindKey(isub);
210 if (aSub.IsPartner(S)) {
211 TDF_Label L = GetLabel(theEnti, theShapeLabel, aSub);
214 TDataStd_Name::Set(L, aNameExt);
220 //=============================================================================
224 //=============================================================================
226 void StoreMaterial( const Handle(Standard_Transient) &theEnti,
227 const TopTools_IndexedMapOfShape &theIndices,
228 const Handle(Transfer_TransientProcess) &theTP,
229 const TDF_Label &theShapeLabel )
231 // Treat Product Definition Shape only.
232 Handle(StepRepr_ProductDefinitionShape) aPDS =
233 Handle(StepRepr_ProductDefinitionShape)::DownCast(theEnti);
234 Handle(StepBasic_ProductDefinition) aProdDef;
236 if(aPDS.IsNull() == Standard_False) {
237 // Product Definition Shape ==> Product Definition
238 aProdDef = aPDS->Definition().ProductDefinition();
241 if (aProdDef.IsNull() == Standard_False) {
242 // Product Definition ==> Property Definition
243 const Interface_Graph &aGraph = theTP->Graph();
244 Interface_EntityIterator aSubs = aGraph.Sharings(aProdDef);
247 for(aSubs.Start(); aSubs.More(); aSubs.Next()) {
248 Handle(StepRepr_PropertyDefinition) aPropD =
249 Handle(StepRepr_PropertyDefinition)::DownCast(aSubs.Value());
251 if(aPropD.IsNull() == Standard_False) {
252 // Property Definition ==> Representation.
253 Interface_EntityIterator aSubs1 = aGraph.Sharings(aPropD);
255 for(aSubs1.Start(); aSubs1.More(); aSubs1.Next()) {
256 Handle(StepRepr_PropertyDefinitionRepresentation) aPDR =
257 Handle(StepRepr_PropertyDefinitionRepresentation)::
258 DownCast(aSubs1.Value());
260 if(aPDR.IsNull() == Standard_False) {
261 // Property Definition ==> Material Name.
262 Handle(StepRepr_Representation) aRepr = aPDR->UsedRepresentation();
264 if(aRepr.IsNull() == Standard_False) {
267 for(ir = 1; ir <= aRepr->NbItems(); ir++) {
268 Handle(StepRepr_RepresentationItem) aRI = aRepr->ItemsValue(ir);
269 Handle(StepRepr_DescriptiveRepresentationItem) aDRI =
270 Handle(StepRepr_DescriptiveRepresentationItem)::DownCast(aRI);
272 if(aDRI.IsNull() == Standard_False) {
273 // Get shape from Product Definition
274 Handle(TCollection_HAsciiString) aMatName = aDRI->Name();
276 if(aMatName.IsNull() == Standard_False) {
277 TCollection_ExtendedString
278 aMatNameExt (aMatName->ToCString());
280 if (aShape.IsNull()) {
282 aShape = GetShape(aProdDef, theTP);
284 if (aShape.IsNull()) {
289 // as PRODUCT can be included in the main shape
290 // several times, we look here for all iclusions.
291 Standard_Integer isub, nbSubs = theIndices.Extent();
293 for (isub = 1; isub <= nbSubs; isub++) {
294 TopoDS_Shape aSub = theIndices.FindKey(isub);
296 if (aSub.IsPartner(aShape)) {
298 GetLabel(aProdDef, theShapeLabel, aSub);
301 TDataStd_Comment::Set(aLabel, aMatNameExt);
315 //=======================================================================
318 //=======================================================================
319 const Standard_GUID& STEPPlugin_ImportDriver::GetID()
321 static Standard_GUID aGUID("a25f88df-461b-45c0-ab6b-a82101fe6ce7");
325 //=======================================================================
326 //function : STEPPlugin_ImportDriver
328 //=======================================================================
329 STEPPlugin_ImportDriver::STEPPlugin_ImportDriver()
333 //=======================================================================
336 //=======================================================================
337 Standard_Integer STEPPlugin_ImportDriver::Execute( TFunction_Logbook& log ) const
339 if( Label().IsNull() ) return 0;
340 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction( Label() );
342 STEPPlugin_IImport aData( aFunction );
344 TCollection_AsciiString aFileName = aData.GetFileName().ToCString();
345 bool anIsIgnoreUnits = aData.GetIsIgnoreUnits();
346 TDF_Label aShapeLabel = aFunction->GetNamingEntry();
348 MESSAGE("Import STEP from file " << aFileName.ToCString() );
350 TopoDS_Shape aResShape;
351 TCollection_AsciiString anError;
353 // Set "C" numeric locale to save numbers correctly
354 Kernel_Utils::Localizer loc;
356 STEPControl_Reader aReader;
358 //VSR: 16/09/09: Convert to METERS
359 Interface_Static::SetCVal("xstep.cascade.unit","M");
360 Interface_Static::SetIVal("read.step.ideas", 1);
361 Interface_Static::SetIVal("read.step.nonmanifold", 1);
364 TopoDS_Compound compound;
365 B.MakeCompound(compound);
370 IFSelect_ReturnStatus status = aReader.ReadFile(aFileName.ToCString());
371 if (status == IFSelect_RetDone) {
372 // Regard or not the model units
373 if( anIsIgnoreUnits ) {
374 // set UnitFlag to units from file
375 TColStd_SequenceOfAsciiString anUnitLengthNames;
376 TColStd_SequenceOfAsciiString anUnitAngleNames;
377 TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
378 aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
379 if (anUnitLengthNames.Length() > 0) {
380 TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
381 if (aLenUnits == "millimetre")
382 Interface_Static::SetCVal("xstep.cascade.unit", "MM");
383 else if (aLenUnits == "centimetre")
384 Interface_Static::SetCVal("xstep.cascade.unit", "CM");
385 else if (aLenUnits == "metre" || aLenUnits.IsEmpty())
386 Interface_Static::SetCVal("xstep.cascade.unit", "M");
387 else if (aLenUnits == "INCH")
388 Interface_Static::SetCVal("xstep.cascade.unit", "INCH");
390 anError = "The file contains not supported units.";
392 // TODO (for other units than mm, cm, m or inch)
393 // else if (aLenUnits == "")
394 // Interface_Static::SetCVal("xstep.cascade.unit", "???");
398 // Need re-scale a model (set UnitFlag to 'meter')
399 Interface_Static::SetCVal("xstep.cascade.unit","M");
402 Standard_Boolean failsonly = Standard_False;
403 aReader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity);
406 Standard_Integer nbr = aReader.NbRootsForTransfer();
407 aReader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity);
409 for (Standard_Integer n = 1; n <= nbr; n++) {
410 Standard_Boolean ok = aReader.TransferRoot(n);
411 // Collecting resulting entities
412 Standard_Integer nbs = aReader.NbShapes();
414 continue; // skip empty root
416 // For a single entity
417 else if (nbr == 1 && nbs == 1) {
418 aResShape = aReader.Shape(1);
419 if (aResShape.ShapeType() == TopAbs_COMPOUND) {
421 TopoDS_Shape currShape;
422 TopoDS_Iterator It (aResShape, Standard_True, Standard_True);
423 for (; It.More(); It.Next()) {
425 currShape = It.Value();
428 aResShape = currShape;
433 for (Standard_Integer i = 1; i <= nbs; i++) {
434 TopoDS_Shape aShape = aReader.Shape(i);
438 B.Add(compound, aShape);
441 if( aResShape.IsNull() )
442 aResShape = compound;
444 // Check if any BRep entity has been read, there must be at least a vertex
445 if ( !TopExp_Explorer( aResShape, TopAbs_VERTEX ).More() )
446 StdFail_NotDone::Raise( "No geometrical data in the imported file." );
448 // BEGIN: Store names and materials of sub-shapes from file
449 TopTools_IndexedMapOfShape anIndices;
450 TopExp::MapShapes(aResShape, anIndices);
452 Handle(Interface_InterfaceModel) Model = aReader.WS()->Model();
453 Handle(XSControl_TransferReader) TR = aReader.WS()->TransferReader();
455 Handle(Transfer_TransientProcess) TP = TR->TransientProcess();
457 Standard_Integer nb = Model->NbEntities();
459 for (Standard_Integer ie = 1; ie <= nb; ie++) {
460 Handle(Standard_Transient) enti = Model->Value(ie);
463 StoreName(enti, anIndices, TP, aShapeLabel);
466 StoreMaterial(enti, anIndices, TP, aShapeLabel);
469 // END: Store names and materials
473 case IFSelect_RetVoid:
474 anError = "Nothing created or No data to process";
476 case IFSelect_RetError:
477 anError = "Error in command or input data";
479 case IFSelect_RetFail:
480 anError = "Execution was run, but has failed";
482 case IFSelect_RetStop:
483 anError = "Execution has been stopped. Quite possible, an exception was raised";
488 anError = "Wrong format of the imported file. Can't import file.";
492 catch( Standard_Failure ) {
493 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
494 anError = aFail->GetMessageString();
498 if( aResShape.IsNull() ) {
499 StdFail_NotDone::Raise( anError.ToCString() );
503 aFunction->SetValue( aResShape );
505 log.SetTouched( Label() );
510 //=======================================================================
511 //function : MustExecute
513 //=======================================================================
514 Standard_Boolean STEPPlugin_ImportDriver::MustExecute( const TFunction_Logbook& ) const
516 return Standard_True;
519 //================================================================================
521 * \brief Returns a name of creation operation and names and values of creation parameters
523 //================================================================================
525 bool STEPPlugin_ImportDriver::
526 GetCreationInformation( std::string& theOperationName,
527 std::vector<GEOM_Param>& theParams )
529 if( Label().IsNull() ) return 0;
530 Handle(GEOM_Function) function = GEOM_Function::GetFunction( Label() );
532 STEPPlugin_IImport aCI( function );
533 Standard_Integer aType = function->GetType();
535 theOperationName = "ImportSTEP";
539 AddParam( theParams, "File name", aCI.GetFileName() );
540 if( aCI.GetIsIgnoreUnits() )
541 AddParam( theParams, "Format", "STEP_SCALE" );
549 TCollection_AsciiString
550 STEPPlugin_ImportDriver::GetValue( const TCollection_AsciiString& theFileName,
551 const TCollection_AsciiString& theParameterName,
552 TCollection_AsciiString& theError )
554 Handle(TCollection_HAsciiString) aValue;
556 if (theParameterName != "LEN_UNITS") {
557 theError = theParameterName + " parameter reading is not supported by STEP plugin";
558 return TCollection_AsciiString();
561 // Set "C" numeric locale to save numbers correctly
562 Kernel_Utils::Localizer loc;
564 STEPControl_Reader aReader;
566 Interface_Static::SetCVal( "xstep.cascade.unit","M" );
567 Interface_Static::SetIVal( "read.step.ideas", 1 );
568 Interface_Static::SetIVal( "read.step.nonmanifold", 1 );
572 IFSelect_ReturnStatus status = aReader.ReadFile( theFileName.ToCString() );
573 if (status == IFSelect_RetDone) {
574 TColStd_SequenceOfAsciiString anUnitLengthNames;
575 TColStd_SequenceOfAsciiString anUnitAngleNames;
576 TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
577 aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
578 if (anUnitLengthNames.Length() > 0) {
579 aValue = new TCollection_HAsciiString( anUnitLengthNames.First() );
581 TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
582 if (aLenUnits == "millimetre")
583 aValue = new TCollection_HAsciiString ("MM");
584 else if (aLenUnits == "centimetre")
585 aValue = new TCollection_HAsciiString ("CM");
586 else if (aLenUnits == "metre")
587 aValue = new TCollection_HAsciiString ("M");
588 else if (aLenUnits == "INCH")
589 aValue = new TCollection_HAsciiString ("INCH");
590 // TODO (for other units than mm, cm, m or inch)
591 //else if (aLenUnits == "")
592 // aValue = new TCollection_HAsciiString ("");
597 theError = theFileName + " reading failed";
600 catch( Standard_Failure ) {
601 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
602 theError = aFail->GetMessageString();
604 if (!aValue.IsNull())
605 return aValue->String();
607 return TCollection_AsciiString();
611 IMPLEMENT_STANDARD_HANDLE( STEPPlugin_ImportDriver, GEOM_BaseDriver );
612 IMPLEMENT_STANDARD_RTTIEXT( STEPPlugin_ImportDriver, GEOM_BaseDriver );