Problem with manipulating Activated reference files from MDL

Start with a DGN has a reference file attachement containing a few cells (orphans will do) .

The attacement is "Activated" via the references dialog so the reference element can be edited.

The cells in the reference file are selected  and the following code fragment executed from a simple primitive command. (SS2 and SS3)

The elements are moved successfully, but if you undo and redo a few times it will cause a crash.

Can anyone reproduce or comment?

 

Private void moveCells
(
Dpoint3d *centre,
int   view
)
 {
 int    iLoop;
 
 int    nElms;
 ElementRef     elemRef;
 UInt32   filePos;

 DgnModelRefP modelRef;

 Transform  transform;
 MSElementDescr *edP;


 //--- Selection set must be active. ---
 nElms = mdlSelect_numSelected( );

 //--- Cycle through selection set looking for each marker. Build a data structure. ---
 for ( iLoop = 0; iLoop < nElms; iLoop++ )
  {
  if ( mdlSelect_getElement( iLoop, &elemRef, &modelRef ) == SUCCESS )
   {
   filePos  = elementRef_getFilePos( elemRef );

   if ( mdlElmdscr_read( &edP, filePos, modelRef, false, NULL ) != NULL )
    {
    if ( mdlElement_getType( &edP->el ) == CELL_HEADER_ELM )
     {
     mdlTMatrix_getIdentity( &transform ); 
     mdlTMatrix_translate( &transform, &transform, 10, 10, 10 );
     mdlElmdscr_transform( edP, &transform );

// FAILS   mdlWorkDgn_write( edP, filePos, modelRef );
//     mdlWorkDgn_saveChanges( modelRef ); 

// FAILS   mdlElmdscr_rewriteByModelRef( edP, NULL, filePos, modelRef );

     mdlElmdscr_rewrite( edP, NULL, filePos ); 


     mdlElmdscr_freeAll( &edP );
     }
    }
   }
  }
 }

 

 

 

Parents
  • If the reference file has been activated, isn't it now the active model reference? 

    Unknown said:
    if ( mdlSelect_getElement( iLoop, &elemRef, &modelRef ) == SUCCESS )

    You can check to see if that modelRef is the active model.  In which case, mdlElmdscr_rewrite is the appropriate function to use.  mdlWorkDgn_xxx is not applicable (see MDL help for mdlSystem_exchangeDesignFile).

     
    Regards, Jon Summers
    LA Solutions

  • All three methods I tried did work to a point.  But all caused the crash with the undo. Not always after the first time.  The crash is not regular but very frequent.

    Activating the reference file in MicroStation seems different to exchanging.  Only one file can be activated at one time.  Maybe the dgn buffers are being switched.

    In any case the mdlSelect_getElement should return the appropriate DgnModelRefP you would expect.

  • There is no reason to ever use mdlElmdscr_rewrite, you can always use mdlElmdscr_rewriteByModelRef instead and specify whatever modelRef you have...even if it just happens to be the current active model. Functions that assume ACTIVEMODEL are a potential source of coding errors and are best avoided.

    So what error status is mdlErrno set to for the call the mdlElmdscr_rewriteByModelRef that isn't working? Because all mdlElmdscr_rewrite does is call mdlElmdscr_rewriteByModelRef with a hard-coded ACTIVEMODEL...so if that works but mdlElmdscr_rewriteByModelRef doesn't...it sounds like you haven't sucessfully made the ref attachment model active...

    * mdlWorkDgn_write is also just a wrapper for mdlElmdscr_rewriteByModelRef since V8.

    Unknown said:
    In any case the mdlSelect_getElement should return the appropriate DgnModelRefP you would expect.

    Yes, it certainly does!



  • Hi Brian,

    Thanks for the clarification.

    The mdlElmdscr_rewriteByModelRef) does not fail or error.  It simply behaves the same way as the other methods.

    Basically I have worked out if the command is performed twice, and then you undo twice it crashes on the second undo.

    Slightly updated code below.  DGN files attached. 

        int                iLoop;
        
        int                nElms;
        ElementRef        elemRef;
        UInt32            filePos;

        DgnModelRefP    modelRef;

        Transform        transform;
        MSElementDescr    *edP;

        nElms = mdlSelect_numSelected( );

        for ( iLoop = 0; iLoop < nElms; iLoop++ )
            {
            if ( mdlSelect_getElement( iLoop, &elemRef, &modelRef ) == SUCCESS )
                {
                if ( elementRef_getElemType( elemRef ) == CELL_HEADER_ELM )
                    {
                    filePos        = elementRef_getFilePos( elemRef );

                    if ( mdlElmdscr_read( &edP, filePos, modelRef, false, NULL ) != NULL )
                        {
                        mdlTMatrix_getIdentity( &transform );  
                        mdlTMatrix_translate( &transform, &transform, 10, 10, 0 );
                        mdlElmdscr_transform( edP, &transform );

                        if ( mdlElmdscr_rewriteByModelRef( edP, NULL, filePos, modelRef ) == 0 )
                            {
                            printf( "Error %d\n", mdlErrno );
                            }

                        mdlElmdscr_freeAll( &edP );
                        }
                    }
                }
            }



    simple.zip
  • mdlErrno

    The selection set may contain elements from multiple models.  You can rewrite only those contained in writeable models, which in general means those in the active model, plus those attachments that live in the same DGN file as the active model and thus share its read/write access mode.

    You didn't provide the answer to Brien's question, "What is the mdlErrno?"

    mdlElmdscr_read return value

    Unknown said:
     if ( mdlElmdscr_read( &edP, filePos, modelRef, false, NULL ) != NULL )

    That's a misleading test.  NULL means zero, so you're testing the return value of mdlElmdscr_read against zero.  It happens to work because that function returns the UInt32 file position of the next element in the model and zero denotes failure or end-of-file.  The following conveys the meaning more succinctly:

    if (0 < mdlElmdscr_read( &edP, filePos, modelRef, false, NULL ))

     
    Regards, Jon Summers
    LA Solutions

  • Ok, I was confused by the FAILS comment in the original code snippet...

    Performed twice on the same selection set...or performed twice on new selections each time? What happens if you perform these steps manually (trying to determine if the problem is in your app or a problem in MicroStation).

    At the point when undo is executed...is the selection set still active? What happens if you clear it first?

    -B



  • Good questions.  MicroStation seems fine. With my command if I cleared the selection set before the undo's it is ok.

    So this prompted me to seach a bit wider assuming the logic to modify the DGN is ok and It was a corruption outside of this code.  Thanks for your help.  Problem solved, it was my mistake.

Reply Children
No Data