+
+ //================================================================================
+ /*!
+ * \brief Map of TCollection_AsciiString initialized by C array of C strings.
+ * Odd items of the C array are map keys, and even items are values
+ */
+ //================================================================================
+
+ struct TStringMap: public map<TCollection_AsciiString,TCollection_AsciiString>
+ {
+ /*!
+ * \brief Filling. The last string must be ""
+ */
+ void Insert(const char* names_values[]) {
+ for ( int i = 0; names_values[i][0] ; i += 2 )
+ insert( make_pair( (char*) names_values[i], names_values[i+1] ));
+ }
+ /*!
+ * \brief Check if a string is in
+ */
+ TCollection_AsciiString Value(const TCollection_AsciiString& name ) {
+ map< _AString, _AString >::iterator it = find( name );
+ return it == end() ? "" : it->second;
+ }
+ };
+
+ //================================================================================
+ /*!
+ * \brief Returns a mesh by object
+ */
+ //================================================================================
+
+ Handle(_pyMesh) ObjectToMesh( const Handle( _pyObject )& obj )
+ {
+ if ( !obj.IsNull() )
+ {
+ if ( obj->IsKind( STANDARD_TYPE( _pyMesh )))
+ return Handle(_pyMesh)::DownCast( obj );
+ else if ( obj->IsKind( STANDARD_TYPE( _pySubMesh )))
+ return Handle(_pySubMesh)::DownCast( obj )->GetMesh();
+ else if ( obj->IsKind( STANDARD_TYPE( _pyGroup )))
+ return Handle(_pyGroup)::DownCast( obj )->GetMesh();
+ }
+ return Handle(_pyMesh)();
+ }
+
+ //================================================================================
+ /*!
+ * \brief Check if objects used as args have been created by previous commands
+ */
+ //================================================================================
+
+ void CheckObjectPresence( const Handle(_pyCommand)& cmd, set<_pyID> & presentObjects)
+ {
+ // either comment or erase a command including NotPublishedObjectName()
+ if ( cmd->GetString().Location( TPythonDump::NotPublishedObjectName(), 1, cmd->Length() ))
+ {
+ bool isResultPublished = false;
+ for ( int i = 0; i < cmd->GetNbResultValues(); i++ )
+ {
+ _pyID objID = cmd->GetResultValue( i+1 );
+ if ( cmd->IsStudyEntry( objID ))
+ isResultPublished = (! theGen->IsNotPublished( objID ));
+ theGen->ObjectCreationRemoved( objID ); // objID.SetName( name ) is not needed
+ }
+ if ( isResultPublished )
+ cmd->Comment();
+ else
+ cmd->Clear();
+ return;
+ }
+ // comment a command having not created args
+ for ( int iArg = cmd->GetNbArgs(); iArg; --iArg )
+ {
+ const _pyID& arg = cmd->GetArg( iArg );
+ if ( arg.IsEmpty() || arg.Value( 1 ) == '"' || arg.Value( 1 ) == '\'' )
+ continue;
+ list< _pyID > idList = cmd->GetStudyEntries( arg );
+ list< _pyID >::iterator id = idList.begin();
+ for ( ; id != idList.end(); ++id )
+ if ( !theGen->IsGeomObject( *id ) && !presentObjects.count( *id ))
+ {
+ cmd->Comment();
+ cmd->GetString() += " ### " ;
+ cmd->GetString() += *id + " has not been yet created";
+ for ( int i = 0; i < cmd->GetNbResultValues(); i++ ) {
+ _pyID objID = cmd->GetResultValue( i+1 );
+ theGen->ObjectCreationRemoved( objID ); // objID.SetName( name ) is not needed
+ }
+ return;
+ }
+ }
+ // comment a command having not created Object
+ const _pyID& obj = cmd->GetObject();
+ if ( !obj.IsEmpty() && cmd->IsStudyEntry( obj ) && !presentObjects.count( obj ))
+ {
+ cmd->Comment();
+ cmd->GetString() += " ### not created object" ;
+ for ( int i = 0; i < cmd->GetNbResultValues(); i++ ) {
+ _pyID objID = cmd->GetResultValue( i+1 );
+ theGen->ObjectCreationRemoved( objID ); // objID.SetName( name ) is not needed
+ }
+ }
+ const _pyID& result = cmd->GetResultValue();
+ if ( result.IsEmpty() || result.Value( 1 ) == '"' || result.Value( 1 ) == '\'' )
+ return;
+ list< _pyID > idList = cmd->GetStudyEntries( result );
+ list< _pyID >::iterator id = idList.begin();
+ for ( ; id != idList.end(); ++id )
+ presentObjects.insert( *id );
+ }
+
+ //================================================================================
+ /*!
+ * \brief Fix SMESH::FunctorType arguments of SMESH::Filter::Criterion()
+ */
+ //================================================================================
+
+ void fixFunctorType( TCollection_AsciiString& Type,
+ TCollection_AsciiString& Compare,
+ TCollection_AsciiString& UnaryOp,
+ TCollection_AsciiString& BinaryOp )
+ {
+ // The problem is that dumps of old studies created using filters becomes invalid
+ // when new items are inserted in the enum SMESH::FunctorType since values
+ // of this enum are dumped as integer values.
+ // This function corrects enum values of old studies given as args (Type,Compare,...)
+ // We can find out how to correct them by value of BinaryOp which can have only two
+ // values: FT_Undefined or FT_LogicalNOT.
+ // Hereafter is the history of the enum SMESH::FunctorType since v3.0.0
+ // where PythonDump appeared
+ // v 3.0.0: FT_Undefined == 25
+ // v 3.1.0: FT_Undefined == 26, new items:
+ // - FT_Volume3D = 7
+ // v 4.1.2: FT_Undefined == 27, new items:
+ // - FT_BelongToGenSurface = 17
+ // v 5.1.1: FT_Undefined == 32, new items:
+ // - FT_FreeNodes = 10
+ // - FT_FreeFaces = 11
+ // - FT_LinearOrQuadratic = 23
+ // - FT_GroupColor = 24
+ // - FT_ElemGeomType = 25
+ // v 5.1.5: FT_Undefined == 33, new items:
+ // - FT_CoplanarFaces = 26
+ // v 6.2.0: FT_Undefined == 39, new items:
+ // - FT_MaxElementLength2D = 8
+ // - FT_MaxElementLength3D = 9
+ // - FT_BareBorderVolume = 25
+ // - FT_BareBorderFace = 26
+ // - FT_OverConstrainedVolume = 27
+ // - FT_OverConstrainedFace = 28
+ // v 6.5.0: FT_Undefined == 43, new items:
+ // - FT_EqualNodes = 14
+ // - FT_EqualEdges = 15
+ // - FT_EqualFaces = 16
+ // - FT_EqualVolumes = 17
+ // v 6.6.0: FT_Undefined == 44, new items:
+ // - FT_BallDiameter = 37
+ // v 6.7.1: FT_Undefined == 45, new items:
+ // - FT_EntityType = 36
+ //
+ // It's necessary to continue recording this history and to fill
+ // undef2newItems (see below) accordingly.
+
+ typedef map< int, vector< int > > TUndef2newItems;
+ static TUndef2newItems undef2newItems;
+ if ( undef2newItems.empty() )
+ {
+ undef2newItems[ 26 ].push_back( 7 );
+ undef2newItems[ 27 ].push_back( 17 );
+ { int items[] = { 10, 11, 23, 24, 25 };
+ undef2newItems[ 32 ].assign( items, items+5 ); }
+ undef2newItems[ 33 ].push_back( 26 );
+ { int items[] = { 8, 9, 25, 26, 27, 28 };
+ undef2newItems[ 39 ].assign( items, items+6 ); }
+ { int items[] = { 14, 15, 16, 17 };
+ undef2newItems[ 43 ].assign( items, items+4 ); }
+ { int items[] = { 37 };
+ undef2newItems[ 44 ].assign( items, items+1 ); }
+ { int items[] = { 36 };
+ undef2newItems[ 45 ].assign( items, items+1 ); }
+ }
+
+ int iType = Type.IntegerValue();
+ int iCompare = Compare.IntegerValue();
+ int iUnaryOp = UnaryOp.IntegerValue();
+ int iBinaryOp = BinaryOp.IntegerValue();
+
+ // find out integer value of FT_Undefined at the moment of dump
+ int oldUndefined = iBinaryOp;
+ if ( iBinaryOp < iUnaryOp ) // BinaryOp was FT_LogicalNOT
+ oldUndefined += 3;
+
+ // apply history to args
+ TUndef2newItems::const_iterator undef_items =
+ undef2newItems.upper_bound( oldUndefined );
+ if ( undef_items != undef2newItems.end() )
+ {
+ int* pArg[4] = { &iType, &iCompare, &iUnaryOp, &iBinaryOp };
+ for ( ; undef_items != undef2newItems.end(); ++undef_items )
+ {
+ const vector< int > & addedItems = undef_items->second;
+ for ( size_t i = 0; i < addedItems.size(); ++i )
+ for ( int iArg = 0; iArg < 4; ++iArg )
+ {
+ int& arg = *pArg[iArg];
+ if ( arg >= addedItems[i] )
+ arg++;
+ }
+ }
+ Type = TCollection_AsciiString( iType );
+ Compare = TCollection_AsciiString( iCompare );
+ UnaryOp = TCollection_AsciiString( iUnaryOp );
+ BinaryOp = TCollection_AsciiString( iBinaryOp );
+ }
+ }