V8i MDL Always Getting 0 in level id

Hello,
I'm sort of new to Microstations and have been tasked with upgrading MicrostationsJ(v 7.0) mdl code to work in v8i select series 4. I've hit an issue with a function that simply gets the level for an element. I've read that levels in Microstations 7 to 8 changed quite a bit, so I know I would have to rewrite the code for this funciton.

The existing function in v7 used the old method of obtaining the level by traversing an array of short integers and the level could be 1 to 63.

So here is my plan to rewrite the funcction to get the level in v8i

1. Use the mdlElement_getProperties function to get the level id of an element. Note that I realize that this is an internal id and does not equate to the level id in v7.

2. Use funcciton mdlLevel_getName to get the level name from the internal level id. The level name is significant to us, since it seems to equate to the old v7 level, example Level 71, Level 42 ect..

My problem is that in step 1, I always get back a 0 for the internal level id.
So when the code below runs I always see the following for each element: this is for thousands of elements always 0. I never see the line good level if the levelid is not 0.

element is graphic
level id: 0

I've commented out the call to mdlLevel_getName, since it seems pointless to call it for now if the levelid is always 0, and don't mind that I am returning 1 form the funciton, this is just for testing for now.

couple of more things:
I will post full code for my program in a reply to this post. this is a test program that I run from the command windows. The program does a file scan of each hard-coded cell then reads each element in the cell.
I know these elements are good because I had code in this program (that I removed for readability) that successfully got other information off the element after the call to getItemLevel.

The dgn that I am using is from v7, so when I opened it in v8i the first time, it converted the file. There is only 1 default model. And if I go into the dgn in v8i, I can see the levels exist that I am tring to get the level name for.

I kow that the way that I am scanning the file is outdated and I will be looking to changing that after I get past my current issue with the levelid.

So here is my question?
What am I doing wrong? Am I on the right track for retreiving the level name for an element or is there another way to do this? If I am on the right track then why am I always gettting a 0 in the levelid?

Help for my issue would be greatly appreciated. I've searched these forms and the reference material without success.

Public int getItemLevel(MSElement *elP)
{

MSWChar levelName [50];
UInt32  levelid;

                 //elements are graphic
                 if(elP->ehdr.isGraphics)
                 {
                  fprintf(fres,"\n element is graphic");  

		  mdlElement_getProperties ( &levelid , NULL , NULL , NULL, NULL , NULL, NULL, NULL, elP );
		  fprintf(fres,"\n level id: %d", levelid);
                  if (levelid != 0)
	   	  {
		    fprintf(fres,"\n good level");
		  } 

/*
                 if (SUCCESS == mdlLevel_getName( levelName, 50, MASTERFILE, levelid ))
                 {
                   fprintf(fres,"\nlevel name = %s",levelName);
                 }
*/	
                }




	return 1;
}

  • And here is the full code for my test program:

    /*
    	ShowLevels - test program
    */
    
    /*---------------------------------------------------------------------------
     Include Files
    -----------------------------------------------------------------------------*/
    #include <stdlib.h>		/* Standard "C" library			*/
    #include <stdio.h> 		/* Standard "C" I/O library     	*/
    #include <string.h> 		/* "C" lib to operate with "string" 	*/
    #include <ctype.h> 		/* "C" lib to operate with "symsol" 	*/
    #include <time.h>           	/* "C" lib to operate with "time"	*/
    
    #include <mdl.h>		/* Main include file for MDL   		*/
    #include <rscdefs.h>		/* Resource Manager Structure Definitions */
    #include <msrsrc.fdf>		/* Resource Manager function prototypes */
    #include <msdefs.h>		/* Defines for MicroStation data structures */
    #include <msrsrc.fdf>		/* Resource Manager function prototypes */
    #include <cexpr.h>		/* Defs for C Expression evaluation functions */
    #include <mscexpr.fdf>		/* C Expression evaluation function Prototypes */
    #include <mselems.h>           	/* Definitions for MicroStat. elements 	*/
    #include <mselmdsc.fdf>		/* MicroStation element function Prototypes */
    #include <dlogitem.h>		/* Dialog Box Item definitions 		*/
    #include <msdialog.fdf>		/* Dialog Box Function Prototypes 	*/
    #include <dbdefs.h>		/* Database definitions		 	*/
    #include <dberrs.h>		/* Database error return codes		*/
    #include <dbserver.h>		/* Database Server Definitions		*/
    #include <rdbmslib.fdf>		/* Database Function Definitions	*/
    #include <msoutput.fdf>		/* Output function Prototypes           */
    #include <msinputq.h>		/* Input queue definitions for MicroStation/MDL */
    #include <msinput.fdf>		/* Input queue Prototypes for MicroStation/MDL */
    #include <scanner.h>		/* Definitions for design files "scanner"	*/
    #include <msscan.fdf>		/* Function Prototypes for "scanner" */
    #include <mscnv.fdf>		/* Prototypes for Convert functions     */
    #include <tcb.h>		/* Definitions for "terminal control block" */
    #include <errno.h>		/* Standard Library error codes		*/
    #include <mssystem.fdf>		/* System function Prototypes           */
    #include <msoutput.fdf>		/* Output function Prototypes           */
    #include <msview.fdf>		/* View function Prototypes             */
    #include <msfile.fdf>		/* File function Prototypes             */
    
    #include <leveltable.fdf>
    
    #include "ShowLevels.h"
    
    /*--------------------------------------------------------------------
      Local Defines 
    ----------------------------------------------------------------------*/
    #define MAX_SIGNALS	1000
    #define MAX_ELEMS	1000
    #define NUM_CELLNAMES	43
    #define LEN_SQL 	256
    
    
    /*---------------------------------------------------------------------
      Global Data 
    ----------------------------------------------------------------------*/
    DialogBox  *GL_dbP;
    //char    GL_text[16], GL_signalName[8], GL_lever[8];
    char    GL_text[50], GL_signalName[25], GL_lever[25];
    int     GL_numLink; 	/* number Signals to be  linked */
    int     GL_numRes; 	/* number Signals currently linked */
    int     GL_numErr;
    FILE	*fres;
    
    
    /*---------------------------------------------------------------------
      Function Prototypes 
    ----------------------------------------------------------------------*/
    Public  void    findDFitems	(void);
    
    Public  int   	getItemLevel	(MSElement *);
    
    char    GL_cellNames[NUM_CELLNAMES][8] =
            {
            "SIG1L","SIG2L","SIG3L","SIG4L","SIG5L","SIG6L",
            "SIG1R","SIG2R","SIG3R","SIG4R","SIG5R","SIG6R",
            "SIG1A","SIG2A","SIG3A","SIG4A","SIG5A","SIG6A",
            "SIG1B","SIG2B","SIG3B","SIG4B","SIG5B","SIG6B",
            "SIG1C","SIG2C","SIG3C","SIG4C","SIG5C","SIG6C",
            "SIG1D","SIG2D","SIG3D","SIG4D","SIG5D","SIG6D",
            "SIG6AR","SIG1BR","SIG5BR",
    	"SIG1CR","SIG4CR","SIG5CR","SIG6DR"
            };
    
    int	GL_itemLevels[3]= {12,30,48};
    
    struct
    {
      int  mslink;
      char name[16];
      char lever[16];
    } GL_signals[MAX_SIGNALS];
    
    FILE	*fres;
    
    int main(int argc, char *argv[])
    {
            char str[128], *alertDir;
     int    status,n,m;
    
            alertDir = getenv("ALERT_DIR");
            strcpy(str,alertDir);
            strcat(str,"maint\\link\\testlog.txt");
            if ( (fres=fopen(str,"w")) == NULL ) 
            {
               printf("Can not open file %s",str);
               mdlSystem_exit(0,1);
            }
    
     	fprintf(fres,"ShowLevels started");
    
     	findDFitems();
    
    //        newSearch(); 
    
     	fprintf(fres,"\n\nfindDFitems complete");
    
    
    
     	fprintf(fres,"\n\nShowLevels ended");
         fclose(fres);
    	mdlSystem_exit(0, 1);
    	return 0;
    }
    
    /*-------------------------------------------------------------------------
      name          findDFitems
      A function to find all Signals in the active design
      file using cell names as search criterion
    --------------------------------------------------------------------------*/
    Public void     findDFitems()
    {
     ULong          elemAddr[MAX_ELEMS], eofPos, filePos, newFilePos, readFilePos;
     int            scanWords, status, status1, i, j, n, m, numAddr, numItems, 
    		exist=0, linkCount, level, mslink;
     ExtScanlist    scanList;
     MSElementDescr *edP, *newEdP;
     MSElement      *elP;
     short          cellNameR50[2];
     char           cellNameAsc[16], str[128], word2[16], word3[16], division[8];
     DatabaseLink   *links[10];
     double		x, y;
     int ttt = 0;
    
    
    fprintf(fres,"\n\nfindDFitems Beginning");
    
     for ( j = 0; j < NUM_CELLNAMES; j++ )
     {
    	strcpy(cellNameAsc,GL_cellNames[j]);
    	mdlScan_initScanlist (&scanList);
    	mdlScan_noRangeCheck (&scanList);
    	memset(scanList.typmask,0x00,sizeof(scanList.typmask));
    	memset(cellNameR50,0,sizeof(cellNameR50));
    
            scanList.scantype       = ELEMTYPE | PICKCELL;
    	scanList.extendedType   = FILEPOS;
    	scanList.typmask[0]     = TMSK0_CELL_HEADER;
    
    	mdlCnv_fromAsciiToR50(strlen(cellNameAsc),cellNameAsc,cellNameR50);
    
    	/* Initialize the scanlist for use w/ the masterfile (file 0) */
    	eofPos = mdlElement_getFilePos (FILEPOS_EOF,NULL);
    
    	mdlScan_initialize (MASTERFILE, &scanList);
    
    	filePos = 0L; /* start search from top of file */
    	do 
    	{
    	   scanWords = sizeof(elemAddr)/sizeof(short);
    	   status = mdlScan_file (elemAddr,&scanWords,sizeof(elemAddr),
    		    &filePos);
    
    	   numAddr = scanWords/sizeof(short);
    
    	   for ( i=0; i<numAddr; i++ )
    	   {
    		if (elemAddr[i] >= eofPos) break;
    		mdlElmdscr_read (&edP,elemAddr[i],0,FALSE,&readFilePos);
    
    		/* 1. Check if this Signal already has Link 
    		*/ 
                    elP = &edP->el;
    
    		/* 2. Get Signal Level and find the Division */
    		level = getItemLevel(elP);
    
    		mdlElmdscr_freeAll( &edP ); 
    	   }
     
    	} while (status == BUFF_FULL);
     }
    }
    
    /*-------------------------------------------------------------------------
      getItemLevel		
    --------------------------------------------------------------------------*/
    Public int getItemLevel(MSElement *elP)
    {
    
    MSWChar levelName [50];
    UInt32  levelid;
    
                     //elements are graphic
                     if(elP->ehdr.isGraphics)
                     {
                      fprintf(fres,"\n element is graphic");  
    
    		  mdlElement_getProperties ( &levelid , NULL , NULL , NULL, NULL , NULL, NULL, NULL, elP );
    		  fprintf(fres,"\n level id: %d", levelid);
                      if (levelid != 0)
    	   	  {
    		    fprintf(fres,"\n good level");
    		  } 
    
    /*
                     if (SUCCESS == mdlLevel_getName( levelName, 50, MASTERFILE, levelid ))
                    {
                      fprintf(fres,"\nlevel name = %s",levelName);
                    }
    */	
    
                    }
    
    
    
    
    	return 1;
    }
    

  • I've read that levels in Microstations 7 to 8 changed quite a bit

    MicroStation/J (V7 file format)

    An element has one of 63 levels.  Each MSElement has that level bit stored in a 64-bit value (4x16-bit short integers).  That is, the entire level domain is specified by that bit.

    Customers didn't like having only 63 levels and campaigned for more, which resulted in the V8 file spec. revealed in 2001.

    Level names were not stored on each element, but in a table stored in the DGN file (if I recall correctly).

    MicroStation V8 (V8 file format)

    Each MSElement has a UInt32  LevelId...

    ..\DgnPlatform\DgnPlatformBaseType.r.h(85): typedef UInt32  LevelId;

    That LevelId points to a level table stored in the DGN file.  The table stores only those levels that have been defined.  That is, the level table doesn't have 2 billion rows.  Each row in that table stored the LevelId, the user-defined level name and optionally a user-defined level number.  A user doesn't normally see the LevelId, but it's what we programmers work with.

    Scanning

    With the V8 API, scanning is easier.  You don't have to set up an ExtScanList. It could well be that the scanlist setup for V8 is wrong.

    Prefer to use the mdlScanCriteria_api.  The SDK supplies examples, and here's another

    Cell Names

    Cell names are not restricted to six packed upper-case characters.  You don't need the conversion function (mdlCnv_fromAsciiToR50) to exchange packed names with a C string. 

     
    Regards, Jon Summers
    LA Solutions

  • Hi ,

    Unfortunately, migrating custom application development often requires a fair amount of learning and work along the way, typically more work the farther behind your code is. We do try to make this complex topic as simple as possible by highlighting the multitude of options, paths and resources available in our wiki: Migrating to CONNECT.

    Where:

    1. MicroStation CONNECT Edition is the most recent and robust supported option available
    2. MicroStation V8i SS10 still receives limited desktop support through 1/2022 (soon to end)
    3. If you do not have developers, assistance is available; see: Need Help Upgrading?
    4. Or if you have developers and time follow the Migrate V8 MDL Code migration path in (reverse - oldest to newest software) order listed. Given that you are migrating from MicroStation/J (over 20 years old now) I am not sure if I can add more to the top-level migration materials link but if I do I certainly will add and update here.

      [UPDATE-20211011 - I added a Migrate V7 Code topic on the Migrating to CONNECT (link above) page pointing to a few relevant MicroStation/J to V8/CONNECT items and considerations I was able to locate.]

    HTH,
    Bob



  • Hi Brenden,

    and have been tasked with upgrading MicrostationsJ(v 7.0) mdl code to work in v8i select series 4

    Depending on size, complexity and also quality of V7 code, it can be (and typically is) enormous task. Everything related to levels have to rewritten, also often scanning, especially when levels are involved, have to be migrated from old mdlScan_ to mdlScanCriteria_ API. And there are plenty of other small and big issues that have to be evaluated.

    I agree with Bob, when V7 > V8i migration is discussed now, whether it makes sense, when migration to CE will require another substantial amount of time.

    I kow that the way that I am scanning the file is outdated and I will be looking to changing that after I get past my current issue with the levelid.

    A question is whether do it in an opposite order would not be better.

    What am I doing wrong?

    I have no time to do any serious analysis (including try to remember how exactly this old scanning worked). but if I understand it right, the code searches for cell headers. Is it correct? The headers are elements, placed (historically in V7 files) in level 0.

    I do not see any recursion in your code, that would dig inside the cell and to analyze the cell content.

    Regards,

      Jan

    Answer Verified By: Brenden OReilly 

  • Thank you, everyone for your responses.  Unfortunately, I must use v8i for now.  Upgrading to Connect will come later.

    Jan, yes you are correct, the element that I am attempting to get the level for is a cell header, so that makes sense that I am getting a 0.  I need to dig into the cell to get the actual levels.

    There is a lot to Microstations that I need to learn Slight smile

  • Upgrading to Connect will come later.

    Be prepared to learn something completely new when moved to CE and (optionally) forget these "old C" things from J and V8.

    There is a lot to Microstations that I need to learn

    This old style, when element data structures are accessed directly, requires really good understanding of elements features and how they are stored.

    Regards,

      Jan

  • Do you not know MicroStation?
    Have you been hired to convert programs for a software you are unfamiliar with? Have you written code for MicroStation in the past, or are you writing it currently?

    While I don't know a lot about coding, I see here so very often where people are trying to rework old code and getting lost in all of the details that have changed. Sometimes, it might be easier to write newer applications by trying to understand WHAT the old code did and write new code to do "that thing", instead of trying to replicate HOW the old code did things.

    MaryB

    Power GeoPak 08.11.09.918
    Power InRoads 08.11.09.918
    OpenRoads Designer 2021 R2